scanf 未考虑 0x09-0x0d

逆向工程 拆卸 记忆 扫描
2021-06-29 08:07:20

我遇到了一些我无法解释的事情。这是问题所在

#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

正如你所看到的,有 myABCDE后跟空字节0x00\x0b不会出现。我不明白为什么 scanf 没有考虑到它。这同样适用于0x090x0c但是0x01to 0x08,0x0e及以上都在工作。我有点失落。

任何的想法 ?

非常感谢。

PS:我在这里发帖的原因是因为我在一个二进制文件前面,当我向他发送字节时0x0b,它的行为不是我所期望的。我颠倒了它的一部分,发现 scanf 是这里的坏人......但是如果你认为这不适合这个论坛,告诉我我会把它移到更合适的地方。谢谢 !

2个回答

scanf函数跳过前导空格,空格是isspace宏/函数返回true的字符集

在标准语言环境中,这组字符由\t(0x09)、\n(0x0a)、\v(0x0b)、\f(0x0c) 和\r(0x0d) 组成。当然,还有空白字符 (0x20)。

有一个在另一个有趣的地方scanf图书馆呼叫处理时\x09~\0xd

您只需放在\x0b输入字符串的开头即可。如果你只是放在\x0b字符串的中间,并且从 head 到 first 有有效的 ascii(不在 \x09~\x0d 中)\x0b,比如

AAAAAA\x0bBBBBB

如果你再次执行你的程序,你会发现下面的Bs 会被放弃,或者输入的字符串会被第二个有效的\x0b.