パスワード認証プログラムの作成 | はじめてのリバースエンジニアリング#1

パスワード認証プログラムを作成し、それを自らリバースエンジニアリングしてアクセス承認を引き出したいシリーズその1。

今回は下準備として、今後解析していくための簡単なパスワード認証プログラムを作成しました。


Introduction

プログラミングの勉強をしたい、という声をよく目にします。

もちろん、私もプログラミングを身につけたいと思っています。
しかし、よくある「プログラミング学習」類のものではあまり興奮が得られなかった1ので、気分転換を図ろうと思いました。

そこで、プログラミングの知識もろくにない私ですが、リバースエンジニアリングなるものに挑戦することにしました。
wikipediaによると、リバースエンジニアリングとは2

リバースエンジニアリング(Reverse engineeringから。直訳すれば逆行工学という意味)とは、機械を分解したり、製品の動作を観察したり、ソフトウェアの動作を解析するなどして、製品の構造を分析し、そこから製造方法や動作原理、設計図などの仕様やソースコードなどを調査することを指す。

今回の私の場合、ソフトウェアの動作を解析して、仕様を調査すること、ということになるでしょう。
こいつは面白そうです。

まずは、LiveOverflow氏の動画3を参考にしながら、自分で改変を加えつつ、流れを再現することを目指します。
今回は下準備として、これから使うパスワード認証プログラムを作成するところまで記しました。


Material

Ubuntu18.04.1 LTS を
Windows10の上に、VMwareによって構築した仮想環境で起動しています。
www.bioerrorlog.work


Results

パスワード認証プログラムの作成

まずは、パスワード認証プログラムを作成しました。
後にバイナリコードを解析して、逆アセンブルするためのものです。
自分で作ったパスワード認証プログラムを自分で暴く、というのはなんとも滑稽なことですが、初心者の私にはもってこいの方法でしょう。

LiveOverflow氏のコード4を参考に、C言語で次のコード"your_pass.c"を書きました。

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

int main(int argc, char *argv[]) {
        if(argc==2) {
                printf("Checking Your Pass: %s\n", argv[1]);
                if(strcmp(argv[1], "Antoine-Marie-Jean-Baptiste-Roger_comte-de-Saint-Exupery")==0) {
                        printf("Hello, Master.\n");
                } else {
                        printf("Access Denied.\n");
                }

        } else {
                printf("Access Denied.\n");
        }
        return 0;
}

まずはコードを少し読み上げます。
"argc"と""argv"はコマンドライン引数と呼ばれ、、コード実行時の引数に関する情報を持っています。

例えばこのコード"your_pass.c"をコンパイルしてバイナリコード"your_pass"を作成し、次のように引数"mypass"を渡して実行してみます。

$ ./your_pass mypass

このときのコマンドライン引数は、

./your_pass mypass
argv[0] argv[1]

argc = 2 (引数の数)
となります。

つまり、コードの最初のif分岐 if(argc==2)は、実行時に引数が一つ渡されたかどうかを判定し、このif分岐がFALSEの場合は、 Access Denied. が表示されます。

一方、このif分岐がTRUEの場合、printf("Checking Your Pass: %s\n", argv[1]);を実行した後、渡された引数のチェックに移ります。

if(strcmp(argv[1], "Antoine-Marie-Jean-Baptiste-Roger_comte-de-Saint-Exupery")==0)

strcmp()は、2つの文字列が等しいときに0を返す関数です。
argv[1](実行時に渡した引数)が、正解のパスワード("Antoine-Marie-Jean-Baptiste-Roger_comte-de-Saint-Exupery")と等しいかどうか、を判定しています。

以上のことから、このコードの挙動は次のようになるはずです。

正しいパスワード:Antoine-Marie-Jean-Baptiste-Roger_comte-de-Saint-Exupery
を引数として渡したときのみ、"Hello, Master"が表示される。

それ以外では、"Access Denied."が表示される。

さっそくyour_pass.cをコンパイルして試してみます。

#コンパイル
$ gcc your_pass.c -o your_pass
#正解パスワードで実行
$ ./your_pass Antoine-Marie-Jean-Baptiste-Roger_comte-de-Saint-Exupery
Checking Your Pass: Antoine-Marie-Jean-Baptiste-Roger_comte-de-Saint-Exupery
Hello, Master.
#不正解パスワードで実行
$ ./your_pass wrong_pass
Checking Your Pass: wrong_pass
Access Denied.
#引数なしで実行
$ ./your_pass
Access Denied.

見事、予想通りの挙動をしてくれました。


Discussion

今回は、これから解析していくパスワード認証プログラムを下準備として作成しました。

それでは、一旦このソースコードについての記憶を消去します。

次回からの目的は、正解パスワードを渡さずしてアクセス承認("Hello, Master."の表示)を引き出すことです。
様々なやり方があるようですが、まずはバイナリコードを逆アセンブラ解析することによってプログラムの挙動を暴き、パスワード認証過程の迂回を目指します。

See also

次↓ www.bioerrorlog.work


  1. もちろん、うまくいかないまでも何かを作ろうと試行錯誤するのはとても楽しいです。しかし、いわゆる「プログラミング言語の勉強」なるものをやっていると、自分でも何がしたいのか分からなくなってきます。

  2. リバースエンジニアリング - Wikipedia

  3. Reversing and Cracking first simple Program - bin 0x05 - YouTube

  4. GitHub - LiveOverflow/liveoverflow_youtube: Material for the YouTube series