Как я могу подключить функции Windows в C/С++?
Если у меня есть функция foo()
, что окна реализованы в kernel32.dll, и она всегда возвращает true, могу ли я иметь свою программу: "bar.exe" зацепить/объединить эту функцию Windows и заставить ее возвращать false для всех процессов вместо этого?
Итак, если мой svchost, например, вызывает foo()
, он вернет false вместо true. То же самое действие следует ожидать для всех других выполняемых в настоящее время процессов.
Если да, то как? Наверное, я ищу общесистемный крючок или что-то в этом роде.
Ответы
Ответ 1
Взгляните на Detours, он идеально подходит для такого рода вещей.
Для общесистемной перехвата прочитайте эту статью из MSDN.
Сначала создайте DLL, которая обрабатывает функции. В этом примере ниже перечислены функции отправки и приема сокетов.
#include <windows.h>
#include <detours.h>
#pragma comment( lib, "Ws2_32.lib" )
#pragma comment( lib, "detours.lib" )
#pragma comment( lib, "detoured.lib" )
int ( WINAPI *Real_Send )( SOCKET s, const char *buf, int len, int flags ) = send;
int ( WINAPI *Real_Recv )( SOCKET s, char *buf, int len, int flags ) = recv;
int WINAPI Mine_Send( SOCKET s, const char* buf, int len, int flags );
int WINAPI Mine_Recv( SOCKET s, char *buf, int len, int flags );
int WINAPI Mine_Send( SOCKET s, const char *buf, int len, int flags ) {
// .. do stuff ..
return Real_Send( s, buf, len, flags );
}
int WINAPI Mine_Recv( SOCKET s, char *buf, int len, int flags ) {
// .. do stuff ..
return Real_Recv( s, buf, len, flags );
}
BOOL WINAPI DllMain( HINSTANCE, DWORD dwReason, LPVOID ) {
switch ( dwReason ) {
case DLL_PROCESS_ATTACH:
DetourTransactionBegin();
DetourUpdateThread( GetCurrentThread() );
DetourAttach( &(PVOID &)Real_Send, Mine_Send );
DetourAttach( &(PVOID &)Real_Recv, Mine_Recv );
DetourTransactionCommit();
break;
case DLL_PROCESS_DETACH:
DetourTransactionBegin();
DetourUpdateThread( GetCurrentThread() );
DetourDetach( &(PVOID &)Real_Send, Mine_Send );
DetourDetach( &(PVOID &)Real_Recv, Mine_Recv );
DetourTransactionCommit();
break;
}
return TRUE;
}
Затем создайте программу для вставки DLL в целевое приложение.
#include <cstdio>
#include <windows.h>
#include <tlhelp32.h>
void EnableDebugPriv() {
HANDLE hToken;
LUID luid;
TOKEN_PRIVILEGES tkp;
OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken );
LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &luid );
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = luid;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges( hToken, false, &tkp, sizeof( tkp ), NULL, NULL );
CloseHandle( hToken );
}
int main( int, char *[] ) {
PROCESSENTRY32 entry;
entry.dwSize = sizeof( PROCESSENTRY32 );
HANDLE snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, NULL );
if ( Process32First( snapshot, &entry ) == TRUE ) {
while ( Process32Next( snapshot, &entry ) == TRUE ) {
if ( stricmp( entry.szExeFile, "target.exe" ) == 0 ) {
EnableDebugPriv();
char dirPath[MAX_PATH];
char fullPath[MAX_PATH];
GetCurrentDirectory( MAX_PATH, dirPath );
sprintf_s( fullPath, MAX_PATH, "%s\\DllToInject.dll", dirPath );
HANDLE hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, entry.th32ProcessID );
LPVOID libAddr = (LPVOID)GetProcAddress( GetModuleHandle( "kernel32.dll" ), "LoadLibraryA" );
LPVOID llParam = (LPVOID)VirtualAllocEx( hProcess, NULL, strlen( fullPath ), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( hProcess, llParam, fullPath, strlen( fullPath ), NULL );
CreateRemoteThread( hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)libAddr, llParam, NULL, NULL );
CloseHandle( hProcess );
}
}
}
CloseHandle( snapshot );
return 0;
}
Этого должно быть более чем достаточно, чтобы вы начали!
Ответ 2
EASYHOOK http://www.codeplex.com/easyhook
Доминировать все вышеупомянутые методы в простоте, гибкости и функциональности.
Это не обсуждалось ранее в процессах Hook. Я прочитал весь лист этой темы и с абсолютным сертификатом, EASYHOOK значительно превосходит. Независимо от того, используете ли вы C, С++, CLR, что угодно.
Я немного вставлю с домашней страницы codeplex, чтобы обеспечить достаточную оплату omage.
Ниже приведен неполный список функций:
- Так называемый "барьер блокировки резьбы" избавится от многих основных проблем при подключении неизвестных API; эта технология уникальна для EasyHook.
- Вы можете написать обработчики управляемых крючков для неуправляемых API-интерфейсов
- Вы можете использовать все удобные управляемые коды, например NET Remoting, WPF и WCF, например
- Документированный, чистый неуправляемый API-интерфейс для подключения
- Поддержка 32- и 64-битного режима ядра (также проверьте мой драйвер PatchGuard 3 обхода, который можно найти в списке выпусков)
- В целевом объекте не осталось ресурсов или утечек памяти.
- Экспериментальный механизм инъекций стелса, который не привлечет внимания ни к одному из существующих AV-программ.
- EasyHook32.dll и EasyHook64.dll являются чистыми неуправляемыми модулями и могут использоваться без какой-либо установленной инфраструктуры .NET!
- Все крючки устанавливаются и автоматически удаляются стабильным образом.
- Поддержка Windows Vista с пакетом обновления 1 (SP1) и Windows Server 2008 с пакетом обновления 1 (SP1) x64 с использованием полностью недокументированных API-интерфейсов, позволяющих подключаться к любому сеансу терминала.
- Управляемая/Неуправляемая трассировка стека модулей внутри обработчика крюка
- Получить управляемый/неуправляемый модуль вызова внутри обработчика привязки
- Создавать собственные трассировки стека внутри обработчика крюка
- Вы сможете писать библиотеки инъекций и процессы хоста, скомпилированные для AnyCPU, что позволит вам вставлять ваш код в 32- и 64-битные процессы из 64- и 32-битных процессов, используя ту же самую сборку во всех случаев.
- EasyHook поддерживает RIP-относительное перемещение адреса для 64-битных целей.
- Не требуется распаковка/установка.
- Распространяемый компонент Visual Studio не требуется.
Я рад, что мой проститутка по-прежнему знает несколько трюков в сравнении, что заставляет меня держать их вокруг. Но, конечно, когда вам нужен КРЮК, 99 раз 100, EASYHOOK'r выведет вас туда быстрее. И он довольно активно поддерживается.
Ответ 3
Пожалуйста, дайте более подробную информацию о функции, которую вы хотите подключить! Существует несколько способов получить свой собственный код, вызываемый в таком случае, например:
-
Вы можете создать поддельную DLL с тем же именем, что и DLL, которая содержит функцию, которую вы хотите подключить (и скопировать ее в папку foo.exe
). Эта библиотека будет выставлять те же функции, что и исходная DLL. Каждая открытая функция просто обходит вызов исходной DLL, за исключением функции, которую вы хотите подключить.
-
Вы можете изменить таблицу указателей функций во время выполнения, например, с помощью (коммерческого) пакета Detour, упомянутого в "кухне". Тем не менее, сделать такую привязку можно легко сделать самостоятельно, см. эту статью, чтобы узнать, как.
-
Вы можете узнать, где определенная функция вызывается в foo.exe
, и просто заменить код сборки, который вызывает функцию с кодом, который возвращает true
". В основном, вы исправляете" foo.exe
".
-
Для определенных функций Windows предлагает автоматическое переключение, например. для событий клавиш и мыши. Для этого проверьте функцию SetWindowsHook.
Ответ 4
Это зависит от версии Windows, на которую вы хотите настроить таргетинг. Тем не менее, если вы играете в Pre-Vista, вы можете просто использовать SetWindowsHookEx для вставки вашей DLL в каждый запущенный процесс. Затем вашей DLL необходимо будет подключить соответствующую функцию с помощью Detours или аналогичного.
Ответ 5
Если вы пишете свой крючок в сборке и не используете Detours (по какой-либо причине), вам нужна некоторая ключевая информация о сохранении FALSE:
- Win32, установите EAX в 0
- Win64, установите RAX на 0
Вам нужно установить EAX или RAX (в зависимости от платформы) на ноль, поскольку последнее, что выполняет функция, которую вы подключаете. Это приведет к тому, что вызывающий код получит 0 в качестве возвращаемого значения (при условии, что они возвращают значение типа int или указателя).