Skip to content

Commit

Permalink
Merge pull request #518 from ninp0/master
Browse files Browse the repository at this point in the history
PWN::Plugins::Assembly module - overhaul using metasm gem - thank you…
  • Loading branch information
ninp0 committed Feb 25, 2024
2 parents 4539281 + ef33860 commit afd3e2c
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 29 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ gem 'jwt', '2.8.0'
gem 'libusb', '0.6.4'
gem 'luhn', '1.0.2'
gem 'mail', '2.8.1'
gem 'metasm', '1.0.5'
# gem 'mongo', '2.19.3'
gem 'msfrpc-client', '1.1.2'
gem 'netaddr', '2.0.6'
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ $ cd /opt/pwn
$ ./install.sh
$ ./install.sh ruby-gem
$ pwn
pwn[v0.5.23]:001 >>> PWN.help
pwn[v0.5.24]:001 >>> PWN.help
```

[![Installing the pwn Security Automation Framework](https://raw.githubusercontent.com/0dayInc/pwn/master/documentation/pwn_install.png)](https://youtu.be/G7iLUY4FzsI)
Expand All @@ -52,7 +52,7 @@ $ rvm use ruby-3.3.0@pwn
$ gem uninstall --all --executables pwn
$ gem install --verbose pwn
$ pwn
pwn[v0.5.23]:001 >>> PWN.help
pwn[v0.5.24]:001 >>> PWN.help
```

If you're using a multi-user install of RVM do:
Expand All @@ -62,7 +62,7 @@ $ rvm use ruby-3.3.0@pwn
$ rvmsudo gem uninstall --all --executables pwn
$ rvmsudo gem install --verbose pwn
$ pwn
pwn[v0.5.23]:001 >>> PWN.help
pwn[v0.5.24]:001 >>> PWN.help
```

PWN periodically upgrades to the latest version of Ruby which is reflected in `/opt/pwn/.ruby-version`. The easiest way to upgrade to the latest version of Ruby from a previous PWN installation is to run the following script:
Expand Down
66 changes: 41 additions & 25 deletions lib/pwn/plugins/assembly.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# frozen_string_literal: true

require 'metasm'
require 'tempfile'

module PWN
Expand All @@ -9,18 +10,29 @@ module Assembly
# Supported Method Parameters::
# PWN::Plugins::Assembly.opcodes_to_asm(
# opcodes: 'required - hex escaped opcode(s) (e.g. "\x90\x90\x90")',
# arch: 'optional - objdump -i architecture (defaults to i386)'
# arch: 'optional - architecture returned from objdump --info (defaults to PWN::Plugins::DetectOS.arch)',
# endian: 'optional - endianess (defaults to :little)'
# )

public_class_method def self.opcodes_to_asm(opts = {})
opcodes = opts[:opcodes]
arch = opts[:arch] || 'i386'
arch = opts[:arch] ||= PNW::Plugins::DetectOS.arch
endian = opts[:endian] ||= :little

opcodes_tmp = Tempfile.new('pwn_opcodes')
File.binwrite(opcodes_tmp.path, opcodes)
# TODO: Implement support for other architectures
# for both 32bit and 64bit
`objdump --disassemble-all --target binary --architecture #{arch} #{opcodes_tmp.path}`
case arch
when 'i386'
arch_obj = Metasm::Ia32.new(endian)
when 'amd64', 'x86_64'
arch_obj = Metasm::X86_64.new(endian)
when 'armv71'
arch_obj = Metasm::ARM.new(endian)
when 'aarch64'
arch_obj = Metasm::ARM64.new(endian)
else
raise "Unsupported architecture: #{arch}"
end

Metasm::Shellcode.disassemble(arch_obj, opcodes).to_s
rescue StandardError => e
raise e
ensure
Expand All @@ -30,29 +42,31 @@ module Assembly
# Supported Method Parameters::
# PWN::Plugins::Assembly.asm_to_opcodes(
# asm: 'required - assembly instruction(s) (e.g. 'nop\nnop\nnop\njmp rsp\n)',
# arch: 'optional - objdump -i architecture (defaults to i386)'
# arch: 'optional - architecture returned from objdump --info (defaults to PWN::Plugins::DetectOS.arch)',
# endian: 'optional - endianess (defaults to :little)'
# )

public_class_method def self.asm_to_opcodes(opts = {})
asm = opts[:asm]
arch = opts[:arch] || 'i386'

asm_code = ".global _start\n_start:\n#{asm}"
arch = opts[:arch] ||= PNW::Plugins::DetectOS.arch
endian = opts[:endian] ||= :little

asm_tmp = Tempfile.new('pwn_asm')
asm_tmp.write(asm_code)
asm_tmp.close
case arch
when 'i386'
arch_obj = Metasm::Ia32.new(endian)
when 'amd64', 'x86_64'
arch_obj = Metasm::X86_64.new(endian)
when 'armv71'
arch_obj = Metasm::ARM.new(endian)
when 'aarch64'
arch_obj = Metasm::ARM64.new(endian)
else
raise "Unsupported architecture: #{arch}"
end

asm_tmp_o = "#{asm_tmp.path}.o"
# TODO: Implement support for other architectures
# for both 32bit and 64bit
system('as', '-o', asm_tmp_o, asm_tmp.path)
`objdump --disassemble-all #{asm_tmp.path}.o`
Metasm::Shellcode.assemble(arch_obj, asm).encode_string
rescue StandardError => e
raise e
ensure
files = [asm_tmp.path, asm_tmp_o]
FileUtils.rm_f(files) if File.exist?(asm_tmp.path)
end

# Author(s):: 0day Inc. <request.pentest@0dayinc.com>
Expand All @@ -69,12 +83,14 @@ module Assembly
puts "USAGE:
#{self}.opcodes_to_asm(
opcodes: 'required - hex escaped opcode(s) (e.g. \"\\x90\\x90\\x90\")',
arch: 'optional - objdump -i architecture (defaults to i386)'
arch: 'optional - architecture returned from objdump --info (defaults to PWN::Plugins::DetectOS.arch)',
endian: 'optional - endianess (defaults to :little)'
)
#{self}.asm_to_opcodes(
asm: 'required - assembly instruction(s) (e.g. 'jmp rsp')',
arch: 'optional - objdump -i architecture (defaults to i386)'
asm: 'required - assembly instruction(s) (e.g. 'nop\nnop\nnop\njmp rsp\n)',
arch: 'optional - architecture returned from objdump --info (defaults to PWN::Plugins::DetectOS.arch)',
endian: 'optional - endianess (defaults to :little)'
)
#{self}.authors
Expand Down
2 changes: 1 addition & 1 deletion lib/pwn/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module PWN
VERSION = '0.5.23'
VERSION = '0.5.24'
end

0 comments on commit afd3e2c

Please sign in to comment.