C - The %x format specifier - c

I have a small question. I know that the %x format specifier can be used to read values from the stack in a format string attack.
I found the following code:
%08x%08x%08x%08x
What does the 08 mean? What is it doing exactly? Thanks :)

Break-down:
8 says that you want to show 8 digits
0 that you want to prefix with 0's instead of just blank spaces
x that you want to print in lower-case hexadecimal.
Quick example (thanks to Grijesh Chauhan):
#include <stdio.h>
int main() {
int data = 29;
printf("%x\n", data); // just print data
printf("%0x\n", data); // just print data ('0' on its own has no effect)
printf("%8x\n", data); // print in 8 width and pad with blank spaces
printf("%08x\n", data); // print in 8 width and pad with 0's
return 0;
}
Output:
1d
1d
1d
0000001d
Also see http://www.cplusplus.com/reference/cstdio/printf/ for reference.

%08x means that every number should be printed at least 8 characters wide with filling all missing digits with zeros, e.g. for '1' output will be 00000001

The format string attack on printf you mentioned isn't specific to the "%x" formatting - in any case where printf has more formatting parameters than passed variables, it will read values from the stack that do not belong to it. You will get the same issue with %d for example.
%x is useful when you want to see those values as hex.
As explained in previous answers, %08x will produce a 8 digits hex number, padded by preceding zeros.
Using the formatting in your code example in printf, with no additional parameters:
printf ("%08x %08x %08x %08x");
Will fetch 4 parameters from the stack and display them as 8-digits padded hex numbers.

That specifies the how many digits you want it to show.
integer value or * that specifies minimum field width. The result is padded with space characters (by default), if required, on the left when right-justified, or on the right if left-justified. In the case when * is used, the width is specified by an additional argument of type int. If the value of the argument is negative, it results with the - flag specified and positive field width.

From http://en.wikipedia.org/wiki/Printf_format_string
use 0 instead of spaces to pad a field when the width option is specified. For example, printf("%2d", 3) results in " 3", while printf("%02d", 3) results in "03".

Related

What is the meaning of this format `%02hhx`?

I saw in some functions that in order to convert number to hexadecimal format, using this format: printf("%02hhx", some_char); , but I don't understand why, and what is the meaning of this format ?
Format string "%02hhx" means:
0: Results that would require less than specified field width shall be printed with leading 0s.
2: use at least 2 characters to format the value
x Print in hexadecimal format.
hh The provided parameter for x is only a char, not an int For values 0..127 it doesn't matter if you add the hh but values above could get sign extended and would be printed with lots of leading F.
The result will just be a hexadecimal value with 2 digits.

Is there an implied word size for printing negative numbers in hexadecimal?

All the following produce the same output of ffffffef:
printf("%x\n", -17);
printf("%2x\n", -17);
printf("%8x\n", -17);
Why?
%x in printf() expects an unsigned int argument. Assuming int is 32-bit, in your example, -17 is converted to 4294967279u (0xffffffef). This means the formated output is at least 8 characters, even if you are using %x or %2x.
You'll get a different result if using:
printf("%hx\n", -17); // ffef
In this example, %hx expects an unsigned short, therefore different result.
In %2x, %4x and %8x, here the numbers represent the minimum character width that will be printed. Now since ffffffef is 8 character wide, it was printed same for all three case, because the character width is >= the number specified. If the number while specifying format would be >= 8, then you will see an extra space at the beginning (this depends on how you have specified the print format).

About printf format string in C

Let's take the following program:
#include <stdio.h>
int main()
{
long t =57 ;
printf("[%+03ld]", t);
}
and it's output:
[+57]
I am somehow confused: I told him to pad the output to width 3 (03ld), with zeroes, however it seems that if I force the output to put a plus sign before the number (+) it will not add the required zeroes if the length of the number is already 2 digits (as in 57). For numbers <10 it pads with 1 zero.
From http://www.cplusplus.com/reference/cstdio/printf/
(0) -> Left-pads the number with zeroes (0) instead of spaces when padding is specified (see width sub-specifier).
(+) -> Forces to preceed the result with a plus or minus sign (+ or -) even for positive numbers. By default, only negative numbers are preceded with a - sign.
(width) -> Minimum number of characters to be printed. If the value to be printed is shorter than this number, the result is padded with blank spaces. The value is not truncated even if the result is larger.
So I just need a clarification ... The (width) specifier from the quote above refers to the full length of the output string (ie: the characters that will be printed) controlled by this format specifier ("%+03ld") or the full length of the characters of the number that is going to be printed?
Yes, the width specifier refers to the width of the entire formatted result, +57 in your case. This makes it useful for printing columnar text for easy reading on screen (important if you're using C to write an old-school text utility!).
C standard is rather precise that converted value is taken a whole. From C11 §7.21.6/2 (emphasis mine):
The fprintf function writes output to the stream pointed to by stream,
under control of the string pointed to by format that specifies how
subsequent arguments are converted for output.
along with §7.21.6/4:
An optional minimum field width. If the converted value has fewer
characters than the field width, it is padded with spaces (by default)
on the left (or right, if the left adjustment flag, described later,
has been given) to the field width. The field width
takes the form of an asterisk * (described later) or a nonnegative decimal integer.
As you quoted "Minimum number of characters to be printed.", so "+" is just another character for printf. Btw the zeros "0" are just characters aswell and have nothing to do with numbers. It could be any character.
Yes, the field width refers to the complete, converted value including decimal dots, signs etc.
You asked for a 3 characters length format and get 3 characters +57. If you want the 0 to be present, just use printf("[%+04ld]", t); and you'll get +057.

Format specifier %02x

I have a simple program :
#include <stdio.h>
int main()
{
long i = 16843009;
printf ("%02x \n" ,i);
}
I am using %02x format specifier to get 2 char output,
However, the output I am getting is:
1010101
while I am expecting it to be :01010101 .
%02x means print at least 2 digits, prepend it with 0's if there's less. In your case it's 7 digits, so you get no extra 0 in front.
Also, %x is for int, but you have a long. Try %08lx instead.
%x is a format specifier that format and output the hex value. If you are providing int or long value, it will convert it to hex value.
%02x means if your provided value is less than two digits then 0 will be prepended.
You provided value 16843009 and it has been converted to 1010101 which a hex value.
Your string is wider than your format width of 2. So there's no padding to be done.
You are actually getting the correct value out.
The way your x86 (compatible) processor stores data like this, is in Little Endian order, meaning that, the MSB is last in your output.
So, given your output:
10101010
the last two hex values 10 are the Most Significant Byte (2 hex digits = 1 byte = 8 bits (for (possibly unnecessary) clarification).
So, by reversing the memory storage order of the bytes, your value is actually: 01010101.
Hope that clears it up!

How to print a positive number as a negative number via printf

While reading about printf(),I found that it can print numbers as positive or negative as desired by the user by following code(for -).But the code doesnt work and the output is a positive value.Please mention where the error is.Thanks
#include<stdio.h>
int main()
{
printf (" %-d\n", 1977);
return 0;
}
From your comments it looks like you misread this page. The - and + specifiers do two completely different things, and neither does what you think '-' should do.
As others have noted, - does left justification. The + specifier prints positive numbers with a leading plus sign (and negative numbers still get a leading minus sign):
printf("%d %d %+d %+d\n", -10, 10, -10, 10);
outputs:
-10 10 -10 +10
printf (" -%d\n", 1977); will output -1997 (bad way to do it), if you would like negative numbers to become positive, do printf (" %d\n", -1 * 1977); (good way to do it)
read the reference for an idea of how format specifiers work
%-d Will left adjust the integer field, it won't flip the sign. Do this instead:
printf (" %d\n", -1977);
Here's the full extract from print(3) under The flag characters:
- The converted value is to be left adjusted on the field bound‐
ary. (The default is right justification.) Except for n con‐
versions, the converted value is padded on the right with
blanks, rather than on the left with blanks or zeros. A - over‐
rides a 0 if both are given.
Update0
I see your true question now: To prepend output with the appropriate sign, use the + flag character to explictly show the sign. Again here is the extract:
+ A sign (+ or -) should always be placed before a number produced
by a signed conversion. By default a sign is used only for neg‐
ative numbers. A + overrides a space if both are used.
And use it like this (The command line printf is mostly identical):
matt#stanley:~/cpfs$ printf "%+d\n" 3
+3
matt#stanley:~/cpfs$ printf "%+d\n" -3
-3
matt#stanley:~/cpfs$ printf "%+u\n" -3
18446744073709551613
Be aware that explicitly requesting the sign won't imply treatment of the corresponding integer as signed as in the %u example above.

Resources