На днях появилась потребность выяснить по какому протоколу общается токен при изготовлении цифровой подписи.
Производитель токена не дает документацию на команды APDU. Пришлось осваивать новую для меня технику оталдки библиотек DLL.
Суть метода в том, чтобы вставить между программой и самой DLL свою шпионскую библиотеку, которая будет вести журнал по используемым вызовам и писать отладочную информацию в файл.
Источником вдохновения послужил открытый проект APDUView, но для моей задачи оказался не применим. Устарел. Поэтому пришлось самоу писать практически с нуля.
Идея в том чтобы создать пустую библиотеку, которая будет передавать прозрачным образом все вызовы на другую библиотеку DLL. Шпионскую библиотеку назовем тем же именем WinSCard.DLL и подложим в папку приложения. Исходную библиотеку назовем словом original.dll.
Источником вдохновения послужил открытый проект APDUView, но для моей задачи оказался не применим. Устарел. Поэтому пришлось самоу писать практически с нуля.
Идея в том чтобы создать пустую библиотеку, которая будет передавать прозрачным образом все вызовы на другую библиотеку DLL. Шпионскую библиотеку назовем тем же именем WinSCard.DLL и подложим в папку приложения. Исходную библиотеку назовем словом original.dll.
- Создаем пустую библиотеку. Для этого надо экспортировать список ВСЕХ вызовов исходной библиотеки. Я не придумал, как это сделать средствами GNU, воспользовался бесплатной утилитой взятой где-то на просторах интернета. Полученный список вызовов вбил в файл original.def.
; Пример заполнения файла original.def
LIBRARY winscard
EXPORTS
ClassInstall32
SCardAccessNewReaderEvent
SCardReleaseAllEvents
SCardReleaseNewReaderEvent
SCardAccessStartedEvent
. . .
- Компилируем пустую библиотеку по определениям original.def. Я использую консоль MinGW/MSYS.
# dlltool original.def --output-lib liboriginal.a
- Создаем файл определений для шпионской WinSCard.DLL. Каждая строчка файла определений в файле winscard.def должна содержать экспорт откуда берется функция, из какой иной библиотеки. Исключение составляет та функция, которая подвергается отладке.
; Пример заполнения файла winscard.def
LIBRARY winscard
EXPORTS
ClassInstall32=original.ClassInstall32
SCardAccessNewReaderEvent=original.SCardAccessNewReaderEvent
; надо указать все вызовы, пропускаю для краткости изложения
; . . .
SCardStatusW=original.SCardStatusW
; команды APDU передаются через вызов SCardTransmit
SCardTransmit
SCardWriteCacheA=original.SCardWriteCacheA
SCardWriteCacheW=original.SCardWriteCacheW
g_rgSCardRawPci=original.g_rgSCardRawPci DATA
g_rgSCardT0Pci=original.g_rgSCardT0Pci DATA
g_rgSCardT1Pci=original.g_rgSCardT1Pci DATA - Надо реализовать функцию SCardTransmit и писать в файл журнала данные, которые приходят от приложения и возвращаются функцией.
//! \file winscard.c BOOL WINAPI DllMain(HINSTANCE hDllInst, DWORD fdwReason) { switch (fdwReason) { case DLL_PROCESS_ATTACH: hOriginal = LoadLibrary("original.dll"); Original_SCardTransmit =GetProcAddress(hOriginal,"SCardTransmit"); break; case DLL_PROCESS_DETACH: FreeLibrary(hOriginal); break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: break; default: return FALSE; } return TRUE; }
DLL_EXPORT LONG WINAPI SCardTransmit(. . .) { LONG result = (*Original_SCardTransmit)(. . .); //! \todo сохраняем праметры и результ в журнал return result; }
- Компилируем шпионскую библиотеку
# gcc -shared -L. -loriginal -o winscard.dll winscard.def winscard.c
- Копируем исходную библиотеку WinSCard.DLL в original.dll. Копируем шпионскую библиотеку с тем же именем в папку приложения.
- Запускаем приложение и и наблюдаем результат.
Комментариев нет:
Отправить комментарий