今日はこの質問をするのがとても楽しかったので、それを取り上げて自分の考えを書き留めておきたいと思います。
まずIDAで開いてメイン関数を表示します
1 つ目は、プログラムがこのゲームに参加するかどうかを決定するということです。Decry() 関数が重要であることが簡単にわかります。クリックしてゲームに参加してください。
さまざまな初期変数の宣言はひとまず置いておいて、次の部分を直接見てください。
画像内の結合関数をクリックすると、実際に 2 つの文字列が 1 つに結合されることがわかります。
したがって、上で行ったのは、初期キーとフラグを合成することでした(!! これはリトルエンディアン ストレージであることに注意してください!!)
それでは次のパートを見てください
ここもわかりやすいのですが、実はキー文字列をすべて大文字から小文字に変更するというものです。
ここへ
テキスト=キルシャドウ
key=adsfkndcls
一番下で、フラグを入力するように求められます。
printf("Please input your flag:");
while ( 1 )
{
v1 = getchar();
if ( v1 == 10 )
break;
if ( v1 == 32 )
{
++v2;
}
else
{
if ( v1 <= 96 || v1 > 122 )
{
if ( v1 > 64 && v1 <= 90 )
{
str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
++v3;
}
}
else
{
str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
++v3;
}
if ( !(v3 % v5) )
putchar(32);
++v2;
}
}
if ( !strcmp(text, str2) )
puts("Congratulation!\n");
else
puts("Try again!\n");
return __readfsqword(0x28u) ^ v11;
while ループ全体では、入力された文字に対して一連の処理を実行し、それを str2 に転送し、最後に str2 がテキストと同じであれば、入力は正しいことになります。
コアコードをもう一度見てください
ASCII コード 32 の文字を除いて、どの文字を入力しても、
str2[v2] = (v1 - 39 - キー[v3 % v5] + 97) % 26 + 97;
この操作
しかし、これは剰余演算であり、計算を効果的に元に戻す方法はなく、爆発するしかありません。
ここでは入力文字が全て大文字であると仮定し、上記の条件を満たす大文字があればフラグの文字が生成されます。
スクリプトは以下に添付されています~~
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
int main(){
string key = "adsfkndcls";
string text = "killshadow";
char res[10];
for(int i=0;i<10;i++){
for(int j=65;j<=90;j++){
if(text[i]==(j-39-key[i]+97)%26+97){
res[i]=j;
break;
}
}
}
cout<<res<<endl;
system("pause");
return 0;
}
最後にフラグ{KLDQCUDFZO}を取得します