%include "util.mac"
%include "vxdn.inc"
%include "icedump.inc"
%include "wiat.inc"
%include "common.inc"
%include "fileio.inc"
%include "options.inc"
%include "memio.inc"
%include "pedata.inc"
%include "peio.inc"
%include "peimp.inc"
%include "peutil.inc"
%include "pereloc.inc"
%include "peres.inc"
%include "plug.inc"
%include "taskmod.inc"
%include "apicall.inc"
%include "win32n.inc"


global Parse_Pedump
global Parse_Hydra
global Service_Pedump
global rOptions


extern SetCB
extern sdata
extern Parser.error
extern Parser.errorMsg
extern Error_V86
extern Error_PM16
extern Error_PMR0
extern ParseExpression


bits 32


segment _LTEXT
;-------------------------------------------------------------------------------
; PEDUMP <ImageBase> <entry RVA> <FileName>
;-------------------------------------------------------------------------------
Parse_Pedump:
	mov	edi,Error_V86
	mov	ebp,[dClient_EFLAGS]
	test	byte [ebp+2],2			; is client in V86 mode?
	jnz	near Parser.errorMsg

	mov	edi,Error_PM16
	mov	ebp,[dClient_CS]
	lar	eax,[ebp]			; is client 32 bit?
	bt	eax,22
	jnc	near Parser.errorMsg

	mov	edi,Error_PMR0
	test	byte [ebp],3			; is client in ring-0?
	jz	near Parser.errorMsg

	push	byte SERVICE_PEDUMP
	mov	ebp,[dClient_EAX]
	pop	dword [ebp]

	call	ParseExpression
	jb	near Parser.error

	mov	[PEBuffer], eax

	call	[pSkipWhiteSpace]
	jz	near Parser.error

	call	ParseExpression
	jb	near Parser.error

	mov	[FinalEIP], eax

	call	[pSkipWhiteSpace]
	jz	near Parser.error

	push	esi
	push	dword __Dest
	call	[pStrcpy_nocheck]
	add	esp,byte 8

	call	SetCB

	mov	ebp,[fExecuteMoreCommands]	; set internal Winice flag to 0
	mov	byte [ebp],0

	popad
	retn


;-------------------------------------------------------------------------------
; HYDRA [<plugin name>]
;-------------------------------------------------------------------------------
Parse_Hydra:
	mov	byte [plugin],0
	call	[pSkipWhiteSpace]
	jz	@F

	push	dword plugin
	push	esi
	Call	strcopy

@@
	popad
	retn


;-------------------------------------------------------------------------------
;
;-------------------------------------------------------------------------------
Service_Pedump:
	Trace_Out "ICEDUMP: Phoenix engine v2.17 (C) G-RoM 1998/2001"
	Trace_Out ""

	mov	[.ESP],esp

	mov	esi, EH_Pedump1
	VMMCall	Install_Exception_Handler
	jnc	@F

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Failed to install exception handler [1]"
	debug_end

	jmp	.ret

@@
	mov	esi, EH_Pedump2
	VMMCall	Install_Exception_Handler
	jnc	@F

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Failed to install exception handler [2]"
	debug_end

	jmp	.free_eh1

@@
	mov	esi, EH_Pedump3
	VMMCall	Install_Exception_Handler
	jnc	@F

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Failed to install exception handler [3]"
	debug_end

	jmp	.free_eh2

@@
	mov	esi, EH_Pedump4
	VMMCall	Install_Exception_Handler
	jnc	@F

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Failed to install exception handler [4]"
	debug_end

	jmp	.free_eh3

@@
.protect_start:

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Exception handlers installed"
	debug_end

	call	GetCurrentProcessID

	push	dword FileNameBuffer
	push	eax
	call	GetNamePID
	test	eax, eax
	jz	.SkipUpdateHeader

	push	dword [PEBuffer]
	push	dword FileNameBuffer
	call	ReloadPEHeader

	cmp	[rOptions+RebuildOptions.ComputeImage], byte 1
	jnz	.SkipUpdateHeader

	push	dword [PEBuffer]
	call	ComputeImageSize

.SkipUpdateHeader:
	push	dword PEInfos
	push	dword [PEBuffer]
	call	GetPEInfos
	test	eax, eax
	jnz	@F

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	mov	eax,[PEBuffer]
	Trace_Out "ICEDUMP: Phoenix : No PE header at #eax"
	debug_end

	jmp	.free_eh4
@@
	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : PEInfos Collected [1]"
	debug_end

	mov	ecx, [PEBuffer]				; Effective IMGBase
	mov	[PEInfos+PEStruc.ImageBase], ecx
	mov	ecx, [PEInfos+PEStruc.ImageSize]
	mov	[PEInfos+PEStruc.FileSize], ecx

	push	ecx
	call	GetMem
	test	eax, eax
	jnz	@F

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Failed to allocate PE Buffer, size: #ecx"
	debug_end

	jmp	.free_eh4

@@
	mov	[hBuffer], eax

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : PE Buffer allocated"
	debug_end

	mov	ecx, [PEInfos+PEStruc.ImageSize]
	mov	edi, [hBuffer]
	mov	esi, [PEBuffer]
	rep	movsb

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : PE Image replicated"
	debug_end

	push	dword PEInfos
	push	dword [hBuffer]
	call	UpdateSections

	cmp	[rOptions+RebuildOptions.ReduceHeader], byte 0
	jz	@F

	push	dword PEInfos
	push	dword [hBuffer]
	Call	ReduceStub
@@
	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : PEInfos Collected [2]"
	debug_end

	call	GetCurrentProcessID

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Current TaskDB: #eax"
	debug_end

	push	dword [PEBuffer]
	push	dword DBuffer
	push	eax
	call	BuildDLLList
	test	eax, eax
	jnz	@F

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Failed to allocate DLL List"
	debug_end

	jmp	.Free1

@@
	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : DLL List allocated"
	debug_end

; load user specified plugin
	cmp	byte [plugin],0
	jnz	@F

	call	.CleanHydra
	jmp	short .skipplugin

@@
	cmp	dword [hPlugin],byte 0
	jz	@F

	push	dword plugin
	call	GetPluginHandle

	cmp	dword [hPlugin],eax
	jz	.skipplugin

	call	.CleanHydra

@@
	push	dword plugin
	call	LoadPlugin

	mov	[hPlugin],eax
	test	eax, eax
	jnz	@F

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Hydra : Plugin Load Failure"
	debug_end
	jmp	short .skipplugin

@@
	cmp	byte [rOptions+RebuildOptions.ImportMode], 4
	jnz	@F

	push	dword ProcessIAT
	push	dword [hPlugin]
	call	GetAddress

	push	eax
	call	SetProcessIAT

@@
	push	dword UnWrapThunk
	push	dword [hPlugin]
	call	GetAddress

	push	eax
	call	SetUnwrapThunk

.skipplugin:
	push	dword IBuffer
	push	dword IData
	push	dword [DBuffer]
	push	dword PEInfos
	push	dword [hBuffer]
	call	RebuildImport
	test	eax, eax
	jnz	@F

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Failed to rebuild Import table"
	debug_end
	jmp	.Free3

@@
	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Import table rebuilt"
	debug_end

	cmp	[rOptions+RebuildOptions.RestoreReloc], byte 1
	jnz	.CheckIfAddSection

	push	dword PEInfos
	push	dword [hBuffer]
	Call	DetectOldReloc

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Old relocation detection attempt done"
	debug_end
.CheckIfAddSection:
	cmp	[rOptions+RebuildOptions.RestoreReloc], byte 2
	jz	.AddObject
	cmp	[rOptions+RebuildOptions.ImportMode], byte 3
	jl	.CheckRSRC

	cmp	[IData+Object.Offset], dword 0
	jz	.CheckRSRC
.AddObject:
	push	byte 1
	push	dword IData
	push	dword PEInfos
	push	dword [hBuffer]
	Call	AddSection
	mov	[ObjPtr1], eax
	mov	[eax+3+Object.Flags], byte 0xFF
.CheckRSRC:
	cmp	[rOptions+RebuildOptions.RestoreRsrc], byte 0
	jz	.SetPEINFOS

	push	byte 0
	push	dword RData
	push	dword PEInfos
	push	dword [hBuffer]
	Call	AddSection

	push	dword RData
	push	dword PEInfos
	push	dword [PEBuffer]	; instead of [hBuffer] just in case someone wanna reduce object/imagesize.
	Call	RebuildRsrc
	test	eax, eax
	jz	.SetPEINFOS
	mov	[RBuffer], eax

	push	byte 1
	push	dword RData
	push	dword PEInfos
	push	dword [hBuffer]
	Call	AddSection

	mov	[ObjPtr2], eax
	mov	[eax+3+Object.Flags], byte 0xFF
	mov	ebx, [eax+Object.RVA]
	mov	[PEInfos+PEStruc.RsrcRVA], ebx

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Resource coagulation done"
	debug_end

.SetPEINFOS:
	mov	eax, [FinalEIP]
	mov	[PEInfos+PEStruc.EIP], eax

	push	dword PEInfos
	push	dword [hBuffer]
	call	SetPEInfos

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : PEInfos updated"
	debug_end

	push	dword CSBannerLen
	push	dword CSBanner
	push	dword PEInfos
	push	dword [hBuffer]
	call	OptimizePE
	test	eax, eax
	jnz	@F

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Failed to optimize PE Image"
	debug_end

	jmp	.Free3

@@
	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : PE Image Optimized"
	debug_end

	xor	ecx, ecx
	mov	ebx, [ObjPtr1]
	test	ebx, ebx
	jz	@F
	mov	[ebx+3+Object.Flags], byte 0xC0

	mov	eax, [ebx+Object.Offset]
	mov	[IData+Object.Offset], eax
	mov	ecx, [ebx+Object.PSize]
@@
	mov	ebx, [ObjPtr2]
	test	ebx, ebx
	jz	@F
	mov	[ebx+3+Object.Flags], byte 0xC0

	add	[ebx+Object.Offset], ecx
	mov	eax, [ebx+Object.Offset]
	mov	[RData+Object.Offset], eax
@@
	push	dword __Dest
	push	dword [PEInfos+PEStruc.FileSize]
	push	dword [hBuffer]
	call	SaveBufferToDisk
	test	eax, eax
	jnz	@F

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Failed to save main image to disk"
	debug_end

	jmp	.Free3

@@
	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Saved main image to disk"
	debug_end

	cmp	byte [rOptions+RebuildOptions.ImportMode], 3
	jl	.SaveRsrc

	cmp	dword [IData+Object.Offset], byte 0
	jz	.SaveRsrc

	push	dword __Dest
	push	dword [IData+Object.Offset]
	push	dword [IData+Object.PSize]
	push	dword [IBuffer]
	call	AppendBufferToDisk
	test	eax, eax
	jnz	.SaveRsrc

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Failed to save import object"
	debug_end

	jmp	.Free3
.SaveRsrc:
	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Saved import object"
	debug_end

	cmp	[rOptions+RebuildOptions.RestoreRsrc], byte 0
	jz	near .ExitNow

	cmp	[RData+Object.Offset], dword 0
	jz	.ExitNow

	push	dword __Dest
	push	dword [RData+Object.Offset]
	push	dword [RData+Object.PSize]
	push	dword [RBuffer]
	call	AppendBufferToDisk
	test	eax, eax
	jnz	.SetStatus

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Failed to save import object"
	debug_end

	jmp	short .Free3
.SetStatus:
	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Saved rsrc object"
	debug_end

	cmp	dword [RBuffer], byte 0
	jz	.ExitNow

	push	dword [RBuffer]
	Call	FreeMem

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : rsrc buffer deallocated"
	debug_end
.ExitNow:

.protect_end:

	jmp	short .Free3

.EH:
	mov	esp,[.ESP]

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Exception Handler Invoked !"
	debug_end

.Free3:
	cmp	dword [IBuffer], byte 0
	jz	.Free2

	push	dword [IBuffer]
	call	FreeMem

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Import buffer deallocated"
	debug_end

.Free2:
	cmp	dword [DBuffer],byte 0
	jz	.Free1

	push	dword [DBuffer]
	call	FreeMem

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : DLL list deallocated"
	debug_end

.Free1:
	cmp	dword [hBuffer].byte 0
	jz	.free_eh4

	push	dword [hBuffer]
	call	FreeMem

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : PE buffer deallocated"
	debug_end

.free_eh4:
	mov	esi,EH_Pedump4
	VMMCall	Remove_Exception_Handler

.free_eh3:
	mov	esi,EH_Pedump3
	VMMCall	Remove_Exception_Handler

.free_eh2:
	mov	esi,EH_Pedump2
	VMMCall	Remove_Exception_Handler

.free_eh1:
	mov	esi,EH_Pedump1
	VMMCall	Remove_Exception_Handler

	debug_start debugflags, ICEDUMP_DEBUG_PEDUMP
	Trace_Out "ICEDUMP: Phoenix : Exception Handlers uninstalled"
	debug_end

.ret:
	popfd
	popad
	retn				; client will return to an INT3


.CleanHydra:
	cmp	dword [hPlugin],byte 0
	jz	@F

	push	dword [hPlugin]
	call	FreePlugin

	xor	eax,eax
	and	[hPlugin],eax

	push	eax
	push	eax
	call	SetUnwrapThunk
	call	SetProcessIAT

@@
	retn


segment _LDATA
	align 4
.ESP:		dd 0
FileNameBuffer: times 256 DB 0
__Dest:		times 256 DB 0
plugin:		times 256 db 0

RBuffer		dd	0
IBuffer		dd	0
DBuffer		dd	0		; DLL List Holder
PEBuffer	dd	0		; Target Base
hBuffer		dd	0
FinalEIP	dd	0
ObjPtr1		dd	0
ObjPtr2		dd	0
hPlugin:	dd	0
ProcessIAT:	db	'ProcessIAT',0
UnWrapThunk:	db	'UnwrapThunk',0

	align 4
EH_Pedump1:	ISTRUC Exception_Handler_Struc
	at EHS_Reserved,	dd 0
	at EHS_Start_EIP,	dd __PEIMPCODESTART__
	at EHS_End_EIP,		dd __PEIMPCODEEND__
	at EHS_Handler,		dd Service_Pedump.EH
	IEND

EH_Pedump2:	ISTRUC Exception_Handler_Struc
	at EHS_Reserved,	dd 0
	at EHS_Start_EIP,	dd __PEIOCODESTART__
	at EHS_End_EIP,		dd __PEIOCODEEND__
	at EHS_Handler,		dd Service_Pedump.EH
	IEND

EH_Pedump3:	ISTRUC Exception_Handler_Struc
	at EHS_Reserved,	dd 0
	at EHS_Start_EIP,	dd __PEUTILCODESTART__
	at EHS_End_EIP,		dd __PEUTILCODEEND__
	at EHS_Handler,		dd Service_Pedump.EH
	IEND

EH_Pedump4:	ISTRUC Exception_Handler_Struc
	at EHS_Reserved,	dd 0
	at EHS_Start_EIP,	dd Service_Pedump.protect_start
	at EHS_End_EIP,		dd Service_Pedump.protect_end
	at EHS_Handler,		dd Service_Pedump.EH
	IEND

IData:	ISTRUC	Object
	at Object.Name, db '.idata',0
	At Object.Flags, dd 0C0000040h
	IEND
RData:  ISTRUC	Object
	at Object.Name, db '.rsrc',0
	At Object.Flags, dd 0C0000020h
	IEND

rOptions:	ISTRUC RebuildOptions
	at RebuildOptions.BuildSection,	db 0
	at RebuildOptions.ShrinkPE,	db 1
	at RebuildOptions.MergeSection,	db 0
	at RebuildOptions.RawMode,	db 0
	at RebuildOptions.ReloadHeader,	db 0
	at RebuildOptions.RestoreReloc,	db 0
	at RebuildOptions.RestoreRsrc,	db 0
	at RebuildOptions.ImportMode,	db 3
	at RebuildOptions.UpdatePSize,	db 1
	at RebuildOptions.UpdateVSize,	db 1
	at RebuildOptions.CaveImport,	db 0
	at RebuildOptions.DllFromDisk,	db 0
	at RebuildOptions.ComputeImage,	db 0
	at RebuildOptions.OldScanner,	db 1
	at RebuildOptions.CodeMode,	db 1
	at RebuildOptions.ReduceHeader,	db 0
	at RebuildOptions.ImportPlugin,	TIMES 256 db 0
	IEND

PEInfos:	ISTRUC PEStruc
	IEND

CSBanner:	DB 0dh,0ah
	DB 'ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ',0Dh,0Ah
	DB ' $Id: Dumped with IceDump v'
	DB ICEDUMP_VERSION_ASCII
	DB ' (C) IceDump Team & Phoenix v2.17 (C) G-RoM',0Dh,0Ah
	DB 'ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ'
CSBannerLen	EQU	$-CSBanner
