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

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

Код:

#include #include 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 ("\na[%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 ()’ from victim_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) 

Хотя программа выводит «Готово» из этой инструкции printf, она перескакивает назад на victim_func () и печатает «Enter n:»

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

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

Атака переполнения буфера намного сложнее, чем эта. Прежде всего вам нужно понять ассемблер, чтобы выполнить это. После того, как вы разобрали программу и функцию, на которые вы хотите настроить таргетинг, вам нужно определить структуру стека, когда она выполняет эту функцию. Вот пример переполнения буфера, используя визуальную студию, но принцип тот же.

 #include "stdafx.h" #include  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; } 

Благодаря parsingке мы знаем, что a в функции1 выделяется до того момента, когда функция сохранила указатель фрейма стека. Значение после этого – это обратный адрес, по которому функция 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].

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

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

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

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

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

Это похоже на очень тяжелое трудовое задание.

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

Теперь я хочу перейти к функции ‘confused ()’ from victim_func (), переполнив там буфер и перезаписать обратный адрес на адрес confused () …

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

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

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

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

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