Neurotic

プログラム src.py と、ファイル model.pth が与えられた。
src.py は、以下の処理をするものだった。

まず、nn.Linear(8, 8, bias=False) とは何かを調べると、 8次元の入力を行列の掛け算により8次元の出力に変換する処理 (bias=False なので定数の加算はしない) のようだった。

A program src.py and a file model.pth were given.
What src.py does is:

To begin with, I searched for what is nn.Linear(8, 8, bias=False).
I found that it converts a 8-dimension input to a 8-dimension output by matrix multiplication (No addition of constant values is performed because bias=False).

Linear — PyTorch 1.10.0 documentation

次に、nn.Sequential とは何かを調べると、渡された処理をそれぞれ順に行う処理のようだった。

Then, I searched for what is nn.Sequential. It turned out to be a process where the passed processes are sequentially done.

Sequential — PyTorch 1.10.0 documentation

これらを組み合わせた nn.Sequential(*([nn.Linear(8, 8, bias=False)] * 7)) は「8次元の入力を行列の掛け算により8次元の出力に変換する処理」を7回繰り返す処理ということだとわかった。

次に、model.pth をバイナリエディタで見ると、先頭に PK が見えた。
そこで、これはzipアーカイブであると推測し、7-Zipで展開した。
すると、archive/data/93839392490432 という256バイトのファイルがあり、これが nn.Linear で用いられる行列のデータであると推測した。
そして、この行列のデータをテキストに変換する以下のプログラムを作成した。

Combining these, nn.Sequential(*([nn.Linear(8, 8, bias=False)] * 7)) should be a process where "a process to convert a 8-dimension input to a 8-dimension output by matrix multiplication" is repeated 7 times.

After that, I viewed model.pth in a binary editor and found it beginning with PK.
Therefore, I guessed that this is a zip archive and unzipped that using 7-Zip.
Then, I found a 256-byte file archive/data/93839392490432 and guessed that this is the data for the matrix used in nn.Linear.
I created this program to convert this matrix data to text:

bin2mat.pl

さらに、src.py の出力としてコメントで書かれているデータもBase64デコードすると256バイトになったので、同様に行列を表すテキストに変換した。

ここで、実験のためにflagの最初の部分 buckeye{CyberChefで To Decimal をかける。

Also, Base64-decoding the data written in the comment as the output of src.py yielded 256-byte data. I also converted this data to a text representation of matrix in the same way.

To use in an experiment, I applied "To Decimal" on CyberChef to the first part of the flag buckeye{.

To Decimal - CyberChef

Raspberry Pi の wolfram コマンドを利用して、この変換結果に model.pth から読み取った行列の7乗を掛けてみた。

Using the wolfram command on Raspberry Pi, I multiplied the matrix read from model.pth to the 7th power to the result of conversion.

model_test.txt

結果は以下のようになった。

This is the result:

Out[4]= {{0.438170130153532794, -0.007831040597014949, -0.104243176889190001, > 0.344312929055393102, -0.413639742721401102, 0.082283533362897931, > 0.013686747264994923, -0.068815595488821103}}

これは、出力データから読み取った以下の行列の1行目と近い値である。

This result is near to this first row of the matrix read from the output data:

{0.4381701052188873291015625, -0.007831037044525146484375, -0.10424315929412841796875, 0.3443129360675811767578125, -0.4136398136615753173828125, 0.082283549010753631591796875, 0.0136867575347423553466796875, -0.06881560385227203369140625}

出力データから読み取った行列に、model.pth から読み取った行列の7乗の逆行列を掛け、さらにその結果を四捨五入した。

I multiplied the inverse of the matrix read from model.pth to the 7th power to the matrix read from the output data, and rounded the result.

model_reverse.txt

以下の結果が得られた。

This is the result:

Out[6]= {{98, 117, 99, 107, 101, 121, 101, 123}, > {119, 52, 49, 116, 95, 49, 116, 115}, > {95, 52, 108, 108, 95, 109, 52, 116}, > {114, 49, 120, 95, 109, 117, 108, 116}, > {49, 112, 108, 49, 99, 97, 116, 49}, {48, 110, 63, 63, 63, 63, 95, 52}, > {108, 119, 121, 52, 121, 53, 95, 104}, {52, 115, 95, 98, 51, 51, 110, 125}}

この結果をCyberChefで変換することで、flagが得られた。

I obtained the flag by converting this result using CyberChef.

Find / Replace, From Decimal - CyberChef

buckeye{w41t_1ts_4ll_m4tr1x_mult1pl1cat10n????_4lwy4y5_h4s_b33n}

BuckeyeCTF 2021