修改IAT,HOOK API

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

//
//write by Gxter
//
//本程序是用寻找并修改(Improt Address Table)的方法来实现HOOK一个API函数

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

#define  UNICODE
#define  _UNICODE


PIMAGE_DOS_HEADER  pDosHeader;
PIMAGE_NT_HEADERS  pNTHeaders;
PIMAGE_OPTIONAL_HEADER   pOptHeader;
PIMAGE_IMPORT_DESCRIPTOR  pImportDescriptor;
PIMAGE_THUNK_DATA         pThunkData;
PIMAGE_IMPORT_BY_NAME     pImportByName;
HMODULE hMod;

int * addr = (int *)MessageBoxA;        //保存函数的入口地址
// 定义MessageBoxA函数原型
typedef int (WINAPI *PFNMESSAGEBOX)(HWND, LPCSTR, LPCSTR, UINT uType);
int WINAPI MessageBoxProxy(IN HWND hWnd, IN LPCSTR lpText, IN LPCSTR lpCaption, IN UINT uType);

int * myaddr = (int *)MessageBoxProxy;

int main()
{
        //OutputDebugString(_T("start !"));
        MessageBoxA(NULL, "原函数", "09HookDemo", 0);

        //-------------HOOK部分
        hMod = GetModuleHandle(NULL);

        pDosHeader = (PIMAGE_DOS_HEADER)hMod;
        pNTHeaders = (PIMAGE_NT_HEADERS)((BYTE *)hMod + pDosHeader->e_lfanew);
        pOptHeader = (PIMAGE_OPTIONAL_HEADER)&(pNTHeaders->OptionalHeader);

        pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE *)hMod + pOptHeader->DataDirectory[1].VirtualAddress);

        while(pImportDescriptor->FirstThunk)
        {
                char * dllname = (char *)((BYTE *)hMod + pImportDescriptor->Name);
                //printf("函数模块:%s/n",dllname);

                pThunkData = (PIMAGE_THUNK_DATA)((BYTE *)hMod + pImportDescriptor->OriginalFirstThunk);

                int no = 1;
                while(pThunkData->u1.Function)
                {
                        char * funname = (char *)((BYTE *)hMod + (DWORD)pThunkData->u1.AddressOfData + 2);
                        PDWORD lpAddr = (DWORD *)((BYTE *)hMod + (DWORD)pImportDescriptor->FirstThunk) +(no-1);
                        
                        //printf("%4d:  ",no);
                        //printf("%30s",funname);
                        //printf("%8x/n",lpAddr);
                        //printf("%8x/n",*lpAddr);
                        //修改内存的部分
                        if((*lpAddr) == (int)addr)
                        {
                                //修改内存页的属性
                                DWORD dwOLD;
                                MEMORY_BASIC_INFORMATION  mbi;
                                VirtualQuery(lpAddr,&mbi,sizeof(mbi));
                                VirtualProtect(lpAddr,sizeof(DWORD),PAGE_READWRITE,&dwOLD);
                                //写内存
                                WriteProcessMemory(GetCurrentProcess(), 
                                                lpAddr, &myaddr, sizeof(DWORD), NULL);
                                //恢复内存页的属性
                                VirtualProtect(lpAddr,sizeof(DWORD),dwOLD,0);
                        }
            //---------
                        no++;
                        pThunkData++;
                }

                pImportDescriptor++;
        }

        //用于测试的API函数
        MessageBoxA(NULL, "原函数", "09HookDemo", 0);

        getchar();
        return 0;
}

int WINAPI MessageBoxProxy(IN HWND hWnd, IN LPCSTR lpText, IN LPCSTR lpCaption, IN UINT uType)
{
        return         ((PFNMESSAGEBOX)addr)(NULL, "Gxter", "Gxter", 0);
        //用地址调用一个API函数
}

关于修改EXE文件的导入表,实际上是一个很古老的话题了(如果您是此中高手,请不要在这篇文章浪费时间了,如果您发现了其中的问题,还请多多指教).一些PE相关的软件,也都实现了这样的功能,例如Stud_PE.
    Stud_PE通过添加一个新节并将导入表连同添加的内容一并复制到新节的方法来实现对DLL的导入.
    使用这样的方法只要是PE格式的EXE文件,都可以实现导入DLL的功能,但此方法,实现了通用性,却增加了文件的大小.
     对于存放在磁盘上PE文件,其中存在着大量的空隙,我们知道PE中的数据是按照一定的文件对齐来组织.IMAGE_OPTIONAL_HEADER结构中的FileAlignment成员保存着文件对齐的大小,这个成员是在链接的时候由链接器指定,如果使用VC来编写程序,可以使用link中的 /filealign来调整文件对齐的大小.
    这里,就是利用这些空隙来使EXE在启动时载入DLL(类似于一些病毒的技术),同时并不改变文件的大小.如何实现?还是要修改导入表.然而这种方法的缺点也是很明显的,并不是每个EXE都有足够的空间让我们来插入数据,按照我的测试,在 Windows 2003 Enterprise sp1中,lsass.exe以及services.exe都是有足够的空间进行插入,而在 Windows 2000 Advance Server sp4中,lsass.exe无法插入,services.exe可以插入.这些EXE文件的 FileAlignment为0x200H.为什么选择这些exe文件?说到这里我的意图已经很明显了,黑客之门便是利用这种方法实现自启动的木马.
    上面说了堆废话,现在直接贴上代码,具体实现请见程序的注释.这里假定您对PE格式有一定的了解.

//
// Copy from Matt Pietrek
// Given an RVA, look up the section header that encloses it and return a
// pointer to its IMAGE_SECTION_HEADER
//
PIMAGE_SECTION_HEADER
GetEnclosingSectionHeader(
    DWORD rva,
    PIMAGE_NT_HEADERS pNTHeader
)
{
    PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION32(pNTHeader);
    unsigned i;
    
    for ( i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ )
    {
        // Is the RVA within this section?
        if ( (rva >= section->VirtualAddress) && 
             (rva < (section->VirtualAddress + section->Misc.VirtualSize)))
            return section;
    }
    
    return 0;
}


int
AddImportDll(
    HANDLE hFile,
    DWORD  dwBase,
    PIMAGE_NT_HEADERS pNTHeader
)
{
    //
    // 通过OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
    // 获得导入表的RVA, 利用此RVA找到ImportTable所在的Section,之后计算Offset,公式:
    //     Offset = (INT)(pSection->VirtualAddress - pSection->PointerToRawData)
    // 之后利用Offset来定位文件中ImportTable的位置.
    //
    PIMAGE_IMPORT_DESCRIPTOR  pImportDesc = 0;
    PIMAGE_SECTION_HEADER     pSection = 0;
    PIMAGE_THUNK_DATA         pThunk, pThunkIAT = 0;
    int Offset = -1;

    pSection = GetEnclosingSectionHeader(
        pNTHeader->OptionalHeader.DataDirectory
            [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,
        pNTHeader);
    if(!pSection)
    {
        fprintf(stderr, "No Import Table../n");
        return -1;
    }

    Offset = (int) (pSection->VirtualAddress - pSection->PointerToRawData);

    //
    // 计算ImportTable在文件中的位置
    //
    pImportDesc =
        (PIMAGE_IMPORT_DESCRIPTOR)(pNTHeader->OptionalHeader.DataDirectory
                    [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress - Offset + dwBase);
    
    //
    // 取出导入的DLL的个数
    //
    int nImportDllCount = 0;
    while(1)
    {
        if ((pImportDesc->TimeDateStamp==0 ) && (pImportDesc->Name==0))
            break;
        pThunk    = (PIMAGE_THUNK_DATA)(pImportDesc->Characteristics);
        pThunkIAT = (PIMAGE_THUNK_DATA)(pImportDesc->FirstThunk);

        if(pThunk == 0 && pThunkIAT == 0)
                return -1;
        
        nImportDllCount++;
        pImportDesc++;
    }

    //
    // 恢复pImportDesc的值,方便下面的复制当前导入表的操作.
    //
    pImportDesc -= nImportDllCount;

    //
    // 取得ImportTable所在Section的RawData在文件中的末尾地址,计算公式:
    //     dwOrigEndOfRawDataAddr = pSection->PointerToRawData + pSection->Misc.VirtualSize
    //
    DWORD dwEndOfRawDataAddr = pSection->PointerToRawData + pSection->Misc.VirtualSize;

    PIMAGE_IMPORT_DESCRIPTOR pImportDescVector = 
        (PIMAGE_IMPORT_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 20 * (nImportDllCount+1));
    if(pImportDescVector == NULL)
    {
        fprintf(stderr, "HeapAlloc() failed. --err: %d/n", GetLastError());
        return -1;
    }
    CopyMemory(pImportDescVector+1, pImportDesc, 20*nImportDllCount);
    

    //
    // 构造添加数据的结构,方法笨拙了点.
    //
    struct _Add_Data
    {
        char    szDllName[256];            // 导入DLL的名字
        int        nDllNameLen;            // 实际填充的名字的长度
        WORD    Hint;                    // 导入函数的Hint
        char    szFuncName[256];        // 导入函数的名字
        int     nFuncNameLen;            // 导入函数名字的实际长度
        int     nTotal;                    // 填充的总长度
    } Add_Data;
    const char szDll[256]  = "test.dll";
    const char szFunc[256] = "Startup";
    strcpy(Add_Data.szDllName, szDll);
    strcpy(Add_Data.szFuncName, szFunc);

    //
    // +1表示'/0'字符
    //
    Add_Data.nDllNameLen  = strlen(Add_Data.szDllName) + 1;
    Add_Data.nFuncNameLen = strlen(Add_Data.szFuncName) + 1;
    Add_Data.Hint = 0;
    //
    // 计算总的填充字节数
    //
    Add_Data.nTotal = Add_Data.nDllNameLen + sizeof(WORD) + Add_Data.nFuncNameLen;

    //
    // 检查ImportTable所在的Section中的剩余空间是否能够容纳新的ImportTable.
    // 未对齐前RawData所占用的空间存放在pSection->VirtualSize中,用此值加上新的ImportTable长度与
    // 原长度进行比较.
    //
    // nTotalLen 为新添加内容的总长度
    // Add_Data.nTotal 为添加的DLL名称,Hint与导入函数的名字的总长度.
    // 8 为IMAGE_IMPORT_BY_NAME结构以及保留空的长度.
    // 20*(nImportDllCount+1) 为新的ImportTable的长度.
    //
    int nTotalLen = Add_Data.nTotal + 8 + 20*(nImportDllCount+1);
    printf("TotalLen: %d byte(s)/n", nTotalLen);
    if(pSection->Misc.VirtualSize + nTotalLen > pSection->SizeOfRawData)
    {
        fprintf(stderr, "No enough space!/n");
        return -1;
    }

    IMAGE_IMPORT_DESCRIPTOR Add_ImportDesc;
    //
    // ThunkData结构的地址
    //
    Add_ImportDesc.Characteristics = dwEndOfRawDataAddr + Add_Data.nTotal + Offset;
    Add_ImportDesc.TimeDateStamp = -1;
    Add_ImportDesc.ForwarderChain = -1;
    //
    // DLL名字的RVA
    //
    Add_ImportDesc.Name = dwEndOfRawDataAddr + Offset;
    Add_ImportDesc.FirstThunk = Add_ImportDesc.Characteristics;

    CopyMemory(pImportDescVector, &Add_ImportDesc, 20);

    //
    // 对文件进行修改
    //
    DWORD dwBytesWritten = 0;
    DWORD dwBuffer = dwEndOfRawDataAddr + Offset + Add_Data.nTotal + 8;
    long  lDistanceToMove = (long)&(pNTHeader->OptionalHeader.DataDirectory
        [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress) - dwBase;
    int nRet =0;

    //
    // 修改IMAGE_DIRECTOR_ENTRY_IMPORT中VirtualAddress的地址,
    // 使其指向新的导入表的位置
    //
    SetFilePointer(hFile, lDistanceToMove, NULL, FILE_BEGIN);

    printf("OrigEntryImport: %x/n", pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    nRet = WriteFile(hFile, (PVOID)&dwBuffer, 4, &dwBytesWritten, NULL);
    if(!nRet)
    {
        fprintf(stderr, "WriteFile(ENTRY_IMPORT) failed. --err: %d/n", GetLastError());
        return -1;
    }
    printf("NewEntryImport: %x/n", pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    //
    // 修改导入表长度,这个部分具体要修改为多少我也没弄明白,不过按照测试,改与不改都可以工作
    //
    dwBuffer = pNTHeader->OptionalHeader.DataDirectory
        [IMAGE_DIRECTORY_ENTRY_IMPORT].Size + 40;
    nRet = WriteFile(hFile, (PVOID)&dwBuffer, 4, &dwBytesWritten, NULL);
    if(!nRet)
    {
        fprintf(stderr, "WriteFile(Entry_import.size) failed. --err: %d/n", GetLastError());
        return -1;
    }

    //
    // 修改ImportTable所在节的长度
    //
    lDistanceToMove = (long)&(pSection->Misc.VirtualSize) - dwBase;
    SetFilePointer(hFile, lDistanceToMove, NULL, FILE_BEGIN);
    dwBuffer = pSection->Misc.VirtualSize + nTotalLen;
    nRet = WriteFile(hFile, (PVOID)&dwBuffer, 4, &dwBytesWritten, NULL);
    if(!nRet)
    {
        fprintf(stderr, "WriteFile(Misc.VirtualSize) failed. --err: %d/n", GetLastError());
        return -1;
    }

    //
    // 从节的末尾添加新的DLL内容
    // 偷点懒,返回值就不检查了..
    //
    lDistanceToMove = dwEndOfRawDataAddr;
    SetFilePointer(hFile, lDistanceToMove, NULL, FILE_BEGIN);
    nRet = WriteFile(hFile, Add_Data.szDllName, Add_Data.nDllNameLen, &dwBytesWritten, NULL);
    nRet = WriteFile(hFile, (LPVOID)&(Add_Data.Hint), sizeof(WORD), &dwBytesWritten, NULL);
    nRet = WriteFile(hFile, Add_Data.szFuncName, Add_Data.nFuncNameLen, &dwBytesWritten, NULL);
    dwBuffer = dwEndOfRawDataAddr + Add_Data.nDllNameLen + Offset;
    nRet = WriteFile(hFile, (LPVOID)&dwBuffer, 4, &dwBytesWritten, NULL);
    dwBuffer = 0;
    nRet = WriteFile(hFile, (LPVOID)&dwBuffer, 4, &dwBytesWritten, NULL);
    nRet = WriteFile(hFile, (LPVOID)pImportDescVector, 20*(nImportDllCount+1), &dwBytesWritten, NULL);

    HeapFree(GetProcessHeap(), 0, pImportDescVector);
    return 0;
}


下面是测试用的DLL代码.

#include <windows.h>
#pragma comment(lib, "user32")

#define __DLL_EXPORT extern "C" __declspec(dllexport)

__DLL_EXPORT void Startup();

BOOL
WINAPI DllMain(
    HINSTANCE hinstDLL,
    DWORD fdwReason,
    LPVOID lpvReserved
)
{
    switch(fdwReason)
    {
    case DLL_PROCESS_ATTACH:
        MessageBox(NULL, "Hook Ok!", "info", MB_OK);
        break;

    case DLL_THREAD_ATTACH:
        break;

    case DLL_PROCESS_DETACH:
        break;

    case DLL_THREAD_DETACH:
        break;
    }

    return TRUE;
}


__DLL_EXPORT void
Startup()
{
    MessageBox(NULL, "Startup()", "info", MB_OK);
}


    这段代码还有些问题,一些EXE文件并不能保证在修改后正确的运行,如何解决?如果您对此感兴趣,请动手来寻找答案吧.
     说点题外话,如果您的系统不幸中了黑客之门,并且您的手头没有windows安装光盘或者DLLCACHE中也没有备份的话.首先要找到被修改的exe文件,之后建立一个备份用Stud_PE打开这个备份,在"头部"标签中"更多"下拉菜单中选IMAGE_DIR_ENTRY_DEBUG,这时,下拉菜单下面的两个对话框中会有两个值,这两个值就是黑可之门修改之前原始的导入表的位置.用这两个值替换"导入表"后面的内容,之后选"保存到文件",退出 Stud_PE用inuse替换,重启之后删除后门dll便可以了.

使用工具:
    hkdoordll.dll(1.1版本)
    Stud_PE 2.0.0.1
    dumpbin.exe

参考资料:
    《Windows 95 System programming SECRETS (中译本

HOOK API修改IAT实现进程隐藏 1 .技术与实现 每个调用的 API 函数地址都保存在 IAT 表中。 API 函数调用时,每个输入节( IMPORT SECTION )所指向的 IAT 结构如下图所示。 程序中每个调用API 函数的CALL指令所使用的地址都是相应函数登记在IAT表的地址。所以为了截获API 函数,我们将IAT表中的地址换成用户自己的API PROXY函数地址,这样每个API调用都是先调用用户自己的A... 阅读详情

相关推荐

HOOK其他进程API和全局HOOK-API

HOOK是一种WINDOWS下存在很久的技术了。 HOOK一般分两种1。HOOK MESSAGE  2。HOOK API 本问讨论的是HOOK API。(如果你是HOOK高手就不要看了) 在最初学HOOK-API的时候通常都是通过覆盖地址和修改IAT的方法。通过这两种技术,我们基本都可以实现对本进程的API函数进行HOOK了。但是在高兴之余会有点遗憾,怎么才能HOOK其他进程的API函数呢?怎么才

4283

Delphi IATHook API

DelphiIAT API Hook 算還沒完成 但已經可以實現Hook了 還沒搞定CreateRemoteThread 所以只能修改自己得IAT(好爛)

Hook技术:IAT Hook详细讨论修改IAT地址和恢复

IAT Hook是Ring3层常用的Hook之一,主要思路大家都知道,就是修改IAT中的函数地址。

weixin_43742894的博客 3294

Delphi API HOOK完全说明

什么是API Hook不知道大家是否还记得,在DOS 系统中编程,经常会采取截取中断向量的技术:我们可以设置新的中断服务程序,当系统其他的程序调用这个中断时,就让它先调用我们自己设置的新的中断服务程 序,然后再调用原来的中断服务程序,这样就能够获得非凡的控制权。许多优秀的软件和大多数DOS 病毒程序都采用了这个方法。 在Windows 中,我们也可以采取类似技术。当系统调用某个API 函数时,就会先进入我们自己的函数,然后再调用原来的API 函数,这样,我们的程序就可以取得更多的控制权,我们就可对Windows 系统中的任意一个函数调用进行动态拦截、跟踪、修改和恢复,就可让Windows 系统中的任意一个函数按我们的设想工作。这种技术有许多名称,比如“陷阱技术”、“重入技术”等,不过我认为还是API Hook 最贴切。原因嘛,等一下你看编程就明白了。

IAT hook实现 (修改pe中的导入表实现hook)

IDA hook的编写 1. 实现hook的原理 在pe文件中有导入表,导入表中用函数名字和地址,我们把这个地址改变做到hook的效果。一下所有代码是32位的只使用了c语言 之前分析过导入表,本文不在分析只实现hook pe结构解析 实现所用到的Windows api //用于获取当前模块的基地址 GetModuleHandleA(NULL) HMODULE WINAPI GetModuleHandleA( _In_opt_ LPCSTR lpModuleName ); //用于修改内存属

&Ψ的博客 1711

4.3 IAT Hook 挂钩技术

IATImport Address Table)Hook是一种针对Windows操作系统的API Hooking 技术,用于修改应用程序对动态链接库(DLL)中导入函数的调用。IAT是一个数据结构,其中包含了应用程序在运行时使用的导入函数的地址。 IAT Hook的原理是通过修改IAT中的函数指针,将原本要调用的函数指向另一个自定义的函数。这样,在应用程序执行时,当调用被钩子的函数时,实际上会执行自定义的函数。通过IAT Hook,我们可以拦截和修改应用程序的函数调用,以实现一些自定义的行为,比如记录日

微软技术分享 1万+

Windows HOOK学习(一):简单的IAT HOOK

(若文章有误的请放过,请在留言区告诉我修改一下) 1. 前言 由于毕设项目的需要,从一个毫无基础的小白(只会C语言基础,windows核心编程,汇编都一窍不通,学的很艰难啊),开始慢慢写Hook,记录一下学习过程和成果。 顺便梳理一下学到的知识。 2.准备工作 要学习Hook,当然首先要准备了解一下基础知识和准备编译器啦。 DLL:全名是Dynamic Link Library(动态链接库)。作用...

weixin_42777366的博客 1435

修改IAT法来hook api

通过学习PE文件的基本知识,实现一个hook api,并利用MessageBox来简单测试: #include #include #include using namespace std; typedef int(WINAPI* PFNMESSAGEBOX)(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType); int* a

junjie1595的专栏 548

修改IAT实现本进程API HOOK

<br />//修改IAT实现本进程API HOOK //coded by xicao //QQ:327062448 //E-MAIL:xicao54007@sina.com #include <windows.h> #include <imagehlp.h>//ImageDirectoryEntryToData #pragma comment(lib,"imagehlp.lib") /******************************************************

leeeryan 1730

使用API-HOOK修改IAT的地址

api-hook

CHkylin的博客 1175

修改导入表HOOK API(ring3_iat_exe_hook_Messagebox)

IATImport Address Table 是PE(可以理解为EXE)的输入地址表,我们知道一个程序运行时可以要调用多个模块,或都说要调用许多API函数,但这些函数不一定都在EXE本身中,例如你调用Messagebox来显示一个对话框时,你只需要调用它,你并没有编写Messagebox的函数的实现过程,Messagebox的函数的实现过程实际上是在user32.dll这个库文件中,当这个程序

cbh84663973的专栏 859

(转)替换 IAT 中的导入函数地址实现 Hook API

替换 IAT 中的导入函数地址实现 Hook API

修改IATHOOK API

#include #include #include #define  UNICODE #define  _UNICODE   PIMAGE_DOS_HEADER  pDosHeader; PIMAGE_NT_HEADERS  pNTHeaders; PIMAGE_OPTIONAL_HEADER   pOptHeader; PIMAGE_IMPORT_DESCRIPTOR

多媒体编程、网络编程、系统编程、网络安全编程、驱动编程 802

(转)修改IAT实现本进程API HOOK

http://www.cppblog.com/gezidan/archive/2011/08/08/152757.html // IATHook.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "IATHook.h" #include &...

weixin_30432579的博客 181

Win32 IAT HOOK

需要 自己实现的HOOK函数 获取IAT 表 函数地址 自己定义一个 函数,与系统函数 的参数和一样 HOOK的实现过程 获取模块的基址 遍历 IAT表里面的函数地址 FirstThunk 指向的是IAT表 通过函数指针调用没修改过的函数 ...

lygl35的博客 227

IAT HOOK

IAT Hook的实现

enjoy5512的博客 1万+

修改导入表HOOK API(ring3_iat_exe_hook_Messagebox)<转>

IATImport Address Table 是PE(可以理解为EXE)的输入地址表,我们知道一个程序运行时可以要调用多个模块,或都说要调用许多API函数,但这些函数不一定都在EXE本身中,例如你调用Messagebox来显示一个对话框时,你只需要调用它,你并没有编写Messagebox的函数的实现过程,Messagebox的函数的实现过程实际上是在user32.dll这个库文件中,当这个

Miibotree 1475

通过下全局API Hook修改IAT中函数地址为何截获不了Ws2_32.dll的recv()

(2)   在ActiveKey.h文件中加入HOOKAPI结构,此结构用来存储被挡截API函数名称、原API函数地址和替代函数地址。            typedef   struct   tag_HOOKAPI          {          LPCSTR   szFunc;//被HOOKAPI函数名称。        PROC   pNewProc;//替代函数地址。    

xu的blog 3509
上一篇: 挖掘操作系统内部未导出函数,将注入进行到底
下一篇: HOOK其他进程API和全局HOOK-API
iiprogram
博客等级 码龄25年 1066粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值