[H3X0R CTF 2016]

Web+Pwnable_120

Simple_Test



120점짜리 Web+Pwnable 문제입니다.

문제를 살펴보기에 앞서, 이 문제는 Web+Pwnable임에도 불구하고 web문제를 우회하여 풀이 할 수 있었습니다..


Misc_1_mic_no_check : http://choiys.tistory.com/entry/H3X0R-CTF-2016-misc1micnocheck


위 1점짜리 문제를 풀이할 때 ;sh를 이용하여 쉘을 띄워 문제를 풀이하였습니다.

그런데 여기서 find / -name flag 2>/dev/null 명령어를 이용하여 검색을 하면 1점짜리 문제의 플래그 뿐만 아니라 다른 문제들의 플래그까지 검색이 가능했습니다.

물론 플래그에 접근 할 수 있는 권한이 없었지만...

디렉토리의 _solved를 빼면 해당 문제의 디렉토리가 나온다는 것은 쉽게 유추 할 수 있었습니다.

그래서 Simple_Test_solved에서 _solved를 뺀 디렉토리를 들어가면 Simple_Test 바이너리가 기다리고 있으며...

실행까지 됩니다.

웹을 풀지 않아도 바이너리에 접근 가능했던거죠.



잡설은 여기까지.. 먼저 웹 문제를 확인 해 봅시다.



simple_sqli.php가 나오는데, sql injection을 통해 로그인을 우회하라는 것 같습니다.



소스를 확인 해 보니 id와 pw의 포맷을 알려주고 있습니다.



guest/guest로 입장 했을 때의 화면이며, admin으로 접속을 해야합니다.

위에서 pw의 포맷을 알려주었으니 그대로 써먹어봅시다.

pw에 guest')-- 를 넣어주면 guest로 로그인이 됩니다.

따라서 a')||1-- 를 넣어줘도 guest로 로그인이 됩니다.

그렇다면 여기서 생각 할 수 있는것은, 첫 번째 row에 guest가 있다고 가정했을 때 2번째 row에 admin이 있을 것입니다.


a')||1 limit 1,1-- 의 쿼리를 입력 했을 때 화면입니다.

limit 구문을 이용하여 2번째 row 값을 출력했더니 예상대로 admin으로의 로그인이 성공했으며, base64로 인코딩 된 문자열이 나타났습니다.



이 값을 decoding 하면 nc로 접속 할 수 있는 ip와 port가 나타납니다.


여기서 이 문제의 취약한 부분이 나타나는데, 문제마다 모두 ip가 같으며, 50001 ~ 50005번 등의 포트를 사용했습니다.

이로 미루어 보았을 때 웹 문제를 풀지 않고 단순 게싱으로도 pwnable 문제로 바로 넘어 갈 수 있습니다.



해당 문제를 확인 해 보니, 바이너리의 소스코드를 보여주는 프로그램이 실행되었습니다. 마지막에 바이너리를 받을 수 있는 구글 드라이브 url이 있으니, 문제를 받아줍시다.



checksec.sh로 Simple_Test 바이너리를 확인 해 보니 NX를 제외한 모든 보호 기법이 해제되어있습니다.



소스는 source 변수가 바이너리를 실행했을 때 나타나는 소스코드가 들어있는 변수입니다.

따라서 stdout으로 소스코드를 출력해주고, read 함수로 stdin으로 100만큼의 버퍼를 읽어들입니다. 하지만 buf 변수는 12바이트의 공간을 가지고 있기 때문에 BOF가 가능한 바이너리라고 볼 수 있습니다.


-----------------------------------------------------------------------------

이 문제는 CTF 도중 풀지 못했던 문제입니다.

하지만 H3X0R 페이스북 페이지에 올라온 송사리님의 WriteUp을 확인 했을때는 NX가 걸려있지 않다고 했는데...

제가 대회중에 확인했을 때 바이너리는 NX비트가 걸려있어 스택에서 쉘코드를 실행 할 수 없는 상태였습니다.

친구가 송사리님과 H3X0R 페이지 관리자분께 사실여부 파악을 위해 문의를 넣은 상태이며, 결과가 나오는대로 WriteUp 작성하겠습니다.

'CTF > H3X0R CTF 2016' 카테고리의 다른 글

[H3X0R CTF 2016] Misc_20_is_this_real_hex  (0) 2016.05.16
[H3X0R CTF 2016] Web_63_php_encrypt  (0) 2016.05.16
[H3X0R CTF 2016] Web_10_cmp  (0) 2016.05.16
[H3X0R CTF 2016] Misc_1_mic_no_check  (0) 2016.05.16
[H3X0R CTF 2016] Reversing_200_RPG Game  (0) 2016.05.16

[H3X0R CTF 2016]

Misc_20

is_this_real_hex



대회 시작부터 공개되었던 20점짜리 misc문제입니다. 초반에 다들 이 문제만 푸셨었더라구요..

무슨 문제인지 확인 해 봅시다.



문제를 다운받으면 26바이트짜리 파일이 있습니다.



출력 해 보니 깨진 문자를 포함한 스트링이 출력됩니다.



문제가 hex가 관련되어있으니 hexdump로 hex값을 뽑아봅니다.



python으로 해당 hex값을 1부터 더해주는 스크립트를 작성해봤습니다.



더하는 결과값으로는 플래그에 관련된 값을 찾을 수 없었습니다.



이제 빼봅시다.



모든 hex값에서 10을 뺐을 때

 

fl[g iy ^ong\in iy yo \}z_ 


라는 문자열이 출력되었습니다.

뭔가 flag 관련된 문자열인듯 하여 이 값을 파보았습니다.



[는 a가 될 것이고, y는 s가 되는 것 같습니다.

그리고 원래의 hex값이 95일 때 _가 됩니다.(문제 힌트에 format is FLAG_IS_THIS_FLAG 와 같이 주어졌습니다.)

확인 해 본 결과, 3, 7, 9, 13, 18, 20, 23, 24, 25, 26번째 자리가 변환되어있었으며, 각각 -10 한 결과에서 +6이나 -6만큼 해줄 때 알파벳으로 출력이 되었습니다.

위 코드처럼 직접 인덱스를 박아줘도 되지만, +6, -6 한 결과가 알파벳의 범위에 있을 경우 출력하는 코드로 작성해도 무방합니다.



위 플래그 값을 대문자로 입력 해주면 됩니다.


FLAG_IS_DONGBIN_IS_SO_CUTE

[H3X0R CTF 2016]

Web_63

php_encrypt



대회 중반에 공개된 63점짜리 Web 문제입니다. 파일을 다운 받은 후 압축을 풀면 php_encrpyt.php라는 파일이 나타납니다. 이 파일을 열어보면 아래 그림과 같은 소스가 나타납니다.



대회 이름에 맞게 변수명이 약간 복잡하게 되어 있습니다. 직접 계산해서 돌려도 되지만, 편하게 php 서버를 돌려 값을 찾아내도록 하겠습니다.

먼저, 알아 낼 수 있는 것들을 알아내보죠.


$_b는 ord

$_는 ?

두 번째 $__는 $_GET['?']입니다.

그렇다면 11번째 라인의 $__[0]은 $_GET['?'][0]으로 볼 수 있겠네요. 1, 2, 3도 마찬가지로 생각 할 수 있습니다.



해당 php소스를 돌려보면 위와 같은 결과 값이 나옵니다. 소스대로, 일정 조건을 만족하지 않으면 ?와 !를 출력하게 됩니다.

이 조건을 만족하는 4자리의 값이 flag일 것 같네요.



해당하는 값을 echo로 바로 때려줍시다.



4번째 자리는 'z'로 이미 명시되어 있기 때문에 출력하지 않았습니다.

이를 이어보면 f9!z가 되겠네요.



flag is f9!z



[H3X0R CTF 2016]

Web_10

cmp



대회 초중반쯤 공개 된 10점짜리 web 문제입니다. 친구들이랑 저녁밥 먹고 다시 들어와 보니 공개 되어 있었죠.. 확인 해 봅시다.


패스워드를 입력하는 text box와 submit 버튼 하나가 있습니다.

여기에 아무 문자나 입력을 하고 submit 해 봅시다.




A를 submit 해 보았더니 2라는 결과값을 뱉어냈습니다.



d를 입력 했을 때는 -33이 나왔습니다.


PHP strcmp() 함수의 반환값의 특성을 이용한 문제인 것 같습니다. 이 문제에서 str1은 flag, str2는 string을 가리키고 있는 것 같습니다.

아스키 코드 상으로 A보다 2만큼 위에 있는 문자는 C입니다. 



C를 입력해주니 15라는 값을 반환 해 주었습니다. C에 이어 다른 글자를 입력 해 주었을 때 위와 같이 양/음수로 나누어 출력을 해 주었습니다.



다른 문자들을 집어 넣어 2번째 문자는 0임을 알 수 있었습니다. 올바른 문자를 입력 했을 때 반환하는 숫자 값이 1씩 줄어드는 것을 보니, 이 값은 남은 string의 길이 같습니다. flag의 총 글자 수는 16인 것을 여기서 알 수 있었습니다.



사실 python으로 스크립트를 작성하여 브포를 돌려볼까도 생각 해 봤지만, 음수도 있고, 반환하는 숫자 값도 일정하지 않아 직접 손으로 브포를 했습니다...

(저 숫자가 남은 글자 수인 것을 알아 낸 타이밍이 4자 이상 찾았을 때라... 귀찮기도 했습니다.)



flag is C0MP4R3_15_900D!



[H3X0R CTF 2016]

Misc_1

mic_no_check



대회 초반에 공개 됐던 misc 1점짜리 문제입니다.



nc로 주어진 ip, port로 접속하면 echo : 라는 문구가 나옵니다. string 값을 입력 받는 것 같네요.



;sh를 입력해주면 shell이 떨어지게 됩니다.

id를 입력 해 보니 mic_no_check_solved 권한으로 로그인 되어 있는 것을 확인 할 수 있습니다.



아마 flag라는 이름으로 flag가 있을 것이니, 검색을 해 줍시다. 

find / -name flag 2>/dev/null 로 결과값만 빠르게 확인 할 수 있습니다.

Write Up을 쓰고 있는 현재, 서버 응답이 상당히 느리기 때문에 대회 당시에 찾았던 경로를 바로 사용하겠습니다.



해당 경로로 이동해 flag 값을 읽어주면 flag를 찾을 수 있습니다.


flag is RESPECT_CODEGATE





대회가 끝나서 하는 말이지만... vim은 터미널이 아니라 사용 할 수 없었지만 /tmp 경로에서


echo "#include<stdio.h>

int main(int argc, char *argv[]){

printf("Hello World!\n");

return 0;

}" > test.c


gcc -o test test.c


./test


위와 같은 형식으로 컴파일 및 파일 구동까지 모두 가능했었습니다. 물론 gdb와 파이썬도 돌아갔구요.

해당 id의 권한을 제한하지 않은 것이 큰 문제였던 것 같습니다.

[H3X0R CTF 2016]

Reversing_200

RPG Game


코드게이트 대학생 세션을 제외하고는 2016년에 처음 참가하는 CTF입니다.

디미고 H3X0R 팀에서 주최하는 CTF인데, 초반 대회 운영 및 문제마다 자잘한 버그/취약점이 하나,둘씩 있어 약간 아쉬웠던 대회였습니다.

이 문제는 대회 초반에 공개된 RPG Game 문제입니다.



바이너리를 실행했을 때의 화면입니다.

Stage1부터 30까지 이루어져있으며 아무 키나 입력하면 HP가 1씩 줄어듭니다. HP를 모두 소진시키면 다음 스테이지로 자동으로 넘어갑니다. 하지만 스테이지가 다음으로 넘어가면 넘어갈수록 기하급수적으로 HP가 늘어나기 때문에 직접 HP를 깎기엔 힘드니 디버거를 통해 값을 바꿔줘야합니다. 일단 이뮤니티로 해당 바이너리를 열어보았습니다.



스트링 값을 확인 해 봤더니 위에서 언급한대로 30까지의 스테이지가 있다는 것을 유추 해 볼 수 있고, WSAStartup() 함수와 hSocketet() 함수, connect() 함수의 존재로 보아 소켓 통신을 한다는 사실을 알 수 있습니다.



conncet() 부분으로 이동 해 보니 send 함수가 있습니다. 여기로 어떤 값을 보내고, recv로 응답값을 수신하는 것 같습니다. 아마 이 부분에서 flag를 받아올 것 같습니다.



HP와 스테이지 값을 손쉽게 바꾸기 위해 Cheat Engine을 추가로 붙여주었습니다.

HP 값과 스테이지 값을 찾아 값을 변경 후, FIX 해 줍시다.



HP값을 왼쪽의 Active 버튼을 눌러 FIX 한 후, 이뮤니티에서 send 부분에 브포를 걸고 어떤 값을 송/수신 하는지 확인 해 보았습니다.



처음 봤을땐 Base64 인코딩인 줄 알았지만, 중간중간에 섞인 특수문자로 보아, 암호화 된 스트링인 것 같습니다.



recv 부분을 보니 받아온 값이 CRACKED! 라는 응답값이었습니다. 아마도 send 부분에서 올바른 값을 보내지 않으면 CRACKED!라는 문구를 뱉어내는 것 같습니다. 여기서 생각 해 볼 수 있는 것은 1에서 바로 30단계로 갔기 때문에 송신 값이 제대로 복호화 되지 않은 채로 넘어갔기 때문이라고 볼 수 있습니다. 그렇다면 1 -> 30이 아닌, 차례대로 30단계까지 가는 방법을 이용해보죠.



스테이지 값을 찾을 필요가 없으니, HP값만 찾아 FIX해줍시다.



10단계까지 왔을 때 HP 양입니다.

1410065408로, 여기서 2배가 된다면 4Byte INT형 변수의 최대 값인 2147483647을 넘어가게 됩니다.



그래서 11단계로 왔을 때 -값에서 더이상 다음 스테이지로 넘어가지 않습니다.



따라서 Cheat Engine에서 값의 Type를 4Byte에서 8Byte로 확장해줍시다.



그러면 값의 제한이 없어 30단계까지 정상적으로 클리어 할 수 있습니다.



다시 이뮤니티로 넘어와 send하는 값을 보니, flag같은 값이 넘어갑니다. 하지만 여기는 send하는 부분이니 recv 값까지 확인 해 봅시다.



위와 같이 base64로 인코딩 된 것 같은 스트링 값을 뱉어냈습니다.



notepad로 복사 해두고, 디코딩 해 봅시다.


Flag is RpG_G@mE_CraCk!

+ Recent posts