zoukankan      html  css  js  c++  java
  • 利用HOOKAPI拦截文件操作

     
    先读下HookAPI 使用文档:

    功能简介

    HookAPI 是一个截获Windows 32API函数的开发包,它可以在Windows调用某个API函数的时候,先调用自己编写的函数,从而实现特殊的功能。

    HookAPI同样也适用于截获用户自己编写的DLL文件中的输出函数。

     

    1.5系统特点:

    1自己编写的替代函数的参数形式和原API函数完全一样,方便了DelphiVB用户的使用。

    2实时截获所有新建立的进程,即进程建立后马上安装钩子,而不是采用定时扫描进程的方法

    3由于不采用定时扫描进程的方法,所以系统资源消耗少,基本上看不到消耗CPU资源。

    4新建立的InstDLL动态库,减少了用户调用HookAPI的代码。

     

    运行和开发平台Windows NT/2000/9x/XP

    包含的文件列表

    EXE目录】:调用InstHook.dll来安装HookAPI的执行程序

    InstHook目录】:安装HookAPIDLL程序

    dll目录】:NT/2000/XP/XP下截获32API函数的DLL程序

    HOOKAPI9x.dll】:Win9x下截获32API函数的DLL程序

    EXE目录】:HookAPI.exe的源码

    HOOKSOCKET目录】:截获Socket函数的mydll例子

    HOOKREG目录】:截获注册表函数的mydll例子

    HOOKFILE目录】:截获文件存取的mydll例子

    HOOKFILE9x目录】:win9x下的截获文件存取的mydll_9x例子

    HookFile_Delphi目录】:截获文件存取的Delphi下的mydll的例子

    HookSocket_Delphi目录】:截取Socket函数的Delphi下的mydll的例子

    使用:用户编写要截获的API函数相对应的自己的实现函数,编译成mydll.dll,同时在自己的程序中调用InstHook.dll中的安装/卸载函数就可以实现自己的截获过程。


    开发指南

    用户需要做的就是编写一个替换老API函数的mydll.dll,并在自己的程序中调用InstHook.dll中的安装/卸载函数就行了。

    Mydll文件的编写:

    1) 建立生成DLL的工程文件mydll

    2) 如果工程名称不是mydll,则如果是win9x,则在工程文件的设置中修改生成的目标输出文件为mydll_9x.dll,其他操作系统(NT/2K/XP)输出文件为mydll.dll

    3) 编写含有自己的调用过程的mydll.cpp程序和DLL输出函数说明文件mydll.def

    4) 编译生成mydll.dll/mydll_9x.dll

    mydll.cpp文件的编写

    从三个例子程序可以看出,mydll.cpp文件其实非常简单,它包含如下内容

    1) 包含mydll.h文件,此文件中只有一个MYAPIINFO结构说明:

    typedef struct

    {

           char *module_name;

           char *function_name;

           char *myfunc_name;

    }MYAPIINFO;

    module_name是要截获的DLL或其他模块文件的名称,如kernel32.dll

    function_name是要截获的API或用户DLL文件中函数的名称和参数,类似C中的说明格式,如connect函数为:connect(SOCKET, struct sockaddr *, INT)

    myfunc_name为自己编写的替代函数的名称,如自己编写了myconnect函数,则myfunc”myconnect”

    2) 为生成win9x下的dll文件(mydll_9x.dll)加入下列编译选项

    #ifdef WIN95

    #pragma code_seg("_INIT")

    #pragma comment(linker,"/SECTION:.bss,RWS /SECTION:.data,RWS /SECTION:.rdata,RWS /SECTION:.text,RWS /SECTION:_INIT,RWS ")

    #pragma comment(linker,"/BASE:0xBFF70000")

    #endif

    如果是生成的win9x下的dll文件(mydll_9x.dll),那么编译选项里要先定义WIN95

    3) 包含一个MYAPIINFO myapi_info[]结构数组定义并赋值,最后必须包含一个NULL项。此结构数组就是要截获的函数信息,如:

    MYAPIINFO myapi_info[] =

    {

           {"WSOCK32.DLL", "socket(INT, INT, INT)", “mysocket”},

    {"WSOCK32.DLL", "connect(SOCKET, struct sockaddr *, INT)", “myconnect”},

           {"WSOCK32.DLL", "recv(INT, char *, INT, INT)", “myrecv”},

           {"WSOCK32.DLL", "send(INT, char *, INT, INT)", “mysend”},

    {"ADVAPI32.DLL", "RegOpenKeyA(HKEY, LPCSTR, PHKEY)", “myRegOpenKeyA”},

    {NULL,NULL,NULL} //最后必须包含此项

    };

    4) 必须包含函数GetMyAPIInfo,如下:

    MYAPIINFO *GetMyAPIInfo()

    {

           return &myapi_info[0];

    }

    5) 编写替换函数,替换函数格式为:

    DWORD _cdecl MyFuncName(type1 param1, type2, param2, …)

    其中函数必须为WINAPI调用方式(Delphi下为stdcall),函数的参数声明必须和原api函数中的参数相对应,如:

    int WINAPI myconnect(SOCKET s, struct sockaddr *name, int namelen)

    {

           struct sockaddr_in *paddr =(struct sockaddr_in *)name;

           char *ip =inet_ntoa(paddr->sin_addr);

           int port =ntohs(paddr->sin_port);

    int ret =connect(s, name, namelen);

    int err=WSAGetLastError();

           WriteLog("connect: ip=%s, port=%d, ret=%d\n", ip, port, ret);

           // check filter

        WSASetLastError(err);

           return ret;

    }

    在此例子中,有保存和恢复错误码的代码,因为在编写自己的处理过程时,错误码可能会被修改,而原调用程序很可能根据错误码来判断进一步的动作;即使在myconnect中不调用原函数connect,那么在myconnect返回时,也要使用WSASetLastErrorSetLastError来正确设置错误码。其他替换函数也应该这样做。

    另外,在win9x下,最好在mydll中调用一下任意一个原先的api函数,以便mydll能调用原先的dll模块,否则就要在hookapi.exe中调用mydll前使用LoadLibrary调用一下原先的dll文件;否则将Hook不成功。


    mydll.def文件的编写

    mydll.def中包含GetMyAPIInfo和自己编写的替换函数的输出说明,如下:

    EXPORTS

           GetMyAPIInfo         @1

           MyFunc1                            @2

           MyFunc2                            @3

    InstallHook.dll文件的使用

    InstHook.dll中的内容很简单,只有四个函数(参见InstHook.h)

    1) int WINAPI InitHookAPI();

    此函数初始化HookAPI

    2) int WINAPI HookAllProcesses();

    此函数实现截获和替换mydll中定义的API

    3) int WINAPI UnhookAllProcesses();

    此函数恢复原先系统的mydll中定义的API

    4) int WINAPI NTHookProcess(DWORD process_id);

    此函数在NT下截获和替换某个特定的进程中的mydll中定义的API,进程必须已经存在

    5) int WINAPI NTUnhookProcess(DWORD process_id);

    此函数在NT下恢复某个特定的进程中的mydll中定义的API,进程必须已经存在

    6) int WINAPI NTHookProcess2(char *mod_name);

    此函数在NTHook某个文件或模块名为mod_name的进程,进程必须已经存在

    7) int WINAPI NTUnhookProcess2(char *mod_name);

    此函数在NTUnhook此函数在NT下截获和替换某个文件或模块名为mod_name的进程,进程必须已经存在


    例子说明

    API中实现了三个例子,每个例子都是截获函数调用,并写日志到c:\hookapi.log,并未进行其他的操作

    截获Socket函数的例子

    本例子中演示了截获Windows 32Socket API函数,截获的DLL文件为WSOCK32.dll,截获的函数有socketconnectrecvsend

    mysocket函数:只是写日志。用户可以不调用socket()函数而直接返回一个socket值,从而在所有的socket函数调用中实现虚假的网络调用,欺骗应用程序。

    myconnect函数:写日志。用户可以在此如下修改myconnect函数:不调用connect()而直接返回成功,欺骗应用程序;connect另外一个主机地址;connect另外一个端口。

    myrecv函数:写日志。用户可以在此如下修改myrecv函数:不调用recv()函数而直接填充自己的buf,欺骗应用程序;调用recv,记录分析接收的数据包;调用recv,解密数据包;调用recv,使用send和另一端再次通讯;等等。

    mysend函数:写日志。用户可以在此如下修改mysend函数:不调用send()函数而直接返回成功,欺骗应用程序;记录分析要发送的数据包;加密数据包(使用另一个buffer),然后调用send将加密包发送出去;等等。

    但截获标准Socket API并不能获取所有系统对网络存取的内容,如驱动程序对网络的存取,如果要截获所有网络存取情况,可以看ipfilter等相关的源码,在编程沙龙上有很多。

    截获注册表函数的例子

    通过截获注册表函数和注册表的值,可以记录分析程序使用和创建了哪些注册表项,用于去除日期限制等应用。但截获标准注册表API并不能获取所有系统对文件存取的内容,如驱动程序对注册表的存取,如果要截获所有注册表存取情况,可以看regmon的源码,在编程沙龙上有。

    截获文件存取的例子

    通过截获文件存取,用户可以分析某个程序的文件存取情况等,但截获标准文件API并不能获取所有系统对文件存取的内容,如驱动程序对文件的存取,如果要截获所有文件存取情况,可以看filemon的源码,在编程沙龙上有。

     

    根据上述例子,用户可以编写自己感兴趣的mydll,截获系统API或某些应用程序附带的dll中的函数的使用情况,来实现自己的特殊功能,如通过截获CreateProcessW来限制用户只能执行特定的应用程序或打开特定的文件。

    编译和运行

    将例子编译成mydll.dll/mydll_9x.dll,将mydll.dllmydll_9x.dllinjlib.dllHookAPINT.dllHookAPI9x.dllInstHook.dll放到和调用InstHook.dll的应用程序(HookAPI.exe)相同的目录下。然后运行调用InstHook.dll<SPAN style="FONT-FAMILY: 宋体;

     

     


    #include "stdafx.h"
    #include <stdio.h>
    #include "mydll.h"

    #ifdef WIN95
    #pragma code_seg("_INIT")
    #pragma comment(linker,"/SECTION:.bss,RWS /SECTION:.data,RWS /SECTION:.rdata,RWS /SECTION:.text,RWS /SECTION:_INIT,RWS ")
    #pragma comment(linker,"/BASE:0xBFF70000")
    #endif

    BOOL APIENTRY DllMain( HANDLE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
          )
    {
        return TRUE;
    }

    void WriteLog(char *fmt,...)
    {
     va_list args;
     char modname[200];
     char temp[5000];
     HANDLE hFile;
            DWORD dw;

     GetModuleFileName(NULL, modname, sizeof(modname));
     if((hFile =CreateFile("c:\\hookapi.log", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) <0)
     {
      return;
     }
     
     _llseek((HFILE)hFile, 0, SEEK_END);
     wsprintf(temp, "mydll.dll:%s:", modname); 
     WriteFile(hFile, temp, strlen(temp), &dw, NULL); 
     va_start(args,fmt);
     vsprintf(temp, fmt, args);
     va_end(args);

     WriteFile(hFile, temp, strlen(temp), &dw, NULL);
     wsprintf(temp, "\r\n");
     WriteFile(hFile, temp, strlen(temp), &dw, NULL);

     _lclose((HFILE)hFile);
    }

    HANDLE WINAPI myCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
    {         
     char temp[200];
     GetModuleFileName(NULL, temp, sizeof(temp));
     WriteLog("%s, myCreateFileA:filename=%s", temp, lpFileName);
     //MessageBox(NULL, temp, "mydll", MB_OK);
     if(strstr(lpFileName, "aaa") !=NULL) return NULL;
     return CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
      dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
    }

    HANDLE WINAPI myCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
    {
     //MessageBox(NULL, "myCreateFileW", "ok", MB_OK);
                                 
     char temp[200];
     GetModuleFileName(NULL, temp, sizeof(temp));
     char fname[128];
     WideCharToMultiByte( CP_ACP, 0, lpFileName, -1, fname, 128,NULL,NULL);

     WriteLog("%s, myCreateFileW:filename=%s", temp, fname);
     //MessageBox(NULL, temp, "mydll", MB_OK);
     
     if(strstr(fname, "aaa.txt") !=NULL)
     {
      WriteLog("CreateFileW aaa found!");
      return CreateFileA("c:\\temp\\bbb.txt", dwDesiredAccess, dwShareMode, lpSecurityAttributes,
       dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
      //SetLastError(ERROR_FILE_NOT_FOUND);
      //return NULL;
     }

     return CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
      dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
    }


    BOOL WINAPI myReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
     LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
    {
     WriteLog("ReadFile:handle=%x", hFile);

     return ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
    }

    BOOL WINAPI myReadFileEx(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
      LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
    {
     WriteLog("ReadFileEx");

     return ReadFileEx(hFile, lpBuffer, nNumberOfBytesToRead,
      lpOverlapped, lpCompletionRoutine);
    }

    BOOL WINAPI myDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
    {

    //     struct _iobuf f;
      WriteLog("DeviceIoControl=%x", hDevice);
      WriteLog("dwIoControlCode=%x,lpInBuffer=%x,lpOutBuffer=%x,lpBytesReturned=%x ",lpInBuffer,dwIoControlCode,lpOutBuffer,lpBytesReturned);
    //      fprintf(f, "DeviceIoControl(%x, %x, ...)\n", hDevice, dwIoControlCode);
            return DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned,NULL);
    }

    MYAPIINFO myapi_info[] =
    {
     {"KERNEL32.DLL", "CreateFileA", 7, "myCreateFileA"},
     {"KERNEL32.DLL", "CreateFileW", 7, "myCreateFileW"},
     {"KERNEL32.DLL", "ReadFile", 5, "myReadFile"},
     {"KERNEL32.DLL", "ReadFileEx", 5, "myReadFileEx"},
        {"KERNEL32.DLL", "DeviceIoControl", 8, "myDeviceIoControl"},
     {NULL,NULL,NULL}
    };

    MYAPIINFO *GetMyAPIInfo()
    {
     return &myapi_info[0];
    }



    网友: laomms 时间:2007-05-18 10:31:04
    调用程序:
    #include <windows.h>
    #include "resource.h"

    #define MsgBox(msg) MessageBox(NULL, msg, "HookAPI - www.programsalon.com", MB_OK)

    BOOL CALLBACK MainDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);

    typedef int (WINAPI *FuncHookOneProcess2)(HWND hwndNotify, char *exe_name);
    typedef int (WINAPI *FuncUnhookOneProcess2)(char *exe_name);
    typedef int (WINAPI *FuncHookAllProcess)();
    typedef int (WINAPI *FuncUnhookAllProcess)();

    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
        WriteProfileString("HookAPI", "exe_name", "HookAPI.exe");

        int isNT =false;
        OSVERSIONINFO VersionInfo;
        VersionInfo.dwOSVersionInfoSize =sizeof(OSVERSIONINFO);

        if(!GetVersionEx(&VersionInfo))
            return false;

        if(VersionInfo.dwPlatformId ==VER_PLATFORM_WIN32_NT)
            isNT =true;

        HINSTANCE hLib;
        if(isNT)
            hLib =LoadLibrary("HookAPINT.dll");
        else
            hLib =LoadLibrary("HookAPI9x.dll");
        if(hLib ==NULL)
        {
            MessageBox(NULL, "LoadLibrary HookAPIxx.dll failed", "HookAPI.exe", MB_OK);
            return false;
        }

        FuncHookOneProcess2 HookOneProcess2 =(FuncHookOneProcess2)GetProcAddress(hLib, "HookOneProcess2");
        FuncUnhookOneProcess2 UnhookOneProcess2 =(FuncUnhookOneProcess2)GetProcAddress(hLib, "UnhookOneProcess2");
        FuncHookAllProcess HookAllProcess =(FuncHookAllProcess)GetProcAddress(hLib, "HookAllProcess");
        FuncUnhookAllProcess UnhookAllProcess =(FuncUnhookAllProcess)GetProcAddress(hLib, "UnhookAllProcess");

        if(HookAllProcess ==NULL)
        {
            MsgBox("HookAllProcess ==NULL");
            FreeLibrary(hLib);
            return 0;
        }
        
        if(UnhookAllProcess ==NULL)
        {
            MsgBox("UnhookAllProcess ==NULL");
            FreeLibrary(hLib);
            return 0;
        }
        if(HookAllProcess() <0)
        {
            MsgBox("HookAllProcesses error!");
            UnhookAllProcess();
            FreeLibrary(hLib);
            return 0;
        }
        // 测试只Hook一个正在运行的程序,下面的函数已经在1.6版本中取消,但还是很有用,所以以后版本中还是会提供
    /*
        if(HookOneProcess2(NULL, "ship.exe") <0)
        {
            MsgBox("HookOneProcess failed!");
            return  0;
        }
    */
        /// HookAllProcesses2是针对无法截获按Ctrl-Alt_Del键时运行的任务管理器等程序的情况使用的。
        /*if(HookAllProcesses2(1000) <0)
        {
            MsgBox("HookAllProcesses error!");

            return 0;
        }*/
        /*char temp[200], temp2[20], temp3[256];

        char *p =(char *)0x7FCEDCF1;//(char *)funcSHFileOperationA;

        wsprintf(temp, "func:%x", p);
        wsprintf(temp2, "%x,%x,%x,%x", *p&0xFF, *(p+1)&0xFF, *(p+2), *(p+3), *(p+4));
        wsprintf(temp3, "[%s], %s", temp, temp2);
        MessageBox(NULL, temp3, "ok", MB_OK);*/

        DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, MainDlgProc);

        UnhookAllProcess();
        FreeLibrary(hLib);

        return 0;
    }

    BOOL CALLBACK MainDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch(msg)
        {
        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
            case IDOK:
                EndDialog(hDlg, IDOK);
                break;
            case ID_HIDE:
                ShowWindow(hDlg, SW_HIDE);
                break;
            }
        default:
            break;
        }

        return FALSE;
    }
  • 相关阅读:
    公司系统缓慢-分析数据库CPU过高原因-连接数
    克隆虚拟机的相关设置
    centos7基本设置和优化
    遇到的问题和解决集中
    chrome优化调教
    shell三剑客之小弟grep
    迭代器和生成器
    函数进阶
    函数介绍&参数的使用
    文件处理中光标的移动以及文件的修改
  • 原文地址:https://www.cnblogs.com/love2wllw/p/1744103.html
Copyright © 2011-2022 走看看