Поделиться через


Сопоставление символов при выгрузке PEB в память

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

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

Заметка Это влияет на файлы символов только для модулей пользовательского режима. Модули и символы в режиме ядра не затрагиваются, так как они отслеживаются в другом списке.

Предположим, что модуль пользовательского режима сопоставляется с текущим процессом и вы хотите исправить символы для него. Найдите любой адрес в диапазоне виртуальных адресов модуля. Например, предположим, что модуль сопоставляется с диапазоном виртуальных адресов, содержащим адрес 7f78e9e00F. Введите следующую команду.

3: kd> !vad 7f78e9e000F 1

Выходные данные команды отображают сведения о дескрипторе виртуального адреса (VAD) для модуля. Выходные данные команды также включают в себя командную строку перезагрузки, которую можно использовать для загрузки символов модуля. Командная строка перезагрузки включает начальный адрес (000007f7'8e9e00000) и размер модуля блокнота (32000).

VAD @ fffffa80056fb960
...
Reload command: .reload notepad.exe=000007f7`8e9e0000,32000

Чтобы загрузить символы, введите команду, указанную в командной строке перезагрузки.

.reload notepad.exe=000007f7`8e9e0000,32000

Ниже приведен еще один пример, использующий немного другой метод. В примере показано, как использовать расширение !vad для сопоставления символов в случае выгрузки PEB. Основная идея заключается в том, чтобы найти начальный адрес и размер соответствующей библиотеки DLL, чтобы затем можно было использовать команду .reload для загрузки необходимых символов. Предположим, что адрес текущего процесса — 0xE0000126`01BA0AF0, и вы хотите исправить символы для него. Сначала используйте команду !process , чтобы получить корневой адрес дескриптора виртуального адреса (VAD):

kd> !process e000012601ba0af0 1
PROCESS e000012601ba0af0
    SessionId: 2  Cid: 0b50    Peb: 6fbfffde000  ParentCid: 0efc
    DirBase: 079e8461  ObjectTable: e000000600fbceb0  HandleCount: 360.
    Image: explorer.exe
    VadRoot e000012601a35e70 Vads 201 Clone 0 Private 917. Modified 2198. Locked 0.
...

Затем используйте расширение !vad для перечисления дерева VAD, связанного с процессом. Эти VAD, помеченные "EXECUTE_WRITECOPY", принадлежат модулям кода.

kd> !vad e000012601a35e70
VAD     level      start      end    commit
...
e0000126019f9790 ( 6)      3fff0    3fff7        -1 Private      READONLY
e000012601be1080 ( 7)   37d9bd30 37d9bd3e         2 Mapped  Exe  EXECUTE_WRITECOPY  <-- these are DLLs
e000012600acd970 ( 5)   37d9bec0 37d9bece         2 Mapped  Exe  EXECUTE_WRITECOPY
e000012601a5cba0 ( 7)   37d9c910 37d9c924         2 Mapped  Exe  EXECUTE_WRITECOPY
...

Затем используйте расширение !vad еще раз, чтобы найти начальный адрес и размер выгруженной памяти, которая содержит интересующую библиотеку DLL. Это подтверждает, что вы нашли правильную библиотеку DLL:

kd> !vad e000012601be1080 1

VAD @ e000012601be1080
  Start VPN:      37d9bd30  End VPN: 37d9bd3e  Control Area:  e00001260197b8d0
  First ProtoPte: e0000006013e00a0  Last PTE fffffffffffffffc  Commit Charge         2 (2.)
  Secured.Flink          0  Blink           0  Banked/Extend:        0
  File Offset   0
   ImageMap ViewShare EXECUTE_WRITECOPY

...
        File: \Windows\System32\ExplorerFrame.dll

Поле "Пуск VPN" (в данном случае 0x37D9BD30) указывает начальный номер виртуальной страницы. Это необходимо преобразовать в фактический адрес, умножив его на размер страницы. Вы можете использовать команду ? (Вычислять выражение), чтобы умножить это значение на 0x2000, которая является размером страницы для компьютера на основе Itanium, из которого получен пример.

kd> ? 37d9bd3e*2000 
Evaluate expression: 7676040298496 = 000006fb`37a7c000

Затем размер диапазона можно преобразовать в байты:

kd> ? 37d9bd3e-37d9bd30+1 <--   computes the number of pages
Evaluate expression: 15 = 00000000`0000000f
kd> ? f*2000
Evaluate expression: 122880 = 00000000`0001e000        

Поэтому ExplorerFrame.dll начинается с адреса 0x000006Fb, 37A7C000 и составляет 0x1E000 байт. Вы можете загрузить его символы с помощью:

kd> .reload /f ExplorerFrame.dll=6fb`37a7c000,1e000