内存写入 隐藏模块

远线程注入dll的局限

注入前

 

 

 注入后

 

 

 这个dll赫然在列,当然我们也可以理解,通过GetProcAddress得到了LoadLibrary函数的地址,用这个地址去加载了我们自己的dll,导入表中当然有这个dll的名称。

当我们使用内存写入这种方式后,无法再通过普通的进程查看模块方式找到我们的模块,将更加隐蔽

思路

我们向一个exe中正确的写入数据,如何是正确的:修复重定位表,修复IAT表

 为什么修复重定位表?

在虚拟的内存空间中,exe的ImageBase为0x400000,已经被占用,如果我们想写入一个exe或者dll的话,首先exe肯定贴不到0x400000那个位置,dll也不一定可以加载到0x1000000,所以我们需要重定位表来修复一些全局变量,那些固定的值.

 为什么修复IAT表?

也许有人有这样的疑问,重定位表中已经包含了IAT表的地址,修复重定位表也就是修复了IAT表的地址,这没有错,问题在于修复的是IAT表的地址,我们知道IAT表里存的是一个地址,地址里面的值才是正在的函数地址,函数地址的值是在运行的时候才会确定下来(这也与重定位有关),而我们运行时系统给我们写的函数地址的值,并不是基于我们希望的那个位置写的,我们希望的位置是在被写入进程中创建空间的首地址,所以这个代码应该在被写入的进程中执行,创建一个线程就可以了.

写入过程

修复IAT表

 1 DWORD WINAPI FixIATTable(LPVOID ImageBase)
 2 {
 3     PIMAGE_DOS_HEADER pDosHeader = NULL;
 4     PIMAGE_NT_HEADERS pNTHeader = NULL;
 5     PIMAGE_FILE_HEADER pPEHeader = NULL;
 6     PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
 7     PIMAGE_SECTION_HEADER pSectionHeader = NULL;
 8     PIMAGE_IMPORT_DESCRIPTOR pIMPORT_DESCRIPTOR = NULL;
 9     PIMAGE_IMPORT_BY_NAME pImage_IMPORT_BY_NAME = NULL;
10 
11     PDWORD OriginalFirstThunk = NULL;
12     PDWORD FirstThunk = NULL;
13 
14     PIMAGE_THUNK_DATA pImageThunkData = NULL;
15 
16     DWORD Original = 0;
17 
18     pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
19     pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)ImageBase + pDosHeader->e_lfanew);
20     pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
21     pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
22 
23     //每个导入表的相关信息占20个字节
24     pIMPORT_DESCRIPTOR = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)ImageBase + pOptionHeader->DataDirectory[1].VirtualAddress);
25 
26     //这里可以进行while操作,这里while的判断依据为pIMPORT_DESCRIPTOR个数
27     DWORD dwFuncAddr = 0;
28     HMODULE hModule;
29     TCHAR Buffer[100] = {0};
30     while (pIMPORT_DESCRIPTOR->FirstThunk && pIMPORT_DESCRIPTOR->OriginalFirstThunk) 
31     {
32         const char* pModuleAddr = (const char*)((DWORD)ImageBase + (DWORD)pIMPORT_DESCRIPTOR->Name);
33         mbstowcs(Buffer, pModuleAddr, 100);
34         hModule = LoadLibrary(Buffer);
35         printf("%s", (LPCWCHAR)((DWORD)ImageBase + (DWORD)pIMPORT_DESCRIPTOR->Name));
36         if (hModule == NULL)
37         {
38             printf("hModuleError:%d",::GetLastError());
39             return 0;
40         }
41         // FirstThunk 指向 IMAGE_THUNK_DATA 结构数组
42         OriginalFirstThunk = (PDWORD)((DWORD)ImageBase + (DWORD)pIMPORT_DESCRIPTOR->OriginalFirstThunk);
43         FirstThunk = (PDWORD)((DWORD)ImageBase + (DWORD)pIMPORT_DESCRIPTOR->FirstThunk);
44 
45         while (*OriginalFirstThunk) 
46         {
47             if (*OriginalFirstThunk & 0x80000000) {
48                 //高位为1 则 除去最高位的值就是函数的导出序号
49                 Original = *OriginalFirstThunk & 0xFFF;    //去除最高标志位。
50                 dwFuncAddr = (DWORD)GetProcAddress(hModule, (PCHAR)Original);
51             }
52             else
53             {
54                 //高位不为1 则指向IMAGE_IMPORT_BY_NAME;
55                 pImage_IMPORT_BY_NAME = (PIMAGE_IMPORT_BY_NAME)((DWORD)ImageBase + *OriginalFirstThunk);
56                 dwFuncAddr = (DWORD)GetProcAddress(hModule, (PCHAR)pImage_IMPORT_BY_NAME->Name);
57             }
58             *FirstThunk = dwFuncAddr;
59             OriginalFirstThunk++;
60         }
61 
62         pIMPORT_DESCRIPTOR++;
63     }
64 
65     while (TRUE)
66     {
67         MessageBox(NULL, NULL, NULL, NULL);
68         Sleep(3000);
69     }
70     return 1;
71 }

如果修复成功会隔三秒弹出一个MessageBox

注入和修复重定位

 1 VOID inject(LPCWSTR InjetName)
 2 {
 3     DWORD _size = 0;
 4     LPVOID pCurrentAddr = NULL;
 5     LPVOID pFarAddr = NULL;
 6     TCHAR path[MAX_PATH] = { 0 };
 7     HANDLE hprocess = NULL;
 8     HANDLE hThread = NULL;
 9     //获取当前进程路径
10     ::GetModuleFileName(NULL, path, MAX_PATH);
11     //获取自身模块的基址
12     HMODULE imagebase = ::GetModuleHandle(NULL);
13     //获得sizeofimage
14     PIMAGE_DOS_HEADER pDosHeader = NULL;
15     PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
16     pDosHeader = (PIMAGE_DOS_HEADER)imagebase;
17     pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pDosHeader + pDosHeader->e_lfanew + IMAGE_SIZEOF_FILE_HEADER + 4);
18     _size = pOptionHeader->SizeOfImage;
19     //自身内存声请空间
20     pCurrentAddr = VirtualAlloc(NULL, _size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
21     if (pCurrentAddr == NULL)
22     {
23         printf("pCurrentAddrError");
24         return;
25     }
26     memcpy(pCurrentAddr, imagebase, _size);
27     //打开要注入的进程
28     hprocess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, _getProcessPid(InjetName));
29     if (hprocess == NULL)
30     {
31         printf("OpenProcessError");
32         return;
33     }
34     //远程空间申请内存
35     pFarAddr = ::VirtualAllocEx(hprocess, NULL, _size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
36     if (pFarAddr == NULL)
37     {
38         printf("VirtualAllocExError");
39         return;
40     }
41     //修复重定位表
42 
43     if (GetRelocAddr(pCurrentAddr) == 0)
44     {
45         printf("没有重定位表");
46         return;
47     }
48     PIMAGE_BASE_RELOCATION pRelocationDirectory = (PIMAGE_BASE_RELOCATION)((DWORD)pCurrentAddr + GetRelocAddr(pCurrentAddr));
49 
50     while (pRelocationDirectory->SizeOfBlock != 0 && pRelocationDirectory->VirtualAddress != 0) 
51     {
52         DWORD sizeOfWord = (pRelocationDirectory->SizeOfBlock - 8) / 2;
53         PWORD pWord = (PWORD)((DWORD)pRelocationDirectory + 8);
54         for (int i = 0; i < sizeOfWord; i++)
55         {
56             if (*pWord >> 12 != 0)
57             {
58                 PDWORD offsetAddr = (PDWORD)(pRelocationDirectory->VirtualAddress + (*pWord & 0xFFF) + (DWORD)pCurrentAddr);
59                 *offsetAddr = *offsetAddr + (DWORD)pFarAddr - GetImageBase(imagebase);
60                 pWord++;
61                 continue;
62             }
63             pWord++;
64         }
65         pRelocationDirectory = (PIMAGE_BASE_RELOCATION)((DWORD)pRelocationDirectory + pRelocationDirectory->SizeOfBlock);
66     }
67     BOOL x = ::WriteProcessMemory(hprocess, pFarAddr, pCurrentAddr, _size, NULL);
68     if (FALSE == x)
69     {
70         printf("WriteProcessMemoryERROR");
71         return;
72     }
73         //执行修复IAT表里存的值和执行自己的功能
74     DWORD FixNewIATTable = (DWORD)FixIATTable  + (DWORD)pFarAddr - (DWORD)imagebase;
75     hThread = ::CreateRemoteThread(hprocess, NULL, 0, (LPTHREAD_START_ROUTINE)FixNewIATTable, pFarAddr, 0, NULL);
76     if (hThread == NULL)
77     {
78         printf("CreateRemoteThreadError");
79         return;
80     }
81     WaitForSingleObject(hThread, -1);
82     CloseHandle(hThread);
83 }

这里有个细节 74行,我们修复IAT表的函数地址也需要重定位

要用到的其他函数

 1 //根据进程名找对应的pid(快照方式)
 2 DWORD _getProcessPid(LPCTSTR lpProcessName)
 3 {
 4     DWORD dwRet = 0;
 5     HANDLE hSnapShot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
 6     if (hSnapShot == INVALID_HANDLE_VALUE)
 7     {
 8         printf("\n获得进程快照失败,返回的GetLastError():%d", ::GetLastError());
 9         return dwRet;
10     }
11 
12     PROCESSENTRY32 pe32;
13     pe32.dwSize = sizeof(PROCESSENTRY32);
14     ::Process32First(hSnapShot, &pe32);
15     do
16     {
17         if (!lstrcmp(pe32.szExeFile, lpProcessName))
18         {
19             dwRet = pe32.th32ProcessID;
20             break;
21         }
22     } while (::Process32Next(hSnapShot, &pe32));
23     ::CloseHandle(hSnapShot);
24     return dwRet;
25 }
26 
27 DWORD GetImageBase(LPVOID pFileBuffer)
28 {
29     PIMAGE_DOS_HEADER pDosHeader = NULL;
30     PIMAGE_NT_HEADERS pNTHeader = NULL;
31     PIMAGE_FILE_HEADER pPEHeader = NULL;
32     PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
33     PIMAGE_SECTION_HEADER pSectionHeader = NULL;
34     pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
35     if (*(PDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew) != IMAGE_NT_SIGNATURE)
36     {
37         printf("不是有效的PE签名");
38         free(pFileBuffer);
39         return 0;
40     }
41     pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
42     pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
43     pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
44 
45     return pOptionHeader->ImageBase;
46 
47 }
48 DWORD GetRelocAddr(LPVOID pFileBuffer)
49 {
50     PIMAGE_DOS_HEADER pDosHeader = NULL;
51     PIMAGE_NT_HEADERS pNTHeader = NULL;
52     PIMAGE_FILE_HEADER pPEHeader = NULL;
53     PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
54     PIMAGE_SECTION_HEADER pSectionHeader = NULL;
55     pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
56     if (*(PDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew) != IMAGE_NT_SIGNATURE)
57     {
58         printf("不是有效的PE签名");
59         free(pFileBuffer);
60         return 0;
61     }
62     pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
63     pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
64     pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
65     pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
66 
67     return pOptionHeader->DataDirectory[5].VirtualAddress;
68 
69 }

代码

// 内存写入,隐藏模块.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <windows.h>
#include <TlHelp32.h>
#include <stdlib.h>
#include <comdef.h> 

DWORD WINAPI FixIATTable(LPVOID ImageBase);
DWORD _getProcessPid(LPCTSTR lpProcessName);
DWORD GetRelocAddr(LPVOID pFileBuffer);
DWORD GetImageBase(LPVOID pFileBuffer);
VOID inject(LPCWSTR InjetPath);


DWORD WINAPI FixIATTable(LPVOID ImageBase)
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pPEHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
    PIMAGE_IMPORT_DESCRIPTOR pIMPORT_DESCRIPTOR = NULL;
    PIMAGE_IMPORT_BY_NAME pImage_IMPORT_BY_NAME = NULL;

    PDWORD OriginalFirstThunk = NULL;
    PDWORD FirstThunk = NULL;

    PIMAGE_THUNK_DATA pImageThunkData = NULL;

    DWORD Original = 0;

    pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)ImageBase + pDosHeader->e_lfanew);
    pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
    pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);

    //每个导入表的相关信息占20个字节
    pIMPORT_DESCRIPTOR = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)ImageBase + pOptionHeader->DataDirectory[1].VirtualAddress);

    //这里可以进行while操作,这里while的判断依据为pIMPORT_DESCRIPTOR个数
    DWORD dwFuncAddr = 0;
    HMODULE hModule;
    TCHAR Buffer[100] = {0};
    while (pIMPORT_DESCRIPTOR->FirstThunk && pIMPORT_DESCRIPTOR->OriginalFirstThunk) 
    {
        const char* pModuleAddr = (const char*)((DWORD)ImageBase + (DWORD)pIMPORT_DESCRIPTOR->Name);
        mbstowcs(Buffer, pModuleAddr, 100);
        hModule = LoadLibrary(Buffer);
        printf("%s", (LPCWCHAR)((DWORD)ImageBase + (DWORD)pIMPORT_DESCRIPTOR->Name));
        if (hModule == NULL)
        {
            printf("hModuleError:%d",::GetLastError());
            return 0;
        }
        // FirstThunk 指向 IMAGE_THUNK_DATA 结构数组
        OriginalFirstThunk = (PDWORD)((DWORD)ImageBase + (DWORD)pIMPORT_DESCRIPTOR->OriginalFirstThunk);
        FirstThunk = (PDWORD)((DWORD)ImageBase + (DWORD)pIMPORT_DESCRIPTOR->FirstThunk);

        while (*OriginalFirstThunk) 
        {
            if (*OriginalFirstThunk & 0x80000000) {
                //高位为1 则 除去最高位的值就是函数的导出序号
                Original = *OriginalFirstThunk & 0xFFF;    //去除最高标志位。
                dwFuncAddr = (DWORD)GetProcAddress(hModule, (PCHAR)Original);
            }
            else
            {
                //高位不为1 则指向IMAGE_IMPORT_BY_NAME;
                pImage_IMPORT_BY_NAME = (PIMAGE_IMPORT_BY_NAME)((DWORD)ImageBase + *OriginalFirstThunk);
                dwFuncAddr = (DWORD)GetProcAddress(hModule, (PCHAR)pImage_IMPORT_BY_NAME->Name);
            }
            *FirstThunk = dwFuncAddr;
            OriginalFirstThunk++;
        }

        pIMPORT_DESCRIPTOR++;
    }

    while (TRUE)
    {
        MessageBox(NULL, NULL, NULL, NULL);
        Sleep(3000);
    }
    return 1;
}

//根据进程名找对应的pid(快照方式)
DWORD _getProcessPid(LPCTSTR lpProcessName)
{
    DWORD dwRet = 0;
    HANDLE hSnapShot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnapShot == INVALID_HANDLE_VALUE)
    {
        printf("\n获得进程快照失败,返回的GetLastError():%d", ::GetLastError());
        return dwRet;
    }

    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32);
    ::Process32First(hSnapShot, &pe32);
    do
    {
        if (!lstrcmp(pe32.szExeFile, lpProcessName))
        {
            dwRet = pe32.th32ProcessID;
            break;
        }
    } while (::Process32Next(hSnapShot, &pe32));
    ::CloseHandle(hSnapShot);
    return dwRet;
}

DWORD GetImageBase(LPVOID pFileBuffer)
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pPEHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    if (*(PDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew) != IMAGE_NT_SIGNATURE)
    {
        printf("不是有效的PE签名");
        free(pFileBuffer);
        return 0;
    }
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
    pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
    pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);

    return pOptionHeader->ImageBase;

}
DWORD GetRelocAddr(LPVOID pFileBuffer)
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pPEHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    if (*(PDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew) != IMAGE_NT_SIGNATURE)
    {
        printf("不是有效的PE签名");
        free(pFileBuffer);
        return 0;
    }
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
    pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
    pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
    pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);

    return pOptionHeader->DataDirectory[5].VirtualAddress;

}
VOID inject(LPCWSTR InjetName)
{
    DWORD _size = 0;
    LPVOID pCurrentAddr = NULL;
    LPVOID pFarAddr = NULL;
    TCHAR path[MAX_PATH] = { 0 };
    HANDLE hprocess = NULL;
    HANDLE hThread = NULL;
    //获取当前进程路径
    ::GetModuleFileName(NULL, path, MAX_PATH);
    //获取自身模块的基址
    HMODULE imagebase = ::GetModuleHandle(NULL);
    //获得sizeofimage
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
    pDosHeader = (PIMAGE_DOS_HEADER)imagebase;
    pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pDosHeader + pDosHeader->e_lfanew + IMAGE_SIZEOF_FILE_HEADER + 4);
    _size = pOptionHeader->SizeOfImage;
    //自身内存声请空间
    pCurrentAddr = VirtualAlloc(NULL, _size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    if (pCurrentAddr == NULL)
    {
        printf("pCurrentAddrError");
        return;
    }
    memcpy(pCurrentAddr, imagebase, _size);
    //打开要注入的进程
    hprocess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, _getProcessPid(InjetName));
    if (hprocess == NULL)
    {
        printf("OpenProcessError");
        return;
    }
    //远程空间申请内存
    pFarAddr = ::VirtualAllocEx(hprocess, NULL, _size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (pFarAddr == NULL)
    {
        printf("VirtualAllocExError");
        return;
    }
    //修复重定位表

    if (GetRelocAddr(pCurrentAddr) == 0)
    {
        printf("没有重定位表");
        return;
    }
    PIMAGE_BASE_RELOCATION pRelocationDirectory = (PIMAGE_BASE_RELOCATION)((DWORD)pCurrentAddr + GetRelocAddr(pCurrentAddr));

    while (pRelocationDirectory->SizeOfBlock != 0 && pRelocationDirectory->VirtualAddress != 0) 
    {
        DWORD sizeOfWord = (pRelocationDirectory->SizeOfBlock - 8) / 2;
        PWORD pWord = (PWORD)((DWORD)pRelocationDirectory + 8);
        for (int i = 0; i < sizeOfWord; i++)
        {
            if (*pWord >> 12 != 0)
            {
                PDWORD offsetAddr = (PDWORD)(pRelocationDirectory->VirtualAddress + (*pWord & 0xFFF) + (DWORD)pCurrentAddr);
                *offsetAddr = *offsetAddr + (DWORD)pFarAddr - GetImageBase(imagebase);
                pWord++;
                continue;
            }
            pWord++;
        }
        pRelocationDirectory = (PIMAGE_BASE_RELOCATION)((DWORD)pRelocationDirectory + pRelocationDirectory->SizeOfBlock);
    }
    BOOL x = ::WriteProcessMemory(hprocess, pFarAddr, pCurrentAddr, _size, NULL);
    if (FALSE == x)
    {
        printf("WriteProcessMemoryERROR");
        return;
    }
        //执行修复IAT表里存的值和执行自己的功能
    DWORD FixNewIATTable = (DWORD)FixIATTable  + (DWORD)pFarAddr - (DWORD)imagebase;
    hThread = ::CreateRemoteThread(hprocess, NULL, 0, (LPTHREAD_START_ROUTINE)FixNewIATTable, pFarAddr, 0, NULL);
    if (hThread == NULL)
    {
        printf("CreateRemoteThreadError");
        return;
    }
    WaitForSingleObject(hThread, -1);
    CloseHandle(hThread);
}

int main()
{
    inject(L"Test.exe");
    return 0;
}

执行效果

 

posted @ 2021-04-02 16:01  Punished  阅读(460)  评论(3编辑  收藏  举报