如何截获a.exe中的一个函数调用,加入处理后再执行后面的语句?
就像hook截获鼠标和键盘的例子。 本帖最后由 SkyGz 于 2015-11-2 23:11 编辑如果是 DLL, 到是好办, EXE 就有点困难了,要知道 该函数的内存地址 才可以..
我想问这EXE是运行中的么?
是的话,写个HOOK DLL, 插入到该EXE的进程中..然后, 晕, 三两句说不完,久没玩了,都忘了
贴点代码,不知有没 给你带来思路,我这个代码(截取INNO SETUP安装包的密码), 作用是 , 将自已的函数 插入到 INNO安装程序里, 然后, 让他运行我的代码,取出 程序的数据, 返回给我的程序用
Function MyGetCommandLineA: PAnsiChar; Stdcall;
Type
PJmpCode = ^TJmpCode;
TJmpCode = Packed Record
JmpCode: Byte;
Address: DWORD;
End;
TVarList = Record {变量列表}
GetInnoPass: DWORD;
CallAddr: DWORD;
End;
Const
HexStr = '53 83 C4 98 8B D8 8B C4 E8 ?? ?? ?? FF BA ?? ?? ?? 00 8B C4 B9 11 00' +
'00 00 E8 ?? ?? ?? FF BA ?? ?? 49 00 8B C4 B9 08 00 00 00 E8 ?? ?? ?? FF 8B C3' +
'E8 ?? ?? ?? FF 8B C8 8B D3 8B C4';//目标进程要查找的数据
Var
S: String;
LibH: THandle;
CurProc, ThreadHandle: THandle;
Written, ThreadID: Cardinal;
MemData: Pointer;
JmpCode: TJmpCode;
GetPwdPtr: DWORD;
//自已DLL内的 函数, 待插到程序内,
Procedure GetPassCode;
Var
VarList: TVarList;
Begin
Asm
MOV EAX, $FFFFFFFF
MOV VarList.GetInnoPass, EAX
MOV EAX, $FFFFFFFF
MOV VarList.CallAddr, EAX
PUSH EBX
CALL VarList.GetInnoPass //将提取到内存中的密码,附值给自已的一个 窗口函数里,并弹出 窗口 显示 当前密码
End;
End;
Begin
Result := GetCommandLineA; //通过HOOK 程序启动命令行的WINDOWS函数, 开始 进行将程序插入到进程里
If Not Data^.IsReadMem Then
Begin
Data^.IsReadMem := True;
If Pos(SkyGz, UpperCase(StrPas(Data^.FileDescription))) <> 0 Then Exit;
S := StringReplace(HexStr, ' ', '', );
CurProc := GetCurrentProcess;
LibH := GetModuleHandleA(PAnsiChar(GetModuleName(0)));
BeginPos := HexFindMemory(CurProc, S, LibH + 400000, LibH + 800000); //在进程里 查找 主程序的 数据.
If BeginPos <> -1 Then
Begin
{在目标进程中分配内存}
MemData := VirtualAllocEx(CurProc, Nil, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
JmpPos := BeginPos + 18 + 7; //在找到的数据里,增加到 相应 位数才是 目标地址
ReadProcessMemory(CurProc, Pointer(JmpPos), @BFD, 5, Written); //将当前位置及地址 保存 备份下来
JmpCode.JmpCode := $E8; //$E9//待修改的跳转指令
JmpCode.Address := LongInt(MemData) - 5 - (JmpPos); //跳转地址
WriteProcessMemory(CurProc, Pointer(JmpPos), @JmpCode, 5, Written); //将跳转地址 写到 目标JmpPos地址里
{把自定义函数写入到目标进程中}
WriteProcessMemory(CurProc, MemData, @GetPassCode, 4096, Written);
{以挂起方式建立远端线程,以便修改}
ThreadHandle := CreateRemoteThread(CurProc, Nil, 0, MemData, Nil, CREATE_SUSPENDED, ThreadID);
GetPwdPtr := DWORD(Windows.GetProcAddress(GetModuleHandleA(PAnsiChar(GetModuleName(HInstance))), 'GetInnoPass'));
WriteProcessMemory(CurProc, Pointer(LongInt(MemData) + 7), @GetPwdPtr, SizeOf(DWORD), Written);
BFD.NewAddress := BFD.Address + 5 + JmpPos; //运行完自已的代码后, 再恢复备份的地址数据 恢复, 继续运行
BFD.NewAddress := BFD.NewAddress - 5 - (DWORD(MemData) + 14);
//WriteProcessMemory(CurProc, Pointer(LongInt(MemData) + 14), @BFD.JmpCode, 1, Written);
WriteProcessMemory(CurProc, Pointer(LongInt(MemData) + 15), @BFD.NewAddress, SizeOf(DWORD), Written);
{释放在目标进程中分配的内存}
//VirtualFreeEx(CurProc, MemData, 4096, MEM_DECOMMIT);
//VirtualFreeEx(CurProc, MemData, 0, MEM_RELEASE);
ResumeThread(ThreadHandle);
CloseHandle(ThreadHandle);
End;
End;
End; 感觉很高深很复杂~莫非这就是春说中的破解软件的方法 修改入口表 这个专业术语叫做钩子函数,一般通过注入的当时把自己的钩子函数注入到目标进程。一般有三种,加载器注入,全局消息注入,远程线程注入 如果能修改a.exe文件办法多的是,不能修改可以在其目录下放个lpk.dll 看上去很高深 jsntzxh 发表于 2015-11-3 06:33
如果能修改a.exe文件办法多的是,不能修改可以在其目录下放个lpk.dll
有思路吗? jsntzxh 发表于 2015-11-3 06:33
如果能修改a.exe文件办法多的是,不能修改可以在其目录下放个lpk.dll
LPK, 在WIN7以上系统貌似没效果了...MS给补了洞 2楼的代码要记录一下,说不定会遇到。 SkyGz 发表于 2015-11-3 14:11
LPK, 在WIN7以上系统貌似没效果了...MS给补了洞
WIN7用管理员权限将lpk.reg导入注册表,重启系统,就能用lpk了。
reg文件内容:
Windows Registry Editor Version 5.00
"ExcludeFromKnownDlls"=hex(7):6c,00,70,00,6b,00,2e,00,64,00,6c,00,6c,00,00,00,\
00,00
再写一个程序,在里面用ctreateprocess的方法打开a.exe
打开的时候加入所有权限,这样就能读写子进程的内存了
原有的程序是用VB编写的,现在想增加一个功能,有一个函数是DOWNLOAD_RECIPT,我想在调用这个函数的时候检查PLC的输入点是否有信号,如果没有信号,跳出对话框,禁止下载程序,否则可以下载程序.
使用HOOK技术无法禁用菜单和toolbar类中的按钮.
页:
[1]