文件钩子实现

本文介绍了 JNotify 库,它允许 Java 应用程序注册文件系统事件。源码分析涵盖了 WatchData 和 Win32FSHook 类,这两个类实现了 Windows 平台上的文件系统监控,包括目录变更、文件操作回调等功能。通过示例展示了如何使用这些类进行文件系统的监视和事件处理。
摘要由CSDN通过智能技术生成

WatchData.h

/*******************************************************************************

 * JNotify - Allow java applications to register to File system events.

 *

 * Copyright (C) 2005 - Content Objects

 *

 * This library is free software; you can redistribute it and/or

 * modify it under the terms of the GNU Lesser General Public

 * License as published by the Free Software Foundation; either

 * version 2.1 of the License, or (at your option) any later version.

 *

 * This library is distributed in the hope that it will be useful,

 * but WITHOUT ANY WARRANTY; without even the implied warranty of

 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU

 * Lesser General Public License for more details.

 *

 * You should have received a copy of the GNU Lesser General Public

 * License along with this library; if not, write to the Free Software

 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

 *

 ******************************************************************************

 *

 * Content Objects, Inc., hereby disclaims all copyright interest in the

 * library `JNotify' (a Java library for file system events).

 *

 * Yahali Sherman, 21 November 2005

 *    Content Objects, VP R&D.

 *

 ******************************************************************************

 * Author : Omry Yadan

 ******************************************************************************/

#ifndef WATCHDATA_H_

#define WATCHDATA_H_

#include <windows.h>

#include <winbase.h>

#include <winnt.h>

#include <string>

using namespace std;

typedef void(*ChangeCallback)(int watchID, int action, const WCHAR* rootPath, const WCHAR* filePath);

class WatchData

{

private:

    static int _counter;

    WCHAR* _path;

    int _watchId;

    HANDLE _hDir;

    int _mask;

    bool _watchSubtree;

    DWORD _byteReturned;

    OVERLAPPED _overLapped;

    char _buffer[8196];

    HANDLE _completionPort;

public:

    WatchData();

    WatchData(const WCHAR* path, int mask, bool watchSubtree, HANDLE completionPort);

    virtual ~WatchData();

    const char* getBuffer() { return _buffer; }

    //  FILE_NOTIFY_INFORMATION* getNotifyInfo(){return _notifyInfo;}

    const int getBufferSize() { return sizeof(_buffer); }

    //  const DWORD getBytesReturned() {return _byteReturned;}

    const WCHAR* getPath() { return _path; }

    const int getId() { return _watchId; }

    //  const HANDLE getDirHandle() {return _hDir;}

    //  const int getMask() {return _mask;}

    int watchDirectory();

    // cancel pending watch on the hDir, returns 0 if okay or errorCode otherwise.

    int unwatchDirectory();

};

#endif /*WATCHDATA_H_*/

Win32FSHook.h

/*******************************************************************************

 * JNotify - Allow java applications to register to File system events.

 *

 * Copyright (C) 2005 - Content Objects

 *

 * This library is free software; you can redistribute it and/or

 * modify it under the terms of the GNU Lesser General Public

 * License as published by the Free Software Foundation; either

 * version 2.1 of the License, or (at your option) any later version.

 *

 * This library is distributed in the hope that it will be useful,

 * but WITHOUT ANY WARRANTY; without even the implied warranty of

 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU

 * Lesser General Public License for more details.

 *

 * You should have received a copy of the GNU Lesser General Public

 * License along with this library; if not, write to the Free Software

 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

 *

 ******************************************************************************

 *

 * Content Objects, Inc., hereby disclaims all copyright interest in the

 * library `JNotify' (a Java library for file system events).

 *

 * Yahali Sherman, 21 November 2005

 *    Content Objects, VP R&D.

 *

 ******************************************************************************

 * Author : Omry Yadan

 ******************************************************************************/

#ifndef WIN32FSHOOK_H_

#define WIN32FSHOOK_H_

#include <windows.h>

#include <string>

#include <map>

#include <queue>

#include <utility>

#include "WatchData.h"

using namespace std;

class Event

{

public:

    int _watchID;

    int _action;

    WCHAR* _rootPath;

    WCHAR* _filePath;

    Event(int wd, int action, const WCHAR* rootPath, const WCHAR* filePath)

    {

        _watchID = wd;

        _action = action;

        size_t len1 = wcslen(rootPath);

        size_t len2 = wcslen(filePath);

        _rootPath = new WCHAR[len1 + 1];

        _filePath = new WCHAR[len2 + 1];

        wcsncpy(_rootPath, rootPath, len1);

        _rootPath[len1] = 0;

        wcsncpy(_filePath, filePath, len2);

        _filePath[len2] = 0;

    }

    ~Event()

    {

        delete[] _rootPath;

        delete[] _filePath;

    }

};

class Win32FSHook

{

private:

    static const DWORD DELETE_WD_SIGNAL = 99999997;

    static const DWORD EXIT_SIGNAL = 99999998;

    static Win32FSHook* instance;

    // running flag

    bool _isRunning;

    // thread handle

    HANDLE _mainLoopThreadHandle;

    HANDLE _completionPort;

    // critical seaction

    CRITICAL_SECTION _cSection;

    // watch id 2 watch map

    map<int, WatchData*> _wid2WatchData;

    // Thread function

    static DWORD WINAPI mainLoop(LPVOID lpParam);

    ChangeCallback _callback;

    void watchDirectory(WatchData* wd);

    CRITICAL_SECTION _eventQueueLock;

    HANDLE _eventQueueEvent;

    void postEvent(Event* event);

    HANDLE _eventsThread;

    static DWORD WINAPI eventLoop(LPVOID lpParam);

    queue<Event*> _eventQueue;

    WatchData* find(int wd);

public:

    static const int ERR_INIT_THREAD = 1;

    Win32FSHook();

    virtual ~Win32FSHook();

    void init(ChangeCallback callback);

    int add_watch(const WCHAR* path, long notifyFilter, bool watchSubdirs, DWORD& error);

    void remove_watch(int watchId);

};

#endif /*WIN32FSHOOK_H_*/

WatchData.cpp

/*******************************************************************************

 * JNotify - Allow java applications to register to File system events.

 *

 * Copyright (C) 2005 - Content Objects

 *

 * This library is free software; you can redistribute it and/or

 * modify it under the terms of the GNU Lesser General Public

 * License as published by the Free Software Foundation; either

 * version 2.1 of the License, or (at your option) any later version.

 *

 * This library is distributed in the hope that it will be useful,

 * but WITHOUT ANY WARRANTY; without even the implied warranty of

 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU

 * Lesser General Public License for more details.

 *

 * You should have received a copy of the GNU Lesser General Public

 * License along with this library; if not, write to the Free Software

 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

 *

 ******************************************************************************

 *

 * Content Objects, Inc., hereby disclaims all copyright interest in the

 * library `JNotify' (a Java library for file system events).

 *

 * Yahali Sherman, 21 November 2005

 *    Content Objects, VP R&D.

 *

 ******************************************************************************

 * Author : Omry Yadan

 ******************************************************************************/

#include "WatchData.h"

 //#include "Logger.h"

int WatchData::_counter = 0;

WatchData::WatchData()

{

}

WatchData::~WatchData()

{

    if (_path != NULL) free(_path);

    _hDir = 0;

}

WatchData::WatchData(const WCHAR* path, int mask, bool watchSubtree, HANDLE completionPort)

    :

    _watchId(++_counter),

    _mask(mask),

    _watchSubtree(watchSubtree),

    _byteReturned(0),

    _completionPort(completionPort)

{

    _path = _wcsdup(path);

    _hDir = CreateFileW(_path,

        FILE_LIST_DIRECTORY | GENERIC_READ,

        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,

        NULL, //security attributes

        OPEN_EXISTING,

        FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);

    if (_hDir == INVALID_HANDLE_VALUE)

    {

        throw GetLastError();

    }

    if (NULL == CreateIoCompletionPort(_hDir, _completionPort, (ULONG_PTR)_watchId, 0))

    {

        throw GetLastError();

    }

}

int WatchData::unwatchDirectory()

{

    int c = CancelIo(_hDir);

    if (_hDir != INVALID_HANDLE_VALUE) CloseHandle(_hDir);

    if (c == 0)

    {

        return GetLastError();

    }

    else

    {

        return 0;

    }

}

int WatchData::watchDirectory()

{

    memset(_buffer, 0, sizeof(_buffer));

    memset(&_overLapped, 0, sizeof(_overLapped));

    if (!ReadDirectoryChangesW(_hDir,

        _buffer,//<--FILE_NOTIFY_INFORMATION records are put into this buffer

        sizeof(_buffer),

        _watchSubtree,

        _mask,

        &_byteReturned,

        &_overLapped,

        NULL))

    {

        return GetLastError();

    }

    else

    {

        return 0;

    }

}

Win32FSHook.cpp

/*******************************************************************************

 * JNotify - Allow java applications to register to File system events.

 *

 * Copyright (C) 2005 - Content Objects

 *

 * This library is free software; you can redistribute it and/or

 * modify it under the terms of the GNU Lesser General Public

 * License as published by the Free Software Foundation; either

 * version 2.1 of the License, or (at your option) any later version.

 *

 * This library is distributed in the hope that it will be useful,

 * but WITHOUT ANY WARRANTY; without even the implied warranty of

 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU

 * Lesser General Public License for more details.

 *

 * You should have received a copy of the GNU Lesser General Public

 * License along with this library; if not, write to the Free Software

 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

 *

 ******************************************************************************

 *

 * Content Objects, Inc., hereby disclaims all copyright interest in the

 * library `JNotify' (a Java library for file system events).

 *

 * Yahali Sherman, 21 November 2005

 *    Content Objects, VP R&D.

 *

 ******************************************************************************

 * Author : Omry Yadan

 ******************************************************************************/

#include "Win32FSHook.h"

#include <stdio.h>

#include <windows.h>

#include <winbase.h>

#include <winnt.h>

#include <time.h>

#include <stdio.h>

 //#include "Lock.h"

#include "WatchData.h"

//#include "Logger.h"

Win32FSHook* Win32FSHook::instance = 0;

Win32FSHook::Win32FSHook()

{

    _callback = 0;

    _mainLoopThreadHandle = INVALID_HANDLE_VALUE;

    _eventsThread = INVALID_HANDLE_VALUE;

    _isRunning = false;

    InitializeCriticalSection(&_cSection);

    InitializeCriticalSection(&_eventQueueLock);

    _eventQueueEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

}

void Win32FSHook::init(ChangeCallback callback)

{

    instance = this;

    _callback = callback;

    if (!_isRunning)

    {

        _completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);

        if (_completionPort == NULL)

        {

            throw GetLastError();

        }

        _isRunning = true;

        DWORD dwThreadId;

        LPVOID dwThrdParam = (LPVOID)this;

        _mainLoopThreadHandle = CreateThread(

            NULL,                        // default security attributes

            0,                           // use default stack size 

            Win32FSHook::mainLoop,       // thread function

            dwThrdParam,                // argument to thread function

            0,                           // use default creation flags

            &dwThreadId);                // returns the thread identifier

        if (_mainLoopThreadHandle == NULL)

        {

            throw ERR_INIT_THREAD;

        }

        SetThreadPriority(_mainLoopThreadHandle, THREAD_PRIORITY_TIME_CRITICAL);

        _eventsThread = CreateThread(

            NULL,                        // default security attributes

            0,                           // use default stack size

            Win32FSHook::eventLoop,       // thread function

            dwThrdParam,                // argument to thread function

            0,                           // use default creation flags

            &dwThreadId);                // returns the thread identifier

        if (_eventsThread == NULL)

        {

            CloseHandle(_mainLoopThreadHandle);

            throw ERR_INIT_THREAD;

        }

    }

}

Win32FSHook::~Win32FSHook()

{

    //  debug("+Win32FSHook destructor");

        // terminate thread.

    _isRunning = false;

    SetEvent(_eventQueueEvent);

    PostQueuedCompletionStatus(_completionPort, EXIT_SIGNAL, (ULONG_PTR)NULL, NULL);

    // cleanup

    if (INVALID_HANDLE_VALUE != _mainLoopThreadHandle) CloseHandle(_mainLoopThreadHandle);

    if (INVALID_HANDLE_VALUE != _eventsThread) CloseHandle(_eventsThread);

    CloseHandle(_completionPort);

    DeleteCriticalSection(&_cSection);

    //  debug("-Win32FSHook destructor");

}

void Win32FSHook::remove_watch(int wd)

{

    //  debug("+remove_watch(%d)", wd);

    EnterCriticalSection(&_cSection);

    map <int, WatchData*>::const_iterator i = _wid2WatchData.find(wd);

    if (i == _wid2WatchData.end())

    {

        //      debug("remove_watch: watch id %d not found", wd);

    }

    else

    {

        WatchData* wd = i->second;

        int res = wd->unwatchDirectory();

        if (res != 0)

        {

            //          log("Error canceling watch on dir %ls : %d",wd->getPath(), res);

        }

        int res2 = _wid2WatchData.erase(wd->getId());

        if (res2 != 1)

        {

            //          log("Error deleting watch %d from map, res=%d",wd->getId(), res2);

        }

        PostQueuedCompletionStatus(_completionPort, DELETE_WD_SIGNAL, (ULONG_PTR)wd, NULL);

    }

    LeaveCriticalSection(&_cSection);

    //  debug("-remove_watch(%d)", wd);

}

int Win32FSHook::add_watch(const WCHAR* path, long notifyFilter, bool watchSubdirs, DWORD& error)

{

    //  debug("+add_watch(%ls)", path);

        // synchronize access by multiple threads

    EnterCriticalSection(&_cSection);

    try

    {

        WatchData* watchData = new WatchData(path, notifyFilter, watchSubdirs, _completionPort);

        if (watchData == 0) throw (DWORD)8; //ERROR_NOT_ENOUGH_MEMORY

        int watchId = watchData->getId();

        _wid2WatchData[watchId] = watchData;

        watchDirectory(watchData);

        LeaveCriticalSection(&_cSection);

        return watchId;

    }

    catch (DWORD err)

    {

        error = err;

        LeaveCriticalSection(&_cSection);

        return 0;

    }

}

WatchData* Win32FSHook::find(int wd)

{

    WatchData* watchData = 0;

    EnterCriticalSection(&_cSection);

    map <int, WatchData*>::const_iterator it = _wid2WatchData.find(wd);

    if (it != _wid2WatchData.end())

    {

        watchData = it->second;

    }

    LeaveCriticalSection(&_cSection);

    return watchData;

}

DWORD WINAPI Win32FSHook::mainLoop(LPVOID lpParam)

{

    //  debug("mainLoop starts");

    Win32FSHook* _this = (Win32FSHook*)lpParam;

    HANDLE hPort = _this->_completionPort;

    DWORD dwNoOfBytes = 0;

    ULONG_PTR ulKey = 0;

    OVERLAPPED* pov = NULL;

    WCHAR name[4096];

    while (_this->_isRunning)

    {

        pov = NULL;

        BOOL fSuccess = GetQueuedCompletionStatus(

            hPort,         // Completion port handle

            &dwNoOfBytes,  // Bytes transferred

            &ulKey,

            &pov,          // OVERLAPPED structure

            INFINITE       // Notification time-out interval

        );

        if (fSuccess)

        {

            if (dwNoOfBytes == 0) continue; // happens when removing a watch some times.

            if (dwNoOfBytes == EXIT_SIGNAL)

                continue;

            if (dwNoOfBytes == DELETE_WD_SIGNAL)

            {

                WatchData* wd = (WatchData*)ulKey;

                delete wd;

                continue;

            }

            int wd = (int)ulKey;

            //      EnterCriticalSection(&_this->_cSection);

            WatchData* watchData = _this->find(wd);

            if (!watchData)

            {

                //          log("mainLoop : ignoring event for watch id %d, no longer in wid2WatchData map", wd);

                continue;

            }

            const char* buffer = watchData->getBuffer();

            //      char buffer[watchData->getBufferSize()];

            //      memcpy(buffer, watchData->getBuffer(), dwNoOfBytes);

            //          LeaveCriticalSection(&_this->_cSection);

            FILE_NOTIFY_INFORMATION* event;

            DWORD offset = 0;

            do

            {

                event = (FILE_NOTIFY_INFORMATION*)(buffer + offset);

                int action = event->Action;

                DWORD len = event->FileNameLength / sizeof(WCHAR);

                for (DWORD k = 0; k < len && k < (sizeof(name) - sizeof(WCHAR)) / sizeof(WCHAR); k++)

                {

                    name[k] = event->FileName[k];

                }

                name[len] = 0;

                _this->postEvent(new Event(watchData->getId(), action, watchData->getPath(), name));

                offset += event->NextEntryOffset;

            } while (event->NextEntryOffset != 0);

            int res = watchData->watchDirectory();

            if (res != 0)

            {

                //          log("Error watching dir %s : %d",watchData->getPath(), res);

            }

        }

        else

        {

            //      log("GetQueuedCompletionStatus returned an error");

        }

    }

    //  debug("mainLoop exits");

    return 0;

}

void Win32FSHook::watchDirectory(WatchData* wd)

{

    //  debug("Watching %ls", wd->getPath());

    int res = wd->watchDirectory();

    if (res != 0)

    {

        //      log("Error watching dir %ls : %d",wd->getPath(), res);

    }

}

void Win32FSHook::postEvent(Event* event)

{

    EnterCriticalSection(&_eventQueueLock);

    _eventQueue.push(event);

    LeaveCriticalSection(&_eventQueueLock);

    SetEvent(_eventQueueEvent);

}

DWORD WINAPI Win32FSHook::eventLoop(LPVOID lpParam)

{

    //  debug("eventLoop starts");

    Win32FSHook* _this = (Win32FSHook*)lpParam;

    queue<Event*> local;

    while (1)

    {

        // quickly copy to local queue, minimizing the time holding the lock

        EnterCriticalSection(&_this->_eventQueueLock);

        while (_this->_eventQueue.size() > 0)

        {

            Event* e = _this->_eventQueue.front();

            local.push(e);

            _this->_eventQueue.pop();

        }

        LeaveCriticalSection(&_this->_eventQueueLock);

        while (local.size() > 0)

        {

            Event* e = local.front();

            local.pop();

            if (_this->_isRunning)

            {

                _this->_callback(e->_watchID, e->_action, e->_rootPath, e->_filePath);

            }

            delete e;

        }

        if (_this->_isRunning)

        {

            WaitForSingleObjectEx(_this->_eventQueueEvent, INFINITE, TRUE);

        }

        else

            break;

    }

    //  debug("eventLoop exits");

    return 0;

}

main.cpp

#include <iostream>

#include <string.h>

#include <windows.h>

#include "Win32FSHook.h"

//因为文件钩子回调的参数是wchar_t *类型,为了让你的程序正常获取到参数的意思,要转成char *类型

//说明:待转换的字符串是wchar,返回值保存在m_char开辟的空间里

char* wchar2char(const wchar_t* wchar, char* m_char)

{

    int len = WideCharToMultiByte(CP_ACP, 0, wchar, wcslen(wchar), NULL, 0, NULL, NULL);

    WideCharToMultiByte(CP_ACP, 0, wchar, wcslen(wchar), m_char, len, NULL, NULL);

    m_char[len] = '\0';

    return m_char;

}

//因为添加文件钩子监听目标文件夹的时候,要用wchar_t *类型传参,为了方便,直接写个char *到wchar_t *的转换函数

//说明:待转换的字符串是cchar,返回值保存在m_wchar开辟的空间里

wchar_t* char2wchar(const char* cchar, wchar_t* m_wchar)

{

    int len = MultiByteToWideChar(CP_ACP, 0, cchar, strlen(cchar), NULL, 0);

    MultiByteToWideChar(CP_ACP, 0, cchar, strlen(cchar), m_wchar, len);

    m_wchar[len] = '\0';

    return m_wchar;

}

void win32FSCallback(int watchID, int action, const WCHAR* rootPath, const WCHAR* filePath)

{

    char tmp[256];    //windows系统文件名只需要256个字节就可以了

    char filename[256];

    strcpy(filename, wchar2char(rootPath, tmp));

    strcat(filename, wchar2char(filePath, tmp));  //把根目录和相对根目录的文件名拼起来就是完整的文件名了

    //std::cout<<"watchID: "<<watchID<<std::endl;

    switch (action)

    {

    case 1:

    {

        std::cout << "创建:" << filename << std::endl;

        break;

    }

    case 2:

    {

        std::cout << "删除:" << filename << std::endl;

        break;

    }

    case 3:

    {

        std::cout << "复制:" << filename << std::endl;

        break;

    }

    case 4:  //在4时别急着换行,因为windows在回调了4之后,就会回调5,拼起来意思才完整

    {

        std::cout << "重命名原文件名:" << filename;

        break;

    }

    case 5:

    {

        std::cout << ",新文件名:" << filename << std::endl;

        break;

    }

    default//其他的一些操作,因为没有文档,我也不知道还有没有其他的action

    {

        std::cout << "操作代码'" << action << "':" << filename << std::endl;

    }

    }

}

int main()

{

    int watchID;

    Win32FSHook win32FSHook;

    win32FSHook.init(win32FSCallback);

    DWORD err;

    wchar_t path[256];

    watchID = win32FSHook.add_watch(char2wchar("C:\\", path),

        1 | 2 | 4 | 8,

        true,

        err);

    if (err == 2)

    {

        std::cout << "该目录无法监听" << std::endl;

    }

    else

    {

        std::cout << "开始监听,按下回车结束监听" << std::endl;

        getchar();

        win32FSHook.remove_watch(watchID);

        std::cout << "结束监听,按下回车退出程序" << std::endl;

        getchar();

    }

    return 0;

}

结果:

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二、API Hook的原理 这里的API既包括传统的Win32 APIs,也包括任何Module输出的函数调用。熟悉PE文件格 式的朋友都知道,PE文件将对外部Module输出函数的调用信息保存在输入表中,即.idata段。 下面首先介绍本段的结构。 输入表首先以一个IMAGE_IMPORT_DESCRIPTOR(简称IID)数组开始。每个被PE文件隐式链接 进来的DLL都有一个IID.在这个数组中的最后一个单元是NULL,可以由此计算出该数组的项数。 例如,某个PE文件从两个DLL中引入函数,就存在两个IID结构来描述这些DLL文件,并在两个 IID结构的最后由一个内容全为0的IID结构作为结束。几个结构定义如下: IMAGE_IMPORT_DESCRIPTOR struct union{ DWORD Characteristics; ;00h DWORD OriginalFirstThunk; }; TimeDateStamp DWORD ;04h ForwarderChain DWORD ;08h Name DWORD ;0Ch FirstThunk DWORD ;10h IMAGE_IMPROT_DESCRIPTOR ends typedef struct _IMAGE_THUNK_DATA{ union{ PBYTE ForwarderString; PDWORD Functions; DWORD Ordinal; PIMAGE_IMPORT_BY_NAME AddressOfData; }u1; } IMAGE_IMPORT_BY_NAME结构保存一个输入函数的相关信息: IMAGE_IMPORT_BY_NAME struct Hint WORD ? ;本函数在其所驻留DLL的输出表中的序号 Name BYTE ? ;输入函数的函数名,以NULL结尾的ASCII字符串 IMAGE_IMPORT_BY_NAME ends OriginalFirstThunk(Characteristics):这是一个IMAGE_THUNK_DATA数组的RVA(相对于PE文件 起始处)。其中每个指针都指向IMAGE_IMPORT_BY_NAME结构。 TimeDateStamp:一个32位的时间标志,可以忽略。 ForwarderChain:正向链接索引,一般为0。当程序引用一个DLL中的API,而这个API又引用别的 DLL的API时使用。 NameLL名字的指针。是个以00结尾的ASCII字符的RVA地址,如"KERNEL32.DLL"。 FirstThunk:通常也是一个IMAGE_THUNK_DATA数组的RVA。如果不是一个指针,它就是该功能在 DLL中的序号。 OriginalFirstThunk与FirstThunk指向两个本质相同的数组IMAGE_THUNK_DATA,但名称不同, 分别是输入名称表(Import Name Table,INT)和输入地址表(Import Address Table,IAT)。 IMAGE_THUNK_DATA结构是个双字,在不同时刻有不同的含义,当双字最高位为1时,表示函数以 序号输入,低位就是函数序号。当双字最高位为0时,表示函数以字符串类型的函数名 方式输入,这时它是指向IMAGE_IMPORT_BY_NAME结构的RVA。 三个结构关系如下图: IMAGE_IMPORT_DESCRIPTOR INT IMAGE_IMPORT_BY_NAME IAT -------------------- /-->---------------- ---------- ---------------- |01| 函数1 ||02| 函数2 || n| ... |"USER32.dll" | |--------------------| | | FirstThunk |---------------------------------------------------------------/ -------------------- 在PE文件中对DLL输出函数的调用,主要以这种形式出现: call dword ptr[xxxxxxxx] 或 jmp [xxxxxxxx] 其中地址xxxxxxxx就是IAT中一个IMAGE_THUNK_DATA结构的地址,[xxxxxxxx]取值为IMAGE_THUNK_DATA 的值,即IMAGE_IMPORT_BY_NAME的地址。在操作系统加载PE文件的过程中,通过IID中的Name加载相应 的DLL,然后根据INT或IAT所指向的IMAGE_IMPORT_BY_NAME中的输入函数信息,在DLL中确定函数地址, 然后将函数地址写到IAT中,此时IAT将不再指向IMAGE_IMPORT_BY_NAME数组。这样[xxxxxxxx]取到的 就是真正的API地址。 从以上分析可以看出,要拦截API的调用,可以通过改写IAT来实现,将自己函数的地址写到IAT中, 达到拦截目的。 另外一种方法的原理更简单,也更直接。我们不是要拦截吗,先在内存中定位要拦截的API的地址, 然后改写代码的前几个字节为 jmp xxxxxxxx,其中xxxxxxxx为我们的API的地址。这样对欲拦截API的 调用实际上就跳转到了咱们的API调用去了,完成了拦截。不拦截时,再改写回来就是了。 这都是自己从网上辛辛苦苦找来的,真的很好啊
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值