BUUCTF/SimpleRev

今日はこの質問をするのがとても楽しかったので、それを取り上げて自分の考えを書き留めておきたいと思います。

まず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}を取得します

おすすめ

転載: blog.csdn.net/weixin_51681694/article/details/125628768