HOME FORUMS MEMBERS RECENT POSTS LOG IN  
× Авторизация
Имя пользователя:
Пароль:
Нет аккаунта? Регистрация
Баннер 1   Баннер 2
НОВЫЕ ТОРГОВАЯ НОВОСТИ ЧАТ
loading...
Скрыть
Вернуться   ANTICHAT > БЕЗОПАСНОСТЬ И УЯЗВИМОСТИ > Электроника и Фрикинг
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

  #1  
Старый 05.03.2021, 10:18
Marylin
Постоянный
Регистрация: 01.09.2019
Сообщений: 378
С нами: 3526561

Репутация: 0
По умолчанию

Одним из приоритетных направлений в разработке любого продукта является его отладка. Ведь мало написать удовлетворяющий требованиям исправно работающий код, так нужно ещё и протестить его в "токсических условиях", на предмет выявления всевозможных ошибок. Для этих целей, инженеры Microsoft включили в состав ОС полноценный механизм дебага в виде двух библиотек пользовательского режима: это Dbgeng.dll – основной движок отладки (Debug Engine), и Dbghelp.dll – вспомогательный процессор отладочных символов PDB (Program Database).

На моей Win-7, библиотека символов имеет размер 0.8 Мб и выдаёт на экспорт аж 205 стандартных API-функций, а вот вторая Dbgeng.dll в три раза тяжелее своего (со)брата с размером ~2.5 Мб, зато экспортирует с выхлопной трубы всего 3 функции. От сюда следует, что эта либа от нас явно что-то скрывает, поскольку жалкие три процедуры никак не могут весить более двух мегабайт. В данной статье мы попытаемся заглянуть внутрь отладочного движка Engine, и в качестве примера вытащим из него полноценный дизассемблер инструкций процессоров х86.

Оглавление:

1. Знакомство с системным механизмом отладки;
2. Component-Object-Model в ассемблере;
3. Структура СОМ-библиотеки Dbgeng.dll;
4. Практика – пишем дизассемблер;
5. Заключение.
---------------------------------------------------------------

1. Знакомство с механизмом отладки

Первые библиотеки отладки, так-же известные как файлы "Symbolic Debugger Engine", были созданы компанией Microsoft в 2001-году для операционной системы Windows-XP. Большая часть либы Dbghelp.dll содержит в себе функции с префиксом(Sym), что говорит об их принадлежности к символьному процессору. Они позволяют по указанному адресу вычислять имена функций, определять типы данных, а также номер строки и название файла, в котором эта строка находится. Поддерживаются и обратные операции, например поиск адреса функции по её имени. Это достаточно творческая единица, если знать как ею пользоваться (
см.документациюна сайте мелкософт).

В состав этой библиотеки входят и привычные нам функции, без каких-либо префиксов. Например потянув за всего одну EnumerateLoadedModules() можно получить список всех модулей DLL (вместе с виртуальной базой и размером), которые загружены в интересующее нас приложение. Поскольку вся черновая работа происходит в фоне, то в большинстве случаях это удобно. На входе, функция требует лишь дескриптор процесса (в примере ниже я передаю -1, т.е. текущий процесс), и адрес callback-процедуры, куда она в цикле будет сбрасывать информацию о модулях. Функция связана со-своей "обратной процедурой" невидимой нитью, так-что программный цикл выстраивать не нужно – обход на автомате прекращается, как только коллбэк возвращает родителю ошибку:


C-подобный:


Код:
format   pe console
entry    start
include
'win32ax.inc'
;
//----------
.
code
start
:
cinvoke  printf
,

invoke  EnumerateLoadedModules
,
-
1
,
Modules
,
0
cinvoke  getch
        cinvoke  exit
,
0
;
//----------
proc     Modules  mName
,
mBase
,
mSize
,
mUser
;
//
,
[
mBase
]
,
[
mSize
]
,
[
mName
]
ret
endp
;
//----- ИМПОРТ ----------
section
'.idata'
import data readable
library  msvcrt
,
'msvcrt.dll'
,
dbghelp
,
'dbghelp.dll'
import   msvcrt
,
printf
,
'printf'
,
getch
,
'_getch'
,
exit
,
'exit'
import   dbghelp
,
EnumerateLoadedModules
,
'EnumerateLoadedModules'


Всё идёт прекрасно до тех пор, пока мы не сталкиваемся с вызовом функций из основного движка-отладки Dbgeng.dll – здесь и начинается самое интересное. Эта библиотека построена по модели СОМ (Component-Object-Model), а значит и вызывать из неё функции нужно соответствующим образом. Но проблема в том, что в отличии от крестов С++ и прочих высокоуровневых языков, ни один из ассемблеров не поддерживает на данный момент технологию COM/ActiveX, и врядли уже будет поддерживать в будущем. Ассемблер – это язык низкого уровня, а прослойка СОМ находится в иерархии намного выше.

Как уже упоминалось, библиотека Dbgeng.dll выдаёт на экспорт всего 3-функции (см.в тотале по ctrl+q) – это DebugCreate(), DebugConnect() и DebugConnectWide(). Но под капотом у неё припрятаны ещё порядка 300 внутренних, неэкспортируемых обычным способом функций. Чтобы подобраться к ним, для начала нужно разобраться, что вообще такое COM-интерфейс и как его реализуют современные компиляторы – вот об этом и поговорим..

2.Component-Object-Modelв ассемблере

COM – многокомпонентная, клиент-серверная модель объектов Microsoft, которая является продолжением OLE и фундаментальной основой многих других технологий, в том числе ActiveX и DCOM (Distributed COM, работа с сетью). Ключевым аспектом COM является то, что эта технология обеспечивает связь между клиентом (нашим приложением) и сервером (операционной системой) посредством "интерфейсов". Именно интерфейс предоставляет клиенту способ узнать у сервера, какие конкретно возможности он поддерживает на текущий момент.

В терминологии языка С++ интерфейс – это абстрактный базовый класс, все методы которого являются виртуальными. То-есть вызов этих методов осуществляется через специальную таблицу-указателей, известную как vTable. Например, вызов метода
Код:
QueryInterface
из интерфейса
Код:
IUnknown
будет выглядеть так:
Код:
IUnknown::QueryInterface()
. На сайте rsdn имеется
увесистый хаб, выделенный специально под описание всех нюансов СОМ-технологии.

Если-же посмотреть на СОМ глазами ассемблера, то интерфейс представляет собой ничто-иное, как обычную структуру в памяти. Чтобы придерживаться общих правил, мы будем называть её так-же, т.е. "vTable". В свою очередь методы – это лишь иное название уже привычных нам API-функций, а указатели на эти функции хранятся внутри интерфейса. Таким образом, интерфейс можно рассматривать как массив указателей на СОМ-функции. Влиться в эту тему поможет ветка на
wasm.in, где представлены материалы по СОМ с реальными примерами на ассемблере – "допризывникам" настоятельно рекомендуется к прочтению.

В операционной системе Win имеется огромное количество СОМ-интерфейсов и это не удивительно, ведь Microsoft строит системы используя объектно-ориентированный подход программирования, а частью ООП является как-раз-таки OLE/ActiveX/СОМ. Чтобы из этого общего пула у нас была возможность выбрать и использовать в своих программах конкретный интерфейс, система назначает ему уникальный идентификатор GUID. Собрав в единую базу, Win хранит все эти идентификаторы в своём кусте реестра под названием "HKEY_CLASSES_ROOT\Interface". Если выбрать любой GUID в левом окне, то в правом получим отождествлённое с этим идентификатором, название интерфейса:



СОМ-сервер операционной системы имеет базовый интерфейс под названием "IUnknown". Он глобален и все остальные наследуются именно от него. GUID этого интерфейса имеет значение
Код:
{00000000-0000-0000-C000-000000000046}
. В своей тушке интерфейс хранит указатели на три метода (функции) и на ассемблере будет выглядеть так:


C-подобный:


Код:
struct IUnknown
  QueryInterface   dd
0
;
// метод позволяет найти адрес интерфейса в памяти, по его GUID.
AddRef           dd
0
;
// метод счётчика-ссылок на интерфейс
Release          dd
0
;
// метод уменьшает счётчик (при достижении нуля интерфейс освобождается)
ends
Как видим, при помощи IUnknown и его метода QueryInterface() можно найти адрес любого СОМ-интерфейса в системе, но только при условии, что мы знаем GUID искомого (нужно будет передать его в качестве аргумента этому методу). Важно запомнить, что базовый интерфейс IUnknown входит в состав буквально всех СОМ-интерфейсов, занимая первые три указателя в нём. СОМ-сервер инкапсулирует его во-все интерфейсы, чтобы вести над ними учёт.

Например, когда мы получаем от сервера ссылку (указатель) на какой-нибудь интерфейс, его метод AddRef() на автомате увеличивает внутренний счётчик-обращений к данному интерфейсу. Если-же интерфейс нам больше не нужен, мы должны вызвать его метод Release(), который соответственно уменьшит этот счётчик на 1. Сервер периодически парсит счётчики активных интерфейсов и если обнаруживает в нём нуль, то из-за ненадобности сразу выгружает его из памяти. Так реализуется "время жизни" СОМ-интерфейсов, и это стандартная схема учёта системных структур, в памяти Win.

3. Структура СОМ-библиотекиDbgeng.dll

Будем считать, что прошлись по макушкам СОМ-технологии, и теперь рассмотрим её реализацию внутри главного героя этой статьи – библиотеки Dbgeng.dll. В каком-то смысле, эта библиотека сама является полноценным СОМ-сервером, поскольку GUID'ы её интерфейсов не прописаны в системном реестре Win, хотя библиотека и является детищем самой Microsoft. Из этических соображений, все разработчики СОМ-интерфейсов обязаны сопровождать свой продукт полной документацией, чтобы армия прикладных программистов могла использовать незнакомые интерфейсы в своих программах. Связано это с тем, что не зная GUID мы просто не сможем найти ни один интерфейс в системе, и соответственно лишимся возможности вызывать из него методы.

Движок-отладки Dbgeng.dll отлично документирован в репозитории мягких – общие сведения о нём можно почерпнуть
по этому линку. Что касается описания непосредственно имеющихся в наличии методов и GUID всех интерфейсов, то они находятся в заголовочном файле Dbgeng.h, электронная версия котороголежит здесь. Судя по этому хидеру, в данную библиотеку включён не один, а целая дюжина связанных с отладкой различных интерфейсов, и в каждом из них имеются свои функции (методы). Исторически, 16-байтные GUID интерфейсов принято обозначать как IID, что подразумевает "Interface-Identifier".



Одной из примечательных особенностей СОМ-интерфейсов является их масштабируемость. Так, если мы захотим изменить уже существующий интерфейс, то достаточно написать недостающие методы, и добавить указатели на них в конец прежнего интерфейса. К примеру, каждый из представленных выше 13-ти фейсов имеет дополнительные экземпляры, к именам которых добавляется порядковый номер по типу: IDebugClient (основной интерфейс), и дальше IDebugClient2 (3,4,5,6,7). Каждый последующий экземпляр включает в себя какие-то свежие методы и ему назначается новый GUID, в результате чего интерфейс шагает в ногу со-временем.

Если учитывать все интерфейсы вместе с расширенными, то в библиотеке Dbgeng.dll операционной системы Win7 зарегистрировано всего 35 СОМ-интерфейсов, а общее число методов в них приближается к отметке 300. Забегая вперёд скажу, что не все они реализованы на должном уровне, в чём мы убедимся позже. Здесь нужно отметить, что движок-отладки включённый в состав ОС отличается от движка ядерного отладчика "WinDbg" – у системного версия [6.1.7601], а у того, что использует отладчик [6.12.2]. Системный файл плохо зарекомендовал себя тем, что в нём вырезана поддержка удалённой отладки, что является козырем отладочного ядра WinDbg. Поэтому и размеры библиотек у них разные, о чём свидетельствует скрин ниже:






Посмотрим на рисунок ниже, где представлена обобщённая структура библиотеки Dbgeng.dll.

Чтобы воспользоваться услугами сервера-отладки, мы должны сначала активировать его функцией CoInitialize() из библиотеки подсистемы исполнения OLE32.dll. Теперь нужно создать "клиента отладки" функцией DebugCreate() из либы Dbgeng.dll, передав ей в виде аргумента GUID интерфейса "IDebugClient::". Это основной интерфейс клиента, где собраны часто используемые им (т.е. нашим приложением) методы.

Если зайти отладчиком OllyDbg в функцию DebugCreate() по [F7], то можно обнаружить, что она проделывает массу полезной работы – например копирует из тушки движка в пространство пользователя различные структуры, находит через GetProcAddress() и подключает вспомогательные функции отладки из библиотеки Ntdll.dll типа: DbgEvent(), DbgBreakPoint() и многое другое. Именно эта функция создаёт полный контекст отладки в памяти ОЗУ, и нам остаётся лишь вызывать методы из требуемых СОМ-интерфейсов:






В качестве демонстрационного примера для вводной части, предлагаю код ниже, который в цикле будет запрашивать у базового интерфейса "IUnknown::" все имеющиеся в наличии интерфейсы отладочного движка. Как уже упоминалось, всего в библиотеке Dbgeng.dll их зарегистрировано 35-штук (вместе с расширенными), а GUID'ы этих интерфейсов я вынес во-внешний инклуд (см.скрепку в конце статьи). По сути здесь нет ничего особенного, однако следующий нюанс требует некоторого пояснения..

Значит передаём функции DebugCreate() GUID интерфейса "IDebugClient::", на что функция возвращает нам адрес этого интерфейса в памяти. Если вернуться к рис.выше, то можно обнаружить, что первые три метода в любом интерфейсе, есть копия базового интерфейса "IUnknown::", а первый метод – как-раз нужный нам QueryInterface(). Он ожидает на входе два аргумента – это GUID искомого интерфейса, и указатель на переменную, куда метод сохранит его адрес.

Особое внимание нужно обратить на способ вызова СОМ-методов в ассемблере. Дело в том, что помимо обозначенных прототипом аргументов, мы всегда должны добавлять ещё один лишний аргумент – в спецификации его назвали "This" и представляет он собой адрес интерфейса. Другими словами, перед вызовом любого метода из какого-либо интерфейса, мы должны явно указать серверу, из какого именно осуществляем вызов. Этот аргумент(This) всегда является первым аргументом метода – вот пример:


C-подобный:


Код:
format   pe console
include
'win32ax.inc'
entry    start
;
//----------
.
data
InterfaceName
:
dd  i01
,
i02
,
i03
,
i04
,
i05
,
i06
,
i07
,
i08
,
i09
,
i10
;
// таблица указателей на имена интерфейсов
dd  i11
,
i12
,
i13
,
i14
,
i15
,
i16
,
i17
,
i18
,
i19
,
i20
            dd  i21
,
i22
,
i23
,
i24
,
i25
,
i26
,
i27
,
i28
,
i29
,
i30
            dd  i31
,
i32
,
i33
,
i34
,
i35

i01         db
10
,
' IUnknown..............: '
,
0
i02         db
10
,
10
,
' IDebugAdvanced........: '
,
0
i03         db
10
,
' IDebugAdvanced2.......: '
,
0
i04         db
10
,
' IDebugAdvanced3.......: '
,
0
i05         db
10
,
10
,
' IDebugBreakpoint......: '
,
0
i06         db
10
,
' IDebugBreakpoint2.....: '
,
0
i07         db
10
,
' IDebugBreakpoint3.....: '
,
0
i08         db
10
,
10
,
' IDebugClient..........: '
,
0
i09         db
10
,
' IDebugClient2.........: '
,
0
i10         db
10
,
' IDebugClient3.........: '
,
0
i11         db
10
,
' IDebugClient4.........: '
,
0
i12         db
10
,
' IDebugClient5.........: '
,
0
i13         db
10
,
' IDebugClient6.........: '
,
0
i14         db
10
,
' IDebugClient7.........: '
,
0
i15         db
10
,
10
,
' IDebugControl.........: '
,
0
i16         db
10
,
' IDebugControl2........: '
,
0
i17         db
10
,
' IDebugControl3........: '
,
0
i18         db
10
,
' IDebugControl4........: '
,
0
i19         db
10
,
' IDebugControl5........: '
,
0
i20         db
10
,
' IDebugControl6........: '
,
0
i21         db
10
,
' IDebugControl7........: '
,
0
i22         db
10
,
10
,
' IDebugDataSpaces......: '
,
0
i23         db
10
,
' IDebugDataSpaces2.....: '
,
0
i24         db
10
,
' IDebugDataSpaces3.....: '
,
0
i25         db
10
,
10
,
' IDebugEventCallbacks..: '
,
0
i26         db
10
,
' IDebugInputCallbacks..: '
,
0
i27         db
10
,
' IDebugOutputCallbacks.: '
,
0
i28         db
10
,
' IDebugOutputCallbacks2: '
,
0
i29         db
10
,
10
,
' IDebugRegisters.......: '
,
0
i30         db
10
,
' IDebugSymbolGroup.....: '
,
0
i31         db
10
,
' IDebugSymbols.........: '
,
0
i32         db
10
,
' IDebugSymbols2........: '
,
0
i33         db
10
,
10
,
' IDebugSystemObjects...: '
,
0
i34         db
10
,
' IDebugSystemObjects2..: '
,
0
i35         db
10
,
' IDebugSystemObjects3..: '
,
0
Client      dd
0
;
// переменная под адрес интерфейса "IDebugClient"
iOffset     dd
0
;
// переменная под адрес остальных интерфейсов (обновляется в цикле)
buff        db
0
;
//----------
.
code
start
:
invoke  SetConsoleTitle
,

invoke  CoInitialize
,
0
;
// активируем СОМ-сервер
;
// Создаём клиента отладки (в переменную Client получим указатель на интерфейс)
invoke  DebugCreate
,
IID_IDebugClient
,
Client
         xchg    ebx
,
eax
        cinvoke  printf
,

,
[
Client
]
cmp     ebx
,
S_OK
         jnz     @error
;
// если ошибка..
;
// Перебрать имеющиеся в движке интерфейсы
mov     ecx
,
35
;
// всего зарегистрировано (длина цикла для LOOP)
mov     esi
,
GuidTable
;
// адрес таблицы-гуидов в инклуде "Dbgeng.inc"
mov     ebx
,
InterfaceName
;
// адрес таблицы с именами интерфейсов
@@
:
push    ecx esi ebx ebx
;
// запомнить для организации цикла!
mov     eax
,
[
Client
]
;
// адрес интерфейса "IDebugClient"
mov     edx
,
[
eax
]
;
// берём из него сразу-же первый указатель на метод QueryInterface()
push    iOffset
;
// куда сохранять указатель на интерфейс
push    esi
;
// GUID очередного интерфейса
push
[
Client
]
;
// аргумент "This" (от куда вызываем метод)
call    dword
[
edx
]
;
// QueryInterface()!
pop     ebx
;
//
mov     edx
,
[
ebx
]
;
// указатель на имя из таблицы
cinvoke  printf
,

,
edx
,
[
iOffset
]
;
// вывести на консоль имя и адрес интерфейса
pop     ebx esi ecx
;
// восстановить данные цикла
add     esi
,
16
;
// следующий GUID в таблице
add     ebx
,
4
;
// следующий указатель на имя
loop    @b
;
// промотать цикл ECX-раз..
@exit
:
invoke  CoUninitialize
;
// освобождаем СОМ-сервер
cinvoke  getch
;
//
cinvoke  exit
,
0
;
// GAME OVER!
;
//===== ОБРАБОТКА ОШИБКИ ======================
@error
:
cinvoke  printf
,

jmp     @exit
;
//----- ИМПОРТ ----------
section
'.idata'
import data readable
library  msvcrt
,
'msvcrt.dll'
,
dbgeng
,
'dbgeng.dll'
,
\
         ole32
,
'ole32.dll'
,
kernel32
,
'kernel32.dll'
import   msvcrt
,
printf
,
'printf'
,
getch
,
'_getch'
,
exit
,
'exit'
import   dbgeng
,
DebugCreate
,
'DebugCreate'
import   ole32
,
CoInitialize
,
'CoInitialize'
,
CoUninitialize
,
'CoUninitialize'
include
'api\kernel32.inc'
include
'equates\dbgeng.inc'
;
//
,
eax
;
// IDebugControl::WaitForEvent
mov     esi
,
[
Control
]
mov     esi
,
[
esi
]
mov     eax
,
[
esi
+
IDebugControl
.
WaitForEvent
]
mov
[
WaitEvent
]
,
eax
        cinvoke  printf
,

,
eax
;
// IDebugControl::Disassemble
mov     esi
,
[
Control
]
mov     esi
,
[
esi
]
mov     eax
,
[
esi
+
IDebugControl
.
Disassemble
]
mov
[
Disasm
]
,
eax
        cinvoke  printf
,

,
eax
;
//***********************************************************
@process
:
;
// Подцепить отладчик к текущему процессу ()
invoke  GetCurrentProcessId
         mov     ebx
,
DEBUG_ATTACH_NONINVASIVE
+
DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND

         push    ebx
;
// флаги
push    eax
;
// Pid процесса
push
0
0
;
// Ulong64 Server
push
[
Client
]
;
// This
call    dword
[
Attach
]
cinvoke  printf
,

,
eax
;
// Ожидать событие отладки..
push
-
1
;
// INFINITY (ждать бесконечно)
push
0
;
// DEBUG_WAIT_DEFAULT
push
[
Control
]
;
// This
call    dword
[
WaitEvent
]
cinvoke  printf
,

,
eax
;
//===== Вызвать дизассемблер!!! ============================
mov     ebx
,
start
;
// адрес первой инструкции
mov     ecx
,
25
;
// всего дизассемблировать инструкций
@@
:
push    ecx ebx
;
// запомнить для цикла..
push    pNextOffs
;
// получим адрес сл.инструкции
push    DisasmSize
;
// получим размер данных в буфере
push
256
;
// размер буфера
push    buff
;
// адрес приёмного буфа
push    DEBUG_DISASM_EFFECTIVE_ADDRESS
;
// флаг дизасма
push
0
;
// см.ниже vvv
push    ebx
;
// qword-адрес в памяти для дизасма
push
[
Control
]
;
// This
call    dword
[
Disasm
]
cinvoke  printf
,

,
buff
;
// распечатать дизасм-листинг!
pop     ebx ecx
;
// восстановить данные цикла
mov     ebx
,
[
pNextOffs
]
;
// адрес сл.инструкции из переменной
loop    @b
;
// промотать ECX-раз..
@exit
:
cinvoke  getch
;
// GAME OVER!
invoke  CoUninitialize
;
// освободить СОМ-сервер
cinvoke  exit
,
0
;
//
;
//===== ПРОЦЕДУРЫ ===============================
@error
:
cinvoke  printf
,

jmp      @exit
;
//----- ИМПОРТ ----------
section
'.idata'
import data readable
library  msvcrt
,
'msvcrt.dll'
,
dbgeng
,
'dbgeng.dll'
,
\
         ole32
,
'ole32.dll'
,
kernel32
,
'kernel32.dll'
import   msvcrt
,
printf
,
'printf'
,
getch
,
'_getch'
,
exit
,
'exit'
import   dbgeng
,
DebugCreate
,
'DebugCreate'
import   ole32
,
CoInitialize
,
'CoInitialize'
,
CoUninitialize
,
'CoUninitialize'
include
'api\kernel32.inc'
include
'equates\dbgeng.inc'
;
//----- РЕСУРСЫ ---------
section
'.rsrc'
resource data readable
directory    RT_VERSION
,
ver

resource     ver
,
1
,
LANG_NEUTRAL
,
vInfo
versioninfo  vInfo
,
\
             VOS__WINDOWS32
,
VFT_APP
,
VFT2_UNKNOWN
,
\
             LANG_ENGLISH
+
SUBLANG_DEFAULT
,
1252
,
\
'CompanyName'
,
'https://codeby.net'
,
\
'LegalCopyright'
,
'Copyright 2020-2021 (c)Marylin'
,
\
'ProductName'
,
'Windows 7'
,
\
'ProductVersion'
,
'6.1.7601.3821'
,
\
'FileDescription'
,
'DbgEngine Disassembler'
,
\
'FileVersion'
,
'0.0.1'
,
\
'OriginalFilename'
,
'DbgDisasm.exe'




Здесь я добавил некоторую вспомогательную информацию в шапке, чтобы продемонстрировать расположение интерфейсов и их методов. Так, первые две строчки указывают на наше пользовательское пространство памяти, куда функция DebugCreate() любезно сбросила указатели на интерфейсы. А вот сами методы находятся уже внутри библиотеки Dbgeng.dll, о чём свидетельствует их адреса с базой
Код:
0x5D0D0000
. Если вызов метода возвращает в
Код:
EAX=0
, значит он прошёл успешно (константа S_OK), иначе в
Код:
EAX
получим следующие коды ошибок:


C-подобный:


Код:
;
// Перечень ошибок - WinError.h.
;
//---------------------------------------------
S_OK
=
0
;
// операция выполнена успешно!
S_FALSE
=
1
;
// без ошибок, но получена только часть результата (см.буфер)
E_NOINTERFACE
=
80004002
h
;
// интерфейс не найден
E_POINTER
=
80004003
h
;
// неверный указатель
E_ABORT
=
80004004
h
;
// операция отвергнута
E_FAIL
=
80004005
h
;
// операция не может быть выполнена
E_ACCESSDENIED
=
80070005
h
;
// доступ запрещён (отладчик находится в безопасном режиме)
E_HANDLE
=
80070006
h
;
// проблема с дескриптором
E_OUTOFMEMORY
=
8007000
Eh
;
// ошибка выделения памяти
E_INVALIDARG
=
80070057
h
;
// неверный аргумент метода
E_UNEXPECTED
=
8000
FFFFh
;
// отладчик в неправильном состоянии (см.WaitForEvent)


5. Заключение.

Программирование СОМ-интерфейсов открывает перед нами огромные возможности, поскольку в своих/больших штанинах они прячут достаточно интересные методы, подобраться к которым можно только через указатель на интерфейс, аля GUID. По модели СОМ построена добрая половина системных библиотек – объектная модель позволяет нам работать с такими механизмами как WMI (инструментарий Windows), технологией DirectX, с библиотекой Shell32.dll и многое другое. Как упоминалось выше, любой СОМ-интерфейс обязан быть документированным, поэтому проблем не возникает – главное уловить логическую нить, а дальше уже дело техники.

По уже отработанной схеме, в скрепку ложу два исполняемых файла, а так-же инклуд с описанием GUID'ов всех интерфейсов движка Dbgeng.dll, с полным описанием входящих в их состав методов. Всем удачи, пока!
 
Ответить с цитированием

  #2  
Старый 06.03.2021, 04:34
Crazy Jack
Новичок
Регистрация: 08.07.2017
Сообщений: 0
С нами: 4657944

Репутация: 0
По умолчанию

Респект и уважуха за такой труд
 
Ответить с цитированием

  #3  
Старый 06.03.2021, 10:13
ROP
Новичок
Регистрация: 27.08.2019
Сообщений: 0
С нами: 3533622

Репутация: 0
По умолчанию

Качество статьи на высоте

Полностью согласен с Eugene75
 
Ответить с цитированием

  #4  
Старый 22.03.2021, 01:16
ProMiNick
Новичок
Регистрация: 21.03.2021
Сообщений: 0
С нами: 2711109

Репутация: 0
По умолчанию

Marylin
, я тебя иногда почитываю.
возникла идея все у тебя сплагиатить. то есть не сделать ничего нового, просто объединить оба твоих примера и переиначить их.
что (будет) делает прога: с ней идет инифайл с указанием целевой библиотеки (COM-сервера), с указанием процедуры загрузки интерфейсов из библиотеки, и текстовый файлик с расписанными интерфейсами.
теперь собственно что прога будет делать: загружать интерфейс по алгоритму из инифайла, затем осуществлять перебор по методам интерфейса, если будет встречен метод с кодом

Код:


Код:
mov eax, E_NOTIMPL
ret 4*кол-во параметров
такой метод метить как нереализованный,
а на все прочие методы натравливать вышеописанный дизассемблер (грубо - до первой встреченной инструкции ret ( т.е. инструкции в потоке инструкций начинающейся с байта $C2 или $C3)),
в результате программа будет показывать доступность интерфейсов, реализованность методов (при наследовании реализованность методов может как появляться так и исчезать, так и быть реализованной иначе), дизассемблинг методов, и это будет конфигурируемо - можно натравливать на любой COM-сервер.
У меня DBGENG.INC это один из исходников будущей программы, ее же синтаксис планируется для перебора интерфейсов и их методов, просчет числа параметров методов так же из этого файла.
в 2х словах - идея программы - ГУИ, 2 компонента - дерево и едитбокс, в дереве интерфейсы и их методы, в эдитбоксе информация синхронно дерева - адреса доступности интерфейсов, реализованность метода, дизасм метода. все остальное файлы рядом с программой 1 ini и 1 inc.
(На первом этапе наверно без 1 ini и 1 inc, а жестко закодировать перечень интерфейсов и их методов из dbgeng.dll)
 
Ответить с цитированием

  #5  
Старый 22.03.2021, 05:32
Marylin
Постоянный
Регистрация: 01.09.2019
Сообщений: 378
С нами: 3526561

Репутация: 0
По умолчанию

Цитата:

ProMiNick сказал(а):

возникла идея все у тебя сплагиатить

Отличная идея, ..осталось реализовать это на практике.
 
Ответить с цитированием

  #6  
Старый 24.12.2021, 02:30
morgot
Новичок
Регистрация: 26.07.2018
Сообщений: 0
С нами: 4106487

Репутация: 0
По умолчанию

Не могу найти, как получить длину инструкции; хотел заюзать эти СОМ для простого дизассемблера длин (чтобы не тащить сторонние). Но что-то не найду ничего среди методов - возвращают или строку или еще что.
А так - статья шикарная , как всегда! В мсдн не указано (или я не видел), что обязательно нужно WaitForEvent вызывать перед дизасмом, иначе возвращает ошибки.
В теории, есть метод GetNearInstruction, на практике он иногда возвращает 0, неясно что такое 0 - длина инструкции не может же быть нулевая; IDebugControl::GetNearInstruction (dbgeng.h) - Windows drivers , кто лучше шарит в инглише, мб будут какие-то мысли? Написать функцию, на вход адрес , на выходе должна быть длина инструкции.
 
Ответить с цитированием
Ответ





Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT ™ © 2001- Antichat Kft.