[GUET-CTF2019] number_game
ステップ
- 定期検査、64ビットプログラム、シェルなし
- 64ビットのidaロード
プログラムは非常に単純です。最初に文字列を入力してv5に格納し、次にsub_4006D6()、sub_400758()、sub_400807()、sub_400881()のいくつかの関数の操作を実行します。 、sub_400917()、最後にフラグが出力されます。 - sub_4006D6()
sub_400758()
sub_400807()
sub_400881()
キー判定関数a1 []にsub_400917()を割り当て、この条件が満たされるとフラグが出力されます。数独のように見えます。各行のデータと各列を同じにすることはできませんunk_601060sub_400917()
に
従ったデータ、これらのデータは約5 * 5に配置されます
str="14#2330#1#0#23##3##042##1"
for i in range(25):
print(str[i],end=" ")
if (i+1)%5==0:
print('\n',end="")
sub_400881()によると、#は上から下、左から右の順序で入力する必要のあるデータであることがわかっています。
- 明らか
0421421430
に最終結果ではありません。データは取得されたsub_400758()とsub_400807()によって変換されるため、動的に調整されたデータのこれら2つの関数の特定の操作を
確認します。時間、デバッグを開始する方法を理解するたびに
次のコンテンツは、このマスターのwpを参照しています
sub_400807関数とsub_400881関数は、実際にはバイナリツリーのプレオーダートラバーサルとミドルオーダートラバーサルであり、文字配列内の添え字を並べ替えます。
まず、sub_400807()に従って、配列添え字のバイナリツリーを作成します。
#include <iostream>
using namespace std;
void func1(int a2, int a3) {
cout << a2 << endl;
if (a2 >= a3)
return;
func1(2 * a2 + 1, a3);
func1(2 * (a2 + 1), a3);
}
int main()
{
func1(0, 10);
system("PAUSE");
return 0;
}
9を超えるものを見ないでください。事前順序トラバーサルの結果は、0137849256であり、これは二分木を構築します。
したがって、順序トラバーサルの結果は、7,3,8,1,9、 4,0,5,2,6。sub_400881
関数は実際には次のとおりです。中次走査シーケンスのbyte_601062へのシーケンス割り当て
は、入力するデータの添え字が7,3,8,1によって再ソートされることを意味します、9,4,0,5,2,6を取得するには、0123456789に従って、0421421430を取得します。もう一度ソートして、入力データを取得します。
# -*- coding:utf-8 -*-
model = [7, 3, 8, 1, 9, 4, 0, 5, 2, 6]
s = [48, 52, 50, 49, 52, 50, 49, 52, 51, 48]
flag = [0] * 10
for i in range(10):
flag[model[i]] = s[i]
print ('flag{' + ''.join([chr(x) for x in flag]) + '}')
フラグ{1134240024}
調整できれば、上記の添え字の値をより直感的に取得できます。
参照wp:https://www.cnblogs.com/Mayfly-nymph/p/12859103.html