3

I've encountered something I can't explain. Here is the problem

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void ask()
{
    char name[64];
    printf("What is your name ? ");
    scanf("%s",name);
    printf("Hi %s\n", name);
}

int main(int argc, char* argv[])
{
    ask();
    return 0;
}

Here is disassembled version :

gdb$ disas ask
Dump of assembler code for function ask:
   0x0804846c <+0>: push   ebp
   0x0804846d <+1>: mov    ebp,esp
   0x0804846f <+3>: sub    esp,0x58
   0x08048472 <+6>: mov    DWORD PTR [esp],0x8048550
   0x08048479 <+13>:    call   0x8048340 <printf@plt>
   0x0804847e <+18>:    lea    eax,[ebp-0x48]
   0x08048481 <+21>:    mov    DWORD PTR [esp+0x4],eax
   0x08048485 <+25>:    mov    DWORD PTR [esp],0x8048565
   0x0804848c <+32>:    call   0x8048370 <__isoc99_scanf@plt>
   0x08048491 <+37>:    lea    eax,[ebp-0x48]
   0x08048494 <+40>:    mov    DWORD PTR [esp+0x4],eax
   0x08048498 <+44>:    mov    DWORD PTR [esp],0x8048568
   0x0804849f <+51>:    call   0x8048340 <printf@plt>
   0x080484a4 <+56>:    leave  
   0x080484a5 <+57>:    ret    
End of assembler dump.

When I run it into gdb, I break on the scanf instruction to get buffer address (2nd on the stack), then I execute scanf instruction, and examine buffer address : No trace of my 0x0b

(gdb) r < <(perl -e 'print "\x0bABCDE"')
--------------------------------------------------------------------------[regs]
  EAX: 0x00000001  EBX: 0xB7FCDFF4  ECX: 0x00000001  EDX: 0xB7FCF354  o d I t s Z a P c 
  ESI: 0x00000000  EDI: 0x00000000  EBP: 0xBFFFF378  ESP: 0xBFFFF320  EIP: 0x08048491
  CS: 0023  DS: 002B  ES: 002B  FS: 0000  GS: 0063  SS: 002B
--------------------------------------------------------------------------[code]
=> 0x8048491 <ask+37>:  lea    eax,[ebp-0x48]
   0x8048494 <ask+40>:  mov    DWORD PTR [esp+0x4],eax
   0x8048498 <ask+44>:  mov    DWORD PTR [esp],0x8048568
   0x804849f <ask+51>:  call   0x8048340 <printf@plt>
   0x80484a4 <ask+56>:  leave  
   0x80484a5 <ask+57>:  ret    
   0x80484a6 <main>: push   ebp
   0x80484a7 <main+1>:  mov    ebp,esp
--------------------------------------------------------------------------------

Breakpoint 1, 0x08048491 in ask ()
gdb$ x/4xw 0xbffff330
0xbffff330: 0x44434241  0xb7e90045  0x0000002f  0xb7fcdff4

As you can see, there is my ABCDE followed by null byte 0x00 but \x0b won't appear. I don't understand why it's not taken into account by scanf. Same goes for 0x09 to 0x0c. But 0x01 to 0x08, 0x0e and above are working. I'm a bit lost.

Any idea ?

Thanks a lot.

PS : Reason I'm posting here is because I was in front of a binary, and when I sent him bytes like 0x0b, its behavior wasn't what I expected. I reversed part of it and found that scanf was the bad guy here ... But if you think this is not appropriate for this forum, just tell me I'll move it wherever is more appropriate. Thanks !

2 Answers 2

5

The scanf function skips over leading whitespace, with whitespace being the set of characters for which the isspace macro/function returns true.

In the standard locale, this set of characters consists of \t (0x09), \n (0x0a), \v (0x0b), \f (0x0c), and \r (0x0d). And, of course, the blank character (0x20).

1
  • Who, thanks for this ! I wouldn't have guessed. Perfect !
    – Hackndo
    Aug 10, 2015 at 9:55
1

There is another interesting place in scanf library call when handling \x09~\0xd.

You just only put \x0b at the head of input string. If you just put \x0b in the middle of string, and there are valid ascii(not in \x09~\x0d) from head to the first \x0b, like

AAAAAA\x0bBBBBB

If you execute your program again, you will find the following Bs will be abandoned or the input string will be truncated by the second valid \x0b.

Your Answer

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

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