flat assembler
Message board for the users of flat assembler.

Index > Windows > Detours example crashes

Author
Thread Post new topic Reply to topic
StakFallT



Joined: 19 Jan 2006
Posts: 50
StakFallT 25 Aug 2007, 04:04
Just as the subject line states, the Detours example crashes.. It compiles ok but it doesn't run. I think I narrowed it down to this bit of code here
Code:
; allocate jump stub
    mov   ecx, ebx
    add   ecx, $5                 ; +$5 for jmp + address back to original API
    call  halloc
    test  eax, eax
    jz    .done
    


Now I've redownloaded the example and recompiled it, just to make sure and it still crashes.. My guess is because the code is not dynamic in detecting how many bytes to jump past or modify etc due to discrepancies in DLLs across various Windows versions. I've implemented a bit of it's code into my current project which doesn't run either, hence why I went back to the detours example and compiled and tried to run it just to make sure..

Also, in the detours example (assuming it runs, even though at the current moment it doesnt), is the halloc and insert_detours routines flexible/dynamic enough to work for any api call, and just the name of the api needs to be changed (I know the cmp on the 2 bytes would be different, but what about everything else?)?
Post 25 Aug 2007, 04:04
View user's profile Send private message Reply with quote
Adam Kachwalla



Joined: 01 Apr 2006
Posts: 150
Adam Kachwalla 25 Aug 2007, 06:22
What OS are you running it under? If you are talking about the "Windows hooking example" on the Examples page, I can run that under Longhorn Server without a problem.
Post 25 Aug 2007, 06:22
View user's profile Send private message Reply with quote
StakFallT



Joined: 19 Jan 2006
Posts: 50
StakFallT 25 Aug 2007, 08:29
Windows XP SP 2 and yeah, the windows hooking example
Post 25 Aug 2007, 08:29
View user's profile Send private message Reply with quote
StakFallT



Joined: 19 Jan 2006
Posts: 50
StakFallT 25 Aug 2007, 18:18
ok I definitely found the spot I think, it wasn't my original belief of where the code-flow was always coming back to (upon a ret from ntdll). Ok lemme elaborate.

I ran the newly downloaded and compiled detours example, it crashes, so I loaded it up into OllyDbg and I found it to make some jumps (no phun intended) to ntdll, probably due to the various Heap Allocations the example does, anyhow, I had thought when control comes back from ntdll ollydbg was showing me that it lands here:
Code:
mov   ecx, ebx
    add   ecx, $5                 ; +$5 for jmp + address back to original API
    call  halloc
    test  eax, eax
    jz    .done
    


it does't.. it lands here
Code:
@@:
    push  ecx
    push  $0
    push  dword [.heapaddr]
    call  [HeapAlloc]
    pop   edi esi ebx
    ret

.hinit:
    ; get the process heap
    call  [GetProcessHeap]        ; .ProcessHeap is located at +$18 in the                
                                           ; Process Environment Block
    test  eax, eax
    jz    .err

    mov   dword [.heapaddr], eax  ; <--- The line that OllyDbg shows flow 
                                                ; always comes back to                                       
    jmp   @b
    


It seems like it's having some kind of memory allocating problem. The error I get in my console window in ollydbg is:
[/code]
Log data, item 1
Address=0040233A
Message=Access violation when writing to [00402345]
Log data, item 0
Message=Debugged program was unable to process exception
[/code]
A problem allocating memory would certainly explain the memory access violation, er the other way around. An access violation would certainly explain why it can't allocate memory. I know the detours (The Windows Hooking) example does modify memory permissions, but I'm pretty sure that's only for writing opcodes to the particular Windows API call's memory.

as I said I'm on Windows XP SP2.. It is somewhat of a botched sp2 upgrade though. I kind of downgraded when I heard from other techs about how bad the upgrade is (they said it's not so bad if it's an OEM install with sp2), but unfortunately for me it didn't downgrade all that well, it's kinda of a hybrid sp1/sp2. BUT... the specific DLLs can only be each either sp1 or sp2, it's not like you can have a DLL half sp1 and half-sp2, at least not without it not-working.

My original thought is maybe the DLL that has the memory_alloc APIs are one sp and the api it's hooking is another, but again, if that were the case it would be seriously big time noticeable via lots and lots of windows crashes on other applications/games/etc <whatever else>.

Now I do get lots of errors about anything odbc related, like checking event logs (I get permission errors which are actually in error, so I have to browse to the event log file and open it as a saved log file).. So it's kinda been proven that if there's a conflict between sp1 and sp2 files it would show itself. Especially on something as basic/generic as the MessageBoxA (Which the detours example latches into) API.

I've kinda thought this through a bit and I don't think it's because this is a botched upgrade/downgrade that would affect it. The only reason I keep coming back to my install is because you said you downloaded it, compiled it and it ran fine ( I even tried running the exe that came with the zip). But then again you're on Server 2003, they might've improved memory handling slightly or something weird, but that can't really be the case because the example was made before 2003 I'm sure, but... unless nobody ever bothered to try it since it's making (the example that is) which is kinda hard to believe.. Hmm I dunno, too many coins with too many equal opposing sides. I guess the best way to figure this out is, go with what is fact:
1 - The problem exists on my dev setup.
2 - My Windows sp number is not known for certain.
3 - I've tried the exe inside the zip and that doesn't run without crashing.
4 - The ASM code compiles ok.
5 - The compiled code doesn't run without crashing.
6 - Loading it into Ollydbg on my dev setup and running reveals the code-flow constantly coming back to the above code to the above mentioned (in the asm code) line.

I think we need someone with an actual known sp1 to run it and someone with an actual known sp2 to run it, and see if it works.

(I wonder... It's kind of a bit of a stretch but I have seen online games crash due to things like the ATI control center is loaded in the systray. Now I've went as far as disabling my McAfee virus scanner, but I wonder if there's some kind of conflict with another program already running...)

Edit: Just realized something, why would an application get an access violation just trying to allocate memory for itself, doesn't make sense... I wonder if the access violation is caused by the permission on the memory not successfully being modified. Though the violation does seem to come during the halloc business.
Post 25 Aug 2007, 18:18
View user's profile Send private message Reply with quote
FrozenKnight



Joined: 24 Jun 2005
Posts: 128
FrozenKnight 25 Aug 2007, 21:39
I have stated before i don't like the detour method of hooking. because of the way fASM handles data, hooks like this one are easy. as you can access the API memory location directly. but if you wanted to do this hte hard way then you can always walk through the PE and replace the API call location in the PE. both of these methods will work on all versions of windows and are much safer than trying to modify system dll's. Simple ms updates can destroy such hooks.
Post 25 Aug 2007, 21:39
View user's profile Send private message Reply with quote
StakFallT



Joined: 19 Jan 2006
Posts: 50
StakFallT 26 Aug 2007, 15:48
Couple of questions:
1 - When you say "like this one are easy" are you referring to the detours example? And yeah I've tried the IAT route, somehow "not fun" just doesn't quite express it well enough Razz
2 - What exactly do you mean by modifying system dll's? You mean open the dll in something like hiew and literally permanently change the data? yeesh! (sp?) Nah my idea of what I'm trying to do is someone can download the app, drop it into the location where they want and run it. (But still having problems getting the detours example to run :/ )
Post 26 Aug 2007, 15:48
View user's profile Send private message Reply with quote
FrozenKnight



Joined: 24 Jun 2005
Posts: 128
FrozenKnight 27 Aug 2007, 09:36
Detours modify system or other dll's in memory, what i was referring to was
Code:
mov [fun], hookedfun    
this method is rather simple in fASM and will work the same as the example above without the mess.
As for the IAT problem simply look over an example of manual imports they should help a little. And I should be able to help with any problems as i have used this method before.
Post 27 Aug 2007, 09:36
View user's profile Send private message Reply with quote
StakFallT



Joined: 19 Jan 2006
Posts: 50
StakFallT 27 Aug 2007, 23:34
Well the problem with something like:
Code:
mov [fun], hookedfun
    


is it doesn't preserve the original API code, the idea for my app is that it will spit out the parameters to the console passed to the API, call the API and then also spit out the result to the console, after which passing the API result back to the app that made the call.

The IAT stuff could work, I mean it would just I dunno how difficult it would be for me. I did play around a bit with IAT modifying stuff in MASM and it was kind of a nightmare, the code was based off existing code and the resulting asm code was designed to be encapsulated into a DLL with an exported function called Install_hook, or something to that effect, which was then to be called by a VB program.

The nice thing about the detours method was that it didn't seem like it would need to be made into a DLL.. Can the IAT method be done the same way (i.e. make it into an app and not a dll with exported functions called by an app to install the DLL's hook code)
Post 27 Aug 2007, 23:34
View user's profile Send private message Reply with quote
FrozenKnight



Joined: 24 Jun 2005
Posts: 128
FrozenKnight 28 Aug 2007, 17:01
Well, I'm not really fond of giving this code out this is only 2 of the 7 source files i used for this project. (i like separating by content and sections) but if you can follow it then you should have no problem with hooking the IAT

heres the most important part the PE inc. this has all of the structures you will need to find and hook the IAT provided you have the base addr of the modual. (sorry, about the C style comments I used struts form MSDN to create this file.)

PE.INC
Code:
;#define IMAGE_DOS_SIGNATURE                 0x5A4D      // MZ
;#define IMAGE_OS2_SIGNATURE                 0x454E      // NE
;#define IMAGE_OS2_SIGNATURE_LE              0x454C      // LE
;#define IMAGE_VXD_SIGNATURE                 0x454C      // LE
;#define IMAGE_NT_SIGNATURE                  0x00004550  // PE00
IMAGE_DOS_SIGNATURE    = 0x5A4D
IMAGE_OS2_SIGNATURE    = 0x454E
IMAGE_OS2_SIGNATURE_LE = 0x454C
IMAGE_VXD_SIGNATURE    = 0x454C
IMAGE_NT_SIGNATURE     = 0x00004550

;typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
;    WORD   e_magic;                     // Magic number
;    WORD   e_cblp;                      // Bytes on last page of file
;    WORD   e_cp;                        // Pages in file
;    WORD   e_crlc;                      // Relocations
;    WORD   e_cparhdr;                   // Size of header in paragraphs
;    WORD   e_minalloc;                  // Minimum extra paragraphs needed
;    WORD   e_maxalloc;                  // Maximum extra paragraphs needed
;    WORD   e_ss;                        // Initial (relative) SS value
;    WORD   e_sp;                        // Initial SP value
;    WORD   e_csum;                      // Checksum
;    WORD   e_ip;                        // Initial IP value
;    WORD   e_cs;                        // Initial (relative) CS value
;    WORD   e_lfarlc;                    // File address of relocation table
;    WORD   e_ovno;                      // Overlay number
;    WORD   e_res[4];                    // Reserved words
;    WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
;    WORD   e_oeminfo;                   // OEM information; e_oemid specific
;    WORD   e_res2[10];                  // Reserved words
;    LONG   e_lfanew;                    // File address of new exe header
;  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

struct IMAGE_DOS_HEADER
  e_magic    dw ?
  e_cblp        dw ?
  e_cp          dw ?
  e_crlc        dw ?
  e_cparhdr     dw ?
  e_minalloc    dw ?
  e_maxalloc    dw ?
  e_ss          dw ?
  e_sp          dw ?
  e_csum        dw ?
  e_ip          dw ?
  e_cs          dw ?
  e_lfarlc      dw ?
  e_ovno        dw ?
  e_res         dw 4 dup (?)
  e_oemid       dw ?
  e_oeminfo     dw ?
  e_res2        dw 10 dup (?)
  e_lfanew     dd ?
ends

;typedef struct _IMAGE_FILE_HEADER {
;    WORD    Machine;
;    WORD    NumberOfSections;
;    DWORD   TimeDateStamp;
;    DWORD   PointerToSymbolTable;
;    DWORD   NumberOfSymbols;
;    WORD    SizeOfOptionalHeader;
;    WORD    Characteristics;
;} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

struct IMAGE_FILE_HEADER
  Machine            dw ?
  NumberOfSections      dw ?
  TimeDateStamp         dd ?
  PointerToSymbolTable  dd ?
  NumberOfSymbols       dd ?
  SizeOfOptionalHeader  dw ?
  Characteristics       dw ?
ends

;#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16
IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16

;typedef struct _IMAGE_DATA_DIRECTORY {
;    DWORD   VirtualAddress;
;    DWORD   Size;
;} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

struct IMAGE_DATA_DIRECTORY
  VirtualAddress dd ?
  Size                  dd ?
ends

;typedef struct _IMAGE_OPTIONAL_HEADER {
;    //
;    // Standard fields.
;    //
;
;    WORD    Magic;
;    BYTE    MajorLinkerVersion;
;    BYTE    MinorLinkerVersion;
;    DWORD   SizeOfCode;
;    DWORD   SizeOfInitializedData;
;    DWORD   SizeOfUninitializedData;
;    DWORD   AddressOfEntryPoint;
;    DWORD   BaseOfCode;
;    DWORD   BaseOfData;
;
;    //
;    // NT additional fields.
;    //
;
;    DWORD   ImageBase;
;    DWORD   SectionAlignment;
;    DWORD   FileAlignment;
;    WORD    MajorOperatingSystemVersion;
;    WORD    MinorOperatingSystemVersion;
;    WORD    MajorImageVersion;
;    WORD    MinorImageVersion;
;    WORD    MajorSubsystemVersion;
;    WORD    MinorSubsystemVersion;
;    DWORD   Win32VersionValue;
;    DWORD   SizeOfImage;
;    DWORD   SizeOfHeaders;
;    DWORD   CheckSum;
;    WORD    Subsystem;
;    WORD    DllCharacteristics;
;    DWORD   SizeOfStackReserve;
;    DWORD   SizeOfStackCommit;
;    DWORD   SizeOfHeapReserve;
;    DWORD   SizeOfHeapCommit;
;    DWORD   LoaderFlags;
;    DWORD   NumberOfRvaAndSizes;
;    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
;} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

struct IMAGE_OPTIONAL_HEADER32
  ;Standard fields.
  Magic                dw ?
  MajorLinkerVersion            db ?
  MinorLinkerVersion            db ?
  SizeOfCode                    dd ?
  SizeOfInitializedData       dd ?
  SizeOfUninitializedData     dd ?
  AddressOfEntryPoint       dd ?
  BaseOfCode                    dd ?
  BaseOfData                    dd ?
  ;NT additional fields.
  ImageBase                 dd ?
  SectionAlignment              dd ?
  FileAlignment         dd ?
  MajorOperatingSystemVersion dw ?
  MinorOperatingSystemVersion dw ?
  MajorImageVersion         dw ?
  MinorImageVersion             dw ?
  MajorSubsystemVersion       dw ?
  MinorSubsystemVersion       dw ?
  Win32VersionValue         dd ?
  SizeOfImage                   dd ?
  SizeOfHeaders         dd ?
  CheckSum                      dd ?
  Subsystem                     dw ?
  DllCharacteristics            dw ?
  SizeOfStackReserve            dd ?
  SizeOfStackCommit             dd ?
  SizeOfHeapReserve             dd ?
  SizeOfHeapCommit              dd ?
  LoaderFlags                   dd ?
  NumberOfRvaAndSizes           dd ?
  DataDirectory         IMAGE_DATA_DIRECTORY; IMAGE_NUMBEROF_DIRECTORY_ENTRIES dup (?)
                              rb sizeof.IMAGE_DATA_DIRECTORY * (IMAGE_NUMBEROF_DIRECTORY_ENTRIES -1)
ends

;typedef struct _IMAGE_NT_HEADERS {
;    DWORD Signature;
;    IMAGE_FILE_HEADER FileHeader;
;    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
;} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

struct IMAGE_NT_HEADERS32
  Signature         dd ?
  FileHeader    IMAGE_FILE_HEADER
  OptionalHeader IMAGE_OPTIONAL_HEADER32
ends

;#define IMAGE_SIZEOF_SHORT_NAME              8
IMAGE_SIZEOF_SHORT_NAME = 8

;typedef struct _IMAGE_SECTION_HEADER {
;    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
;    union {
;            DWORD   PhysicalAddress;
;            DWORD   VirtualSize;
;    } Misc;
;    DWORD   VirtualAddress;
;    DWORD   SizeOfRawData;
;    DWORD   PointerToRawData;
;    DWORD   PointerToRelocations;
;    DWORD   PointerToLinenumbers;
;    WORD    NumberOfRelocations;
;    WORD    NumberOfLinenumbers;
;    DWORD   Characteristics;
;} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

struct IMAGE_SECTION_HEADER
  Name       db IMAGE_SIZEOF_SHORT_NAME dup (?)
  union
    PhysicalAddress        dd ?
    VirtualSize         dd ?
  ends
  VirtualAddress      dd ?
  SizeOfRawData         dd ?
  PointerToRawData      dd ?
  PointerToRelocations  dd ?
  PointerToLinenumbers  dd ?
  NumberOfRelocations   dw ?
  NumberOfLinenumbers   dw ?
  Characteristics       dd ?
ends

;typedef struct _IMAGE_IMPORT_DESCRIPTOR {
;    union {
;        DWORD   Characteristics;            // 0 for terminating null import descriptor
;        DWORD   OriginalFirstThunk;         // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
;    };
;    DWORD   TimeDateStamp;                  // 0 if not bound,
;                                            // -1 if bound, and real date\time stamp
;                                            //     in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
;                                            // O.W. date/time stamp of DLL bound to (Old BIND)
;
;    DWORD   ForwarderChain;                 // -1 if no forwarders
;    DWORD   Name;
;    DWORD   FirstThunk;                     // RVA to IAT (if bound this IAT has actual addresses)
;} IMAGE_IMPORT_DESCRIPTOR;
;typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;

struct IMAGE_IMPORT_DESCRIPTOR
  union
    Characteristics   dd ?
    OriginalFirstThunk  dd ?
  ends
  TimeDateStamp       dd ?
  ForwarderChain        dd ?
  Name                  dd ?
  FirstThunk            dd ?
ends

;typedef struct _IMAGE_IMPORT_BY_NAME {
;    WORD    Hint;
;    BYTE    Name[1];
;} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

struct IMAGE_IMPORT_BY_NAME
  Hint       dw ?
  Name          db 1 dup (?)
ends

;typedef struct _IMAGE_THUNK_DATA32 {
;    union {
;        DWORD ForwarderString;      // PBYTE
;        DWORD Function;             // PDWORD
;        DWORD Ordinal;
;        DWORD AddressOfData;        // PIMAGE_IMPORT_BY_NAME
;    } u1;
;} IMAGE_THUNK_DATA32;

struct IMAGE_THUNK_DATA32
  union
    ForwarderString     dd ?
    Function            dd ?
    Ordinal             dd ?
    AddressOfData       dd ?
  ends
ends

;#define IMAGE_ORDINAL_FLAG32 0x80000000
IMAGE_ORDINAL_FLAG32 = 0x80000000

IMAGE_SCN_TYPE_REG = 0x00000000      ;Reserved.
IMAGE_SCN_TYPE_DSECT = 0x00000001 ;Reserved.
IMAGE_SCN_TYPE_NOLOAD = 0x00000002        ;Reserved.
IMAGE_SCN_TYPE_GROUP = 0x00000004 ;Reserved.
IMAGE_SCN_TYPE_NO_PAD = 0x00000008        ;Reserved.
IMAGE_SCN_TYPE_COPY = 0x00000010  ;Reserved.
IMAGE_SCN_CNT_CODE = 0x00000020   ;Section contains executable code.
IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040       ;Section contains initialized data.
IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080    ;Section contains uninitialized data.
IMAGE_SCN_LNK_OTHER = 0x00000100       ;Reserved.
IMAGE_SCN_LNK_INFO = 0x00000200   ;Reserved.
IMAGE_SCN_TYPE_OVER = 0x00000400  ;Reserved.
IMAGE_SCN_LNK_COMDAT = 0x00001000 ;Section contains COMDAT data.
IMAGE_SCN_MEM_FARDATA = 0x00008000    ;Reserved.
IMAGE_SCN_MEM_PURGEABLE = 0x00020000      ;Reserved.
IMAGE_SCN_MEM_16BIT = 0x00020000  ;Reserved.
IMAGE_SCN_MEM_LOCKED = 0x00040000 ;Reserved.
IMAGE_SCN_MEM_PRELOAD = 0x00080000        ;Reserved.
IMAGE_SCN_ALIGN_1BYTES = 0x00100000       ;Align data on a 1-byte boundary.
IMAGE_SCN_ALIGN_2BYTES = 0x00200000        ;Align data on a 2-byte boundary.
IMAGE_SCN_ALIGN_4BYTES = 0x00300000        ;Align data on a 4-byte boundary.
IMAGE_SCN_ALIGN_8BYTES = 0x00400000        ;Align data on a 8-byte boundary.
IMAGE_SCN_ALIGN_16BYTES = 0x00500000       ;Align data on a 16-byte boundary.
IMAGE_SCN_ALIGN_32BYTES = 0x00600000      ;Align data on a 32-byte boundary.
IMAGE_SCN_ALIGN_64BYTES = 0x00700000      ;Align data on a 64-byte boundary.
IMAGE_SCN_ALIGN_128BYTES = 0x00800000     ;Align data on a 128-byte boundary.
IMAGE_SCN_ALIGN_256BYTES = 0x00900000    ;Align data on a 256-byte boundary.
IMAGE_SCN_ALIGN_512BYTES = 0x00A00000    ;Align data on a 512-byte boundary.
IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000   ;Align data on a 1024-byte boundary.
IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000  ;Align data on a 2048-byte boundary.
IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000  ;Align data on a 4096-byte boundary.
IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000  ;Align data on a 8192-byte boundary.
IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000  ;Section contains extended relocations.
IMAGE_SCN_MEM_DISCARDABLE = 0x02000000       ;Section can be discarded as needed.
IMAGE_SCN_MEM_NOT_CACHED = 0x04000000   ;Section cannot be cached.
IMAGE_SCN_MEM_NOT_PAGED = 0x08000000      ;Section cannot be paged.
IMAGE_SCN_MEM_SHARED = 0x10000000  ;Section can be shared in memory.
IMAGE_SCN_MEM_EXECUTE = 0x20000000 ;Section can be executed as code.
IMAGE_SCN_MEM_READ = 0x40000000    ;Section can be read.
IMAGE_SCN_MEM_WRITE = 0x80000000       ;Section can be written to.    


this is the actual core of the hook it looks up the base address from the modual name, then it used structs defined previously to address the IAT and modify a function based on it's name or ord. sorry i didnt comment much as i didn't think i would be using this source again.)

Code:
;#define PAGE_NOACCESS          0x01
PAGE_NOACCESS = 0x01
;#define PAGE_READONLY          0x02
PAGE_READONLY = 0x02
;#define PAGE_READWRITE         0x04
PAGE_READWRITE = 0x04
;#define PAGE_WRITECOPY         0x08
PAGE_WRITECOPY = 0x08
;#define PAGE_EXECUTE           0x10
PAGE_EXECUTE = 0x10
;#define PAGE_EXECUTE_READ      0x20
PAGE_EXECUTE_READ = 0x20
;#define PAGE_EXECUTE_READWRITE 0x40
PAGE_EXECUTE_READWRITE = 0x40
;#define PAGE_EXECUTE_WRITECOPY 0x80
PAGE_EXECUTE_WRITECOPY = 0x80
;#define PAGE_GUARD            0x100
PAGE_GUARD = 0x100
;#define PAGE_NOCACHE          0x200
PAGE_NOCACHE = 0x200
;#define PAGE_WRITECOMBINE     0x400
PAGE_WRITECOMBINE = 0x400

;#define TH32CS_SNAPHEAPLIST 0x00000001
;#define TH32CS_SNAPPROCESS  0x00000002
;#define TH32CS_SNAPTHREAD   0x00000004
;#define TH32CS_SNAPMODULE   0x00000008
;#define TH32CS_SNAPMODULE32 0x00000010
;#define TH32CS_SNAPALL      (TH32CS_SNAPHEAPLIST | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD | TH32CS_SNAPMODULE)
;#define TH32CS_INHERIT      0x80000000
TH32CS_SNAPHEAPLIST = 0x00000001
TH32CS_SNAPPROCESS  = 0x00000002
TH32CS_SNAPTHREAD   = 0x00000004
TH32CS_SNAPMODULE   = 0x00000008
TH32CS_SNAPMODULE32 = 0x00000010
TH32CS_SNAPALL       = TH32CS_SNAPHEAPLIST or TH32CS_SNAPPROCESS or TH32CS_SNAPTHREAD or TH32CS_SNAPMODULE
TH32CS_INHERIT         = 0x80000000

INVALID_HANDLE_VALUE = -1

;#define MAX_MODULE_NAME32 255
;#define MAX_PATH          260

MAX_MODULE_NAME32 = 255
MAX_PATH      = 260

;typedef struct tagMODULEENTRY32 {
;  DWORD dwSize;
;  DWORD th32ModuleID;
;  DWORD th32ProcessID;
;  DWORD GlblcntUsage;
;  DWORD ProccntUsage;
;  BYTE* modBaseAddr;
;  DWORD modBaseSize;
;  HMODULE hModule;
;  TCHAR szModule[MAX_MODULE_NAME32 + 1];
;  TCHAR szExePath[MAX_PATH];
;} MODULEENTRY32,
;*PMODULEENTRY32;

struct MODULEENTRY32
  dwSize               dd ?
  th32ModuleID          dd ?
  th32ProcessID         dd ?
  GlblcntUsage          dd ?
  ProccntUsage          dd ?
  modBaseAddr           dd ?
  modBaseSize           dd ?
  hModule               dd ?
  szModule              db (MAX_MODULE_NAME32 + 1) dup (?)
  szExePath               db MAX_PATH dup (?)
ends

proc HookImport  szModule, szImpDll, ImpFunc, ImpFuncIsOrdinal, HookProc
  local BaseAddr:DWORD
  push     [szModule]
  call    FindModule
  cmp     eax, 0
  jz  .fail
  mov  [BaseAddr], eax
  push       eax
  call   VerifyPEfromMZ
  cmp eax, 0
  jz  .fail2
  push        [ImpFuncIsOrdinal]
  push    [ImpFunc]
  push     [szImpDll]
  push    [BaseAddr]
  push    eax
  call   FindImports
  cmp    eax, 0
  jz  .fail3

  local HookAddr:DWORD, OldAddr:DWORD, OldProtect:DWORD, JunkProtect:DWORD
  mov       [HookAddr], eax
  push       ebx
  lea    ebx, [OldProtect]
  push     ebx
  push   PAGE_READWRITE
  push        4
  push     eax
  call   near [VirtualProtect]
  cmp  eax, 0
  jz  .fail4

  mov     eax, [HookAddr]
  push       DWORD [eax]
  pop    DWORD [OldAddr]
  mov        ebx, [HookProc]
  mov        [eax], ebx

  lea ebx, [JunkProtect]
  push    ebx
  lea    ebx, [OldProtect]
  push     ebx
  push   4
  push     eax
  call   [VirtualProtect]
  mov       eax, [OldAddr]
  pop ebx
  ret
 .fail4:
  pop   ebx
 .fail3:
 .fail2:
 .fail:
  xor     eax, eax
  ret
endp

proc   FindImports  PEaddr, BaseAddr, szModual, ImportName, IsOrd
  push    esi
  push   edi
  push   ebx
  push   edx
  mov    esi, [PEaddr]
  mov  esi, [esi + IMAGE_NT_HEADERS32.OptionalHeader\
           + IMAGE_OPTIONAL_HEADER32.DataDirectory\
           + (sizeof.IMAGE_DATA_DIRECTORY * 1)\
               + IMAGE_DATA_DIRECTORY.VirtualAddress]
  add   esi, [BaseAddr]
  local ImportBaseAddr:DWORD
  mov    [ImportBaseAddr], esi
  .while0:
   xor        eax, eax
   or       eax, [esi + IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk]
   or        eax, [esi + IMAGE_IMPORT_DESCRIPTOR.TimeDateStamp]
   or     eax, [esi + IMAGE_IMPORT_DESCRIPTOR.ForwarderChain]
   or    eax, [esi + IMAGE_IMPORT_DESCRIPTOR.Name]
   or      eax, [esi + IMAGE_IMPORT_DESCRIPTOR.FirstThunk]
   cmp       eax, 0
   jz         .fail

   push  MAX_MODULE_NAME32
   push  [szModual]
   mov        eax, [esi + IMAGE_IMPORT_DESCRIPTOR.Name]
   add     eax, [BaseAddr]
   push  eax
   call  stricmp
   cmp   eax, 0
   jnz        .next0

   mov    edi, [esi + IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk]
   cmp       edi, 0
   jz        .fail
   mov  ebx, [esi + IMAGE_IMPORT_DESCRIPTOR.FirstThunk]
   add       edi, [BaseAddr]

   .while1: ;while edi != 0

    test  dword [edi], IMAGE_ORDINAL_FLAG32
    jnz    .importByOrdinal
     cmp   [IsOrd], 0
     jz   .next1
     mov   eax, [edi]
     add   eax, [BaseAddr]
     add   eax, IMAGE_IMPORT_BY_NAME.Name
     push  MAX_MODULE_NAME32
     push  [ImportName]
     push  eax
     call  stricmp
     cmp   eax, 0
     jz    .fin
     jmp   .next1

   .importByOrdinal:
    cmp   [IsOrd], 0
    jnz    .next1
    mov   edx, [ImportName]
    mov   eax, [edi]
    and   eax, 0xFFFF
    cmp   eax, [edx]
    jz         .fin

   .next1:
    add   edi, 4
    add   ebx, 4
    cmp   dword [edi], 0
   jnz       .while1
  .next0:
   add      esi, sizeof.IMAGE_IMPORT_DESCRIPTOR
  jmp   .while0

  ;db 10 dup 0x90
 .fin:
  mov  eax, ebx
  add  eax, [BaseAddr]
  pop  edx
  pop  ebx
  pop  edi
  pop  esi
  ret

 .fail:
  xor        eax, eax
  pop  edx
  pop  ebx
  pop  edi
  pop  esi
  ret
endp

proc   VerifyPEfromMZ  MZaddr
  mov eax, [MZaddr]
  cmp  word [eax + IMAGE_DOS_HEADER.e_magic], IMAGE_DOS_SIGNATURE
  jnz     .fail
  add  eax, [eax + IMAGE_DOS_HEADER.e_lfanew]
  cmp dword [eax + IMAGE_NT_HEADERS32.Signature], IMAGE_NT_SIGNATURE
  jnz .fail
  ret
 .fail:
  pop  ebx
  xor    eax, eax
  ret
endp

proc   FindModule  wszModuleNamePtr
  push  ebx
  push   ecx
  push   edx
  push   0
  push     TH32CS_SNAPMODULE
  call     [CreateToolhelp32Snapshot]
  cmp     eax, INVALID_HANDLE_VALUE
  jz       .fail
  local hSnapshot:DWORD, ModEntry:MODULEENTRY32
  mov       [hSnapshot], eax
  mov       [ModEntry.dwSize], sizeof.MODULEENTRY32
  lea        edx, [ModEntry]
  push       edx
  push   eax
  call   near [Module32First]
  cmp   eax, 0
  jz  .fail
  cmp  [wszModuleNamePtr], 0
  jz   .exittrue
 .checkmodname:
  push      MAX_MODULE_NAME32 + 1
  push [wszModuleNamePtr]
  lea     eax, [ModEntry.szModule]
  push      eax
  ;call  strcmp
  call        stricmp
  cmp        eax, 0
  jz  .exittrue
  lea      eax, [ModEntry]
  push       eax
  push   [hSnapshot]
  call   near [Module32Next]
  cmp    eax, 0
  jz  .fail
  jmp  .checkmodname
  ;db    'hope your having fun looking at this!',0
 .exittrue:
  push      [hSnapshot]
  call   [CloseHandle]
  mov  eax, [ModEntry.modBaseAddr]
  pop    edx
  pop    ecx
  pop    ebx
  ret
 .closeandfail:
  push   [hSnapshot]
  call   [CloseHandle]
 .fail:
  pop   edx
  pop    ecx
  pop    ebx
  xor eax,eax
  ret
endp

proc  stricmp  dest, src, count
  push  esi
  push   edi
  push   ebx
  push   ecx
  push   edx
  mov    esi, [src]
  mov     edi, [dest]
  mov    ebx, [count]
  xor   eax, eax
  xor       ecx, ecx
  xor       edx, edx
 .checkloop:
  cmp   ecx, ebx
  jge       .cleanup
  inc       ecx
  mov    al, byte [esi]
  mov dl, byte [edi]
  cmp dl, 0
  jz   .checkagain
  cmp    al, 0
  jz   .srcisgreater
  cmp  al, 'Z'
  jg       @f
  cmp     al, 'A'
  jl       @f
  or      al, 0x20
 @@:
  cmp   dl, 'Z'
  jg       @f
  cmp     dl, 'A'
  jl       @f
  or      dl, 0x20
 @@:
  inc   esi
  inc    edi
  sub    al, dl
  jz  .checkloop
  jmp     .cleanup
 .checkagain:
  cmp  al, 0
  jz   .same
  mov  eax, 1
  jmp .cleanup
 .srcisgreater:
  mov        eax, -1
  jmp        .cleanup
 .same:
  xor        eax, eax
 .cleanup:
  pop     edx
  pop    ecx
  pop    ebx
  pop    edi
  pop    esi
  ret
endp    


i almost forgot you will need these funtions for everything to work correctly.
Code:
;the follwoing imports are required for proper useage of myHookFinctions
section '.itext' import data readable writeable
  library     kernel32,   'KERNEL32.DLL'

  import      kernel32,\
         Module32First,            'Module32First',\         ;hook
        Module32Next,             'Module32Next',\          ;
            CreateToolhelp32Snapshot, 'CreateToolhelp32Snapshot',\ ;required
         CloseHandle,              'CloseHandle',\           ;
            VirtualProtect,           'VirtualProtect'\        ;imports
              \
          ,GetModuleHandle,    'GetModuleHandleA'    


Admins or mods please delete any material which is against policy's or violation of copyrights. as i am not sure if anything here violates either.


Last edited by FrozenKnight on 12 Sep 2007, 08:39; edited 1 time in total
Post 28 Aug 2007, 17:01
View user's profile Send private message Reply with quote
FrozenKnight



Joined: 24 Jun 2005
Posts: 128
FrozenKnight 05 Sep 2007, 08:19
i just realized i never gave you an example of how to use the files i provided above.

heres the test file i gave (though they can be used in any pe file i used them in a DLL used to hook a coupple of functions in mIRC. just for test purposes.)

Code:
format PE GUI 4.0 DLL ;at 7000000h; on 'mirc.exe'
entry  DllMain

include 'win32a.inc'
include 'PE.inc'

;include 'HookDllStructs.inc'
include 'HookDllData.inc'
include 'HookDllImports.inc'
include 'hookDllRes.inc'

section '.code' code readable executable

include 'HookDllFunctions.asm'
;HookImport  szModule, szImpDll, ImpFunc, ImpFuncIsOrdinal, HookProc
;retuns old import addr in eax

;dllname db 'HookDll.dll',0
proc        DllMain  hinstDLL, fdwReason, lpvReserved
  mov      eax, [fdwReason]
  cmp       eax, DLL_PROCESS_ATTACH
  jz .attach
  cmp        eax, DLL_PROCESS_DETACH
  jz .detach
  ret

 .attach:
;send
  push        fsend
  push 0
  push     ordsend
  push       szImpName
  push     0;szModname
  call   HookImport
  mov     [fOrgsend], eax
  cmp        eax, 0
  jz  .failattach
;recv
  push  frecv
  push 0
  push     ordrecv
  push       szImpName
  push     0;szModname
  call   HookImport
  mov     [fOrgrecv], eax
  cmp        eax, 0
  jz  .failattach

 .failattach:
  ret

 .detach:
  push    [fOrgsend]
  push    0
  push     ordsend
  push       szImpName
  push     0;szModname
  call   HookImport
;recv
  push   [fOrgrecv]
  push    0
  push     ordrecv
  push       szImpName
  push     0;szModname
  call   HookImport
  ret
endp

;szModname db 'mirc.exe',0
szImpName db 'WSOCK32.dll',0
ordrecv   dd 16;recv
ordsend   dd 19;send

;int send(
;  SOCKET s,
;  const char* buf,
;  int len,
;  int flags
;);
proc        fsend  s, buf, len, flags

  push [flags]
  push       [len]
  push [buf]
  push [s]
  call   [fOrgsend]
  ret
endp

;int recv(
;  SOCKET s,
;  char* buf,
;  int len,
;  int flags
;);
proc    frecv  s, buf, len, flags

  push [flags]
  push       [len]
  push [buf]
  push [s]
  call   [fOrgrecv]
  ret
endp


section '.reloc' fixups data discardable    


While i believe with my experience now i could clean these files up quite a bit and even optimize them I haven ever taken the time to do so.


Last edited by FrozenKnight on 12 Sep 2007, 08:43; edited 1 time in total
Post 05 Sep 2007, 08:19
View user's profile Send private message Reply with quote
ManOfSteel



Joined: 02 Feb 2005
Posts: 1154
ManOfSteel 10 Sep 2007, 16:16
Detour example crashes on Win98SE too.
insert_detour call fails since the original MessageBoxA is shown and oMessageBoxA crashes the program.
What should be modified to make it work?
Post 10 Sep 2007, 16:16
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.