2011-09-08 17 views
18

非常に単純なバッファオーバーフロー攻撃を実行しようとしています。私はこれにかなり初心者です。この質問は愚かであれば、バッファオーバーフロー攻撃

:-)コードを私に言い訳してください私は、関数のアドレスを取得するためにobjdumpは使用している場合

#include<stdio.h> 
#include<stdlib.h> 

int i, n; 

void confused(int i) 
{ 
printf("**Who called me? Why am I here?? *** %x\n ", i); 
} 

void shell_call(char *c) 
{ 
printf(" ***Now calling \"%s\" shell command *** \n", c); 
system(c); 
} 

void victim_func() 
{ 
int a[4]; 
printf("Enter n: "); scanf("%d",&n); 
printf("~~~~~~~~~~~~~ values and address of n locations ~~~~~~~~~~"); 
for (i = 0;i <n ;i++) 
    printf ("\n a[%d] = %x, address = %x", i, a[i], &a[i]); 
printf("\nEnter %d HEX Values \n", n); 

// Buffer Overflow vulnerability HERE! 

for (i=0;i<n;i++) scanf("%x",&a[i]); 
    printf("Done reading junk numbers\n"); 
} 

int main() 
{ 
victim_func(); 
printf(“\n done”); 
return 0; 
} 

、私は次のようしている:

main(): 0x804854d 
Address of main() where printf() is called: 0x8048563 
victim_func(): 0x8048455 
confused(): 0x8048414 

さて、私が望むのは、bufferをオーバーフローさせ、返りアドレスをconfused()のアドレスに上書きすることによって、victim_func()から関数 'confused()'にジャンプすることです。そして、私はconfused()からmainのprintf()ステートメントに戻り、正常に終了したいと思います。

は私が何をやっている:だから、私は、printf文から、それは(バックvictim_funcにジャンプさ)とプリントが「nを入力」「完了」のプログラムのプリント、が、次の入力

Enter n: 7 
Enter 7 HEX values: 
1 
2 
3 
4 
5 
8048414 (This is to jump to confused) 
8048563 (this is to jump to printf() in main) 

を提供します違う?どんな助けでも大歓迎です!

PS:正しい質問をしてもわかりません。詳細が必要な場合はお知らせください。

+5

実際、これは学校での課題です! – Ashwin

+0

これが本当に宿題の場合は、そのようにタグ付けしてください。 – NPE

+7

@VJoこれは素晴らしい教育的な仕事だと思います。私はそれを自分自身で試してみたいと思っています。コードのアセンブラ実装を深く理解し、直接実験する必要があります。白い帽子もこれらのアイデアを把握する必要があります。 – Elemental

答えて

8

バッファオーバーフロー攻撃は、これよりもはるかに複雑です。まず、これを実行するためにアセンブラを理解する必要があります。ターゲットとするプログラムと関数を逆アセンブルした後、その関数を実行しているときにスタックレイアウトを決定する必要があります。 これは、Visual Studioを使用しているバッファオーバーフローのサンプルですが、原則は同じです。

#include "stdafx.h" 
#include <math.h> 

volatile double test; 

double function3() 
{ 
    test++; 
    return exp(test); 
} 

double function2() 
{ 
    return log(test); 
} 

double function1() 
{ 
    int a[5] = {0};   
    a[7] = (int)&function3; 
    return exp(function2()); 

} 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
    double a = function1(); 
    test = a; 
    return a; 
} 

逆アセンブリのおかげで、in function1は、関数がスタックフレームポインタを保存した場所の前に割り当てられています。それ以降の値は、function1が終了した場合に戻るべき戻りアドレスです。このことから

00401090 55    push  ebp <- we save the stack pointer 
00401091 8B EC   mov   ebp,esp 
00401093 83 EC 1C   sub   esp,1Ch <- save space to allocate a[5] 
00401096 B8 CC CC CC CC mov   eax,0CCCCCCCCh 
0040109B 89 45 E4   mov   dword ptr [ebp-1Ch],eax <- crt debug init a[5] 
0040109E 89 45 E8   mov   dword ptr [ebp-18h],eax 
004010A1 89 45 EC   mov   dword ptr [ebp-14h],eax 
004010A4 89 45 F0   mov   dword ptr [ebp-10h],eax 
004010A7 89 45 F4   mov   dword ptr [ebp-0Ch],eax 
004010AA 89 45 F8   mov   dword ptr [ebp-8],eax 
004010AD 89 45 FC   mov   dword ptr [ebp-4],eax 

我々は[7]別のアドレスで、機能はありませんメインに戻るが、我々は[7]で書いたものは何でもアドレスとなります上書きした場合、我々は結論付けることができます。

これが役に立ちます。

+0

患者の説明に感謝します。それは私が立ち往生している場所です!配列の5ワードを格納するために1Chワードを割り当てる必要があるのはなぜですか?ここでスタック構造を詳しく教えてください。 – Ashwin

+0

そして、これは私の分解されたメインルーチンのチャンクです。 '0x0804855b :\tサブ$の0x4の、%esp' ' 0x0804855e :\tコール0x8048455 ' ' 0x08048563 :\t MOVL $ 0x804872e、(%のESP) ' ' 0x0804856a :\tコール0x8048364 <[email protected]> ' したがって、私は0x8048563でmain()に戻ります。混乱しています。正しいメモリ位置にリターンアドレスを置くことに問題はありません。そして、main()は "Done"を印刷して再開します。しかし、この時点で、それはvictim_func()に戻り、 "Enter n:"を出力します。これはわかりません。 – Ashwin

1

まず、サンプル入力に数字5を入力しないでください。あなたの配列は[4]と宣言されており、要素のインデックスは0〜3です - あなたの攻撃入力は私にとって間違っているようです。

また、あなたのプログラムは、アーキテクチャに関するいくつかの事を想定しているように私には思える:

  • sizof(int型)==はsizeof(メモリアドレス)
  • 環境の成長機構の方向が実装スタック

これらの前提の1つが間違っていると、決してうまくいかないでしょう。

これは非常に難しい作業課題のようです。

バッファオーバーフロー攻撃の例は、コードの制御フローを変更するよりも簡単です。たとえば、ユーザーから保護されているはずの別のデータ(セキュリティ設定など)を上書きすることができます。

+2

アレイの境界を超えたインデックス作成は、そのような攻撃の仕組みを正確に示しています。そのような攻撃は常にプラットフォームに依存します。それらはスタックのレイアウト方法に依存し、一般にアセンブラを必要とします。通常の解決策は、何かをバッファに入れたマシンコードを入れ、スタックの戻りアドレスをバッファのアドレスに置き換えることです。 –

0

あなたは、[i ]。私は、コンパイラがスタック上のデータを16に整列させるようなことをしているのではないかと推測しています。

1

さて、私が欲しいのは()のアドレスに戻りアドレスがバッファをオーバーフローし、上書きしてvictim_funcから「)(混同」関数にジャンプすることです...()混同

最新のLinuxプラットフォームでは、テストのために2つのセキュリティ機能がオフになっていることを確認する必要があります。 NXスタックでは最初、スタックプロテクタでは2番目です。

NX-Stackをオフにするには、(-Wl,z,noexecstackではなく)を使用します。スタックプロテクタをオフにするには、-fstack-protectorまたは-fstack-protector-allとは対照的に、-fno-stack-protectorを使用します。

電源を切る必要がある場合があります。その保護はFORTIFY_SOURCEです。 FORTIFY_SOURCEは、memcpystrcpyのようなリスクの高い機能の「より安全な」バリアントを使用します。コンパイラは、宛先バッファサイズを推測できるときに、より安全なバリアントを使用します。コピーが宛先バッファ・サイズを超える場合、プログラムはabort()を呼び出します。 FORTIFY_SOURCEを無効にするには、プログラムを-U_FORTIFY_SOURCEまたは-D_FORTIFY_SOURCE=0でコンパイルします。

セキュリティ機能は、過去に非常に多くの問題があったため、デフォルトで有効になっています。一般的には、(実験しているような)多くの問題を止めるので、良いことです。

関連する問題