1

I am currently working with UDP packets and I need to craft and send custom data. Because it is easier for me to read I work with strings representing hexadecimal values. I have something like this :

a = "12"
b = "15"
header = "c56b4040003300" + a + "800401" + b + "90000000"

Now, what I want to do is converting my header variable into hexadecimal (but not with the hexadecimal value of every character in header). It means that if I write my header variable in a file and I open it with a hexadecimal editor, I want to see

c5 6b 40 40 00 33 00 12 80 04 01 15 90 00 00 00

I don't have a good knowledge of ruby and I couldn't find a way to do it so far. The pack function converts characters in hexa but not hexadecimal string representation as hexadecimal value. And doing something like

header = "\xc5\x6b\x40\x40\x00\x33\x00\x" + a + "\x80\x04\x01\x" + b + "\x90\x00\x00\x00"

will throw me an error saying "invalid hex escape" (which make sense). So if you have a solution to this problem please tell me (if possible without using any external library)

1
  • Basically what I want is the equivalent of binascii.hexlify and binascii.unhexlify in python Commented May 18, 2018 at 14:13

2 Answers 2

2
require 'strscan'
s = StringScanner.new('hexstring here')
s.scan(/../).map { |x| x.hex.chr }.join
Sign up to request clarification or add additional context in comments.

1 Comment

whow that is something magic but works pretty well ! Thank you
2

String#to_i takes a base argument that will do what you want:

["c56b4040003300", a, "800401", b, "90000000"].join.to_i(16)

But it may not make sense to represent your data as an large integer. If you just want a blob of binary data, you can concatenate everything together and use Array#pack:

[["c56b4040003300", a, "800401", b, "90000000"].join].pack('H*')

Or you can pack the individual components and concatenate the results:

["c56b4040003300", a, "800401", b, "90000000"].map { |s| [s].pack('H*') }.join

Or you can just work with an array of bytes throughout your program:

bytes = "c56b4040003300".scan(/../)
bytes << a
bytes.concat "800401".scan(/../)
bytes << b
bytes.concat "90000000".scan(/../)
bytes.unpack('H*' * bytes.size)

Hope that helps!

4 Comments

thx for your answer, it work well ! How would you do the opposite operation ? (starting from the hexa and getting the string ? (tried with unpack but couldn't make it work))
@Mtoy You're welcome! It should just be result.unpack('H*')
Oh yeah ok. I think I'm not familiar enough with pack and unpack methods. I will take some time to understand it correctly. Thanks a lot for your help
@Mtoy It's definitely confusing, especially when you get into endianness and word size and all that good stuff. But it is The Way™ to convert to/from binary data in many languages.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.