2

I'm trying to covert hex number into ASCII text and for that I used xxd. But the issue with that it's not throwing any output.

For Example, I used:

echo 86973746F7279200D6C73202D6C7472200D6E206E657473746174730D6E20696E666F200D6E207374617475730D657869740D | xxd -r -p

but it's not giving me any output.

Is there any other way to covert this without the help of online generator? Please help!!

rtx13
  • 2,580
  • 1
  • 6
  • 22

3 Answers3

5

Your hex data has a number of CR (0D) bytes which cause the cursor to rewind to the beginning of the line and overwrite any previous output. In addition, when the pipeline is done running, your shell prompt will overwrite any remaining output.

You will most likely want to convert CR to LF to see the output by appending | tr '\r' '\n' to the pipeline:

$ echo 686973746F7279200D6C73202D6C7472200D6E206E657473746174730D6E20696E666F200D6E207374617475730D657869740D | xxd -r -p | tr '\r' '\n'
history 
ls -ltr 
n netstats
n info 
n status
exit
rtx13
  • 2,580
  • 1
  • 6
  • 22
  • Thanks a lot for your help. That make sense. – spacewitch666 Apr 06 '20 at 05:47
  • You're welcome. If you find any answer that solves your problem, please feel free to vote up (▲) and/or accept it (✔︎). – rtx13 Apr 06 '20 at 05:55
  • 2
    Alternatively: `<<<'686973746F7279200D6C73202D6C7472200D6E206E657473746174730D6E20696E666F200D6E207374617475730D657869740D' xxd -r -p | strings`. `strings` ensure non-printable characters are discarded. – Léa Gris Apr 06 '20 at 05:58
  • @LéaGris This This answers the question better than the answer you're commenting on (maybe add as another answer?) – Ross Jacobs Apr 06 '20 at 06:01
  • @LéaGris I'm not sure if OP wants all non-printable characters discarded as OP didn't specify the nature or origin of the hex data. Perhaps there are terminal control characters that may need to be preserved. In addition, `strings` likely doesn't preserve strings with utf-8 characters. – rtx13 Apr 06 '20 at 06:03
3

You can actually use printf and sed to split every 2 characters and output in whatever format you need. You use sed to create a newline delimited list of 2-character strings and by outputting as a string you avoid the control character conversion issues with, e.g. 0D, etc... You can use printf "0x%s\n" (which by virtue of printf processing each line of input will result in the output of all you 2-char values)

For example you could do:

printf "0x%s\n" $(echo "686973746F7279200D6C73202D6C7472200D6E206E657473746174730D6E20696E666F200D6E207374617475730D657869740D" |
sed 's/\(..\)/\1\n/g')

or the equivalent with a herestring (bash only)

printf "0x%s\n" $(sed 's/\(..\)/\1\n/g' <<< "686973746F7279200D6C73202D6C7472200D6E206E657473746174730D6E20696E666F200D6E207374617475730D657869740D")

Output

0x68
0x69
0x73
0x74
0x6F
0x72
0x79
0x20
0x0D
0x6C
0x73
0x20
0x2D
0x6C
0x74
0x72
0x20
0x0D
0x6E
0x20
0x6E
0x65
0x74
0x73
0x74
0x61
0x74
0x73
0x0D
0x6E
0x20
0x69
0x6E
0x66
0x6F
0x20
0x0D
0x6E
0x20
0x73
0x74
0x61
0x74
0x75
0x73
0x0D
0x65
0x78
0x69
0x74
0x0D

If you want the value in lower-case hex, then you can actually process the input values as hex using the "0x%02x" conversion:

printf "0x%02x\n" $(echo "686973746F7279200D6C73202D6C7472200D6E206E657473746174730D6E20696E666F200D6E207374617475730D657869740D" |
sed 's/\(..\)/0x\1\n/g')

Output

0x68
0x69
0x73
0x74
0x6f
0x72
0x79
0x20
0x0d
0x6c
0x73
0x20
0x2d
0x6c
0x74
0x72
0x20
0x0d
0x6e
0x20
0x6e
0x65
0x74
0x73
0x74
0x61
0x74
0x73
0x0d
0x6e
0x20
0x69
0x6e
0x66
0x6f
0x20
0x0d
0x6e
0x20
0x73
0x74
0x61
0x74
0x75
0x73
0x0d
0x65
0x78
0x69
0x74
0x0d

Which depending on what you want as output may be all you need. Let me know if you need a slightly different output format and I'm happy to help further.

Or -- If I have it backwards, and you actually want the ASCII value for every character in the string, you can use a simple for loop and printf to print the ASCII value of every character. To output the ASCII value, you precede the double-quoted variable name with a single-quote, e.g.

a="686973746F7279200D6C73202D6C7472200D6E206E657473746174730D6E20696E666F200D6E207374617475730D657869740D"
for ((i = 0; i < ${#a}; i++)); do printf "%s - 0x%02x\n" "${a:i:1}" "'${a:i:1}"; done

Output

Character and ASCII value of each character:

6 - 0x36
8 - 0x38
6 - 0x36
9 - 0x39
7 - 0x37
3 - 0x33
7 - 0x37
4 - 0x34
6 - 0x36
F - 0x46
7 - 0x37
2 - 0x32
7 - 0x37
9 - 0x39
2 - 0x32
0 - 0x30
0 - 0x30
D - 0x44
6 - 0x36
C - 0x43
7 - 0x37
3 - 0x33
2 - 0x32
0 - 0x30
2 - 0x32
D - 0x44
6 - 0x36
C - 0x43
7 - 0x37
4 - 0x34
7 - 0x37
2 - 0x32
2 - 0x32
0 - 0x30
0 - 0x30
D - 0x44
6 - 0x36
E - 0x45
2 - 0x32
0 - 0x30
6 - 0x36
E - 0x45
6 - 0x36
5 - 0x35
7 - 0x37
4 - 0x34
7 - 0x37
3 - 0x33
7 - 0x37
4 - 0x34
6 - 0x36
1 - 0x31
7 - 0x37
4 - 0x34
7 - 0x37
3 - 0x33
0 - 0x30
D - 0x44
6 - 0x36
E - 0x45
2 - 0x32
0 - 0x30
6 - 0x36
9 - 0x39
6 - 0x36
E - 0x45
6 - 0x36
6 - 0x36
6 - 0x36
F - 0x46
2 - 0x32
0 - 0x30
0 - 0x30
D - 0x44
6 - 0x36
E - 0x45
2 - 0x32
0 - 0x30
7 - 0x37
3 - 0x33
7 - 0x37
4 - 0x34
6 - 0x36
1 - 0x31
7 - 0x37
4 - 0x34
7 - 0x37
5 - 0x35
7 - 0x37
3 - 0x33
0 - 0x30
D - 0x44
6 - 0x36
5 - 0x35
7 - 0x37
8 - 0x38
6 - 0x36
9 - 0x39
7 - 0x37
4 - 0x34
0 - 0x30
D - 0x44
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
0

You can use python3 inline to print the ASCII characters. This may not mimic xxd output as other answers do, but allows you to see the \r\n-type characters that are causing problems.

$ str='686973746F7279200D6C73202D6C7472200D6E206E657473746174730D6E20696E666F200D6E207374617475730D657869740D'
$ python3 -c "b=b''.fromhex('$str'); s=str(b)[2:-1]; print(s)"
history \rls -ltr \rn netstats\rn info \rn status\rexit\r

Here,

  • b=b''.fromhex('$str') converts the hex numbers to a bytes object. If you've used python, for a character like a newline
  • str(b)[2:-1] converts a bytes object that looks like b'abcd' to abcd. The b and 's are not important for output and so are truncated.
  • If you want to replace the \r as in @rtx13's answer, add s.replace('\r', '=n').

Additional bash usage notes

You are probably getting an extra newline in your output when sending to xxd. echo adds a newline to output. To demonstrate:

$ echo '' | xxd
00000000: 0a

When you do not want to add bytes in your pipeline use printf for more consistent behavior.

Ross Jacobs
  • 2,962
  • 1
  • 17
  • 27