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'
|
2010-03-03 04:58:12 +00:00
|
|
|
|
2005-12-08 15:37:10 +00:00
|
|
|
#
|
|
|
|
# Ensures that the nasm environment is sane.
|
|
|
|
#
|
|
|
|
def self.check
|
2010-03-03 04:58:12 +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.")
|
2010-03-03 04:58:12 +00:00
|
|
|
|
|
|
|
@@ndisasm_path =
|
2007-03-24 18:15:45 +00:00
|
|
|
Rex::FileUtils.find_full_path('ndisasm') ||
|
|
|
|
Rex::FileUtils.find_full_path('ndisasm.exe') ||
|
|
|
|
Rex::FileUtils.find_full_path('ndisasmw.exe') ||
|
2010-03-03 04:58:12 +00:00
|
|
|
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:31:44 +00:00
|
|
|
tmp = Tempfile.new('nasmXXXX')
|
2010-10-12 01:48:42 +00:00
|
|
|
tmp.binmode
|
|
|
|
|
2007-03-24 18:31:44 +00:00
|
|
|
tpath = tmp.path
|
|
|
|
opath = tmp.path + '.out'
|
2005-12-08 15:37:10 +00:00
|
|
|
|
|
|
|
# Write the assembly data to a file
|
2007-03-24 18:31:44 +00:00
|
|
|
tmp.write("BITS 32\n" + assembly)
|
|
|
|
tmp.flush()
|
|
|
|
tmp.seek(0)
|
2005-12-08 15:37:10 +00:00
|
|
|
|
|
|
|
# Run nasm
|
2007-03-24 18:31:44 +00:00
|
|
|
if (system(@@nasm_path, '-f', 'bin', '-o', opath, tpath) == false)
|
2005-12-08 15:37:10 +00:00
|
|
|
raise RuntimeError, "Assembler did not complete successfully: #{$?.exitstatus}"
|
|
|
|
end
|
|
|
|
|
|
|
|
# Read the assembled text
|
2007-03-24 18:31:44 +00:00
|
|
|
rv = ::IO.read(opath)
|
2005-12-08 15:37:10 +00:00
|
|
|
|
|
|
|
# Remove temporary files
|
2007-03-24 18:31:44 +00:00
|
|
|
File.unlink(opath)
|
2010-03-03 04:58:12 +00:00
|
|
|
tmp.close(true)
|
2005-12-08 15:37:10 +00:00
|
|
|
|
|
|
|
rv
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Disassembles the supplied raw opcodes
|
|
|
|
#
|
|
|
|
def self.disassemble(raw)
|
|
|
|
check
|
2010-03-03 04:58:12 +00:00
|
|
|
|
2007-03-24 18:31:44 +00:00
|
|
|
tmp = Tempfile.new('nasmout')
|
2010-10-12 01:48:42 +00:00
|
|
|
tmp.binmode
|
|
|
|
|
2007-03-24 18:35:34 +00:00
|
|
|
tfd = File.open(tmp.path, "wb")
|
2010-03-03 04:58:12 +00:00
|
|
|
|
2007-03-24 18:35:34 +00:00
|
|
|
tfd.write(raw)
|
|
|
|
tfd.flush()
|
|
|
|
tfd.close
|
2005-12-08 15:37:10 +00:00
|
|
|
|
2007-03-24 18:35:34 +00:00
|
|
|
p = ::IO.popen("\"#{@@ndisasm_path}\" -u \"#{tmp.path}\"")
|
2005-12-08 15:37:10 +00:00
|
|
|
o = ''
|
|
|
|
|
|
|
|
begin
|
|
|
|
until p.eof?
|
|
|
|
o += p.read
|
|
|
|
end
|
|
|
|
ensure
|
|
|
|
p.close
|
|
|
|
end
|
|
|
|
|
2010-03-03 04:58:12 +00:00
|
|
|
tmp.close(true)
|
2005-12-08 15:37:10 +00:00
|
|
|
|
|
|
|
o
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
2010-03-03 04:58:12 +00:00
|
|
|
end
|