Board logo

Subject: 一个有些类似APIHOOK的问题,请高手帮忙看看 [Print This Page]

Author: 精灵猪    Time: 2007-4-5 03:07     Subject: 一个有些类似APIHOOK的问题,请高手帮忙看看

function TrueFunctionAddress(func: Pointer): Pointer;
var
  Code: PlmportCode;
begin
  Result := func;
  if func = nil then exit;
  try
    Code := func;
    if (Code.jumplnstruction = $25FF) then
    begin
      Result := Code.AddressOfPointer_ToFunction^;
    end;
  except
    Result := nil;
  end;
end;


procedure doit;
begin
messagebox(0,'执行动作','',mb_ok);
end;

用TrueFunctionAddress(@doit);可以得到doit的地址比如我要修改 $00404200 这个地方改为指向doit的jmp应该如何做 有点类似API钩子的那种方法 可是钩的不是API是段代码而已
================================================
我的目的是 让程序执行到00404200这个位置的时候跳到我指定的函数上执行完再跳回去 不知道这种办法成不成 研究了好长时间没解决 求高手指点一下 或者有更好的方法给小弟介绍一下 小弟感激不禁
Author: zjy    Time: 2007-4-5 08:17     Subject: 可以使用或参考CnWizards中提供的CnWizMethodHook.pas文件

可以用来Hook普通的函数或对象方法等,见附件

Attachment: CnWizMethodHook.pas (2007-4-5 08:17, 6.62 K) / Download count 634
http://bbs.cnpack.org/attachment.php?aid=264
Author: Passion    Time: 2007-4-5 09:07

确实,CnWizMethodHook可以很方便的做到这个事情,
前提是在同一进程内。
Author: 精灵猪    Time: 2007-4-5 18:37

可否给个CnWizMethodHook的例子 比如把00404200的地址改为 jmp xxxxxxxx 其中xxxxxxxx为doit函数的地址 ?
Author: kendling    Time: 2007-4-5 21:02

呵呵,CW里就有例子。
Author: Passion    Time: 2007-4-5 22:47

对,CW的源码里头,搜索这个MethodHook的类名就行了。
Author: 精灵猪    Time: 2007-4-6 00:29

多谢各位老哥的回家 不过新的问题出现了 我成功修改程序跳到我指定的函数上了 我的函数是这样写的
procedure doit;
var
s:string;
bagin
asm
mov s,esi
end;
end;
可是执行完我的代码后程序就报错了 主要是我的程序不能跳回到被修改的代码里了 而delphi 的汇编里不能指定 jmp xxxxxx这样的语句

doit的这个函数的目的就是读esi的字符串 读到 00为止 请教各位大哥这个函数我应该如何设计?如果可以不用汇编写我想会方便很多 应该如何做呢?
Author: 精灵猪    Time: 2007-4-6 00:41

jmp 不灵我又用了
push xxxxxx
ret
的方法 虽然是跳回去了 但是还是报错了 看来这个方法也不灵
Author: 精灵猪    Time: 2007-4-6 02:25

小弟又测试了一下 结果不报错了 不过小弟用 mov ser,esi 不能把ESI所指的字符串传递到str里 请问各位大哥如何才能传递到str里 用汇编实在太麻烦了 另外如果高手有其他方法可以在程序经过的时候把esi的字符串传递到str里 而不用汇编也请指点小弟一下  小弟等各位高手的回答 辛苦各位了
Author: zjy    Time: 2007-4-6 08:29

CnWizMethodHook的函数Hook是通过修改被Hook的函数执行体前5个字节为相对跳转指令来实现的,如果需要在执行完Hook函数后重新执行被Hook的函数,需要在Hook函数中先Unhook恢复原函数的前5个字节代码,调用完原函数后再重新Hook。

要获得 esi 的字符串,用汇编是可以的,不过不要用 string 类型的变量,用 PChar 类型即可。

从你提供的资料来看,似乎并不是做函数的Hook,而是想在函数执行体(某个DLL的?)内部插入个钩子来取得 esi 寄存器的值。如果是这样的需求,可以用下面的方法:
1、创建一个TCnMethodHook对象Hook掉目标地址。
2、在Hook函数中用,根据需要用汇编先保存寄存器现场,再将 esi 读到 pchar 全局变量。
3、在Hook函数中用UnhookMethod恢复被Hook函数体。
4、恢复寄存器现场,再用绝对跳转指令或者push 地址加 ret 的方法跳回到原地址执行。
5、如果需要多次挂接,在适应的时机重新挂接。

注:如果在Hook函数中用汇编直接返回原函数,则Hook函数中不能定义任何局部变量。因为局部变量会从堆栈中分配,如果没有正常退出函数而是直接跳转,就会导致堆栈错误,除非你自己去修改堆栈指针。另外,保存寄存器现场也是很重要的,否则Hook函数中修改了EAX等寄存器的内容,可能导致返回后影响原函数正常执行。

调这样的程序,建议用汇编窗口来调试。
Author: 精灵猪    Time: 2007-4-6 12:35

感谢zjy大哥的回答 现在的问题是
1我用TCnMethodHook.Create方法HOOK掉了指定的地址跳到了我的函数上了
2 定义str为pchar变量 可是如何把esi地址上的字符串传递到 str上?  mov str,esi 这样吗?
3 在Hook函数中用UnhookMethod恢复被Hook函数体 这句没理解意思 ,由于程序是修改了原程序的代码 所以我在我的函数上先用pushad保存了各寄存器然后popad 后面又把修改的5字节写上再跳回去的 难道zjy大哥说的方法 UnhookMethod可以不用做这些吗? 小弟新手请教UnhookMethod应该如何调用? TCnMethodHook.UnhookMethod; 这样编译不通过
4 在delphi里用汇编 jmp xxxxxx的绝对跳转用不了的 只能用push 地址加 ret的方法 如果要用jmp xxxxxx 应该如何做?


我的代码是这样的 先用
TCnMethodHook.Create(pointer($005b2617), @doit);
这样就HOOK到了005b2617地址上了
一下是我的doit函数
  procedure doit;
  asm
   cmp edx,0  //判断edx是否为0
   je @getadd //如果是就到getadd上去
   jmp @exit//不是就调用exit

   @getadd:
   pushad
   mov str,esi //str是pchar变量,这里存储的并不是esi的字符串 而是地址 关键是这里不知道如何处理
   popad
   jmp @exit

   @exit:
   add     eax, 8  //这里是恢复被修改的自己 由于我不会用UnhookMethod恢复被Hook函数体 请教如果用的话是不是不用写这些了?应该怎么用?
   test    edi, edi
   push $5B261C  
   ret
  end;




Welcome to CnPack Forum (http://bbs.cnpack.org/) Powered by Discuz! 5.0.0