Я экспериментирую с загрузкой функций из DLL во время выполнения в Windows. Я попытался сделать программу, которая будет печатать свои собственные модули, на основе этого: https://learn.microsoft.com/en-us/windows/win32/psapi/enumerating-all-modules-for-a-process.
Мне нужны две функции, чтобы делать то, что я хочу: EnumProcessModules и GetModuleFileNameExA. Мне удалось получить их оба из psapi.dll во время выполнения, однако GetModuleFileNameExA просто не работает должным образом, и я не могу сказать, почему
это функциональный скрипт, который я написал:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <psapi.h>
typedef DWORD (__cdecl *EnumModules)(HANDLE hprocess, HMODULE *moduleHandles, DWORD cb, LPDWORD lpcNeeded);
typedef DWORD (__cdecl *GetModuleName)(HANDLE hprocess, HMODULE hmodule, LPSTR name, DWORD size);
void ErrorMessage(const char *message){
fprintf(stderr, message);
exit(EXIT_FAILURE);
}
int PrintModules( HANDLE pHandle )
{
HMODULE hMods[1024];
DWORD cbNeeded;
unsigned int i;
if (NULL == pHandle)
return EXIT_FAILURE;
// Loads the lib
HMODULE psapiLib = LoadLibrary("C:\\Windows\\SysWOW64\\psapi.dll");
if (! psapiLib) ErrorMessage("Error loading psapi.dll\n");
// Get the functions we need from the lib
EnumModules getModules = (EnumModules)GetProcAddress(psapiLib, "EnumProcessModules");
GetModuleName getModuleName = (GetModuleName)GetProcAddress(psapiLib, "GetModuleFileNameExA");
if (!getModules) ErrorMessage("Error finding EnumProcessModules from psapi.dll\n");
if (!getModuleName) ErrorMessage("Error finding GetModuleFileNameExA from psapi.dll\n");
// Get a list of all the modules in this process.
if ( getModules(pHandle, hMods, sizeof(hMods), &cbNeeded))
{
for ( i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ )
{
LPSTR szModName;
szModName = malloc(1024 * sizeof(LPSTR));
// Get the full path to the module's file.
// change GetModuleFileNameExA with getModuleName to see the error
if ( GetModuleFileNameExA( pHandle, hMods[i], szModName, 1024 * sizeof(char))){
// Print the module name and handle value.
printf(("\t%s (0x%08X)\n"), szModName, hMods[i] );
}
free(szModName);
}
}
return 0;
}
int main( void )
{
HANDLE myHandle = GetCurrentProcess();
PrintModules(myHandle);
CloseHandle(myHandle);
return 0;
}
Если я изменю эту часть
if ( GetModuleFileNameExA( pHandle, hMods[i], szModName, 1024 * sizeof(char))){
// Print the module name and handle value.
printf(("\t%s (0x%08X)\n"), szModName, hMods[i] );
}
к этому
if ( getModuleName( pHandle, hMods[i], szModName, 1024 * sizeof(char))){
// Print the module name and handle value.
printf(("\t%s (0x%08X)\n"), szModName, hMods[i] );
}
поэтому вместо этого он будет использовать мою функцию, избавляя от необходимости связывать psapi.dll во время загрузки, это просто не работает. Это либо segfault, либо ничего не напечатает. Я пытался модифицировать то, как я представляю буфер, пытался использовать widechar или Tchar, но, похоже, ничего не работает.
Это вывод, который у меня есть с функциональным скриптом: вывод рабочего скрипта
и это вывод, который у меня есть с моей функцией: вывод нефункционального скрипта
Самое смешное, что одна из функций, getModules (указывающая на EnumProcessModules), работала отлично! Я просто не могу понять, что происходит.
Вы должны изменить эту строку кода
typedef DWORD (__cdecl *EnumModules)(HANDLE hprocess, HMODULE *moduleHandles, DWORD cb, LPDWORD lpcNeeded);
к этому.
typedef DWORD(__stdcall* EnumModules)(HANDLE hprocess, HMODULE* moduleHandles, DWORD cb, LPDWORD lpcNeeded);
для получения дополнительной информации вы можете ссылаться на это
То же самое и с
GetModuleName
typedef. Почти все функции Win32 API используют__stdcall
, за исключением таких функций, какwsprintf
, которые требуют__cdecl