首页
社区
课程
招聘
[原创]记一次Hook调试
发表于: 2019-4-17 11:04 5834

[原创]记一次Hook调试

2019-4-17 11:04
5834
最近在看冀云的《C++黑客编程揭秘与防范》,在我尝试运行IAT Hook中的程序(注入DLL到Notepad,并Hook住CreateFile函数)时,却发现DLL总是注入不成功。

源代码:
#include <Windows.h>

typedef HANDLE (WINAPI *CREATEFILEW)(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);

CREATEFILEW dwCreateFileWAddr = 0;

HANDLE
WINAPI
MyCreateFileW(
            LPCWSTR lpFileName,
            DWORD dwDesiredAccess,
            DWORD dwShareMode,
            LPSECURITY_ATTRIBUTES lpSecurityAttributes,
            DWORD dwCreationDisposition,
            DWORD dwFlagsAndAttributes,
            HANDLE hTemplateFile
    )
{
    WCHAR wFileName[MAX_PATH] = { 0 };
    wcscpy(wFileName, lpFileName);
    if ( wcscmp(wcslwr(wFileName), L"g:\\test.txt") == 0 )
    {
        if ( MessageBox(NULL, "是否打开文件", "提示", MB_YESNO) == IDYES )
        {
            return dwCreateFileWAddr(lpFileName,
                            dwDesiredAccess,
                            dwShareMode,
                            lpSecurityAttributes,
                            dwCreationDisposition,
                            dwFlagsAndAttributes,
                            hTemplateFile);
        } 
        else
        {
            return INVALID_HANDLE_VALUE;
        }
    }
    else
    {
        return dwCreateFileWAddr(lpFileName,
            dwDesiredAccess,
            dwShareMode,
            lpSecurityAttributes,
            dwCreationDisposition,
            dwFlagsAndAttributes,
            hTemplateFile);
    }
}

VOID HookNotePadProcessIAT()
{
    // 获得Createfile
    HMODULE hMod = LoadLibrary("kernel32.dll");
    DWORD dwFuncAddr = (DWORD)GetProcAddress(hMod, "CreateFileW");
    CloseHandle(hMod);

    // 获取记事本进程模块基址
    HMODULE hModule = GetModuleHandleA(NULL);

    // 定位PE结构
    PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hModule;
    PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)((DWORD)hModule + pDosHdr->e_lfanew);

    // 保存映像基址及导入表的RVA
    DWORD dwImageBase = pNtHdr->OptionalHeader.ImageBase;
    DWORD dwImpRva = pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;

    // 导入表的VA
    PIMAGE_IMPORT_DESCRIPTOR pImgDes = (PIMAGE_IMPORT_DESCRIPTOR)(dwImageBase + dwImpRva);

    char szAddr[10] = { 0 };

    PIMAGE_IMPORT_DESCRIPTOR pTmpImpDes = pImgDes;
    BOOL bFound = FALSE;

    // 查找欲HOOK函数的模块名
    while ( pTmpImpDes->Name )
    {
        DWORD dwNameAddr = dwImageBase + pTmpImpDes->Name;
        char szName[MAXBYTE] = { 0 };
        strcpy(szName, (char*)dwNameAddr);

        if ( strcmp(strlwr(szName), "kernel32.dll") == 0 )
        {
            bFound = TRUE;
            break;
        }
        pTmpImpDes ++;
    }

    // 判断是否找到欲HOOK函数所在的函数名
    if ( bFound == TRUE )
    {
        bFound = FALSE;
        char szAddr[10] = { 0 };

        // 逐个遍历该模块的IAT地址
        PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)(pTmpImpDes->FirstThunk + dwImageBase);

        while ( pThunk->u1.Function )
        {
            DWORD *pAddr = (DWORD *)&(pThunk->u1.Function);
            // 比较是否与欲HOOK函数的地址相同
            if ( *pAddr == dwFuncAddr )
            {
                bFound = TRUE;
                dwCreateFileWAddr = (CREATEFILEW)*pAddr;
                DWORD dwMyHookAddr = (DWORD)MyCreateFileW;
                // 修改为Hook函数的地址
                WriteProcessMemory(GetCurrentProcess(), (LPVOID)pAddr, &dwMyHookAddr, sizeof(DWORD), NULL);
                break;
            }
            pThunk ++;
        }
    }

    if ( bFound == TRUE )
    {
        MessageBox(NULL, "Hook Successfully !", NULL, MB_OK);
    } 
    else
    {
        MessageBox(NULL, "Hook Unsuccessfully !", NULL, MB_OK);
    }
}

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    switch ( ul_reason_for_call )
    {
    case DLL_PROCESS_ATTACH:
        {
            // 在DLL被加载时调用HookNotePadProcessIAT()
            //DebugBreak();
			HookNotePadProcessIAT();
			//MessageBox(NULL, "text", "title", MB_OK);
            break;
        }
    }
    return TRUE;
}

#include <Windows.h>

typedef HANDLE (WINAPI *CREATEFILEW)(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);

CREATEFILEW dwCreateFileWAddr = 0;

HANDLE
WINAPI
MyCreateFileW(
            LPCWSTR lpFileName,
            DWORD dwDesiredAccess,
            DWORD dwShareMode,
            LPSECURITY_ATTRIBUTES lpSecurityAttributes,
            DWORD dwCreationDisposition,
            DWORD dwFlagsAndAttributes,
            HANDLE hTemplateFile
    )
{
    WCHAR wFileName[MAX_PATH] = { 0 };
    wcscpy(wFileName, lpFileName);
    if ( wcscmp(wcslwr(wFileName), L"g:\\test.txt") == 0 )
    {
        if ( MessageBox(NULL, "是否打开文件", "提示", MB_YESNO) == IDYES )
        {
            return dwCreateFileWAddr(lpFileName,
                            dwDesiredAccess,
                            dwShareMode,
                            lpSecurityAttributes,
                            dwCreationDisposition,
                            dwFlagsAndAttributes,
                            hTemplateFile);
        } 
        else
        {
            return INVALID_HANDLE_VALUE;
        }
    }
    else
    {
        return dwCreateFileWAddr(lpFileName,
            dwDesiredAccess,
            dwShareMode,
            lpSecurityAttributes,
            dwCreationDisposition,
            dwFlagsAndAttributes,
            hTemplateFile);
    }
}

VOID HookNotePadProcessIAT()
{
    // 获得Createfile
    HMODULE hMod = LoadLibrary("kernel32.dll");
    DWORD dwFuncAddr = (DWORD)GetProcAddress(hMod, "CreateFileW");
    CloseHandle(hMod);

    // 获取记事本进程模块基址
    HMODULE hModule = GetModuleHandleA(NULL);

    // 定位PE结构
    PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hModule;
    PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)((DWORD)hModule + pDosHdr->e_lfanew);

    // 保存映像基址及导入表的RVA
    DWORD dwImageBase = pNtHdr->OptionalHeader.ImageBase;
    DWORD dwImpRva = pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;

    // 导入表的VA
    PIMAGE_IMPORT_DESCRIPTOR pImgDes = (PIMAGE_IMPORT_DESCRIPTOR)(dwImageBase + dwImpRva);

    char szAddr[10] = { 0 };

    PIMAGE_IMPORT_DESCRIPTOR pTmpImpDes = pImgDes;
    BOOL bFound = FALSE;

    // 查找欲HOOK函数的模块名
    while ( pTmpImpDes->Name )
    {
        DWORD dwNameAddr = dwImageBase + pTmpImpDes->Name;
        char szName[MAXBYTE] = { 0 };
        strcpy(szName, (char*)dwNameAddr);

        if ( strcmp(strlwr(szName), "kernel32.dll") == 0 )
        {
            bFound = TRUE;
            break;
        }
        pTmpImpDes ++;
    }

    // 判断是否找到欲HOOK函数所在的函数名
    if ( bFound == TRUE )
    {
        bFound = FALSE;
        char szAddr[10] = { 0 };

        // 逐个遍历该模块的IAT地址
        PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)(pTmpImpDes->FirstThunk + dwImageBase);

        while ( pThunk->u1.Function )
        {
            DWORD *pAddr = (DWORD *)&(pThunk->u1.Function);
            // 比较是否与欲HOOK函数的地址相同
            if ( *pAddr == dwFuncAddr )
            {
                bFound = TRUE;
                dwCreateFileWAddr = (CREATEFILEW)*pAddr;
                DWORD dwMyHookAddr = (DWORD)MyCreateFileW;
                // 修改为Hook函数的地址
                WriteProcessMemory(GetCurrentProcess(), (LPVOID)pAddr, &dwMyHookAddr, sizeof(DWORD), NULL);
                break;
            }
            pThunk ++;
        }
    }

    if ( bFound == TRUE )
    {
        MessageBox(NULL, "Hook Successfully !", NULL, MB_OK);
    } 
    else
    {
        MessageBox(NULL, "Hook Unsuccessfully !", NULL, MB_OK);
    }
}

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    switch ( ul_reason_for_call )
    {
    case DLL_PROCESS_ATTACH:
        {
            // 在DLL被加载时调用HookNotePadProcessIAT()
            //DebugBreak();
			HookNotePadProcessIAT();
			//MessageBox(NULL, "text", "title", MB_OK);
            break;
        }
    }
    return TRUE;
}

我的运行环境是win10 64位,在我编译出64位的DLL和64位的注入器程序后,发现还是注入失败。
在调试过注入器代码后,发现CreateRemoteThread函数是执行成功了的,DLL却注入失败。

于是觉得调试一下DLL_PROCESS_ATTACH后的代码部分。x64dbg附加notepad.exe,注入器注入DLL,发现程序断在了00007FFEA7791210处,这里出现了EXCEPTION_ACCESS_VIOLATION访问异常。

ida调试一下DLL,发现这里是在解析pe文件,定位NTHeader。

[培训]科锐逆向工程师培训第53期2025年7月8日开班!

最后于 2019-4-17 11:20 被吴俊编辑 ,原因: 部分内容没有发出去
收藏
免费 1
支持
分享
最新回复 (2)
雪    币: 42947
活跃值: (65767)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
2
感谢分享~
2019-4-17 13:15
0
雪    币: 20
活跃值: (27)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
来自山总的肯定
2019-4-17 13:29
0
游客
登录 | 注册 方可回帖
返回