接下來,視頻講解的都是各個例子(https://space.bilibili.com/14500640/)
(1)程序中自身就含有system函數和"/bin/sh"字符串
(2)程序中自身就有system函數,但是沒有"/bin/sh"字符串
(3)程序中自身就沒有system函數和"/bin/sh"字符串,但給出了libc.so文件
(4)程序中自身就沒有system函數和"/bin/sh"字符串,並且沒有給出libc.so文件
1.ret2text
ret2text即需要我們控制程序執行程序本身已有的的代碼(.text)。
nx則是no execution, 如果開啓的話就不能讓IP寄存器指向堆、棧
objdump -R 文件名 ---> 可以查看文件中的函數
2.ret2shellcode
簡介
ret2shellcode顧名思義,就是return to shellcode,即讓程序中某個函數執行結束後,返回到shellcode的地址去執行shellcode,得到system(sh)的效果。
shellcode 指的是用於完成某個功能的彙編代碼,常見的功能主要是獲取目標系統的 shell。一般來說,shellcode 需要我們自己填充。
ret2shellcode的侷限性在於,在棧溢出的基礎上,要想執行 shellcode,需要對應的 binary 在運行時,shellcode 所在的區域具有可執行權限,即通常情況下我們checksec程序是NX保護就關閉的,否則當程序溢出成功轉入shellcode時,程序會嘗試在數據頁面上執行指令,此時CPU就會拋出異常,而不是去執行惡意指令。
這裏是up主的筆記:
這個時候就有兩個注意點
1NX:NX disabled
2 strncpy(buf2, &s, 0x64u);
第一句代表,我們把shellcode放在堆,棧或者其他數據段上,然後讓IP寄存器指向那裏就可以獲得shell
第二句代碼的意思是程序會把輸入複製到buf2去,buf2是什麼呢?
. bss : 0804A080 buf2 db 64h dup(?)
PIE:No PIE (0x8048000 )
在PIE沒有開啓的情況下, bss段的地址是固定的,所以,我們把shellcode寫入bss段,然後跳轉過去就可以獲得shell了
下面實際寫一下exp
這裏提一下 ,現代的操作系統,都默認開啓了aslr保護措施,這個保護措施是由系統管理的,開啓時,堆,棧,libc的地址會隨機化
但是bss段沒有隨機化
這裏要先確定多少偏移能夠覆蓋返回地址
這裏提下,我是通過cyclic工具獲取偏移的, 也可以手動計算
這裏112個字節之後就是用來控制返回地址的數據,這個地址我們用buf2的地址,在前面112個字節裏面放入shellcode
這裏提一下, asm功能和系統, OS位數都有關,所以要指定程序的位數(設置binary)
pwntooLs的shellcraft模塊提供了一些寫好的shellcode ,大家可以去看文檔,
3.ret2syscall(該題是靜態鏈接)
ret2syscall,即控制程序執行系統調用,獲取 shell。
靜態鏈接是指在編譯階段直接把靜態庫加入到可執行文件中去,這樣可執行文件會比較大。
動態鏈接是指鏈接階段僅僅只加入一些描述信息,而程序執行時再從系統中把相應動態庫加載到內存中去。
所以在PWN中,如果是靜態鏈接的題目,問題就變得非常簡單了。
vmmap:查看現有的進程或者追蹤新的進程並查看其電腦內存使用
第一步,ROPgadget --binary rop -- ropchain,會生成了一個rop chain,只要我們讓程序跳到這裏開始執行,就可以獲得shell
ret2libc 即控制函數的執行 libc 中的函數,通常是返回至某個函數的 plt 處或者函數的具體位置 (即函數對應的 got 表項的內容)。一般情況下,我們會選擇執行 system("/bin/sh"),故而此時我們需要知道 system 函數的地址。
4.ret2libc1
現在plt表中有system函數,但是參數不是‘/bin/sh’,但是程序中有‘/bin/sh’
內存中搜索字符串:ROPgadget --binary ret2libc1 --string '/bin/sh'
plt中放的是代瑪 (如果在plt表中存在某個函數,我們用這個地址相當於直接使用這個函數)
got中放的是數據
然後後面的四個a是執行完system的返回地址,因爲我們這裏直接獲得了shell,這個地址執行不到,陸使寫
p32 (0x8049720)這裏則是存放/ b1n/ sh的地址
將system函數的起始地址佈局到棧上是,相當於這裏去調用system函數,所以執行system函數之前會存放system函數的下一條指令的地址,再接下來是函數的參數
(該程序源代碼:https://download.csdn.net/download/qq_43935969/12119259)
5.ret2libc2
現在plt表中有system函數,但是參數不是‘/bin/sh’,但是程序中也沒有‘/bin/sh’
但是程序有輸入點,所以就考慮將‘/bin/sh’先輸入到程序中,然後將地址給system做參數
這裏就是執行了gets(elf. bss( )+0x100)
然後執行了system( elf. bss( )+0x100)
中間通過一個gadget連接起來
然後程序執行到gets的時候會等待我們輸入
p. sendline( , /bin/sh\x00' )
research的最初想法:
pop eax的作用是平衡棧幀,因爲get函數有一個參數,而在(3)中提到過,參數有多少,返回的時候就要add多少,pop eax就可以讓esp+4,ret就可以結束get函數,而eip這裏都還沒變,所以繼續執行112之後的作爲返回地址
這是pwntools官網上對rop.search()的解釋,因爲‘/bin/sh’是兩個字節,所以需要8位
rop可以結束棧幀,get函數結束
6.ret2libc3
沒有system函數也沒有‘/bin/sh‘,那我們就要找到對應的.so庫獲取庫裏面對應的system函數的地址和/bin/sh的地址。
思路:
1.泄露 一個調用函數的地址
2.獲取 libc 版本
3.獲取 system 地址與 /bin/sh的地址
4.再次執行源程序
5.觸發棧溢出執行 system(‘/bin/sh’)
PIE沒開,說明.text段、got表和plt表都是不變的
查看函數中各個表有哪些(有哪些函數):objdump -R 名字
泄露 一個調用函數的地址:
exp:
(a)0x8048618是mian的返回地址,泄露了put的地址後返回到main處再次執行
(b)接受到泄露的四個字節後要u32,解包
(c)0x15ba0b是binsh的偏移地址,是在gdb調試中算出來的
binsh程序中的地址 - libc的地址
(4)第二次重定位問題?所以偏移地址改變,104
【注:system()函數調用/bin/sh來執行參數指定的命令,/bin/sh 一般是一個軟連接,指向某個具體的shell】
done!