Атака переполнения буфера - PullRequest
       3

Атака переполнения буфера

19 голосов
/ 08 сентября 2011

Я пытаюсь выполнить очень простую атаку переполнения буфера.Я новичок в этом.Итак, если этот вопрос глуп, пожалуйста, извините: -)

Код:

#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 () из жертвы_func (), переполнив там буфер и переписав адрес возврата на адрес confused ().И я хочу вернуться из confused () в оператор printf () в main и выйти нормально.Итак, я предоставляю следующий ввод

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)

Несмотря на то, что программа выводит «Done» из этого оператора printf, она возвращает обратно к жертве_func () и печатает «Enter n:»

Что я делаю неправильно?Любая помощь будет принята с благодарностью!

PS: Я не уверен, правильно ли я сформулировал вопрос.Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

Ответы [ 4 ]

9 голосов
/ 08 сентября 2011

Атака переполнения буфера намного сложнее, чем эта. Прежде всего вам нужно понять ассемблер, чтобы выполнить это. После того, как вы разберете программу и функцию, на которую вы хотите нацелиться, вам нужно определить макет стека, когда он выполняет эту функцию. Вот пример переполнения буфера, который использует 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 in1 расположена раньше, чем функция сохранила указатель кадра стека. Значение после этого является адресом возврата, на который должна перейти функция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 

Из этого можно сделать вывод, что если мы перезаписываем [7] с другим адресом, функция вернется не к основному, а с любым адресом, который мы написали в [7].

Надеюсь, это поможет.

2 голосов
/ 12 сентября 2014

Теперь я хочу перейти к функции confused () из жертвы_функции (), переполнив там буфер и переписав адрес возврата на адрес confused () ...

На современных платформах Linux вам также необходимо убедиться, что две функции безопасности отключены для тестирования. Первый в NX-стеках, а второй - в стековых протекторах.

Чтобы отключить NX-стеки, используйте -Wl,z,execstack (вместо -Wl,z,noexecstack). Чтобы отключить защиту стека, используйте -fno-stack-protector (в отличие от -fstack-protector или -fstack-protector-all).

Есть третья защита, которую вам может потребоваться отключить. Эта защита FORTIFY_SOURCE. FORTIFY_SOURCE использует «более безопасные» варианты функций высокого риска, такие как memcpy и strcpy. Компилятор использует более безопасные варианты, когда он может определить размер буфера назначения. Если копия превысит размер буфера назначения, программа вызывает abort(). Чтобы отключить FORTIFY_SOURCE, скомпилируйте программу с помощью -U_FORTIFY_SOURCE или -D_FORTIFY_SOURCE=0.

Функции безопасности включены по умолчанию, потому что в прошлом было очень много проблем. В общем, это хорошо, потому что это останавливает многие проблемы (например, ту, с которой вы экспериментируете).

1 голос
/ 08 сентября 2011

Прежде всего, мне кажется, что вы не должны вводить число 5 в выборке. Ваш массив объявлен как [4], поэтому элементы имеют индекс 0-3 - поэтому ваши данные атаки кажутся мне неправильными.

Мне также кажется, что ваша программа предполагает несколько вещей об архитектуре:

  • sizof (int) == sizeof (адрес памяти)
  • Направление роста и механизм реализации стека сред

Если одно из этих предположений не соответствует действительности, оно никогда не сработает.

Это похоже на очень тяжелую работу.

Существуют более простые примеры атак переполнения буфера, чем изменение потока управления кода. Например, вы можете перезаписать другой фрагмент данных, который должен быть защищен от пользователя (например, параметр безопасности)

0 голосов
/ 08 сентября 2011

Вы не показали нам вывод программы с адресами [i]. Я подозреваю, что компилятор делает что-то вроде выравнивания данных в стеке до 16. Это может быть намного дальше к адресу возврата, чем вы ожидаете.

...