天天看點

pwn學習筆記

PWN學習筆記——初稿

注明:本篇學習筆記是入門學習pwn時的随筆,是以不具有任何參考價值 ,僅作為對學習路線回顧參考的筆記以及入門紀念。

使用 Kali Linux , 稱霸區域網路 ![doge]

調試,調試!

Ida中的靜态調試顯示的函數和輸出之間的距離,有時候會因為各種原因😁而顯示錯誤,需要用pwndbg動态調試觀察一下。淦,gdb顯示的位址有時候也不對

IDA基本操作 (靜态調試)

shift + F12

space

F5

ctrl + F

Pwndbg基本操作(動态調試)

Pwndbg + 檔案名  進入對某個檔案的調試

r 運作

b + 位址/函數  設定斷點

checksec + 檔案名  檢視保護措施

stack + 數字  檢視棧段

vmmap' 顯示虛拟記憶體的的空間分布(觀察讀寫的權 限是否有沖突-w與x不同時出現

plt 檢視檔案裡的plt表項

x + 位址 顯示該位址的内容和位址

got 檢視got中儲存的函數數量及其位元組、資料等資訊

disass + 位址 反彙編位址的資料,進而檢視其彙編代碼或plt

c 繼續執行程式,直到遇到斷點/程式中斷

start 開始執行程式,會停到main函數;如果沒有main函數,則會停到程 序的入口

s 附近

backtrace 顯示函數調用棧段的狀态

return 快速回到mian函數

求求了,用用py吧 🐶

(context.arch = “amd64”)  調整攻擊環境 

shellcode.sh()

print(xxx)  更清楚地檢視shellcode

print(asm(xxx))  檢視shellcode的機器碼

擷取shellcode : 1.shellstore 2.pwntools – shellcraft.sh() (後面就是方法) 

Print(asm(shellcode.(amd64.)sh()))

嘿嘿嘿·🤭,腳本(介紹一下大緻模闆,最簡單的那種啊,别誤會)

vim exp.py

from pwn import *
​
(context.arch = "amd64")
​
io = process("本地檔案路徑")  //與本地檔案互動 
​
OR  
​
io = remote("IP", 端口 )
​
io.recvline()               //接受程式給的檔案
​
payload = b'”x”(位元組型的資料) + p32(劫持程式的位址)  //将一個整數的位址轉化成位元組型的資料  32位的                                                   ebp占4個位元組,64位的·ebp占8個位元組
io.send(payload)            //發送資料   
​
OR  
​
io.sendline(payload)        //發送一行資料,相當于在資料末尾加/n;
​
io.interactive()            //互動       
from pwn import *
​
(context.arch = "amd64")
​
io = process("本地檔案路徑")   //與本地檔案互動 
​
OR  
​
io = remote("IP", 端口 )
​
io.recvline()                //接受程式給的檔案
​
asm(shellcode.(amd64.)sh())  //擷取shellcode的機器碼    
​
payload = asm( shellcode.(amd64.)sh()),lhust( 112, b’A ) /*補充位元組流(這裡就是A )到112 */ + p32( 劫持程式的位址(可以是全局變量的位址) )
​
io.send(payload)            //發送資料   
​
OR  
​
io.sendline(payload)        //發送一行資料,相當于在資料末尾加/n;
​
io.interactive()            //互動       

還有很多呐!

呐,shellcode注意啥啊

bss預設可執行,是以我們可以通過全局變量向其輸入shellcode

gets 漏洞

未初始化的全局變量儲存在bss裡

不會算數,py來救

使用python計算棧段之間的距離

0x….(高位址) – 0x…(低位址)

>>>十進制數

Hex(十進制)

>>>十六進制

保護措施 🛡

1-NX 棧不可執行

2-ASLR 讓函數的棧、共享連接配接庫、堆段進行位址随機化,

0 – 未打開;1 – 部分随機化;2 – 全部随機化

關閉ASLR – “echo 0 > /proc/sys/kernel/randomize_va_space”

3-Canary(金絲雀) 在調用一個函數,剛建立棧幀時,首先把一個值(canary)放在低位址空間裡,在銷毀 函數時,先檢查這個值(canary)是否發生改變,如果值改變,就會其強行将程式退出

4-Pie 編譯時打開開關,随機化elf檔案映像(text,bss。data)

程式進不去怎麼辦😱

修改檔案權限

#!/bin/sh
​
gcc -fno-stack-protector -z execstack -no-pie -g -o re2stack ret2stack.c
​      

-fno-stack-protector 關閉canary,使棧溢出首先可行

-z execstack  打開棧的可執行權限

-no-pie  關閉pie

-g  帶上調試資訊,便于觀看(一定要帶着re2stack.c)

-o  輸出檔案名

請問位元組是啥🤐

8比特 – 1 位元組

每4比特可以直接寫成一個16進制的值,

每兩個16進制數就是1個位元組

ROP!!!

沒有連續的代碼,但是通過一段一段的這個函數中包含的代碼片段,達到相同的執行效果,即模拟程式的執行

其中思想的不同:沒有一步到位的位址一次覆寫到tet,調用shell(即調用shell攻擊目标,無法通過一個位址一次,是以需要,自己将程式中的指令組合起來,起到shell的作用)

我們所需要的為eaxebx…指派的代碼本來就存在,但是不連續,我們需要把他們組成一個鍊式結構(gadget),是以需要溢出很長的一段資料,把這些調成想要的格式,使其能夠連續工作,并使其最後一條指令為ret。

對于系統調用,要在所有以ret結尾的代碼中,找出個代碼片段,它們的作用分别是pop eax、pop ebx、pop ecx、pop edx,pop一個寄存器的指令可以将數值直接寫到棧上

PS:系統調用 —— 本質上隻是一段函數,X86使用中斷進行系統調用,第一個棧幀是main函數的棧幀,在main函數之前執行的所有函數都是沒有棧幀的

pwn學習筆記

ret2syscall

因為需要執行大量代碼段,故通過局部變量溢出, 組合一些gadget執行大量的代碼片段,故将從ret開始的一大段棧空間,覆寫成gadget位址和對應的參數,此時,在main函數傳回時,就會傳回到已經被覆寫掉的,現在是ret的位址, 并執行指令

(ret把目前棧頂的值pop到eip)ret等效于pop eip

pwn學習筆記

pwn學習筆記
pwn學習筆記

get ­­­­­­­­­­­­­­­­­­­­--binary 檔案名 -- only “ pop | ret 要尋找的指令|管道符 grep xx 把輸入參數中含有xx的指令顯示出來

Ret = pop xxx 即把xxx彈出到eip 

Xor 清空寄存器

下面是示例!

pwn學習筆記
pwn學習筆記

Int 0x80 ( eax = 0xb , ebx = …, ecx = 0,edx = 0 )進行系統調用( int – 中斷指令 ),通過寄存器傳參,來确定要調用哪一個函數。在執行int 0x80 這個彙編代碼對應的機器碼時,要確定四個寄存器都已經存儲了對應的函數所需要的參數,即0xb這一個系統調用号對應的sys_execve() 對應的核心裡的函數的調用号,而0xb 在這裡·也帶代表了那個函數

下面使用pwntools便捷擷取/bin/sh的位址

pwn學習筆記

使用next傳入生成器

pwn學習筆記

最後一層是要輸入的垃圾資料,倒數第三行是要給

倒數第二層輸入的資料,以此類推

pwn學習筆記

動态連結 

當我們使用file指令去檢視一些檔案的屬性時,下面兩點也會被顯示出來:

動态連結:gcc -fno-pie -o dytest xxx.py   dynamically link

靜态連結:gcc -fno-poe --static -o statest xxx.py   statically link

本塊主要讨論動态連結

動态連結相關結構

pwn學習筆記

dynamic section 為作業系統描述了整個動态連結的完整内容

提供動态連結相關資訊

link_map 儲存程序載入的動态連結庫的連結清單

dl_runtime_resolve 解析第一次在動态連結的函數的真實位址

裝載器中用于解析動态連結庫中函數的實際位址的函數

got  全局的符号、變量位址

got.plt 全局的函數位址

動态占用記憶體小(其庫函數占用少)

動态連結過程

ldd 檔案名 檢視檔案用到的所有動态連結庫

pwn學習筆記

下面分流程分析

pwn學習筆記

text —— 代碼節;foo@olt —— foo是自己寫的函數;plt是代碼段中存放函數真實位址的一個節; PLT0(PLT最開始的兩段指令)

因為foo是個動态連結庫中的代碼,是以call foo,并不能直接跳轉到它自己代碼段裡的foo函數,隻能去代碼段中的plt節,而每個被調用的動态連結庫中的函數都會在其中創立一個表項,

1、call foo@plt 程序首次調用 foo

2、jmp *(foo@GOT) 跳轉到 .plt 中的 foo 表項,plt 中的代碼立即跳轉到.got.plt 中記錄的位址

3、push 由于程序是第一次調用 foo,故.got.plt 中記錄的位址是 foo@plt+1

4、jmp 回到 .plt 是,解析 foo 的實際位址

5、push *(GOT+4) 跳轉到 .plt 頭部,為 dl_runtime_resolve 函數傳參

6、push *(GOT+4) 跳轉到 .plt 頭部,為 dl_runtime_resolve 函數傳參

pwn學習筆記

7、call_fix_up dl_runtime_resolve 函數解析 foo 的真正位址填入 .got.plt 中

8、ret 0xc 此後 .got.plt 中儲存的是 foo 的真實位址

pwn學習筆記

9、call foo@plt 系統第二次調用foo

10、jum *(foo@GOT)  直接自 .got.plt 跳轉到 foo 的真實位址,沒有了第一次的解析位址過程

ok,接下來展示完整流程

pwn學習筆記

IDA的細節

init 用作初始化的一個節,記錄了初始化代碼

plt 存放函數真實位址的一個節

got 存放資料的節

ret2libc

往往依賴于rop所需要的各種gadget創造執行shellcode的環境,但其目标是傳回libc裡的system函數這一類可以為我們提供一個shell的函數

TRANSLATE with

x

English

Arabic Hebrew Polish
Bulgarian Hindi Portuguese
Catalan Hmong Daw Romanian
Chinese Simplified Hungarian Russian
Chinese Traditional Indonesian Slovak
Czech Italian Slovenian
Danish Japanese Spanish
Dutch Klingon Swedish
English Korean Thai
Estonian Latvian Turkish
Finnish Lithuanian Ukrainian
French Malay Urdu
German Maltese Vietnamese
Greek Norwegian Welsh
Haitian Creole Persian

COPY THE URL BELOW

Back

EMBED THE SNIPPET BELOW IN YOUR SITE

Enable collaborative features and customize widget: Bing Webmaster Portal