ctftime에 올라온 대회들 중에서 처음 참가해보는 대회입니다.
팀 이름은 동아리 이름인 Secumaster 이지만 정작 참가한건 저 혼자네요.
2번째 암호학 문제만 풀었으면 2위를 기록할수 있었는데, 아쉽게도 대회가 끝나고나서야 풀이법을 떠올려버렸습니다...
2위를 못해서 Offsec 강의를 못받는건 아쉽긴 해도 수상권인 3위에 들어간것에 만족합니다.
문제 리스트
misc
- con-string-cat
- list-dir-list
- locked-out
pwn
- i-hate-garbages
- sos
rev
- iron
- Formless
web
- inspect
crypto
- Pixelite
- funwithrandom-1
con-string-cat
이 문제는 파이썬의 포맷스트링 에 대한 취약점을 찾는것이 목표입니다.
저는 offset은 23을 입력하고 ".__init__.__globals__" 를 입력해서 {param.__init__.__globals__} 를 완성시켜서 프로그램의 글로벌값을 유출시킨뒤 플래그값을 얻었습니다.
list-dir-list
import random
key = open('key.txt').read()
random.seed(2023)
enc_key = ""
for j in range(8):
i = 0
lst = []
while i < len(key):
lst.append(key[i+j])
i += 8
random.shuffle(lst)
for c in lst:
enc_key += c
print("this may be helpful:")
print(enc_key)
blacklist = [
"import",
"os",
"sys",
"ls",
"cat",
"la",
"flag",
"tac",
"key",
]
strictly_prohibited = [
"apt",
"install",
"cd",
"builtins",
"subprocess",
"exec",
"eval",
"input",
"blacklist",
"strictly_prohibited",
"echo",
"grep",
"find",
"pickle",
"key",
"write"
]
while True:
cmd = input(">>> ")
evl_cmd = eval(cmd)
can_run = True
for word in strictly_prohibited:
if word in evl_cmd.lower():
can_run = False
break
if can_run:
if evl_cmd[0:len(key)] == key:
exec(evl_cmd[len(key):])
else:
for word in blacklist:
if word in evl_cmd.lower():
can_run = False
break
if can_run:
exec(evl_cmd)
이 문제는 파이썬의 eval 함수를 이용해서 해당 프로그램이 돌아가고있는 서버에 원하는 명령을 수행하는것이 목적입니다.
소스를 분석해보면 키값을 암호화한뒤 서버에서 출력하는데 이 암호화 값을 복호화해서 키값과 함께 원하는 명령을 사용하면 필터링을 거치지 않고 해당 시스템에 원하는 명령을 내릴수 있으므로 저는 이 방법으로 쉘을 따서 플래그를 얻었습니다.
locked-out
해당 사이트에 들어가면 그냥 nginx 초기화면만 있어서 당황했는데 conf파일을 분석해보니 /app 경로가 시작경로인것 같으므로 이 사이트에서부터 시작했습니다.
그런데 이 사이트에 들어가보면 랜덤한 텍스트를 출력하는 기능만 있습니다.
주어진 js파일을 분석해보면 이 기능을 만드는 소스는 secret.js라는 파일에 있는거 같은데
이것을 어떻게 유출 시킬지 찾아보니, nginx 설정에 의한 파일탐색 취약점이 존재한다는것을 알게됐습니다.
마침 이 웹서버의 설정을 보니 파일경로 설정에 취약점이 보여서, /appsrc/secret.js 라는 경로로 접근하는것을 성공했습니다.
이 소스를 분석한뒤 랜덤 텍스트에 특정 패턴이 있다는것을 알게되고, 이 분석을 기반으로 익스코드를 짰습니다.
output4.bin은 4가지의 텍스트 중에서 랜덤화 키값이 4인 텍스트입니다.
i-hate-garbages
이 문제는 평범한 ROP 문제로 보이지만 생각보다 복잡합니다.
버퍼를 지정된 크기인 64바이트가 아닌 80바이트까지 xor연산을 수행한다는 점에서
ROP를 방해할려는 로직이 추가된것으로 보이고, 이것을 해결하더라도 플래그값을 가져올때 사용하는 함수인
fopen 함수가 rsp레지스터 값이 16바이트로 정렬되어있지 않으면 내부에서 segmentation fault를 발생시키는것 때문에
ret가젯을 추가하고, 또 이 ret가젯을 추가한것에 대한 사이즈를 고려해서 이 ret가젯을 xor연산시키고 win함수의 주소는 xor 시키지 않는 방식으로 익스코드를 구상했습니다.
sos
이 문제는 바이너리에서 제공하는 기능 자체가 굉장히 제한적인 제가 공부해보지 못한 유형이라서 상당히 애먹었는데, 알고보니 SROP 라는 기법을 사용해야 풀수있는 문제였습니다.
심지어 이 문제에서는 pop rax 가젯이 없어서 rax를 조작할 방법을 찾아야 하는데
저는 바이너리 파일에 흩어져 있는 비트연산 가젯들을 활용하여 rax를 조작한뒤 sigreturn 을 호출하는 방식으로 execve를 사용해서 쉘을 따냈습니다.
iron
이번 문제는 Rust로 작성된 프로그램을 리버싱하는거라 상당히 분석하기 어려웠습니다.
하지만 c++과 비슷한 구조로 되어있어서 어찌저찌 플래그 로직을 발견한뒤 분석해서 플래그를 얻었습니다.
Formless
이 문제는 약간의 페이크가 있는 문제였습니다.
처음 나오는 플래그 생성 로직을 그대로 분석해서 플래그를 만들어보면 페이크 플래그가 나옵니다.
그래서 더 분석해본 결과, 처음 init 로직에서 플래그 생성에 사용되는 값이 변조되는것을 확인했고
이것을 기반으로 메모리를 직접 패치하면서 분석해서 플래그를 얻었습니다.
inspect
이번 문제는 웹 문제입니다. 문제 설명에서 rest api를 사용하지 않고 웹사이트를 만들었다고 하는데
rest api와 대조되는 다른것을 찾아보니 GraphQL 이라는것을 찾았습니다.
이 문제에서 주어진 웹사이트는 그냥 들어가지지 않고 /graphql 이라는 경로를 붙이면 이 웹사이트의 데이터베이스를 검색할수있는 사이트에 접속할수 있습니다.
저는 각종 쿼리로 이 웹사이트의 DB를 검색해보다가 다음과 같은 쿼리를 사용해서 플래그값을 찾았습니다.
하지만 페이크 플래그들이 너무 많아서 하나하나 찾느라 시간이 꽤나 많이 걸렸습니다.
플래그를 계속 찾다가 하도 안나와서 이게 페이크인줄 알았지만, 계속 찾다보니 유의미한 플래그가 보여서 이 플래그를 입력해보니 정답 이였습니다.
Pixelite
이 문제는 플래그 이미지를 시간대를 시드로 사용하는 랜덤값으로 xor 연산하여 다시 이미지로 저장한것을 복호화 하는 문제 입니다. 단순히 이것만 주어졌다면 푸는것은 사실상 불가능하지만, 다행히도 이 이미지가 만들어졌을 당시의 시간값이 주어졌기 때문에 이를 기반으로 복호화 코드를 짜면 손쉽게 플래그를 얻을수 있습니다.
funwithrandom-1
저는 이 문제를 대회가 끝날때까지 못풀었습니다.
다행히 대회가 끝난뒤에 다른분이 롸업을 올려주셔서 그걸 기반으로 풀어봤습니다.
이 문제에서는 특정 랜덤 함수를 분석해서 다음 랜덤값을 예측하는것이 목표인데, 이걸 푼분은 코드에 보이는 언탬퍼링 이라는 작업을 거치면 서버에서 주어진 값을 가지고 그값이 시프트 연산이 되기전의 값을 도출해낼수 있다고 합니다.
이 방법의 원리는 천천히 다시 보면서 이해를 해야할것 같습니다. 암튼 이방법으로 그 전의 값을 알아내고 값을 다시 연산해서 랜덤함수를 공략할수 있습니다.
'CTF' 카테고리의 다른 글
2023 TAMUctf write-up (0) | 2023.05.15 |
---|---|
[2023 root access CTF] write-up (3) | 2023.05.02 |
2022 Hacking Land CTF write-up (0) | 2022.08.01 |
[Reversing] Baby_Keylogger (0) | 2022.07.09 |
[Forensic] Baby_RSA writeup (0) | 2022.05.11 |