バッファオーバーランによるリターンアドレスの書き換え(おまけ) | reverse-eg-mal-memoのブログ

reverse-eg-mal-memoのブログ

サイバーセキュリティに関して、あれこれとメモするという、チラシの裏的存在。
medium(英語):https://sachiel-archangel.medium.com/

バッファオーバランによるリターンアドレスの書き換え」の記事で使用した、バッファオーバーランするサンプルソースです。

こういうの書いちゃイケナイという見本だからね!!

 

なお、本稿で述べた通り、通常で作成したプロジェクトではいくつかのセキュリティ機能がデフォルトでオンになっており、普通に作ったらバッファオーバランができませんでした

そのため、記事のためにオプション等で魔改造をして、頑張って脆弱なコードに仕上げました

今回一番時間食ったのここじゃないかなぁ・・・

 

まず、__security_check_cookie関数 が入らないよう、コンパイルオプションで /GS- を指定しています。

 

また、文字列を分かりやすくするため、ASCII文字を1文字とするために文字セットを「マルチバイト文字セットを使用する」にしています。

 

さらに、コードを変に複雑にしないよう、最適化オプションをオフにしています。

 

今回、最終的に外しましたが、 strcpy() で警告が出ないよう、「#pragma warning(disable : 4996)」を入れています。これはコンパイルオプションでワーニングレベルを変えてもOKです。

 

あとは、デベロッパやランタイムが入っていない環境でも動くように、コンパイラのコード生成のランタイムライブラリをマルチスレッド(/MT)にしたり、pdbを出力しないようリンカのデバッグのデバッグ情報の生成をオフにしたりしていますが、このあたりはお好みで。

 

また、ループカウンタの i がグローバル変数にしてあります。これは、これをローカル変数にすると、どうしても buf の下に領域がアサインされてしまい、バッファオーバーランをした時にカウンタを上書きし、別の意味で面白い不審な動作をしてしまったので、スタック上にカウンタが置かれないようにグローバル変数にするという、(普通はしなくてもいい)涙ぐましい努力をしています。

 

BufferOverRun.cpp

#include "pch.h"
#include <stdio.h>
#include <string.h>
#pragma warning(disable : 4996)

int i;

void OverRunFunc(const char *strData)
{
    char buf[16];
    
    i = 0;
    memset(buf, 0x00, sizeof(buf));

    for (;;)
    {
        buf[i] = strData[i];
        if (buf[i] == NULL)
            break;
        i++;
    }

    printf("%s\r\n", buf);

    return;
}

int main()
{
    OverRunFunc("Test");
    OverRunFunc("Buffer over run.        ");
    return 0;
}