繁体   English   中英

为什么 printf 没有打印出这个缓冲区溢出中的字符串?

[英]Why didn't printf print out the string in this buffer overflow?

我正在学习缓冲区溢出。 我写了一个小C程序:

#include<stdio.h>
#include<string.h>
void vuln();
void win();
void main(int argc, char *argv[]){
        vuln();

}
void win (){
        printf("Pwned!!");
}
void vuln(){
        char buffer[256];
        printf("Enter a string: ");
        scanf(" %s", buffer);
}

vuln function的拆解:

gef➤  disas vuln
Dump of assembler code for function vuln:
   0x0000555555555179 <+0>:     push   rbp
   0x000055555555517a <+1>:     mov    rbp,rsp
   0x000055555555517d <+4>:     sub    rsp,0x100
   0x0000555555555184 <+11>:    lea    rdi,[rip+0xe81]        # 0x55555555600c
   0x000055555555518b <+18>:    mov    eax,0x0
   0x0000555555555190 <+23>:    call   0x555555555030 <printf@plt>
   0x0000555555555195 <+28>:    lea    rax,[rbp-0x100]
   0x000055555555519c <+35>:    mov    rsi,rax
   0x000055555555519f <+38>:    lea    rdi,[rip+0xe77]        # 0x55555555601d
   0x00005555555551a6 <+45>:    mov    eax,0x0
   0x00005555555551ab <+50>:    call   0x555555555040 <__isoc99_scanf@plt>
   0x00005555555551b0 <+55>:    nop
   0x00005555555551b1 <+56>:    leave  
   0x00005555555551b2 <+57>:    ret    
End of assembler dump.

我设法通过使用有效载荷来win

>>> payload = "A"264 + p64(0x0000555555555161)

问题是它没有打印出 function win中的字符串。 我得到的只是分段错误。 这是我得到的:

Program received signal SIGSEGV, Segmentation fault.
0x00007fffffffe158 in ?? ()
[ Legend: Modified register | Code | Heap | Stack | String ]
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax   : 0x7               
$rbx   : 0x0               
$rcx   : 0x0               
$rdx   : 0x0               
$rsp   : 0x00007fffffffe068  →  0x0000000200000000
$rbp   : 0x4141414141414141 ("AAAAAAAA"?)
$rsi   : 0x656e7750        
$rdi   : 0x00005555555592a0  →  "Pwned!! string: "
$rip   : 0x00007fffffffe158  →  0x00007fffffffe436  →  "/media/sf_Code/asm/vuln"
$r8    : 0x00007ffff7fb9500  →  0x00007ffff7fb9500  →  [loop detected]
$r9    : 0x7               
$r10   : 0x0000555555556004  →  0x00212164656e7750 ("Pwned!!"?)
$r11   : 0x246             
$r12   : 0x0000555555555060  →  <_start+0> xor ebp, ebp
$r13   : 0x00007fffffffe150  →  0x0000000000000002
$r14   : 0x0               
$r15   : 0x0               
$eflags: [zero carry PARITY ADJUST sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000 
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffe068│+0x0000: 0x0000000200000000   ← $rsp
0x00007fffffffe070│+0x0008: 0x00005555555551c0  →  <__libc_csu_init+0> push r15
0x00007fffffffe078│+0x0010: 0x00007ffff7e1ebbb  →  <__libc_start_main+235> mov edi, eax
0x00007fffffffe080│+0x0018: 0x0000000000000000
0x00007fffffffe088│+0x0020: 0x00007fffffffe158  →  0x00007fffffffe436  →  "/media/sf_Code/asm/vuln"
0x00007fffffffe090│+0x0028: 0x0000000200100000
0x00007fffffffe098│+0x0030: 0x0000555555555145  →  <main+0> push rbp
0x00007fffffffe0a0│+0x0038: 0x0000000000000000
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
   0x7fffffffe152                  add    BYTE PTR [rax], al
   0x7fffffffe154                  add    BYTE PTR [rax], al
   0x7fffffffe156                  add    BYTE PTR [rax], al
 → 0x7fffffffe158                  ss     in  al, 0xff
   0x7fffffffe15b                  (bad)  
   0x7fffffffe15c                  (bad)  
   0x7fffffffe15d                  jg     0x7fffffffe15f
   0x7fffffffe15f                  add    BYTE PTR [rsi-0x1c], cl
   0x7fffffffe162                  (bad)  
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "vuln", stopped 0x7fffffffe158 in ?? (), reason: SIGSEGV
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x7fffffffe158 → ss in  al, 0xff

printf没有打印出字符串?

stdout 默认为行缓冲,字符串不以换行符结尾。 如果您将其更改为puts("Pwned;!"); 然后stdout将在puts返回之前被刷新。

但是使用printf ,数据只是坐在 stdio 缓冲区中,直到其他东西打印换行符,或者直到fflush(stdout) exit()或从main干净地返回将导致 fflush,但 segfaulting 将终止进程,而无需进行系统调用以将该 I/O 数据交给操作系统。

这与在汇编中使用 printf 导致空输出完全相同的问题,除了这种情况是使用_exit(2)系统调用而不是段错误。


如果目标是强制您在不中断后续执行的情况下调用win() ,那么这是另一个级别的挑战。

但是如果win()应该代表一个成功的 ROP 攻击,它调用system()execve"/bin/sh" ,那么win()写得不好。 execve将在现场发生,而不是稍后发生。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM