2005-12-17 06:46:23 +00:00
|
|
|
#!/usr/bin/env ruby
|
2005-12-08 15:37:10 +00:00
|
|
|
|
|
|
|
require 'tempfile'
|
|
|
|
require 'rex/file'
|
|
|
|
require 'rex/text'
|
|
|
|
|
|
|
|
module Rex
|
|
|
|
module Assembly
|
|
|
|
|
|
|
|
###
|
|
|
|
#
|
|
|
|
# This class uses nasm to assemble and disassemble stuff.
|
|
|
|
#
|
|
|
|
###
|
|
|
|
class Nasm
|
|
|
|
|
2007-03-24 18:15:45 +00:00
|
|
|
@@nasm_path = 'nasm'
|
|
|
|
@@ndisasm_path = 'ndisasm'
|
|
|
|
|
2005-12-08 15:37:10 +00:00
|
|
|
#
|
|
|
|
# Ensures that the nasm environment is sane.
|
|
|
|
#
|
|
|
|
def self.check
|
2007-03-24 18:15:45 +00:00
|
|
|
@@nasm_path =
|
2007-03-24 18:09:14 +00:00
|
|
|
Rex::FileUtils.find_full_path('nasm') ||
|
|
|
|
Rex::FileUtils.find_full_path('nasm.exe') ||
|
|
|
|
Rex::FileUtils.find_full_path('nasmw.exe') ||
|
|
|
|
raise(RuntimeError, "No nasm installation was found.")
|
2007-03-24 18:15:45 +00:00
|
|
|
|
|
|
|
@@ndisasm_path =
|
|
|
|
Rex::FileUtils.find_full_path('ndisasm') ||
|
|
|
|
Rex::FileUtils.find_full_path('ndisasm.exe') ||
|
|
|
|
Rex::FileUtils.find_full_path('ndisasmw.exe') ||
|
|
|
|
raise(RuntimeError, "No ndisasm installation was found.")
|
2005-12-08 15:37:10 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Assembles the supplied assembly and returns the raw opcodes.
|
|
|
|
#
|
|
|
|
def self.assemble(assembly)
|
|
|
|
check
|
|
|
|
|
|
|
|
# Open the temporary file
|
2007-03-24 18:09:14 +00:00
|
|
|
tmp = Tempfile.new('nasmXXXX').path
|
2005-12-08 15:37:10 +00:00
|
|
|
file = File.new(tmp, "w")
|
|
|
|
|
|
|
|
# Write the assembly data to a file
|
|
|
|
begin
|
|
|
|
file.write("BITS 32\n" + assembly)
|
|
|
|
file.close
|
|
|
|
file = nil
|
|
|
|
ensure
|
|
|
|
file.close if (file)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Run nasm
|
2007-03-24 18:15:45 +00:00
|
|
|
if (system(@@nasm_path, '-f', 'bin', '-o', "#{tmp}.out", tmp) == false)
|
2005-12-08 15:37:10 +00:00
|
|
|
raise RuntimeError, "Assembler did not complete successfully: #{$?.exitstatus}"
|
|
|
|
end
|
|
|
|
|
|
|
|
# Read the assembled text
|
2006-12-17 07:00:44 +00:00
|
|
|
rv = ::IO.read(tmp + ".out")
|
2005-12-08 15:37:10 +00:00
|
|
|
|
|
|
|
# Remove temporary files
|
|
|
|
File.unlink(tmp)
|
|
|
|
File.unlink(tmp + ".out")
|
|
|
|
|
|
|
|
rv
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Disassembles the supplied raw opcodes
|
|
|
|
#
|
|
|
|
def self.disassemble(raw)
|
|
|
|
check
|
|
|
|
|
2005-12-30 21:15:32 +00:00
|
|
|
# Race condition?! You bet!
|
2005-12-08 15:37:10 +00:00
|
|
|
tmp = Tempfile.new('nasmout').path
|
2005-12-30 21:15:32 +00:00
|
|
|
File.open(tmp, "wb") { |f| f.write(raw) }
|
2005-12-08 15:37:10 +00:00
|
|
|
|
2007-03-24 18:15:45 +00:00
|
|
|
p = ::IO.popen("'#{@@ndisasm_path}' -u '#{tmp}'")
|
2005-12-08 15:37:10 +00:00
|
|
|
o = ''
|
|
|
|
|
|
|
|
begin
|
|
|
|
until p.eof?
|
|
|
|
o += p.read
|
|
|
|
end
|
|
|
|
ensure
|
|
|
|
p.close
|
|
|
|
end
|
|
|
|
|
|
|
|
File.unlink(tmp)
|
|
|
|
|
|
|
|
o
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|