;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;Patch KERNEL32.DLL export table to avoid common export address.
;
;(C) G-RoM / IceDump Team [Initial code]
;(C) Owl   / IceDump Team [Magic code]
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
;Started on    : 01st Dec 2000
;Latest update : 15th apr 2001
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
		BITS 32

		%include "vxdn.inc"
		%include "pedata.inc"
		%include "memio.inc"
		%include "apicall.inc"
		%include "util.mac"


global ApplyPatchOnSharedDLL


;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; macros Definitions
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
%macro pushr 0
 push esi
 push edi
 push ebx
 push edx
 push ecx
%endmacro

%macro popr 0
 pop  ecx
 pop  edx
 pop  ebx
 pop  edi
 pop  esi
%endmacro


;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
SEGMENT _SDATA
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
	align 4
__ExportBlockStart__:
K32EipTable	dd	0	; Kernel32
K32PatchStart	dd	0       ; Kernel32
U32EipTable	dd	0       ; User32
U32PatchStart	dd	0       ; User32
A32EipTable	dd	0       ; Advapi32
A32PatchStart	dd	0       ; Advapi32
G32EipTable	dd	0       ; GDI32
G32PatchStart	dd	0       ; GDI32
K32Base		dd	0
U32Base		dd	0
A32Base		dd	0
G32Base		dd	0
__ExportBlockEnd__:


;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
SEGMENT _LTEXT
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Bubble sort
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
;esp+4 : Table
;esp+8 : Nb entries
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
SortTable:
	push	ebp
	mov	ebp, esp
	pushad

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Init Index I & J + Boolean.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	push	byte 1
	pop	edx

	mov     esi, [ebp+08h]	; table
	mov     eax, [ebp+0Ch]  ; nb entry
	test    eax, eax
	jz      .SortDone

	dec     eax
	shl     eax, 3
	add     esi, eax

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Permutation where done ?
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
.LoopI:
	dec	edx
	jnz	.SortDone

	mov     edi, [ebp+08h]

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; J < I ?
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
.LoopJ:
	cmp     edi, esi
	jae     .EndInc

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Index[J+1]<Index[J] ?
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	mov     eax, [edi+04h]
	cmp     [edi+0Ch], eax
	jae     .IncJ

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Permute index[J+1] & Index[J]
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	push	dword [edi]
	push	dword [edi+4]

	mov     ebx, [edi+08h]
	mov     [edi], ebx
	mov     ebx, [edi+0Ch]
	mov     [edi+04], ebx

	pop	dword [edi+0Ch]
	pop	dword [edi+08h]

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Permute was done.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	push	byte 1
	pop	edx

.IncJ:
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; J++
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	add     edi, byte 08h
	jmp     short .LoopJ

.EndInc:
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; I--
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	sub     esi, byte 08h
	jmp     short .LoopI

.SortDone:
	popad
	pop	ebp
	retn	08h


;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Create Sorted Table containing Slot and Export Address
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
;esp+4 : DLL BASE
;esp+8 : EipTable address
;
;eax=nb bytes needed for whole addresses/ eax=0 on failure.
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
CreateTable:
	push	ebp
	mov	ebp, esp
	pushr

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Grab export rva.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	mov	edx, [ebp+08h]
	mov	esi, edx
	add	esi, [esi+MZHEADER.NewHeader]
	mov	esi, [esi+PEHeader.ExportRVA]
	mov	[ExportRVA], esi
	add	esi, edx
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Allocate a table.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	mov	ecx, [esi+ExportDir.NbExport]
	lea	eax, [8*ecx+8]

	push	eax
	Call	GetMem
	test	eax, eax
	jz	.Return

	mov	edi, eax
	mov	ebx, [ebp+0Ch]
	mov	[ebx], eax

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Save Slot and ExportAddress.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	mov	esi, [esi+ExportDir.ExportAddress]
	add	esi, edx
	push	ecx

.Looop:
	mov	eax, esi
	stosd

	lodsd
	add	eax, edx	; Store VA
	stosd

	dec	ecx
	jnz	short .Looop

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Sort table on ExportAddress.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	xor	eax, eax
	stosd
	stosd

	mov	eax, [esp]
	lea	eax, [eax+4*eax]

	mov	ebx, [ebp+0Ch]
	push	dword [ebx]
	Call	SortTable

.Return:
	popr
	pop	ebp
	retn	08h


;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Eliminate from table first occurrance of export addresses
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
;esp+4 : DLL BASE
;esp+8 : Total bytes
;
;eax=needed amount of byte for patch / eax=0 on failure.
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
EliminateFirst:
	push	ebp
	mov	ebp, esp
	pushr

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Initialize algorithm.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
 	xor 	eax, eax		; for test
 	xor 	edx, edx                ;
 	dec 	edx                     ; -1 for killing record
	mov	ecx, [ebp+0Ch]		; total nb of bytes
	mov 	esi, [ebp+08h]          ; Source
 	mov 	ebx, [esi+04h]          ; Previous
 	mov 	edi, esi                ; Destination
 	add 	esi, byte 08h           ; next record

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; If current exportaddress!=previous one then kill previous (-1,xx)
; else move to next.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
.LoopWhile:
 	cmp 	[esi], eax
 	jz  	.EndWhile

 	cmp 	[esi+04h], ebx
 	jnz 	.NotEqual

 	add 	esi, byte 08h
 	jmp 	short .LoopWhile

.NotEqual:
 	mov 	[edi], edx
 	mov 	ebx, [esi+04h]
 	mov 	edi, esi
 	add 	esi, byte 08h
	sub	ecx, byte 05h
 	jmp 	short .LoopWhile

.EndWhile:
	mov	eax, ecx
	popr
	pop	ebp
	retn	08h


;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; recommit a range of memory
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
;esp+4 : start address (must be page aligned)
;esp+8 : size (must be page aligned)
;
;eax=0 on failure.
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
ReCommitArea:
	push	ebp
	mov	ebp, esp
	pushr

;-------------------------------------------------------------------------------
; voodoo magic...
;
; 1. allocate memory to hold copy of section data (neeeded in step 3)
; 2. enter critical section (no thread switch should occur)
; 3. copy section data to temporary buffer
; 4. decommit section (this would cause other threads to die if they tried
;    to access this region, since it is no longer valid)
; 5. commit section again, this time using a different pager
; 6. copy section data back
; 7. exit critical section
;
; the end result is that the section is no longer backed by a file and we're
; free to modify it as we want. this is a very powerful technique.
;-------------------------------------------------------------------------------
	VMMCall	_HeapAllocate, dword [ebp+0Ch], byte HEAPZEROINIT
	test	eax, eax
	jz	near .Return

	push	eax

	VMMCall	Begin_Critical_Section

	mov	ecx, [ebp+0Ch]
	mov	esi, [ebp+08h]
	mov	edi, eax
	rep	movsb

	pop	esi

	mov	ebx, [ebp+0Ch]
	add	ebx, 0xFFF
	shr	ebx, 12
	mov	edi, [ebp+08h]
	shr	edi, 12

	VMMCall	_PageDecommit, edi, ebx, dword PC_STATIC
	test	eax, eax
	jnz	@F

	Trace_Out "ICEDUMP: PageDecommit failed for #edi/#ebx"
	jmp	short .Return

@@
	VMMCall	_PageCommit, edi, ebx, byte PD_FIXEDZERO, byte 0, dword PC_FIXED | PC_STATIC | PC_USER | PC_WRITEABLE
	test	eax, eax
	jnz	@F

	Trace_Out "ICEDUMP: PageCommit failed for #edi/#ebx, expect a system crash..."
	jmp	short .Return			; this means *big* trouble ;P

@@
	push	esi
	mov	ecx, [ebp+0Ch]
	mov	edi, [ebp+08h]
	rep	movsb
	pop	esi

	VMMCall	End_Critical_Section

	VMMCall	_HeapFree, esi, byte 0

	push	byte 1
	pop	eax

.Return:
	popr
	pop	ebp
	retn	08h


;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
;esp+4 : DLL BASE
;esp+8 : Free Space Start
;esp+c : Space need in bytes.
;
;eax=0 on failure.
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
FindFreeSpace:
	push	ebp
	mov	ebp, esp
	pushr
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Move to section table.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	mov	edi, [ebp+08h]
	add	edi, [edi+MZHEADER.NewHeader] 		; PE start VA
  	movzx 	esi, word [edi+PEHeader.NTHeaderSize]   ; esi=
  	lea  	esi, [edi+esi+PEHeader.NTHeaderSize+4]  ; esi=PEVA+headersize+4
	movzx	ecx, word [edi+PEHeader.NbObj]

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Init algorithm logic
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	sub	esi, byte Object_size
	inc	ecx

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Scan for a section hole using PSIZE-VSIZE criteria (c) EliCZ
;
; I may come up with a new method later if needed (splitting ?).
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
.ScanSection:
	xor	eax, eax
	dec	ecx
	jz	.Return

	add	esi, byte Object_size
	mov	eax, [esi+Object.PSize]
	sub	eax, [esi+Object.VSize]
	sub	eax, byte 4
	cmp	eax, [ebp+10h]
	jb	.ScanSection

	mov	[PatchObj], esi

	push	dword [esi+Object.PSize]
	mov	eax, [esi+Object.RVA]
	add	eax, [ebp+08h]
	push	eax
	call	ReCommitArea
	test	eax,eax
	jz	.Return

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Compute Free Space address and save it.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	mov	eax, [ebp+08h]
	add	eax, [esi+Object.VSize]
	add	eax, [esi+Object.RVA]
	add	eax, byte 4
	mov	esi, [ebp+0Ch]
	mov	[esi], eax

	push	byte 01
	pop	eax
	jmp	short .Return

.ReturnBad:
	VMMCall	End_Critical_Section

	pop	eax
	VMMCall	_HeapFree, eax, byte 0
	xor	eax, eax

.Return:
	popr
	pop	ebp
	retn	0Ch


;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;Locate Free Space
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
;esp+4 : DLL BASE
;esp+8 : Free Space Start
;
;eax=0 on failure.
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
LocateFreeSpace:
	push	ebp
	mov	ebp, esp
	pushr
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Move to section table.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	mov	edi, [ebp+08h]
	mov	edx, edi
	add	edi, [edi+MZHEADER.NewHeader] 		; PE start VA
  	movzx 	esi, word [edi+PEHeader.NTHeaderSize]   ; esi=
  	lea  	esi, [edi+esi+PEHeader.NTHeaderSize+4]  ; esi=PEVA+headersize+4

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Move to 3rd section (_INIT).
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	add	esi, byte 2*Object_size

	mov	[PatchObj], esi
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Set source to VA of 3rd section.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	mov	eax, [esi+Object.PSize]
	add	eax, 0xFFF
	shr	eax, 12
	mov	esi, [esi+Object.RVA]
	add	esi, edx
	shr	esi, 12

	VMMCall	_PageCommit, esi, eax, byte PD_FIXEDZERO, byte 0, dword PC_FIXED | PC_STATIC | PC_USER

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Save beginning of padding area.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	mov	edi, [ebp+0Ch]
	shl	esi, 12
	mov	[edi], esi

	popr
	pop	ebp
	retn	08h

;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Apply our black magic spell on Export Table Section owner if not already
; protected.
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
;esp+4 : dll base
;
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
CastSpellOnExportTable:
	push	ebp
	mov	ebp, esp
	pushad
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Load various ptr needed for scan loop.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	mov	edi, [ebp+08h]
	mov	edx, edi
	add	edi, [edi+MZHEADER.NewHeader] 		; PE start VA
  	movzx 	esi, word [edi+PEHeader.NTHeaderSize]   ; esi=
  	lea  	esi, [edi+esi+PEHeader.NTHeaderSize+4]  ; esi=PEVA+headersize+4
	movzx	ecx, word [edi+PEHeader.NbObj]
	mov	eax, [ExportRVA]
.ScanObj:
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Is our export table included in this section ?
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	mov	ebx, [esi+Object.RVA]
	add	ebx, [esi+Object.VSize]
	cmp	eax, ebx
	jb	.FoundObj
	add	esi, Object_size
	dec	ecx
	jnz	.ScanObj
	jmp	.Return
.FoundObj:
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Is the section already protected ?
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	cmp	esi, [PatchObj]
	jz	.Return
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Invoke our black magic spell.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	push	dword [esi+Object.PSize]
	mov	eax, [esi+Object.RVA]
	add	eax, [ebp+08h]
	push	eax
	call	ReCommitArea
	test	eax,eax
	jz	.Return
.Return:
	popad
	pop	ebp
	retn	04h
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
;esp+4 : eip table
;esp+8 : Patch Start
;esp+c : dll base
;
;eax=0 on failure.
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
PatchExport:
	push	ebp
	mov	ebp, esp
	pushad

	mov	esi, [ebp+08h]
	mov	edi, [ebp+0ch]
	mov	ebx, [ebp+10h]

.LoopP:
	lodsd
	test	eax, eax
	jz	.AllDone

	inc	eax
	jz	.Next
;	dec	eax

	lodsd
	sub	eax, edi
	sub	eax, byte 05

	mov	[edi], byte 0xE9
	mov	[edi+1], eax

	mov	eax, [esi-08h]
	sub	edi, ebx	; base
	mov	[eax], edi
	add	edi, ebx	; base

	add	edi, byte 05
	jmp	short .LoopP

.Next:
	lodsd
	jmp	short .LoopP

.AllDone:
	popad
	pop	ebp
	retn	0Ch


;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; esp+4 : DLL base
; esp+8 : EipTable Holder
; esp+C : PatchStart Holder
;
;
; eax=1 on success
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
ApplyExportPatch:
	push	ebp
	mov	ebp, esp
	pushr

	mov	esi, [ebp+08h]
	mov	edi, [ebp+0Ch]	; EipTable Address
	mov	ebx, [ebp+10h]	; PatchStart Address

	push	edi		; EipTable Address
	push	esi
	Call	CreateTable
	test	eax, eax
	jz  	.Return

	push	eax
	push	dword [edi]
	Call	EliminateFirst
	test	eax, eax
	jnz	@F

	push	dword [edi]
	call	FreeMem
	and	dword [edi], byte 0
	jmp	short .Return1

@@
	push	eax
	push	ebx		; PatchStart
	push	esi
	Call	FindFreeSpace
	test	eax, eax
	jnz	@F

	push	dword [edi]
	call	FreeMem
	and	dword [edi], byte 0
	xor	eax, eax
	jmp	short .Return

@@
	push	esi
	Call	CastSpellOnExportTable

	push	esi
	push	dword [ebx]
	push	dword [edi]
	Call	PatchExport

.Return1:
	xor	eax, eax
	inc	eax

.Return:
	popr
	pop	ebp
	retn	0Ch


;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; esp+4 : Kernel32 base
;
; eax=1 on success
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
ApplyK32ExportPatch:
	push	ebp
	mov	ebp, esp
	pushr

	mov	esi, [ebp+08h]

	push	dword K32PatchStart
	push	esi
	Call	LocateFreeSpace
	test	eax, eax
	jz	.Return

	push	dword K32EipTable
	push	esi
	Call	CreateTable
	test	eax, eax
	jz  	.Return

	push	eax
	push	dword [K32EipTable]
	Call	EliminateFirst
	test	eax, eax
	jnz	@F

	push	dword [K32EipTable]
	call	FreeMem
	and	dword [K32EipTable], byte 0
	jmp	short .Return1

@@
	push	esi
	Call	CastSpellOnExportTable

	push	esi
	push	dword [K32PatchStart]
	push	dword [K32EipTable]
	Call	PatchExport

.Return1:
	xor	eax, eax
	inc	eax

.Return:
	popr
	pop	ebp
	retn	04h


ApplyPatchOnSharedDLL:
	pushr

	cmp	dword [K32Base], byte 0
	jnz	.u32

	push	dword szK32
	Call	GetModuleHandle
	mov	[K32Base], eax
	test	eax, eax
	jz	@F

	push	eax
	Call	ApplyK32ExportPatch
	test	eax, eax
	jnz	.u32

@@
	Trace_Out "ICEDUMP: warning, KERNEL32 exports are not renormalized"

.u32:
	cmp	dword [U32Base], byte 0
	jnz	.a32

	push	dword szU32
	Call	GetModuleHandle
	mov	[U32Base], eax
	test	eax, eax
	jz	@F

	push	dword U32PatchStart
	push	dword U32EipTable
	push	eax
	Call	ApplyExportPatch
	test	eax, eax
	jnz	.a32

@@
	Trace_Out "ICEDUMP: warning, USER32 exports are not renormalized"

.a32:
	cmp	dword [A32Base], byte 0
	jnz	.g32

	push	dword szA32
	Call	GetModuleHandle
	mov	[A32Base], eax
	test	eax, eax
	jz	@F

	push	dword A32PatchStart
	push	dword A32EipTable
	push	eax
	Call	ApplyExportPatch
	test	eax, eax
	jnz	.g32

@@
	Trace_Out "ICEDUMP: warning, ADVAPI32 exports are not renormalized"

.g32:
	cmp	dword [G32Base], byte 0
	jnz	.Return

	push	dword szG32
	Call	GetModuleHandle
	mov	[G32Base], eax
	test	eax, eax
	jz	@F

	push	dword G32PatchStart
	push	dword G32EipTable
	push	eax
	Call	ApplyExportPatch
	test	eax, eax
	jnz	.Return

@@
	Trace_Out "ICEDUMP: warning, GDI32 exports are not renormalized"

.Return:
	popr
	retn


segment _LDATA
	align 4
ExportRVA	DD	0
PatchObj	DD	0
szK32	DB	'KERNEL32.DLL',0
szU32   DB	'USER32.DLL',0
szA32   DB	'ADVAPI32.DLL',0
szG32   DB	'GDI32.DLL',0
