diff --git a/modules/nops/riscv32le/simple.rb b/modules/nops/riscv32le/simple.rb new file mode 100644 index 0000000000000..075ef75d19dc1 --- /dev/null +++ b/modules/nops/riscv32le/simple.rb @@ -0,0 +1,77 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +# This class implements a simple NOP generator for RISC-V 32-bit (Little Endian) +class MetasploitModule < Msf::Nop + + def initialize + super( + 'Name' => 'Simple', + 'Alias' => 'riscv32le_simple', + 'Description' => 'Simple NOP generator', + 'License' => MSF_LICENSE, + 'Author' => ['bcoles'], + 'Arch' => ARCH_RISCV32LE) + register_advanced_options([ + OptBool.new('RandomNops', [false, 'Generate a random NOP sled', true]) + ]) + end + + def generate_sled(length, opts) + badchars = opts['BadChars'] || '' + random = opts['Random'] || datastore['RandomNops'] + nops = [ + 0x00028293, # addi t0, t0, 0 + 0x00030313, # addi t1, t1, 0 + 0x00038393, # addi t2, t2, 0 + 0x000e0e13, # addi t3, t3, 0 + 0x000e8e93, # addi t4, t4, 0 + 0x000f0f13, # addi t5, t5, 0 + 0x000f8f93, # addi t6, t6, 0 + ] + + # addi x0, x0, 0 + # addi x0, x0, 1 + # addi x0, x0, 2 + # addi x0, x0, ... + # addi x0, x0, 0x799 + instruction = 0x00000013 + while instruction <= 0x79900013 + instruction += 0x100000 + nops << instruction + end + + # Remove nops containing BadChars + good_nops = [] + nops.each do |nop| + good_byte = true + [nop].pack('V*').each_byte do |nop_byte| + badchars.each_byte do |bad_byte| + if nop_byte == bad_byte + good_byte = false + break + end + end + break unless good_byte + end + good_nops << nop if good_byte + end + + # Give up if no safe nops are available + return if good_nops.empty? + + # Use random instructions for all NOPs + if random + sled = '' + (length / 4).times do + sled << [good_nops.sample].pack('V*') + end + return sled + end + + # Use a single instruction for all NOPs + return ([good_nops.sample].pack('V*') * (length / 4)) + end +end diff --git a/modules/nops/riscv64le/simple.rb b/modules/nops/riscv64le/simple.rb new file mode 100644 index 0000000000000..c3d922304a179 --- /dev/null +++ b/modules/nops/riscv64le/simple.rb @@ -0,0 +1,88 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +# This class implements a simple NOP generator for RISC-V 64-bit (Little Endian) +class MetasploitModule < Msf::Nop + + def initialize + super( + 'Name' => 'Simple', + 'Alias' => 'riscv64le_simple', + 'Description' => 'Simple NOP generator', + 'License' => MSF_LICENSE, + 'Author' => ['bcoles'], + 'Arch' => ARCH_RISCV64LE) + register_advanced_options([ + OptBool.new('RandomNops', [false, 'Generate a random NOP sled', true]) + ]) + end + + def generate_sled(length, opts) + badchars = opts['BadChars'] || '' + random = opts['Random'] || datastore['RandomNops'] + nops = [ + 0x40000033, # subi x0, x0, 0 + 0x02000033, # mul x0, x0, 0 + 0x02004033, # div x0, x0, 0 + 0x00028293, # addi t0, t0, 0 + 0x00030313, # addi t1, t1, 0 + 0x00038393, # addi t2, t2, 0 + 0x000e0e13, # addi t3, t3, 0 + 0x000e8e93, # addi t4, t4, 0 + 0x000f0f13, # addi t5, t5, 0 + 0x000f8f93, # addi t6, t6, 0 + 0x400282b3, # subi t0, t0, 0 + 0x40030333, # subi t1, t1, 0 + 0x400383b3, # subi t2, t2, 0 + 0x400e0e33, # subi t3, t3, 0 + 0x400e8eb3, # subi t4, t4, 0 + 0x400f0f33, # subi t5, t5, 0 + 0x400f8fb3, # subi t6, t6, 0 + ] + + # Add harmless zero register addition instructions as NOPs + # addi x0, x0, 0 + # addi x0, x0, 1 + # addi x0, x0, 2 + # addi x0, x0, ... + # addi x0, x0, 0x799 + instruction = 0x00000013 + while instruction <= 0x79900013 + instruction += 0x100000 + nops << instruction + end + + # Remove nops containing BadChars + good_nops = [] + nops.each do |nop| + good_byte = true + [nop].pack('V*').each_byte do |nop_byte| + badchars.each_byte do |bad_byte| + if nop_byte == bad_byte + good_byte = false + break + end + end + break unless good_byte + end + good_nops << nop if good_byte + end + + # Give up if no safe nops are available + return if good_nops.empty? + + # Use random instructions for all NOPs + if random + sled = '' + (length / 4).times do + sled << [good_nops.sample].pack('V*') + end + return sled + end + + # Use a single instruction for all NOPs + return ([good_nops.sample].pack('V*') * (length / 4)) + end +end