Skip to content

Commit

Permalink
Add 32-bit/64-bit RISC-V LE NOP sled modules
Browse files Browse the repository at this point in the history
  • Loading branch information
bcoles committed Sep 30, 2024
1 parent 4d1658d commit 09c698c
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 0 deletions.
77 changes: 77 additions & 0 deletions modules/nops/riscv32le/simple.rb
Original file line number Diff line number Diff line change
@@ -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
88 changes: 88 additions & 0 deletions modules/nops/riscv64le/simple.rb
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 09c698c

Please sign in to comment.