Используя 'bytes at CS: EIP', чтобы узнать, где произошел сбой - PullRequest
3 голосов
/ 02 марта 2012

Я получаю отчеты о сбоях от конечных пользователей с информацией доктора Ватсона, и я хочу использовать их, чтобы узнать, где произошел сбой (т.е. в какой строке кода).

Я не могу просто использовать EIP из отчета о сбое, потому что файл, который мы отправляем, имеет цифровую подпись, и это меняет все смещения. Однако информация о сбое также имеет «байты в CS: EIP», которые являются первыми 16 байтами, начиная с EIP, где произошел сбой. Это выглядит так:

Bytes at CS:EIP:
85 c4 14 c3 8b ff 55 8b ec 6a 0a 6a 00 ff 75 08

Эти 16 байтов встречаются в exe ровно один раз. Я могу найти их смещение в EXE, используя только средство просмотра HEX, но чтобы перейти туда во время отладки и посмотреть, какая строка находится в источнике, мне нужно знать их смещение в памяти после загрузки EXE.

Как лучше всего сканировать сегмент кода программы после ее загрузки? Могу ли я добавить код, который находит, где находится базовое смещение EXE-файла, а затем перебрать его и использовать memcmp, чтобы найти, где происходит шаблон байтов.

Кроме того, как я могу найти, где находится базовое смещение EXE?

Ответы [ 5 ]

4 голосов
/ 02 марта 2012

Я использую очень простой подход к той же проблеме.

Сначала я dumpbin мой исполняемый файл, чтобы найти физическое (в файле) смещение сегмента кода.

Затем я вычитаю его из адреса памяти, где эти "волшебные" байты находятся в двоичном файле.

Затем я запускаю программу в отладчике и просто добавляю это смещение к виртуальному адресу сегмента кода.

       .text name
  10EE8E virtual size
    1000 virtual address (00401000 to 0050FE8D)
  10F000 size of raw data

 --> 400 file pointer to raw data (00000400 to 0010F3FF) <--

       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
60000020 flags
         Code
         Execute Read
2 голосов
/ 02 марта 2012

Если вы используете что-то вроде ollydbg , вы можете сканировать их память процесса во время ее работы и сообщать вам файл: строку и исходный код при просмотре найденных точек (до тех пор, покаPDB связаны правильно).Он также позволяет просматривать виртуализированный адрес, если вы открываете файл статически.

1 голос
/ 24 ноября 2014

Все, что вам нужно сделать, это поместить ваши файлы PE (.dll и .exe) и файлы PDB на сервер символов, а затем указать отладчик (windbg или VS) на ваш сервер символов плюс сервер символов Microsoft.PE-файлы и PDB-файлы будут автоматически загружены, будет показана разборка для всех уровней стека вызовов и найдены исходные файлы.

Если ваши PE-файлы подписаны, то вы должны поставить подписанный файл.PE-файлы на вашем сервере символов, хотя, если вы поместите неподписанные файлы на своем сервере символов, они, вероятно, будут нормально загружаться (байты кода не будут затронуты), возможно, с некоторыми предупреждениями о контрольной сумме.

Для бонусных отметок вы должны запустить индексацию источникадо добавления PDB на сервер символов.Таким образом, отладчики могут получить правильную версию исходного файла из системы контроля версий - магическую.Это действительно не так сложно.Я делаю все эти шаги в своих хобби-проектах.

Ссылки из моего блога: https://randomascii.wordpress.com/2013/03/09/symbols-the-microsoft-way/ https://randomascii.wordpress.com/2011/11/11/source-indexing-is-underused-awesomeness/

Повторюсь: это должно сработать.Я просмотрел сотни аварийных дампов с компьютеров клиентов, работая во многих различных компаниях, и благодаря серверу символов и исходному серверу я получаю машинный код, имена функций, исходный код, локальные переменные и т. Д. Без усилий.

1 голос
/ 02 марта 2012

Или, если вы просто работаете с базовыми инструментами, вы можете использовать dumpbin (он же link /dump /all) из Visual Studio или SDK платформы.Он может дать вам шестнадцатеричный дамп и / или разборку со всеми примененными перемещениями, а также подберет PDB для добавления имен символов в ваши списки.Все это говорит о том, что DLL может быть перемещена на другой адрес во время загрузки из-за конфликта, но вы используете dumpbin /headers, чтобы узнать базовое смещение библиотеки по умолчанию.

Не докторУотсон дает вам значение EIP, а не только байты?Прошло много времени с тех пор, как я использовал это.Лучшее решение - подписаться на WinQual - тогда конечные пользователи смогут загружать свои аварийные дампы в Microsoft, и вы сможете собирать их оттуда, а также получать актуальные мини-дампы и дампы кучи.

0 голосов
/ 02 марта 2012

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

unsigned char buf[] = { 0x85, 0xc4, 0x14, 0xc3, 0x8b, 0xff, 0x55, 0x8b, 0xec, 0x6a, 0x0a, 0x6a, 0x00, 0xff, 0x75, 0x08  };
HMODULE hModule = GetModuleHandle(NULL);
char* ii;
for (ii = (char*) hModule; memcmp(ii, buf, sizeof(buf)); ii++);

char buf2[1000];
sprintf(buf2, "%p", ii);
MessageBox(0,buf2,0,0);
...