MadCode Hook didn't work on WINME

c++ / delphi package - dll injection and api hooking
cool_tester
Posts: 75
Joined: Sun Oct 31, 2004 5:45 am

MadCode Hook didn't work on WINME

Post by cool_tester »

Hi there,
i just tried an application that hooks an API within the application only, NOT a System Wide hook, and it didn't work the first time, but worked after i closed it and re-stared the application, so which isn't good.

so i need to know does madcodehook installs something into the system first? and the application have to restart after the first time?
second HOW can i tell if the hook failed from within my application so i can try to re-hook again without having to restart the application? do i just use the longBool returned by HookAPI, and if it didn't hook the first do i have to use HookAPI again or should i use RenewHook instead?

I noticed this on WINME, so I'm not sure if it has the same effect on other systems.
Thanks,
cool_tester
Posts: 75
Joined: Sun Oct 31, 2004 5:45 am

Post by cool_tester »

Some more info:
after i restared the system, the same exact thing happend, start the application the first time and no Hooks.... close the application, and start it again and voild we are hooked, also HookAPI always returns TRUE even when we are not hooked.....

Is this a bug?

i tried four different times, it won't work on the first run of the application.
What do you think?
thanks.
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

I can only guess what went wrong. Here's my guess: In win9x there are several 32bit APIs which do nothing but thunk down to the win9x 16bit dlls. The 32bit APIs are structered very strangely, as a result madCodeHook can't use the main hooking technique (extended code overwriting). In that case madCodeHook automatically uses the alternative hooking technique (mixture mode, explained in the documentation). This alternative hooking technique is not bad at all, but it has one disadvantage: If an application called GetProcAddress to get the address of an API and saves this address somewhere to later use it for calling the API. And if madCodeHook *later* hooks this API for the first time, the hook will not catch API calls which are done through the saved address. As soon as the API was hooked the first time, the problem is gone (until the next reboot).

This would explain why you needed to restart the application.

Which API did you hook?
cool_tester
Posts: 75
Joined: Sun Oct 31, 2004 5:45 am

Post by cool_tester »

i was hooking OpenClipboard API so i can control what the user can copy to the clipboard before it gets to the clipboard .... that way i can allow or disallow the process based on what is being copied?

also i tried to RenewHook but nothing and unhooked and hooked again without any success, the only way to get it to work is restarting the APP.

so do you have any solutions to this problem? any work arounds.?


Thanks.
cool_tester
Posts: 75
Joined: Sun Oct 31, 2004 5:45 am

Post by cool_tester »

Yup the same Exact Behavior on Win 95, damn .....

BTW that's the only API i'm trying to hook, what should i do?

Thanks,
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

Put your app into the autostart and hook & unhook the API once during initialization. After that the problem is gone until the next reboot. Your program can close after it has hooked & unhooked at startup, if you want that.
cool_tester
Posts: 75
Joined: Sun Oct 31, 2004 5:45 am

Post by cool_tester »

MY Hats of to you, :)
It works when i do Hook it and unhook it during initialization.....


THANK YOU VERY MUCH... man i started to panic for a minute there...
cool_tester
Posts: 75
Joined: Sun Oct 31, 2004 5:45 am

Post by cool_tester »

on more question:
is it OK if i Hook it at Initialization and Unhook at Finalization or no.?
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

Sure, that's ok, too.
cool_tester
Posts: 75
Joined: Sun Oct 31, 2004 5:45 am

Post by cool_tester »

Cool,
Ok here is what Works so others can benefit from it.

I Put the Hook on the very first line after initialization, and put the UnHook at the very first line in finalization .. and it works every time.

BTW no need to hook and unhook it just has to be hook first.

Thanks again for your help.

Can you see me jump up and down ! :)
uall
Posts: 254
Joined: Sun Feb 20, 2005 1:24 pm

Post by uall »

madshi i am working on my new codehook and i have added a ExtendedImportTable hook which catch *some* (only if procedure is global declarated) of the APIs which are imported by GetProcAddress here is the code:

Code: Select all

var oldLoadLibraryA: function(s: pchar): integer; stdcall;
    LoadLibraryABeforeOurHookWasInstalled: function(s: pchar): integer; stdcall;

function myLoadLibraryA(s: pchar): integer; stdcall;
begin
  result := oldLoadLibraryA(s);
  MessageBox(0,pchar('Dll loaded: '+s),nil,0);
end;

function HookExtendedImportTable(hmodule: integer; oldaddress, newaddress, notchange: pointer): integer; stdcall;
type trelocblock = record
                     vaddress: integer;
                     size: integer;
                   end;
     prelocblock = ^trelocblock;
var myreloc: prelocblock;
    reloccount: integer;
    startp: ^word;
    i: integer;
    p: ^integer;
    IDH: PImageDosHeader;
    INH: PImageNtHeaders;
begin
  result := 0;
  if (hmodule <> 0) then
  begin
    IDH := pointer(hmodule);
    if (not IsBadReadPtr(IDH,4)) and (IDH^.e_magic = IMAGE_DOS_SIGNATURE) then
    begin
      INH := pointer(cardinal(hmodule)+cardinal(IDH^._lfanew));
      if (not IsBadReadPtr(INH,4)) and (INH^.Signature = IMAGE_NT_SIGNATURE) then
      begin
        myreloc := pointer(hmodule+integer(INH^.OptionalHeader.DataDirectory[5].VirtualAddress));
        startp := pointer(integer(myreloc)+8);
        while myreloc^.vaddress <> 0 do
        begin
          reloccount := (myreloc^.size-8) div sizeof(word);
          for i := 0 to reloccount-1 do
          begin
            if (startp^ xor $3000 < $1000) then
            begin
              p := pointer(myreloc^.vaddress+startp^ mod $3000+hmodule);
              if (not isbadreadptr(pointer(integer(p)-2),6)) and
                 (pbyte(integer(p)-2)^ = $FF) and
                 ((pbyte(integer(p)-1)^ = $25) or (pbyte(integer(p)-1)^ = $15)) and

                 (not isbadreadptr(pointer(p^),4)) and
                 (p^ <> integer(notchange)) and

                 (not isbadreadptr(ppointer(p^)^,4)) and
                 (ppointer(p^)^ = oldaddress) then
              begin
                ppointer(p^)^ := newaddress;
                inc(result);
              end;
            end;
            startp := pointer(integer(startp)+sizeof(word));
          end;
          myreloc := pointer(startp);
          startp := pointer(integer(startp)+8);
        end;
      end;
    end;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  // we dont know that:
  @LoadLibraryABeforeOurHookWasInstalled := getprocaddress(getmodulehandle('kernel32.dll'),'LoadLibraryA');
  LoadLibraryABeforeOurHookWasInstalled('aha2.dll');

  // our extended Import Table Hook (i call it RelocationHook)
  @OldLoadLibraryA := GetProcAddress(GetModuleHandleA('kernel32.dll'),'LoadLibraryA');
  HookExtendedImportTable(GetModuleHandle(nil),@oldLoadLibraryA,@myLoadLibraryA,@@oldLoadLibraryA);
  // new call
  LoadLibraryABeforeOurHookWasInstalled('aha.dll');
end;
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

Interesting! May I use that idea for a future madCodeHook version?
uall
Posts: 254
Joined: Sun Feb 20, 2005 1:24 pm

Post by uall »

sure, its gonna be public in the next days
i have created so many new functions when i was in hospital last week, also i created my own disassembler / debugger which took me up to 100 hours ^^ but it was so boring there, maybe i find some other function which are interesting for you
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

Great - thanks!
uall
Posts: 254
Joined: Sun Feb 20, 2005 1:24 pm

Post by uall »

I have done some little changes of the HookExtendedImportTable code.
Now u dont need to know the address of you old call (@@oldLoadLibrary) but u have to add a new funktion NextLoadLibraryA


The Hookmethod is littlebit faster because of removing one IF line and removing one isbadreadptr call. (but i think its not interesting ;>)

also i forgot to say that the result is the count of all installed hooks
using NextCodeHook instead of @@oldLoadLibrary will help u (madshi) to implement it easier to madCodeHook
also i forgot to say that u dont need to use ImportTable hook anymore because this hook will do it also.

only problem is that u have to call it for every module, ill look if i can add it so i can change the header to:

function HookExtendedImportTable(oldaddress, newaddress: pointer; var nextaddress: pointer): integer; stdcall;

here is the new code:

Code: Select all

var oldLoadLibraryA: function(s: pchar): integer; stdcall;
    LoadLibraryABeforeOurHookWasInstalled: function(s: pchar): integer; stdcall;
    nextLoadLibraryA: function(s: pchar): integer; stdcall;

function myLoadLibraryA(s: pchar): integer; stdcall;
begin
  result := nextLoadLibraryA(s);
  MessageBox(0,pchar('Dll loaded: '+s),nil,0);
end;

function HookExtendedImportTable(hmodule: integer; oldaddress, newaddress: pointer; var nextaddress: pointer): integer; stdcall;
type TRelocBlock = record
                     vaddress: integer;
                     size: integer;
                   end;
     PRelocBLock = ^TRelocBlock;
var myreloc: PRelocBlock;
    reloccount: integer;
    startp: ^word;
    i: integer;
    p: ^integer;
    IDH: PImageDosHeader;
    INH: PImageNtHeaders;
begin
  result := 0;
  IDH := pointer(hmodule);
  if (not IsBadReadPtr(IDH,4)) and (IDH^.e_magic = IMAGE_DOS_SIGNATURE) then
  begin
    INH := pointer(cardinal(hmodule)+cardinal(IDH^._lfanew));
    if (not IsBadReadPtr(INH,4)) and (INH^.Signature = IMAGE_NT_SIGNATURE) then
    begin
      myreloc := pointer(hmodule+integer(INH^.OptionalHeader.DataDirectory[5].VirtualAddress));
      startp := pointer(integer(myreloc)+8);
      while myreloc^.vaddress <> 0 do
      begin
        reloccount := (myreloc^.size-8) div sizeof(word);
        for i := 0 to reloccount-1 do
        begin
          if (startp^ xor $3000 < $1000) then
          begin
            p := pointer(myreloc^.vaddress+startp^ mod $3000+hmodule);
            if (not isbadreadptr(pointer(integer(p)-2),6)) and
               (pbyte(integer(p)-2)^ = $FF) and
               ((pbyte(integer(p)-1)^ = $25) or (pbyte(integer(p)-1)^ = $15)) and

               (not isbadreadptr(ppointer(p^)^,4)) and
               (ppointer(p^)^ = oldaddress) then
            begin
              ppointer(p^)^ := newaddress;
              inc(result);
            end;
          end;
          startp := pointer(integer(startp)+sizeof(word));
        end;
        myreloc := pointer(startp);
        startp := pointer(integer(startp)+8);
      end;
    end;
  end;
  nextaddress := oldaddress;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  // we dont know that:
  @LoadLibraryABeforeOurHookWasInstalled := getprocaddress(getmodulehandle('kernel32.dll'),'LoadLibraryA');
  LoadLibraryABeforeOurHookWasInstalled('aha2.dll');   // not catched because hook is not installed

  // our extended Import Table Hook (i call it RelocationHook)
  @OldLoadLibraryA := GetProcAddress(GetModuleHandleA('kernel32.dll'),'LoadLibraryA');
  HookExtendedImportTable(GetModuleHandle(nil),@oldLoadLibraryA,@myLoadLibraryA,@nextLoadLibraryA);
  // new call
  LoadLibraryABeforeOurHookWasInstalled('aha.dll');   // catched
  LoadLibraryA('test.dll');                           // catched
end;
Post Reply