19

非常に単純なバッファ オーバーフロー攻撃を実行しようとしています。私はこれにほとんど初心者です。したがって、この質問がばかげている場合は、すみません:-)

コード:

#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; 
}

objdump を使用して関数アドレスを取得すると、次のようになります。

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

今、私が欲しいのは、そこでバッファをオーバーフローさせ、戻りアドレスをconfused()のアドレスに上書きすることにより、victim_func()から関数「confused()」にジャンプすることです。そして、混乱した()からメインのprintf()ステートメントに戻り、正常に終了したいと思います。したがって、次の入力を提供します

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)

ただし、プログラムはその printf ステートメントから "Done" を出力しますが、victim_func() に戻って "Enter n:" を出力します。

私は何を間違っていますか?どんな助けでも大歓迎です!

PS: 質問が正しいかどうかわかりません。さらに情報が必要な場合はお知らせください。

4

4 に答える 4

9

バッファ オーバーフロー攻撃は、これよりもはるかに複雑です。これを行うには、まずアセンブラを理解する必要があります。対象とするプログラムと関数を逆アセンブルしたら、その関数を実行するときのスタック レイアウトを決定する必要があります。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;
}

逆アセンブルのおかげで、関数がスタック フレーム ポインターを保存した場所の前に、関数 1 の a が割り当てられていることがわかります。その次の値は、関数 1 が終了した場合に移動する戻りアドレスです。

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 

このことから、a[7] を別のアドレスで上書きすると、関数はメインに戻るのではなく、a[7] に書き込んだアドレスに戻ると結論付けることができます。

お役に立てれば。

于 2011-09-08T07:36:16.210 に答える
1

まず第一に、サンプル入力に数字の 5 を入力するべきではないように思えます。あなたの配列は a[4] と宣言されているため、要素には 0 ~ 3 のインデックスが付けられているため、攻撃入力は私には間違っているようです。

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

  • sizof(int)==sizeof(メモリアドレス)
  • 環境スタック実装の成長の方向性と仕組み

これらの仮定のいずれかが正しくない場合、それは決して機能しません。

これは非常に大変な仕事の割り当てのようです。

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

于 2011-09-08T07:36:23.630 に答える
0

a[i] のアドレスを使用したプログラムの出力を示していません。コンパイラは、スタック上のデータを 16 に揃えるなどの処理を行っていると思われます。予想よりもはるかに戻りアドレスが遠い可能性があります。

于 2011-09-08T07:39:02.300 に答える