%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 "peutil.inc"
%include "taskmod.inc"
%include "apicall.inc"
%include "dumpctx.inc"
%include "win32n.inc"


global Parse_FDump
global Service_FDump


extern 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
;-------------------------------------------------------------------------------
; FDUMP <entry RVA> <FileName>
;-------------------------------------------------------------------------------
Parse_FDump:
	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

	call	ParseExpression
	jb	near Parser.error

	mov	[NewEIP], eax

	call	[pSkipWhiteSpace]
	jz	near Parser.error

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

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

	call	SetCB

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

	popad
	retn


;-------------------------------------------------------------------------------
;
;-------------------------------------------------------------------------------
Service_FDump:
	Trace_Out "ICEDUMP: Ymir engine v1.00 (C) G-RoM 2001"
	Trace_Out ""

	push	byte 0
	call	GetModuleHandle
	mov	[hPE], eax

	push	dword PEInfos
	push	eax
	call	GetPEInfos
	test	eax, eax
	jnz	@F

	debug_start debugflags, ICEDUMP_DEBUG_FDUMP
	mov	eax,[hPE]
	Trace_Out "ICEDUMP: Ymir : No PE header at #eax"
	debug_end

	jmp	.ret

@@
	debug_start debugflags, ICEDUMP_DEBUG_FDUMP
	Trace_Out "ICEDUMP: Ymir : PEInfos Collected [1]"
	debug_end

	mov	ecx, [PEInfos+PEStruc.ImageSize]
	mov	[PEInfos+PEStruc.FileSize], ecx

	push	ecx
	call	GetMem
	test	eax, eax
	jnz	@F

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

	jmp	.ret

@@
	mov	[hBuffer], eax

	debug_start debugflags, ICEDUMP_DEBUG_FDUMP
	Trace_Out "ICEDUMP: Ymir : PE Buffer allocated"
	debug_end

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

	debug_start debugflags, ICEDUMP_DEBUG_FDUMP
	Trace_Out "ICEDUMP: Ymir : PE Image replicated"
	debug_end

	push	dword PEInfos
	push	dword [hBuffer]
	call	UpdateSections

	push	byte 0
	push	dword IData
	push	dword PEInfos
	push	dword [hBuffer]
	call	AddSection

	mov	eax, [IData+Object.VSize]
	mov	[PEInfos+PEStruc.ImportSize], eax
	mov	eax, [IData+Object.RVA]
	mov	[PEInfos+PEStruc.ImportRVA], eax

	push	eax
	push	dword IBuffer
	call	DumpContext
	mov	[IData+Object.VSize], eax

	push	dword [PEInfos+PEStruc.FAlign]
	push	eax
	call	AlignOffset
	mov	[IData+Object.PSize], eax

	mov	eax, [NewEIP]
	mov	[PEInfos+PEStruc.EIP], eax

	push	dword PEInfos
	push	dword [hBuffer]
	call	SetPEInfos

	debug_start debugflags, ICEDUMP_DEBUG_FDUMP
	Trace_Out "ICEDUMP: Ymir : 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_FDUMP
	Trace_Out "ICEDUMP: Ymir : Failed to optimize PE Image"
	debug_end

	jmp	.removeimp

@@
	debug_start debugflags, ICEDUMP_DEBUG_FDUMP
	Trace_Out "ICEDUMP: Ymir : PE Image Optimized"
	debug_end

	push	byte 1
	push	dword IData
	push	dword PEInfos
	push	dword [hBuffer]
	call	AddSection

	push	dword __EXE__
	push	dword [PEInfos+PEStruc.FileSize]
	push	dword [hBuffer]
	call	SaveBufferToDisk
	test	eax, eax
	jnz	@F

	debug_start debugflags, ICEDUMP_DEBUG_FDUMP
	Trace_Out "ICEDUMP: Ymir : Failed to save main image to disk"
	debug_end

	jmp	.removeimp

@@
	debug_start debugflags, ICEDUMP_DEBUG_FDUMP
	Trace_Out "ICEDUMP: Ymir : Saved main image to disk"
	debug_end

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

	debug_start debugflags, ICEDUMP_DEBUG_FDUMP
	Trace_Out "ICEDUMP: Ymir : Failed to save import object"
	debug_end

	jmp	short .removeimp

.ExitNow:
	debug_start debugflags, ICEDUMP_DEBUG_FDUMP
	Trace_Out "ICEDUMP: Ymir : Saved import object"
	debug_end

.removeimp:
	push	dword [IBuffer]
	call	FreeMem

.removebuf:
	push	dword [hBuffer]
	call	FreeMem

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


segment _LDATA
	align 4
hPE	dd	0
hBuffer	dd	0
IBuffer	dd	0
NewEIP	dd	0
__EXE__	times 256 db 0

IData:	ISTRUC	Object
	at Object.Name, db '.idata',0
	At Object.Flags, dd 0C0000040h
	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 & Ymir v1.00 (C) G-RoM',0Dh,0Ah
	DB 'ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ'
CSBannerLen	EQU	$-CSBanner
