/************************************************************************ Inline HOOK API V1.1 thanks to 海风月影, xIkUg ,sucsor by solosky created at 2011.06.29, updated at 2011.06.30 ---------------------------------- Inline HOOK API V1.1 2011.06.30 ---------------------------------- 1. 修复没有判断申请空间是否成功的BUG; 2. 修复释放内存的参数错误的BUG; ---------------------------------- Inline HOOK API V1.0 2011.06.29 ---------------------------------- 1. HOOK任何函数,仅需知道原型和调用方式即可(可以HOOK对象方法,但需要保存和恢复this指针) 2. UnHOOK已经HOOK的函数 感谢海风月影提供的反汇编长度引擎!! ************************************************************************/ /************************************************************************/ #include "inlinehook.h" /************************************************************************/ /* InlineHOOK一个函数 /* param ppRealFun 被HOOK的函数指针,注意这里必须指向函数的指针,因为需要修改这个值,来返回新的函数地址 /* param pHookFun 自己编写的HOOK函数指针 /* return PHOOK_ENV 成功后返回HOOK之后的环境上下文,可以用这个指针取消HOOK,失败返回NULL /************************************************************************/ PHOOK_ENV __stdcall HookFun(PVOID *ppRealFun,const PVOID pHookFun) { DWORD dwRealFun = *(DWORD*)ppRealFun; DWORD dwHookFun = (DWORD) pHookFun; //首先计算需要替换原始函数的前几个字节 DWORD replaceCodeSize = FindOpcodeSize((BYTE*)dwRealFun); while (replaceCodeSize<5) //至少5个字节,因为jmp xxxx至少需要5个字节 replaceCodeSize += FindOpcodeSize((BYTE*)((DWORD)dwRealFun + (DWORD)replaceCodeSize)); if (replaceCodeSize>16) return NULL; //分配HOOK的环境变量,存放代理代码和一些数据 PHOOK_ENV pHookEnv = (PHOOK_ENV)VirtualAlloc(NULL,sizeof(HOOK_ENV),MEM_COMMIT,PAGE_EXECUTE_READWRITE); if(pHookEnv==NULL) return NULL; memset(pHookEnv, sizeof(HOOK_ENV), 0); memset(pHookEnv->mHookStub.uJumpBack, 0x90, sizeof(pHookEnv->mHookStub.uJumpBack)); //填充跳回和跳去的机器码为nop memset(pHookEnv->mHookStub.uJumpTo, 0x90, sizeof(pHookEnv->mHookStub.uJumpTo)); //在这个环境变量上保存一些信息,便于恢复hook pHookEnv->dwReplacedBytes = replaceCodeSize; //替换的字节长度 pHookEnv->dwRealFunAddr = dwRealFun; //原始函数地址 pHookEnv->dwHookFunAddr = dwHookFun; //HOOK函数地址 //填充STUB跳转到HOOK函数的代码 *(pHookEnv->mHookStub.uJumpTo) = 0xE9; //JMP指令 *(DWORD*)(pHookEnv->mHookStub.uJumpTo+1) = dwHookFun-((DWORD)pHookEnv->mHookStub.uJumpTo)-5; //A B C => B=C-A-5 //填充STUB跳转回原函数的头replaceCodeSize个字节代码 memcpy(pHookEnv->mHookStub.uJumpBack, (PVOID)dwRealFun, replaceCodeSize); *(pHookEnv->mHookStub.uJumpBack+replaceCodeSize) = 0xE9; //JMP指令,准备跳回到原始函数 *(DWORD*)(pHookEnv->mHookStub.uJumpBack+replaceCodeSize+1) = dwRealFun-((DWORD)(pHookEnv->mHookStub.uJumpTo)+replaceCodeSize)-5; //关键的时候来了,现在需要替换原始函数的前replaceCodeSize个字节为一个JMP到STUB的指令 DWORD dwOldProctect = 0; if (!VirtualProtect((PVOID)dwRealFun, replaceCodeSize,PAGE_EXECUTE_READWRITE,&dwOldProctect)) goto FAILED; *(UCHAR*)(dwRealFun) = 0xE9; *(DWORD*)(dwRealFun+1) = (DWORD)(pHookEnv->mHookStub.uJumpTo)-dwRealFun-5; if(replaceCodeSize>5) memset((PVOID)(dwRealFun+5), 0x90, replaceCodeSize-5); if (!VirtualProtect((PVOID)dwRealFun,replaceCodeSize,dwOldProctect,&dwOldProctect)) goto FAILED; //修改真实函数地址为STUB的跳回指令开始 *(ppRealFun) = pHookEnv->mHookStub.uJumpBack; return pHookEnv; FAILED: if(pHookEnv) VirtualFree(pHookEnv, 0, MEM_RELEASE); return NULL; } /************************************************************************/ /* 取消HOOK一个函数 /* param pHookEnv HOOK的环境上下文,又hookFun函数返回 /* return bool 成功返回TRUE失败返回FALSE /************************************************************************/ BOOL __stdcall UnHookFun(PHOOK_ENV pHookEnv) { //恢复真实函数修改的前几个字节即可 DWORD dwOldProctect = 0; if (!VirtualProtect((PVOID)pHookEnv->dwRealFunAddr, pHookEnv->dwReplacedBytes, PAGE_EXECUTE_READWRITE,&dwOldProctect)) goto FAILED; memcpy((PVOID)pHookEnv->dwRealFunAddr, (PVOID)pHookEnv->mHookStub.uJumpBack, pHookEnv->dwReplacedBytes); if (!VirtualProtect((PVOID)pHookEnv->dwRealFunAddr, pHookEnv->dwReplacedBytes,dwOldProctect,&dwOldProctect)) goto FAILED; if(!VirtualFree(pHookEnv, 0, MEM_RELEASE)) goto FAILED; return TRUE; FAILED: return FALSE; } /************************************************************************/ /* 查找给定地址的机器指令长度 (感谢海风月影提供的反汇编长度引擎) /* param intr0 指令地址 /* return bool 成功返回当前指令长度 /************************************************************************/ DWORD __stdcall FindOpcodeSize(BYTE* iptr0) { BYTE* iptr = iptr0; DWORD f = 0; prefix: BYTE b = *iptr++; f |= table_1[b]; if (f&C_FUCKINGTEST) if (((*iptr)&0x38)==0x00) // ttt f=C_MODRM+C_DATAW0; // TEST else f=C_MODRM; // NOT,NEG,MUL,IMUL,DIV,IDIV if (f&C_TABLE_0F) { b = *iptr++; f = table_0F[b]; } if (f==C_ERROR) { //printf("error in X\n",b); return C_ERROR; } if (f&C_PREFIX) { f&=~C_PREFIX; goto prefix; } if (f&C_DATAW0) if (b&0x01) f|=C_DATA66; else f|=C_DATA1; if (f&C_MODRM) { b = *iptr++; BYTE mod = b & 0xC0; BYTE rm = b & 0x07; if (mod!=0xC0) { if (f&C_67) // modrm16 { if ((mod==0x00)&&(rm==0x06)) f|=C_MEM2; if (mod==0x40) f|=C_MEM1; if (mod==0x80) f|=C_MEM2; } else // modrm32 { if (mod==0x40) f|=C_MEM1; if (mod==0x80) f|=C_MEM4; if (rm==0x04) rm = (*iptr++) & 0x07; // rm<-sib.base if ((rm==0x05)&&(mod==0x00)) f|=C_MEM4; } } } // C_MODRM if (f&C_MEM67) if (f&C_67) f|=C_MEM2; else f|=C_MEM4; if (f&C_DATA66) if (f&C_66) f|=C_DATA2; else f|=C_DATA4; if (f&C_MEM1) iptr++; if (f&C_MEM2) iptr+=2; if (f&C_MEM4) iptr+=4; if (f&C_DATA1) iptr++; if (f&C_DATA2) iptr+=2; if (f&C_DATA4) iptr+=4; return iptr - iptr0; } /************************************************************************ 使用方法: 原始的LoadLibraryA的声明是: HMODULE WINAPI LoadLibraryA( LPCSTR lpLibFileName ); 1. 那么首先定义一下hook的WINAPI的类型 typedef HMODULE (WINAPI* __pfnLoadLibraryA)(LPCTSTR lpFileName); 2. 定义一个全局的变量,用于保存正式的函数地址 __pfnLoadLibraryA real_loadLibrary; 3. 自定义自己的hook函数,可以在里面调用真实的被HOOK函数地址 HMODULE my_loadLibrary(LPCTSTR lpFileName) { char s[30]; sprintf(s, "loading dll: %s", lpFileName); MessageBox(NULL, s, "MSG", MB_OK); real_loadLibrary(lpFileName); } 4. HOOK的过程 real_loadLibrary = LoadLibraryA; //保存原始的LoadLibrary PHOOK_ENV env = HookFun((PVOID*)&real_loadLibrary, (PVOID)my_loadLibrary); //HOOK, 返回PHOOK_ENV, 同时把真实的函数地址保存到了real_loadLibrary变量中 LoadLibrary("test.dll"); //正常调用,已经被HOOK UnHookFun(env); //取消HOOK LoadLibrary("test.dll"); //没效果 */ ////////////////////////////////////////////////////////////////////////////////////////////////// //定义下面这行可以作为演示使用 //#define TEST_MAIN1 #define TEST_MAIN2 #ifdef TEST_MAIN1 typedef HMODULE (WINAPI* __pfnLoadLibraryA)(LPCTSTR lpFileName); __pfnLoadLibraryA real_loadLibrary; HMODULE WINAPI my_loadLibrary(LPCTSTR lpFileName) { char s[30]; sprintf(s, "loading dll: %s", lpFileName); MessageBox(NULL, s, "MSG", MB_OK); return real_loadLibrary(lpFileName); } int main() { real_loadLibrary = LoadLibraryA; PHOOK_ENV env = HookFun((PVOID*)&real_loadLibrary, (PVOID)my_loadLibrary); LoadLibrary("test.dll"); UnHookFun(env); LoadLibrary("test.dll"); return 1; } #endif #ifdef TEST_MAIN2 //首先需要定义一个被HOOK的函数原型 typedef DWORD (* pFun)(DWORD a, DWORD b); //然后需要定义一个全局的函数指针,保存真实的函数地址(也就是经过处理后的函数的新入口) pFun real_add; //这个是被HOOK的函数 DWORD add(DWORD a, DWORD b) { printf("add: %d+%d=%d\n", a, b, a+b); return a+b; } //这个是自定义的HOOK函数,可以通过全局的函数指针调用真实的函数 DWORD my_add(DWORD a, DWORD b) { printf("my_add(mins): %d-%d=%d\n",a, b, a-b); return real_add(a, b); } int main(int argc, char **argv) { DWORD a = 10; DWORD b = 6; add(a, b); real_add = add; PHOOK_ENV env = HookFun((PVOID*)&real_add, (PVOID)my_add); add(a, b); add(4, 7); UnHookFun(env); add(a, b); return 1; } /* 输出: add: 10+6=16 my_add(mins): 10-6=4 add: 10+6=16 my_add(mins): 4-7=-3 add: 4+7=11 add: 10+6=16 */ #endif /////////////////////////////////////////////////////////////////////////
2024-01-17 14:41:21 5KB hook
1
二维CFT具有在应力张量基础上建立的无限组换向守恒电荷,称为量子KdV电荷。 我们在圆上计算这些KdV电荷的热相关函数。 我们表明,这些相关函数是由作用于环划分函数的准模微分算子给出的。 我们确定它们的模数变换性质,在许多情况下给出明确的表达式,并给出一个任意相关函数的表达式,该函数取决于中心电荷的有限数量的函数。 我们证明了这些模块化微分算子消除了非2最小模型的(2m +1,2)系列的特征。 我们还表明,KdV电荷的分布在较大水平上急剧达到峰值。
2024-01-16 14:44:16 856KB Open Access
1
这是pb中常用的函数介绍,如何,类型,返回值,有的还附有示例,是pb中最常用的api
2024-01-16 13:05:24 120KB
1
一些开发中经常用到的函数,侧重于数据窗口的开发
比较适合新手(对基础比较熟的新手)
2024-01-16 12:59:20 802KB 电子书
1
MATLAB中fft函数用法、性质、特性、缺陷全面深入解析(含程序).docx
2024-01-15 22:48:02 130KB
1
YOLOv5|YOLOv7|YOLOv8改各种IoU损失函数:YOLOv8涨点Trick,改进添加SIoU损失函数、EIoU损失函数、GIoU损失函数、α-IoU损失函数-CSDN博客.mhtml
2024-01-15 16:19:33 3.33MB
1
在本文中,我们将最优外汇风险对冲解决方案的Kim(2013)扩展到多种外汇汇率,并提出了其应用方法。 首先,介绍了多种外币买卖的广义最优套期保值方法。 第二,包括处理远期合同的费用。 第三,作为对冲绩效评估的标准,考虑了Leontief效用函数,该函数代表了对冲者的风险厌恶性。 第四,介绍了有关进行套期保值所需的具体步骤。 计算了三种常规对冲工具(即看涨/卖出货币期权,远期合约和未平仓头寸)的最佳组合的加权比。 对于指定水平的预期收益,数学优化的封闭形式解决方案可以实现较低水平的外汇风险。 此外,还提供了有关可以通过Excel在业务领域中执行的过程的建议。
2024-01-14 17:53:07 1.3MB 外汇交易 封闭式解决方案
1
为解决在产品导购中人们无法合理地对多特征对象进行定量化优度评价的问题,采用多级优度评价方法对对象进行优劣评价.多级优度评价方法在原可拓优度评价方法的基础上,进一步明确了衡量指标中社会指标、经济指标、技术指标等三大指标的界定以及它们之间的关系,同时给定了各个评价指标之间的层次关系以及不同层次衡量指标的权系数的设定原则,完善了多级优度评价的体系结构.以手机产品导购为例对多级优度评价方法进行了案例研究.研究结果表明:多级优度评价方法能够帮助用户合理地根据自身需求对多特征的对象进行定量化优度评价,使得产品导购行业具有了比较完善的、合理的优度评价体系,提高了产品导购的效率和科学性.
2024-01-14 16:11:26 781KB 关联函数 产品导购
1
实用的炒股同花顺app公式,100+,函数及api介绍,同花顺常用的API接口,您可以根据自己的需求选择相应的接口进行调用。同花顺公式是同花顺软件中内置的一个编程语言,通过使用该语言可以自定义各种复杂的技术指标和策略,并在K线图中进行展示。同花顺公式主要用于量化交易、股票分析和研究等领域。 用户可以使用同花顺公式来编写一些简单或复杂的数学计算公式,以及自定义的技术指标和交易策略。这些公式可以针对不同的投资者需求实现个性化设置,根据不同的情况,自动进行买入卖出的操作,从而使投资效果更加稳定和优秀。 同花顺公式支持常见的逻辑运算和数学运算符,同时还提供了大量的函数和变量,以便用户能够更快捷地完成公式编写工作。用户可以通过使用同花顺公式,快速地开发一些量化交易策略,提高研究效率和交易的盈利水平。
2024-01-14 11:38:38 7KB 编程语言
1
本文讨论了贝叶斯方法,用于在测试过程中估计和预测软件系统的可靠性。 针对软件故障,提出了由Musa-Okumoto(1984)软件可靠性模型引起的非均质泊松过程(NHPP)。 Musa-Okumoto NHPP可靠性模型由执行时间部分和日历时间部分两个部分组成,是软件可靠性分析中的一种流行模型。 软件可靠性模型的预测分析对于修改,调试和确定何时终止软件开发测试过程非常重要。 但是,文献中缺少对Musa-Okumoto(1984)NHPP模型的贝叶斯和古典预测分析。 本文讨论了与开发测试程序密切相关的单样本预测中的四个软件可靠性问题。 采用基于非信息先验的贝叶斯方法来为这些问题制定明确的解决方案。 给出了基于真实和模拟数据的示例,以说明已开发的理论预测结果。
1