c++ hook 各位大虾,我用Writeprocessutility hookMemory来修改某条汇编代码来达到hoo

全国统一热线:400-028-
VPS SERVER
CLOUD HOST
欢迎光临西部数码,我们将竭诚为您提供最优质的服务!
浅谈API HOOK技术(二)
浅谈API HOOK技术(二)
在这里我将要实现转跳。有人说修改内存内容要进入Ring 0 才可以。可是Windows本身提供了一个写内存的指令WriteProcessMemory。有了这把利器,我们几乎无所不能。如游戏的修改等在这里我们只谈APIHOOK。function RepointFunction(OldFunc, NewFunc: Pointer): Ivar
IsDone: TL
function RepointAddrInModule(hModule: TH OldFunc, NewFunc: Pointer): I
Dos: PImageDosH
NT: PImageNTH
ImportDesc: PImage_Import_E
RVA: DWORD;
written: DWORD;
Result := 0;
Dos := Pointer(hModule);
if IsDone.IndexOf(Dos) &= 0
IsDone.Add(Dos);
OldFunc := LocateFunctionAddress(OldFunc);
if IsBadReadPtr(Dos, SizeOf(TImageDosHeader))
if Dos.e_magic && IMAGE_DOS_SIGNATURE
NT := Pointer(Integer(Dos)
dos._lfanew);
RVA := NT^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
if RVA = 0
ImportDesc := pointer(integer(Dos)
while (ImportDesc^.Name && 0) do
DLL := PChar(Integer(Dos)
ImportDesc^.Name);
RepointAddrInModule(GetModuleHandle(PChar(DLL)), OldFunc, NewFunc);
Func := Pointer(Integer(DOS)
ImportDesc.LookupTable);
while Func^ && nil do
f := LocateFunctionAddress(Func^);
if f = OldFunc then
WriteProcessMemory(GetCurrentProcess, Func, @NewFunc, 4, written);
if Written & 0 then Inc(Result);
Inc(Func);
Inc(ImportDesc);
IsDone := TList.C
Result := RepointAddrInModule(GetModuleHandle(nil), OldFunc, NewFunc);
IsDone.F有了这两个函数我们几乎可以更改任何API函数。我们可以先写一个DLL文件。我这里以修改Text相关函数为例:先定义几个函数:type
TTextOutA = function(DC: HDC; X, Y: I Str: PAnsiC Count: Integer): BOOL;
TTextOutW = function(DC: HDC; X, Y: I Str: PWideC Count: Integer): BOOL;
TTextOut = function(DC: HDC; X, Y: I Str: PC Count: Integer): BOOL;
TDrawTextA = function(hDC: HDC; lpString: PAnsiC nCount: I var lpRect: TR uFormat: UINT): I
TDrawTextW = function(hDC: HDC; lpString: PWideC nCount: I var lpRect: TR uFormat: UINT): I
TDrawText = function(hDC: HDC; lpString: PC nCount: I var lpRect: TR uFormat: UINT): Ivar
OldTextOutA: TTextOutA;
OldTextOutW: TTextOutW;
OldTextOut: TTextO
OldDrawTextA: TDrawTextA;
OldDrawTextW: TDrawTextW;
OldDrawText: TDrawT......function MyTextOutA(DC: HDC; X, Y: I Str: PAnsiC Count: Integer): BOOL;begin
OldTextOutA(DC, X, Y, ''''ABC'''', length(''''ABC''''));
function MyTextOutW(DC: HDC; X, Y: I Str: PWideC Count: Integer): BOOL;begin
OldTextOutW(DC, X, Y, ''''ABC'''', length(''''ABC''''));
function MyTextOut(DC: HDC; X, Y: I Str: PC Count: Integer): BOOL;begin
OldTextOut(DC, X, Y, ''''ABC'''', length(''''ABC''''));
function MyDrawTextA(hDC: HDC; lpString: PAnsiC nCount: I var lpRect: TR uFormat: UINT): Ibegin
OldDrawTextA(hDC, ''''ABC'''', length(''''ABC''''), lpRect, uFormat);
function MyDrawTextW(hDC: HDC; lpString: PWideC nCount: I var lpRect: TR uFormat: UINT): Ibegin
OldDrawTextW(hDC, ''''ABC'''', length(''''ABC''''), lpRect, uFormat);
function MyDrawText(hDC: HDC; lpString: PC nCount: I var lpRect: TR uFormat: UINT): Ibegin
OldDrawText(hDC, ''''ABC'''', length(''''ABC''''), lpRect, uFormat);
调用时我们要把原来的函数地址保存下来:
if @OldTextOutA = nil then
@OldTextOutA := LocateFunctionAddress(@TextOutA);
if @OldTextOutW = nil then
@OldTextOutW := LocateFunctionAddress(@TextOutW);
if @OldTextOut = nil then
@OldTextOut := LocateFunctionAddress(@TextOut);
if @OldDrawTextA = nil then
@OldDrawTextA := LocateFunctionAddress(@DrawTextA);
if @OldDrawTextW = nil then
@OldDrawTextW := LocateFunctionAddress(@DrawTextW);
if @OldDrawText = nil then
@OldDrawText := LocateFunctionAddress(@DrawText);然后很顺其自然的用自己的函数替换掉原来的函数
RepointFunction(@OldTextOutA, @MyTextOutA);
版权申明:本站文章均来自网络,如有侵权,请联系028-0
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
服务器技术
西部数码.cn
CopyRight & &西部数码&版权所有
电话总机:028- (20线)
400电话: 400- 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
api hook 原理
下载积分:1500
内容提示:api hook 原理
文档格式:TXT|
浏览次数:0|
上传日期: 05:35:41|
文档星级:
该用户还上传了这些文档
api hook 原理
官方公共微信协议型网络游戏外挂制作之APIHOOK_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
协议型网络游戏外挂制作之APIHOOK
上传于|0|0|文档简介
&&协议型网络游戏外挂制作之APIHOOK1
阅读已结束,如果下载本文需要使用1下载券
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩4页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢今天看啥 热点:
前两天共享了TP驱动和CE编写DNF外挂脚本,那些都是&利其器&,今天继续&善其事&。
当今外挂界主流首推E语言,纯中文编程,不过小白本人没接触过,听说各种模块化的东西,用起来特容易,又名&易语言&。大一的课程只教过C++,那就凑合着用c++编写吧。还是先说下,小白c++功底不高,很多代码只知道怎么写但不知道为什么,这里推荐游戏辅助编程爱好者看《郁金香C++外挂教程》,如果c++的基础实在薄弱就看完孙鑫老师的《孙鑫c++20课》,那个教程虽然是讲C++基础的,但整个20课俨然就是一个外挂编写基础,从用户界面MFC的设计到多线程的注入技术,发包的基础,动态链接库,简单钩子,都学会再看别人代码至少不会一点头绪没有。
这里还是以DNF为例,为啥?因为我目前只研究过DNF,前一阵是研究单机魔兽改图的,和外挂技术一比那就弱爆了。
动态链接库我现在使用还不是很熟练,所以这里先介绍一下不用动态链接库的远程注入代码。
这一贴我还是先扔个砖头,不介绍远程call调用,只说说基础的远程代码注入。
DNF驱动就好比美女的衣服,被脱去后DNF赤裸裸站在你面前,我们可以对其代码为所欲为。
OD找call不是本文的重点,只简单提一下:以人物血量为例。目前来说当前血量基址有两个:01E16E20,01E1805C,对其中任意一个下内存写入断点,堆栈找返回地址,四五层之后,会发现如下一段代码:
mov ecx,esi
call edx调用之前栈顶值就是目标当前血量(这里已经不再只限于人物血量,怪物血量更新也掉用此函数),当怪物打我们时,目前(日)来说这个函数地址(edx值)是。
外挂的原理无非就是修改内存,这里就是修改栈顶值,OD手动把她改为0,运行后就实现秒怪了。
下面我们用C++代码来实现这一功能:
当怪物打我们时,我们在call edx调用时(即当DNF执行到地址时)把保存我们血量的那一堆栈值改为9999,即伪无敌。
大体说下编写思路,最开始肯定获得修改dnf进程内存权限,打开DNF进程后,在其内部申请一段内存,写入我们修改过的代码,并把原DNF代码修改使之运行到时跳转到我们自己编写的代码里去,干完坏事再跳回去,神不知鬼不觉..
(清理现场我做的不是很好,不过这里内存的释放不一定那么重要,没影响)
HWND hwnd = ::FindWindow(NULL,&地下城与勇士&);
& if (!hwnd)
& & MessageBox(&请先运行游戏!&);
& ::GetWindowThreadProcessId(hwnd,&processid);
& HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS,false,processid);
//以上过程为套话,窗口名可以下载spy++获取,想知道每个具体函数自行MSDN或百度
& LPCVOID base = (LPCVOID)0x;
//base是要跳转的dnf原程序代码,我们在这里修改代码,使之跳到我们自己的函数中
& ::ReadProcessMemory(handle,(LPCVOID)0x, & &(LPVOID)&m_char,6,NULL);
//设一个char[1000]型类成员变量,保存游戏程序在处原代码,以便不想用外挂时将代码还原
& LPVOID newaddr=VirtualAllocEx(handle,NULL,0x256,MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
//在DNF进程中申请内存以便存放我们自己编写的代码
& m_newmem=
//保存新申请的内存地址在LPVOID型类成员变量m_newmem中,以便释放
& char ch1={0xe9};
& ::WriteProcessMemory(handle,(LPVOID)0x,(LPVOID)&ch1,1,NULL);
//改写地址中DNF源代码,使他&跳&到我们自己的代码中,我们的代码在申请的newaddr内存中,汇编指令跳jmp机器码0xe9
& int Jmp1=(int)newaddr-0x-5;
//汇编中jmp某地址,转成机器码需要用公式转换:
//机器码中地址=目标地址-e9(jmp)字节所在地址-5
& ::WriteProcessMemory(handle,(LPVOID)0x,(LPVOID)&Jmp1,4,NULL);
//将跳转地址即申请的内存地址转成机器码写入内存
& char ch2={0x90};
& ::WriteProcessMemory(handle,(LPVOID)0x,(LPVOID)&ch2,1,NULL);
//我们改写了源代码的6个字节,而jmp newaddr只用了5个字节,这一字节没有用,用0x90(nop)空代码代替,不改也可以,因为程序不再会执行这里
//随着DNF的更新,这一地址值将会发生变化,但特征码一般不会变,以后若果发现程序不可用,可以特征码搜出新的地址替换
& char ch[15]={0xc7,0x44,0x24,0x04,0x99,0x99,0x00,0x00,0x55,0x8b,0xec,0x8b,0x45,0x10,0xe9};
/*我们自己的代码,汇编代码的机器码,最好你手头有汇编和机器码转换的东东,比如CE里随便写一段就能看见对应的机器码,我这里的汇编是这样的:
mov [esp+04], & &&
&因为是call edx跳过来的,所以堆栈中被压入了call edx下一句地址,那我们的当前血值就是栈顶指针+4,即[esp,+4]里的值,把0x9999传入就是设定当前血量0x9999
push ebp & & & & //源代码 不变
mov ebp,esp & &//源代码 不变
mov eax,[ebp+10] & &//源代码 不变*/
& ::WriteProcessMemory(handle,newaddr,(LPVOID)&ch,15,NULL);
//代码写入到e9(jmp),跳转地址仍需要用公式转换
& int Jmp2=0x60c6a6-(int)newaddr-14-5;
/*我们改写了源代码从开始的6个字节,所以我们应跳回到+6的位置,而当前e9(jmp)所在地址是newaddr+14*/
& ::WriteProcessMemory(handle,(LPVOID)((int)newaddr+15),(LPVOID)&Jmp2,4,NULL);
//写入跳回地址jmp
& & & & CloseHandle(handle);
若果不想用此功能,可将源代码写回
& HWND hwnd = ::FindWindow(NULL,&地下城与勇士&);
& if (!hwnd)
& & MessageBox(&请先运行游戏!&);
& ::GetWindowThreadProcessId(hwnd,&processid);
& HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS,false,processid);
& & & & ::WriteProcessMemory(handle,(LPVOID)0x,(LPVOID)&m_char,6,NULL);
//写回我们改写的6个字节,之前已经保存在了类成员变量中
& & & & VirtualFreeEx(handle,m_newmem,NULL,0x256);
//释放内存,可有可无
如果你对此感兴趣,还可以设置一个编辑框,关联类成员变量后动态输入数字来修改当前血量,还可以编写动态链接库创建全局钩子实现在仓库按Home键呼出外挂界面并且按F2实现功能的开启与关闭,对DC使用熟练还可以美化用户界面,一个简单的C++DNF外挂就编写好了。
友情提醒:
如果你一直开着此功能刷图,掉线率达90%以上,如果要投入使用,请不要一直开启,而且可以将MOV [ESP +4],9999改成add [esp+4],XXX等等实现比较稳定的功能,这里不再赘述。
曾经怀疑出小三是因为有dnf代码校验,后来测试了一下一直手动修改堆栈值还是掉线,看来DNF不是检测的代码来判定小三的。
文中代码新建MFC添加按钮后直接复制可用,我不提供EXE文件下载
暂无相关文章
相关搜索:
相关阅读:
相关频道:
&&&&&&&&&&&&&&&&
C++教程最近更新

我要回帖

更多关于 writeprocessmemory 的文章

 

随机推荐