Pwntools 高级应用
上一篇blog中我简要介绍了一下pwntools的各个模块基本的使用方法,这里给出一点其他方面的补充。
GDB调试
对于elf文件来说,可能有时需要我们进行一些动态调试工作这个时候就需要用到gdb,pwntools的gdb模块也提供了这方面的支持。
其中最常用的还是attach函数,在指定process之后可以attach上去调试,配合proc模块就可以得到对应进程的pid非常方便。
但是比较麻烦的是在实现上,attach函数需要开启一个新的terminal,这个terminal的类型必须使用环境变量或者context对象来指定。研究了一番源码之后,找到了解决方案。
1 | s = process('./pwnme') |
proc.pidof(s)[0]能够取出process的id,然后attach上去。context.terminal制定的是终端类型和参数,我用的是gnome-terminal可以这样写,这样运行后会自动打开一个新的gnome-terminal并在里面启动gdb并自动断下来,这样就可以调试了。
还可以使用其他xterm,tmux等其他终端,如果脚本运行在tmux中,可以这样指定
1 | context.terminal = ['tmux', 'splitw', '-h'] |
这两种可以让gdb运行在横向或者纵向分割出来的tmux窗口中。
另外,也可以在attach的时候指定gdb脚本,这样可以断在自己想的地方。
1 | # 新版本中不再使用execute参数,改用gdbscript |
2019.10更新
实际上现在 attach
时已经不再需要手动pidof来查找pid了,可以直接传入process来attach上去,同时gdbscript也可以传入一个文件对象,例如
1 | s = process('./pwnme') |
DynELF 符号leak
相当好用的一个工具,给出一个函数句柄,可以解析任意符号的位置。这个函数的功能是:输入任意一个address,输出这个address中的data(至少1byte)。
文档中给出了一个例子
1 | p = process('./pwnme') |
这个例子当然没有实际意义,在应用中我们可以在leak函数中布置rop链,使用write函数leak出一个address的地址,然后返回。接着就可以使用d.lookup
函数查找符号了,通常我们都是需要找system的符号。
关于ROP模块
目前ROP模块还不支持build一个x64的rop链(my issue),但是还是可以寻找一些gadget来帮助我们手动布置rop的。
1 | './pwnme') elf = ELF( |
以这些寄存器结尾的属性保存着能够控制它们的gadget,当然如果没有build功能的话同样 可以使用其它的ropgadget工具也是很方便的。