From b410802a2e70840f63640d20f108ce5c4121005c Mon Sep 17 00:00:00 2001 From: jj Date: Mon, 11 Dec 2023 19:23:14 +0100 Subject: [PATCH] use String#b instead of force_encoding --- metasm.rb | 10 ++++++++++ metasm/cpu/ia32/debug.rb | 3 +-- metasm/encode.rb | 9 ++++----- metasm/exe_format/autoexe.rb | 23 +++++++++++------------ metasm/exe_format/coff_encode.rb | 7 ++----- metasm/exe_format/elf.rb | 12 ++++-------- metasm/exe_format/elf_encode.rb | 9 +++------ metasm/exe_format/macho.rb | 7 ++----- metasm/exe_format/mz.rb | 3 +-- metasm/exe_format/pe.rb | 3 +-- metasm/exe_format/serialstruct.rb | 2 +- metasm/exe_format/wasm.rb | 3 +-- metasm/gui/win32.rb | 3 ++- metasm/main.rb | 14 +++----------- metasm/os/linux.rb | 2 +- metasm/os/main.rb | 5 +++++ metasm/preprocessor.rb | 3 +-- misc/hexdump.rb | 2 +- misc/lint.rb | 2 +- tests/ia32.rb | 6 +----- tests/mips.rb | 10 +--------- tests/x86_64.rb | 6 +----- 22 files changed, 58 insertions(+), 86 deletions(-) diff --git a/metasm.rb b/metasm.rb index 53eca638b..cc760951b 100644 --- a/metasm.rb +++ b/metasm.rb @@ -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 diff --git a/metasm/cpu/ia32/debug.rb b/metasm/cpu/ia32/debug.rb index b6b751bc4..c9513a2ff 100644 --- a/metasm/cpu/ia32/debug.rb +++ b/metasm/cpu/ia32/debug.rb @@ -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 diff --git a/metasm/encode.rb b/metasm/encode.rb index 6230a201a..e294a9a32 100644 --- a/metasm/encode.rb +++ b/metasm/encode.rb @@ -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 diff --git a/metasm/exe_format/autoexe.rb b/metasm/exe_format/autoexe.rb index 100b6878a..5f56bf6ab 100644 --- a/metasm/exe_format/autoexe.rb +++ b/metasm/exe_format/autoexe.rb @@ -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 @@ -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) @@ -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 diff --git a/metasm/exe_format/coff_encode.rb b/metasm/exe_format/coff_encode.rb index 41d73a585..25b64ca95 100644 --- a/metasm/exe_format/coff_encode.rb +++ b/metasm/exe_format/coff_encode.rb @@ -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| @@ -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 @@ -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) } diff --git a/metasm/exe_format/elf.rb b/metasm/exe_format/elf.rb index 62ee98d2f..ccf869537 100644 --- a/metasm/exe_format/elf.rb +++ b/metasm/exe_format/elf.rb @@ -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' } @@ -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 @@ -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 diff --git a/metasm/exe_format/elf_encode.rb b/metasm/exe_format/elf_encode.rb index 89b12c100..a007d629b 100644 --- a/metasm/exe_format/elf_encode.rb +++ b/metasm/exe_format/elf_encode.rb @@ -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 @@ -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 @@ -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 } diff --git a/metasm/exe_format/macho.rb b/metasm/exe_format/macho.rb index cb857a3b2..102fa3d38 100644 --- a/metasm/exe_format/macho.rb +++ b/metasm/exe_format/macho.rb @@ -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', diff --git a/metasm/exe_format/mz.rb b/metasm/exe_format/mz.rb index 183f5ce27..197f58ecb 100644 --- a/metasm/exe_format/mz.rb +++ b/metasm/exe_format/mz.rb @@ -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 diff --git a/metasm/exe_format/pe.rb b/metasm/exe_format/pe.rb index d26a6f665..6974232aa 100644 --- a/metasm/exe_format/pe.rb +++ b/metasm/exe_format/pe.rb @@ -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 diff --git a/metasm/exe_format/serialstruct.rb b/metasm/exe_format/serialstruct.rb index f1a10a623..e656c2102 100644 --- a/metasm/exe_format/serialstruct.rb +++ b/metasm/exe_format/serialstruct.rb @@ -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='') diff --git a/metasm/exe_format/wasm.rb b/metasm/exe_format/wasm.rb index 80c63d797..d1d528cac 100644 --- a/metasm/exe_format/wasm.rb +++ b/metasm/exe_format/wasm.rb @@ -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', diff --git a/metasm/gui/win32.rb b/metasm/gui/win32.rb index 1bc4a107a..d32abc7e6 100644 --- a/metasm/gui/win32.rb +++ b/metasm/gui/win32.rb @@ -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) diff --git a/metasm/main.rb b/metasm/main.rb index d7233b43a..a0425c1d2 100644 --- a/metasm/main.rb +++ b/metasm/main.rb @@ -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 @@ -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 diff --git a/metasm/os/linux.rb b/metasm/os/linux.rb index 1e842f3b7..7b764a567 100644 --- a/metasm/os/linux.rb +++ b/metasm/os/linux.rb @@ -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 diff --git a/metasm/os/main.rb b/metasm/os/main.rb index f13cf1f2e..1bbb01299 100644 --- a/metasm/os/main.rb +++ b/metasm/os/main.rb @@ -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++)) diff --git a/metasm/preprocessor.rb b/metasm/preprocessor.rb index 00c55b1c0..009189f70 100644 --- a/metasm/preprocessor.rb +++ b/metasm/preprocessor.rb @@ -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 diff --git a/misc/hexdump.rb b/misc/hexdump.rb index b836a6ac2..ac3116ee4 100644 --- a/misc/hexdump.rb +++ b/misc/hexdump.rb @@ -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 diff --git a/misc/lint.rb b/misc/lint.rb index 476960984..ecae2fa25 100644 --- a/misc/lint.rb +++ b/misc/lint.rb @@ -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 diff --git a/tests/ia32.rb b/tests/ia32.rb index 5179a5458..785267dd1 100644 --- a/tests/ia32.rb +++ b/tests/ia32.rb @@ -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 diff --git a/tests/mips.rb b/tests/mips.rb index 1aa550d80..94b81653e 100644 --- a/tests/mips.rb +++ b/tests/mips.rb @@ -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 diff --git a/tests/x86_64.rb b/tests/x86_64.rb index ee71f2bf8..2ed5a7055 100644 --- a/tests/x86_64.rb +++ b/tests/x86_64.rb @@ -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