2013-05-18 3 views
1

Я работал над лабораторией bufbomb от CSAPPS, и я застрял на одной из фаз.Поиск начального адреса массива

Я не буду вдаваться в детали gore-y проекта, так как мне просто нужно подтолкнуть в правильном направлении. Мне трудно найти начальный адрес массива, называемый «buf» в данной сборке.

Мы дали функцию под названием getbuf:

#define NORMAL_BUFFER_SIZE 32 

int getbuf() 
{ 
    char buf[NORMAL_BUFFER_SIZE]; 
    Gets(buf); 
    return 1; 
} 

И сборка отвалов:

Dump of assembler code for function getbuf: 
0x08048d92 <+0>: sub $0x3c,%esp 
0x08048d95 <+3>: lea 0x10(%esp),%eax 
0x08048d99 <+7>: mov %eax,(%esp) 
0x08048d9c <+10>: call 0x8048c66 <Gets> 
0x08048da1 <+15>: mov $0x1,%eax 
0x08048da6 <+20>: add $0x3c,%esp 
0x08048da9 <+23>: ret 
End of assembler dump. 


Dump of assembler code for function Gets: 
0x08048c66 <+0>: push %ebp 
0x08048c67 <+1>: push %edi 
0x08048c68 <+2>: push %esi 
0x08048c69 <+3>: push %ebx 
0x08048c6a <+4>: sub $0x1c,%esp 
0x08048c6d <+7>: mov 0x30(%esp),%esi 
0x08048c71 <+11>: movl $0x0,0x804e100 
0x08048c7b <+21>: mov %esi,%ebx 
0x08048c7d <+23>: jmp 0x8048ccf <Gets+105> 
0x08048c7f <+25>: mov %eax,%ebp 
0x08048c81 <+27>: mov %al,(%ebx) 
0x08048c83 <+29>: add $0x1,%ebx 
0x08048c86 <+32>: mov 0x804e100,%eax 
0x08048c8b <+37>: cmp $0x3ff,%eax 
0x08048c90 <+42>: jg  0x8048ccf <Gets+105> 
0x08048c92 <+44>: lea (%eax,%eax,2),%edx 
0x08048c95 <+47>: mov %ebp,%ecx 
0x08048c97 <+49>: sar $0x4,%cl 
0x08048c9a <+52>: mov %ecx,%edi 
0x08048c9c <+54>: and $0xf,%edi 
0x08048c9f <+57>: movzbl 0x804a478(%edi),%edi 
0x08048ca6 <+64>: mov %edi,%ecx 
---Type <return> to continue, or q <return> to quit--- 
0x08048ca8 <+66>: mov %cl,0x804e140(%edx) 
0x08048cae <+72>: mov %ebp,%ecx 
0x08048cb0 <+74>: and $0xf,%ecx 
0x08048cb3 <+77>: movzbl 0x804a478(%ecx),%ecx 
0x08048cba <+84>: mov %cl,0x804e141(%edx) 
0x08048cc0 <+90>: movb $0x20,0x804e142(%edx) 
0x08048cc7 <+97>: add $0x1,%eax 
0x08048cca <+100>: mov %eax,0x804e100 
0x08048ccf <+105>: mov 0x804e110,%eax 
0x08048cd4 <+110>: mov %eax,(%esp) 
0x08048cd7 <+113>: call 0x8048820 <[email protected]> 
0x08048cdc <+118>: cmp $0xffffffff,%eax 
0x08048cdf <+121>: je  0x8048ce6 <Gets+128> 
0x08048ce1 <+123>: cmp $0xa,%eax 
0x08048ce4 <+126>: jne 0x8048c7f <Gets+25> 
0x08048ce6 <+128>: movb $0x0,(%ebx) 
0x08048ce9 <+131>: mov 0x804e100,%eax 
0x08048cee <+136>: movb $0x0,0x804e140(%eax,%eax,2) 
0x08048cf6 <+144>: mov %esi,%eax 
0x08048cf8 <+146>: add $0x1c,%esp 
0x08048cfb <+149>: pop %ebx 
0x08048cfc <+150>: pop %esi 
0x08048cfd <+151>: pop %edi 
---Type <return> to continue, or q <return> to quit--- 
0x08048cfe <+152>: pop %ebp 
0x08048cff <+153>: ret 
End of assembler dump. 

У меня трудное время, определяя местонахождение, где начальный адрес BUF является (или где buf вообще в этом беспорядке!). Если бы кто-то мог указать на это, я был бы очень признателен.

Попытка раствора

Reading symbols from /home/user/CS247/buflab/buflab-handout/bufbomb...(no debugging symbols found)...done. 
(gdb) break getbuf 
Breakpoint 1 at 0x8048d92 
(gdb) run -u user < firecracker-exploit.bin 
Starting program: /home/user/CS247/buflab/buflab-handout/bufbomb -u user < firecracker-exploit.bin 
Userid: ... 
Cookie: ... 

Breakpoint 1, 0x08048d92 in getbuf() 
(gdb) print buf 
No symbol table is loaded. Use the "file" command. 
(gdb) 

ответ

2

Как было отмечено некоторыми другими людьми, buf выделяется в стек во время выполнения.Смотрите эти строки в функции getbuf():

0x08048d92 <+0>: sub $0x3c,%esp 
0x08048d95 <+3>: lea 0x10(%esp),%eax 
0x08048d99 <+7>: mov %eax,(%esp) 

Первая строка вычитает 0x3c (60) байты из указателя стека, эффективно выделять так много места. Дополнительные байты за пределами 32, вероятно, для параметров для Gets (его трудно сказать, что соглашение о вызове для Gets точно, поэтому его трудно сказать). Вторая строка получает адрес из 16 байтов. Это оставляет 44 байта выше него, которые нераспределены. Третья строка помещает этот адрес в стек, вероятно, для вызова функции функции. (помните, что стек растет, поэтому указатель стека будет указывать на последний элемент в стеке). Я не уверен, почему компилятор создал такие странные смещения (60 байт, а затем 44), но, вероятно, есть веская причина. Если я это выясню, я уточню здесь.

Внутри получает функцию мы имеем следующие строки:

0x08048c66 <+0>: push %ebp 
0x08048c67 <+1>: push %edi 
0x08048c68 <+2>: push %esi 
0x08048c69 <+3>: push %ebx 
0x08048c6a <+4>: sub $0x1c,%esp 
0x08048c6d <+7>: mov 0x30(%esp),%esi 

Здесь мы видим, что сохранить состояние некоторых из регистров, которые добавляют до 16 байт, а затем получает резервы 28 (0x1c) байтов в стеке. Последняя строка ключевая: она захватывает значение в 0x30 байт по стеку и загружает его в% esi. Это значение является адресом buf, помещенным в стек getbuf. Зачем? 4 для возврата addres плюс 16 для регистров + 28 зарезервированных = 48. 0x30 = 48, поэтому он захватывает последний элемент, помещенный в стек getbuf(), до вызова get.

Чтобы получить адрес buf, вы должны фактически запустить программу в отладчике, потому что адрес, вероятно, будет отличаться при каждом запуске программы или даже вызове функцию в этом отношении. Вы можете установить точку прерывания в любой из этих строк выше и либо сбросить регистр% eax, когда он содержит адрес, который будет помещен в стек во второй строке getbuf, либо сбросить регистр% esi, когда он снят с стек. Это будет указатель на ваш буфер.

+0

Большое вам спасибо! Я очень благодарен вам за то, что вы прошли через логику того, как вы пришли к своему заключению, - это очень поможет мне при выполнении следующих двух этапов задания. –

+0

Не проблема. Прокомментируйте, если у вас есть дополнительные вопросы. – Dougvj

0

buf выделяется в стеке. Таким образом, вы не сможете определить свой адрес из списка сборок. Другими словами, buf выделяется (и поэтому его адрес известен) только при вводе функции getbuf() во время выполнения.

Если вы должны знать адрес, один из вариантов было бы использовать GBD (но убедитесь, что вы собираете с -g флаг, чтобы включить поддержку отладки), а затем:

gdb a.out # I'm assuming your binary is a.out 
break getbuf # Set a breakpoint where you want gdb to stop 
run   # Run the program. Supply args if you need to 
      # WAIT FOR your program to reach getbuf and stop  
print buf 

Если вы хотите идти по этому пути , необходим хороший учебник gdb (example). Вы также можете разместить printf внутри getbuf и отладить этот путь - это зависит от того, что вы пытаетесь сделать.

Еще один пункт выскочит из вашего кода. По возвращении с getbuf результат Gets будет разорван. Это связано с тем, что Gets предположительно записывает свои результаты в выделенную стекю buf. Когда вы вернетесь с getbuf, ваш стек сдувается, и вы не можете надежно получить доступ к buf.

+0

Я пробовал это, и я получил «Таблица символов не загружена. Используйте команду« файл »из GDB (и да, файл открыт и запущен в GDB, когда я это делаю). * Sidenote: Это странное поведение, о котором вы говорили, намеренно. Весь смысл назначения - ввести код эксплойта, чтобы программа немного перескочила, чтобы пройти через эти избыточные строки кода. –

+0

отредактировал ответ, чтобы предложить, как вы должны использовать gdb! –

+0

Сделал именно это, но я все еще получаю это сообщение. Я обновил свой оригинальный пост, чтобы показать свою попытку. –

0

Чтобы увидеть информацию об отладке при использовании gdb, вы должны использовать ключ -g3 с gcc, когда вы скомпилируете man.cse man gcc для получения более подробной информации о переключателе -g. Только тогда gcc добавит информацию об отладке (таблицу символов) в исполняемый файл.

0
0x08048cd4 <+110>: mov %eax,(%esp) 
0x08048cd7 <+113>: **call 0x8048820 <[email protected]>** 
0x08048cdc <+118>: cmp $0xffffffff,%eax 
0x0848cdf <+121>: je  0x8048ce6 <Gets+128> 
0x08048ce1 <+123>: cmp $0xa,%eax 
0x08048ce4 <+126>: jne 0x8048c7f <Gets+25> 
0x08048ce6 <+128>: movb $0x0,(%ebx) 
0x08048ce9 <+131>: mov 0x804e100,%eax 
0x08048cee <+136>: movb $0x0,0x804e140(%eax,%eax,2) 
0x08048cf6 <+144>: mov %esi,%eax 
0x08048cf8 <+146>: add $0x1c,%esp 
0x08048cfb <+149>: **pop %ebx** 
0x08048cfc <+150>: **pop %esi** 
0x08048cfd <+151>: **pop %edi** 
---Type <return> to continue, or q <return> to quit--- 
0x08048cfe <+152>: **pop %ebp** 
0x08048cff <+153>: ret 
End of assembler dump. 

Я не знаю, ваш вкус ассемблера, но есть вызов там, который может использовать начальный адрес

В конце программы выскакивают различные указатели

Вот где я хотел бы начать глядя

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

Смежные вопросы