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:\codes\Detours-4.0.1\bin.X86>tracebld.exe /o:1.txt notepad
TRACEBLD: Ready for clients. Press Ctrl-C to stop.
TRACEBLD: Starting: `notepad'
TRACEBLD: with `F:\codes\Detours-4.0.1\bin.X86\trcbld32.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:\codes\Detours-4.0.1\bin.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:\ProgramData\NVIDIA Corporation\Drs\nvdrssel.bin</t:File>

<t:File read="true">C:\ProgramData\NVIDIA Corporation\Drs\nvdrsdb1.bin</t:File>

<t:File read="true">C:\Windows\Fonts\staticcache.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:\codes\Detours-4.0.1\bin.X86>withdll.exe /d:C:\Users\cutep\source\repos\ConsoleApplication1\Debug\dll1.dll notepad
Press any key to continue . . .
withdll.exe: Starting: `notepad'
withdll.exe: with `C:\Users\cutep\source\repos\ConsoleApplication1\Debug\dll1.dll'
Resume Thread...
Press any key to continue . . .

输出

'notepad.exe' (Win32): Loaded 'C:\Windows\syswow64\notepad.exe'. Cannot find or open the PDB file.
...
'notepad.exe' (Win32): Loaded 'C:\Users\cutep\source\repos\ConsoleApplication1\Debug\Dll1.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().\n");
}
else {
printf("dslept" DETOURS_STRINGIFY(DETOURS_BITS) ".dll: "
" Error detouring EntryPoint(): %d\n", 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\n", 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);
}

利用detours写了一个工具用于instrument任意指定dll的任意指定函数入口的更多相关文章

  1. 用Java开发一个工具类,提供似于js中eval函数功能的eval方法

    今天在看到<Java疯狂讲义>中一个章节习题: 开发一个工具类,该工具类提供一个eval()方法,实现JavaScript中eval()函数的功能--可以动态运行一行或多行程序代码.例如: ...

  2. 【逆向工具】IDA使用2-VS2015版本release查找main函数入口,局部变量

    VS2015版本release查找main函数入口 vc++开发的程序main或WinMain函数是语法规定的用户入口,而不是应用程序入口.入口代码是mainCRTstartup.wmainCRTSt ...

  3. js 利用throw 写的一个小程序

    在下边的小程序中比较特殊的是使用isNaN()函数判断一个参数是不是数字, <!DOCTYPE html> <!DOCTYPE html> <html> <h ...

  4. 利用PyQt4写的小工具软件

    应公司文职工作人员需求,写一个车间人员工作时间的统计软件,输入开始工作时间1,再输入结束工作时间2,计算两个时间的差值. 根据需求,初步构想的UI界面如下: 下面开始干活. 分析后觉得利用PyQt4来 ...

  5. 利用HttpClient写的一个简单页面获取

    之前就听说过利用网络爬虫来获取页面,感觉还挺有意思的,要是能进行一下偏好搜索岂不是可以满足一下窥探欲. 后来从一本书上看到用HttpClient来爬取页面,虽然也有源码,但是也没说用的HttpClie ...

  6. 利用jquery写的一个TAB页切换效果

    函数如下 /** *切换效果 */ function switab(tab,con,tab_c_css,tab_n_css,no) { $(tab).each(function(i){ if(i == ...

  7. apue编程之参考du代码利用递归写的一个简单的du命令的源代码

    #include <stdio.h> #include <stdlib.h> #include <glob.h> #include <string.h> ...

  8. 访问github太慢?我写了一个开源小工具一键变快

    前言 GitHub应该是广大开发者最常去的站点,这里面有大量的优秀项目,是广大开发者寻找资源,交友学习的好地方.尤其是前段时间GitHub公布了一项代码存档计划--Arctic Code Vault, ...

  9. 利用jdbc简单封装一个小框架(类似DBUtils)

    利用jdbc写的一个类似DBUtils的框架 package com.jdbc.orm.dbutils; import java.io.IOException; import java.io.Inpu ...

随机推荐

  1. Gitlab创建一个项目

    1.安装git yum install git 2.生成密钥文件:使用ssh-keygen生成密钥文件.ssh/id_rsa.pub ssh-keygen 执行过程中输入密码,以及确认密码,并可设置密 ...

  2. Docker以https访问Harbor私有仓库(二)

    1 说明 前文Centos7搭建Harbor私有仓库(二)中,我们以https方式搭建了Harbor,本篇我们主要配置Docker以https方式访问Harbor私有仓库 2 Docker配置 2.1 ...

  3. 关于MySQL数据库编码修复相关问题

    本篇主要是本人在实际开发过程中遇到的MySQL字符编码等bug修复相关问题. 在使用下列语句在执行数据库表通过flask-sqlacodegen 进行ORM映射成模型类的时候发生的bug: flask ...

  4. Tomcat+Nginx+Memcached综合案例

    Tomcat+Nginx+Memcached综合案例 说明 通过Nginx解析静态页面并将动态负载均衡调度给后面的多个Tomcat,Tomcat解析java动态程序. 由于http是无状态的协议,你访 ...

  5. struct并不报错

    struct { int item; struct list* next; }list; 如果结构体定义如上,使用下面的代码,将会报错 //添加元素,由于我们实现的是单向链表,所以使用从尾部添加 bo ...

  6. spring cloud (七) Config server基于svn配置

    1 pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="h ...

  7. An exception has occurred, use %tb to see the full traceback.----parser.parse_args()报错

    一.报错: 原因: 由于在jupyter notebook中,args不为空. 二.问题解决 改成args = parser.parse_args(args=[])

  8. Kotlin协程作用域与构建器详解

    在上次我们是通过了这种方式来创建了一个协程: 接着再来看另一种创建协程的方式: 下面用它来实现上一次程序一样的效果,先来回顾一下上一次程序的代码: 好,下面改用runBlocking的方式: 运行一下 ...

  9. 自动化测试常用断言的使用方法(python+selenium)

    自动化测试常用断言的使用方法(python) 自动化测试中寻找元素并进行操作,如果在元素好找的情况下,相信大家都可以较熟练地编写用例脚本了,但光进行操作可能还不够,有时候也需要对预期结果进行判断. 这 ...

  10. python学习类与方法的调用规则

    1类方法的特点是类方法不属于任何该类的对象,只属于类本身 2类的静态方法类似于全局函数,因为静态方法既没有实例方法的self参数也没有类方法的cls参数,谁都可以调用 3.实例方法只属于实例,是实例化 ...