diff --git a/lib/rex/text/hex.rb b/lib/rex/text/hex.rb index 7be5348..20c8a70 100644 --- a/lib/rex/text/hex.rb +++ b/lib/rex/text/hex.rb @@ -166,6 +166,25 @@ def self.dehex!(str) str.gsub!(regex) { |x| x[2,2].to_i(16).chr } end + # + # Converts a string to a comma-separated hex byte sequence suitable for + # use in assembly `db` directives. + # + # @example + # Rex::Text.to_hex_cstring("hi") # => "0x68, 0x69, 0x00" + # Rex::Text.to_hex_cstring("") # => "0x00" + # Rex::Text.to_hex_cstring("hi", nullbyte: false) # => "0x68, 0x69" + # Rex::Text.to_hex_cstring("", nullbyte: false) # => "" + # + # @param str [String] The string to convert + # @param nullbyte [Boolean] Whether to append a null terminator (default: true) + # @return [String] Comma-separated hex bytes + def self.to_hex_cstring(str, nullbyte: true) + bytes = str.to_s.bytes + bytes.push(0) if nullbyte + bytes.map { |byte| '0x%02x' % byte }.join(', ') + end + private # diff --git a/spec/rex/text/hex_spec.rb b/spec/rex/text/hex_spec.rb index 6ce35b8..b47bf22 100644 --- a/spec/rex/text/hex_spec.rb +++ b/spec/rex/text/hex_spec.rb @@ -3,6 +3,34 @@ require 'timeout' RSpec.describe Rex::Text do + describe ".to_hex_cstring" do + it 'should return just a null terminator for an empty string' do + expect(described_class.to_hex_cstring("")).to eq("0x00") + end + + it 'should return hex bytes with a null terminator for a non-empty string' do + expect(described_class.to_hex_cstring("AB")).to eq("0x41, 0x42, 0x00") + end + + it 'should handle nil by treating it as an empty string' do + expect(described_class.to_hex_cstring(nil)).to eq("0x00") + end + + it 'should handle binary data' do + expect(described_class.to_hex_cstring("\xff\x00\x01")).to eq("0xff, 0x00, 0x01, 0x00") + end + + context 'with nullbyte: false' do + it 'should return an empty string for an empty input' do + expect(described_class.to_hex_cstring("", nullbyte: false)).to eq("") + end + + it 'should return hex bytes without a null terminator' do + expect(described_class.to_hex_cstring("AB", nullbyte: false)).to eq("0x41, 0x42") + end + end + end + describe ".hexify" do let(:wrap) { 60 } it 'should wrap at the specified columns' do