adongliu 发表于 2015-11-2 21:57:30

如何截获a.exe中的一个函数调用,加入处理后再执行后面的语句?

就像hook截获鼠标和键盘的例子。

SkyGz 发表于 2015-11-2 22:13:22

本帖最后由 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;

nyszx 发表于 2015-11-2 22:32:42

感觉很高深很复杂~莫非这就是春说中的破解软件的方法

wzda_gundam 发表于 2015-11-3 00:06:58

修改入口表

gxnnhy 发表于 2015-11-3 00:43:03

这个专业术语叫做钩子函数,一般通过注入的当时把自己的钩子函数注入到目标进程。一般有三种,加载器注入,全局消息注入,远程线程注入

jsntzxh 发表于 2015-11-3 06:33:47

如果能修改a.exe文件办法多的是,不能修改可以在其目录下放个lpk.dll

qq854149876 发表于 2015-11-3 07:58:27

看上去很高深

adongliu 发表于 2015-11-3 14:00:26

jsntzxh 发表于 2015-11-3 06:33
如果能修改a.exe文件办法多的是,不能修改可以在其目录下放个lpk.dll

有思路吗?

SkyGz 发表于 2015-11-3 14:11:37

jsntzxh 发表于 2015-11-3 06:33
如果能修改a.exe文件办法多的是,不能修改可以在其目录下放个lpk.dll

LPK, 在WIN7以上系统貌似没效果了...MS给补了洞

TANK99 发表于 2015-11-3 14:15:44

2楼的代码要记录一下,说不定会遇到。

jsntzxh 发表于 2015-11-3 20:53:13

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



canspider 发表于 2015-11-3 20:58:12

再写一个程序,在里面用ctreateprocess的方法打开a.exe
打开的时候加入所有权限,这样就能读写子进程的内存了

adongliu 发表于 2015-11-3 21:45:37

原有的程序是用VB编写的,现在想增加一个功能,有一个函数是DOWNLOAD_RECIPT,我想在调用这个函数的时候检查PLC的输入点是否有信号,如果没有信号,跳出对话框,禁止下载程序,否则可以下载程序.

使用HOOK技术无法禁用菜单和toolbar类中的按钮.
页: [1]
查看完整版本: 如何截获a.exe中的一个函数调用,加入处理后再执行后面的语句?