导出 IDA 符号 & CTF PWN 题环境准备

导出 IDA 符号

做逆向和 pwn 题时总会发现一些符号被stripped掉的ELF文件,使用GDB调试时由于没有符号导致识别困难而且断点麻烦, 这时候就想把IDA中识别到的或者用户自己定义的函数名(或者其他符号)导出到ELF文件的SYMTAB中,在Github上找到一个适用于 IDA 7.0 ~ 7.3 的插件 https://github.com/BlackVS/IDA-exportsymbols 做了一些小小的工作让其支持 IDA 7.4+ 并且优化了一下GUI界面:

https://github.com/FrnkPsycho/ida-exportsymbols

用法说明什么的都写在README里了

PWN 题环境准备

pwninit -> 将 xxx_patched 文件用 IDA 打开 -> 如果想要导入符号则使用上面提到的 exportsymbols

pwninit 之前:

1
2
3
4
> ldd hacknote
linux-gate.so.1 (0xf7f2e000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7c00000)
/lib/ld-linux.so.2 (0xf7f30000)

pwninit(如果文件夹下只有一个ELF和libc动态库则不需要带参数)
注意如果不要在VMware虚拟机的Windows共享文件夹下执行操作,否则symlink会失败(因为Windows的文件系统不支持Linux的软链接):

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
> pwninit --bin hacknote
bin: hacknote
libc: ./libc_32.so.6

fetching linker
https://launchpad.net/ubuntu/+archive/primary/+files//libc6_2.23-0ubuntu5_i386.deb
unstripping libc
https://launchpad.net/ubuntu/+archive/primary/+files//libc6-dbg_2.23-0ubuntu5_i386.deb
eu-unstrip: cannot find matching section for [13] '.text'
eu-unstrip: cannot find matching section for [14] '__libc_freeres_fn'
eu-unstrip: cannot find matching section for [15] '__libc_thread_freeres_fn'
eu-unstrip: cannot find matching section for [16] '.rodata'
eu-unstrip: cannot find matching section for [17] '.stapsdt.base'
eu-unstrip: cannot find matching section for [18] '.interp'
eu-unstrip: cannot find matching section for [19] '.eh_frame_hdr'
eu-unstrip: cannot find matching section for [20] '.eh_frame'
eu-unstrip: cannot find matching section for [21] '.gcc_except_table'
eu-unstrip: cannot find matching section for [22] '.hash'
eu-unstrip: cannot find matching section for [23] '.tdata'
eu-unstrip: cannot find matching section for [24] '.tbss'
eu-unstrip: cannot find matching section for [25] '.init_array'
eu-unstrip: cannot find matching section for [26] '__libc_subfreeres'
eu-unstrip: cannot find matching section for [27] '__libc_atexit'
eu-unstrip: cannot find matching section for [28] '__libc_thread_subfreeres'
eu-unstrip: cannot find matching section for [29] '.data.rel.ro'
eu-unstrip: cannot find matching section for [30] '.dynamic'
eu-unstrip: cannot find matching section for [31] '.got'
eu-unstrip: cannot find matching section for [32] '.got.plt'
eu-unstrip: cannot find matching section for [33] '.data'
eu-unstrip: cannot find matching section for [34] '.bss'
warning: failed unstripping libc: eu-unstrip exited with failure: exit status: 1
setting ./ld-2.23.so executable
symlinking ./libc.so.6 -> libc_32.so.6
copying hacknote to hacknote_patched
running patchelf on hacknote_patched

遇到一些无法 unstrip libc 的情况一般不用管

xxx_patched 文件导入IDA,添加用户自定义的函数名称:

图 0

图 1

选择想要导出的段,保存为ELF文件。

使用GDB就能看到自定义的函数名了:

图 2

同时因为我们patch了ELF,用ldd看到libc已经指向了刚才生成的软链接:

1
2
3
4
> ldd hacknote_patched
linux-gate.so.1 (0xf7ef8000)
libc.so.6 => ./libc.so.6 (0xf7d3e000)
./ld-2.23.so => /lib/ld-linux.so.2 (0xf7efa000)

vmmap 发现libc/ld不再使用系统路径下的libc/ld:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
Start End Perm Size Offset File
0x8046000 0x8048000 rw-p 2000 0 /home/frnks/temppwn/hacknote/hacknote_patched
0x8048000 0x8049000 r-xp 1000 2000 /home/frnks/temppwn/hacknote/hacknote_patched
0x8049000 0x804a000 r--p 1000 2000 /home/frnks/temppwn/hacknote/hacknote_patched
0x804a000 0x804b000 rw-p 1000 3000 /home/frnks/temppwn/hacknote/hacknote_patched
0xf7d84000 0xf7f31000 r-xp 1ad000 0 /home/frnks/temppwn/hacknote/libc_32.so.6
0xf7f31000 0xf7f32000 ---p 1000 1ad000 /home/frnks/temppwn/hacknote/libc_32.so.6
0xf7f32000 0xf7f34000 r--p 2000 1ad000 /home/frnks/temppwn/hacknote/libc_32.so.6
0xf7f34000 0xf7f35000 rw-p 1000 1af000 /home/frnks/temppwn/hacknote/libc_32.so.6
0xf7f35000 0xf7f3a000 rw-p 5000 0 [anon_f7f35]
0xf7f3a000 0xf7f3e000 r--p 4000 0 [vvar]
0xf7f3e000 0xf7f40000 r-xp 2000 0 [vdso]
0xf7f40000 0xf7f62000 r-xp 22000 0 /home/frnks/temppwn/hacknote/ld-2.23.so
0xf7f62000 0xf7f63000 rw-p 1000 0 [anon_f7f62]
0xf7f63000 0xf7f64000 r--p 1000 22000 /home/frnks/temppwn/hacknote/ld-2.23.so
0xf7f64000 0xf7f65000 rw-p 1000 23000 /home/frnks/temppwn/hacknote/ld-2.23.so
0xff7ee000 0xff80f000 rw-p 21000 0 [stack]

因为该题是libc 2.23,所以没有tcache,分配又释放发现chunk都在fastbins而非tcachebins:

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
pwndbg> heap
pwndbg will try to resolve the heap symbols via heuristic now since we cannot resolve the heap via the debug symbols.
This might not work in all cases. Use `help set resolve-heap-via-heuristic` for more details.

Free chunk (fastbins) | PREV_INUSE
Addr: 0x91bf000
Size: 0x10 (with flag bits: 0x11)
fd: 0x00

Free chunk (fastbins) | PREV_INUSE
Addr: 0x91bf010
Size: 0x30 (with flag bits: 0x31)
fd: 0x00

Free chunk (fastbins) | PREV_INUSE
Addr: 0x91bf040
Size: 0x10 (with flag bits: 0x11)
fd: 0x91bf000

Free chunk (fastbins) | PREV_INUSE
Addr: 0x91bf050
Size: 0x30 (with flag bits: 0x31)
fd: 0x91bf010

Top chunk | PREV_INUSE
Addr: 0x91bf080
Size: 0x20f80 (with flag bits: 0x20f81)

pwndbg> bins
fastbins
0x10: 0x91bf040 —▸ 0x91bf000 ◂— 0x0
0x30: 0x91bf050 —▸ 0x91bf010 ◂— 0x0
unsortedbin
empty
smallbins
empty
largebins
empty

提示 pwndbg will try to resolve the heap symbols via heuristic now since we cannot resolve the heap via the debug symbols. 是因为题目提供的libc一般不带调试符号,pwndbg 采用了一些技术推测出了堆相关数据的位置。如果没能推测出则可以通过下载对应glibc版本并导入 .debug 文件夹,具体参考: https://www.cnblogs.com/9man/p/17741818.html
`

gdb 我用的是 pwngdb 环境,下载pwndbg和Pwngdb,将 ~/.gdbinit 的内容改为如下即可,注意更改路径。

1
2
3
4
5
6
7
8
9
10
11
12
13
> cat ~/.gdbinit
source ~/pwndbg/gdbinit.py
source ~/Pwngdb/pwngdb.py
source ~/Pwngdb/angelheap/gdbinit.py

set disable-randomization on
#set follow-fork-mode child

define hook-run
python
import angelheap
angelheap.init_angelheap()
end