加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

利用detours写了一个工具用于instrument任意指定dll的任意指定函

发布时间:2020-12-14 05:56:03 所属栏目:Windows 来源:网络整理
导读:目录 wiki Disas Dtest Simple withdll load一个dll到指定进程 tracebld显示相关进程涉及的文件读写操作 My Instrumentation tool: wiki https://github.com/microsoft/Detours/wiki Disas Tests the Detours disassembler tables. Uses DetourEnumerateExpo

目录

  • wiki
  • Disas
  • Dtest
  • Simple
  • withdll load一个dll到指定进程
  • tracebld显示相关进程涉及的文件读写操作
  • My Instrumentation tool:

wiki

https://github.com/microsoft/Detours/wiki

Disas

Tests the Detours disassembler tables.

Uses
DetourEnumerateExports,DetourEnumerateModules,DetourGetEntryPoint,DetourGetModuleSize.

Dtest

Detours the Win32 Sleep function and a private function. The private function is first detoured,then detoured recursively 3 times using the DetourAttach API.

Uses
DetourAttach,DetourTransactionBegin,DetourTransactionCommit,DetourUpdateThread.

Simple

detour to modify the Windows Sleep API.

withdll load一个dll到指定进程

The withdll.exe program include in the Detours package uses the DetourCreateProcessWithDlls API to start a new process with a named DLL.

example of withdll

tracebld显示相关进程涉及的文件读写操作

command

F:codesDetours-4.0.1bin.X86>tracebld.exe /o:1.txt notepad
TRACEBLD: Ready for clients.  Press Ctrl-C to stop.
TRACEBLD: Starting: `notepad'
TRACEBLD:   with `F:codesDetours-4.0.1bin.X86trcbld32.dll'
TRACEBLD: 1 processes.

output file

<?xml version="1.0" encoding="UTF-8"?>

-<t:Process xmlns:t="http://schemas.microsoft.com/research/tracebld/2008" exe="notepad" par="" id="::0.::">

<t:Directory>F:codesDetours-4.0.1bin.X86</t:Directory>

<t:Executable>%SYSDIR%notepad.exe</t:Executable>

<t:Line>%SYSDIR%notepad.exe </t:Line>

<t:Return>0</t:Return>


-<t:Files>

<t:File write="true" read="true">.NvAdminDevice</t:File>

<t:File read="true">C:ProgramDataNVIDIA CorporationDrsnvdrssel.bin</t:File>

<t:File read="true">C:ProgramDataNVIDIA CorporationDrsnvdrsdb1.bin</t:File>

<t:File read="true">C:WindowsFontsstaticcache.dat</t:File>

</t:Files>

<t:Vars> </t:Vars>

</t:Process>

My Instrumentation tool:

配置文件 input.txt

dll=kernel32.dll fun=OpenFile
dll=user32.dll fun=MessageBoxA
dll=user32.dll fun=MessageBoxW
dll=user32.dll fun=OffsetRect
dll=kernel32.dll fun=WaitForSingleObject
dll=kernel32.dll fun=CloseHandle

测试

F:codesDetours-4.0.1bin.X86>withdll.exe /d:C:UserscutepsourcereposConsoleApplication1Debugdll1.dll notepad
Press any key to continue . . .
withdll.exe: Starting: `notepad'
withdll.exe:   with `C:UserscutepsourcereposConsoleApplication1Debugdll1.dll'
Resume Thread...
Press any key to continue . . .

输出

'notepad.exe' (Win32): Loaded 'C:Windowssyswow64notepad.exe'. Cannot find or open the PDB file.
...
'notepad.exe' (Win32): Loaded 'C:UserscutepsourcereposConsoleApplication1DebugDll1.dll'. Symbols loaded.
...
processing line: dll=kernel32.dll fun=OpenFile
processing line: dll=user32.dll fun=MessageBoxA
processing line: dll=user32.dll fun=MessageBoxW
processing line: dll=user32.dll fun=OffsetRect
processing line: dll=kernel32.dll fun=WaitForSingleObject
processing line: dll=kernel32.dll fun=CloseHandle
processing line: 

>>dll=kernel32.dll fun=WaitForSingleObject

>>dll=kernel32.dll fun=CloseHandle

.....
>>dll=user32.dll fun=OffsetRect

>>dll=user32.dll fun=OffsetRect
...

>>dll=kernel32.dll fun=CloseHandle

Exception thrown at 0x0FF81BCC (ucrtbased.dll) in notepad.exe: 0xC0000005: Access violation reading location 0xFEEEFEEE.

The program '[0x1DE0] notepad.exe' has exited with code 0 (0x0).

link: https://files.cnblogs.com/files/cutepig/ConsoleApplication1.7z

核心代码

//dllmain.cpp

// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include <detours.h>
#include "../Injector.h"

Injector gInj;
static int (WINAPI * TrueEntryPoint)(VOID) = NULL;
static int (WINAPI * RawEntryPoint)(VOID) = NULL;

static void DebugStr(const char *fmt,...)
{
    va_list l;
    va_start(l,fmt);

    char s[100];
    vsnprintf(s,100,fmt,l);
    printf(s);
    OutputDebugStringA(s);
}

int WINAPI TimedEntryPoint(VOID)
{
    FILE *fp = fopen("input.txt","r");
    if (!fp)
    {
        DebugStr("Open file fails");
        return -1;
    }
    
    char s[300];
    while (fgets(s,300,fp))
    {
        DebugStr("processing line: %s",s);

        char dll[100];
        char fun[100];
        if (2 != sscanf(s,"dll=%s fun=%s",dll,fun))
        {
            DebugStr("Error scanf from line: %s",s);
            continue;
        }
        PVOID pFun = DetourFindFunction(dll,fun);
        if (!pFun)
        {
            DebugStr("Error DetourFindFunction from line: %s %s",fun);
            continue;
        }

        gInj.Inject(pFun,s);
    }
    
    return TrueEntryPoint();
}

BOOL WINAPI DllMain(HINSTANCE hinst,DWORD dwReason,LPVOID reserved)
{
    LONG error;
    (void)hinst;
    (void)reserved;

    if (DetourIsHelperProcess()) {
        return TRUE;
    }

    if (dwReason == DLL_PROCESS_ATTACH) {
        DetourRestoreAfterWith();

        

        // NB: DllMain can't call LoadLibrary,so we hook the app entry point.
        TrueEntryPoint = (int (WINAPI *)(VOID))DetourGetEntryPoint(NULL);
        RawEntryPoint = TrueEntryPoint;


        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourAttach(&(PVOID&)TrueEntryPoint,TimedEntryPoint);
        error = DetourTransactionCommit();

        if (error == NO_ERROR) {
            printf("dslept" DETOURS_STRINGIFY(DETOURS_BITS) ".dll: "
                " Detoured EntryPoint().n");
        }
        else {
            printf("dslept" DETOURS_STRINGIFY(DETOURS_BITS) ".dll: "
                " Error detouring EntryPoint(): %dn",error);
        }
    }
    else if (dwReason == DLL_PROCESS_DETACH) {
        
    }
    return TRUE;
}
// injector.cpp

#include <Windows.h>
#include <assert.h>
#include <vector>
#include <algorithm>
#include <detours.h>
#include "Injector.h"

void GenCode(char *&p,int n,const char *data)
{
    //std::copy(data,data + n,p);
    memcpy(p,data,n);
    p += n;
}

void GenAddEsp4(char *&p)
{
    char data[3] = { 0x83,0xC4,0x04 };
    GenCode(p,3,data);
}

void GenPushPtr(char *&p,void const *pData)
{
    char *pcoffset = (char *)&pData;
    char data[5] = { 0x68,pcoffset[0],pcoffset[1],pcoffset[2],pcoffset[3] };
    GenCode(p,5,data);
}

void GenCall(char *&p,void const *pFn)
{
    DWORD offset = (DWORD)pFn - ((DWORD)p + 5);
    char *pcoffset = (char *)&offset;
    char data[5] = { 0xe8,data);
}

void GenJump(char *&p,void const *pFn)
{
    DWORD offset = (DWORD)pFn - ((DWORD)p + 5);
    char *pcoffset = (char *)&offset;
    char data[5] = { 0xe9,data);
}

class InjectorImpl
{
    struct Code {
        char* adr;
        char* codeOfJump;
        Code() :adr(0),codeOfJump(0)
        {}
    };

    struct Item {
        std::string desc;
        void const *fOriginal;
        void  *fTramper;    // the original function is changed to tramper after inject
        Code code;
        char *codeOfJump;   // ptr pointer to jump. It shoulod be updated after Submit

        Item():fOriginal(0),fTramper(0),codeOfJump(0)
        {}
    };

    std::vector<Item> mvItems;

    static void MyInstrument(Item *item)
    {
        char s[100];
        _snprintf_s(s,">>%sn",item->desc.c_str());
        printf(s);
        OutputDebugStringA(s);
    }

    static Code GenInjectCodePart1(Item const *item)
    {
        int size = 100;
        char *adr = (char*)VirtualAlloc(NULL,size,MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE);

        Code code;
        code.adr = adr;
        // write code to the region
        char *p = adr;

        // Call Instrument("hello")
        GenPushPtr(p,item);
        GenCall(p,MyInstrument);
        GenAddEsp4(p);

        // call test()
        //GenCall(p,Test);

        // Jump to Add()
        code.codeOfJump = p;
        
        return code;
    }

    static void GenInjectCodePart2(Item const *item)
    {
        int size = 100;
        assert(item->fTramper != item->fOriginal);

        char *p = item->code.codeOfJump;
        GenJump(p,item->fTramper);

        // Set as executable
        DWORD oldProtection;
        BOOL ok = VirtualProtect(item->code.adr,PAGE_EXECUTE_READ,&oldProtection);
        assert(ok);

        FlushInstructionCache(GetCurrentProcess(),item->code.adr,size);
    }
    void FreeInjectCode(char* adr)
    {
        VirtualFree(adr,MEM_RELEASE);
    }
public:
    InjectorImpl()
    {
        mvItems.reserve(100);
    }
    ~InjectorImpl()
    {}

    void Inject(void const *f,char const *desc)
    {
        assert(mvItems.size() < mvItems.capacity());

        mvItems.push_back(Item());
        Item &item = mvItems.back();
        item.fOriginal = item.fTramper = (void*)f;
        item.desc = desc;

        Code code = GenInjectCodePart1(&item);
        item.code = code;

        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourAttach(&(PVOID&)item.fTramper,item.code.adr);
        DetourTransactionCommit();

        GenInjectCodePart2(&item);
    }

    //void Test()
    //{
    //  Item item;
    //  item.fOriginal = item.fTramper = (void*)Add;
    //  item.desc = "desc";
    //  Code code = GenInjectCodePart1(&item);
    //  item.code = code;
    //  GenInjectCodePart2(&item);

    //  int(*pAdd)(int a,int b) = (int(*)(int a,int b))item.code.adr;
    //  assert(pAdd(1,2) == 3);
    //}
private:

};

// Injector
/////////////////////

Injector::Injector():impl(new InjectorImpl)
{
}
Injector::~Injector(){}

void Injector::Inject(void const *f,char const *desc)
{
    impl->Inject(f,desc);
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读