在pwntools里面调用gdb

在pwn里面,几个重要的工具有IDA,ollydbg,gdb(pwndbg,peda…),pwntools等

IDA是比较全面的工具,界面也比较友好,但是动态调试elf比较麻烦,需要选中remote linux debugger,详见IDA+pwntools环境搭建,这里使用pwntools进行交互的好处作者提到是可以 发送不可打印字符,但是我按照作者的教程,pwntools成功连接上ubuntu docker里面运行的elf,并在IDA中attach上该elf,按下F9运行,EIP却依然指向vsdo(vsdo好像是某种系统调用,具体还得去研究原因),并不能停在已经设置好的断点处,很奇怪的是这时候send过去字符,IDA的界面上程序就会跳到断点处了,如下面所示:
在pwntools里面调用gdb_第1张图片
上面的第一个断点像被跳过了一样,直接跳到了第二个断点,而且因为在IDA和kali虚拟机之间切换还是很麻烦的。。。加上还有ubuntu的docker,端口socat转发之类的操作,实在麻烦,因此自己研究了一下pwntools里面自带的gdb方法

举上面链接的教程0x01里面的一个elf——hello做例子,在python控制台里面输入

>>>from pwn import *
>>>io = gdb.debug('./hello', 'break main')

之后会跳出一个gdb的终端窗口,停在了程序初始化的指令处(大概是?),接着在gdb窗口中输入c,继续运行,程序停在了刚刚设置的main处,在hello函数内设置断点:

pwndbg> disass hello
Dump of assembler code for function hello:
   0x08048484 <+0>:	push   ebp
   0x08048485 <+1>:	mov    ebp,esp
   0x08048487 <+3>:	sub    esp,0x18
   0x0804848a <+6>:	mov    DWORD PTR [ebp-0x12],0x0
   0x08048491 <+13>:	mov    DWORD PTR [ebp-0xe],0x0
   0x08048498 <+20>:	mov    WORD PTR [ebp-0xa],0x0
   0x0804849e <+26>:	sub    esp,0x4
   0x080484a1 <+29>:	push   0x64
   0x080484a3 <+31>:	lea    eax,[ebp-0x12]
   0x080484a6 <+34>:	push   eax
   0x080484a7 <+35>:	push   0x0
   0x080484a9 <+37>:	call   0x8048320 <read@plt>
   0x080484ae <+42>:	add    esp,0x10
   0x080484b1 <+45>:	sub    esp,0x8
   0x080484b4 <+48>:	lea    eax,[ebp-0x12]
   0x080484b7 <+51>:	push   eax
   0x080484b8 <+52>:	push   0x8048578
   0x080484bd <+57>:	call   0x8048330 <printf@plt>
   0x080484c2 <+62>:	add    esp,0x10
   0x080484c5 <+65>:	nop
   0x080484c6 <+66>:	leave  
   0x080484c7 <+67>:	ret    
End of assembler dump.
pwndbg> b* 0x080484b1
Breakpoint 2 at 0x80484b1
pwndbg> b* 0x080484a7
Breakpoint 3 at 0x80484a7

设置的断点一个在read前面,一个在print前面,这时候我们切换到刚刚的python控制台

>>> io.send('1')

切换到gdb窗口输入c,停在了read前面的断点,没事情发生,再按下c,停在了read后面,此时我们观察寄存器

pwndbg> c
Continuing.

Breakpoint 2, 0x080484b1 in hello ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────────────────────────[ REGISTERS ]──────────────────────────────────
 EAX  0x1
 EBX  0x0
 ECX  0xff87e8f6 ◂— 0x31 /* '1' */
 EDX  0x64
 EDI  0xf7f17000 ◂— 0x1d6d6c
 ESI  0xf7f17000 ◂— 0x1d6d6c
 EBP  0xff87e908 —▸ 0xff87e918 ◂— 0x0
 ESP  0xff87e8f0 —▸ 0xf7f173fc —▸ 0xf7f18980 ◂— 0x0
 EIP  0x80484b1 (hello+45) ◂— sub    esp, 8

发现‘1’被放在了ECX所指向的内存处,说明pwntools发送过来的输入放在了这里了,此时在python控制台输入io.recv(),发现没有输出,阻塞住了,此时在gdb窗口输入c,发现python控制台输出Hello, 1,因为这时候程序继续运行了,printf被调用,得到输出,并且这个进程exited normally

gdb.attach

pwntools里面关于gdb还有别的用法,比如gdb.attach

from pwn import *
io = process('./hello')
gdb.attach(io, 'b* main')

hello是一个简单的程序:等待输入,然后输出“hello …\n”。执行完上面的命令后你会发现,新打开了一个gdb窗口,它并不会停留在main处,而是停在了vsyscall之类的系统调用上面,这是因为io这个进程已经是运行了的,它阻塞在了等待输入read的地方,main已经执行过了,所以不会停,因此在read后面设置的断点才会有效,这个问题不知道怎么解决。。。

你可能感兴趣的:(ctf,pwn)