/*

The Shellcoder's Handbook. Edycja polska
Jack Koziol, David Litchfield, Dave Aitel, Chris Anley, 
Sinan Eren, Neel Mehta, Riley Hassell
Wydawnictwo Helion


Rozdzia 20
Alternatywne strategie eksploitw
rsc.c

Komentarze i uwagi prosz przesya na adres jack@infosecinstitute.com 
lub za porednictwem witryny http://www.infosecinstitute.com 

*/

// rsc.c
// Prosty mechanizm zdalnych wywoa dla systemu Windows

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

int Marshall( unsigned char flags, unsigned size, unsigned char *data, unsigned char *out, unsigned out_len )
{
     out[0] = flags;
     *((unsigned *)(&(out[1]))) = size;
     memcpy( &(out[5]), data, size );

     return size + 5;
}

////////////////////////////
// Znaczniki parametrw ////
////////////////////////////

// wskanik, a nie warto
#define IS_PTR     0x01

// parametr moe by in, out lub in | out
#define IS_IN     0x02 
#define IS_OUT     0x04

// dane zakoczone bajtem zerowym
#define IS_SZ     0x08

// dane zakoczone bajtem zerowym (acuch unicode)
#define IS_SZZ     0x10


////////////////////////////
// Znaczniki funkcji ///////
////////////////////////////

// function is __cdecl (default is __stdcall)
#define FN_CDECL     0x01


int AsmDemarshallAndCall( unsigned char *buff, void *loadlib, void *getproc )
{
     // params:
     // ebp: dllname
     // +4     : fnname
     // +8     : num_params
     // +12     : out_param_size
     // +16     : function_flags
     // +20     : params_so_far
     // +24     : loadlibrary
     // +28     : getprocaddress
     // +32     : address of out data buffer

     _asm
     {
     // przygotowuje parametry - kod ten jest nieco skomplikowany
     // ze wzgldu na wywoanie funkcji z poziomu asemblera wbudowanego w C

          push ebp
          sub esp, 0x100
          mov ebp, esp
          mov ebx, dword ptr[ebp+0x158]; // buff
          mov dword ptr [ebp + 12], 0;
          mov eax, dword ptr [ebp+0x15c];//loadlib
          mov dword ptr[ebp + 24], eax;
          mov eax, dword ptr [ebp+0x160];//getproc
          mov dword ptr[ebp + 28], eax;

          mov dword ptr [ebp], ebx; // ebx = dllname

          sub esp, 0x800;          // rezerwuje obszar dla danych
          mov dword ptr[ebp + 32], esp;

          jmp start;

          // zwiksza ebx do momentu, gdy wskae bajt '0'
skip_string:
          mov al, byte ptr [ebx];
          cmp al, 0;
          jz done_string;
          inc ebx;
          jmp skip_string;

done_string:
          inc ebx;
          ret;

start:
          // przeskakuje nazw biblioteki dll
          call skip_string;

          // aduje nazw funkcji
          mov dword ptr[ ebp + 4 ], ebx

          // przeskakuje nazw funkcji
          call skip_string;
               
          // aduje licznik parametrw
          mov ecx, dword ptr [ebx]
          mov edx, ecx
          mov dword ptr[ ebp + 8 ], ecx

          // aduje rozmiar parametru
          add ebx,4
          mov ecx, dword ptr [ebx]
          mov dword ptr[ ebp + 12 ], ecx

          // aduje znaczniki funkcji
          add ebx,4
          mov ecx, dword ptr [ebx]
          mov dword ptr[ ebp + 16 ], ecx

          add ebx,4

// w tej ptli, edx zawiera licznik pozostaych parametrw.

next_param:
          cmp edx, 0
          je call_proc
          
          mov cl, byte ptr[ ebx ];     // cl = znaczniki
          inc ebx;

          mov eax, dword ptr[ ebx ];     // eax = rozmiar
          add ebx, 4;

          mov ch,cl;
          and cl, 1;                         // wskanik?
          jz not_ptr;

          mov cl,ch;

// wskanik 'in' czy 'inout' ?
          and cl, 2;                         
          jnz is_in;
          
                                   // wskanik 'out'
                                   // pobiera wskanik danych
          mov ecx, dword ptr [ ebp + 32 ]
          push ecx

// wskanik danych wskazywa bdzie teraz koniec bufora
          add dword ptr [ ebp + 32 ], eax          
          add ebx, eax
          dec edx
          jmp next_param

is_in:
          push ebx                         

// parametr 'in' lub 'inout'
// co oznacza, e dane znajduj si w odebranym pakiecie
          add ebx, eax
          dec edx
          jmp next_param


not_ptr:
          mov eax, dword ptr[ ebx ];
          push eax;
          add ebx, 4
          dec edx
          jmp next_param;

call_proc:
          // parametry przygotowane, wywoujemy funkcj...
          mov eax, dword ptr[ ebp ];
          push eax;
          mov eax, dword ptr[ ebp + 24 ];
          call eax;
          mov ebx, eax;
          mov eax, dword ptr[ ebp + 4 ];
          push eax;
          push ebx;
          mov eax, dword ptr[ ebp + 28 ];
          call eax; // wywoania funkcji getprocaddress
          call eax; // wywoanie naszej funkcji

          // pora posprzta
          add esp, 0x800;
          add esp, 0x100;
          pop ebp
     }

     return 1;
}



int main( int argc, char *argv[] )
{
     unsigned char buff[ 256 ];
     unsigned char *psz;
     DWORD freq = 1234;
     DWORD dur = 1234;
     DWORD show = 0;
     HANDLE hk32;
     void *loadlib, *getproc;
     char *cmd = "cmd /c dir > c:\\foo.txt";

     psz = buff;

     strcpy( psz, "kernel32.dll" );
     psz += strlen( psz ) + 1;

     strcpy( psz, "WinExec" );
     psz += strlen( psz ) + 1;

     *((unsigned *)(psz)) = 2;          // licznik parametrw
     psz += 4;

     *((unsigned *)(psz)) = strlen( cmd ) + 1;     // rozmiar parametru
     psz += 4;

     // ustawia fn_flags
     *((unsigned *)(psz)) = 0;
     psz += 4;

     psz += Marshall( IS_IN, sizeof( DWORD ), (unsigned char *)&show, psz, sizeof( buff ) );
     psz += Marshall( IS_PTR | IS_IN, strlen( cmd ) + 1, (unsigned char *)cmd, psz, sizeof( buff ) );

     hk32 = LoadLibrary( "kernel32.dll" );
     loadlib = GetProcAddress( hk32, "LoadLibraryA" );
     getproc = GetProcAddress( hk32, "GetProcAddress" );

     AsmDemarshallAndCall( buff, loadlib, getproc );

     return 0;
}
