단순 xor 역연산이다. 알고 있는 값들을 토대로 하나씩 xor 역연산 해가면서 찾아나아가면 된다. 참고로 S[0] = "LINECTF{" 임을 알고 있으면 된다.
X Factor
rsa blind signature attack 같은 느낌인데 sign을 해주는 기능을 제공해주지는 않는다. 대신 plain -> signature pair들을 제공해주기 때문에 이 값들을 sign함수 대신 사용하는 느낌으로 가야된다. 0x686178656c696f6e 값의 signature를 구하는 문제이다.
문제 제목이 힌트라고 볼 수 있는데, 각 plain 값들을 소인수분해한다. 이는 factordb 사이트를 이용하면 된다. a ~ g의 값들을 사용하여 Z를 만들어내려면 ( f * b * g * d * g * d ) / ( c * e * a ) 가 된다.
plain a ~ g, Z의 signature 값을 Sa ~ Sg, SZ 라고 하면, 위 사진의 식에서 M=Z = ( f * b * g * d * g * d ) / ( c * e * a ) , r= Sc * Se * Sa r^e mod N = c * e * a 이므로 M' = ( f * b * g * d * g * d ) / ( c * e * a ) * (c * e * a) mod N = ( f * b * g * d * g * d )
S' = M'^d mod N = ( f * b * g * d * g * d )^d mod N = ( Sf * Sb * Sg * Sd * Sg * Sd ) mod N
우리가 원하는 S = S'/r mod N = ( ( Sf * Sb * Sg * Sd * Sg * Sd ) / ( Sc * Se * Sa ) ) mod N 이다.
https://ohgym.tistory.com/13, 모듈로 나눗셈 성질
( Sc * Se * Sa ) 의 역원을 구해야 한다.
https://ohgym.tistory.com/13
( Sc * Se * Sa ) 와 N 은 서로소이므로 확장된 유클리드 호제법을 사용하여 역원 x를 구한다.
처음에 크립토 잡고 풀다가 하루 다 보내버리고 뒤늦게 웹에 합류하여 문제를 풀었다. 좀 더 빨리 웹을 잡고 풀었으면 좀 더 점수를 낼 수 있었을 텐데 아쉬웠다. 그리고 예선전은 인원 제한이 없는걸 몰랐어서 처음엔 4명 모아서 할려고 했다가 대회 시작 직전에 뒤늦게 사람 2명밖에 못 데려온 것도 좀 아쉬었다. 내년에는 소학회원들 많이 데리고 하면 좋을 거 같다.
코게에도 포렌식이나 네트워크 문제 나왔으면 좋겠다. 예전엔 그래도 한 두개씩 나왔던거 같은데..
WEB - superbee
golang으로 작성되어 있고
beego 라는 프레임워크를 사용하고 있다.
플래그는 app.conf에 정의되어 있고 (물론 주어진 파일에서는 REDEACTED)
main.go
http://[IP]/main/index 경로로 접속하면 flag를 확인할 수 있도록 되어 있지만
main.go
쿠키값을 비교하여 admin이 아니면 플래그를 확인할 수 없고, login 페이지로 redirect된다.
먼저 어드민 패스워드를 획득하여 어드민계정으로 로그인 하는 방법은
패스워드를 알아낼 방법이 없으므로 불가능하고
SSTI일까 생각해봤지만,
main.go
사용자가 입력한 값으로 render하는 곳이 없고, 애초에 beego에서는 값을 직접 때려주기 때문에 불가능하다.
어떻게 풀어야 될까 생각을 해보다가
main.go
/admin/authkey 페이지로 접근해서 encrypted_auth_key를 얻고
aes 복호화를 해서 평문 auth_key를 얻어서 sess 쿠키 값을 설정해서 main/index로 접근하여 flag를 얻는 루트같았다.
main.go
그러지 않고서야 aesencrypt함수를 넣어두고 admin페이지를 만들어둘 이유가 없다고 생각했다.
main.go
그런데 admin/authkey에 접근할려면 domain이 localhost가 되어야 한다.
아니 ssrf때릴 곳도 없는거 같은데 어떻게 domain명을 localhost로 만들지 고민을 하다가
Ctx.Input.Domain()이 사실 처음 보는 함수였기 때문에 정확히 어떻게 동작하는 지 알 필요가 있었다.
아주대 사이버보안학과의 날을 맞아 11월 27일 토요일 12:00 부터 23:59까지 12시간동안 후이즈 & 해머 CTF가 개최되었다.
난 포렌식 5문제와 미스크 한 문제를 출제 및 대회 운영 및 관리를 담당하였다.
문제를 제작할 때 항상 참신하고 재밌는 문제를 만들려고는 하는데 쉽지가 않다. 요즘 학교 과제하느라 CTF도 열심히 안하고 포렌식 공부도 거의 안해서 머리 속에 새로운 지식이 없다. 정체된 상황에 올해 대회 문제출제를 두 번 하면서 아이디어가 거의 바닥나 버렸다. 여기서 문제를 더 뽑아내려고 하다보니 문제 퀄리티가 개인적으로 아쉽다.
앞으로도 문제 출제하려면 공부해야겠다..
Official Write up
원래 출제자 롸업 안썼는데 이번 대회에서는 문제풀이 세미나가 없어서 작성하게 됐다.
문제만들면서 플래그 값 설정하는 것도 하나의 재미라고 느끼는데, 이번에는 그냥 문제명이랑 소금 섞어서 md5 해시값을 플래그 값으로 설정했다. 밀린 과제하면서 문제 만들려다보니 시간을 조금이라도 줄이려..
문제 난이도는 사보 학생들만 참여하고 대회 시간이 12시간으로 짧은 것을 고려하여 전체적으로 쉽지만 다양하게 (스테가노, 멀티미디어, 네트워크, 메모리, 디스크) 출제했다.
Forensic
사보의 기묘한 모험 - 436 points, 7 solvers
Whois&HaMer.png 이미지 파일 하나가 주어진다.
HxD
해당 파일을 헥스 에디터로 열어서 보면, PNG 푸터 시그니쳐 뒤에 데이터가 존재함을 알 수 있다.
binwalk 명령어를 사용하면 PNG + ZIP + PNG 구조로 이루어진 것을 확인할 수 있다.
가운데 ZIP 파일 영역을 따로 추출(헥스에디터로 직접 뽑아내기, Winhex 기능 사용하기,foremost 사용하기, 다양하다)해서 압축을 풀면 flag.7z 파일이 있으며
flag.7z 파일의 압축을 풀면 flag.txt를 얻을 수 있다.
flag.txt의 내용을 base64 디코딩하면 플래그를 획득할 수 있다.
ASCTF{5B75794CE6A122D57EDAABFE80CD09F1}
그날 본 사진의 크기를 우리는 아직 모른다. - 484 points, 4 solvers
i_found.png 이미지 파일 하나가 주어진다. 이미지 뷰어로 열어보면 아무것도 보이지 않는다.
왜냐하면 사진 크기가 1 * 1로 설정되어 있기 때문이다.
그런데 사진 크기가 1 * 1 가 정상일리 없다.
tweakpng.exe로 열어보면 IHDR 청크의 CRC값이 올바르지 않다고 한다.
따라서 사진의 크기 값이 강제로 수정되었으며, 올바른 크기값을 찾아야한다는 것을 알 수 있다.
$ apt-get install dwarfdump
$ apt-get install build-essential
$ cd volatility/tools/linux
$ make
$ head module.dwarf (module.dwarf 파일이 생성되었는지 확인)
$ sudo zip volatility/volatility/plugins/overlays/linux/Ubuntu1204.zip volatility/tools/linux/module.dwarf /boot/System.map-5.4.0-24-generic
vol.py --info에서 프로필에서 확인 가능하면 성공
분석할 준비가 끝났다.
linux_bash
linux_bash 플러그인을 사용해보면 터미널에 입력한 내용을 확인할 수 있는데,
asctf라는 파일을 실행한 것을 확인할 수 있으며
linux_pslist
pslist로도 pid 2743에서 확인할 수 있다.
asctf 파일을 추출하는 방법은 여기서는 두가지가 있는데, linux_dump_map을 사용하는 것과 linux_find_file을 사용하는 것이다.
linux_dump_map을 사용하기 위해서 먼저 linux_proc_maps를 통해 start 주소값을 얻어서
linux_dump_map으로 추출할 수 있다.
linux_find_file 을 사용하기 위해서는 정확한 파일 경로를 알아야 한다. 윈도우의 filescan이 있었으면 좋겠지만..
다시 linux_bash화면으로 돌아가보면, 앞에 cd .. cd home cd mandu를 통해 현재 디렉토리 위치가 /home/mandu/ 임을 확인할 수 있다.
따라서 asctf라는 파일은 /home/mandu/asctf 에 위치함을 알 수 있다.
Inode 값을 획득할 수 있고 이 값을 사용해서 다시 linux_find_file을 사용하면 파일을 추출할 수 있다,
이렇게 추출한 asctf파일을 실행해주면 base64 문자열을 획득할 수 있으며 실행결과에 나와있듯이 base64 디코딩 2번 시도해주면 플래그를 얻을 수 있다.
ASCTF{5818F673E8A6EA7BE5524722407090D5_2743}
헥스에디터로 열어서 ASCTF 검색하면 바로 찾을 수 있다.
('ASCTF{' 랑 flag 검색하는거는 막았지만 ASCTF는 못 막았다..)
문제 다시 만들기엔 시간이 없어서 pid값을 플래그에 추가해서 인증하는 것으로 수정했다.
(플래그를 출력하는 프로세스의 pid를 찾으라는 내용이 문제 풀이 방향에 힌트를 주는 것 같지만.. 언인텐으로 간단히 풀리는 것 보단 낫다.)
[대회 종료 후] 예상대로 출력하는 플래그는 많이들 찾으셨지만 pid값은 제대로 찾지 못하셨다.
그런데 문제가 대회 종료 30분 전까지 안풀렸고, 볼라티리티로 잘 안된다는 문의까지 들어와서 파일 잘 못 올라갔나 하고 식은땀 줄줄 흘리며 체크섬 확인했다. (문제 만들때 삽질을 많이해서 다른 버전의 파일이 올라갔을 가능성이 1%정도 있었다.) 다행히 파일은 풀리는걸로 제대로 올라갔었다.
다운로드 폴더에서는 dream.zip파일을 찾을 수 있으며 그 안에는 아주 수상해보이는 ps1파일, bat 파일을 찾을 수 있다.
(롸업 쓰면서 든 생각인데, zip 파일에 암호 걸어서 패스워드를 웹상의 파일 다운로드 경로에 같이 둬서 크롬 방문 기록을 반드시 확인하게 할 걸 그랬다.)
readme.txt
readme에서는 dream_installer.bat를 실행하라고 한다.
dream_installer.bat
dream_installer.bat 은 파워쉘로 dream.ps1을 실행한다.
dream.ps1
dream.ps1은 http://35.212.225.5/asctf/hello.pyc 를 임시폴더에 다운받아와 실행한다.
임시폴더에서 hello.pyc를 찾을 수 있다.
hello.pyc는 uncompyle6로 디컴파일 할 수 있다.
간단하다. 단순 xor이다.
important.enc = important.hwp xor key 이므로 바탕화면에서 찾았던 important.enc를 important.hwp로 이름을 바꾼뒤에 hello.pyc를 실행하면 복호화된 important.enc를 얻을 수 있으며 다시 이름을 .hwp로 바꿔서 열어주면 플래그를 획득할 수 있다.
ASCTF{E95312D231A4784B78E631FD91468DBB}
Misc & Crypto
사보 스파이 - 493 points, 3 solvers
에니그마랑 난수방송 합친 문제
책상 1 폴더에서 에니그마 모델명을 확인할 수 있으며 '글자가 적혀있는 종이.pdf'에서 암호문을 얻을 수 있다.