以下のファイルが与えられた。
These files were given:
distributed_files/headless_horseman
をmain
関数から以下の関数が呼び出されていることがわかった。
print_intro
:メッセージを出力する。offer_pumpkins
:scanf
関数の書式%d
で整数を読み込む。count_offering
:読み込んだ整数をfirst_count
関数およびsecond_count
関数でチェックし、両方のチェックに通過したらdump_heads
関数を呼び出す。
first_count
関数は、入力の上位16ビットが 0xdead
かをチェックしている。
second_count
関数は、入力の下位16ビットが 0xface
かをチェックしている。
(second_count
関数は逆コンパイル結果では入力全体をチェックしているように見えるが、アセンブリコードを見ると下位16ビットしか見ていないことがわかる)
合わせると、0xdeadface
、すなわち -559023410
を入力すればいいことがわかる。
distributed_files/headless_horseman
を-559023410
を入力すると、以下の6個のファイルが出力された。
Decompiling distributed_files/headless_horseman
using main
calling these functions:
print_intro
: Print some messages.offer_pumpkins
: Read an integer using the function scanf
with the format specifier %d
.count_offering
: Check the integer read by functions first_count
and second_count
, and call the function dump_heads
if the input passes both checks.
The function first_count
checks if the upper 16 bits of the input is 0xdead
.
The function second_count
checks if the lower 16 bits of the input is 0xface
.
(The function second_count
looks as if it is checking the whole input, but reading the assembly code reveals that it is checking only the lower 16 bits.)
Combining these, the value to input is 0xdeadface
, which means -559023410
.
I executed distributed_files/headless_horseman
on -559023410
.
As a result, it produced these 6 files:
dessicated_head
fetid_head
moldy_head
putrid_head
shrunken_head
swollen_head
各ファイルの内容を確認すると、それぞれELFヘッダーのようだった。
そこで、これらのファイルを distributed_files/body_bag
ディレクトリ内のファイルと総当りで合体させる以下のプログラムを作成し、実行した。
Checking the contents of each files, they looked ELF headers.
I created this program to concatenate the files with the files in the directory distributed_files/body_bag
using all combinations, and executed that.
できたファイル群を readelf -lS
でチェックすると、以下の3個のファイルのみエラーが出なかった。
I checked the resulting files using the command readelf -lS
. As a result, these 3 files didn't produce any errors while the other files did:
dessicated_head_decomposing_body
moldy_head_bloated_body
shrunken_head_rotting_body
そこで、これらのファイルをGhidraで逆コンパイルした。
dessicated_head_decomposing_body
では、main
関数からkatrina
関数が呼ばれていた。
katrina
関数では、メッセージを出力した後文字列を読み込み、それをencrpyted_words
(21 09 04 09 1C 00 7F 24 00 1A 09 1C 28 00 00
) とxorして出力していた。
ここで出力されるメッセージの中に、以下の部分があった。
Seeing this, I decompiled these files using Ghidra.
In the file dessicated_head_decomposing_body
, the function main
calls the function katrina
.
The function katrina
prints some messages, reads a string, and print the string with exclusive-ored with encrpyted_words
(21 09 04 09 1C 00 7F 24 00 1A 09 1C 28 00 00
).
The message printed here contained this part:
'Drat! it looks like I encrypted my portion but I cant seem to remember what I used!'
'can you help me out? I was never very creative with these things, maybe try the street I grew up on? or my Home Town?'
distributed_files/README.txt
を読むと、「the village of Sleepy Hollow」についてのお話が書かれていた。
そこで、Sleepy Hollow
とのXORをとった。
Reading distributed_files/README.txt
, I found a story about "the village of Sleepy Hollow".
Seeing this, I calculated XOR with Sleepy Hollow
on
結果は really_loves_
となった。
moldy_head_bloated_body
では、main
関数からichabod
関数が呼ばれていた。
ichabod
関数では、check_surroundings
関数を呼び出し、その返り値が0ならprint_incantation
関数を呼び出していた。
print_incantation
関数では、"ZmxhZ3t0aGVfaG9yc2VtYW5fanVzdF8="
をb_decode
関数に渡した結果を出力していた。
そこで、このデータにCyberChefの From Base64 を適用してみた。
The result was really_loves_
.
In the file moldy_head_bloated_body
, the function main
calls the function ichabod
.
The function ichabod
calls the function check_surroundings
, and when its return values is 0, it calls the function print_incantation
.
The function print_incantation
prints the result of the function b_decode
with "ZmxhZ3t0aGVfaG9yc2VtYW5fanVzdF8="
passed as an argument.
Seeing this, I tried applying "From Base64" to the data on CyberChef.
結果は flag{the_horseman_just_
となった。
shrunken_head_rotting_body
では、main
関数からbrom
関数が呼ばれていた。
brom
関数は、local_10
の値が指定のものだったらprint_flag
関数を呼ぶ処理をしていた。
print_flag
関数では、letters
、to_replace
、buff
の値を用いて何かを出力していた。
そこで、print_flag
関数の処理を再現する以下のプログラムを書き、実行した。
The result was flag{the_horseman_just_
.
In the file shrunken_head_rotting_body
, the function main
calls the function brom
.
The function brom
calls the function print_flag
if the value of local_10
is what is expected.
The function print_flag
prints something based on the values of letters
, to_replace
, and buff
.
Seeing this, I created this program to mimic what is done in the function print_flag
, and executed that.
結果は pumpkin_pie}
となった。
これらの3個のファイルの解析結果を繋げることで、flagが得られた。
The result was pumpkin_pie}
.
I obtained the flag by concatenating what are obtained from these 3 files.