미친해커

[Reversing] DLL Injection + IAT Hooking 본문

Reversing

[Reversing] DLL Injection + IAT Hooking

미친해커 2022. 2. 14. 05:09
반응형

IAT Hooking 응용

UserMode에서의 Hooking은 여러 다른 기술들과 함께 응용하여 사용할 수 있다.

 

DLL Injection + IAT Hooking 조합으로 실제 프로그램을 대상으로 Hooking을 진행해 보자

필요한 바이너리

1. DLL Injector

// File : Injector.c
#include <stdio.h>
#include <windows.h>

#define DesiredAccess (PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD)

LPCSTR GetBaseName(LPCSTR path)
{
    ssize_t length = strlen(path);

    for (; length > -1; length--)
    {
        if (path[length] == '\\')
            return path + length + 1;
    }

    return path;
}

void error(LPCSTR FunctionName)
{
    printf("[-] %s Failed\n", FunctionName);
    printf("[*] GetLastError : %d\n", GetLastError());
}

int main(int argc, char *argv[])
{
    if (argc < 3)
    {
        printf("Usage : %s [PID] [DLL Path]\n", GetBaseName(argv[0]));
        printf("ex : %s 1234 C:\\Hack.dll", GetBaseName(argv[0]));
        return -1;
    }

    DWORD PID = atoi(argv[1]);
    LPCSTR Path = argv[2];
    size_t length = strlen(Path);

    printf("[*] Attempting get target process permissions...\n");

    HANDLE hProcess = OpenProcess(DesiredAccess, FALSE, PID);

    if (hProcess == NULL)
    {
        error("OpenProcess");
        return -1;
    }

    printf("[*] OpenProcess success!\n");
    printf("[+] Get process handle : 0x%X\n", hProcess);

    PVOID PathAddress = VirtualAllocEx(hProcess, NULL, length, MEM_COMMIT, PAGE_READWRITE);

    if (PathAddress == NULL)
    {
        error("VirtualAllocEx");
        return -1;
    }

    printf("[*] Allocate buffer to target process success!\n");
    printf("[+] Buffer address is 0x%p\n", PathAddress);

    printf("[*] DLL path writing...\n");

    SIZE_T NumberOfBytesWritten;

    if (WriteProcessMemory(hProcess, PathAddress, Path, length, NULL) == FALSE)
    {
        error("WriteProcessMemory");
        return -1;
    }

    printf("[*] Written DLL Path\n");

    printf("[*] HMODULE of kernel32.dll finding...\n");

    HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
    
    if (hKernel32 == NULL)
    {
        error("GetModuleHandleA");
        return -1;
    }

    printf("[*] HMODULE of kernel32.dll found!\n");
    printf("[+] HMODULE of kernel32.dll is 0x%p\n", hKernel32);

    printf("[*] LoadLibraryA address of kernel32.dll finding...\n");

    FARPROC lpLoadLibraryA = GetProcAddress(hKernel32, "LoadLibraryA");

    if (lpLoadLibraryA == NULL)
    {
        error("GetProcAddress");
        return -1;
    }

    printf("[*] LoadLibraryA address of kernel32.dll found!\n");
    printf("[+] LoadLibraryA address is 0x%p\n", lpLoadLibraryA);

    HANDLE hThread = CreateRemoteThread(hProcess, NULL, NULL, lpLoadLibraryA, PathAddress, 0, NULL);

    if (hThread == NULL)
    {
        error("CreateRemoteThread");
        return -1;
    }

    WaitForSingleObject(hThread, INFINITE);

    DWORD ExitCode;
    GetExitCodeThread(hThread, &ExitCode);

    if (ExitCode == NULL)
    {
        printf("DLL Injection Failed\n");
        return -1;
    }

    printf("[+] DLL Injection Success!\n");

    return 0;
}

Injector.exe
0.06MB

2. IAT Hooking DLL

#include <Windows.h>
#include <winternl.h>

NTSTATUS (NTAPI *OriginNtCreateFile)(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength);

BOOL IATHook(HMODULE hModule, LPCSTR lpProcName, PVOID NewFunc, PVOID *OriginFunc)
{
    BOOL ret = FALSE;
    ULONGLONG ImageBase = (ULONGLONG)hModule;
    IMAGE_IMPORT_DESCRIPTOR (*IMPORT)[1] = ImageBase + ((IMAGE_NT_HEADERS *)(ImageBase + ((IMAGE_DOS_HEADER *)ImageBase)->e_lfanew))->OptionalHeader.DataDirectory[1].VirtualAddress;

    for (int i = 0;; i++)
    {
        if (IMPORT[i]->OriginalFirstThunk == NULL)
            break;

        for (int j = 0;; j++)
        {
            IMAGE_THUNK_DATA *THUNK = ImageBase + IMPORT[i]->OriginalFirstThunk + j * sizeof(void *);

            if (THUNK->u1.AddressOfData == NULL)
            {
                break;
            }

            if (THUNK->u1.Ordinal < 0x80000000)
            {
                IMAGE_IMPORT_BY_NAME *IMPORT_NAME = ImageBase + THUNK->u1.AddressOfData;
                printf("[+] Function Name : %s\n", IMPORT_NAME->Name);
                printf("[+] IAT Address : 0x%p\n", ImageBase + IMPORT[i]->FirstThunk + j * sizeof(void *));

                if (strcmp(IMPORT_NAME->Name, lpProcName) == 0)
                {
                    if (OriginFunc != NULL)
                        *OriginFunc = *(ULONG_PTR *)(ImageBase + IMPORT[i]->FirstThunk + j * sizeof(void *));
                    DWORD OldProtect;
                    VirtualProtect((ImageBase + IMPORT[i]->FirstThunk + j * sizeof(void *)), 8, PAGE_READWRITE, &OldProtect); // 해당 IAT 주소에 쓰기 권한을 부여
                    *(ULONG_PTR *)(ImageBase + IMPORT[i]->FirstThunk + j * sizeof(void *)) = NewFunc;
                    VirtualProtect((ImageBase + IMPORT[i]->FirstThunk + j * sizeof(void *)), 8, PAGE_READONLY, &OldProtect);
                    ret = TRUE;
                    break;
                }
            }
        }
    }

    return ret;
}

NTSTATUS NTAPI NewNtCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength)
{
    MessageBoxA(NULL, "Call NtCreateFile", "Hook.dll", 0);

    return OriginNtCreateFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, EaBuffer, EaLength);
}

BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID lpReserved)
{
    switch (fdwReason)
    {
    case DLL_PROCESS_ATTACH:
        if (IATHook(GetModuleHandleA("kernelbase.dll"), "NtCreateFile", NewNtCreateFile, &OriginNtCreateFile) == FALSE)
        {
            MessageBoxA(NULL, "failed hook!", "Hook.dll", MB_ICONWARNING);
        }
        break;
    }
}

Hook.dll
0.05MB

Try Hooking!

위 바이너리들을 이용해 이제 notepad.exe를 대상으로 후킹을 진행한다.

 

메모장을 실행하고 cmd에서 다음과 같이 커맨드를 입력한다.

I:\DLL Injection\src>Injector.exe 40192 "I:\DLL Injection\src\Hook.dll"
[*] Attempting get target process permissions...
[*] OpenProcess success!
[+] Get process handle : 0x88
[*] Allocate buffer to target process success!
[+] Buffer address is 000002C617EE0000
[*] DLL path writing...
[*] Written DLL Path
[*] HMODULE of kernel32.dll finding...
[*] HMODULE of kernel32.dll found!
[+] HMODULE of kernel32.dll is 00007FFF64A00000
[*] LoadLibraryA address of kernel32.dll finding...
[*] LoadLibraryA address of kernel32.dll found!
[+] LoadLibraryA address is 00007FFF64A1EBB0
[+] DLL Injection Success!

 

이렇게 DLL Injection이 성공했다면 메모장에서 [파일] -> [열기] 를 클릭하면 다음 그림과 같이 메시지 박스가 성공적으로 나오는 것을 확인할 수 있다.

&nbsp;

반응형
Comments