CTF PWN TOOLS开发

做pwn感觉可以总结一些工具

脚本模板

首先是写pwn题exp的脚本模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/env python3
# -*- coding=utf-8 -*-

from pwn import *
import os

DEBUG = 1

def localDebug(p):
pid = util.proc.pidof(p)[0]
with open("debug.sh", "w") as f:
f.write("#!/bin/bash\n")
f.write(f"gdb -p {pid}")
os.chmod("debug.sh", 0o777)

def main():
if DEBUG:
p = process("xxx")
context.log_level = "debug"
localDebug(p)
else:
p = remote("x.x.x.x", 1111)
# context.log_level = "debug"

if __name__ == "__main__":
main()

没啥好说的,一个本地调试模式,一个远程模式。就说说调试方式,我不喜欢pwntools自带的gdb模块,因为要图形界面,但是我一般用的都是只有终端的,所以我喜欢一个屏幕对半分开,一个运行脚本,一个执行gdb。但是每次这种方式,都是手动打gdb -p xxx,所以把这个直接加在模版里,就方便多了。这种方式加上pause()来调试,感觉挺不错的。

加符号

有些题目有一些复杂的结构体,在ida里逆向逆出来了,但是使用gdb调试的时候却没办法直观的看这个结构体,然后想了个办法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct xx1 {
xx
};

struct xx2 {
...
};

int main(int argc, char *argv[])
{
struct xx1 a;
struct xx2 b;
write(1, "hello\n", 6);
return 0;
}

然后编译一下:

1
$ gcc -g -c symbol.c

能得到一个symbol.o

然后在.gdbinit里面加入:

1
2
3
4
5
$ cat .gdbinit
add-symbol-file symbol.o
define SF
p *(struct xx1 *) $arg0
end

然后可以加上一个命令,来打印出我们自己加上的这个结构体。

加插件

在调试开了PIE的程序的时候,每次想看看BSS段的数据,都要查看一下程序基地址,非常麻烦,所以我写了个插件,辅助我的操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!/usr/bin/env python3
# -*- coding=utf-8 -*-

from email.mime import base
import gdb

def getBase(pid):
with open(f"/proc/{pid}/maps", "r") as f:
data = f.readline()
data = data.split("-")[0].strip("-")
baseAddr = int(data, 16)
return hex(baseAddr)

class PIEBreakPoint(gdb.Command):
"""when pie is on, show address, breakpoint etc.
Usage: pb [offset]
Example:
(gdb) pb 0x1234
"""

def __init__(self):
super(self.__class__, self).__init__("pb", gdb.COMMAND_USER)
def invoke(self, args, from_tty):
pid = gdb.selected_inferior().pid
if not pid:
print("Please run program first.")
return
args = args.split(" ")
if len(args) != 1:
print("args error.")
return
offset = args[0]
baseAddr = getBase(pid)
cmd = f"b *({baseAddr} + {offset})"
gdb.execute(cmd)

class PIEShowData(gdb.Command):
"""when pie is on, show address, breakpoint etc.
Usage: pies [format] [offset]
Example:
(gdb) pies
"""

def __init__(self):
super(self.__class__, self).__init__("pies", gdb.COMMAND_USER)
def invoke(self, args, from_tty):
pid = gdb.selected_inferior().pid
if not pid:
print("Please run program first.")
return
args = args.split(" ")
if len(args) != 2:
print("args error.")
return
offset = args[1]
baseAddr = getBase(pid)
cmd = f"{args[0]} ({baseAddr} + {offset})"
gdb.execute(cmd)

PIEBreakPoint()
PIEShowData()

以后还需要啥功能再继续加。上面这个功能好像GEF里面已经有了,但是我做堆题的时候还是比较喜欢pwndbg插件,这个插件里好像还没实现这个功能。

其他

以后想到啥再继续加

Author

Hcamael

Posted on

2022-08-02

Updated on

2022-08-02

Licensed under