понедельник, 28 февраля 2011 г.

Синтетические символы: делаем дизассемблер WinDbg дружелюбнее

Многие не любят использовать WinDbg для отладки "чужих" модулей, (т.е. тех, к которым нет символов) из-за его не самого дружелюбного дизассемблера. Простой пример это отображение импортов. Например, имеем небольшую функцию:
0:000> uf 00401090
00401090 51 push ecx
00401091 56 push esi
00401092 8b742410 mov esi,dword ptr [esp+10h]
00401096 6a00 push 0
00401098 6a00 push 0
0040109a 8d44240c lea eax,[esp+0Ch]
0040109e 50 push eax
0040109f 6800040000 push 400h
004010a4 56 push esi
004010a5 6a00 push 0
004010a7 6800110000 push 1100h
004010ac ff1510c04000 call dword ptr [image+0xc010 (0040c010)]
004010b2 8b4c2404 mov ecx,dword ptr [esp+4]
004010b6 8b54240c mov edx,dword ptr [esp+0Ch]
004010ba 51 push ecx
004010bb 56 push esi
004010bc 52 push edx
004010bd 6824c24000 push offset image+0xc224 (0040c224)
004010c2 6a10 push 10h
004010c4 68fcc14000 push offset image+0xc1fc (0040c1fc)
004010c9 e832ffffff call image+0x1000 (00401000)
004010ce 8b44241c mov eax,dword ptr [esp+1Ch]
004010d2 83c418 add esp,18h
004010d5 50 push eax
004010d6 ff1514c04000 call dword ptr [image+0xc014 (0040c014)]
004010dc 5e pop esi
004010dd 59 pop ecx
004010de c3 ret

Так мы ее видим в статике дизассемблера WinDbg. Но стоит дойти до адреса 004010ac, как WinDbg вычислит значение по адресу 0040c010 и выведет следующую строку:
call dword ptr [image+0xc010 (0040c010) ds:0023:0040c010={kernel32!FormatMessageW (77e4f831)]
На самом деле, по адресу 0040c010 расположен элемент IAT (директория импортов PE). При этом логика WinDbg ясна: значение по адресу 0040c010 может измениться, поэтому он и не вычисляет значение содержимого IAT при статическом дизассемблировании. Но если мы уверены, что содержимое таблицы импорта уже сформировано, то было бы неплохо добавить символы на обращения по этим адресам.
Для подобного рода задач в Debugger Engine расширений WinDbg введено понятие синтетических символов (Synthetic Symbols). Фактически, это символ, добавленный пользователем по заданному виртуальному адресу. Синтетический символ, как и любой другой символ модуля, имеет атрибуты имени и размера. Смысл атрибута имени очевиден, а размер символа нужен для формирования символов вида: module!SymName+33. Важная особенность: при перезагрузке символов для модуля (reload), все добавленные синтетические символы удаляются.
Для добавления синтетического имени в расширении pykd есть 2-а пути:
  • Функция addSynSymbol(адрес_символа, размер_символа, имя_символа)
  • Метод addSynSymbol(смещение_символа, размер_символа, имя_символа) класса dbgModuleClass
Добавление синтетического символа через метод addSynSymbol касса dbgModuleClass отличается только тем, что в качестве адреса необходимо передать смещение относительно начала модуля.
А теперь вернемся к примеру функции, дизассемблерный листинг которой был приведен ранее. Для демонстрации работы запустим скрипт ~\samples\synimp.py, который принимает на вход адрес внутри модуля. Скрипт, для указанного модуля, добавляет импорты, как синтетические символы с префиксом "_imp_". После работы скрипта функция выглядит намного понятнее и о ее назначении можно догадаться без трассировки:
0:000> uf 00401090
00401090 51 push ecx
00401091 56 push esi
00401092 8b742410 mov esi,dword ptr [esp+10h]
00401096 6a00 push 0
00401098 6a00 push 0
0040109a 8d44240c lea eax,[esp+0Ch]
0040109e 50 push eax
0040109f 6800040000 push 400h
004010a4 56 push esi
004010a5 6a00 push 0
004010a7 6800110000 push 1100h
004010ac ff1510c04000 call dword ptr [image!_imp_kernel32!FormatMessageW (0040c010)]
004010b2 8b4c2404 mov ecx,dword ptr [esp+4]
004010b6 8b54240c mov edx,dword ptr [esp+0Ch]
004010ba 51 push ecx
004010bb 56 push esi
004010bc 52 push edx
004010bd 6824c24000 push offset image+0xc224 (0040c224)
004010c2 6a10 push 10h
004010c4 68fcc14000 push offset image+0xc1fc (0040c1fc)
004010c9 e832ffffff call image+0x1000 (00401000)
004010ce 8b44241c mov eax,dword ptr [esp+1Ch]
004010d2 83c418 add esp,18h
004010d5 50 push eax
004010d6 ff1514c04000 call dword ptr [image!_imp_kernel32!LocalFree (0040c014)]
004010dc 5e pop esi
004010dd 59 pop ecx
004010de c3 ret

Стоит обратить внимание, что функционал синтетических символов будет включен в сборку pykd с версии 0.0.16

Комментариев нет:

Отправить комментарий