Во всех современных системах имеются воины теневого фронта. Эти гонцы шастают туда-сюда, всё что-то вынюхивают, и записывают логи в свои блокноты для последующего анализа. Они прячутся под маской легальных мониторов безопасности Win, хотя представляют собой типичных шпионов Spy. В ответ свободные кодеры ответили ОС целым классом аналогичного по смыслу софта на любой вкус: FileMon (в народе филемон), DiskMon, RegMon, ProcMon, и прочие производные от них. Но в контексте данной статьи мы остановимся только на API-шпионах - что это за фрукты и с чем их едят.
Оглавление:
1. Детали механизма
API-шпион входит в активный инструмент исследователей. Будучи натравленным на прикладной софт, он перехватывает вызовы всех (или отфильтрованных по маске) WinAPI, чтобы предоставить нам список их текущих аргументов. Зная, какие функции и с какими параметрами вызывает защита, мы можем ставить точки-останова, всплывая отладчиком в непосредственной близости от штаб-квартиры врага. Если же этой информации у нас нет, брэйки приходится разбрасывать вслепую, гадая на кофейной гуще, какой именно API воспользовалась программа. В общем исследовать софт без шпионов становится совсем худо, ведь мало иметь список импорта в РЕ-файле - нужны ещё и аргументы вызовов.
Примитивные мониторы API хукают импорт прямо из пользовательского режима, более продвинутые инжектят свои DLL в память клиентов, однако серьёзный шпион всегда таскает с собой собственный драйвер, что позволяет ему залечь на самое дно системы. При этом у любого шпиона имеется своя база-данных DB, где хранится полный список функций из системных DLL, с кол-вом параметров для каждой из них. Благодаря именно базе становится возможным вести правильные логи, в которых будут лежать валидные аргументы функций. Вот фрагмент из такой базы для либы Kernel32.dll:
2. Софт для API-шпионажа
Довольно долго достойным шпионом был Kerberos от Рустема Фасихова. Он отлично справлялся со своими обязанностями на 32-битных WinXP, пока не ввалилась в нашу жизнь 64-битная эра, отправив на свалку сотни тонн уникального кода. Но автор Kerberos'a не забросил свой продукт, и немного причесав ему фейс выпустил в свет уже под другим именем API Logger, хотя реальную поддержку х64 почему-то так и не реализовал. Это простой, компактный (размер всего 16к), а потому наверное самый быстрый инструмент в своём классе для х32, который несомненно заслуживает внимания. Кстати на "Kerberos" есть сурки, т.ч. при желании можно будет самим портировать его и на х64.
Не последнюю роль в API-шпионах играют фильтры, благодаря которым можно отсеивать в логах вызовы неинформативных функций. Например, если не взвести галку "Only EXE calls" в опциях выше (хук api только из этого экзешника), то получим массу ненужного/промежуточного хлама, перебирать который придётся потом в ручную. Как видим в свежей версии есть и встроенный профайлер - помимо самих аргументов функций, он замерят и потраченное на них время как в милли/сек (указывается в первых квадратных скобках в конце), так и в тиках счётчика производительности QPC (Query Performance Counter, последний в строке). Вот пример лога:
А вот ещё один шпион наших дней API Monitor - он раздаётся бесплатно сразу в двух ипостасях х32/64, и благодаря наличию своего драйвера, представляет собой тяжёлую артиллерию. Это уже серьёзный инструмент для профессионалов с массой тумблеров, выводит просто огромное кол-во информации, включая подробное описание параметров. Мощный фильтр позволяет выбирать не только библиотеки DLL, но и функциональные их составляющие (например только работа с файлами, памятью или устройствами внутри одной kernel32.dll). В целом монитор производит хорошее впечатление, что подтверждается на практике.
3. Плагин "Logexts" в отладчике WinDBG
Сторонний софт от энтузиастов это хорошо, но согласитесь намного комфортнее держать весь арсенал в одном месте, и такой вариант предлагает нам WinDBG. Прямо не отходя от кассы, мы можем загрузить его расширение "Logexts", которое выступает в роли пусть и примитивного, но шпиона. Его логи - это точная ксерокопия Kerberos'a, хотя фильтр намного мощнее.
Команда
Значит
3.1. Своя реализация в скриптах
Плагин выше шпионит? Да. Хорошо? Не очень.. т.к. даже при тщательной фильтрации в логе много мусора, но это уже генетическая особенность самого WinDBG, а не плагина. Он логирует не только вызовы api из конкретно нашего приложения, но и уходит в глубину во-вложенные с заходом в
В арсенале WinDBG есть т.н. "точки-останова по соответствию"
Как видим, отладчик создал 5 брейков - первый указан явно, а остальные с подстановочным знаком(), т.е. все функции из Ntdll.dll, имена которых начинаются с префикса
Более того, в команде
Но аргументов у функций может быть много, и перечислять их все в одной ком.строке отладчика довольно муторно. Поэтому имеет смысл вынести последовательность команд во внешний файл-скрипта, и вызывать его с параметром командой
Обратите внимание на экранирующий символ(\) - он нужен, чтобы отделить параметры команды
Здесь видно, что скрипт не распознаёт число аргументов у функции, поэтому выводит все возможные. Решает эту проблему база-данных, как в примере выше использует шпион Kerberos.
А что с отладчиком х64Dbg? Для него тоже можно написать аналогичный скрипт, только в этом нет необходимости, т.к. существует плагин "xAnalyzer", который декодирует аргументы всех системных DLL, причём делает это весьма качественно.
4. Выводы
В природе есть много API-шпионов, и на описанных здесь свет клином не сошёлся. Например в качестве универсального решения можно рассматривать утилиты "WinAPIOverride" и "SpyStudio", причём некоторые распространяются с исходниками, а потому изучить их гены будет проще. Но под каким именем не скрывался-бы шпион, это незаменимое оружие для отладки упакованных программ. Так, одним выстрелом мы сможем получить подробную карту вызовов api с сжатого кода, пропустив нудный процесс пошаговой распаковки. Это касается и динамической загрузки библиотек и функций через
Оглавление:
1. Детали механизма
2. Софт для API-шпионажа
3. Плагин "Logexts" в отладчике WinDBG
- своя реализация в скриптах
4. Выводы
1. Детали механизма
API-шпион входит в активный инструмент исследователей. Будучи натравленным на прикладной софт, он перехватывает вызовы всех (или отфильтрованных по маске) WinAPI, чтобы предоставить нам список их текущих аргументов. Зная, какие функции и с какими параметрами вызывает защита, мы можем ставить точки-останова, всплывая отладчиком в непосредственной близости от штаб-квартиры врага. Если же этой информации у нас нет, брэйки приходится разбрасывать вслепую, гадая на кофейной гуще, какой именно API воспользовалась программа. В общем исследовать софт без шпионов становится совсем худо, ведь мало иметь список импорта в РЕ-файле - нужны ещё и аргументы вызовов.
Примитивные мониторы API хукают импорт прямо из пользовательского режима, более продвинутые инжектят свои DLL в память клиентов, однако серьёзный шпион всегда таскает с собой собственный драйвер, что позволяет ему залечь на самое дно системы. При этом у любого шпиона имеется своя база-данных DB, где хранится полный список функций из системных DLL, с кол-вом параметров для каждой из них. Благодаря именно базе становится возможным вести правильные логи, в которых будут лежать валидные аргументы функций. Вот фрагмент из такой базы для либы Kernel32.dll:
Код:
[kernel32.dll]
AddAtomA ,1
AddAtomW ,1
AllocConsole ,0
AllocateUserPhysicalPages ,3
;.......
Beep ,2
BeginUpdateResourceA ,2
BeginUpdateResourceW ,2
BindIoCompletionCallback ,3
;.......
CopyFileA ,3
CopyFileExA ,6
CreateConsoleScreenBuffer ,5
CreateDirectoryA ,2
CreateFileA ,7
;.......
DeleteAtom ,1
DeleteFileA ,1
DeviceIoControl ,8
DuplicateHandle ,7
;.......
2. Софт для API-шпионажа
Довольно долго достойным шпионом был Kerberos от Рустема Фасихова. Он отлично справлялся со своими обязанностями на 32-битных WinXP, пока не ввалилась в нашу жизнь 64-битная эра, отправив на свалку сотни тонн уникального кода. Но автор Kerberos'a не забросил свой продукт, и немного причесав ему фейс выпустил в свет уже под другим именем API Logger, хотя реальную поддержку х64 почему-то так и не реализовал. Это простой, компактный (размер всего 16к), а потому наверное самый быстрый инструмент в своём классе для х32, который несомненно заслуживает внимания. Кстати на "Kerberos" есть сурки, т.ч. при желании можно будет самим портировать его и на х64.
Не последнюю роль в API-шпионах играют фильтры, благодаря которым можно отсеивать в логах вызовы неинформативных функций. Например, если не взвести галку "Only EXE calls" в опциях выше (хук api только из этого экзешника), то получим массу ненужного/промежуточного хлама, перебирать который придётся потом в ручную. Как видим в свежей версии есть и встроенный профайлер - помимо самих аргументов функций, он замерят и потраченное на них время как в милли/сек (указывается в первых квадратных скобках в конце), так и в тиках счётчика производительности QPC (Query Performance Counter, последний в строке). Вот пример лога:
Код:
API Logger v1.9
(C)2004-2012 black_ninja
QPC Frequency = 14318180 tics/sec
Functions ready to hook: 1282
Total function in DB : 1282
Include modules : KERNEL32.DLL
LOG START
StackTr~.EXE 00403006 GetCurrentProcessId() ret: 00000E38 [6] [86]
StackTr~.EXE 00403014 OpenProcess(001F0FFF, 00000000, 00000E38) ret: 000000D8 [59] [845]
StackTr~.EXE 004031A2 GetTickCount() ret: 01FD85BC [4] [66]
StackTr~.EXE 004031A2 GetTickCount() ret: 01FD85BC [3] [43]
StackTr~.EXE 0040309A GetModuleHandleA(00403088: "user32.dll") ret: 752D0000 [9] [141]
LOG END
А вот ещё один шпион наших дней API Monitor - он раздаётся бесплатно сразу в двух ипостасях х32/64, и благодаря наличию своего драйвера, представляет собой тяжёлую артиллерию. Это уже серьёзный инструмент для профессионалов с массой тумблеров, выводит просто огромное кол-во информации, включая подробное описание параметров. Мощный фильтр позволяет выбирать не только библиотеки DLL, но и функциональные их составляющие (например только работа с файлами, памятью или устройствами внутри одной kernel32.dll). В целом монитор производит хорошее впечатление, что подтверждается на практике.
3. Плагин "Logexts" в отладчике WinDBG
Сторонний софт от энтузиастов это хорошо, но согласитесь намного комфортнее держать весь арсенал в одном месте, и такой вариант предлагает нам WinDBG. Прямо не отходя от кассы, мы можем загрузить его расширение "Logexts", которое выступает в роли пусть и примитивного, но шпиона. Его логи - это точная ксерокопия Kerberos'a, хотя фильтр намного мощнее.
Команда
!load подгружает плагин, и далее help выводит ознакомительную справку. При этом во всех командах е = включить опцию, а d выключить (enable/disable):
Код:
0:000> kd> !load logexts
0:000> kd> !logexts.help
Windows API Logging Extensions v3.01
Main control:
!loge [dir] Enable logging. Output directory optional.
!logi [dir] Initialize but don't enable logging.
!logd Disable logging.
Output:
!logo List output settings.
!logo [e|d] [d|t|v] Enable/disable output:
d - Debugger
t - Text file
v - Verbose log
Categories:
!logc List all categories.
!logc p # List APIs in category #.
!logc [e|d] * Enable/disable all categories.
!logc [e|d] # [#] [#] ... Enable/disable category #.
Buffer access:
!logb p Print buffer contents to debugger.
!logb f Flush buffer to log files.
Debugging Logexts:
!logs Print statistics.
!logh [i|c] Print hook info (import | com).
!logspew [e|d] Enable/disable logexts info messages.
Module inclusion/exclusion:
!logm Display module inclusion/exclusion list.
!logm [i|x] [DLL] [DLL] ... Specify module inclusion/exclusion list.
0: kd>
Значит
!loge активизирует шпиона. Команду желательно вводить последней уже после того, как настроим все остальные опции. В дефолте каталог с логами создаётся на раб.столе, хотя при желании можно задать и свой путь в аргументе !loge. Вот типичная последовательность:1. Командой
!logo проверить, включена-ли опция ведения логов в файл *.txt и если нет, активировать её !logo e t.
2. Фильтром на уровне самих DLL управляет
!logm, но есть нюанс. Проблема в том, что работа самого плагина основана на api из Kernel32.dll, а потому ручное подключение (inclusion) этой DLL в круг подозреваемых может привести к мёртвому циклу (плаг будет бесконечно ловить сам-себя). Именно по этой причине он ругается на команду !logm i kernel32.dll, хотя в дефолте выборочные api из этой либы уже подключены. Но хуже всего то, что подключение одной автоматически отключает все остальные DLL, в результате чего можно получить пустой лог. Если подключать - только с явным перечислением всех необходимых, кроме Kernel32.dll:
Код:
0:000> !logm i user32.dll gdi32.dll advapi32.dll ntdll.dll
Included modules:
user32.dll
gdi32.dll
advapi32.dll
ntdll.dll
3. Тонкие настройки фильтра скрыты в
!logc, а текущие можно просмотреть командой без параметров. Это предпочтительный вариант, чем оперировать на более низком уровне самих DLL. Здесь можно выбрать список перехвата api по назначению, а не по их именам, например только работа с памятью(16), файловый ввод-вывод(15), девайсы(7), и т.д. Просмотреть содержимое каждой категории можно аргументом(р). Обратите внимание, что в дефолте включены абсолютно все, в результате чего в логе получим много мусора. Поэтому лучше фильтровать вывод аргументом(е) выборочно - сначала все отключаем(d*), а затем включаем(e) только интересные.
Код:
0:000> !logc
Categories:
1 AdvApi32 Enabled
2 AtomFunctions Enabled
3 AVIFileExports Enabled
4 Clipboard Enabled
5 ComponentObjectModel Enabled
6 DebuggingAndErrorHandling Enabled
7 DeviceFunctions Enabled
8 Direct3D Enabled
9 DirectDraw Enabled
10 DirectPlay Enabled
11 DirectSound Enabled
12 GDI Enabled
13 HandleAndObjectFunctions Enabled
14 HookingFunctions Enabled
15 IOFunctions Enabled
16 MemoryManagementFunctions Enabled
17 Multimedia Enabled
18 Printing Enabled
19 ProcessesAndThreads Enabled
20 RegistryFunctions Enabled
21 Shell Enabled
22 StringManipulation Enabled
23 ThreadLocalStorage Enabled
24 User32 Enabled
25 User32StringExports Enabled
26 Version Enabled
27 WinSock2 Enabled
0:000> !logc p 15
IOFunctions:
_hread KERNEL32.DLL
_hwrite KERNEL32.DLL
_lclose KERNEL32.DLL
_lcreat KERNEL32.DLL
_llseek KERNEL32.DLL
_lopen KERNEL32.DLL
_lread KERNEL32.DLL
_lwrite KERNEL32.DLL
AreFileApisANSI KERNEL32.DLL
CancelIo KERNEL32.DLL
CopyFileA KERNEL32.DLL
CopyFileExA KERNEL32.DLL
CreateDirectoryA KERNEL32.DLL
CreateDirectoryExA KERNEL32.DLL
CreateFileA KERNEL32.DLL
CreateIoCompletionPort KERNEL32.DLL
DefineDosDeviceA KERNEL32.DLL
DeleteFileA KERNEL32.DLL
FindClose KERNEL32.DLL
........
0:000> !logc d *
All categories disabled.
0:000> !logc e 15 16
15 IOFunctions Enabled
16 MemoryManagementFunctions Enabled
4. Как только покончим с настройками, можно включить теперь и логирование командой
!loge. А вообще это не принципиально и активировать логгер можно в любой момент хоть в самом начале. Это даёт возможность налету менять настройки фильтра уже в процессе отладки. Теперь запускаем на исполнение клиента командой g, и получаем подробный лог вызовов api с их аргументами на текущий момент. Отчёты будут оседать как в файл, так и в окно отладчика:
Код:
0:000> !loge
Logexts injected. Output: "C:\Users\Marylin\Desktop\LogExts\"
Logging enabled.
0:000> g
Parsing the manifest files...
Location: C:\Program Files\Debugging Tools for Windows (x64)\winext\manifest\main.h
Parsing file "main.h" ...
Parsing file "winerror.h" ...
Parsing file "kernel32.h" ...
Parsing file "debugging.h" ...
Parsing file "processes.h" ...
Parsing file "memory.h" ...
Parsing file "registry.h" ...
Parsing file "fileio.h" ...
Parsing file "strings.h" ...
Parsing file "user32.h" ...
Parsing file "clipboard.h" ...
Parsing file "hook.h" ...
Parsing file "gdi32.h" ...
Parsing file "winspool.h" ...
Parsing file "version.h" ...
Parsing file "winsock2.h" ...
Parsing file "advapi32.h" ...
Parsing file "uuids.h" ...
Parsing file "com.h" ...
Parsing file "shell.h" ...
Parsing file "ole32.h" ...
Parsing file "ddraw.h" ...
Parsing file "winmm.h" ...
Parsing file "avifile.h" ...
Parsing file "dplay.h" ...
Parsing file "d3d.h" ...
Parsing file "d3dtypes.h" ...
Parsing file "d3dcaps.h" ...
Parsing file "d3d8.h" ...
Parsing file "d3d8types.h" ...
Parsing file "d3d8caps.h" ...
Parsing file "dsound.h" ...
Parsing completed.
Thrd e58 000007FEFE45EA8F LocalAlloc( LMEM_ZEROINIT 0x00000030) -> 0x0000000002607E30
Thrd e58 000007FEFD7C628E LocalAlloc( LMEM_FIXED 0x000004D0) -> 0x00000000002A4020
Thrd e58 000000007748F9C0 HeapAlloc( 0x001C0000 0x00000000 0x00000200) -> 0x00000000002A1840
ModLoad: 000007fe`fb6a0000 000007fe`fb6f6000 C:\Windows\system32\uxtheme.dll
ModLoad: 000007fe`f16d0000 000007fe`f16dc000 C:\Program Files\Punto Switcher\PSHook64.dll
ModLoad: 000007fe`fd6f0000 000007fe`fd709000 C:\Windows\system32\imagehlp.dll
Thrd e58 000000007748461F GetSystemDirectoryW( 261) -> 0x00000013 ( "C:\Windows\system32")
Thrd e58 000000007748EDB0 GlobalLock( 0x03650008) -> 0x0265E0B0
Thrd e58 00000000774B215A GlobalSize( 0x03650008) -> 0x00042036
..........
3.1. Своя реализация в скриптах
Плагин выше шпионит? Да. Хорошо? Не очень.. т.к. даже при тщательной фильтрации в логе много мусора, но это уже генетическая особенность самого WinDBG, а не плагина. Он логирует не только вызовы api из конкретно нашего приложения, но и уходит в глубину во-вложенные с заходом в
call. Это полезно, но не всегда, а потому можно пойти другим путём и собрать API-шпион вручную, отправив всю последовательность команд во внешний скрипт.В арсенале WinDBG есть т.н. "точки-останова по соответствию"
bm (break match). В своём аргументе команда позволяет использовать подстановочные знаки, что чрезвычайно полезно, когда необходимо отлаживать все экспортируемые функции DLL, или только группу, имена которых соответствуют заданному шаблону.
Код:
0:000> bm /a kernel32!ReadFile
1: 00000000`773705b8 @!"kernel32!ReadFile"
0:000> bm /a ntdll!NtMap*
2: 00000000`775ea630 @!"ntdll!NtMapCMFModule"
3: 00000000`775e9a20 @!"ntdll!NtMapViewOfSection"
4: 00000000`775e97d0 @!"ntdll!NtMapUserPhysicalPagesScatter"
5: 00000000`775ea640 @!"ntdll!NtMapUserPhysicalPages"
0:000>
Как видим, отладчик создал 5 брейков - первый указан явно, а остальные с подстановочным знаком(), т.е. все функции из Ntdll.dll, имена которых начинаются с префикса
NtMap_xx(). Поскольку в режиме User число точек-останова не ограничего (хотя в режиме kernel их может быть макс.32), можно поставить брейки хоть на все функции(), но это перегрузит отладчик, поэтому лучше использовать фильтр.Более того, в команде
bm мы можем определить, что делать отладчику по достижении точки-останова - это условие необходимо заключить в кавычки. Например такая конструкция покажет содержимое регистров RCX/RDX, где будут лежать первые два аргумента:
Код:
0:000> bm /a kernel32!ReadFile ".printf \"RCX = %p. RDX = %p\", @rcx,@rdx"
Но аргументов у функций может быть много, и перечислять их все в одной ком.строке отладчика довольно муторно. Поэтому имеет смысл вынести последовательность команд во внешний файл-скрипта, и вызывать его с параметром командой
$$>a< scriptName.txt kernel32!Create*. Вот пример:
Код:
$$ ====================================================
$$ Останов на всех API или по маске в указанном модуле
$$ Использование: $$>a< "script.txt" module_name
$$ Пример: $$>a< "breakapi.txt" kernel32!Create*
$$ ====================================================
$$ Установить брейк на точку-входа в программу
bp @$exentry; g
$$ Удалить все точки-останова (clear)
bc *
$$ Переменная для параметра скрипта
r $t0 = 0
$$ Установить брейк с именем функции из параметра
bm /a ${$arg1} "
$$ Распечатать всё, что нужно...
.printf \"\\n>>> ${$arg1} called\\n\";
.printf \" RCX (arg1): %p \\n\", @rcx;
.printf \" RDX (arg2): %p \\n\", @edx;
.printf \" R8 (arg3): %p \\n\", @r8;
.printf \" R9 (arg4): %p \\n\", @r9;
.printf \" RSP+20 (arg5): %p \\n\", poi(@rsp+0x20);
.printf \" RSP+28 (arg6): %p \\n\", poi(@rsp+0x28);
.printf \" RSP+30 (arg7): %p \\n\", poi(@rsp+0x30);
.printf \" Retn address: %p \\n\\n\", poi(@rsp);
$$ Отобразить содержимое стека
k n
.echo
"
Обратите внимание на экранирующий символ(\) - он нужен, чтобы отделить параметры команды
.printf" ", от блока условий команды bm" ", т.к. они используют одинаковые символы("). Результатом работы данного скрипта будет такой лог, в который можно добавить ещё произвольное кол-во информации на своё усмотрение:
Код:
0:000> $$>a< "d:\wdbScript.txt" kernel32!GetCurrent*
Breakpoint 0 hit
1: 00000000`7736dca8 @!"kernel32!GetCurrentDirectoryA"
2: 00000000`77374d38 @!"kernel32!GetCurrentProcess"
3: 00000000`773ca210 @!"kernel32!GetCurrentConsoleFont"
4: 00000000`77372f20 @!"kernel32!GetCurrentThreadIdStub"
5: 00000000`773ca150 @!"kernel32!GetCurrentConsoleFontEx"
6: 00000000`77372f60 @!"kernel32!GetCurrentThreadStub"
7: 00000000`77374a90 @!"kernel32!GetCurrentProcessIdStub"
8: 00000000`7737b478 @!"kernel32!GetCurrentDirectoryW"
9: 00000000`773a9100 @!"kernel32!GetCurrentUmsThread"
10: 00000000`77374a98 @!"kernel32!GetCurrentProcessId"
11: 00000000`77372f68 @!"kernel32!GetCurrentThread"
12: 00000000`773a8840 @!"kernel32!GetCurrentActCtx"
13: 00000000`7737b470 @!"kernel32!GetCurrentDirectoryWStub"
14: 00000000`77374d30 @!"kernel32!GetCurrentProcessStub"
15: 00000000`7736dca0 @!"kernel32!GetCurrentDirectoryAStub"
16: 00000000`773920cc @!"kernel32!GetCurrentJaEraIndex"
17: 00000000`77372f30 @!"kernel32!GetCurrentThreadId"
0:000> g
>>> kernel32!GetCurrent* called
RCX (arg1): 000007fffffda000
RDX (arg2): 0000000000402000
R8 (arg3): 000007fffffda000
R9 (arg4): 0000000000402000
RSP+20 (arg5): 0000000000000000
RSP+28 (arg6): 0000000000000000
RSP+30 (arg7): 000000007737556d
Retn address: 000000000040200e
# Child-SP RetAddr Call Site
00 00000000`0006ff28 00000000`0040200e kernel32!GetCurrentProcessStub
01 00000000`0006ff30 00000000`00000000 image00000000_00400000+0x200e
kernel32!GetCurrentProcessStub:
00000000`77374d30 eb06 jmp kernel32!GetCurrentProcess (00000000`77374d38)
Здесь видно, что скрипт не распознаёт число аргументов у функции, поэтому выводит все возможные. Решает эту проблему база-данных, как в примере выше использует шпион Kerberos.
А что с отладчиком х64Dbg? Для него тоже можно написать аналогичный скрипт, только в этом нет необходимости, т.к. существует плагин "xAnalyzer", который декодирует аргументы всех системных DLL, причём делает это весьма качественно.
4. Выводы
В природе есть много API-шпионов, и на описанных здесь свет клином не сошёлся. Например в качестве универсального решения можно рассматривать утилиты "WinAPIOverride" и "SpyStudio", причём некоторые распространяются с исходниками, а потому изучить их гены будет проще. Но под каким именем не скрывался-бы шпион, это незаменимое оружие для отладки упакованных программ. Так, одним выстрелом мы сможем получить подробную карту вызовов api с сжатого кода, пропустив нудный процесс пошаговой распаковки. Это касается и динамической загрузки библиотек и функций через
LoadLibrary() + GetProcAddress(). В общем от шпионов одни плюсы, и ни одного минуса, а использовать их или нет - решать вам. Всем удачи, пока!
Последнее редактирование модератором: