SlideShare a Scribd company logo
1 of 42
Download to read offline
怪しい
Windowsプログラミング



 名古屋313
自己紹介
●   隅須三郎(@nagoya313)
●   C++初心者
●
    Windows系男子
●   名古屋出身/在住の3月13日生まれという
    わけではない
今日の内容
●   適当に作ったプログラムを元ソースを弄ら
    ずに改造する
     ➔
         Win32APIとDirect3D9製のC++プログラム
     ➔   外部からの拡張は考慮せずに作成
元となるプログラムの概要
●    エントリポイント

    int WINAPI WinMain(HINSTANCE hInst,
                       HINSTANCE hPrevInst,
                       LPSTR cmdLine,
                       int cmdShow) {
      InitWindow();
      InitDirect3D9();
      ShowWindow(g_hWnd, cmdShow);
      return Loop();
    }
元となるプログラムの概要
●    ウィンドウクラスの登録とウィンドウ作成
    void InitWindow() {
      WNDCLASSEX wc;
      ZeroMemory(&wc, sizeof(WNDCLASSEX));
      wc.cbSize        = sizeof(WNDCLASSEX);
      wc.style         = CS_HREDRAW | CS_VREDRAW;
      wc.lpfnWndProc   = WndProc;
      wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
      wc.hbrBackground = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
      wc.lpszClassName = kClassName;
      RegisterClassEx(&wc);
      g_hWnd = CreateWindow(kClassName, L"やみなべ!",
                            WS_OVERLAPPEDWINDOW,
                            CW_USEDEFAULT, CW_USEDEFAULT,
                            CW_USEDEFAULT, CW_USEDEFAULT,
                            nullptr,nullptr,
                GetModuleHandle(nullptr), nullptr);
    }
元となるプログラムの概要
●   Direct3D9の初期化
void InitDirect3D9() {
  g_pD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
  D3DPRESENT_PARAMETERS d3dpp;
  ZeroMemory(&d3dpp, sizeof(d3dpp));
  d3dpp.Windowed         = TRUE;
  d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
  d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
  d3dpp.BackBufferWidth = 640;
  d3dpp.BackBufferHeight = 480;
  g_pD3d9->CreateDevice(D3DADAPTER_DEFAULT,
                        D3DDEVTYPE_HAL,
                        g_hWnd,
                        D3DCREATE_HARDWARE_VERTEXPROCESSING,
                        &d3dpp,
                        &g_pDevice);
  D3DXCreateTextureFromFile(g_pDevice, L"d3.png", &g_pTexture);
}
元となるプログラムの概要
●   メッセージループ
int Loop() {
  for (;;) {
    MSG msg;
    if (PeekMessage (&msg, nullptr, 0, 0, PM_NOREMOVE)) {
      auto ret = GetMessage (&msg, nullptr, 0, 0);
      if (!ret || ret == -1) {
        g_pD3d9->Release();
        g_pDevice->Release();
        return msg.wParam ;
      }
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    } else {
      Update();
    }
  }
}
元となるプログラムの概要
●   1Fでの処理(黒で消して画像を表示)
struct VertexImage2D {
   float x;
   float y;
   float z;
   float rhw;
   float u;
   float v;
};

void Update() {
  g_pDevice->BeginScene();
  g_pDevice->Clear(0, nullptr, D3DCLEAR_TARGET,
                    D3DCOLOR_XRGB(0, 0, 0), 1.f, 0);
  VertexImage2D vertex[4] = {
     {0.f, 0.f, 0.f, 1.f, 0.f, 0.f},
     {162.f, 0.f, 0.f, 1.f, 1.f, 0.f},
     {0.f, 309.f, 0.f, 1.f, 0.f, 1.f},
     {162.f, 309.f, 0.f, 1.f, 1.f, 1.f}
  };
  g_pDevice->SetTexture(0, g_pTexture);
  g_pDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
  g_pDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertex,
sizeof(vertex[0]));
  g_pDevice->EndScene();
  g_pDevice->Present(nullptr, nullptr, nullptr, nullptr);
}
元となるプログラムの概要
●   ウィンドウプロシージャ(×を押したら終了)
LRESULT WINAPI WndProc(HWND hWnd,
                        UINT msg,
                        WPARAM wp,
                        LPARAM lp) {
  if (msg == WM_DESTROY) {
    PostQuitMessage(0);
    return 0;
  }
  return DefWindowProc(hWnd, msg, wp, lp);
}
DLL(Dynamic Link Library)
                             の裏話
●   Windowsだとexeがあるディレクトリに同名
    のdllがあるとSystem32とかにあるものより
    も優先的に読み込まれる
      ➔   こっそり偽者を置いておけばプログラムが
           偽者を勝手に読んでくれる
d3d9.dllの偽物を作る
●   d3d9.dllの偽者を置いておけば勝手にプロ
    グラムが読み込む
●   使われる関数がDirect3DCreate9だけなの
    で簡単に作れる
●   プログラムが読み込む関数はいい加減に
    作ったら残当する
      ➔   関数名とか引数の数とか呼び出し規約と
           かはきっちりする必要がある
d3d9.dllの偽物を作る
●   VisualC++ 2010を想定
●   DLL、空のプロジェクトを作成
d3d9.dllの偽物を作る
●    d3d9.defを用意
●    エクスポートする関数名を列挙
●
     プロジェクトプロパティ→構成プロパティ→
     リンカ→入力→モジュール定義ファイルに
     d3d9.defを指定
    LIBRARY d3d9
    EXPORTS
       Direct3DCreate9 @4
d3d9.dllの偽物を作る
●    エントリポイント

    BOOL APIENTRY DllMain(HINSTANCE,
                          DWORD reason,
                          LPVOID) {
      return reason == DLL_PROCESS_ATTACH ?
                       Init() :
                       TRUE;
    }
d3d9.dllの偽物を作る
●   本物のDirect3DCreate9を取得
BOOL Init() {
  // 本物のD3D9.dllがあるパスを取得
  TCHAR strPathBuffer[kBufferMax];
  GetSystemDirectory(strPathBuffer, kBufferMax);
  PathAppend(strPathBuffer, L"D3D9.DLL");
  HMODULE hOriginalModule = LoadLibrary(strPathBuffer);
  if (!hOriginalModule) {
    return FALSE;
  }
  // 本物のDirect3DCreate9のアドレスを取得
  g_pOriginalDirect3DCreate9 = reinterpret_cast<IDirect3D9 *(WINAPI *)
(UINT)>(GetProcAddress(hOriginalModule, "Direct3DCreate9"));
  if (!g_pOriginalDirect3DCreate9) {
    return FALSE;
  }
  return TRUE;
}
d3d9.dllの偽物を作る
●    偽物のDirect3DCreate9を作る

    extern "C" {
    IDirect3D9 *WINAPI Direct3DCreate9(UINT
    SDKVersion) {
      return (*g_pOriginalDirect3DCreate9)
    (SDKVersion);
    }
    }
d3d9.dllの偽物を作る
●   作ったdllを元のプログラムと同じディレクト
    リに置けば仕込みは完了
改造1:MessageDialogを仕込む

●   Initの中にMessageBoxを仕込む
BOOL Init() {
  MessageBox(nullptr, L"侵入!", L"", 0);
  // ..
  return TRUE;
}
改造2:消去色を赤に
●   IDirect3D9Device9::Clearを差し替える
●   第4引数を常に赤にして本物のClearに渡す
Direct3DはC言語でも
                開発出来ます?
●   とはいいつつもクラスっぽい呼び出しが絡
    むDirect3Dでの開発は純粋なC言語で出
    来るの?
Direct3DはC言語でも
                          開発出来ます
●   Direct3D周りにヘッダを読む前に
    #define CINTERFACE
    を唱えるとDirect3Dが変身
Direct3DはC言語でも
                       開発出来ます
g_pDevice->Clear(0, nullptr, D3DCLEAR_TARGET,
D3DCOLOR_XRGB(0, 0, 0), 1.f, 0);
 が
g_pDevice->lVptbl->Clear(g_pDevice, 0, nullptr,
D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.f,
0);
 こうなる
vtableみたいなの登場
●   Cインターフェイスの仮想函数テーブルのよ
    うなサムシングの函数ポインタを偽物に書
    き換えれば差し替え達成
IDirect3D9::CreateDevice
                              を差し替え
●   IDirect3DDevice9を製造する大元を叩く
extern "C" {
IDirect3D9 *WINAPI Direct3DCreate9(UINT SDKVersion) {
  IDirect3D9 *pD3d9 = (*g_pOriginalDirect3DCreate9)
(SDKVersion);
  // 本物を退避
  g_pOriginalCreateDevice = pD3d9->lpVtbl-
>CreateDevice;
  // 偽物に書き換え
  pD3d9->lpVtbl->CreateDevice = MyCreateDevice;
  return pD3d9;
}
}
IDirect3DDevice9::Clear
                                   を差し替え
●   偽CleateDevice内でClearを差し替え
HRESULT WINAPI MyCreateDevice(引数省略...
                              IDirect3DDevice9**
ppReturnedDeviceInterface) {
  HRESULT ret = (*g_pOriginalCreateDevice)(引数省略...,

ppReturnedDeviceInterface);
  if (SUCCEEDED(ret)) {
    // 本物を退避
    g_pOriginalClear = (*ppReturnedDeviceInterface)->lpVtbl-
>Clear;
    // 偽物に書き換え
    (*ppReturnedDeviceInterface)->lpVtbl->Clear = MyClear;
  }
  return ret;
}
偽IDirect3DDevice9::Clear
●   常に赤を指定した本物を呼び出す
HRESULT WINAPI MyClear(IDirect3DDevice9 *pDevice,
                       DWORD Count,
                       const D3DRECT *pRects,
                       DWORD Flags,
                       D3DCOLOR Color,
                       float Z,
                       DWORD Stencil) {
  return (*g_pOriginalClear)(pDevice, Count,
pRects, Flags, D3DCOLOR_XRGB(255, 0, 0), Z,
Stencil);
}
差し替える
              偽IHogeHoge::Hogeの型
●   MSDNに乗っているものに呼び出し規約
    WINAPIを付けて第一引数にIHogeHoge *を
    加える函数ポインタ
HRESULT Hoge(int, double);

    があったら
HRESULT (WINAPI *Hoge)(IHogeHoge *, int, double);

    になる
実はセグる
●   lpVtblがある場所はアクセス保護されてい
    る
      ➔
          VirtualProtectを使って書き込み出来るよう
            にする必要がある
CぷらーならRAIIだよね
●    VirtualProtectをRAIIっぽく
struct ScopedVirtualProtect {
  template <typename P>
  ScopedVirtualProtect(P p, DWORD dwNewProtext) : m_p(p),
m_size(sizeof(*p)) {
    VirtualProtect(m_p, m_size, dwNewProtext, &m_oldProtect);
  }
    ~ScopedVirtualProtect() {
      VirtualProtect(m_p, m_size, m_oldProtect, &m_oldProtect);
    }

 private:
   ScopedVirtualProtect(const ScopedVirtualProtect &);
   ScopedVirtualProtect &operator =(const ScopedVirtualProtect &);
   LPVOID m_p;
   SIZE_T m_size;
   DWORD m_oldProtect;
};
アクセス権限書き換え
●    偽物に書き換える前に仕込む
ScopedVirtualProtect protect(pD3d9->lpVtbl,
                             PAGE_EXECUTE_WRITECOPY);
pD3d9->lpVtbl->CreateDevice = MyCreateDevice;




    ScopedVirtualProtect
       protect((*ppReturnedDeviceInterface)->lpVtbl,
               PAGE_EXECUTE_WRITECOPY);
     (*ppReturnedDeviceInterface)->lpVtbl->Clear = MyClear;
改造3:ウィンドウサイズ
              変更とEscキーでの終了
●   IDIrect3D9::CreateDeviceを差し替えたこと
    でフォーカスウィンドウハンドルが手に入る
       ➔
           ウィンドウハンドルを使って色々出来る
ウィンドウサイズ変更
●   640*480に変えるついでにサイズ変更不可
    なスタイルに変更
HRESULT WINAPI MyCreateDevice(引数省略.. HWND hFocusWindow, 引数省略..) {
  RECT rect = {0, 0, 640, 480};
  // サイズ変更不可スタイル
  const DWORD kWinsowStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
WS_MINIMIZEBOX;
  // ウィンドウスタイル変更
  SetWindowLong(hFocusWindow, GWL_STYLE, kWinsowStyle);
  // ウィンドウサイズ計算
  AdjustWindowRect(&rect, kWinsowStyle, FALSE);
  // ウィンドウサイズ変更
  SetWindowPos(hFocusWindow, nullptr,
                0, 0,
                rect.right – rect.left, rect.bottom - rect.top,
                SWP_NOMOVE | SWP_NOZORDER);
  // ..
  return ret;
}
Escキーで終了処理を追加
●   ウィンドウプロシージャを置き換える

HRESULT WINAPI MyCreateDevice(引数省略. HWND hFocusWindow, 引数省略.) {
  // ..
  // ウィンドウプロシージャ置き換え
  SetWindowLong(hFocusWindow, GWL_WNDPROC,
reinterpret_cast<LONG>(&WndProc));
  // ..
  return ret;
}
新しいウィンドウプロシージャ
●   Escキーを押したらウィンドウを破棄
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wp,
LPARAM lp) {
  if (msg == WM_DESTROY) {
    PostQuitMessage(0);
    return 0;
  }
  // エスケープが押されたら窓を破棄
  if (msg == WM_KEYDOWN) {
    if (wp == VK_ESCAPE) {
      DestroyWindow(hWnd);
    }
    return 0;
  }
  return DefWindowProc(hWnd, msg, wp, lp);
}
改造4:読み込む画像
           ファイル名を修正
●   画像表示といいつつ何もでてない?
➔   ファイルの拡張子を間違って指定
    (×bmp→○bmq)
D3DXCreateTextureFromFile
                        を乗っ取り
●   ファイル名の拡張子を替える処理を加えた
    偽者に差し替える
●   偽d3d9.dllは既にプロセスに侵入している
インポートセクションの取得
●   DLL名とか函数名とかが入っている領域
●   先頭には読み込むdllの数だけ
    IMAGE_IMPORT_DESCRIPTOR構造体が配
    置
// ベースアドレスを取得
HMODULE hBase = GetModuleHandle(nullptr);
DWORD dwSize;
// IMAGE_IMPORT_DESCRIPTOR テーブルのアドレスの取得
PIMAGE_IMPORT_DESCRIPTOR imgDesc =
static_cast<PIMAGE_IMPORT_DESCRIPTOR>(
    ImageDirectoryEntryToData(
        hBase,
        TRUE,
        IMAGE_DIRECTORY_ENTRY_IMPORT,
        &dwSize));
d3dx9_xx.dllを探す
●   D3DXCreateTextureFromFile函数が入って
    いるdllを探す
// 最後のIMAGE_IMPORT_DESCRIPTORは0で埋められている
while (imgDesc->Name) {
  // imgDesc->Nameはdll名までの相対オフセット
  const char * strModule = reinterpret_cast<char
*>((reinterpret_cast<DWORD>(hBase) + imgDesc->Name));
  // 使っているSDKに依存
  if (!std::strcmp(strModule, "d3dx9_43.dll")) {
    break;
  }
  ++imgDesc;
}
D3DXCreateTextureFromFile
                                   を探す
●   インポートアドレステーブルとインポート
    ネームテーブルを取得
// インポートアドレステーブル
PIMAGE_THUNK_DATA pIAT =
reinterpret_cast<PIMAGE_THUNK_DATA>(
    reinterpret_cast<DWORD>(hBase) + imgDesc->FirstThunk);
// インポートネームテーブル
PIMAGE_THUNK_DATA pINT =
reinterpret_cast<PIMAGE_THUNK_DATA>(
    reinterpret_cast<DWORD>(hBase) + imgDesc-
>OriginalFirstThunk);
D3DXCreateTextureFromFile
                                         をフック
●    D3DXCreateTextureFromFileを差し替え
while (pIAT->u1.Function) {
    // 最上位が立ってたら名前じゃない
    if (!(pINT->u1.AddressOfData & 0x80000000)) {
      // 名前取得
    PIMAGE_IMPORT_BY_NAME pImportName =
reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
    reinterpret_cast<DWORD>(hBase) + pINT->u1.AddressOfData);
      // D3DXCreateTextureFromFileかを比較
    if (!std::strcmp(reinterpret_cast<char *>(pImportName->Name),
"D3DXCreateTextureFromFileW")) {
        // 本物を退避
      g_pOriginalD3DXCreateTextureFromFile =
reinterpret_cast<decltype(g_pOriginalD3DXCreateTextureFromFile)>(pIAT-
>u1.Function);
        // 偽物に書き換え
      scoped_virtual_protect protect(pIAT, PAGE_READWRITE);
      pIAT->u1.Function =
reinterpret_cast<DWORD>(MyD3DXCreateTextureFromFile);
      break;
    }
  }
  ++pIAT; ++pINT;
}
偽D3DXCreateTextureFromFile

●   ファイル名の拡張子をbmqに差し替え
HRESULT WINAPI MyD3DXCreateTextureFromFile(LPDIRECT3DDEVICE9 pDevice,
                                           LPCTSTR pSrcFile,
                                           LPDIRECT3DTEXTURE9 *ppTexture) {
  LPTSTR pTemp = static_cast<LPTSTR>(std::malloc(sizeof(*pTemp) *
(lstrlen(pSrcFile) + 1)));
  lstrcpy(pTemp, pSrcFile);
  // 拡張子を差し替え
  PathRenameExtension(pTemp, L".bmq");
  auto ret = (*g_pOriginalD3DXCreateTextureFromFile)(pDevice, pTemp,
ppTexture);
  std::free(pTemp);
  return ret;
}
おしまい

More Related Content

What's hot

EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスするEWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスするKiyoshi Sawada
 
【TechBuzz】第9回cocos2d-x勉強会「シェーダ書いてますか?」
【TechBuzz】第9回cocos2d-x勉強会「シェーダ書いてますか?」【TechBuzz】第9回cocos2d-x勉強会「シェーダ書いてますか?」
【TechBuzz】第9回cocos2d-x勉強会「シェーダ書いてますか?」nyagasuki
 
GoCon 2015 Summer GoのASTをいじくって新しいツールを作る
GoCon 2015 Summer GoのASTをいじくって新しいツールを作るGoCon 2015 Summer GoのASTをいじくって新しいツールを作る
GoCon 2015 Summer GoのASTをいじくって新しいツールを作るMasahiro Wakame
 
基礎からのCode Contracts
基礎からのCode Contracts基礎からのCode Contracts
基礎からのCode ContractsYoshifumi Kawai
 
JJUG CCC 2012 Real World Groovy/Grails
JJUG CCC 2012 Real World Groovy/GrailsJJUG CCC 2012 Real World Groovy/Grails
JJUG CCC 2012 Real World Groovy/GrailsUehara Junji
 
Synthesijer jjug 201504_01
Synthesijer jjug 201504_01Synthesijer jjug 201504_01
Synthesijer jjug 201504_01Takefumi MIYOSHI
 
coma Creators session vol.2
coma Creators session vol.2coma Creators session vol.2
coma Creators session vol.2Atsushi Tadokoro
 
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスするEWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスするKiyoshi Sawada
 
知って得するC#
知って得するC#知って得するC#
知って得するC#Shota Baba
 
競技プログラミングのためのC++入門
競技プログラミングのためのC++入門競技プログラミングのためのC++入門
競技プログラミングのためのC++入門natrium11321
 
Markup Template Engine introduced Groovy 2.3
Markup Template Engine introduced Groovy 2.3Markup Template Engine introduced Groovy 2.3
Markup Template Engine introduced Groovy 2.3Uehara Junji
 
unique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるときunique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるときShintarou Okada
 
Webデザイン 第10回:HTML5実践 Three.jsで3Dプログラミング
Webデザイン 第10回:HTML5実践 Three.jsで3DプログラミングWebデザイン 第10回:HTML5実践 Three.jsで3Dプログラミング
Webデザイン 第10回:HTML5実践 Three.jsで3DプログラミングAtsushi Tadokoro
 
Synthesijer zynq qs_20150316
Synthesijer zynq qs_20150316Synthesijer zynq qs_20150316
Synthesijer zynq qs_20150316Takefumi MIYOSHI
 
EWD 3トレーニングコース#21 GlobalストレージのJavaScript用抽象化-(b) JavaScriptの永続オブジェクト
EWD 3トレーニングコース#21 GlobalストレージのJavaScript用抽象化-(b) JavaScriptの永続オブジェクトEWD 3トレーニングコース#21 GlobalストレージのJavaScript用抽象化-(b) JavaScriptの永続オブジェクト
EWD 3トレーニングコース#21 GlobalストレージのJavaScript用抽象化-(b) JavaScriptの永続オブジェクトKiyoshi Sawada
 
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGLMedia Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGLAtsushi Tadokoro
 

What's hot (20)

EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスするEWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
 
C++勉強会
C++勉強会C++勉強会
C++勉強会
 
【TechBuzz】第9回cocos2d-x勉強会「シェーダ書いてますか?」
【TechBuzz】第9回cocos2d-x勉強会「シェーダ書いてますか?」【TechBuzz】第9回cocos2d-x勉強会「シェーダ書いてますか?」
【TechBuzz】第9回cocos2d-x勉強会「シェーダ書いてますか?」
 
GoCon 2015 Summer GoのASTをいじくって新しいツールを作る
GoCon 2015 Summer GoのASTをいじくって新しいツールを作るGoCon 2015 Summer GoのASTをいじくって新しいツールを作る
GoCon 2015 Summer GoのASTをいじくって新しいツールを作る
 
基礎からのCode Contracts
基礎からのCode Contracts基礎からのCode Contracts
基礎からのCode Contracts
 
JJUG CCC 2012 Real World Groovy/Grails
JJUG CCC 2012 Real World Groovy/GrailsJJUG CCC 2012 Real World Groovy/Grails
JJUG CCC 2012 Real World Groovy/Grails
 
Synthesijer jjug 201504_01
Synthesijer jjug 201504_01Synthesijer jjug 201504_01
Synthesijer jjug 201504_01
 
coma Creators session vol.2
coma Creators session vol.2coma Creators session vol.2
coma Creators session vol.2
 
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスするEWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
 
知って得するC#
知って得するC#知って得するC#
知って得するC#
 
覚醒!JavaScript
覚醒!JavaScript覚醒!JavaScript
覚醒!JavaScript
 
T93 com入門
T93 com入門T93 com入門
T93 com入門
 
競技プログラミングのためのC++入門
競技プログラミングのためのC++入門競技プログラミングのためのC++入門
競技プログラミングのためのC++入門
 
Markup Template Engine introduced Groovy 2.3
Markup Template Engine introduced Groovy 2.3Markup Template Engine introduced Groovy 2.3
Markup Template Engine introduced Groovy 2.3
 
unique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるときunique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるとき
 
Webデザイン 第10回:HTML5実践 Three.jsで3Dプログラミング
Webデザイン 第10回:HTML5実践 Three.jsで3DプログラミングWebデザイン 第10回:HTML5実践 Three.jsで3Dプログラミング
Webデザイン 第10回:HTML5実践 Three.jsで3Dプログラミング
 
Synthesijer zynq qs_20150316
Synthesijer zynq qs_20150316Synthesijer zynq qs_20150316
Synthesijer zynq qs_20150316
 
EWD 3トレーニングコース#21 GlobalストレージのJavaScript用抽象化-(b) JavaScriptの永続オブジェクト
EWD 3トレーニングコース#21 GlobalストレージのJavaScript用抽象化-(b) JavaScriptの永続オブジェクトEWD 3トレーニングコース#21 GlobalストレージのJavaScript用抽象化-(b) JavaScriptの永続オブジェクト
EWD 3トレーニングコース#21 GlobalストレージのJavaScript用抽象化-(b) JavaScriptの永続オブジェクト
 
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGLMedia Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL
 
20130819 jjugnslt
20130819 jjugnslt20130819 jjugnslt
20130819 jjugnslt
 

Viewers also liked

Tcl/Tkクイック入門
Tcl/Tkクイック入門Tcl/Tkクイック入門
Tcl/Tkクイック入門nyaocat
 
IdrisでWebアプリを書く
IdrisでWebアプリを書くIdrisでWebアプリを書く
IdrisでWebアプリを書くHideyuki Tanaka
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるHideyuki Tanaka
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門Hideyuki Tanaka
 
開発者の方向けの Sql server(db) t sql 振り返り
開発者の方向けの Sql server(db) t sql 振り返り開発者の方向けの Sql server(db) t sql 振り返り
開発者の方向けの Sql server(db) t sql 振り返りOda Shinsuke
 
2016年を振り返って
2016年を振り返って2016年を振り返って
2016年を振り返ってOda Shinsuke
 
できる!並列・並行プログラミング
できる!並列・並行プログラミングできる!並列・並行プログラミング
できる!並列・並行プログラミングPreferred Networks
 
並列プログラミング 入門!&おさらい!
並列プログラミング入門!&おさらい!並列プログラミング入門!&おさらい!
並列プログラミング 入門!&おさらい!道化師 堂華
 
2015 lodc&UDC ゴミ多言語変換用データ基盤
2015 lodc&UDC ゴミ多言語変換用データ基盤2015 lodc&UDC ゴミ多言語変換用データ基盤
2015 lodc&UDC ゴミ多言語変換用データ基盤Takuya Yamagata
 
Streaming data processing ライブラリの紹介 (主に Conduit)
Streaming data processing ライブラリの紹介 (主に Conduit)Streaming data processing ライブラリの紹介 (主に Conduit)
Streaming data processing ライブラリの紹介 (主に Conduit)krdlab
 
Session2:「グローバル化する情報処理」/伊藤敬彦
Session2:「グローバル化する情報処理」/伊藤敬彦Session2:「グローバル化する情報処理」/伊藤敬彦
Session2:「グローバル化する情報処理」/伊藤敬彦Preferred Networks
 

Viewers also liked (20)

Tcl/Tkクイック入門
Tcl/Tkクイック入門Tcl/Tkクイック入門
Tcl/Tkクイック入門
 
IdrisでWebアプリを書く
IdrisでWebアプリを書くIdrisでWebアプリを書く
IdrisでWebアプリを書く
 
Xpath in-lens
Xpath in-lensXpath in-lens
Xpath in-lens
 
手書きスライド
手書きスライド手書きスライド
手書きスライド
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISる
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門
 
開発者の方向けの Sql server(db) t sql 振り返り
開発者の方向けの Sql server(db) t sql 振り返り開発者の方向けの Sql server(db) t sql 振り返り
開発者の方向けの Sql server(db) t sql 振り返り
 
Sql world とは
Sql world とはSql world とは
Sql world とは
 
2016年を振り返って
2016年を振り返って2016年を振り返って
2016年を振り返って
 
できる!並列・並行プログラミング
できる!並列・並行プログラミングできる!並列・並行プログラミング
できる!並列・並行プログラミング
 
並列プログラミング 入門!&おさらい!
並列プログラミング入門!&おさらい!並列プログラミング入門!&おさらい!
並列プログラミング 入門!&おさらい!
 
Haskell超入門 Part.1
Haskell超入門 Part.1Haskell超入門 Part.1
Haskell超入門 Part.1
 
2015 lodc&UDC ゴミ多言語変換用データ基盤
2015 lodc&UDC ゴミ多言語変換用データ基盤2015 lodc&UDC ゴミ多言語変換用データ基盤
2015 lodc&UDC ゴミ多言語変換用データ基盤
 
Streaming data processing ライブラリの紹介 (主に Conduit)
Streaming data processing ライブラリの紹介 (主に Conduit)Streaming data processing ライブラリの紹介 (主に Conduit)
Streaming data processing ライブラリの紹介 (主に Conduit)
 
Ppl
PplPpl
Ppl
 
Digital Signature and PKI
Digital Signature and PKIDigital Signature and PKI
Digital Signature and PKI
 
Session2:「グローバル化する情報処理」/伊藤敬彦
Session2:「グローバル化する情報処理」/伊藤敬彦Session2:「グローバル化する情報処理」/伊藤敬彦
Session2:「グローバル化する情報処理」/伊藤敬彦
 
Icfp2009
Icfp2009Icfp2009
Icfp2009
 
Yesod勉強会
Yesod勉強会Yesod勉強会
Yesod勉強会
 
Monad tutorial
Monad tutorialMonad tutorial
Monad tutorial
 

Similar to 怪しいWindowsプログラミング

WindowsストアーアプリでSharpDXを動かしてみる
WindowsストアーアプリでSharpDXを動かしてみるWindowsストアーアプリでSharpDXを動かしてみる
WindowsストアーアプリでSharpDXを動かしてみるShinichiAoyagi
 
Cocos2d xをさらにさわってみよう!
Cocos2d xをさらにさわってみよう!Cocos2d xをさらにさわってみよう!
Cocos2d xをさらにさわってみよう!Tomoaki Shimizu
 
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクトEWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクトKiyoshi Sawada
 
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクトEWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクトKiyoshi Sawada
 
C++ lecture-1
C++ lecture-1C++ lecture-1
C++ lecture-1sunaemon
 
第142回Smalltalk勉強会 - PharoJSで作るWebアプリケーション
第142回Smalltalk勉強会 - PharoJSで作るWebアプリケーション第142回Smalltalk勉強会 - PharoJSで作るWebアプリケーション
第142回Smalltalk勉強会 - PharoJSで作るWebアプリケーションMasashi Umezawa
 
cocos2d-xとネイティブ間の連携
cocos2d-xとネイティブ間の連携cocos2d-xとネイティブ間の連携
cocos2d-xとネイティブ間の連携Tomoaki Shimizu
 
Unity C#3からC#6に向けて
Unity C#3からC#6に向けてUnity C#3からC#6に向けて
Unity C#3からC#6に向けてonotchi_
 
Halide による画像処理プログラミング入門
Halide による画像処理プログラミング入門Halide による画像処理プログラミング入門
Halide による画像処理プログラミング入門Fixstars Corporation
 
PF部2011年12月勉強会.androidsola
PF部2011年12月勉強会.androidsolaPF部2011年12月勉強会.androidsola
PF部2011年12月勉強会.androidsolaandroid sola
 
社内勉強会資料(Varnish Module)
社内勉強会資料(Varnish Module)社内勉強会資料(Varnish Module)
社内勉強会資料(Varnish Module)Iwana Chan
 
Media Art II 2013 第5回:openFrameworks Addonを使用する
Media Art II 2013 第5回:openFrameworks Addonを使用するMedia Art II 2013 第5回:openFrameworks Addonを使用する
Media Art II 2013 第5回:openFrameworks Addonを使用するAtsushi Tadokoro
 
Android Lecture #04 @PRO&BSC Inc.
Android Lecture #04 @PRO&BSC Inc.Android Lecture #04 @PRO&BSC Inc.
Android Lecture #04 @PRO&BSC Inc.Yuki Higuchi
 
“Symbolic bounds analysis of pointers, array indices, and accessed memory reg...
“Symbolic bounds analysis of pointers, array indices, and accessed memory reg...“Symbolic bounds analysis of pointers, array indices, and accessed memory reg...
“Symbolic bounds analysis of pointers, array indices, and accessed memory reg...Masahiro Sakai
 
Androidプログラミング初心者のためのゲームアプリ開発入門
Androidプログラミング初心者のためのゲームアプリ開発入門Androidプログラミング初心者のためのゲームアプリ開発入門
Androidプログラミング初心者のためのゲームアプリ開発入門Masahiko Mizuta
 
werkkzeug3のGUI実装
werkkzeug3のGUI実装werkkzeug3のGUI実装
werkkzeug3のGUI実装Hisanari Otsu
 
DTrace for biginners part(2)
DTrace for biginners part(2)DTrace for biginners part(2)
DTrace for biginners part(2)Shoji Haraguchi
 
ぱっと見でわかるC++11
ぱっと見でわかるC++11ぱっと見でわかるC++11
ぱっと見でわかるC++11えぴ 福田
 

Similar to 怪しいWindowsプログラミング (20)

WindowsストアーアプリでSharpDXを動かしてみる
WindowsストアーアプリでSharpDXを動かしてみるWindowsストアーアプリでSharpDXを動かしてみる
WindowsストアーアプリでSharpDXを動かしてみる
 
emc++ chapter32
emc++ chapter32emc++ chapter32
emc++ chapter32
 
Cocos2d xをさらにさわってみよう!
Cocos2d xをさらにさわってみよう!Cocos2d xをさらにさわってみよう!
Cocos2d xをさらにさわってみよう!
 
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクトEWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
 
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクトEWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
 
C++ lecture-1
C++ lecture-1C++ lecture-1
C++ lecture-1
 
第142回Smalltalk勉強会 - PharoJSで作るWebアプリケーション
第142回Smalltalk勉強会 - PharoJSで作るWebアプリケーション第142回Smalltalk勉強会 - PharoJSで作るWebアプリケーション
第142回Smalltalk勉強会 - PharoJSで作るWebアプリケーション
 
cocos2d-xとネイティブ間の連携
cocos2d-xとネイティブ間の連携cocos2d-xとネイティブ間の連携
cocos2d-xとネイティブ間の連携
 
Unity C#3からC#6に向けて
Unity C#3からC#6に向けてUnity C#3からC#6に向けて
Unity C#3からC#6に向けて
 
Halide による画像処理プログラミング入門
Halide による画像処理プログラミング入門Halide による画像処理プログラミング入門
Halide による画像処理プログラミング入門
 
PF部2011年12月勉強会.androidsola
PF部2011年12月勉強会.androidsolaPF部2011年12月勉強会.androidsola
PF部2011年12月勉強会.androidsola
 
社内勉強会資料(Varnish Module)
社内勉強会資料(Varnish Module)社内勉強会資料(Varnish Module)
社内勉強会資料(Varnish Module)
 
Media Art II 2013 第5回:openFrameworks Addonを使用する
Media Art II 2013 第5回:openFrameworks Addonを使用するMedia Art II 2013 第5回:openFrameworks Addonを使用する
Media Art II 2013 第5回:openFrameworks Addonを使用する
 
Android Lecture #04 @PRO&BSC Inc.
Android Lecture #04 @PRO&BSC Inc.Android Lecture #04 @PRO&BSC Inc.
Android Lecture #04 @PRO&BSC Inc.
 
“Symbolic bounds analysis of pointers, array indices, and accessed memory reg...
“Symbolic bounds analysis of pointers, array indices, and accessed memory reg...“Symbolic bounds analysis of pointers, array indices, and accessed memory reg...
“Symbolic bounds analysis of pointers, array indices, and accessed memory reg...
 
Androidプログラミング初心者のためのゲームアプリ開発入門
Androidプログラミング初心者のためのゲームアプリ開発入門Androidプログラミング初心者のためのゲームアプリ開発入門
Androidプログラミング初心者のためのゲームアプリ開発入門
 
werkkzeug3のGUI実装
werkkzeug3のGUI実装werkkzeug3のGUI実装
werkkzeug3のGUI実装
 
DTrace for biginners part(2)
DTrace for biginners part(2)DTrace for biginners part(2)
DTrace for biginners part(2)
 
ぱっと見でわかるC++11
ぱっと見でわかるC++11ぱっと見でわかるC++11
ぱっと見でわかるC++11
 
Hbstudy41 auto scaling
Hbstudy41 auto scalingHbstudy41 auto scaling
Hbstudy41 auto scaling
 

怪しいWindowsプログラミング

  • 2. 自己紹介 ● 隅須三郎(@nagoya313) ● C++初心者 ● Windows系男子 ● 名古屋出身/在住の3月13日生まれという わけではない
  • 3. 今日の内容 ● 適当に作ったプログラムを元ソースを弄ら ずに改造する ➔ Win32APIとDirect3D9製のC++プログラム ➔ 外部からの拡張は考慮せずに作成
  • 4. 元となるプログラムの概要 ● エントリポイント int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdLine, int cmdShow) { InitWindow(); InitDirect3D9(); ShowWindow(g_hWnd, cmdShow); return Loop(); }
  • 5. 元となるプログラムの概要 ● ウィンドウクラスの登録とウィンドウ作成 void InitWindow() { WNDCLASSEX wc; ZeroMemory(&wc, sizeof(WNDCLASSEX)); wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)); wc.lpszClassName = kClassName; RegisterClassEx(&wc); g_hWnd = CreateWindow(kClassName, L"やみなべ!", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr,nullptr,             GetModuleHandle(nullptr), nullptr); }
  • 6. 元となるプログラムの概要 ● Direct3D9の初期化 void InitDirect3D9() { g_pD3d9 = Direct3DCreate9(D3D_SDK_VERSION); D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; d3dpp.BackBufferWidth = 640; d3dpp.BackBufferHeight = 480; g_pD3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &g_pDevice); D3DXCreateTextureFromFile(g_pDevice, L"d3.png", &g_pTexture); }
  • 7. 元となるプログラムの概要 ● メッセージループ int Loop() { for (;;) { MSG msg; if (PeekMessage (&msg, nullptr, 0, 0, PM_NOREMOVE)) { auto ret = GetMessage (&msg, nullptr, 0, 0); if (!ret || ret == -1) { g_pD3d9->Release(); g_pDevice->Release(); return msg.wParam ; } TranslateMessage(&msg); DispatchMessage(&msg); } else { Update(); } } }
  • 8. 元となるプログラムの概要 ● 1Fでの処理(黒で消して画像を表示) struct VertexImage2D { float x; float y; float z; float rhw; float u; float v; }; void Update() { g_pDevice->BeginScene(); g_pDevice->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.f, 0); VertexImage2D vertex[4] = { {0.f, 0.f, 0.f, 1.f, 0.f, 0.f}, {162.f, 0.f, 0.f, 1.f, 1.f, 0.f}, {0.f, 309.f, 0.f, 1.f, 0.f, 1.f}, {162.f, 309.f, 0.f, 1.f, 1.f, 1.f} }; g_pDevice->SetTexture(0, g_pTexture); g_pDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); g_pDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertex, sizeof(vertex[0])); g_pDevice->EndScene(); g_pDevice->Present(nullptr, nullptr, nullptr, nullptr); }
  • 9. 元となるプログラムの概要 ● ウィンドウプロシージャ(×を押したら終了) LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { if (msg == WM_DESTROY) { PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, msg, wp, lp); }
  • 10. DLL(Dynamic Link Library) の裏話 ● Windowsだとexeがあるディレクトリに同名 のdllがあるとSystem32とかにあるものより も優先的に読み込まれる ➔ こっそり偽者を置いておけばプログラムが 偽者を勝手に読んでくれる
  • 11. d3d9.dllの偽物を作る ● d3d9.dllの偽者を置いておけば勝手にプロ グラムが読み込む ● 使われる関数がDirect3DCreate9だけなの で簡単に作れる ● プログラムが読み込む関数はいい加減に 作ったら残当する ➔ 関数名とか引数の数とか呼び出し規約と かはきっちりする必要がある
  • 12. d3d9.dllの偽物を作る ● VisualC++ 2010を想定 ● DLL、空のプロジェクトを作成
  • 13. d3d9.dllの偽物を作る ● d3d9.defを用意 ● エクスポートする関数名を列挙 ● プロジェクトプロパティ→構成プロパティ→ リンカ→入力→モジュール定義ファイルに d3d9.defを指定 LIBRARY d3d9 EXPORTS Direct3DCreate9 @4
  • 14. d3d9.dllの偽物を作る ● エントリポイント BOOL APIENTRY DllMain(HINSTANCE, DWORD reason, LPVOID) { return reason == DLL_PROCESS_ATTACH ? Init() : TRUE; }
  • 15. d3d9.dllの偽物を作る ● 本物のDirect3DCreate9を取得 BOOL Init() { // 本物のD3D9.dllがあるパスを取得 TCHAR strPathBuffer[kBufferMax]; GetSystemDirectory(strPathBuffer, kBufferMax); PathAppend(strPathBuffer, L"D3D9.DLL"); HMODULE hOriginalModule = LoadLibrary(strPathBuffer); if (!hOriginalModule) { return FALSE; } // 本物のDirect3DCreate9のアドレスを取得 g_pOriginalDirect3DCreate9 = reinterpret_cast<IDirect3D9 *(WINAPI *) (UINT)>(GetProcAddress(hOriginalModule, "Direct3DCreate9")); if (!g_pOriginalDirect3DCreate9) { return FALSE; } return TRUE; }
  • 16. d3d9.dllの偽物を作る ● 偽物のDirect3DCreate9を作る extern "C" { IDirect3D9 *WINAPI Direct3DCreate9(UINT SDKVersion) { return (*g_pOriginalDirect3DCreate9) (SDKVersion); } }
  • 17. d3d9.dllの偽物を作る ● 作ったdllを元のプログラムと同じディレクト リに置けば仕込みは完了
  • 18. 改造1:MessageDialogを仕込む ● Initの中にMessageBoxを仕込む BOOL Init() { MessageBox(nullptr, L"侵入!", L"", 0); // .. return TRUE; }
  • 19. 改造2:消去色を赤に ● IDirect3D9Device9::Clearを差し替える ● 第4引数を常に赤にして本物のClearに渡す
  • 20. Direct3DはC言語でも 開発出来ます? ● とはいいつつもクラスっぽい呼び出しが絡 むDirect3Dでの開発は純粋なC言語で出 来るの?
  • 21. Direct3DはC言語でも 開発出来ます ● Direct3D周りにヘッダを読む前に #define CINTERFACE を唱えるとDirect3Dが変身
  • 22. Direct3DはC言語でも 開発出来ます g_pDevice->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.f, 0); が g_pDevice->lVptbl->Clear(g_pDevice, 0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.f, 0); こうなる
  • 23. vtableみたいなの登場 ● Cインターフェイスの仮想函数テーブルのよ うなサムシングの函数ポインタを偽物に書 き換えれば差し替え達成
  • 24. IDirect3D9::CreateDevice を差し替え ● IDirect3DDevice9を製造する大元を叩く extern "C" { IDirect3D9 *WINAPI Direct3DCreate9(UINT SDKVersion) { IDirect3D9 *pD3d9 = (*g_pOriginalDirect3DCreate9) (SDKVersion); // 本物を退避 g_pOriginalCreateDevice = pD3d9->lpVtbl- >CreateDevice; // 偽物に書き換え pD3d9->lpVtbl->CreateDevice = MyCreateDevice; return pD3d9; } }
  • 25. IDirect3DDevice9::Clear を差し替え ● 偽CleateDevice内でClearを差し替え HRESULT WINAPI MyCreateDevice(引数省略... IDirect3DDevice9** ppReturnedDeviceInterface) { HRESULT ret = (*g_pOriginalCreateDevice)(引数省略..., ppReturnedDeviceInterface); if (SUCCEEDED(ret)) { // 本物を退避 g_pOriginalClear = (*ppReturnedDeviceInterface)->lpVtbl- >Clear; // 偽物に書き換え (*ppReturnedDeviceInterface)->lpVtbl->Clear = MyClear; } return ret; }
  • 26. 偽IDirect3DDevice9::Clear ● 常に赤を指定した本物を呼び出す HRESULT WINAPI MyClear(IDirect3DDevice9 *pDevice, DWORD Count, const D3DRECT *pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) { return (*g_pOriginalClear)(pDevice, Count, pRects, Flags, D3DCOLOR_XRGB(255, 0, 0), Z, Stencil); }
  • 27. 差し替える 偽IHogeHoge::Hogeの型 ● MSDNに乗っているものに呼び出し規約 WINAPIを付けて第一引数にIHogeHoge *を 加える函数ポインタ HRESULT Hoge(int, double); があったら HRESULT (WINAPI *Hoge)(IHogeHoge *, int, double); になる
  • 28. 実はセグる ● lpVtblがある場所はアクセス保護されてい る ➔ VirtualProtectを使って書き込み出来るよう にする必要がある
  • 29. CぷらーならRAIIだよね ● VirtualProtectをRAIIっぽく struct ScopedVirtualProtect { template <typename P> ScopedVirtualProtect(P p, DWORD dwNewProtext) : m_p(p), m_size(sizeof(*p)) { VirtualProtect(m_p, m_size, dwNewProtext, &m_oldProtect); } ~ScopedVirtualProtect() { VirtualProtect(m_p, m_size, m_oldProtect, &m_oldProtect); } private: ScopedVirtualProtect(const ScopedVirtualProtect &); ScopedVirtualProtect &operator =(const ScopedVirtualProtect &); LPVOID m_p; SIZE_T m_size; DWORD m_oldProtect; };
  • 30. アクセス権限書き換え ● 偽物に書き換える前に仕込む ScopedVirtualProtect protect(pD3d9->lpVtbl, PAGE_EXECUTE_WRITECOPY); pD3d9->lpVtbl->CreateDevice = MyCreateDevice; ScopedVirtualProtect protect((*ppReturnedDeviceInterface)->lpVtbl, PAGE_EXECUTE_WRITECOPY); (*ppReturnedDeviceInterface)->lpVtbl->Clear = MyClear;
  • 31. 改造3:ウィンドウサイズ 変更とEscキーでの終了 ● IDIrect3D9::CreateDeviceを差し替えたこと でフォーカスウィンドウハンドルが手に入る ➔ ウィンドウハンドルを使って色々出来る
  • 32. ウィンドウサイズ変更 ● 640*480に変えるついでにサイズ変更不可 なスタイルに変更 HRESULT WINAPI MyCreateDevice(引数省略.. HWND hFocusWindow, 引数省略..) { RECT rect = {0, 0, 640, 480}; // サイズ変更不可スタイル const DWORD kWinsowStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; // ウィンドウスタイル変更 SetWindowLong(hFocusWindow, GWL_STYLE, kWinsowStyle); // ウィンドウサイズ計算 AdjustWindowRect(&rect, kWinsowStyle, FALSE); // ウィンドウサイズ変更 SetWindowPos(hFocusWindow, nullptr, 0, 0, rect.right – rect.left, rect.bottom - rect.top, SWP_NOMOVE | SWP_NOZORDER); // .. return ret; }
  • 33. Escキーで終了処理を追加 ● ウィンドウプロシージャを置き換える HRESULT WINAPI MyCreateDevice(引数省略. HWND hFocusWindow, 引数省略.) { // .. // ウィンドウプロシージャ置き換え SetWindowLong(hFocusWindow, GWL_WNDPROC, reinterpret_cast<LONG>(&WndProc)); // .. return ret; }
  • 34. 新しいウィンドウプロシージャ ● Escキーを押したらウィンドウを破棄 LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { if (msg == WM_DESTROY) { PostQuitMessage(0); return 0; } // エスケープが押されたら窓を破棄 if (msg == WM_KEYDOWN) { if (wp == VK_ESCAPE) { DestroyWindow(hWnd); } return 0; } return DefWindowProc(hWnd, msg, wp, lp); }
  • 35. 改造4:読み込む画像 ファイル名を修正 ● 画像表示といいつつ何もでてない? ➔ ファイルの拡張子を間違って指定 (×bmp→○bmq)
  • 36. D3DXCreateTextureFromFile を乗っ取り ● ファイル名の拡張子を替える処理を加えた 偽者に差し替える ● 偽d3d9.dllは既にプロセスに侵入している
  • 37. インポートセクションの取得 ● DLL名とか函数名とかが入っている領域 ● 先頭には読み込むdllの数だけ IMAGE_IMPORT_DESCRIPTOR構造体が配 置 // ベースアドレスを取得 HMODULE hBase = GetModuleHandle(nullptr); DWORD dwSize; // IMAGE_IMPORT_DESCRIPTOR テーブルのアドレスの取得 PIMAGE_IMPORT_DESCRIPTOR imgDesc = static_cast<PIMAGE_IMPORT_DESCRIPTOR>( ImageDirectoryEntryToData( hBase, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &dwSize));
  • 38. d3dx9_xx.dllを探す ● D3DXCreateTextureFromFile函数が入って いるdllを探す // 最後のIMAGE_IMPORT_DESCRIPTORは0で埋められている while (imgDesc->Name) { // imgDesc->Nameはdll名までの相対オフセット const char * strModule = reinterpret_cast<char *>((reinterpret_cast<DWORD>(hBase) + imgDesc->Name)); // 使っているSDKに依存 if (!std::strcmp(strModule, "d3dx9_43.dll")) { break; } ++imgDesc; }
  • 39. D3DXCreateTextureFromFile を探す ● インポートアドレステーブルとインポート ネームテーブルを取得 // インポートアドレステーブル PIMAGE_THUNK_DATA pIAT = reinterpret_cast<PIMAGE_THUNK_DATA>( reinterpret_cast<DWORD>(hBase) + imgDesc->FirstThunk); // インポートネームテーブル PIMAGE_THUNK_DATA pINT = reinterpret_cast<PIMAGE_THUNK_DATA>( reinterpret_cast<DWORD>(hBase) + imgDesc- >OriginalFirstThunk);
  • 40. D3DXCreateTextureFromFile をフック ● D3DXCreateTextureFromFileを差し替え while (pIAT->u1.Function) { // 最上位が立ってたら名前じゃない if (!(pINT->u1.AddressOfData & 0x80000000)) { // 名前取得 PIMAGE_IMPORT_BY_NAME pImportName = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>( reinterpret_cast<DWORD>(hBase) + pINT->u1.AddressOfData); // D3DXCreateTextureFromFileかを比較 if (!std::strcmp(reinterpret_cast<char *>(pImportName->Name), "D3DXCreateTextureFromFileW")) { // 本物を退避 g_pOriginalD3DXCreateTextureFromFile = reinterpret_cast<decltype(g_pOriginalD3DXCreateTextureFromFile)>(pIAT- >u1.Function); // 偽物に書き換え scoped_virtual_protect protect(pIAT, PAGE_READWRITE); pIAT->u1.Function = reinterpret_cast<DWORD>(MyD3DXCreateTextureFromFile); break; } } ++pIAT; ++pINT; }
  • 41. 偽D3DXCreateTextureFromFile ● ファイル名の拡張子をbmqに差し替え HRESULT WINAPI MyD3DXCreateTextureFromFile(LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, LPDIRECT3DTEXTURE9 *ppTexture) { LPTSTR pTemp = static_cast<LPTSTR>(std::malloc(sizeof(*pTemp) * (lstrlen(pSrcFile) + 1))); lstrcpy(pTemp, pSrcFile); // 拡張子を差し替え PathRenameExtension(pTemp, L".bmq"); auto ret = (*g_pOriginalD3DXCreateTextureFromFile)(pDevice, pTemp, ppTexture); std::free(pTemp); return ret; }