Skip to content

Commit

Permalink
use String#b instead of force_encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
jjyg committed Dec 11, 2023
1 parent c8f02d5 commit b410802
Show file tree
Hide file tree
Showing 22 changed files with 58 additions and 86 deletions.
10 changes: 10 additions & 0 deletions metasm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,13 @@ class Hash
alias index key
end
end

# not sure when String#b was actually introduced
if not String.new.respond_to?(:b)
puts "using ruby1.9 workaround for String#b" if $DEBUG
class String
def b
dup.force_encoding(Encoding::BINARY)
end
end
end
3 changes: 1 addition & 2 deletions metasm/cpu/ia32/debug.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ def dbg_disable_bp(dbg, bp)
end
end

DBG_BPX = "\xcc"
DBG_BPX.force_encoding('BINARY') if DBG_BPX.respond_to?(:force_encoding)
DBG_BPX = "\xcc".b
def dbg_enable_bpx(dbg, bp)
bp.internal[:previous] ||= dbg.memory[bp.address, 1]
dbg.memory[bp.address, 1] = DBG_BPX
Expand Down
9 changes: 4 additions & 5 deletions metasm/encode.rb
Original file line number Diff line number Diff line change
Expand Up @@ -277,13 +277,12 @@ def encode(type, endianness, backtrace=nil)
when Integer; EncodedData.new Expression.encode_imm(val, type, endianness, backtrace)
else
str = case INT_SIZE[type]
when 8; "\0"
when 16; "\0\0"
when 32; "\0\0\0\0"
when 64; "\0\0\0\0\0\0\0\0"
when 8; "\0".b
when 16; "\0\0".b
when 32; "\0\0\0\0".b
when 64; "\0\0\0\0\0\0\0\0".b
else [0].pack('C')*(INT_SIZE[type]/8)
end
str = str.force_encoding('BINARY') if str.respond_to?(:force_encoding)
EncodedData.new(str, :reloc => {0 => Relocation.new(self, type, endianness, backtrace)})
end
end
Expand Down
23 changes: 11 additions & 12 deletions metasm/exe_format/autoexe.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ def self.execlass_from_signature(raw)

# register a new binary file signature
def self.register_signature(sig, exe=nil, &b)
sig.force_encoding('binary') if sig.respond_to?(:force_encoding)
(@signatures ||= []) << [sig, exe || b]
end

Expand All @@ -52,16 +51,16 @@ def self.unknown_signature(raw)

# raw signature copies (avoid triggering exefmt autorequire)
init_signatures
register_signature("\x7fELF") { ELF }
register_signature(lambda { |raw| raw[0, 2] == "MZ" and off = raw[0x3c, 4].to_s.unpack('V')[0] and off < raw.length and raw[off, 4] == "PE\0\0" }) { PE }
register_signature("\x7fELF".b) { ELF }
register_signature(lambda { |raw| raw[0, 2] == "MZ".b and off = raw[0x3c, 4].to_s.unpack('V')[0] and off < raw.length and raw[off, 4] == "PE\0\0".b }) { PE }
%w[feedface cefaedfe feedfacf cffaedfe].each { |sig| register_signature([sig].pack('H*')) { MachO } }
register_signature("\xca\xfe\xba\xbe") { UniversalBinary }
register_signature("dex\n") { DEX }
register_signature("dey\n") { DEY }
register_signature("\xfa\x70\x0e\x1f") { FatELF }
register_signature("\x50\x4b\x03\x04") { ZIP }
register_signature("\0asm") { WasmFile }
register_signature('Metasm.dasm') { Disassembler }
register_signature("\xca\xfe\xba\xbe".b) { UniversalBinary }
register_signature("dex\n".b) { DEX }
register_signature("dey\n".b) { DEY }
register_signature("\xfa\x70\x0e\x1f".b) { FatELF }
register_signature("\x50\x4b\x03\x04".b) { ZIP }
register_signature("\0asm".b) { WasmFile }
register_signature('Metasm.dasm'.b) { Disassembler }

# replacement for AutoExe where #load defaults to a Shellcode of the specified CPU
def self.orshellcode(cpu=nil, &b)
Expand All @@ -79,7 +78,7 @@ class << c ; self ; end.send(:define_method, :unknown_signature) { |raw|
# special class that decodes a LoadedPE or LoadedELF from its signature (used to read memory-mapped binaries)
class LoadedAutoExe < AutoExe
init_signatures
register_signature("\x7fELF") { LoadedELF }
register_signature(lambda { |raw| raw[0, 2] == "MZ" and off = raw[0x3c, 4].to_s.unpack('V')[0] and off < raw.length and raw[off, 4] == "PE\0\0" }) { LoadedPE }
register_signature("\x7fELF".b) { LoadedELF }
register_signature(lambda { |raw| raw[0, 2] == "MZ".b and off = raw[0x3c, 4].to_s.unpack('V')[0] and off < raw.length and raw[off, 4] == "PE\0\0".b }) { LoadedPE }
end
end
7 changes: 2 additions & 5 deletions metasm/exe_format/coff_encode.rb
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,7 @@ def encode(coff, edata)
@iat_p ||= Expression[coff.label_at(edata['iat'].last, 0, 'iat'), :-, coff.label_at(coff.encoded, 0)]
edata['idata'] << super(coff)

@libname.force_encoding('BINARY') if @libname.respond_to?(:force_encoding)
edata['nametable'] << @libname << 0
edata['nametable'] << @libname.b << 0

ord_mask = 1 << (coff.bitsize - 1)
@imports.each { |i|
Expand All @@ -183,8 +182,7 @@ def encode(coff, edata)
else
edata['nametable'].align 2
ptr = coff.encode_xword(rva_end['nametable'])
i.name.force_encoding('BINARY') if i.name.respond_to?(:force_encoding)
edata['nametable'] << coff.encode_half(i.hint || 0) << i.name << 0
edata['nametable'] << coff.encode_half(i.hint || 0) << i.name.b << 0
end
edata['ilt'] << ptr
edata['iat'].last << ptr
Expand Down Expand Up @@ -628,7 +626,6 @@ def encode_header
end
end
s.rawaddr = nil if s.rawaddr.kind_of?(::Integer) # XXX allow to force rawaddr ?
s.name.force_encoding('BINARY') if s.name.respond_to?(:force_encoding)
s_table << s.encode(self)
}

Expand Down
12 changes: 4 additions & 8 deletions metasm/exe_format/elf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@

module Metasm
class ELF < ExeFormat
MAGIC = "\x7fELF" # 0x7f454c46
MAGIC.force_encoding('BINARY') if MAGIC.respond_to?(:force_encoding)
MAGIC = "\x7fELF".b # 0x7f454c46
CLASS = { 0 => 'NONE', 1 => '32', 2 => '64', 200 => '64_icc' }
DATA = { 0 => 'NONE', 1 => 'LSB', 2 => 'MSB' }
VERSION = { 0 => 'INVALID', 1 => 'CURRENT' }
Expand Down Expand Up @@ -455,10 +454,8 @@ class ELF < ExeFormat
0x406 => 'TLS_TPREL64', 0x407 => 'TLSDESC' },
}

DEFAULT_INTERP = '/lib/ld-linux.so.2'
DEFAULT_INTERP64 = '/lib64/ld-linux-x86-64.so.2'
DEFAULT_INTERP.force_encoding('BINARY') if DEFAULT_INTERP.respond_to?(:force_encoding)
DEFAULT_INTERP64.force_encoding('BINARY') if DEFAULT_INTERP64.respond_to?(:force_encoding)
DEFAULT_INTERP = '/lib/ld-linux.so.2'.b
DEFAULT_INTERP64 = '/lib64/ld-linux-x86-64.so.2'.b

class SerialStruct < Metasm::SerialStruct
new_int_field :addr, :off, :xword, :sword, :sxword
Expand Down Expand Up @@ -755,8 +752,7 @@ def addr_to_off(addr)
end

class FatELF < ExeFormat
MAGIC = "\xfa\x70\x0e\x1f" # 0xfat..elf
MAGIC.force_encoding('BINARY') if MAGIC.respond_to?(:force_encoding)
MAGIC = "\xfa\x70\x0e\x1f".b # 0xfat..elf

class SerialStruct < Metasm::SerialStruct
new_int_field :qword
Expand Down
9 changes: 3 additions & 6 deletions metasm/exe_format/elf_encode.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ def make_name_p elf
return if name_p and sne.data[@name_p, @name.length+1] == @name+0.chr
return if @name_p = sne.data.index(@name+0.chr)
@name_p = sne.virtsize
@name.force_encoding('BINARY') if name.respond_to?(:force_encoding)
sne << @name << 0
sne << @name.b << 0
end
end

Expand Down Expand Up @@ -93,8 +92,7 @@ def make_name_p(elf, strtab)
return if name_p and s[@name_p, @name.length+1] == @name+0.chr
return if @name_p = s.index(@name+0.chr)
@name_p = strtab.length
@name.force_encoding('BINARY') if name.respond_to?(:force_encoding)
strtab << @name << 0
strtab << @name.b << 0
end
end

Expand Down Expand Up @@ -522,8 +520,7 @@ def encode_segments_dynamic
add_str = lambda { |n|
if n and n != '' and not ret = strtab.encoded.data.index(n + 0.chr)
ret = strtab.encoded.virtsize
n.force_encoding('BINARY') if n.respond_to?(:force_encoding)
strtab.encoded << n << 0
strtab.encoded << n.b << 0
end
ret || 0
}
Expand Down
7 changes: 2 additions & 5 deletions metasm/exe_format/macho.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,13 @@

module Metasm
class MachO < ExeFormat
MAGIC = "\xfe\xed\xfa\xce" # 0xfeedface
MAGIC = "\xfe\xed\xfa\xce".b # 0xfeedface
CIGAM = MAGIC.reverse # 0xcefaedfe
MAGIC64 = "\xfe\xed\xfa\xcf" # 0xfeedfacf
MAGIC64 = "\xfe\xed\xfa\xcf".b # 0xfeedfacf
CIGAM64 = MAGIC64.reverse # 0xcffaedfe

MAGICS = [MAGIC, CIGAM, MAGIC64, CIGAM64]

# "a" != "a" lolz!
MAGICS.each { |s| s.force_encoding('BINARY') } if MAGIC.respond_to?(:force_encoding)

CPU = {
1 => 'VAX', 2 => 'ROMP',
4 => 'NS32032', 5 => 'NS32332',
Expand Down
3 changes: 1 addition & 2 deletions metasm/exe_format/mz.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@

module Metasm
class MZ < ExeFormat
MAGIC = 'MZ' # 0x4d5a
MAGIC.force_encoding('BINARY') if MAGIC.respond_to?(:force_encoding)
MAGIC = 'MZ'.b # 0x4d5a
class Header < SerialStruct
mem :magic, 2, MAGIC
words :cblp, :cp, :crlc, :cparhdr, :minalloc, :maxalloc, :ss, :sp, :csum, :ip, :cs, :lfarlc, :ovno
Expand Down
3 changes: 1 addition & 2 deletions metasm/exe_format/pe.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@

module Metasm
class PE < COFF
MAGIC = "PE\0\0" # 0x50450000
MAGIC.force_encoding('BINARY') if MAGIC.respond_to?(:force_encoding)
MAGIC = "PE\0\0".b # 0x50450000

attr_accessor :coff_offset, :signature, :mz, :productid

Expand Down
2 changes: 1 addition & 1 deletion metasm/exe_format/serialstruct.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def virtual(*a)

# a fixed-size memory chunk
def mem(name, len, defval='')
new_field(name, lambda { |exe, me| exe.curencoded.read(len) }, lambda { |exe, me, val| d = val[0, len].ljust(len, 0.chr) ; d.force_encoding('BINARY') if d.respond_to?(:force_encoding) ; d }, lambda { |exe, me| len }, defval)
new_field(name, lambda { |exe, me| exe.curencoded.read(len) }, lambda { |exe, me, val| val[0, len].ljust(len, 0.chr).b }, lambda { |exe, me| len }, defval)
end
# a fixed-size string, 0-padded
def str(name, len, defval='')
Expand Down
3 changes: 1 addition & 2 deletions metasm/exe_format/wasm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ module Metasm
# WebAssembly
# leb integer encoding taken from dex.rb
class WasmFile < ExeFormat
MAGIC = "\0asm"
MAGIC.force_encoding('binary') if MAGIC.respond_to?(:force_encoding)
MAGIC = "\0asm".b

SECTION_NAME = { 1 => 'Type', 2 => 'Import', 3 => 'Function', 4 => 'Table',
5 => 'Memory', 6 => 'Global', 7 => 'Export', 8 => 'Start',
Expand Down
3 changes: 2 additions & 1 deletion metasm/gui/win32.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2039,7 +2039,8 @@ def initialize(*a, &b)
:style => Win32Gui::CS_DBLCLKS,
:hcursor => Win32Gui.loadcursora(0, Win32Gui::IDC_ARROW),
:lpszclassname => cname,
:lpfnwndproc => Win32Gui.callback_alloc_c('__stdcall int wndproc(int, int, int, int)') { |hwnd, msg, wp, lp| windowproc(hwnd, msg, wp, lp) }
# __stdcall LRESULT (*WNDPROC)(HWND, UINT, WPARAM, LPARAM)
:lpfnwndproc => Win32Gui.callback_alloc_c('__stdcall uintptr_t wndproc(uintptr_t, int, uintptr_t, uintptr_t)') { |hwnd, msg, wp, lp| windowproc(hwnd, msg, wp, lp) }

Win32Gui.registerclassexa(cls)

Expand Down
14 changes: 3 additions & 11 deletions metasm/main.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1008,16 +1008,11 @@ class EncodedData
attr_reader :ptr # custom writer
def ptr=(p) @ptr = @export[p] || p end

INITIAL_DATA = ''
INITIAL_DATA.force_encoding('BINARY') if INITIAL_DATA.respond_to?(:force_encoding)
INITIAL_DATA = ''.b

# opts' keys in :reloc, :export, :virtsize, defaults to empty/empty/data.length
def initialize(data=INITIAL_DATA.dup, opts={})
if data.respond_to?(:force_encoding) and data.encoding.name != 'ASCII-8BIT' and data.length > 0
puts "Forcing edata.data.encoding = BINARY at", caller if $DEBUG
data = data.dup.force_encoding('binary')
end
@data = data
@data = data.b
@reloc = opts[:reloc] || {}
@export = opts[:export] || {}
@inv_export = @export.invert
Expand Down Expand Up @@ -1167,10 +1162,7 @@ def <<(other)
@virtsize += other.virtsize
else
fill
if other.respond_to?(:force_encoding) and other.encoding.name != 'ASCII-8BIT' and other.length > 0
puts "Forcing edata.data.encoding = BINARY at", caller if $DEBUG
other = other.dup.force_encoding('binary')
end
other = other.b if other.kind_of?(String)
if @data.empty?; @data = other.dup
elsif other.empty?
elsif not @data.kind_of?(String); @data = @data.to_str << other
Expand Down
2 changes: 1 addition & 1 deletion metasm/os/linux.rb
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ def readmem(off, len)
end

def writemem(off, str)
str.force_encoding('binary') if str.respond_to?(:force_encoding)
str = str.b
decal = off % @host_intsize
if decal > 0
off -= decal
Expand Down
5 changes: 5 additions & 0 deletions metasm/os/main.rb
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@ def realstring
ret << self[addr, len]
end

# compat with String#b (force encoding binary)
def b
self
end

# alias to realstring
# for bad people checking respond_to? :to_str (like String#<<)
# XXX alias does not work (not virtual (a la C++))
Expand Down
3 changes: 1 addition & 2 deletions metasm/preprocessor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -715,8 +715,7 @@ def readtok_nopp
def readtok_nopp_str(tok, delimiter)
tok.type = :quoted
tok.raw << delimiter
tok.value = ''
tok.value.force_encoding('binary') if tok.value.respond_to?(:force_encoding)
tok.value = ''.b
c = nil
loop do
raise tok, 'unterminated string' if not c = getchar
Expand Down
2 changes: 1 addition & 1 deletion misc/hexdump.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def hexdump(ctx={})
print s.unpack('C*').map { |b| '%02x' % b }.join(' ').ljust(3*16-1) + ' ' if fmt.include? 'c'
print s.unpack('v*').map { |b| '%04x' % b }.join(' ').ljust(5*8-1) + ' ' if fmt.include? 'w'
print s.unpack('L*').map { |b| '%08x' % b }.join(' ').ljust(9*4-1) + ' ' if fmt.include? 'd'
print s.tr("\0-\x1f\x7f-\xff".force_encoding('BINARY'), '.') if fmt.include? 'a'
print s.tr("\0-\x1f\x7f-\xff".b, '.') if fmt.include? 'a'
puts
elsif not ctx[:lastdup]
ctx[:lastdup] = true
Expand Down
2 changes: 1 addition & 1 deletion misc/lint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def lint_file(tg)
end

def compile_warn(tg)
r, w = IO.pipe('binary')
r, w = IO.pipe(Encoding::BINARY)
if !fork
r.close
$stderr.reopen w
Expand Down
6 changes: 1 addition & 5 deletions tests/ia32.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@ def assemble(src, cpu=@@cpu32)
def assert_equal(a, b) super(b, a) end

def bin(s)
if s.respond_to?(:force_encoding)
s.force_encoding('BINARY')
else
s
end
s.b
end

def test_basic
Expand Down
10 changes: 1 addition & 9 deletions tests/mips.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,19 +105,11 @@ def test_enc
# '' << "\x80" => 8bits
# '' << 0x80 => ascii
# Edata.data is ascii for now, so this is needed to make the test work.
str = bin("\x24\x0e\xff\xfb\x01\xc0\x70\x27\x24\x0b\xff\xb7\x05\x10\xff\xff\x28\x08\x82\x82\x01\x60\x58\x27\x03\xeb\xc8\x21\x28\x17\x82\x82\x8f\x31\xff\xfc\x24\x0d\xff\xfb\x01\xa0\x68\x27\x21\xaf\xff\xfd\x8f\x28\xff\xfc\x02\xef\xb8\x21\x01\x11\x18\x26\x02\xee\xf0\x2b\xaf\x23\xff\xfc\x21\xa6\xff\xff\x17\xc0\xff\xf9\x03\x2d\xc8\x21\x24\x02\x10\x33\x01\x4a\x54\x0c\0\0\0\0")
str = "\x24\x0e\xff\xfb\x01\xc0\x70\x27\x24\x0b\xff\xb7\x05\x10\xff\xff\x28\x08\x82\x82\x01\x60\x58\x27\x03\xeb\xc8\x21\x28\x17\x82\x82\x8f\x31\xff\xfc\x24\x0d\xff\xfb\x01\xa0\x68\x27\x21\xaf\xff\xfd\x8f\x28\xff\xfc\x02\xef\xb8\x21\x01\x11\x18\x26\x02\xee\xf0\x2b\xaf\x23\xff\xfc\x21\xa6\xff\xff\x17\xc0\xff\xf9\x03\x2d\xc8\x21\x24\x02\x10\x33\x01\x4a\x54\x0c\0\0\0\0".b
assert_equal(str, sc.encoded.data)

dasm_src = Metasm::Shellcode.disassemble(Metasm::MIPS.new(:big), sc.encoded.data).to_s
lines = dasm_src.respond_to?(:lines) ? dasm_src.lines : dasm_src.to_a
assert_equal(26, lines.grep(/^[^\/].*\S/).length)
end

def bin(s)
if s.respond_to?(:force_encoding)
s.force_encoding('BINARY')
else
s
end
end
end
6 changes: 1 addition & 5 deletions tests/x86_64.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,7 @@ def test_user
end

def bin(s)
if s.respond_to?(:force_encoding)
s.force_encoding('BINARY')
else
s
end
s.b
end

def test_basic
Expand Down

0 comments on commit b410802

Please sign in to comment.