CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/encoders/x86/add_sub.rb
Views: 1904
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Encoder
7
Rank = ManualRanking
8
9
def initialize
10
super(
11
'Name' => 'Add/Sub Encoder',
12
'Description' => %q{
13
Encodes payload with add or sub instructions. This idea came
14
from (offensive-security) muts' hp nnm 7.5.1 exploit.
15
},
16
'Author' => 'Melih Sarica <ms[at]sevure.com>',
17
'Arch' => ARCH_X86,
18
'License' => MSF_LICENSE,
19
'Decoder' =>
20
{
21
'BlockSize' => 4
22
})
23
end
24
25
def add_or_sub(avchars)
26
add = [0x05, 0x50, 0x58, 0x25, 0x54, 0x5C]
27
sub = [0x2D, 0x50, 0x58, 0x25, 0x54, 0x5C]
28
return 1 if add.all?{|ch|avchars.include?ch.chr}
29
return 2 if sub.all?{|ch|avchars.include?ch.chr}
30
return 0
31
end
32
33
def write_inst(inst, mcode)
34
@data << inst
35
if mcode != 0
36
for i in 0...4
37
t = mcode & 0x000000FF;
38
@data << t
39
mcode = mcode >> 8;
40
end
41
end
42
end
43
44
def rand_with_av_chars()
45
t2 = 0
46
for i in 0...4
47
c = @avchars[rand(@avchars.size)].ord.to_i()
48
t2 = t2 <<8
49
t2 += c
50
end
51
return t2
52
end
53
54
def check_non_av_chars(target)
55
for i in 0...4
56
t = target & 0x000000FF;
57
return true if not @avchars.include?t.chr
58
target = target >> 8;
59
end
60
return false
61
end
62
63
def encode_inst(target)
64
begin
65
a = rand_with_av_chars()
66
b = rand_with_av_chars()
67
c = target - a - b if @set == 1
68
c = 0 - target - a - b if @set == 2
69
c = c%(0xFFFFFFFF+1)
70
end while check_non_av_chars(c) == true
71
write_inst(@inst["opcode"], a)
72
write_inst(@inst["opcode"], b)
73
write_inst(@inst["opcode"], c)
74
end
75
76
def encode_shellcode(target, z1, z2)
77
write_inst(@inst["and"], z1);
78
write_inst(@inst["and"], z2);
79
encode_inst(target);
80
write_inst(@inst["push"], 0);
81
end
82
83
def decoder_stub(state)
84
buf = ""
85
shellcode = state.buf.split(//)
86
while shellcode.size>0
87
buf << shellcode.pop(4).join
88
end
89
state.buf = buf
90
@data = ""
91
@avchars = ""
92
for i in 0..255
93
@avchars = @avchars + i.chr.to_s if not state.badchars.include?i.chr.to_s
94
end
95
offset = (datastore['BufferOffset'] || 0).to_i
96
@inst = {}
97
@set = add_or_sub(@avchars)
98
if @set == 0 then
99
raise EncodingError, "Bad character list includes essential characters."
100
exit
101
elsif @set == 1 then #add
102
@inst["opcode"] = 0x05
103
else #sub
104
@inst["opcode"] = 0x2d
105
end
106
@inst["push"] = 0x50
107
@inst["pop"] = 0x58
108
@inst["and"] = 0x25
109
@inst["push_esp"] = 0x54
110
@inst["pop_esp"] = 0x5c
111
if state.buf.size%4 != 0 then
112
raise EncodingError, "Shellcode size must be divisible by 4, try nop padding."
113
exit
114
end
115
#init
116
write_inst(@inst["push_esp"], 0)
117
write_inst(@inst["pop"], 0)
118
encode_inst(offset)
119
write_inst(@inst["push"], 0)
120
write_inst(@inst["pop_esp"], 0)
121
#zeroing registers
122
begin
123
@z1 = rand_with_av_chars()
124
@z2 = rand_with_av_chars()
125
end while @z1&@z2 != 0
126
decoder = @data
127
return decoder
128
end
129
130
def encode_block(state, block)
131
#encoding shellcode
132
@data = ""
133
target = block.split(//)
134
return if target.size<4
135
t = 0
136
for i in 0..3
137
t1 = target[3-i][0].ord.to_i
138
t = t<<8
139
t = t + t1
140
end
141
encode_shellcode(t, @z1, @z2);
142
encoded = @data
143
return encoded
144
end
145
end
146
147
148