0

I am having difficulty in understanding the way print command of Perl interprets the hexadecimal values. I am using a very simple program of just 8 lines to demonstrate my question. Following code with gdb will explain my question in detail:

anil@anil-Inspiron-N5010:~/Desktop$ gcc -g code.c
anil@anil-Inspiron-N5010:~/Desktop$ gdb -q ./a.out
Reading symbols from ./a.out...done.
(gdb) list
1   #include <stdio.h>
2   
3   int main(int argc, char* argv[])
4   {
5       int i;
6       for (i =0; i<argc; ++i)
7           printf ("%p\n", argv[i]);
8       return 0;
9   }
(gdb) break 8
Breakpoint 1 at 0x40057a: file code.c, line 8.
(gdb) run $(perl -e 'print "\xdd\xcc\xbb\xaa"') $(perl -e 'print "\xcc\xdd\xee\xff"')
Starting program: /home/anil/Desktop/a.out $(perl -e 'print "\xdd\xcc\xbb\xaa"') $(perl -e 'print "\xcc\xdd\xee\xff"')
0x7fffffffe35d
0x7fffffffe376
0x7fffffffe37b

Breakpoint 1, main (argc=3, argv=0x7fffffffdfe8) at code.c:8
8       return 0;
(gdb) x/2x argv[1]
0x7fffffffe376: 0xaabbccdd  0xeeddcc00

In above shown lines I have used gdb to debug the program. As command line arguments, I have passed two (hexadecimal) arguments (excluding the name of the program itself): \xdd\xcc\xbb\xaa and \xcc\xdd\xee\xff. Owing to the little-endian architecture, those arguments should be interpreted as 0xaabbccdd and 0xffeeddcc but as you can see the last line of above shown debugging shows 0xaabbccdd and 0xeeddcc00. Why is this so? What am I missing ?? This has happened with some other arguments too. I am requesting you to help me with this.

PS: 2^32 = 4294967296 and 0xffeeddcc = 4293844428 (2^32 > 0xffeeddcc). I don't know if still there is any connection.

2
  • Endianness is how multi-byte scalar values such as int are stored. The arguments to your programs are strings. (It would be a bit silly if Little-Endian machines printed "lleHow o!dlr", wouldn't it?) Commented Jan 16, 2015 at 17:07
  • the input of the form \x##\x##\x##\x## shows that they contain hexadecimal values, hence they need to be interpreted bit differently. Commented Jan 16, 2015 at 18:47

2 Answers 2

2

Command-line arguments are NUL-terminated strings.

Arguments argv[1] is a pointer to the first character of a NUL-terminated string.

7FFFFFFFE376  DD CC BB AA 00

argv[2] is a pointer to the first character of a NUL-terminated string.

7FFFFFFFE37B  CC DD EE FF 00

If you pay attention, you'll notice they happen to be located immediately one after the other in memory.

7FFFFFFFE376  DD CC BB AA 00 CC DD EE FF 00

You asked to print two (32-bit) integers starting at argv[1]

7FFFFFFFE376  DD CC BB AA 00 CC DD EE FF 00
              ----------- -----------
               0xAABBCCDD 0xEEDDCC00

For x/2x to be correct, you would have needed to use

perl -e'print "\xdd\xcc\xbb\xaa\xcc\xdd\xee\xff"'
   -or-
perl -e'print pack "i*", 0xaabbccdd, 0xffeeddcc'

For the arguments you passed, you need to use

(gdb) x argv[1]
0x3e080048cbd:  0xaabbccdd
(gdb) x argv[2]
0x3e080048cc2:  0xffeeddcc
Sign up to request clarification or add additional context in comments.

2 Comments

yes, I know realize why other arguments too were giving similar results. thanks for the detailed answer.
In case the run command is following: run $(perl -e 'print "\xaa\xbb\x00\xcc"') $(perl -e 'print "\xaa\xbb\xcc\x00"') $(perl -e 'print "\xaa\x00\xdd\xcc"') the expected result on x/15xb argv[1] is: 0xaa 0xbb 0x00 0xcc 0x00 0xaa 0xbb 0xcc 0x00 0x00 0xaa 0x00 0xdd 0xcc 0x00 in which the 5th, 10th and 15th 0x00 should belong to null terminator but the actual output is: 0xaa 0xbb 0xcc 0x00 0xaa 0xbb 0xcc 0x00 0xaa 0xdd 0xcc 0x00 0x58 0x44 0x47 in which I think 0x00 of the input has been ignored, only 0x00 corresponding to null-terminator has been considered. Any explanation??
2

You are confusing yourself by printing strings as numbers. In a little-endian architecture, in a four-byte value such as 0xDDCCBBAA, the bytes are numbered left-to-right from the starting address.

So let's take a look at the output of your debugger command:

(gdb) x/2x argv[1]
0x7fffffffe376: 0xaabbccdd  0xeeddcc00

Looking at that byte by byte, it would be:

0x7fffffffe376: dd
0x7fffffffe377: cc
0x7fffffffe378: bb
0x7fffffffe379: aa

0x7fffffffe37a: 00  # This NUL terminates argv[1]
0x7fffffffe37b: cc  # This address corresponds to argv[2]
0x7fffffffe37c: dd
0x7fffffffe37d: ee

Which is not unexpected, no?

You might want to use something like this to display arguments in hex:

x/8bx argv[1]

(which will show 8 bytes in hexadecimal)

5 Comments

thanks for pointing out the mistake, was mistakenly ignoring the NUL-terminator.
In case the run command is following: run $(perl -e 'print "\xaa\xbb\x00\xcc"') $(perl -e 'print "\xaa\xbb\xcc\x00"') $(perl -e 'print "\xaa\x00\xdd\xcc"') the expected result on x/15xb argv[1] is: 0xaa 0xbb 0x00 0xcc 0x00 0xaa 0xbb 0xcc 0x00 0x00 0xaa 0x00 0xdd 0xcc 0x00 in which the 5th, 10th and 15th 0x00 should belong to null terminator but the actual output is: 0xaa 0xbb 0xcc 0x00 0xaa 0xbb 0xcc 0x00 0xaa 0xdd 0xcc 0x00 0x58 0x44 0x47 in which it seems that 0x00 of the input has been ignored, only 0x00 corresponding to null-terminator has been considered. Any explanation??
@aniliitb10: bash strings cannot contain NULs. Or, more accurately, bash strings are always terminated with a NUL. So the result of $(printf '\xaa\xbb\x00\xcc') (which is the same as your perl print statement) is effectively a NUL-terminated string of two characters, \xaa\xbb.
no, output shows that it is effectively a string of three characters, \xaa\xbb\xcc terminated with a NUL character. Can it just skip \x00 and proceed again to print \xcc as it did in $(perl -e 'print "\xaa\xbb\x00\xcc" ') ??
@aniliitb10: Interesting. You're right, bash removes the NULs from the string, rather than terminating the string when it hits one. I stand corrected. But either way, bash strings cannot contain NUL characters.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.