[그림 1] 문제


Matrix에서는 문제에서 딱히 힌트가 없어보였습니다.

그런데 문제에서 visualize라는 단어에서 한 가지 힌트를 얻을 수 있었습니다.

KUCIS수업을 들으면서 전북대 정보보호 동아리 사람들과 이야기를 하면서 보이게 하도록 해보는 게 어떨까 해서 matrix.txt의 헥사 값을 이진수로 보도록 하였습니다.

[그림 2] matrix.txt 파일


이 파일은 matrix.txt에서 쓰여진 헥스값입니다. 이 값을 이진수로 바꿔보면 다음 [그림 3]과 같습니다.

[그림 3] 이진수로 바꾼 matrix.txt


이 값을 다시 흑백의 네모로 구분해보면, QR코드와 같은 모습을 볼 수 있습니다.

[그림 4]는 SecuMaster 회장의 노가다를 통해 탄생한 QR코드입니다.


[그림 4] 노가다를 통한 QR코드


하지만 [그림 4]와 같은 방법으로 QR코드로 만들어보았지만, 제대로 실행이 되지 않았습니다.

이 이유는 QR코드의 세 개의 큰 정사각형을 보면 살짝 튀어나온 부분이 있는 것을 볼 수 있습니다.


이는 SecuMaster 부회장이 발견한 힌트이며, QR코드에는 중복되는 코드가 있다는 것을 발견하였습니다.

중복된 부분은 [그림 5]와 같습니다.

[그림 5] 중복된 코드 부분


이를 삭제하고, python 코드를 통해 이미지를 만들게 되면, 다음과 같은 소스를 통해 QR코드를 작성할 수 있습니다.

from PIL import Image, ImageDraw
key ="""0000000000000000000000000000000 0111111101110001111111011111110 0100000101001000000000010000010 0101110101000001010000010111010 0101110101101000010010010111010 0101110101001010100000010111010 0100000100100001001100010000010 0111111101010101010101011111110 0000000001011000001011000000000 0010101101101111101110110111110 0011100001111110111100010011110 0111001101001011010000111010110 0101010000101100000011100010110 0001001110100001010101010010000 0100011001100100001101000101000 0101111111001011111110101110110 0010011011011001010110110101010 0001011101000011110101100111010 0010101001100010001100000001010 0010101100101001000000100000110 0101100000101010110011001011010 0111011101010011111101111111100 0000000001000000001011000110110 0111111100000001101101010101000 0100000101100101011111000111010 0101110100111011001001111111010 0101110101011110101011010101100 0101110100010000000101110100000 0100000101100010011001100101100 0111111100000010101001001010000 0000000000000000000000000000000"""
key = key.split(" ")
Image = Image.new("RGB", (32, 32), "white")
for a in range(0,31):
	for b in range(0,31):
             if(key[a][b]=="1"):
                     Image.putpixel((a,b),1)
             else:
                     pass
 
#Image.show()
Image.save("save.png")


PIL이라는 모듈을 따로 설치해야 하는 번거로움이 있지만, 위와 같은 소스를 통해 QR코드를 얻을 수 있습니다.

그리고 그 QR코드를 QR코드 리더기로 보면 [그림 6]과 같이 됩니다.


[그림 6] 문제 해결






[그림 1] 문제


문제를 요약하면 빨간 글씨로 된 해쉬 값을 통해 웹사이트를 들어가 Flag를 가져와 달라고 하는 것입니다.

admin, 그리고 빨간 글씨로 된 패스워드의 해쉬. 이 두 가지가 이 문제를 푸는 열쇠일 것 같습니다.

먼저 Hash를 풀어보기 위해 좋은 사이트로 들어갑시다.


해쉬 체크 및 인코드, 디코드 사이트 URL : https://md5hashing.net/

해쉬 : c7e83c01ed3ef54812673569b2d79c4e1f6554ffeb27706e98c067de9ab12d1a


해쉬 타입을 살펴보면 다음과 같이 나옵니다.

[그림 2] Hash Type Check


메뉴에서 Hash Type Check를 살펴보면 [그림 3]처럼 나오게 됩니다.

[그림 3] Hash Type Check Result


맨 위에서부터 확률이 높은 순입니다.

이 해쉬는 아마 SHA256(64Byte)일 것 같습니다.

그렇다면 이제 SHA256일 것이라는 추측으로 문제를 풀어보도록 합시다.


SHA256으로 디코딩 해보면, 다음과 같이 Vo83* 이라는 값이 나옵니다.

첫 번째로 했던 추측이 맞아 떨어진 걸까요?

[그림 4] 해쉬값을 SHA256으로 디코딩한 결과 값


이제 문제의 사이트로 들어가서 ID는 admin, PW는 Vo83*로 입력하여 인증을 해봅시다.

[그림 5] 인증 하기

[그림 6] 문제 해결


[그림 1] 문제


문제를 요약하면 corrupt.png라는 파일이 전송 도중 잘못되었다고 합니다. 이것을 고쳐주실 수 있는지에 대한 답을 요구하고 있습니다.

그렇다면 우리는 여기서 corrupt.png라는 파일이 어떻게 잘못되었는지 알아볼 필요가 있습니다.

혹시 IDAT 부분이 잘못되었는지, 헤더가 잘못되었는지 말이지요.


먼저 파일을 열어보려고 하는데 png 파일임에도 불구하고 이미지로 열리지 않는 것을 볼 수 있습니다.

이미지가 열리지 않는다는 것은, 윈도우 상에서 File Signature와 확장자가 맞지 않을 때 발생합니다.

파일 시그니처 참고 URL : http://forensic-proof.com/archives/300

먼저 헤더 부분을 비교해봅시다.


[그림 2] corrupt.png 헤더 부분


corrupt.png의 헤더 부분을 보면 16Byte 코드로 90 50 4E 47 0E 1A 0A 1B을 보면 마치 PNG파일 같이 보입니다.

원래 PNG 시그니처는 이렇습니다. ==> 89 50 4E 47 0D 0A 1A 0A

비교를 해보니 확실히 다르다는 걸 알 수 있습니다.


불량 : 90 50 4E 47 0E 1A 0A 1B

원래 : 89 50 4E 47 0D 0A 1A 0A


이제 헤더 부분을 바꿔주면 [그림 3]과 같이 나오게 됩니다.


[그림 3] 문제 해결


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

2016_IceCTF_Stage03_Matrix(85pt)  (0) 2016.09.07
2016_IceCTF_Stage02_Kitty(70pt)  (0) 2016.09.04
2016_IceCTF_Stage03_Audio(50pt)  (0) 2016.09.04
2016_IceCTF_Stage02_Miners(65pt)  (0) 2016.09.04
2016_IceCTF_Stage02_Demo(55pt)  (0) 2016.09.01
2016_IceCTF_Stage02_RSA(60pt)  (0) 2016.09.01
2016_IceCTF_Stage02_RSA?(50pt)  (0) 2016.08.26
2016_IceCTF_Stage02_Flag Storage(50pt)  (0) 2016.08.26

[그림 1] 문제


this audio signal을 입력하면 사운드 파일을 다운로드 받을 수 있습니다.

사운드 파일에는 Flag가 숨겨져 있다고 합니다.


먼저 재생을 해보면 딱히 음성으로 들리는 것 같지 않은 소리가 들릴 뿐 아무것도 일어나지 않았습니다.

또한 파일을 HxD로 열어본 결과 flag로 보이는 그 어떤 것도 보이지 않았습니다.

문제는 Forensics이기 때문에 스테가노 그래피는 아니라고 판단됩니다.


이 문제는 SecuMaster 회원 중 한 명의 도움을 받아 풀 수 있었습니다.

도움을 받은 회원의 블로그 URL : http://mer-bleu.tistory.com/

[그림 2] 문제 해결


문제의 답은 사운드 파일의 스팩트럼에 들어있었습니다.

음향 분석 및 에디터 툴 중 하나를 사용하여 TFFT 혹은 FFT를 확인해 보면 [그림 2]와 같은 Flag를 얻을 수 있습니다.

[그림 1] 문제


문제를 요약하면 miners.vuln.icec.tf 라는 곳에 들어가서 flag를 가져와야 하는데, DB에는 컬럼들이 하나도 없다도 합니다.

계정이 하나도 없다는 것은 ID, PW 등의 정보가 하나도 없다는 것이므로 컬럼이 없다고 볼 수 있습니다.


일반적으로 admin' or 1=1 -- 과 같은 방법으로 하면 Login Failed라는 문구와 함께 실패한 모습을 볼 수 있습니다.


[그림 2] php 소스


소스를 요약하면 쿼리문에서 username, password를 입력받아서 그것을 connect 할 곳(($con)에 보낸 후 응답하는 값 중 행의 숫자가 1이면 Flag를 뱉어내는 형식입니다.
그렇다면 우리는 어떻게 해서든 리턴되는 행의 수를 1개로 만들어야 합니다.

여기서 힌트는 컬럼이 하나도 없다는 것입니다.

소스를 분석하지 않고 바보같이 limit 방법으로 했다가 계속 풀리지 않았던 게 새록새록 떠오릅니다.

컬럼이 없다면 우리는 가짜 컬럼을 만들어줄 필요가 있습니다.

가짜로 컬럼을 만들기 위해서는 union으로 select문을 사용해야 합니다.

방법은 [그림 3]과 같습니다.

[그림 3] union과 select를 사용하여 가짜 리턴 컬럼을 만들어줌


' and 1=0, union select 1,2,3 #

과 같은 방법으로 했을 때, query에 들어가는 응답은 이렇게 됩니다.

SELECT *
FROM users
WHERE username='' and  1=0

union
SELECT
1,2,3 #' AND password=''

우리가 눈여겨 봐야 할 부분은 union 다음 부분부터 입니다.

먼저 username '' and 1=0 까지 하나의 select 문입니다.

그리고 union 다음의 select문은 그 다음의 select문이지요.


첫 번째 select문은 and 1=0이므로 무조건 아무것도 select하지 않게 됩니다.

두 번째 select문은 1,2,3을 리턴하고 ' AND pass...로 되어 있는 뒷 부분은 #으로 인해 주석처리가 됩니다.

즉, 1,2,3만 리턴하게 됩니다.


그렇게 하면 [그림 4]와 같이 풀이가 되는 것을 알 수 있습니다.

[그림 4] 문제 해결


문제가 해결됐음에도, 아직 찝찝한 기분입니다.

Miners는 동음이의어로 음을 표현하는 - 일 수 있고, 광부들이라는 표현도 있습니다.

SQL Injection이기 때문에 -- 주석이 더 생각납니다.

처음에는 %20-- 을 하면 주석인 줄 알고 아, 혹시 이 문제 잘못됐나...라고 생각했지만, 알고보니

%20--%20이 정확한 주석이었더군요.

그래서 [그림 5]와 같이 풀이를 할 수도 있습니다.

[그림 5] 또 다른 풀이


[그림 1] 문제


Demo 문제에서는 CTF 자체 서버에서 /home/demo라는 디렉토리에 shell이 있는데 그것을 크랙해줄 수 있냐고 말하고 있습니다.

그렇다면 shell로 들어가보도록 해야 겠습니다.

[그림 2] /home/demo에 들어 있는 파일들


demo 디렉토리에는 demo라는 실행파일, demo.c, flag.txt, Makefile이 쭈루룩 나열되어 있습니다.

다행히 others 권한 부분에 read권한이 demo.c에 있는 것으로 보아 cat 명령어로 볼 수 있을 것 같습니다.

demo.c를 살펴보도록 합시다.

[그림 3] demo.c 소스코드


main보다는 먼저 void 형태의 함수인 give_shell()이 눈에 띕니다.

give_shell() 함수는 딱 보니 /bin/sh을 주도록 하는 것 같습니다.

그리고 main에서는 env에서 '_'의 끝이 icesh이라면 give_shell이라는 함수를 실행한다고 합니다.

그렇다면 env를 통해 환경변수를 보도록 합시다.


[그림 4] env 명령어로 본 환경변수


환경변수 이름 중 _ 라고 되어 있는 부분을 살펴보면 /usr/bin/env입니다.

/usr/bin/env의 끝 부분이 env로 되어 있습니다. 그리고 strncmp이므로 6글자씩 비교(null문자 포함)이지만 basename이기 때문에 끝의 글자가 icesh이어야 제대로 비교가 될 수 있다는 것을 알 수 있습니다.

따라서 우리는 /usr/bin/env를 바꿀 방법을 찾아보도록 합시다.

환경변수 _는 우리가 사용한 명령어의 위치를 말해주는 것 같습니다.

즉, 프로그램을 실행시키면 env에 실행한 파일의 PWD가 들어가게 된다는 것입니다.

같은 방법으로 env명령어가 아닌 set 명령어로 실행해보고 이를 확인할 수 있었습니다.


[그림 5] set 명령어로 본 환경변수


set 명령어를 사용하니 _환경변수가 /usr/bin/env에서 set으로 바뀐 것을 확인할 수 있습니다.

그렇다면 만약 demo실행파일을 실행시켰을 때, 환경변수 _에는 /home/demo/demo가 들어갈 것입니다.

그럼 우리는 끝에 icesh을 붙이기 위해서는 심볼릭 링크로 접근하는 방법이 있습니다.


심볼릭 링크 만드는 방법은 다음과 같습니다.


ln -s [링킹할 파일 위치] [링크파일의 이름 및 위치]

ln -s /home/demo/demo ~/icesh


[그림 6]은 simbolic link에 대한 실험 내용입니다.

simbol.c의 소스는 다음과 같습니다.(사실 어떤 header 파일을 해야 할 지 몰라서.... 죄다 집어넣었습니다.)


//simbol.c 소스코드
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <libgen.h>
#include <string.h>
#include <stdio.h>

int main()
{
	printf("simpbolic ==> %s\n", getenv("_"));   
	return 0;
}

[그림 6] simbolic link 실험 모습


먼저 simbol.c 코딩하고 testest라는 심볼링 링크를 만들었습니다. 심볼링 링크는 [그림 6]과 같이 나타나있습니다.

getenv 함수를 통해 심볼링 링크로 실행했을 떄와 그냥 실행했을 때의 차이를 나타내보았습니다.

basename은 심볼링 링크가 뜨는 것을 확인할 수 있습니다.

그렇다면 이제 icesh이라는 심볼링 링크로 만들어 /home/demo/demo파일로 연결하도록 합시다.

[그림 7] icesh 심볼링 링크 생성


이제 icesh이라는 심볼링 링크를 실행하면 ~/icesh이 되며, 곧 basename이 icesh이 됩니다.


[그림 8] 문제 해결



[그림 1] 문제


문제에서 RSA에 대한 관리를 말하고 있는데, 어떠한 실수를 한 것 같다는 말을 합니다.

flag.txt를 보면 꽤 많은 내용의 값들이 나열되어 있는데 여기서 힌트는 correctly, ellipsis가 아닐까 합니다.

먼저 flag.txt를 살펴봅시다.

[그림 2] flag.txt


RSA? 문제와 마찬가지로 RSA를 이용한 암/복호화를 위한 재료가 작성되어 있는 것을 볼 수 있습니다.


N은 modulo 계산을 하기 위한(mod N) 값인 것 같습니다.

e는 공개키의 재료인 것 같습니다.( 공개키 ==> Public Key(e, N))

c는 Cipher Text의 c인 것 같습니다.

phi는 ∮(N)를 말합니다. ∮(N)은 (p-1)(q-1)을 의미합니다. 또한 N은 p*q를 의미합니다.

d는 복호화 키(개인키)를 의미하는 것 같습니다.(d는 Decrypt의 d인 것 같습니다.)


암호화 : c = m^e mod N

복호화 : m = c^d mod N


참고 URL : http://pulsebeat.tistory.com/56

참고 URL : http://reinliebe.tistory.com/79


RSA?와는 다르게 RSA는 개인키와 phi가 주어진 것으로 보아 다른 방향으로 접근해야 할 것 같습니다.

RSA?에서는 암호화를 하는 과정으로 풀이를 진행하였지만, 본 문제는 복호화가 이루어져야 할 것 같습니다.


N=0x1564aade6f1b9f169dcc94c9787411984cd3878bcd6236c5ce00b4aad6ca7cb0ca8a0334d9fe0726f8b057c4412cfbff75967a91a370a1c1bd185212d46b581676cf750c05bbd349d3586e78b33477a9254f6155576573911d2356931b98fe4fec387da3e9680053e95a4709934289dc0bc5cdc2aa97ce62a6ca6ba25fca6ae38c0b9b55c16be0982b596ef929b7c71da3783c1f20557e4803de7d2a91b5a6e85df64249f48b4cf32aec01c12d3e88e014579982ecd046042af370045f09678c9029f8fc38ebaea564c29115e19c7030f245ebb2130cbf9dc1c340e2cf17a625376ca52ad8163cfb2e33b6ecaf55353bc1ff19f8f4dc7551dc5ba36235af9758b

e=0x10001

phi=0x1564aade6f1b9f169dcc94c9787411984cd3878bcd6236c5ce00b4aad6ca7cb0ca8a0334d9fe0726f8b057c4412cfbff75967a91a370a1c1bd185212d46b581676cf750c05bbd349d3586e78b33477a9254f6155576573911d2356931b98fe4fec387da3e9680053e95a4709934289dc0bc5cdc2aa97ce62a6ca6ba25fca6ae366e86eed95d330ffad22705d24e20f9806ce501dda9768d860c8da465370fc70757227e729b9171b9402ead8275bf55d42000d51e16133fec3ba7393b1ced5024ab3e86b79b95ad061828861ebb71d35309559a179c6be8697f8a4f314c9e94c37cbbb46cef5879131958333897532fea4c4ecd24234d4260f54c4e37cb2db1a0

d=0x12314d6d6327261ee18a7c6ce8562c304c05069bc8c8e0b34e0023a3b48cf5849278d3493aa86004b02fa6336b098a3330180b9b9655cdf927896b22402a18fae186828efac14368e0a5af2c4d992cb956d52e7c9899d9b16a0a07318aa28c8202ebf74c50ccf49a6733327dde111393611f915f1e1b82933a2ba164aff93ef4ab2ab64aacc2b0447d437032858f089bcc0ddeebc45c45f8dc357209a423cd49055752bfae278c93134777d6e181be22d4619ef226abb6bfcc4adec696cac131f5bd10c574fa3f543dd7f78aee1d0665992f28cdbcf55a48b32beb7a1c0fa8a9fc38f0c5c271e21b83031653d96d25348f8237b28642ceb69f0b0374413308481

c=0x126c24e146ae36d203bef21fcd88fdeefff50375434f64052c5473ed2d5d2e7ac376707d76601840c6aa9af27df6845733b9e53982a8f8119c455c9c3d5df1488721194a8392b8a97ce6e783e4ca3b715918041465bb2132a1d22f5ae29dd2526093aa505fcb689d8df5780fa1748ea4d632caed82ca923758eb60c3947d2261c17f3a19d276c2054b6bf87dcd0c46acf79bff2947e1294a6131a7d8c786bed4a1c0b92a4dd457e54df577fb625ee394ea92b992a2c22e3603bf4568b53cceb451e5daca52c4e7bea7f20dd9075ccfd0af97f931c0703ba8d1a7e00bb010437bb4397ae802750875ae19297a7d8e1a0a367a2d6d9dd03a47d404b36d7defe8469

plainText = hex(pow(c,d,N))
plainText = plainText.replace('L', '')
plainText = plainText.replace('0x', '')

plainText = plainText.decode('hex')

print plainText


RSA?와는 다르게 c^d mod N으로 진행하였습니다. d는 개인키로, 본 소스는 복호화 키를 사용하여 복호화 하는 과정을 나타낸 것입니다.


이를 실행하면 [그림 3]과 같습니다.


[그림 3] 문제 해결

[그림 1] 문제


문제에서도 볼 수 있듯이 RSA라는 것을 노골적으로 말하고 있습니다.

묻지도 따지지도 말고 flag.txt를 다운받아 봅시다.

[그림 2] flag.txt


RSA를 이용한 암/복호화를 위한 재료가 작성되어 있는 것을 볼 수 있습니다.

N은 modulo 계산을 하기 위한(mod N) 값인 것 같습니다.

e는 공개키의 재료인 것 같습니다.( 공개키 ==> Public Key(e,N))

c는 Cipher Text의 c인 것 같습니다.


RSA의 암호화, 복호화에 대한 공식은 다음과 같습니다.


암호화 : c = m^e mod N

복호화 : m = c^d mod N(d는 Private Key의 d이고, Decrypt의 d를 가져온 것 같습니다.)


참고 URL : http://pulsebeat.tistory.com/56

참고 URL : http://reinliebe.tistory.com/79


자 그럼 이제 암호화, 복호화 과정을 알았으니, Python으로 코드를 작성해보도록 합시다.

N=0x180be86dc898a3c3a710e52b31de460f8f350610bf63e6b2203c08fddad44601d96eb454a34dab7684589bc32b19eb27cffff8c07179e349ddb62898ae896f8c681796052ae1598bd41f35491175c9b60ae2260d0d4ebac05b4b6f2677a7609c2fe6194fe7b63841cec632e3a2f55d0cb09df08eacea34394ad473577dea5131552b0b30efac31c59087bfe603d2b13bed7d14967bfd489157aa01b14b4e1bd08d9b92ec0c319aeb8fedd535c56770aac95247d116d59cae2f99c3b51f43093fd39c10f93830c1ece75ee37e5fcdc5b174052eccadcadeda2f1b3a4a87184041d5c1a6a0b2eeaa3c3a1227bc27e130e67ac397b375ffe7c873e9b1c649812edcd

e=0x1

c=0x4963654354467b66616c6c735f61706172745f736f5f656173696c795f616e645f7265617373656d626c65645f736f5f63727564656c797d


plainText = hex(pow(c,e,N))
plainText = plainText.replace('L', '')
plainText = plainText.replace('0x', '')

plainText = plainText.decode('hex')

print plainText

# if the decode('hex') doesn't work.. it's because of worng hex code that cannot express in hex or ascii. so we have to check that hex value can express or not


동아리 원의 도움을 받아 pow 함수를 사용하는 커다란 팁을 이용하여 소스를 만들어보았습니다.

pow함수를 이용하여 c,e,N을 RSA 암호화에 맞도록 해보았습니다.

powe(c,e,N)이 의미하는 것은 c^e mod N이라는 것을 의미합니다.

그리고 그 아래의 부가적인 소스는 string 형식으로 이쁘게 출력하기 위한 부수적인 작업입니다.


이를 실행하면 [그림 3]과 같습니다.

[그림 3] 문제 해결




[그림 1] 문제


문제의 힌트는 [그림 1]에서 this를 클릭하면 SQL Injection이라는 것을 알려줍니다.

두근두근 SQL Injection으로 한 번 해보도록 합시다. 웹사이트로 들어가봅니다.

[그림 2] 웹사이트로 들어가본 모습


웹사이트에서 Username, Password를 물어보는 로그인 창이 나왔습니다.

이 외의 다른 힌트는 없는 것 같으니, 일단 SQL Injection으로 문제를 풀어보라고 하는 것 같습니다.


먼저 admin, 1234를 각각 입력하여 로그인을 시도해보았습니다.

Login Failed라는 메세지가 나오고 다른 말은 나오지 않았습니다.

그렇다면 admin' or '1'='1 과 같은 기본적인 SQL Injection을 시도해보도록 하였습니다.


[그림 3] 문제 해결


나닛..!???@?@!@?!?

+ Recent posts