#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;
}
这里是反汇编的版本:
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.
当我将其运行到gdb中时,我中断scanf指令以获取缓冲区地址(堆栈中的第二个地址),然后执行scanf指令,并检查缓冲区地址:
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
如您所见,存在我的
ABCDE
,后跟空字节0x00
,但不会出现\x0b
。我不明白为什么scanf不考虑它。 0x09
至0x0c
也是如此。但是0x01
至0x08
,0x0e
及更高版本正在运行。我有点迷茫。有什么主意吗?
非常感谢。
PS:之所以在这里发布是因为我当时在二进制文件前面,当我向他发送
0x0b
之类的字节时,其行为不是我所期望的。我撤消了部分讨论,发现scanf在这里是坏人……但是,如果您认为这不适用于本论坛,请告诉我,我会将其移至更合适的位置。谢谢!#1 楼
scanf
函数会跳过前导空格,而空格是isspace
宏/函数为其返回true的字符集。在标准语言环境中,该字符集由
\t
(0x09),\n
(0x0a),\v
(0x0b),\f
(0x0c)和\r
(0x0d)。当然还有空白字符(0x20)。#2 楼
处理scanf
时,在\x09~\x0b
xd
库调用中还有一个有趣的地方。您只需将
\x0b
放在输入字符串的开头。如果只是将\x0b
放在字符串的中间,并且从头到第一个AAAAAA\x0bBBBBB
都有有效的ascii(不在\ x09〜\ x0d中),例如B
如果再次执行程序,则会发现以下
\x0b
将被放弃,或者输入字符串将被第二个有效的q4312079q截断。
评论
谁,为此感谢!我不会猜到的。太好了!
– Hackndo
15年8月10日在9:55