http://scz.617.cn:8/unix/201901171036.txt
大家好,我是以碳基生命形态存在的人形调试器,比较擅长排查一些不作不死的疑难杂症。今天给大家带来的故事发生在某平行宇宙的某个时间点。
/etc/passwd里有:
scz:x:1000:1000:scz,,,:/home/scz:/tmp/sczsh
/tmp/sczsh内容如下:
#!/bin/bash
exec /bin/bash "$@"
为何出现这种局面无关紧要,不过这并非YY出来的场景,实际遭遇过。此处将整个问题简化收敛成这么一个例子。以scz登录后env可以看到:
SHELL=/tmp/sczsh
$ file -b /tmp/some
ELF 32-bit LSB pie executable ...
readelf -h /tmp/some
ELF Header:
...
Type: DYN (Shared object file)
...
Entry point address: 0x415a
...
现在执行:
$ gdb -q -nx /tmp/some
(gdb) starti
Starting program: /tmp/some
Program stopped.
0xb7fd70b0 in ?? () from /lib/ld-linux.so.2
我以为starti之后停在some进程空间中,实际停在bash进程空间中:
(gdb) info proc mappings
process 10247
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x400000 0x41e000 0x1e000 0x0 /bin/bash
0x41e000 0x4d1000 0xb3000 0x1e000 /bin/bash
0x4d1000 0x528000 0x57000 0xd1000 /bin/bash
0x529000 0x530000 0x7000 0x128000 /bin/bash
...
(gdb) info proc status
process 10247
Name: bash
...
(gdb) info proc stat
process 10247
Process: 10247
Exec file: bash
...
Start of text: 0x400000
End of text: 0x4d0638
Start of stack: 0xbffff700
(gdb) info proc exe
process 10247
exe = '/bin/bash'
(gdb) info proc cmdline
process 10247
cmdline = '/bin/bash'
(gdb) shell ps -f -o pid,user,args
PID USER COMMAND
10092 scz /bin/bash
10245 scz \_ gdb -q -nx /tmp/some
10247 scz \_ /bin/bash -c exec /tmp/some
10251 scz \_ ps -f -o pid,user,args
此时想继续调试并断在some进程空间中某地址,"set follow-exec-mode new"没用。
有个歪招:
(gdb)catch exec
Catchpoint 1 (exec)
(gdb) c
Continuing.
process 10247 is executing new program: /tmp/some
Catchpoint 1 (exec'd /tmp/some), 0xb7fd70b0 in ?? () from /lib/ld-linux.so.2
断下来的时候,已经切入新进程映像,前提是exec*()成功。
"catch exec"并不等同于"catch syscall execve",后者断下来时还在原进程映像中,尚未切入新进程映像。
(gdb) info proc mappings
process 10247
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x400000 0x402000 0x2000 0x0 /tmp/some
0x402000 0x417000 0x15000 0x2000 /tmp/some
0x417000 0x423000 0xc000 0x17000 /tmp/some
0x424000 0x426000 0x2000 0x23000 /tmp/some
...
(gdb) info proc exe
process 10247
exe = '/tmp/some'
(gdb) info files
...
Entry point: 0x40415a
(gdb) shell ps -f -o pid,user,args
PID USER COMMAND
10092 scz /bin/bash
10245 scz \_ gdb -q -nx /tmp/some
10247 scz \_ /tmp/some
10255 scz \_ ps -f -o pid,user,args
现在"tb *0x40415a"可以断在some的"Entry point"。
前面都是垃圾,看着很NB但毫无意义。正经套路是:
$ gdb -q -nx /tmp/some
(gdb) help run
...
To start the inferior without using a shell, use "set startup-with-shell off".
(gdb) show startup-with-shell
Use of shell to start subprocesses is on.
缺省是on,改成off:
(gdb)set startup-with-shell off
这样设置之后再run、start、starti,由gdb直接启动被调试进程,不经shell。
(gdb) starti
Starting program: /tmp/some
Program stopped.
0xb7fd70b0 in ?? () from /lib/ld-linux.so.2
(gdb) info proc mappings
process 10261
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x400000 0x402000 0x2000 0x0 /tmp/some
0x402000 0x417000 0x15000 0x2000 /tmp/some
0x417000 0x423000 0xc000 0x17000 /tmp/some
0x424000 0x426000 0x2000 0x23000 /tmp/some
...
(gdb) shell ps -f -o pid,user,args
PID USER COMMAND
10092 scz /bin/bash
10259 scz \_ gdb -q -nx /tmp/some
10261 scz \_ /tmp/some
10265 scz \_ ps -f -o pid,user,args
程序员的调试技能就是在林林总总的坑中爬出来的。
题外话,个人觉得这种不大不小的坑在CTF比赛中会增加趣味性,不过我是在真实场景遭遇的,其障碍性后果是副产品。
准备测试用例、写这篇文档时,把SecureCRT弄崩了,决定视而不见,不挂调试器。
领取专属 10元无门槛券
私享最新 技术干货