質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

1回答

1307閲覧

APIを使用したプロセスを特定したい

sitsumon_jirou

総合スコア5

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

1クリップ

投稿2020/10/26 05:08

どのプロセスがユーザが指定したAPIを使用したのか確認を行う,APIの使用履歴を確認できるツールを探しています.

API Monitorが目的に近いようですが,API Monitorは指定したプロセスがどのAPIを使用しているかということしかわかりません.

普通にパソコンを使っているときの情報を取得したいため,特別な作業をしていない時のAPI使用履歴を知りたいです.

現在はツールが見つからないため,c++で自作していますがうまくいってないです.
自作のコードでは対象のAPIのIATを書き換えてグローバルにフックしようとしています.
以下にコードを記します.このコードの改善方法がわかる方がいたら訂正していただきたいです.

dll

1fp_MessageBoxW MessageBoxWPtr = NULL; 2TCHAR fileNameBuf[MAX_PATH]=("not complete"); 3 4//書き換える関数(MessageBoxW)の定義 5int 6WINAPI 7HookedMessageBoxW( 8 HWND hWnd, 9 LPCSTR lpText, 10 LPCSTR lpCaption, 11 UINT uType 12) 13{ 14 OutputDebugString(TEXT("HookedMessageBoxW!\n")); //デバックビューに出力 15 return MessageBoxWPtr(hWnd,lpText,lpCaption,uType); //元の関数を呼び出す 16} 17 18 19 20 21void APIHook() { 22 if (GetModuleFileName(GetModuleHandle(NULL), fileNameBuf, MAX_PATH) > 0) { 23 MessageBoxWPtr = (fp_MessageBoxW)RewriteFunction("User32.dll", "MessageBoxW", HookedMessageBoxW); 24 } 25 } 26} 27 28 29BOOL APIENTRY DllMain( HMODULE hModule, 30 DWORD dwReason, 31 LPVOID lpReserved 32 ) 33{ 34 if (dwReason == DLL_PROCESS_ATTACH) 35 { 36 DisableThreadLibraryCalls(hModule); 37 APIHook(); 38 } 39 return TRUE; 40}

rewrite

1void* RewriteFunctionImp(const char* szRewriteModuleName, const char* szRewriteFunctionName, void* pRewriteFunctionPointer) 2{ 3 for (int i = 0; i < 2; i++) { 4 // ベースアドレス 5 intptr_t pBase = 0; 6 if (i == 0) { 7 if (szRewriteModuleName) { 8 pBase = (intptr_t)::GetModuleHandleA(szRewriteModuleName); 9 } 10 } 11 else if (i == 1) { 12 pBase = (intptr_t)GetModuleHandle(NULL); 13 } 14 if (!pBase)continue; 15 16 // イメージ列挙 17 ULONG ulSize; 18 PIMAGE_IMPORT_DESCRIPTOR pImgDesc = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData((HMODULE)pBase, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize); 19 for (; pImgDesc->Name; pImgDesc++) { 20 21 const char* szModuleName = (char*)(intptr_t)(pBase + pImgDesc->Name); 22 23 PIMAGE_THUNK_DATA pFirstThunk = (PIMAGE_THUNK_DATA)(intptr_t)(pBase + pImgDesc->FirstThunk); 24 PIMAGE_THUNK_DATA pOrgFirstThunk = (PIMAGE_THUNK_DATA)(intptr_t)(pBase + pImgDesc->OriginalFirstThunk); 25 // 関数列挙 26 27 for (; pFirstThunk->u1.Function; pFirstThunk++, pOrgFirstThunk++) { 28 29 if (IMAGE_SNAP_BY_ORDINAL(pOrgFirstThunk->u1.Ordinal))continue; 30 PIMAGE_IMPORT_BY_NAME pImportName = (PIMAGE_IMPORT_BY_NAME)(intptr_t)(pBase + (intptr_t)pOrgFirstThunk->u1.AddressOfData); 31 if (!szRewriteFunctionName) { 32 // 表示のみ 33 printf("Module:%s Hint:%d, Name:%s\n", szModuleName, pImportName->Hint, pImportName->Name); 34 } 35 else { 36 37 // 書き換え判定 38 if (stricmp((const char*)pImportName->Name, szRewriteFunctionName) != 0)continue; 39 40 // 保護状態変更 41 DWORD dwOldProtect; 42 if (!VirtualProtect(&pFirstThunk->u1.Function, sizeof(pFirstThunk->u1.Function), PAGE_READWRITE, &dwOldProtect)) 43 return NULL; // エラー 44 //OutputDebugString(pImportName->Name); 45 MessageBoxW(NULL, wc, wc, MB_OK); 46 // 書き換え 47 void* pOrgFunc = (void*)(intptr_t)pFirstThunk->u1.Function; // 元のアドレスを保存しておく 48 WriteProcessMemory(GetCurrentProcess(), &pFirstThunk->u1.Function, &pRewriteFunctionPointer, sizeof(pFirstThunk->u1.Function), NULL); 49 pFirstThunk->u1.Function = (intptr_t)pRewriteFunctionPointer; 50 51 // 保護状態戻し 52 VirtualProtect(&pFirstThunk->u1.Function, sizeof(pFirstThunk->u1.Function), dwOldProtect, &dwOldProtect); 53 return pOrgFunc; // 元のアドレスを返す 54 } 55 } 56 } 57 } 58 return NULL; 59} 60

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

まず一点、

cpp

1return pOrgFunc; // 元のアドレスを返す

この部分で return をしてしまっているので、一つのthunkを書き換えた時点で RewriteFunctionImp の処理が終了してしまうように見えます。実際は、各モジュールごとにIATが存在するため、例えばUser32.dllのMessageBoxWを書き換えようとしてこの関数を呼んだ場合、書き換えが行われるのはUser32.dllのIATだけであり、例えば実行ファイル本体のIATは書き換えが行われず、Hookを経由することもなくなってしまうのではないでしょうか。

次に、

cpp

1for (int i = 0; i < 2; i++) {

このループでは szRewriteModuleName に渡された名前のモジュールと、実行ファイル本体だけを対象にしていますが、実際は実行ファイルの読み込んだ全てのモジュールから監視したいAPIが呼ばれている可能性があり、他のモジュール内部からのAPI呼び出しはそのモジュールのIATを経由するはずです。
そのため、全てのAPI呼び出しをフックするには、CreateToolhelp32Snapshotなどを利用して読み込まれた全モジュールを列挙し、それぞれのIATを書き換える必要があります。

投稿2020/10/26 13:49

kazatsuyu

総合スコア158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sitsumon_jirou

2020/10/28 04:50

IATの仕組みについて理解が足りてませんでした. もっと勉強しようと思います. 回答ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問