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函數之前執行的所有函數都是沒有棧幀的

ret2syscall
因為需要執行大量代碼段,故通過局部變量溢出, 組合一些gadget執行大量的代碼片段,故将從ret開始的一大段棧空間,覆寫成gadget位址和對應的參數,此時,在main函數傳回時,就會傳回到已經被覆寫掉的,現在是ret的位址, 并執行指令
(ret把目前棧頂的值pop到eip)ret等效于pop eip
get --binary 檔案名 -- only “ pop | ret 要尋找的指令|管道符 grep xx 把輸入參數中含有xx的指令顯示出來
Ret = pop xxx 即把xxx彈出到eip
Xor 清空寄存器
下面是示例!
Int 0x80 ( eax = 0xb , ebx = …, ecx = 0,edx = 0 )進行系統調用( int – 中斷指令 ),通過寄存器傳參,來确定要調用哪一個函數。在執行int 0x80 這個彙編代碼對應的機器碼時,要確定四個寄存器都已經存儲了對應的函數所需要的參數,即0xb這一個系統調用号對應的sys_execve() 對應的核心裡的函數的調用号,而0xb 在這裡·也帶代表了那個函數
下面使用pwntools便捷擷取/bin/sh的位址
使用next傳入生成器
最後一層是要輸入的垃圾資料,倒數第三行是要給
倒數第二層輸入的資料,以此類推
動态連結
當我們使用file指令去檢視一些檔案的屬性時,下面兩點也會被顯示出來:
動态連結:gcc -fno-pie -o dytest xxx.py dynamically link
靜态連結:gcc -fno-poe --static -o statest xxx.py statically link
本塊主要讨論動态連結
動态連結相關結構
dynamic section 為作業系統描述了整個動态連結的完整内容
提供動态連結相關資訊
link_map 儲存程序載入的動态連結庫的連結清單
dl_runtime_resolve 解析第一次在動态連結的函數的真實位址
裝載器中用于解析動态連結庫中函數的實際位址的函數
got 全局的符号、變量位址
got.plt 全局的函數位址
動态占用記憶體小(其庫函數占用少)
動态連結過程
ldd 檔案名 檢視檔案用到的所有動态連結庫
下面分流程分析
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 函數傳參
7、call_fix_up dl_runtime_resolve 函數解析 foo 的真正位址填入 .got.plt 中
8、ret 0xc 此後 .got.plt 中儲存的是 foo 的真實位址
9、call foo@plt 系統第二次調用foo
10、jum *(foo@GOT) 直接自 .got.plt 跳轉到 foo 的真實位址,沒有了第一次的解析位址過程
ok,接下來展示完整流程
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