Path: blob/master/modules/encoders/x86/context_cpuid.rb
19612 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 cpuid value is generated and supplied10# manually...1112Rank = ManualRanking1314def initialize15super(16'Name' => 'CPUID-based Context Keyed Payload Encoder',17'Description' => %q{18This is a Context-Keyed Payload Encoder based on CPUID and Shikata Ga Nai.19},20'Author' => 'Dimitris Glynos',21'Arch' => ARCH_X86,22'License' => MSF_LICENSE,23'Decoder' => {24'KeySize' => 4,25'BlockSize' => 426})2728register_options(29[30OptString.new('CPUID_KEY',31[32true,33'CPUID key from target host (see tools/context/cpuid-key utility)',34'0x00000000'35]),36]37)38end3940def obtain_key(_buf, _badchars, state)41state.key = datastore['CPUID_KEY'].hex42return state.key43end4445#46# Generates the shikata decoder stub.47#48def decoder_stub(state)49# If the decoder stub has not already been generated for this state, do50# it now. The decoder stub method may be called more than once.51if state.decoder_stub.nil?52# Shikata will only cut off the last 1-4 bytes of it's own end53# depending on the alignment of the original buffer54cutoff = 4 - (state.buf.length & 3)55block = keygen_stub + generate_shikata_block(state, state.buf.length + cutoff, cutoff) || (raise BadGenerateError)5657# Take the last 1-4 bytes of shikata and prepend them to the buffer58# that is going to be encoded to make it align on a 4-byte boundary.59state.buf = block.slice!(block.length - cutoff, cutoff) + state.buf6061# Cache this decoder stub. The reason we cache the decoder stub is62# because we need to ensure that the same stub is returned every time63# for a given encoder state.64state.decoder_stub = block65end6667state.decoder_stub68end6970protected7172def keygen_stub73"\x31\xf6" + # xor %esi,%esi74"\x31\xff" + # xor %edi,%edi75"\x89\xf8" + # cpuid_loop: mov %edi,%eax76"\x31\xc9" + # xor %ecx,%ecx77"\x0f\xa2" + # cpuid78"\x31\xc6" + # xor %eax,%esi79"\x39\xf0" + # cmp %esi,%eax80"\x75\x03" + # jne not_first_time81"\x8d\x78\x01" + # lea 0x1(%eax,1),%edi82"\x31\xde" + # not_first_time: xor %ebx,%esi83"\x31\xce" + # xor %ecx,%esi84"\x31\xd6" + # xor %edx,%esi85"\x83\xef\x01" + # sub $0x1,%edi86"\x75\xe6" + # jne cpuid_loop87"\x89\xf0" # mov %esi,%eax88end8990#91# Returns the set of FPU instructions that can be used for the FPU block of92# the decoder stub.93#94def fpu_instructions95fpus = []96970xe8.upto(0xee) { |x| fpus << "\xd9" + x.chr }980xc0.upto(0xcf) { |x| fpus << "\xd9" + x.chr }990xc0.upto(0xdf) { |x| fpus << "\xda" + x.chr }1000xc0.upto(0xdf) { |x| fpus << "\xdb" + x.chr }1010xc0.upto(0xc7) { |x| fpus << "\xdd" + x.chr }102103fpus << "\xd9\xd0"104fpus << "\xd9\xe1"105fpus << "\xd9\xf6"106fpus << "\xd9\xf7"107fpus << "\xd9\xe5"108109# This FPU instruction seems to fail consistently on Linux110# fpus << "\xdb\xe1"111112fpus113end114115#116# Returns a polymorphic decoder stub that is capable of decoding a buffer117# of the supplied length and encodes the last cutoff bytes of itself.118#119def generate_shikata_block(state, length, cutoff)120# Declare logical registers121key_reg = Rex::Poly::LogicalRegister::X86.new('key', 'eax')122addr_reg = Rex::Poly::LogicalRegister::X86.new('addr')123124# Declare individual blocks125endb = Rex::Poly::SymbolicBlock::End.new126127# FPU blocks128fpu = Rex::Poly::LogicalBlock.new(129'fpu',130*fpu_instructions131)132fnstenv = Rex::Poly::LogicalBlock.new('fnstenv', "\xd9\x74\x24\xf4")133134# Get EIP off the stack135popeip = Rex::Poly::LogicalBlock.new(136'popeip',137proc { |b| (0x58 + b.regnum_of(addr_reg)).chr }138)139140# Clear the counter register141clear_register = Rex::Poly::LogicalBlock.new(142'clear_register',143"\x31\xc9",144"\x29\xc9",145"\x33\xc9",146"\x2b\xc9"147)148149# Initialize the counter after zeroing it150init_counter = Rex::Poly::LogicalBlock.new('init_counter')151152# Divide the length by four but ensure that it aligns on a block size153# boundary (4 byte).154length += 4 + (4 - (length & 3)) & 3155length /= 4156157if (length <= 255)158init_counter.add_perm("\xb1" + [ length ].pack('C'))159else160init_counter.add_perm("\x66\xb9" + [ length ].pack('v'))161end162163# Key initialization block164165# Decoder loop block166loop_block = Rex::Poly::LogicalBlock.new('loop_block')167168xor = proc { |b| "\x31" + (0x40 + b.regnum_of(addr_reg) + (8 * b.regnum_of(key_reg))).chr }169xor1 = proc { |b| xor.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - cutoff) ].pack('c') }170xor2 = proc { |b| xor.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - 4 - cutoff) ].pack('c') }171add = proc { |b| "\x03" + (0x40 + b.regnum_of(addr_reg) + (8 * b.regnum_of(key_reg))).chr }172add1 = proc { |b| add.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - cutoff) ].pack('c') }173add2 = proc { |b| add.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - 4 - cutoff) ].pack('c') }174sub4 = proc { |b| "\x83" + (0xe8 + b.regnum_of(addr_reg)).chr + "\xfc" }175add4 = proc { |b| "\x83" + (0xc0 + b.regnum_of(addr_reg)).chr + "\x04" }176177loop_block.add_perm(178proc { |b| xor1.call(b) + add1.call(b) + sub4.call(b) },179proc { |b| xor1.call(b) + sub4.call(b) + add2.call(b) },180proc { |b| sub4.call(b) + xor2.call(b) + add2.call(b) },181proc { |b| xor1.call(b) + add1.call(b) + add4.call(b) },182proc { |b| xor1.call(b) + add4.call(b) + add2.call(b) },183proc { |b| add4.call(b) + xor2.call(b) + add2.call(b) }184)185186# Loop instruction block187loop_inst = Rex::Poly::LogicalBlock.new(188'loop_inst',189"\xe2\xf5"190)191192# Define block dependencies193fnstenv.depends_on(fpu)194popeip.depends_on(fnstenv)195init_counter.depends_on(clear_register)196loop_block.depends_on(popeip, init_counter)197loop_inst.depends_on(loop_block)198199# Generate a permutation saving the EAX, ECX and ESP registers200loop_inst.generate([201Rex::Arch::X86::EAX,202Rex::Arch::X86::ESP,203Rex::Arch::X86::ECX204], nil, state.badchars)205end206end207208209