MENU閉じる

LAB

その他プログラムTIPS

研究室プログラムTIPSその他2011.6.23

ドングル

少し前に自宅での3DCGのアニメーション用に
messiah studio(http://www.projectmessiah.com/)というソフトを超キャンペーン価格で購入したのですが、
このソフトのライセンス認証が少し面白い仕組みになっていました。
市販のUSBメモリをハードウェアキーとして動作させるのです。

昔はライセンス認証の為だけに専用のドングルと呼ばれるハードウェアを使っていたのですが、
果たして市販のUSBメモリがその役目を果たせるのか気になったので少し調べてみました。
するとWindowsではWMIという機能でディスクドライブのユニークなIDを取得できるようです。
ソースコードも沢山見つける事が出来たのですが、
C#やVBのコードばかりでしたので、C++ではどう書いたら良いのか試しに書いてみました。

今回はUSBのディスクドライブを列挙してその固有IDを表示するものです。
(ソースコードはVisualStudio2010のコンソールアプリケーションで動作確認しています。)

#include
#include
 
// ただの加算関数
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;
} 

COMの初期化関係で行数が多いですが、
実質はインスタンス作成部分から固有ID取得までが目的の処理になります。
この固有IDを基にしたライセンスファイルを作成して、
アプリケーション起動時に二つの整合性を確認出来れば確かにハードウェアキーとして使えそうです。
面白くなってきたのでもしかしたら次回に続くかもしれないです。

RECRUIT

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

RECRUIT SITE