Path: blob/master/modules/encoders/x86/add_sub.rb
19758 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Encoder6Rank = ManualRanking78def initialize9super(10'Name' => 'Add/Sub Encoder',11'Description' => %q{12Encodes payload with add or sub instructions. This idea came13from (offensive-security) muts' hp nnm 7.5.1 exploit.14},15'Author' => 'Melih Sarica <ms[at]sevure.com>',16'Arch' => ARCH_X86,17'License' => MSF_LICENSE,18'Decoder' => {19'BlockSize' => 420})21end2223def add_or_sub(avchars)24add = [0x05, 0x50, 0x58, 0x25, 0x54, 0x5C]25sub = [0x2D, 0x50, 0x58, 0x25, 0x54, 0x5C]26return 1 if add.all? { |ch| avchars.include? ch.chr }27return 2 if sub.all? { |ch| avchars.include? ch.chr }2829return 030end3132def write_inst(inst, mcode)33@data << inst34if mcode != 035for _ in 0...436t = mcode & 0x000000FF37@data << t38mcode >>= 839end40end41end4243def rand_with_av_chars44t2 = 045for _ in 0...446c = @avchars[rand(@avchars.size)].ord.to_i47t2 <<= 848t2 += c49end50return t251end5253def check_non_av_chars(target)54for _ in 0...455t = target & 0x000000FF56return true if !@avchars.include? t.chr5758target >>= 859end60return false61end6263def encode_inst(target)64loop do65a = rand_with_av_chars66b = rand_with_av_chars67c = target - a - b if @set == 168c = 0 - target - a - b if @set == 269c %= (0xFFFFFFFF + 1)70break unless check_non_av_chars(c) == true71end72write_inst(@inst['opcode'], a)73write_inst(@inst['opcode'], b)74write_inst(@inst['opcode'], c)75end7677def encode_shellcode(target, z1, z2)78write_inst(@inst['and'], z1)79write_inst(@inst['and'], z2)80encode_inst(target)81write_inst(@inst['push'], 0)82end8384def decoder_stub(state)85buf = ''86shellcode = state.buf.split(//)87buf << shellcode.pop(4).join until shellcode.empty?88state.buf = buf89@data = ''90@avchars = ''91for i in 0..25592@avchars += i.chr.to_s if !state.badchars.include? i.chr.to_s93end94offset = (datastore['BufferOffset'] || 0).to_i95@inst = {}96@set = add_or_sub(@avchars)97if @set == 098raise EncodingError, 'Bad character list includes essential characters.'99elsif @set == 1 # add100@inst['opcode'] = 0x05101else # sub102@inst['opcode'] = 0x2d103end104105@inst['push'] = 0x50106@inst['pop'] = 0x58107@inst['and'] = 0x25108@inst['push_esp'] = 0x54109@inst['pop_esp'] = 0x5c110if state.buf.size % 4 != 0111raise EncodingError, 'Shellcode size must be divisible by 4, try nop padding.'112end113114# init115write_inst(@inst['push_esp'], 0)116write_inst(@inst['pop'], 0)117encode_inst(offset)118write_inst(@inst['push'], 0)119write_inst(@inst['pop_esp'], 0)120# zeroing registers121loop do122@z1 = rand_with_av_chars123@z2 = rand_with_av_chars124break unless @z1 & @z2 != 0125end126decoder = @data127return decoder128end129130def encode_block(_state, block)131# encoding shellcode132@data = ''133target = block.split(//)134return if target.size < 4135136t = 0137for i in 0..3138t1 = target[3 - i][0].ord.to_i139t <<= 8140t += t1141end142encode_shellcode(t, @z1, @z2)143encoded = @data144return encoded145end146end147148149