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


    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

    1570716876227

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

    command

    F:codesDetours-4.0.1in.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.1in.X86	rcbld32.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.1in.X86</t:Directory>
    
    <t:Executable>%SYSDIR%
    otepad.exe</t:Executable>
    
    <t:Line>%SYSDIR%
    otepad.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 CorporationDrs
    vdrssel.bin</t:File>
    
    <t:File read="true">C:ProgramDataNVIDIA CorporationDrs
    vdrsdb1.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.1in.X86>withdll.exe /d:C:Userscutepsource
    eposConsoleApplication1Debugdll1.dll notepad
    Press any key to continue . . .
    withdll.exe: Starting: `notepad'
    withdll.exe:   with `C:Userscutepsource
    eposConsoleApplication1Debugdll1.dll'
    Resume Thread...
    Press any key to continue . . .
    

    输出

    'notepad.exe' (Win32): Loaded 'C:Windowssyswow64
    otepad.exe'. Cannot find or open the PDB file.
    ...
    'notepad.exe' (Win32): Loaded 'C:Userscutepsource
    eposConsoleApplication1DebugDll1.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", dll, 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().
    ");
    		}
    		else {
    			printf("dslept" DETOURS_STRINGIFY(DETOURS_BITS) ".dll: "
    				" Error detouring EntryPoint(): %d
    ", 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, pcoffset[0], pcoffset[1], pcoffset[2], pcoffset[3] };
    	GenCode(p, 5, data);
    }
    
    void GenJump(char *&p, void const *pFn)
    {
    	DWORD offset = (DWORD)pFn - ((DWORD)p + 5);
    	char *pcoffset = (char *)&offset;
    	char data[5] = { 0xe9, pcoffset[0], pcoffset[1], pcoffset[2], pcoffset[3] };
    	GenCode(p, 5, 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, 100, ">>%s
    ", 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, size, PAGE_EXECUTE_READ, &oldProtection);
    		assert(ok);
    
    		FlushInstructionCache(GetCurrentProcess(), item->code.adr, size);
    	}
    	void FreeInjectCode(char* adr)
    	{
    		VirtualFree(adr, 0, 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);
    }
    
    
  • 相关阅读:
    003.iSCSI客户端管理
    002.iSCSI服务端配置
    001.iSCSI简介
    004.RAID删除
    003.RAID管理
    002.RAID创建
    001.RAID简介
    001.hadoop及hbase部署
    001.Parted工具使用
    007.LVM查看命令
  • 原文地址:https://www.cnblogs.com/cutepig/p/11651505.html
Copyright © 2020-2023  润新知