미친해커

[C] Rlibloaderapi.h - GetModuleHandle 본문

C/Remote libloaderapi.h

[C] Rlibloaderapi.h - GetModuleHandle

미친해커 2022. 2. 17. 13:40
반응형

GetModuleHandle

GetModuleHandle 함수는 kernel32.dll와 kernelbase.dll에 정의되어있는 함수이다. 해당 함수는 현재 프로세스에 로드된 DLL 중 인자로 넣은 DLL 이름의 HMODULE을 반환하는 함수이다.

 

HMODULE은 과거 윈도우에서 다른 용도로 만들어졌지만 현재 윈도우에서는 DLL의 ImageBase를 담는 자료형이 되었다. 실제로 GetModuleHandle 함수를 이용해 특정 DLL의 HMODULE을 반환 받으면 해당 값은 해당 DLL의 ImageBase 인 것을 확인할 수 있다. 이 또한 현재 프로세스가 아닌 다른 프로세스에 로드된 DLL의 ImageBase를 구하기 위해 Remote 버전을 구현하게 되었다.

GetRemoteModuleHandle

HMODULE GetRemoteModuleHandleA(HANDLE ProcessHandle, LPCSTR lpModuleName)
{
    HMODULE hModule = NULL;
    LPWSTR ModuleName = NULL;
    int ModuleNameLength = MultiByteToWideChar(CP_ACP, 0, lpModuleName, -1, NULL, 0);
    ModuleName = calloc(ModuleNameLength, sizeof(wchar_t));
    MultiByteToWideChar(CP_ACP, 0, lpModuleName, -1, ModuleName, ModuleNameLength);
    hModule = GetRemoteModuleHandleW(ProcessHandle, ModuleName);
    free(ModuleName);
    return hModule;
}

HMODULE GetRemoteModuleHandleW(HANDLE ProcessHandle, LPCWSTR lpModuleName)
{
#ifdef _WIN64
    BOOL bWow64Process;
    IsWow64Process(ProcessHandle, &bWow64Process);
    size_t SizeOfPointer = bWow64Process ? 4 : 8;
#else
    size_t SizeOfPointer = 4;
#endif
    
    HMODULE hModule = NULL;
    PVOID PebBaseAddress = GetRemotePeb(ProcessHandle);

    if (PebBaseAddress == NULL)
        return hModule;

    PVOID PebLdrData = NULL;

    if (ReadProcessMemory(ProcessHandle, 
#ifdef _WIN64
            (ULONG_PTR)PebBaseAddress + (bWow64Process ? Peb_LdrOffset32 : Peb_LdrOffset64), 
#else
            (ULONG_PTR)PebBaseAddress + Peb_LdrOffset32,
#endif
            &PebLdrData, 
            SizeOfPointer, 
            NULL) == FALSE)
        return hModule;

#ifdef _WIN64
    PVOID LdrDataTableEntry = (ULONG_PTR)PebLdrData + (bWow64Process ? PebLdrData_LOMLOffset32 : PebLdrData_LOMLOffset64);
    size_t SizeOfUnicodeString = bWow64Process ? sizeof(UNICODE_STRING32) : sizeof(UNICODE_STRING64);
#else
    PVOID LdrDataTableEntry = (ULONG_PTR)PebLdrData + PebLdrData_LOMLOffset32;
    size_t SizeOfUnicodeString = sizeof(UNICODE_STRING);
#endif

    BYTE *UnicodeString = calloc(1, SizeOfUnicodeString);

    for (LPWSTR ModuleName = NULL; ReadProcessMemory(ProcessHandle, LdrDataTableEntry, &LdrDataTableEntry, SizeOfPointer, NULL) 
            && 
#ifdef _WIN64
            (ULONG_PTR)PebLdrData + (bWow64Process ? PebLdrData_LOMLOffset32 : PebLdrData_LOMLOffset64) != LdrDataTableEntry
#else
            (ULONG_PTR)PebLdrData + PebLdrData_LOMLOffset32 != LdrDataTableEntry
#endif
        ; free(ModuleName))
    {
        if (ReadProcessMemory(ProcessHandle, 
#ifdef _WIN64
                (ULONG_PTR)LdrDataTableEntry + (bWow64Process ? LdrDataTableEntry_BaseDllName32 : LdrDataTableEntry_BaseDllName64), 
#else
                (ULONG_PTR)LdrDataTableEntry + LdrDataTableEntry_BaseDllName32,
#endif
                UnicodeString, 
                SizeOfUnicodeString, 
                NULL) == FALSE)
            return hModule;

#ifdef _WIN64
        ModuleName = malloc(bWow64Process ? ((UNICODE_STRING32 *)UnicodeString)->Length + 2 : ((UNICODE_STRING64 *)UnicodeString)->Length + 2);
#else
        ModuleName = malloc(sizeof(UNICODE_STRING));
#endif
        if (ReadProcessMemory(ProcessHandle, 
#ifdef _WIN64
                bWow64Process ? ((UNICODE_STRING32 *)UnicodeString)->Buffer : ((UNICODE_STRING64 *)UnicodeString)->Buffer, 
                ModuleName,
                bWow64Process ? ((UNICODE_STRING32 *)UnicodeString)->Length + 2 : ((UNICODE_STRING64 *)UnicodeString)->Length + 2,
#else
                ((UNICODE_STRING *)UnicodeString)->Buffer,
                ModuleName, 
                ((UNICODE_STRING *)UnicodeString)->Length,
#endif
                NULL) == FALSE)
            return hModule;

        if (wcsicmp(lpModuleName, ModuleName))
            continue;

        if (ReadProcessMemory(ProcessHandle, 
#ifdef _WIN64
                (ULONG_PTR)LdrDataTableEntry + (bWow64Process ? LdrDataTableEntry_DllBase32 : LdrDataTableEntry_DllBase64), 
#else
                (ULONG_PTR)LdrDataTableEntry + LdrDataTableEntry_DllBase32,
#endif
                &hModule, 
                SizeOfPointer, // sizeof(HMODULE), 
                NULL) == FALSE && (RtlFreeHeap(_get_heap_handle(), 0, ModuleName) || TRUE))
            return hModule;

        free(ModuleName);
        break;
    }

    free(UnicodeString);
    return hModule;
}

사용예시

#include <stdio.h>
#include "Rlibloaderapi.h"

int main()
{
    DWORD PID;
    printf("PID : ");
    scanf("%d", &PID);
    
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
    
    if (hProcess == NULL)
    {
    	printf("OpenProcess Failed\n");
        printf("GetLastError : %d\n", GetLastError());
        return -1;
    }
    
    char Modulename[MAX_PATH];
    printf("Module name : ");
    scanf("%s", Modulename);
    
    printf("%s : 0x%p", Modulename, GetRemoteModuleHandleA(hProcess, Modulename));
    
    return 0;
}
반응형
Comments