Hotel Codeifornia

TCPサーバの接続情報、サーバのプログラム(ELFファイル)hotel_codeifornia、テキストファイルpubkey.pemが与えられた。
hotel_codeiforniaGhidraで逆コンパイルすると、以下のmain関数があった。

Information to connect to a TCP server, a server program (ELF file) hotel_codeifornia and a text file pubkey.pem were given.
Decompiling hotel_codeifornia via Ghidra, I found this function main:

main.c

main関数は、codeとsignを入力させた後、入力データを以下のverify_sig関数でチェックし、
チェックを通ればpython -c '(入力したcode)'を実行するようになっていた。

The main function firstly asks to input "code" and "sign". Then, check the input via the following function verify_sig.
Finally, it executes python -c '(the "code" entered)' if the input passes the check.

verify_sig.c

verify_sig関数は、「signをe乗してnで割った余りを__gmpz_export関数で変換したもの」と 「codeのSHA-256ハッシュ値」をstrncmp関数で比較し、一致と判定されればOKとみなすという処理をしていた。
eとnの値はpubkey.pemから読み込んでいた。

pubkey.pemにはBase64エンコードされたデータが書かれていた。
この部分をCyberChefに貼り付け、以下の処理を行うと、2個のINTEGERが得られた。
大きい方のINTEGERがn、小さい方のINTEGERがeであると仮定した。

The function verify_sig compares "sign to e-th power modulo n, converted via a function __gmpz_export" and "the SHA-256 hash value of code" via the function strncmp and judge as passed when the comparision results in equal.
The values of e and n were read from pubkey.pem.

The file pubkey.pem had a Base64-encoded data.
I obtained two INTEGERs by pasting the data to CyberChef and applying the following recipe.
I assumed that the large INTEGER is n and the small INTEGER is e.

From Base64, To Hex, Parse ASN.1 hex string - CyberChef

strncmp関数は0x00のバイトまでしか比較しないので、 余りの変換結果とSHA-256ハッシュそれぞれについて2バイト目が0x00となり、1バイト目が一致するcodeとsignを探せばよさそうである。
まず、変換方法が明らかではないが、上位のバイトほど先に来ると仮定した以下のプログラムで余りが条件を満たすsignを探した。

The function strcmp only compare data until 0x00 byte. Therefore, it should be useful to search for "sign" and "code" such that the second bytes of the converted remainder and the SHA-256 hash value are 0x00 and the first bytes are equal.
Firstly, I searched for a satisfying "sign" via this program. (How the remainder is converted is not obvious, but I assumed that the highest byte comes first.)

search_sign.py

この結果を用い、以下のプログラムで条件を満たすcodeを探した。

Using the result, I searched for a satisfying "code" via this program:

search_code.pl

結果、codeに';/bin/sh;'\Y#、signにadを入力するとシェルを起動できることがわかった。 (signは16進数で入力することに注意する)

lsコマンドを用いるとファイルflag.txtがあることがわかり、 cat flag.txtコマンドを実行するとflagが出力された。

As a result, I found that entering ';/bin/sh;'\Y# as "code" and ad as "sign" launches the shell. (note that "sign" should be entered in hexadecimal)

I found that a file flag.txt exists via the ls command. Executing a command cat flag.txt resulted in the flag printed.

ractf{W3lComE_t0_Th3_LA_B3d_n_br3Akfast}

RACTF 2021