HEXA BLOG

プログラム

HEXA BLOGプログラム2011.8.31

ドングル3

お久しぶりです。
先日激辛料理レストランで撃沈しましたふらふら
沈みゆく太陽good sun晴れこと山口です。
今日も元気です。
今回でドングルシリーズ最後となります。
もはやドングルそのものとは関係の薄い内容となっておりますが、
そもそもドングルとはプログラムの実行制限により、
プログラムライセンス保持者を守るパンチものです。
どんなに頑張ってハードウェアキーを使って、
安全にライセンスキーをやり取りしても、
実際に実行するプログラム側を攻撃されてしまうこともあるのです。
今回はこの実行するプログラムを守る方法の一つをご紹介します。
実行コードを隠すです。
簡単なサンプルコードを以下に掲載します。
Windows7(Intel Core i7CPU) VisualStudio2010にて動作確認しています。

#include<stdio.h>
#include<windows.h>
// ただの加算関数
int funcAdd(int a, int b)
{
return a + b;
}
// 上の関数のx86バイナリコード
unsigned char codeAdd[] =
{
// _a$ = 8
// _b$ = 12
0x55,                               //  push    ebp
0x8b, 0xec,                         //  mov     ebp,    esp
0x81, 0xec, 0xc0,0x00, 0x00, 0x00,  //  sub     esp,    192
0x53,                               //  push    ebx
0x56,                               //  push    esi
0x57,                               //  push    edi
0x8d, 0xbd, 0x40, 0xff, 0xff, 0xff, //  lea     edi,    [ebp - 192]
0xb9, 0x30, 0x00, 0x00, 0x00,       //  mov     ecx,    48
0xb8, 0xcc, 0xcc, 0xcc, 0xcc,       //  mov     eax,    -858993460
0xf3, 0xab,                         //  rep     stosd
0x8b, 0x45, 0x08,                   //  mov     eax,    _a$[ebp]
0x03, 0x45, 0x0c,                   //  add     eax,    _b$[ebp]
0x5f,                               //  pop     edi
0x5e,                               //  pop     esi
0x5b,                               //  pop     ebx
0x8b, 0xe5,                         //  mov     esp,    edp
0x5d,                               //  pop     edp
0xc3                                //  ret     0
};
typedef int(*funcType)(int a, int b);
int main()
{
// 通常関数のコール結果
printf("func %d\n", funcAdd(5, 10));
// 少し前のwindowsから実行属性の無い領域を実行させられないプロテクトが入っている為
// 実行属性付の領域を確保する
void* code = VirtualAlloc( NULL, sizeof(codeAdd), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(code != NULL){
memcpy(code, codeAdd, sizeof(codeAdd));
DWORD oldProteted;
VirtualProtect( code, sizeof(codeAdd), PAGE_EXECUTE, &oldProteted );
// このような感じでデータ領域のコードを実行属性の領域に移してきて実行させる事が出来る
funcType func = (funcType)code;
printf("code %d\n", func(5, 10));
}
return 0;
}

funcAddという関数はプログラムコードを逆アセンブラした際に、
プログラム領域に配置されますが、
codeAddというデータはデータ領域に配置されます。
ある程度の規模のプログラムになるとちょっと見ただけでは、
このcodeAdd部分を探すのは難しくなります。
さらにこれを応用すると実行コードを暗号化したり
別ファイルからリソースの如く読み込んだり出来ます。
より目につきにくく読みにくくすることが出来るようになります。
ちなみにx86バイナリコードは
構成プロパティのC/C++の出力ファイルから
アセンブリの出力で
“アセンブリコードとコンピュータ語コード(/FAc)”を選択するとビルド後に出力されるものを利用しています。
とは言えこのあたりの防衛はいつかは破られると言われているものです。
頻繁にバージョンアップを行って、最新版を生み出し続ける事が最大の対策かもしれないですね。
今回でドングルシリーズを終了して、
次回は最近興味を持っているHTML5的なお話か最近購入した3Dマウスのお話が出来たらいいなと思います。
ではまた手(パー)

RECRUIT

大阪・東京共にスタッフを募集しています。
特にキャリア採用のプログラマー・アーティストに興味がある方は下のボタンをクリックしてください

RECRUIT SITE