46

I have a binary file that I can send with netcat:

$ nc -l localhost 8181 < my.dat

The file contains this:

$ xxd my.dat
0000000: 0006 3030 3030 4e43                      ..0000NC

What I really want to do is send the hex string directly. I've tried this:

$ echo '0006303030304e43' | nc -l localhost 8181

However, the above command just sends the ascii string directly to nc.

55

I used the -r and -p switch to xxd:

$ echo '0006303030304e43' | xxd -r -p | nc -l localhost 8181

Thanks to inspiration from @Gilles answer, here's a perl version:

$ echo '0006303030304e43' | perl -e 'print pack "H*", <STDIN>' | nc -l localhost 8181
  • Works great for Postgres's bytea hex format once the leading \x is striped off. – nathancahill May 10 '16 at 19:38
  • Thanks! Works great also for checking Firefox dictionaries digests in manifest! md5sum ../it/manifest.json | awk '{print $1}' | xxd -r -p | hd – Avio May 30 at 10:08
26

Here a solution without xxd or perl:

If the echo builtin of your shell supports it (bash and zsh do, but not dash), you just need to use the right backslash escapes:

echo -ne '\x00\x06\x30\x30\x30\x30\x4e\x43' | nc -l localhost 8181

If you have /bin/echo from GNU coreutils (nearly standard on Linux systems) or from busybox you can use it, too.

With sed you can generate a escaped pattern:

$ echo '0006303030304e43' | sed -e 's/../\\x&/g'
\x00\x06\x30\x30\x30\x30\x4e\x43

Combined:

echo -ne "$(echo '0006303030304e43' | sed -e 's/../\\x&/g')" | nc -l localhost 8181
  • very nice solution! – Chris Snow Jul 12 '13 at 13:17
  • 2
    Replacing echo with printf removes the guess work if echo supports extended features or not. printf "$(echo '0006303030304e43' | sed -e 's/../\\x&/g')" | nc -l localhost 8181. – Jaakko Aug 9 '18 at 7:11
12

If you have xxd, that's easy: it can convert to and from hexadecimal.

echo '0006303030304e43' | xxd -r -p | nc -l localhost 8181

I don't think there's a reasonable (and reasonably fast) way to convert hexadecimal to binary using only POSIX tools. It can be done fairly easy in Perl. The following script converts hexadecimal to binary, ignoring any input character that isn't a hexadecimal digit. It complains if an input line contains an odd number of hexadecimal digits.

#!/usr/bin/env perl
$^W = 1;
$c = undef;
while (<>) {
    tr/0-9A-Fa-f//cd;
    if (defined $c) { warn "Consuming $c"; $_ = $c . $_; $c = undef; }
    if (length($_) & 1) { s/(.)$//; $c = $1; }
    print pack "H*", $_;
}
if (!eof) { die "$!"; }
if (defined $c) { warn "Odd number of hexadecimal digits"; }

If you really need to stick to POSIX (e.g. on an embedded device), I recommend using Base64 instead of hexadecimal. You can use uudecode to decode Base64. The input must have the header format and end line produced by uuencode, it can't be raw Base64.

uudecode <<EOF | nc -l localhost 8181
begin-base64 644 -
AAYwMDAwTkM=
====
EOF
1

Similar to this: https://stackoverflow.com/questions/1604765/linux-shell-scripting-hex-string-to-bytes/47253233#47253233

I wrote a tool that perform various transformations from stdin and spits out the result to stdout. cryptocli dd will only do those transformations and nothing else.

echo -n 0006303030304e43 | cryptocli dd -decoders hex | nc -l localhost 8081

Will work for you.

The tool is open source, you can find it here: https://github.com/tehmoon/cryptocli

Edit:

You can also encode directly to hex using my tool:

cat my.dat | cryptocli dd -encoders hex | nc -l localhost 8081
  • (1) What does 616263 have to do with this question?  Please use the data from the question.  (2) Can you explain how this works? Please do not respond in comments, edit your answer to make it clearer and more complete. – G-Man Says 'Reinstate Monica' Nov 12 '17 at 20:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.