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

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

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

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

DLL

DLL(Dynamic Link Library)とは、他のモジュールからも使用する事が出来る、関数とデータが格納されているモジュールのことです。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

API

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

Q&A

2回答

2270閲覧

Detours hookを用いてWinExec関数をhookする方法

sitsumon_jirou

総合スコア5

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

DLL

DLL(Dynamic Link Library)とは、他のモジュールからも使用する事が出来る、関数とデータが格納されているモジュールのことです。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

API

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

0グッド

0クリップ

投稿2021/05/11 07:52

編集2021/05/11 07:54

前提・実現したいこと

Windows APIのWinExec関数を用いたプロセスの起動を捕捉したいと思い,Detoursを用いてWinExec関数をhookしたいと考えました.
しかし,WinExec関数をhookしようとするとエラーが出てきます.
またDetours hook自体が動くか確認用に実装したMessageBoxW関数は正常にhookできます.

発生している問題・エラーメッセージ

Run-Time Check Failure #0 - The value of ESP was no properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

該当のソースコード

プログラムの構成は「コードを注入するファイル(detours_hook_1113.exe)」と「Detoursを使用した注入されるdllファイル(Dll1.dll)」です.

c++

1#include <Windows.h> 2#include <tchar.h> 3#include <tlhelp32.h> 4#include <stdio.h> 5 6 7#define TARGET_EXE "APIapp1.exe"//対象プロセス 8#define DLL_FILE "Dll1.dll" 9#define MY_PROCESS "detours_hook_1113.exe" 10 11 12 13int APIlog() { 14 //WCHAR* success_procName[1024]; 全体フック用 15 //WCHAR* fault_procName[1024]; 全体フック用 16 int success_num = 0; 17 int fault_num = 0; 18 //get dll path 19 TCHAR dllPath[256]; 20 GetModuleFileName(NULL, dllPath, sizeof(dllPath)); 21 int dllPathLen = (lstrlen(dllPath) + 1) * sizeof(TCHAR); 22 23 _tcscpy_s(_tcsrchr(dllPath, _T('\')) + 1, dllPathLen, _T(DLL_FILE)); 24 25 DWORD targetProcId = -1; //target process id 26 27 //search target process 28 HANDLE hSnapShot; 29 if ((hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) == INVALID_HANDLE_VALUE) { 30 //CreateToolhelp32Snapshot Error 31 MessageBox(NULL, _T("CreateToolhelp32Snapshot"), _T("Error"), MB_OK); 32 return -1; 33 } 34 35 PROCESSENTRY32 pEntry; 36 pEntry.dwSize = sizeof(pEntry); 37 BOOL result = Process32First(hSnapShot, &pEntry); 38 39 40 41 ////////////////対象のみ////////////////////// 42 while (result) { 43 if (lstrcmp(_T(TARGET_EXE), pEntry.szExeFile) == 0) { 44 targetProcId = pEntry.th32ProcessID; 45 break; 46 } 47 result = Process32Next(hSnapShot, &pEntry); 48 } 49 50 if (targetProcId == -1) { 51 MessageBox(NULL, _T("Process Not Found."), _T("Error"), MB_OK); 52 return -1; 53 } 54 55 //open target process 56 HANDLE hTargetProc; 57 if ((hTargetProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetProcId)) == NULL) { 58 //OpenProcess Error 59 MessageBox(NULL, _T("OpenProcess"), _T("Error"), MB_OK); 60 return -1; 61 } 62 63 //VirtualAlloc 64 PWSTR memAddr; 65 if ((memAddr = (PWSTR)VirtualAllocEx(hTargetProc, NULL, dllPathLen, MEM_COMMIT, PAGE_READWRITE)) == NULL) { 66 //VirtualAllocEX Error 67 MessageBox(NULL, _T("VirtualAllocEx"), _T("Error"), MB_OK); 68 return -1; 69 } 70 71 //WriteProcessMemory 72 if (WriteProcessMemory(hTargetProc, memAddr, (PVOID)dllPath, dllPathLen, NULL) == 0) { 73 //WriteProcessMemory Error 74 MessageBox(NULL, _T("WriteProcessMemory"), _T("Error"), MB_OK); 75 return -1; 76 } 77 78 FARPROC LoadLibFunc; 79 if ((LoadLibFunc = GetProcAddress(GetModuleHandle(_T("Kernel32")), "LoadLibraryW")) == NULL) { 80 //GetProcAddress Error 81 MessageBox(NULL, _T("LoadLibraryW_GetProcAddress"), _T("Error"), MB_OK); 82 return -1; 83 } 84 85 //CreateRemoteThread 86 HANDLE hThread; 87 if ((hThread = CreateRemoteThread(hTargetProc, NULL, 0, (PTHREAD_START_ROUTINE)LoadLibFunc, memAddr, 0, NULL)) == NULL) { 88 //CreateRemoteThread Error 89 MessageBox(NULL, _T("CreateRemoteThread"), _T("Error"), MB_OK); 90 return -1; 91 } 92 93 WaitForSingleObject(hThread, INFINITE); 94 //////////////end/////////////////////////////////////// 95 96 printf("Success1\n"); 97 printf("キーを押すとアンロード\n"); 98 getchar(); 99 FARPROC FreeLibFunc; 100 if ((FreeLibFunc = GetProcAddress(GetModuleHandle(_T("Kernel32")), "FreeLibrary")) == NULL) { 101 //GetProcAddress Error 102 MessageBox(NULL, _T("FreeLibrary_GetProcAddress"), _T("Error"), MB_OK); 103 return -1; 104 } 105 106 WaitForSingleObject(hThread, INFINITE); 107 108 printf("Success2\n"); 109 getchar(); 110 CloseHandle(hSnapShot); 111 return 0; 112} 113//////////////////////APIend/////////////////////////////////////////// 114 115int main(void) 116{ 117 APIlog(); 118}

c++

1 2#include <windows.h> 3#include <tchar.h>//_Tマクロの設定 4#include <dbghelp.h>//デバッグのやつ? 5#include <detours.h>//detours hookのやつ 6#include<stdio.h> 7#include <winternl.h>//nt系の話? 8#include <psapi.h>//getmodulename() 9#include<fstream>//出力系 10#include<iostream>//出力系? 11#include <time.h>//時刻 12//#include <string> 13 14 15//#include <stdlib.h> 16//#include <locale.h> 17 18#include "header.h" 19#include <tlhelp32.h> 20 21#pragma comment(lib,"ntdll.lib") 22#pragma comment(lib, "detours.lib") 23 24 25const char* logfilename = "C:\logfile.txt"//ログファイル名 26 27bool Hookfunc_flag = FALSE; 28using Type1 = decltype(MessageBoxW); 29Type1* PureMessageBoxW = &MessageBoxW; 30using Type2 = decltype(WinExec); 31Type2* PureWinExec = &WinExec; 32 33 34///////////////実装されているAPIリスト/////////////////////////////////////////////////// 35int WINAPI HookMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType); 36UINT HookWinExec(LPCSTR lpCmdLine,UINT uCmdShow); 37//////////////////////////////////////////////////////////////////////////////////////////////////////////// 38 39BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) 40{ 41 BOOL bResult = FALSE; 42 43 switch (ul_reason_for_call) 44 { 45 case DLL_PROCESS_ATTACH: 46 { 47 DetourRestoreAfterWith(); 48 DetourTransactionBegin(); 49 DetourUpdateThread(GetCurrentThread()); 50 DetourAttach(&(PVOID&)PureMessageBoxW, HookMessageBoxW); 51 DetourAttach(&(PVOID&)PureWinExec, HookWinExec); 52 DetourTransactionCommit(); 53 printf("ATTACH"); 54 getchar(); 55 } 56 57 break; 58 59 case DLL_PROCESS_DETACH: 60 { 61 DetourTransactionBegin(); 62 DetourUpdateThread(GetCurrentThread()); 63 DetourDetach(&(PVOID&)PureMessageBoxW, HookMessageBoxW); 64 DetourDetach(&(PVOID&)PureWinExec, HookWinExec); 65 DetourTransactionCommit(); 66 printf("DETTACH"); 67 getchar(); 68 } 69 break; 70 71 default: 72 break; 73 } 74 return TRUE; 75} 76 77 78/////////////////////フック関数群//////////////////////////////////// 79///////////////////messageboxW-begin//////////////////////////////////// 80int WINAPI HookMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) 81{ 82 if (Hookfunc_flag) { 83 return PureMessageBoxW(hWnd, lpText, lpCaption, uType); 84 } 85 Hookfunc_flag = TRUE; 86 87 printf("mesW_dbg\n"); 88 89 TCHAR procName[MAX_PATH] = TEXT("<unknown>"); 90 GetModuleBaseName(GetCurrentProcess(), 0, procName, sizeof(procName) / sizeof(TCHAR)); 91 time_t timer; 92 struct tm local_time; 93 timer = time(NULL); 94 localtime_s(&local_time, &timer); 95 96 std::wofstream outputfile(logfilename, std::ios::app); 97 outputfile << local_time.tm_year + 1900; 98 outputfile << "/"; 99 outputfile << local_time.tm_mon + 1; 100 outputfile << "/"; 101 outputfile << local_time.tm_mday; 102 outputfile << " "; 103 outputfile << local_time.tm_hour; 104 outputfile << ":"; 105 outputfile << local_time.tm_min; 106 outputfile << ":"; 107 outputfile << local_time.tm_sec; 108 outputfile << " "; 109 outputfile << procName; 110 outputfile << "->MessageBoxW:"; 111 outputfile << lpText; 112 outputfile << "\n"; 113 outputfile.close(); 114 Hookfunc_flag = FALSE; 115 return PureMessageBoxW(NULL, L"hook_W", L"hook_W", MB_OK); 116} 117/////////////messageboxW-end//////////////////////////////////// 118 119////////////WinExec//////////////////////////// 120UINT HookWinExec( 121 LPCSTR lpCmdLine, 122 UINT uCmdShow 123) 124{ 125 if (Hookfunc_flag) { 126 return PureWinExec( 127 lpCmdLine, 128 uCmdShow 129 ); 130 } 131 Hookfunc_flag = TRUE; 132 133 printf("win_dbg\n"); 134 135 TCHAR procName[MAX_PATH] = TEXT("<unknown>"); 136 GetModuleBaseName(GetCurrentProcess(), 0, procName, sizeof(procName) / sizeof(TCHAR)); 137 printf("ProcessName:%ws",procName); 138 time_t timer; 139 struct tm local_time; 140 timer = time(NULL); 141 localtime_s(&local_time, &timer); 142 143 std::wofstream outputfile(logfilename, std::ios::app); 144 outputfile << local_time.tm_year + 1900; 145 outputfile << "/"; 146 outputfile << local_time.tm_mon + 1; 147 outputfile << "/"; 148 outputfile << local_time.tm_mday; 149 outputfile << " "; 150 outputfile << local_time.tm_hour; 151 outputfile << ":"; 152 outputfile << local_time.tm_min; 153 outputfile << ":"; 154 outputfile << local_time.tm_sec; 155 outputfile << " "; 156 outputfile << procName; 157 outputfile << "->WinExec->"; 158 outputfile << lpCmdLine; 159 160 outputfile << "\n"; 161 outputfile.close(); 162 Hookfunc_flag = FALSE; 163 return PureWinExec(lpCmdLine, uCmdShow); 164} 165/////////////WinExec-end////////////////////////////////////

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

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

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

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

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

guest

回答2

0

CallingConventionがちがうからでしょこれ。
MSDNのWinExecから引き写してきたからとおもいますけど、WinExecがcdeclなわけないでしょ。
SDKのヘッダ(WinBase.h)を見れば、WINAPIとちゃんと書いてあります。

C++

1WINBASEAPI 2UINT 3WINAPI 4WinExec( 5 _In_ LPCSTR lpCmdLine, 6 _In_ UINT uCmdShow 7 );

投稿2021/06/27 05:41

matukeso

総合スコア1590

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

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

sitsumon_jirou

2021/06/28 07:53

回答ありがとうございます. 呼び出し規約についての知識がなかったので助かりました.
guest

0

Windows APIのWinExec関数を用いたプロセスの起動を捕捉したいと思い,
Detoursを用いてWinExec関数をhookしたいと考えました.

「プロセスの起動を捕捉したい」のであれば、User Mode 側のプログラムだけでは無理です。
Process の起動と終了を監視する、PsSetCreateProcessNotifyRoutineEx() 等のカーネル サービス関数を利用した、Kernel Mode 側の Driver を別途開発する必要があります。

投稿2021/05/12 01:58

Bego

総合スコア69

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

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

sitsumon_jirou

2021/05/12 05:19 編集

回答ありがとうございます. 続けての質問で恐縮なのですが,プロセスを起動するAPI(WinExec,CreateProcessなど)のHookはKernel Mode Driverでなければ不可能ということでしょうか?
Bego

2021/05/12 05:43

> プロセスを起動するAPI(WinExec,CreateProcessなど)のHookは > Kernel Mode Driverでなければ不可能ということでしょうか? マイクロソフトの公式ドキュメント、ちゃんと読んでますか? -------------------------- WinExec function (winbase.h) https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-winexec Note This function is provided only for compatibility with 16-bit Windows. Applications should use the CreateProcess function. -------------------------- CreateProcess 系 API (CreateProcessA, CreateProcessAsUserA, etc.) の Hook は一応可能ですが、DLL Injection 可能な Process に限定されます。 Session 0 で動作する Service Process に対しては DLL Injection は出来ないので、それら Process に対する API Hook も無理。 すべての Process の起動を監視したいのであれば、Kernel Mode 側の Driver を別途開発する必要がある、ということです。
sitsumon_jirou

2021/05/12 06:55

全てのプロセスを監視したいわけではないため,WinExecの捕捉をできればよいのですが,質問に書かれているようなエラーが出てしまい,困っているという状況です.
sitsumon_jirou

2021/05/13 06:19

このエラーはアプリケーションから呼び出すべきではないWinExecを呼び出しているがゆえに出てしまっているということでしょうか?
Bego

2021/05/13 07:09

-------------------------- WinExec function (winbase.h) https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-winexec Note This function is provided only for compatibility with 16-bit Windows. Applications should use the CreateProcess function. 注釈 この関数は 16 ビット Windows との互換性のためだけに提供されています。 アプリケーションは CreateProcess 関数を使用してください。 --------------------------
sitsumon_jirou

2021/05/13 07:23

公式ドキュメントを読みましたが,このエラーとドキュメントの文章の関係性が理解できません.すいません.
Bego

2021/05/13 07:46

では逆に質問ですが、ドキュメントに「CreateProcess を使え」と明記されているのに、32ビット/64ビット Windows ではサポートされていない "WinExec" に固執するのはなぜですか?
sitsumon_jirou

2021/05/13 08:01

フックのターゲットとしているテストファイルに最初CreateProcessの実装を試みたのですが,CreateProcessそのものがうまく実装できませんでした.そこで次にWinExecで試していたところ,テストファイルのWinExecそのもはうまく動いたため,これをフックしようと思いました. そこでこのエラーが出てきてしまい対処がわからなかったために質問しました.
Bego

2021/05/13 08:52 編集

だったら、CreateProcess での実装を見直すべだと思います。 そもそも 32ビット/64ビット Windows ではサポートされていない "WinExec" で 「うまく動いた」という、その根拠が私には全く理解できませんでした。 ドキュメントに、「WinExec 関数は、16 ビット Windows との互換性のためだけに提供されている。CreateProcess 関数を使え」と明記されているのに、「WinExecそのもはうまく動いた」とする根拠は何ですか?
sitsumon_jirou

2021/05/14 04:22 編集

CreateProcessの実装を見直そうと思います. WinExecでnotepadを起動するだけのコードでnotepadが起動したのでそれをうまくいっていると判断してしまいました. またあのエラーメッセージの原因はそれが理由ということですか?
Bego

2021/05/14 05:33

> またあのエラーメッセージの原因はそれが理由ということですか? run-time error なので、デバッグしないと確実なことは言えない。 エラー発生時のプロセス ダンプを採取し、そのダンプ ファイルと、exe, dll のシンボル ファイルをどっかにアップロードしてもらえるなら、私の方でも確認はできます。 ちなみに、Windows 10 の kernel32.dll の中を確認したら一応 WinExec API は存在していましたが、WinExec 内部から CreateProcessA をコールしているだけです。 なので、CreateProcessA の代わりに WinExec を Hook するというのは、全く無意味。
sitsumon_jirou

2021/05/14 05:43

ありがとうございます. Createprocessで実装してみようと思います.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問