Module: Pwnlib::Asm
- Included in:
- Pwn
- Defined in:
- lib/pwnlib/asm.rb
Overview
Convert assembly code to machine code and vice versa. Use two open-source projects keystone
/capstone
to asm/disasm.
Constant Summary collapse
- DEFAULT_VMA =
Default virtaul memory base address of architectures.
This address may be different by using different linker.
{ i386: 0x08048000, amd64: 0x400000, arm: 0x8000 }.freeze
- ARCH_EM =
Mapping
context.arch
to::ELFTools::Constants::EM::EM_*
. { aarch64: 'AARCH64', alpha: 'ALPHA', amd64: 'X86_64', arm: 'ARM', cris: 'CRIS', i386: '386', ia64: 'IA_64', m68k: '68K', mips64: 'MIPS', mips: 'MIPS', powerpc64: 'PPC64', powerpc: 'PPC', s390: 'S390', sparc64: 'SPARCV9', sparc: 'SPARC' }.freeze
Class Method Summary collapse
-
.asm(code, vma: 0) ⇒ String
Convert assembly code to machine code.
-
.disasm(data, vma: 0) ⇒ String
Disassembles a bytestring into human readable assembly.
-
.make_elf(data, vma: nil, to_file: false) {|path| ... } ⇒ String, Object
Builds an ELF file from executable code.
Class Method Details
.asm(code, vma: 0) ⇒ String
Convert assembly code to machine code.
126 127 128 129 |
# File 'lib/pwnlib/asm.rb', line 126 def asm(code, vma: 0) ('keystone_engine', install_keystone_guide) KeystoneEngine::Ks.new(ks_arch, ks_mode).asm(code, vma)[0] end |
.disasm(data, vma: 0) ⇒ String
Disassembles a bytestring into human readable assembly.
disasm depends on another open-source project - capstone, error will be raised if capstone is not intalled.
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/pwnlib/asm.rb', line 81 def disasm(data, vma: 0) ('crabstone', install_crabstone_guide) # will raise error if require fail. cs = Crabstone::Disassembler.new(cs_arch, cs_mode) insts = cs.disasm(data, vma).map do |ins| [ins.address, ins.bytes, ins.mnemonic.to_s, ins.op_str.to_s] end max_dlen = format('%x', insts.last.first).size + 2 max_hlen = insts.map { |ins| ins[1].size }.max * 3 max_ilen = insts.map { |ins| ins[2].size }.max insts.reduce('') do |s, ins| hex_code = ins[1].map { |c| format('%02x', c) }.join(' ') inst = if ins[3].empty? ins[2] else format("%-#{max_ilen}s %s", ins[2], ins[3]) end s + format("%#{max_dlen}x: %-#{max_hlen}s %s\n", ins[0], hex_code, inst) end end |
.make_elf(data, vma: nil, to_file: false) {|path| ... } ⇒ String, Object
Builds an ELF file from executable code.
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/pwnlib/asm.rb', line 183 def make_elf(data, vma: nil, to_file: false) to_file ||= block_given? vma ||= DEFAULT_VMA[context.arch.to_sym] vma &= -0x1000 # ELF header # Program headers # <data> headers = create_elf_headers(vma) ehdr = headers[:elf_header] phdr = headers[:program_header] entry = ehdr.num_bytes + phdr.num_bytes ehdr.e_entry = entry + phdr.p_vaddr ehdr.e_phoff = ehdr.num_bytes phdr.p_filesz = phdr.p_memsz = entry + data.size elf = ehdr.to_binary_s + phdr.to_binary_s + data return elf unless to_file path = Dir::Tmpname.create(['pwn', '.elf']) do |temp| File.open(temp, 'wb', 0o750) { |f| f.write(elf) } end block_given? ? yield(path).tap { File.unlink(path) } : path end |