クラッキング入門(2) IDA Freewareを使用したcrackmeの解説、keygenの作成


注意事項

この記事ではクラッキングを助長する意図はありません。
また、この記事で紹介する手法はあくまでも一例です。小学生でも「オレ強い」できるレベルしか紹介する気はありません。(CTF入門以下のレベルです...)
あくまで自分の作ったソフトウェアのセキュリティ向上にお役立てください。
商用ソフトウェアではこの手法はほぼ通用しませんし、改変したソフトウェアを使用することは訴訟リスクにもなりえます。

はじめに

こんにちは。
前回、リバースエンジニアリングって何?ハッキング入門してみるという記事を書いたのですが、案外LGTMが多かったので続きを書いてみようかと思います。
今回は、簡単なcrackmeのリバースエンジニアリング、及びkeygenの作成です。
crackmeとはその名の通り、バイナリのクラッキング練習用に作成されたプログラムのことです。

必要なもの

  • GhidraやIDA Free (もちろんProでも同じです)、HopperなどのDisassembler
  • crackme by LiveOverflow
  • 前準備として、0x07_0x08_uncrackable_crackmeにあるlicense_2.cをコンパイルしておいてください。
gcc license_2.c -o license_2

手順

解析

筆者が使い慣れていることもあり、今回はIDA Freewareを使用します。
Ghidraなどでも手順はほとんど同じです。(IDA Freewareは商用利用が禁止されている点やx86/64にしか対応していない点にご注意ください)

まず、先程コンパイルしたlicense_2を読み込み、Graph Viewを表示してみます。

分かりやすいようにラベルをつけておきました。これだけでも十分分かりやすいですが、main関数の擬似コードを表示してみましょう。(IDAの場合F5)

今回は単純なプログラムなので、ほぼソースコードそのままの擬似コードが生成されました。(コメント部分は私が書いたものです)
コードから、このプログラムのライセンスチェックは以下のフローで行われると推測されます。

  1. 変数v5を用意
  2. 引数(以下key)の存在チェック(ない場合Usageを表示)
  3. strlenでkeyの長さを取得し、その回数だけforループ
  4. forループ内で、key[i]をintに変換、変数に加算
  5. ループ終了後、v5が916ならAccess Granted!を表示、違うのであればWRONG!を表示

今回は、これにあったKeygenを、擬似コードから作成してみます。

Keygenの作成

今回のKeygenは、それぞれの文字のUnicode値の合計が916になるようなKeyを生成するプログラムです。
私の場合、以下のようなコードになりました。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    printf("Generating License...\n");

    char key[512];
    int charSum;

    while (1) {
        char randomLetter = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"[arc4random() % 65];
        charSum += (int)randomLetter;
        strncat(key, &randomLetter, 1);
        if (charSum == 916) {
            printf("Key: %s", key);
            break;
        } else if (charSum > 916) {
            charSum = 0;
            memset(key, 0, sizeof(key));
        }
    }

    return 0;
}

まず、whileループの中で、randomLetterにランダムな文字列を代入します。
(ここでは abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_[arc4random() % 文字数+ヌル終端文字列]で生成しています)

次に、randomLetterをUnicode値に変換し、charSumに加算します。
また、strncat(key, &randomLetter, 1)で、keyにrandomLetterをappendします。

もしcharSumが916なら、そのkeyを表示、それより小さければループを継続、それより大きければcharSumとkeyを初期化しループを継続します。

今回私はC言語でKeygenを書きましたが、フォルダ内にはpythonで書かれたものもあります。ぜひ参考にしていただければと思います。

おわりに

今回は単純なcrackmeの解説とkeygenの作成方法について説明しました。
このcrackmeはかなり簡単なものですが、crackmeへのイントロダクションになれば幸いです。

また、今回のcrackmeはLiveOverflowが作成したものです。
Youtubeチャンネルではかなり有益なセキュリティ関連の知識(CTFの解き方など)の動画をアップロードされているので、ぜひ御覧ください。