上次问个拦截GETPROCADDRESS的API的问题!http://expert.csdn.net/Expert/topic/1782/1782428.xml?temp=.278042 在mygetprocaddress函数里判断是否有我要拦截的函数,如果有则跳转到我要拦截的函数myrecvfrom里,我是在myrecvfrom里处理完数据调用getprocaddress函数来获得recvfrom的原类的地址的!我是这么写的:function mygetproc(hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall;
    var a:integer;
        b:lpcstr;    begin     a:=hmodule;
     b:=lpprocname;
     if (b='recvfrom') then
     begin
     my1:=a;  //my1全局变量是HMODULE类型,用来存储hModuled的数据;
     my2:=b; //my2也是全局变量,是LPCSTR类型
     result:=@myrecvfrom;//跳转到我的地址;
    
     end
     else
     
     result:=getprocaddress(a,b);
    end;function myrecvfrom(s: TSocket; var Buf; len, flags: Integer;
  var from: TSockAddr; var fromlen: Integer): Integer; stdcall;
    begin
     处理数据的地方!    @myfun:= getprocaddress(my1,my2);    result:= myfun(s,buf,len,flags,from,fromlen);
    
 
  end;
请你帮我看看什么地方有待改进?为什么要拦截的程序有时总是非法操作呢?

解决方案 »

  1.   

    我都快被你弄胡涂了 ^_^
    上个帖子不是已经写的很清楚了吗,我觉得可能是这里的问题
    @myfun:= getprocaddress(my1,my2);
    照你的意思应该是这样吧type
      TMyrecvfrom = function myrecvfrom(s: TSocket; var Buf; len, flags: Integer;
      var from: TSockAddr; var fromlen: Integer): Integer; stdcall;你用 @myfun:= getprocaddress(my1,my2); 取得真实函数地址,但是这个 getprocaddress 已经被挂接了,会跳到 function mygetproc(hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall; 这里面呢?判断lpprocname先,若是 recvfrom 就跳转,也就是说,又是一个死循环啊!所以不行,你为什么不在程序最开始(那个帖子我说过了)的时候取得正确地址呢?
    getprocaddress(...)得到真实地址,保存下来。唯一的要求就是这时候这个函数没有被挂接。
    你再看看上个帖子,我觉得我说的很清楚了 ^_^
      

  2.   

    function myrecvfrom(s: TSocket; var Buf; len, flags: Integer;
      var from: TSockAddr; var fromlen: Integer): Integer; stdcall;
        begin
         处理数据的地方!    @myfun:= getprocaddress(my1,my2);    result:= myfun(s,buf,len,flags,from,fromlen);
        
     
      end;
    我发现我用if (b='recvfrom') then 时就会出错!是不是要分配动态内存啊?(我刚开始接触DELPHI,所以不是很熟悉!不要笑我!呵呵!)而比如我要拦截的程序用了3个getpeocaddress加载了3个函数!而这个recvfrom函数是第3个被加载的!那么我用一个记数变量var zz:integer;改一下初始化 zz:=1;function mygetproc(hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall;
        var a:integer;
         b:lpcstr;    begin    a:=hmodule;
         b:=lpprocname;     if zz=3 then
         begin
         my1:=a;
         my2:=b;
         zz:=zz+1;
        
         result:=@myrecvfrom;
       
         end     else
         begin
         zz:=zz+1;
         
         result:=getprocaddress(a,b);
         end;就是把 if (b='recvfrom') then 改为了判断热recvfrom是被第几个加载的函数,这样就不会出错了!我总觉得是不是原来定义的b:lpcstr;在这里要分配一个动态内存才可以啊?谢谢!帮帮看看吧!为了这个我到现在还没有吃午饭!郁闷,饥饿ING!:)
      

  3.   

    这样定义吧function mygetproc(hModule: HMODULE; lpProcName: PChar): Pointer; stdcall; //用pchar和pointer
    字符串比较用 StrIComp ,具体可以看帮助。
    还有,“而比如我要拦截的程序用了3个getpeocaddress加载了3个函数!”这是什么意思?
    你的实现代码是在dll中吧,那样不存在我说的死循环的问题。
      

  4.   

    对实现的代码全在DLL里!但你说的地方我有些不明白就是:function mygetproc(hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall;
        var a:integer;
            b:lpcstr;    begin     a:=hmodule;
         b:=lpprocname;
         if (b='recvfrom') then
         begin
         my1:=a;  //my1全局变量是HMODULE类型,用来存储hModuled的数据;
         my2:=b; //my2也是全局变量,是LPCSTR类型
         result:=@myrecvfrom;//跳转到我的地址;
        
         end
         else
         
         result:=getprocaddress(a,b);
        end;上面的:
         else
         result:=getprocaddress(a,b);  这里我调用getprocaddress(a,b)时,是在调用getprocaddress真正的地址,还是又进入到mygetproc里啊?我都是在一个DLL里实现的代码!谢谢!
      

  5.   

    我明白了!......不过楼主你这样真没有必要,用stricomp,不区分大小写比较,相等返回0。
    还有声明函数还是用pchar和pointer比较好。
    在windows.pas中有 FARPROC = Pointer;和 LPCSTR = PAnsiChar;
      

  6.   

    面的:
         else
         result:=getprocaddress(a,b);  这里我调用getprocaddress(a,b)时,是在调用getprocaddress真正的地址,还是又进入到mygetproc里啊?我都是在一个DLL里实现的代码!谢谢!帮我回答下这个呗!
      

  7.   

    这样说吧,你要拦截一个.exe的某个api函数,通过修改导入表地址。比如getprocaddress。
    取得真实的函数地址地址又是用getproceaddress,但是是在dll中,也就是说,只要你没有修改这个dll的导入表地址,那么就是调用真正的函数,不会又回到你的挂接函数中。
    function mygetproc(hModule: HMODULE; lpProcName: Pchar): FARPROC; stdcall;
    begin
         if stricomp(lpProcName,pchar('recvfrom')) = 0 then //拦截的是目标函数
         begin
           Result := @myrecvfrom; 
           //返回挂接函数地址
         end else
         result := getprocaddress(hmodule,lpprocname);
         //否则返回真实地址,用getproceaddress得到,因为是在dll中,所以不会循环;
    end;
      

  8.   

    那就是说这里的result := getprocaddress(hmodule,lpprocname);的确是返回getprocaddress的真实函数的地址是吗?而不会进入到我的mygetproc函数里?
      

  9.   

    当然,你挂接的是.exe里的getprocaddress,现在是调用的dll中的getprocaddress,当然不会进入你的挂接函数。除非你把这个dll中的getprocaddress也挂接了。