inf158704
Участник
Offline
|
|
« : 11-09-2012 07:08 » |
|
Уважаемые программисты. Я люблю еще живую операционку win98 и хочет сделать что нибуть полезное. Основная проблема сейчас это отсутствие драйверов для нее. 3G модем и wifi были бы очень даже неплохими примочками на стареньких ноутбуках. Драйвера от XP не ставятся иной раз по причине отсутсвия одной двух функций ядра. Например для D-link DWA-140 нехватет, всего ничего, обработки NdisInitializeString. которую можно выдернуть из XP с помощю IDA и выглядит она так: ; Exported entry 136. NdisInitializeString ; Attributes: bp-based frame ; __stdcall NdisInitializeString(x, x)
public _NdisInitializeString@8 _NdisInitializeString@8 proc near
arg_0= dword ptr 8 arg_4= dword ptr 0Ch
mov edi, edi push ebp mov ebp, esp push edi mov edi, [ebp+arg_4] mov eax, edi lea ecx, [eax+1]
loc_128C3: mov dl, [eax] inc eax test dl, dl jnz short loc_128C3 push esi mov esi, [ebp+arg_0] sub eax, ecx add eax, eax mov [esi], ax add eax, 2 mov [esi+2], ax movzx eax, ax push 7473444Eh push eax push 0 call ds:__imp__ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x) test eax, eax mov [esi+4], eax pop esi jz short loc_1290B
loc_128F5: mov cl, [edi] test cl, cl jz short loc_12907 movzx cx, cl mov [eax], cx inc edi inc eax inc eax jmp short loc_128F5
loc_12907: and word ptr [eax], 0
loc_1290B: pop edi pop ebp retn 8 _NdisInitializeString@8 endp ExAllocatePoolWithTag при этом обрабатываеться Win98, а больше ничего вроде перекрестного невижу. Как универсальным решение Уолтер Они в своей книге предлагает "нижний фильтрующий драйвер" WDMSTUB.sys в котором сделаны заглужки или реализованы довольно много функция. Работа основана на расширении таблицы символических имен с помощю _PELDR_AddExportTable. Нашел вот на него описание: _PELDR_AddExportTable ---------------------------------------------- include vxdldr.inc
LRESULT CDECL PELDR_AddExportTable(PHPEEXPORTTABLE phExportTable, PSTR pszModuleName, ULONG cExportedFunctions, ULONG cExportedNames, ULONG ulOrdinalBase, PVOID *pExportNameList, PUSHORT pExportOrdinals, PVOID *pExportAddrs, PHLIST phList);
Добавляет таблицу экспорта в список экспортируемых таблиц. Использует соглашения о вызовах принятые в С.
Возвращет PELDR_ERR_NOERROR, при удачном вызове , в противном случае возвращает PELDR_ERR_MEM_NOMEMORY, что говорит о недостаточном кол-ве памяти для выполнения запроса.
phExportTable - адрес HPEEXPORTTABLE по которому находиться указатель на таблицу экспорта в случае успешного завершения ф-ции.
pszModuleName - адрес завершающейся нулем строки, содержащей имя модуля. например "VXDLDR.VXD"
cExportedFunctions - кол-во экспортируемых функций
cExportedNames - кол-во экспортируемых имен
ulOrdinalBase - значение базы для таблицы ординалов
pExportNameList - адрес массива указателей на завершающиеся нулем строки. этот список содержит экспортируемые имена модуля.
pExportOrdinals - адрес массива ординал. этот массив должен соответствовать один к одному со списком экспортируемых имен.
pExportAddrs - адрес массива экспортируемых адресов. Этот массив используется при разрешении адресов импорта. Ординал представляет собой индекс в этом массиве.
phList - адрес на хэндл списка экспортируемых таблиц. Этот параметр установлен когда клиент ограничивает список таблиц экспорта. Если значение NULL используется глобальный список таблиц экспорта. Если хэндл на который указывает phList равен NULL, создается новый локальный список таблиц экспорта.
Указатели и данные на которые ссылаются с помощью pszModuleName, pExportNameList, pExportOrdinals, pExportAddrs, или phList должны оставаться действительными до тех пока таблица экспорта не будет удалена с использованием _PELDR_RemoveExportTable. У меня проблема такая, исходник очен сложный для моего понимания. даже учитывая. что в книге дана пояснения на русском языке. А сделать я хотел вот что: для упрощения задачи сделать шаблон в который будут вставлятся куски кода выдранные из XP. На один драйвер одна функция. Есть штук пять файлов которые также экспортируют по 1 - 3 символических имени но на них нет исходников и еще непонятно будет ли всетаки система видеть эти символические имена. загрузку предпологаю сделать также как сделано сдесь, изменяя название файла в соответствии с названием функции: ; ; myDrv.inf - информационный файл для установки драйвера myDrv.sys ;
[Version] Signature="$WINDOWS NT$" DriverVer=14/07/2002,1.00.0000 Class=ABCDHardware ClassGuid={68BFDE59-4096-11d5-B627-F0E02944B7B4} Provider=%PROVIDER%
[DestinationDirs] DefaultDestDir = 10,system32\drivers ;%SystemRoot%\system32\drivers
[ClassInstall32] Addreg=ABCDHWClassReg
[ABCDHWClassReg] HKR,,,0,"Ассемблерные драйверы" HKR,,Icon,,-5
[Manufacturer] %PROVIDER%=PROVIDER
[SourceDisksNames] 1="",,
[SourceDiskFiles] myDrv.sys=1
[myDrv_CopyFiles] myDrv.sys
[PROVIDER] %PLMKDEVICE%=myDrv_Install
[myDrv_Install] CopyFiles = myDrv_CopyFiles AddReg = myDrv_AddReg
[myDrv_Install.NT] CopyFiles = myDrv_CopyFiles
[myDrv_Install.NT.Services] AddService = myDrv,0x00000002,myDrv_Install_services
[myDrv_Install.nt.FactDef]
[myDrv_Install_services] DisplayName = "myDrvservice" ServiceType = 1 ; SERVICE_KERNEL_DRIVER StartType = 3 ; SERVICE_DEMAND_START ErrorControl = 1 ; SERVICE_ERROR_NORMAL ServiceBinary = %10%\system32\drivers\myDrv.sys LoadOrderGroup = "Extended Base"
[myDrv_AddReg] HKR,,DevLoader,,"*ntkern" HKR,,NTMPDriver,,"myDrv.sys"
[myDrv_Install.FactDef]
[Strings] PROVIDER="Спасибо Юрику" PLMKDEVICE="Драйвер " Тут сразу вопрос не будет ли конфликтов при загруске? Ставил 3 разных драйвера вроде конфликтов небыло. Ну и главный вопрос может делал кто чтото подобное?
|
|
|
Записан
|
|
|
|
dE fENDER
Интересующийся
Offline
|
|
« Ответ #1 : 11-09-2012 08:58 » |
|
У меня проблема такая, исходник очен сложный для моего понимания. даже учитывая. что в книге дана пояснения на русском языке.
Что-то конкретно не ясно? непонятно будет ли всетаки система видеть эти символические имена
Напишите тест и проверьте. Тут сразу вопрос не будет ли конфликтов при загруске?
Если делать так, как у Они - не будет. Он проверяет, не существует ли уже такая функция в таблице, этот момент выделен жирным в описании. Пара советов - выдергивайте из checked билда ОС, смотрите исходники ReactOS/Win2000, попробуйте использовать hex-reys, вылизывайте обработанный код, а не вставляйте то, что выдернулось на автомате. Ну и не дергайте все подряд, только то, что нужно для конкретного драйвера.
|
|
|
Записан
|
|
|
|
inf158704
Участник
Offline
|
|
« Ответ #2 : 11-09-2012 11:10 » |
|
dE fENDER, спасибо что откликнулись Что-то конкретно не ясно? По книжке все выглядит красиво. Но вот исходник уж очень отличаеться. Напишите тест и проверьте. Насчет теста хотелось бы поподробнее узнать что можно взять за основу? Я считаю что можно обойтись без проверки для начала, можно будет и ручками выбрать те функции которые нужно подрузить, wdmcheck покажет чего нехватает, и лепить несколько функий в одну тяжеловато... я одну то пока вставить немогу... А чем вам ненравиться код который я выдрал из XP? вроде глобальные переменные не используеться или я чтото пропустил? Добавлено через 26 минут и 47 секунд:INITCODE оставлю без изменений так чтоли? хотя здесь вообще понять немогу ничего... #pragma INITCODE
#pragma warning(disable:4035)
BOOLEAN Test_Debug_Installed() { VMMCall(Test_Debug_Installed) _asm setnz al }
#pragma warning(default:4035)
extern "C" ULONG _fltused = 0;
// Flags in CR0:
#define CR0_PG 0x80000000 // paging #define CR0_ET 0x00000010 // extension type (80387) #define CR0_TS 0x00000008 // task switched #define CR0_EM 0x00000004 // emulate math coprocessor #define CR0_MP 0x00000002 // math present #define CR0_PE 0x00000001 // protection enable #define CR0_CD 0x40000000 // cache disable #define CR0_NW 0x20000000 // not write-through #define CR0_AM 0x00040000 // alignment mask #define CR0_WP 0x00010000 // write protect #define CR0_NE 0x00000020 // numeric error
BOOL CheckPrecisionErrata() { // CheckPrecisionErrata static double Dividend = 4195835.0; static double Divisor = 3145727.0; BOOL result = FALSE;
_asm { pushfd ; save flags cli mov eax, cr0 ; make sure flags are the way we need them mov ecx, eax and eax, not (CR0_TS or CR0_MP or CR0_EM) mov cr0, eax
fninit ; initialize coprocessor fld Dividend ; perform division to show up precision errata fdiv Divisor fmul Divisor fcomp Dividend fstsw ax ; capture floating point status sahf
jc noproblem jz noproblem mov result, 1 noproblem: mov cr0, ecx ; restore CR0 popfd ; restore flags (including enable state) }
return result; } // CheckPrecisionErrata
BOOLEAN DefineStubs() { // DefineStubs
// Construct the name, ordinal, and address tables for functions we're going // to stub. In various releases of Windows 98 and Millenium, some or all of // these functions will be supported by the operating system, and we don't // want to preempt the standard implementation.
stubnames = (char**) _HeapAllocate(sizeof(names) + sizeof(remlocknames), HEAPZEROINIT); // largest we might ever need if (!stubnames) return FALSE;
stubaddresses = (PFN*) _HeapAllocate(sizeof(addresses) + sizeof(remlockaddresses) + sizeof(critaddresses), HEAPZEROINIT); if (!stubaddresses) { _HeapFree(stubnames, 0); return FALSE; }
ordinals = (WORD*) _HeapAllocate((arraysize(names) + arraysize(remlocknames) + arraysize(critnames)) * sizeof(WORD), HEAPZEROINIT); if (!ordinals) { _HeapFree(stubaddresses, 0); _HeapFree(stubnames, 0); return FALSE; }
int i, istub; for (i = 0, istub = 0; i < arraysize(names); ++i) { // for each possible stub if (_PELDR_GetProcAddress((HPEMODULE) ntoskrnl, names[i], NULL) == 0) { // stub this function KdPrint((DRIVERNAME " - Stubbing %s\n", names[i])); stubnames[istub] = names[i]; ordinals[istub] = (WORD) istub; stubaddresses[istub] = addresses[i]; ++istub; } // stub this function else KdPrint((DRIVERNAME " - %s already implemented - not stubbing it\n", names[i])); } // for each possible stub
// We have a special problem with the remove lock functions, in that Win98SE leaves out // just IoRemoveLockAndWaitEx. We'll stub all of them if we find this function missing.
if (_PELDR_GetProcAddress((HPEMODULE) ntoskrnl, "IoReleaseRemoveLockAndWaitEx", NULL) == 0) { // stub remove lock functions KdPrint((DRIVERNAME " - Stubbing all remove lock functions\n")); for (i = 0; i < arraysize(remlocknames); ++i) { // for each remove lock function stubnames[istub] = remlocknames[i]; ordinals[istub] = (WORD) istub; stubaddresses[istub] = remlockaddresses[i]; ++istub; } // for each remove lock function } // stub remove lock functions else KdPrint((DRIVERNAME " - Not stubbing remove lock functions\n"));
// Always replace the critical region functions to avoid having the IRQL raised
for (i = 0; i < arraysize(critnames); ++i) { // for each critical region function KdPrint((DRIVERNAME " - Stubbing %s\n", critnames[i])); stubnames[istub] = critnames[i]; ordinals[istub] = (WORD) istub; stubaddresses[istub] = critaddresses[i]; ++istub; } // for each critical region function
// Create an export table to provide for these functions
if (_PELDR_AddExportTable(&hExportTable, ntoskrnl, istub, istub, 0, (PVOID*) stubnames, ordinals, stubaddresses, NULL) != 0) { // can't define exports KdPrint((DRIVERNAME " - Unable to define export table\n")); UndefineStubs(); return FALSE; } // can't define exports
// See if debugger running
bKdDebuggerEnabled = Test_Debug_Installed();
// Get build number from HKLM\Software\Microsoft\Windows\CurrentVersion[VersionNumber]
VMMHKEY hkey; if (_RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SETUP, &hkey) == 0) { // get value char value[64]; DWORD size = sizeof(value); if (_RegQueryValueEx(hkey, "VersionNumber", NULL, NULL, (PBYTE) value, &size) == 0) { // parse value char* p = value; cvtnum(p); // major version number if (*p == '.') ++p; cvtnum(p); // minor version number if (*p == '.') ++p; buildnum = cvtnum(p); // build number } // parse value _RegCloseKey(hkey); } // get value
// In win98 gold, define the WMILIB functions
if (buildnum < 2222) { // define wmilib exports if (_PELDR_AddExportTable(&hWmilibExportTable, wmilib, arraysize(wminames), arraysize(wmiaddresses), 0, (PVOID*) wminames, wmiordinals, wmiaddresses, NULL) != 0) { KdPrint((DRIVERNAME " - Can't stub WMILIB functions\n")); UndefineStubs(); } KdPrint((DRIVERNAME " - Stubbing WmiSystemControl and WmiCompleteRequest\n")); } // define wmilib exports
// Determine CPU feature flags
DWORD machineinfo; #undef Get_Machine_Info VMMCall(Get_Machine_Info) _asm mov machineinfo, ebx ; capture machine type flags if (machineinfo & GMIF_CPUID) { // cpuid supported _asm mov eax, 1 ; EAX = 1 => request for feature flags _asm cpuid _asm mov features, edx ; save feature flags } // cpuid supported
if (features & FEATURE_FPU) PrecisionErrata = (BOOLEAN) CheckPrecisionErrata();
// Determine the default locale for ZwQueryDefaultLocale
locale = GetSystemLocale();
return TRUE; } // DefineStubs
а вот для таблицы нашел только это: static char* names[] = { "PoRegisterSystemState", };
static PFN addresses[] = { (PFN) PoRegisterSystemState, }; а вот как организуеться (по книжке) static WORD ordinals[] = { 0, }; в исходнике немогу никак На всякий случай иходник оригинального драйвера: // WDMSTUB.CPP -- Stubs for missing Win2K WDM service functions // Copyright (C) 1998 by Walter Oney // All rights reserved
#include "stddcls.h" #include "driver.h" #include "NonStubs.h"
#define IFSMGR_SERVICES_ONLY #include "ifsmgr.h"
CCHAR cKeNumberProcessors = 1; BOOLEAN bKdDebuggerEnabled = 0;
BOOLEAN PrecisionErrata = FALSE; DWORD features = 0;
// Pentium feature flags returned in EDX from CPUID with EAX == 1
#define FEATURE_FPU 0x00000001 // FPU on chip #define FEATURE_RDTSC 0x00000010 // RDTSC instruction supported #define FEATURE_MACHINE_CHECK 0x00000080 // machine check exception can occur #define FEATURE_CMPXCHG8B 0x00000100 // CMPXCHG8B instruction supported #define FEATURE_MMX 0x00800000 // MMX instructions supported #define FEATURE_XMMI 0x02000000
#define BCS_WANSI 0 // ifs.h generates too many compile errors if we include it
extern "C" NTSYSAPI NTSTATUS NTAPI ObReferenceObjectByName(PUNICODE_STRING name, ULONG unknown1, ULONG unknown2, ULONG unknown3, POBJECT_TYPE type, KPROCESSOR_MODE mode, ULONG unknown4, PVOID *object); extern "C" POBJECT_TYPE* IoDriverObjectType;
///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
// Names of functions stubbed by this VxD. This isn't the array we actually pass // to PELDR -- it's the array we use when we construct a list of functions // that aren't already implemented by NTKERN. The names must be in resident storage // because we don't copy them when we build the export table.
static char* names[] = { "PoRegisterSystemState", "PoSetSystemState", "PoUnregisterSystemState", "IoReportTargetDeviceChangeAsynchronous", "ExSystemTimeToLocalTime", "ExLocalTimeToSystemTime", "IoCreateNotificationEvent", "IoCreateSynchronizationEvent", "IoAllocateWorkItem", "IoFreeWorkItem", "IoQueueWorkItem", "PsGetVersion", "RtlUshortByteSwap", "RtlUlongByteSwap", "RtlUlonglongByteSwap", "RtlInt64ToUnicodeString", "KeSetTargetProcessorDpc", "KeNumberProcessors", "KdDebuggerEnabled", "IoReuseIrp", "IoRaiseInformationalHardError", "HalTranslateBusAddress", "ExIsProcessorFeaturePresent", "MmGetSystemRoutineAddress", "ZwQueryInformationFile", "ZwSetInformationFile", "ZwQueryDefaultLocale", "ExFreePoolWithTag", "ZwLoadDriver", "ZwUnloadDriver", "SeSinglePrivilegeCheck", "IoSetCompletionRoutineEx", };
// As of SP-9, we're using C11 with the Xp options. String constants therefore end // up in the referencing code segment, but we need to have *this* constant persist:
static char* ntoskrnl = "ntoskrnl.exe";
static char* remlocknames[] = { "IoAcquireRemoveLockEx", "IoReleaseRemoveLockEx", "IoReleaseRemoveLockAndWaitEx", "IoInitializeRemoveLockEx", };
// The Win98 implementation of KeEnterCriticalRegion incorrectly raises the IRQL to // APC_LEVEL, so we'll stub it no matter what
static char* critnames[] = { "KeEnterCriticalRegion", "KeLeaveCriticalRegion", };
// Macros added in Xp DDK:
#undef RtlUshortByteSwap #undef RtlUlongByteSwap #undef RtlUlonglongByteSwap
USHORT FASTCALL RtlUshortByteSwap( IN USHORT Source );
ULONG FASTCALL RtlUlongByteSwap( IN ULONG Source );
ULONGLONG FASTCALL RtlUlonglongByteSwap( IN ULONGLONG Source );
NTSTATUS ZwLoadDriver(PUNICODE_STRING); NTSTATUS ZwUnloadDriver(PUNICODE_STRING);
#pragma warning(disable:4273) // inconsistent dll linkage
// Addresses of stub functions (must line up with names array)
NTSTATUS ZwQueryDefaultLocale(BOOLEAN thread, LCID* plocale);
static PFN addresses[] = { (PFN) PoRegisterSystemState, (PFN) PoSetSystemState, (PFN) PoUnregisterSystemState, (PFN) IoReportTargetDeviceChangeAsynchronous, (PFN) ExSystemTimeToLocalTime, (PFN) ExLocalTimeToSystemTime, (PFN) IoCreateNotificationEvent, (PFN) IoCreateSynchronizationEvent, (PFN) IoAllocateWorkItem, (PFN) IoFreeWorkItem, (PFN) IoQueueWorkItem, (PFN) PsGetVersion, (PFN) RtlUshortByteSwap, (PFN) RtlUlongByteSwap, (PFN) RtlUlonglongByteSwap, (PFN) RtlInt64ToUnicodeString, (PFN) KeSetTargetProcessorDpc, (PFN) &cKeNumberProcessors, (PFN) &bKdDebuggerEnabled, (PFN) IoReuseIrp, (PFN) IoRaiseInformationalHardError, (PFN) HalTranslateBusAddress, (PFN) ExIsProcessorFeaturePresent, (PFN) MmGetSystemRoutineAddress, (PFN) ZwQueryInformationFile, (PFN) ZwSetInformationFile, (PFN) ZwQueryDefaultLocale, (PFN) ExFreePoolWithTag, (PFN) ZwLoadDriver, (PFN) ZwUnloadDriver, (PFN) SeSinglePrivilegeCheck, (PFN) IoSetCompletionRoutineEx, };
static PFN remlockaddresses[] = { (PFN) IoAcquireRemoveLockEx, (PFN) IoReleaseRemoveLockEx, (PFN) IoReleaseRemoveLockAndWaitEx, (PFN) IoInitializeRemoveLockEx, };
static PFN critaddresses[] = { (PFN) KeEnterCriticalRegion, (PFN) KeLeaveCriticalRegion, };
// Win98 Gold doesn't have WMILIB. It wouldn't do any good anyway, since WMI is broken // due to user-mode bugs.
static char *wmilib = "wmilib.sys";
static char* wminames[] = { "WmiSystemControl", "WmiCompleteRequest", };
static WORD wmiordinals[] = { 0, 1, };
static PFN wmiaddresses[] = { (PFN) WmiSystemControl, (PFN) WmiCompleteRequest, };
__int64 GetZoneBias(); DWORD buildnum;
HPEEXPORTTABLE hExportTable = 0; char** stubnames; // names of functions we stubbed PFN* stubaddresses; // addresses of the stub functions WORD* ordinals; // ordinal table to correlate the other two tables
HPEEXPORTTABLE hWmilibExportTable = 0;
LCID locale; // default locale LCID GetSystemLocale(); DWORD atox(char* s); int cvtnum(char*& p);
NTSTATUS CompletionRoutineWrapper(PDEVICE_OBJECT fdo, PIRP Irp, PCOMPLETION_CONTEXT ctx);
///////////////////////////////////////////////////////////////////////////////
#pragma warning(disable:4035)
UINT __declspec(naked) __cdecl UniToBCS(PBYTE pBCSPath, WCHAR* pUniPath, UINT length, UINT maxLength, UINT charSet) { VxDJmp(UniToBCS) }
#pragma warning(default:4035)
///////////////////////////////////////////////////////////////////////////////
#pragma INITCODE
#pragma warning(disable:4035)
BOOLEAN Test_Debug_Installed() { VMMCall(Test_Debug_Installed) _asm setnz al }
#pragma warning(default:4035)
extern "C" ULONG _fltused = 0;
// Flags in CR0:
#define CR0_PG 0x80000000 // paging #define CR0_ET 0x00000010 // extension type (80387) #define CR0_TS 0x00000008 // task switched #define CR0_EM 0x00000004 // emulate math coprocessor #define CR0_MP 0x00000002 // math present #define CR0_PE 0x00000001 // protection enable #define CR0_CD 0x40000000 // cache disable #define CR0_NW 0x20000000 // not write-through #define CR0_AM 0x00040000 // alignment mask #define CR0_WP 0x00010000 // write protect #define CR0_NE 0x00000020 // numeric error
BOOL CheckPrecisionErrata() { // CheckPrecisionErrata static double Dividend = 4195835.0; static double Divisor = 3145727.0; BOOL result = FALSE;
_asm { pushfd ; save flags cli mov eax, cr0 ; make sure flags are the way we need them mov ecx, eax and eax, not (CR0_TS or CR0_MP or CR0_EM) mov cr0, eax
fninit ; initialize coprocessor fld Dividend ; perform division to show up precision errata fdiv Divisor fmul Divisor fcomp Dividend fstsw ax ; capture floating point status sahf
jc noproblem jz noproblem mov result, 1 noproblem: mov cr0, ecx ; restore CR0 popfd ; restore flags (including enable state) }
return result; } // CheckPrecisionErrata
BOOLEAN DefineStubs() { // DefineStubs
// Construct the name, ordinal, and address tables for functions we're going // to stub. In various releases of Windows 98 and Millenium, some or all of // these functions will be supported by the operating system, and we don't // want to preempt the standard implementation.
stubnames = (char**) _HeapAllocate(sizeof(names) + sizeof(remlocknames), HEAPZEROINIT); // largest we might ever need if (!stubnames) return FALSE;
stubaddresses = (PFN*) _HeapAllocate(sizeof(addresses) + sizeof(remlockaddresses) + sizeof(critaddresses), HEAPZEROINIT); if (!stubaddresses) { _HeapFree(stubnames, 0); return FALSE; }
ordinals = (WORD*) _HeapAllocate((arraysize(names) + arraysize(remlocknames) + arraysize(critnames)) * sizeof(WORD), HEAPZEROINIT); if (!ordinals) { _HeapFree(stubaddresses, 0); _HeapFree(stubnames, 0); return FALSE; }
int i, istub; for (i = 0, istub = 0; i < arraysize(names); ++i) { // for each possible stub if (_PELDR_GetProcAddress((HPEMODULE) ntoskrnl, names[i], NULL) == 0) { // stub this function KdPrint((DRIVERNAME " - Stubbing %s\n", names[i])); stubnames[istub] = names[i]; ordinals[istub] = (WORD) istub; stubaddresses[istub] = addresses[i]; ++istub; } // stub this function else KdPrint((DRIVERNAME " - %s already implemented - not stubbing it\n", names[i])); } // for each possible stub
// We have a special problem with the remove lock functions, in that Win98SE leaves out // just IoRemoveLockAndWaitEx. We'll stub all of them if we find this function missing.
if (_PELDR_GetProcAddress((HPEMODULE) ntoskrnl, "IoReleaseRemoveLockAndWaitEx", NULL) == 0) { // stub remove lock functions KdPrint((DRIVERNAME " - Stubbing all remove lock functions\n")); for (i = 0; i < arraysize(remlocknames); ++i) { // for each remove lock function stubnames[istub] = remlocknames[i]; ordinals[istub] = (WORD) istub; stubaddresses[istub] = remlockaddresses[i]; ++istub; } // for each remove lock function } // stub remove lock functions else KdPrint((DRIVERNAME " - Not stubbing remove lock functions\n"));
// Always replace the critical region functions to avoid having the IRQL raised
for (i = 0; i < arraysize(critnames); ++i) { // for each critical region function KdPrint((DRIVERNAME " - Stubbing %s\n", critnames[i])); stubnames[istub] = critnames[i]; ordinals[istub] = (WORD) istub; stubaddresses[istub] = critaddresses[i]; ++istub; } // for each critical region function
// Create an export table to provide for these functions
if (_PELDR_AddExportTable(&hExportTable, ntoskrnl, istub, istub, 0, (PVOID*) stubnames, ordinals, stubaddresses, NULL) != 0) { // can't define exports KdPrint((DRIVERNAME " - Unable to define export table\n")); UndefineStubs(); return FALSE; } // can't define exports
// See if debugger running
bKdDebuggerEnabled = Test_Debug_Installed();
// Get build number from HKLM\Software\Microsoft\Windows\CurrentVersion[VersionNumber]
VMMHKEY hkey; if (_RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SETUP, &hkey) == 0) { // get value char value[64]; DWORD size = sizeof(value); if (_RegQueryValueEx(hkey, "VersionNumber", NULL, NULL, (PBYTE) value, &size) == 0) { // parse value char* p = value; cvtnum(p); // major version number if (*p == '.') ++p; cvtnum(p); // minor version number if (*p == '.') ++p; buildnum = cvtnum(p); // build number } // parse value _RegCloseKey(hkey); } // get value
// In win98 gold, define the WMILIB functions
if (buildnum < 2222) { // define wmilib exports if (_PELDR_AddExportTable(&hWmilibExportTable, wmilib, arraysize(wminames), arraysize(wmiaddresses), 0, (PVOID*) wminames, wmiordinals, wmiaddresses, NULL) != 0) { KdPrint((DRIVERNAME " - Can't stub WMILIB functions\n")); UndefineStubs(); } KdPrint((DRIVERNAME " - Stubbing WmiSystemControl and WmiCompleteRequest\n")); } // define wmilib exports
// Determine CPU feature flags
DWORD machineinfo; #undef Get_Machine_Info VMMCall(Get_Machine_Info) _asm mov machineinfo, ebx ; capture machine type flags if (machineinfo & GMIF_CPUID) { // cpuid supported _asm mov eax, 1 ; EAX = 1 => request for feature flags _asm cpuid _asm mov features, edx ; save feature flags } // cpuid supported
if (features & FEATURE_FPU) PrecisionErrata = (BOOLEAN) CheckPrecisionErrata();
// Determine the default locale for ZwQueryDefaultLocale
locale = GetSystemLocale();
return TRUE; } // DefineStubs
///////////////////////////////////////////////////////////////////////////////
#pragma PAGEDCODE
VOID UndefineStubs() { // UndefineStubs if (hExportTable) _PELDR_RemoveExportTable(hExportTable, NULL); if (ordinals) _HeapFree(ordinals, 0); if (stubaddresses) _HeapFree(stubaddresses, 0); if (stubnames) _HeapFree(stubnames, 0);
hExportTable = NULL; ordinals = NULL; stubaddresses = NULL; stubnames = NULL;
if (hWmilibExportTable) _PELDR_RemoveExportTable(hWmilibExportTable, NULL); hWmilibExportTable = NULL; } // UndefineStubs
///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
PVOID PoRegisterSystemState(PVOID hstate, ULONG flags) { // PoRegisterSystemState ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); return NULL; } // PoRegisterSystemState
VOID PoSetSystemState(ULONG flags) { // PoSetSystemState ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); } // PoSetSystemState
VOID PoUnregisterSystemState(PVOID hstate) { // PoUnregisterSystemState ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); } // PoUnregisterSystemState
NTSTATUS IoReportTargetDeviceChangeAsynchronous(PDEVICE_OBJECT pdo, PVOID NfyStruct, PDEVICE_CHANGE_COMPLETE_CALLBACK Callback, PVOID Context) { // IoReportTargetDeviceChangeAsynchronous ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); return STATUS_NOT_IMPLEMENTED; } // IoReportTargetDeviceChangeAsynchronous
VOID ExSystemTimeToLocalTime(PLARGE_INTEGER systime, PLARGE_INTEGER localtime) { // ExSystemTimeToLocalTime localtime->QuadPart = systime->QuadPart - GetZoneBias(); } // ExSystemTimeToLocalTime
VOID ExLocalTimeToSystemTime(PLARGE_INTEGER localtime, PLARGE_INTEGER systime) { // ExLocalTimeToSystemTime systime->QuadPart = localtime->QuadPart + GetZoneBias(); } // ExLocalTimeToSystemTime
PKEVENT IoCreateNotificationEvent(PUNICODE_STRING EventName, PHANDLE EventHandle) { // IoCreateNotificationEvent ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); return NULL; } // IoCreateNotificationEvent
PKEVENT IoCreateSynchronizationEvent(PUNICODE_STRING EventName, PHANDLE EventHandle) { // IoCreateSynchronizationEvent ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); return NULL; } // IoCreateSynchronizationEvent
PIO_WORKITEM IoAllocateWorkItem(PDEVICE_OBJECT DeviceObject) { // IoAllocateWorkItem return AllocateWorkItem(DeviceObject); } // IoAllocateWorkItem
VOID IoFreeWorkItem(PIO_WORKITEM item) { // IoFreeWorkItem FreeWorkItem(item); } // IoFreeWorkItem
VOID IoQueueWorkItem(PIO_WORKITEM item, PIO_WORKITEM_ROUTINE Routine, WORK_QUEUE_TYPE QueueType, PVOID Context) { // IoQueueWorkItem QueueWorkItem(item, Routine, QueueType, Context); } // IoQueueWorkItem
BOOLEAN PsGetVersion(PULONG MajorVersion, PULONG MinorVersion, PULONG BuildNumber, PUNICODE_STRING spnum) { // PsGetVersion #undef Get_VMM_Version USHORT version; ULONG dbgver; VMMCall(Get_VMM_Version); _asm mov version, ax _asm mov dbgver, ecx
if (MajorVersion) *MajorVersion = version >> 8; if (MinorVersion) *MinorVersion = version & 255; if (BuildNumber) *BuildNumber = buildnum; if (spnum) spnum->Length = 0;
return dbgver != 0; } // PsGetVersion
NTSTATUS IoAcquireRemoveLockEx(PIO_REMOVE_LOCK p, PVOID tag, PCSTR file, ULONG line, ULONG size) { // IoAcquireRemoveLockEx ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); return AcquireRemoveLock(p, tag, file, line, size); } // IoAcquireRemoveLockEx
VOID IoReleaseRemoveLockEx(PIO_REMOVE_LOCK p, PVOID tag, ULONG size) { // IoReleaseRemoveLockEx ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); ReleaseRemoveLock(p, tag, size); } // IoReleaseRemoveLockEx
VOID IoReleaseRemoveLockAndWaitEx(PIO_REMOVE_LOCK p, PVOID tag, ULONG size) { // IoReleaseRemoveLockAndWaitEx ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); ReleaseRemoveLockAndWait(p, tag, size); } // IoReleaseRemoveLockAndWaitEx
VOID IoInitializeRemoveLockEx(PIO_REMOVE_LOCK p, ULONG tag, ULONG maxminutes, ULONG hwm, ULONG size) { // IoInitializeRemoveLockEx ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); InitializeRemoveLock(p, tag, maxminutes, hwm, size); } // IoInitializeRemoveLockEx
#pragma warning(disable:4035)
USHORT FASTCALL RtlUshortByteSwap(USHORT source) { // RtlUshortByteSwap _asm movzx eax, cx _asm xchg ah, al } // RtlUshortByteSwap
ULONG FASTCALL RtlUlongByteSwap(ULONG source) { // RtlUlongByteSwap _asm mov eax, ecx _asm bswap eax } // RtlUlongByteSwap
ULONGLONG FASTCALL RtlUlonglongByteSwap(ULONGLONG source) { // RtlUlonglongByteSwap _asm mov eax, ecx _asm xchg eax, edx _asm bswap eax _asm bswap edx } // RtlUlonglongByteSwap
#pragma warning(default:4035)
NTSTATUS RtlInt64ToUnicodeString(ULONGLONG value, ULONG base, PUNICODE_STRING string) { // RtlInt64ToUnicodeString return STATUS_NOT_IMPLEMENTED; } // RtlInt64ToUnicodeString
VOID KeEnterCriticalRegion() { // KeEnterCriticalRegion ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); } // KeEnterCriticalRegion
VOID KeLeaveCriticalRegion() { // KeLeaveCriticalRegion ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); } // KeLeaveCriticalRegion
VOID KeSetTargetProcessorDpc(PRKDPC dpc, CCHAR number) { // KeSetTargetProcessorDpc } // KeSetTargetProcessorDpc
VOID KeSetImportanceDpc(PRKDPC dpc, KDPC_IMPORTANCE importance) { // KeSetImportanceDpc } // KeSetImportanceDpc
VOID IoReuseIrp(PIRP Irp, NTSTATUS status) { // IoReuseIrp ReuseIrp(Irp, status); } // IoReuseIrp
void __cdecl MessageCallback(char* msg);
BOOLEAN IoRaiseInformationalHardError(NTSTATUS status, PUNICODE_STRING string, PKTHREAD thread) { // IoRaiseInformationalHardError char* msg = (char*) _HeapAllocate(1024, 0); if (!msg) return FALSE; if (string) { // convert string data UINT unilen = string->Length; UINT ansilen = unilen / 2; char* ansistring = (char*) _HeapAllocate(ansilen + 1, 0); if (!ansistring) { _HeapFree(msg, 0); return FALSE; }
#define BCS_OEM 1 ansistring[UniToBCS((PBYTE) ansistring, string->Buffer, unilen, ansilen, BCS_OEM)] = 0; _Sprintf(msg, "An operation failed with status %8.8lX. The operation relates to '%s'", status, ansistring); _HeapFree(ansistring, 0); } // convert string data else _Sprintf(msg, "An operation failed with status %8.8lX", status);
BOOL okay; okay = _SHELL_CallAtAppyTime((APPY_CALLBACK) MessageCallback, (DWORD) msg, 0) != 0; if (!okay) { // can't queue regular message box SHELL_SYSMODAL_Message(Get_Sys_VM_Handle(), MB_OK | MB_ICONHAND | MB_SYSTEMMODAL, msg, "Windows - Operation Failed"); _HeapFree(msg, 0); okay = TRUE; } // can't queue regular message box
return (BOOLEAN) okay; } // IoRaiseInformationalHardError
BOOLEAN HalTranslateBusAddress(INTERFACE_TYPE InterfaceType, ULONG BusNumber, PHYSICAL_ADDRESS BusAddress, PULONG AddressSpace, PPHYSICAL_ADDRESS TranslatedAddress) { // HalTranslateBusAddress ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); *TranslatedAddress = BusAddress; return TRUE; } // HalTranslateBusAddress
BOOLEAN ExIsProcessorFeaturePresent(ULONG feature) { // ExIsProcessorFeaturePresent BOOLEAN result = FALSE;
switch (feature) { // determine if feature present case PF_FLOATING_POINT_PRECISION_ERRATA: result = PrecisionErrata; break;
case PF_FLOATING_POINT_EMULATED: result = (features & FEATURE_FPU) == 0; break;
case PF_COMPARE_EXCHANGE_DOUBLE: result = (features & FEATURE_CMPXCHG8B) != 0; break;
case PF_MMX_INSTRUCTIONS_AVAILABLE: result = (features & FEATURE_MMX) != 0;
case PF_PPC_MOVEMEM_64BIT_OK: case PF_ALPHA_BYTE_INSTRUCTIONS: break; // non-x86 features
case PF_XMMI_INSTRUCTIONS_AVAILABLE: result = (features & FEATURE_XMMI) != 0; break;
case PF_3DNOW_INSTRUCTIONS_AVAILABLE: break; // assume false until somebody needs it to work...
case PF_RDTSC_INSTRUCTION_AVAILABLE: result = (features & FEATURE_RDTSC) != 0; break;
case PF_PAE_ENABLED: break; // Win98 doesn't run on phys addr extension machines } // determine if feature present
return result; } // ExIsProcessorFeaturePresent
PVOID MmGetSystemRoutineAddress(PUNICODE_STRING name) { // MmGetSystemRoutineAddress char ansiname[256]; ansiname[UniToBCS((PBYTE) ansiname, name->Buffer, name->Length, 255, BCS_WANSI)] = 0; return _PELDR_GetProcAddress((HPEMODULE) ntoskrnl, ansiname, NULL); } // MmGetSystemRoutineAddress
NTSTATUS ZwQueryInformationFile(HANDLE h, PIO_STATUS_BLOCK pstatus, PVOID fi, ULONG length, FILE_INFORMATION_CLASS c) { // ZwQueryInformationFile pstatus->Status = STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } // ZwQueryInformationFile
NTSTATUS ZwSetInformationFile(HANDLE h, PIO_STATUS_BLOCK pstatus, PVOID fi, ULONG length, FILE_INFORMATION_CLASS c) { // ZwSetInformationFile pstatus->Status = STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } // ZwSetInformationFile
NTSTATUS ZwQueryDefaultLocale(BOOLEAN thread, LCID* plocale) { // ZwQueryDefaultLocale *plocale = locale; return STATUS_SUCCESS; } // ZwQueryDefaultLocale
VOID ExFreePoolWithTag(PVOID p, ULONG tag) { // ExFreePoolWithTag ExFreePool(p); } // ExFreePoolWithTag
NTSTATUS ZwLoadDriver(PUNICODE_STRING ServiceKey) { // ZwLoadDriver return _NtKernLoadDriver(ServiceKey); } // ZwLoadDriver
NTSTATUS ZwUnloadDriver(PUNICODE_STRING ServiceKey) { // ZwUnloadDriver
// Isolate the service name from the end of the key. // This will be the name of the driver object
for (int i = ServiceKey->Length / sizeof(WCHAR) - 1; i >= 0; --i) if (ServiceKey->Buffer[i] == L'\\') break; ++i; // skip backslash int lname = ServiceKey->Length / sizeof(WCHAR) - i;
WCHAR objname[128]; wcscpy(objname, L"\\Driver\\"); memcpy(objname + 8, ServiceKey->Buffer + i, 2 * lname); objname[lname + 8] = 0; UNICODE_STRING oname; RtlInitUnicodeString(&oname, objname);
// Find the driver object
PDRIVER_OBJECT DriverObject; NTSTATUS status = ObReferenceObjectByName(&oname, 0, 0, 0, *IoDriverObjectType, KernelMode, 0, (PVOID*) &DriverObject); if (!NT_SUCCESS(status)) { KdPrint((DRIVERNAME " - Can't locate driver object %ws - %X\n", objname, status)); return status; } ObDereferenceObject(DriverObject); // remove reference from ObReferenceObjectByName
// Determine the module name by reading the registry key, backscanning // to the last backslash, and converting to ANSI
OBJECT_ATTRIBUTES oa; InitializeObjectAttributes(&oa, ServiceKey, OBJ_KERNEL_HANDLE, NULL, NULL);
HANDLE hkey; status = ZwOpenKey(&hkey, KEY_READ, &oa); if (!NT_SUCCESS(status)) { KdPrint((DRIVERNAME " - ZwOpenKey(%ws) failed - %X\n", ServiceKey->Buffer, status)); return status; }
struct foo : public _KEY_VALUE_PARTIAL_INFORMATION { UCHAR buffer[511]; } value; UNICODE_STRING valname; ULONG size; RtlInitUnicodeString(&valname, L"ImagePath"); status = ZwQueryValueKey(hkey, &valname, KeyValuePartialInformation, &value, sizeof(value), &size); ZwClose(hkey);
if (!NT_SUCCESS(status)) { KdPrint((DRIVERNAME " - ZwQueryValueKey failed - %X\n", status)); return status; }
for (i = value.DataLength / sizeof(WCHAR) - 1; i >= 0; --i) if (((PWCHAR) (value.Data))[i] == L'\\') break; ++i; lname = value.DataLength / sizeof(WCHAR) - i; memcpy(objname, value.Data + i * 2, lname * 2); objname[lname] = 0;
BYTE modname[64]; modname[UniToBCS(modname, objname, lname * 2, sizeof(modname), BCS_WANSI)] = 0; HPEMODULE hmod = _PELDR_GetModuleHandle((PSTR) modname);
if (!hmod) { KdPrint((DRIVERNAME " - Can't get module handle to %s\n", modname)); return STATUS_UNSUCCESSFUL; }
// At long last, unload the module and release the extra references to // the device object
if (DriverObject->DriverUnload) (*DriverObject->DriverUnload)(DriverObject); ObDereferenceObject(DriverObject); ObDereferenceObject(DriverObject); _PELDR_FreeModule(hmod, NULL);
return STATUS_SUCCESS; } // ZwUnloadDriver
BOOLEAN SeSinglePrivilegeCheck(LUID PrivilegeValue, KPROCESSOR_MODE PreviousMode) { // SeSinglePrivilegeCheck ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); ASSERT(PreviousMode == UserMode || PreviousMode == KernelMode); return TRUE; } // SeSinglePrivilegeCheck
NTSTATUS IoSetCompletionRoutineEx(PDEVICE_OBJECT fdo, PIRP Irp, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID Context, BOOLEAN success, BOOLEAN failure, BOOLEAN cancel) { // IoSetCompletionRoutineEx ASSERT(fdo); ASSERT(Irp); ASSERT(CompletionRoutine); ASSERT(success || failure || cancel);
PCOMPLETION_CONTEXT ctx = (PCOMPLETION_CONTEXT) _HeapAllocate(sizeof(COMPLETION_CONTEXT), 0); if (!ctx) return STATUS_INSUFFICIENT_RESOURCES; ctx->CompletionRoutine = CompletionRoutine; ctx->Context = Context; ctx->fdo = fdo;
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) CompletionRoutineWrapper, (PVOID) ctx, success, failure, cancel);
return STATUS_SUCCESS; } // IoSetCompletionRoutineEx
NTSTATUS WmiSystemControl(PWMILIB_CONTEXT WmiLibInfo, PDEVICE_OBJECT DeviceObject, PIRP Irp, PSYSCTL_IRP_DISPOSITION IrpDisposition) { // WmiSystemControl Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; IoCompleteRequest(Irp, IO_NO_INCREMENT); *IrpDisposition = IrpProcessed; return STATUS_SUCCESS; } // WmiSystemControl
NTSTATUS WmiCompleteRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp, NTSTATUS Status, ULONG BufferUsed, CCHAR PriorityBoost) { // WmiCompleteRequest ASSERT(FALSE); // shouldn't be called because no callbacks are being called return STATUS_NOT_SUPPORTED; } // WmiCompleteRequest
///////////////////////////////////////////////////////////////////////////////
void __cdecl MessageCallback(char* msg) { // MessageCallback #pragma pack(2) struct { // MessageBox parameters WORD fuStyle; // style flags DWORD lpszTitle; // title string DWORD lpszText; // message text WORD hwndParent; // parent window handle } parms; // MessageBox parameters #pragma pack()
// Construct parameter list for call to MessageBox
parms.fuStyle = MB_OK | MB_ICONHAND; parms.lpszTitle = _SHELL_LocalAllocEx(LMEM_STRING, 0, "Windows - Operation Failed"); parms.lpszText = _SHELL_LocalAllocEx(LMEM_STRING, 0, msg); parms.hwndParent = 0; // Invoke MessageBox to display the message
if (parms.lpszTitle && parms.lpszText) _SHELL_CallDll("USER", "MESSAGEBOX", sizeof(parms), &parms);
// Cleanup
if (parms.lpszText) _SHELL_LocalFree(parms.lpszText); if (parms.lpszTitle) _SHELL_LocalFree(parms.lpszTitle); _HeapFree(msg, 0); } // MessageCallback
///////////////////////////////////////////////////////////////////////////////
__int64 GetZoneBias() { // GetZoneBias DWORD hkey; if (_RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_TIMEZONE, &hkey) != 0) return 0;
__int64 bias; LONG actbias; DWORD size = sizeof(actbias);
if (_RegQueryValueEx(hkey, REGSTR_VAL_TZACTBIAS, NULL, NULL, &actbias, &size) == 0) { // compute 100-ns bias actbias *= 60; // minutes to seconds _asm mov eax, actbias _asm mov ecx, 10000000 // seconds to 100-ns units _asm imul ecx _asm mov dword ptr bias, eax _asm mov dword ptr bias+4, edx
} // compute 100-ns bias else bias = 0;
_RegCloseKey(hkey); return bias; } // GetZoneBias
///////////////////////////////////////////////////////////////////////////////
DWORD atox(char* s) { // atox DWORD result = 0; char ch; while ((ch = *s++)) { // convert hex number BYTE hexit; if (ch >= '0' && ch <= '9') hexit = ch - '0'; else if (ch >= 'A' && ch <= 'F') hexit = ch - ('A' - 10); else if ( ch >= 'a' && ch <= 'f') hexit = ch - ('a' - 10); else break; // invalid hexit -- ignore
result <<= 4; result += hexit; } // convert hex number
return result; } // atox
/////////////////////////////////////////////////////////////////////////////// // Convert ascii string to number, skipping characters
int cvtnum(char*& p) { // cvtnum int result = 0; char ch; while ((ch = *p++) && ch >= '0' && ch <= '9') { result *= 10; result += (ch - '0'); } return result; } // cvtnum
///////////////////////////////////////////////////////////////////////////////
LCID GetSystemLocale() { // GetSystemLocale LCID lcid = LOCALE_SYSTEM_DEFAULT; // in case nothing found #define REGSTR_PATH_LOCALE TEXT("System\\CurrentControlSet\\Control\\Nls\\Locale")
// Query the registry to determine the default locale
DWORD hKey; if (_RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_LOCALE, &hKey) != 0) return lcid;
char szLocale[9]; DWORD size = sizeof(szLocale); DWORD type;
if (_RegQueryValueEx(hKey, NULL, NULL, &type, (PBYTE) szLocale, &size) == 0 && type == REG_SZ) lcid = atox(szLocale);
_RegCloseKey(hKey); return lcid; } // GetSystemLocale
///////////////////////////////////////////////////////////////////////////////
#pragma warning(disable:4035)
LONG __stdcall Get_System_Time() { // Get_System_Time VMMCall(Get_System_Time) } // Get_System_Time
#pragma warning(default:4035)
///////////////////////////////////////////////////////////////////////////////
NTSTATUS CompletionRoutineWrapper(PDEVICE_OBJECT junk, PIRP Irp, PCOMPLETION_CONTEXT ctx) { // CompletionRoutineWrapper ObReferenceObject(ctx->fdo); NTSTATUS status = (*ctx->CompletionRoutine)(junk, Irp, ctx->Context); ObDereferenceObject(ctx->fdo); _HeapFree((PVOID) ctx, 0); return status; } // CompletionRoutineWrapper
|
|
« Последнее редактирование: 11-09-2012 11:37 от inf158704 »
|
Записан
|
|
|
|
dE fENDER
Интересующийся
Offline
|
|
« Ответ #3 : 11-09-2012 23:12 » |
|
Исходник потом прокомментирую поподробней, сейчас нет времени. Тест - простейший драйвер, в котором вызываете функцию (для начала одну), которой нет в 98. Там будет с десяток строк, думаю. Смотрите, что с ним происходит под ХР и под 98. Под ХР оно должно отработать, под 98, соответственно, загрузить драйвер не получится - посмотрите, как именно это происходит, хотя вы наверно уже видели. Как профессиональный программист, вы не должны пытаться обойтись без теста, а наоборот, стремиться начинать решение любой задачи с того, что пишете тесты, которые фейлятся. А затем добиваетесь, чтобы все они успешно проходили. Почитайте про test-driven development. Считайте это не просто еще одним из методов разработки, а единственным. Конечно есть множество задач, где написание тестов, корректно и полностью проверяющих правильность решения займет больше времени чем нахождение правильного решения или вообще невозможно. Но даже в таком случае лучше написать пару тестов, которые проверяют, что приложение хотя бы не заваливается. А данная задача просто предназначена для для такого подхода. Хочу подчеркнуть - без данного теста или проверки на другом драйвере (например, упомянутом вами D-link DWA-140 или что еще имеется под рукой) - т.е. без какого-то критерия правильности получается, что вы занимаетесь не решением задачи и не даже не изучением каких-то механизмов или приемов, а вообще непонятно чем. Код, который вы выдрали, мне не нравится тем, что вы вряд ли понимаете, что там происходит (это с оглядкой на то, что у вас возникли проблемы прочесть Сишный исходник), хотя может я ошибаюсь и вы с лету читаете ассемблер и видите неочевидные зависимости в коде. А сам код выдернутой функции я не даже не смотрел. Как я понимаю, вы занимаетесь этим для себя, у вас нет какого-то жесткого дедлайна и имеется достаточно большое количество времени для изучения. Ну так этим надо пользоваться чтобы во всем подробно и основательно разобраться. Более того, на собственном опыте неоднократно наблюдал, что когда ставятся жесткие и нереалистичные временные рамки и всякие далекие от процесса разработки менеджеры и начальники пытаются заставить исполнителей побыстрей лепить все из кусков левого кода, не давая им времени на изучение этого самого кода - рамки в итоге всегда срываются а полученный код не только не решает хоть какой-либо процент поставленной задачи, но и непригоден для дальнейшей доработки. По поводу данного ИДОвского ассемблера могу перечислить такого рода аргументы - лучше переносимый и читаемый код на ЯВУ, чем платформеннозависимый на ассемблере, ассемблер тяжело читать "по диагонали", не факт, что после дизассемблирования и перекомпиляции вы получите тот же самый машинный код, что был в оригинале...; дальше просто лень перечислять. Как заполняются ординалы в приведенном вами исходнике: int i, istub; // объявляем переменную istub для подсчета текущего кода ординала for (i = 0, istub = 0; i < arraysize(names); ++i)// здесь она зануляется. Обратите внимание, что она и в других циклах используется и там уже не зануляется { if (_PELDR_GetProcAddress((HPEMODULE) ntoskrnl, names[i], NULL) == 0) { ... ordinals[istub] = (WORD) istub; // Здесь в массив ординалов кидаем ее значения: [0, x, x, x, ], [0, 1, x, x, ], [0, 1, 2, x, ], [0, 1, 2, 3, ], ... ... ++istub; // А здесь она увеличивается } ... }
Настройте виртуалку и ядерный отладчик; пройдите интересующие участки по шагам - многие вопросы исчезнут. Это может быть долго и тяжело, но это надо обязательно сделать в первую очередь.
|
|
|
Записан
|
|
|
|
inf158704
Участник
Offline
|
|
« Ответ #4 : 19-12-2012 12:30 » |
|
к сожалению у меня никаких успехов... понял одно что используеться несеолько массисов static PFN addresses[] = { static PFN remlockaddresses[] = { static PFN critaddresses[] = { поэтому так услажнена INITCODE с ее проверками for (i = 0, istub = 0; i < arraysize(names); ++i) ... for (i = 0; i < arraysize(critnames); ++i) ... зачем надо было городить это все непонятно ... в старом драйвере на vxd который никаких таких заморочек невижу... только вот беда компильнуть у меня неполучаеться его... может ктото сможет подсказать в чем дело? исходники на него нашел здесь: http://web.archive.org/web/19991002220610/http://www.oneysoft.com/WdmStub.zip
|
|
|
Записан
|
|
|
|
sss
Специалист
Offline
|
|
« Ответ #5 : 19-12-2012 13:49 » |
|
inf158704, Вы не понимаете? Просто невозможно помочь в таком "широком" диапазоне узкого вопроса. Может быть другие идеи ? Я в общем не верю, что дело заключается только в NdisInitializeString (версии NDIS сходятся ?). Ну замените её запросто на RtlInitString.. Там тоже самое..
|
|
|
Записан
|
while (8==8)
|
|
|
inf158704
Участник
Offline
|
|
« Ответ #6 : 19-12-2012 14:53 » |
|
на даный момент у меня задача простая обрезать WdmStub в самый минимум оставить внедрение в ядро только одной вообще любой функции... проблема возникла на уровне обрезания INIT есть версия этого драйвера в виде SYS файла и более старая VXD VXD версия более понятная, беда только в том что я ее немогу скомпилировать... почему незнаю... ntddk.h втюхивал и от ХР и от NT компилил в си 6, компиляторы подменял из DDK 2600 пути прописывал как смог... если кто может просто прошу компильнуть у себя на нормально настроенном... без ддк98 гдето прочитал что VXD не компилиться
|
|
|
Записан
|
|
|
|
inf158704
Участник
Offline
|
|
« Ответ #7 : 19-12-2012 15:00 » |
|
inf158704, Ну замените её запросто на RtlInitString.. Там тоже самое..
где заменить? в драйвере на DLINK? у меня исходников нет... HIEWом подменить в таблице импорта? чет на сказку похоже...
|
|
|
Записан
|
|
|
|
sss
Специалист
Offline
|
|
« Ответ #8 : 20-12-2012 02:31 » |
|
где заменить?
Не в таблице импорта, а везде в коде вызов.. В таблице импорта "заглушите" NdisInitializeString чем нибудь другим, а в коде, где вызовы поставьте константу на RtlInitString из Вашей win98. Если всё дело только в одной функции, то я бы точно не стал бы мудрить с универсальным стабом. Вообще бы написал соседний драйвер, эмулятор нужной функции и заменил вызовы на него - только для тестов, далее конечно можно было бы и потрудиться над затачиванием проекта на более универсальные цели. HIEWом подменить в таблице импорта? чет на сказку похоже...
Не понимаю - технику инжекта DLL кто то отменил что ли? Ваш проект тоже не очень реален..
|
|
« Последнее редактирование: 20-12-2012 02:35 от sss »
|
Записан
|
while (8==8)
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #9 : 20-12-2012 03:49 » |
|
inf158704, направить бы твою энергию в нужное русло ))
|
|
|
Записан
|
|
|
|
inf158704
Участник
Offline
|
|
« Ответ #10 : 20-12-2012 04:13 » |
|
я отдыхаю и пытаюсь растопить толстый слой жира на мозжечке... в WOT играть надоела а ремонт дома уже прекратил Добавлено через 19 минут и 23 секунды:где заменить?
Не в таблице импорта, а везде в коде вызов.. В таблице импорта "заглушите" NdisInitializeString чем нибудь другим, а в коде, где вызовы поставьте константу на RtlInitString из Вашей win98. Если всё дело только в одной функции, то я бы точно не стал бы мудрить с универсальным стабом. Вообще бы написал соседний драйвер, эмулятор нужной функции и заменил вызовы на него - только для тестов, далее конечно можно было бы и потрудиться над затачиванием проекта на более универсальные цели. HIEWом подменить в таблице импорта? чет на сказку похоже...
Не понимаю - технику инжекта DLL кто то отменил что ли? Ваш проект тоже не очень реален.. чесно признаюсь непонял что вы имеете в виду... готовый SYS файл я немогу коректировать, можно заглушить функцию понятно в таблице импорта, хотя тут тоже есть вопрос, может ли быть в таблице 2 функции с одинаковым названием? но главное непонимаю как сделать вызов DLL из тела... допустим в асемблера ето выглядит приблиззително так другая функция но неважно: push eax push 0 call ds:__imp__ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x) test eax, eax mov [esi+4], eax pop esi а вот где вызвать можно здесь ДЛЛ вообще непредставляю каким образом еслибы это был DOS я б как вирус к концу файла прицепился и переправил CALL но некатит... скорее всего я просто незнаю и непонимаю... Добавлено через 36 минут и 25 секунд:поясню что непонял "поставьте константу на RtlInitString из" вызов это тупой CALL с адресом из таблицы а в таблице RtlInitString нет и еслибы я умел править таблицу, места там нет и даже если есть понятия неимею где обявлена ее длина и еще черт знает там что может быть
|
|
« Последнее редактирование: 20-12-2012 05:09 от inf158704 »
|
Записан
|
|
|
|
sss
Специалист
Offline
|
|
« Ответ #11 : 20-12-2012 08:19 » |
|
а в таблице RtlInitString нет
Зато есть адрес RtlInitString в системе и он не будет меняться. Вы можете один раз его найти в своей системе и он не будет меняться.. То есть заменить: call ds:__imp__ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x) на call 0x7C901225 Что сложного? Вы не верите, что он не будет изменяться от запуска к запуску? Поверьте не будет.. Если опкод получиться меньше, заполните nop-ами. Наверное не ExAllocatePoolWithTag, а NdisInitializeString? Понимаете, в качестве единственной недостающей функции у Вас именно такая, которую легко заменить. Или нет в Win98 RtlInitString ?
|
|
« Последнее редактирование: 20-12-2012 08:27 от sss »
|
Записан
|
while (8==8)
|
|
|
inf158704
Участник
Offline
|
|
« Ответ #12 : 20-12-2012 08:47 » |
|
понял буду пробовать спасибо
|
|
|
Записан
|
|
|
|
sss
Специалист
Offline
|
|
« Ответ #13 : 20-12-2012 12:25 » |
|
Удачи.
|
|
|
Записан
|
while (8==8)
|
|
|
inf158704
Участник
Offline
|
|
« Ответ #14 : 21-12-2012 10:51 » |
|
на сегодня испортил код до такого вида // WDMSTUB.CPP -- Stubs for missing Win2K WDM service functions // Copyright (C) 1998 by Walter Oney // All rights reserved
#include "stddcls.h" #include "driver.h" #include "NonStubs.h"
#define IFSMGR_SERVICES_ONLY #include "ifsmgr.h"
BOOLEAN bKdDebuggerEnabled = 0;
BOOLEAN PrecisionErrata = FALSE; DWORD features = 0;
// Pentium feature flags returned in EDX from CPUID with EAX == 1
#define FEATURE_FPU 0x00000001 // FPU on chip //#define FEATURE_RDTSC 0x00000010 // RDTSC instruction supported //#define FEATURE_MACHINE_CHECK 0x00000080 // machine check exception can occur //#define FEATURE_CMPXCHG8B 0x00000100 // CMPXCHG8B instruction supported //#define FEATURE_MMX 0x00800000 // MMX instructions supported //#define FEATURE_XMMI 0x02000000
//#define BCS_WANSI 0 // ifs.h generates too many compile errors if we include it
extern "C" NTSYSAPI NTSTATUS NTAPI ObReferenceObjectByName(PUNICODE_STRING name, ULONG unknown1, ULONG unknown2, ULONG unknown3, POBJECT_TYPE type, KPROCESSOR_MODE mode, ULONG unknown4, PVOID *object); extern "C" POBJECT_TYPE* IoDriverObjectType;
///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
// Names of functions stubbed by this VxD. This isn't the array we actually pass // to PELDR -- it's the array we use when we construct a list of functions // that aren't already implemented by NTKERN. The names must be in resident storage // because we don't copy them when we build the export table.
static char* names[] = { "PoRegisterSystemState", "KdDebuggerEnabled", };
// As of SP-9, we're using C11 with the Xp options. String constants therefore end // up in the referencing code segment, but we need to have *this* constant persist:
static char* ntoskrnl = "ntoskrnl.exe";
// The Win98 implementation of KeEnterCriticalRegion incorrectly raises the IRQL to // APC_LEVEL, so we'll stub it no matter what
#pragma warning(disable:4273) // inconsistent dll linkage
// Addresses of stub functions (must line up with names array)
static PFN addresses[] = { (PFN) PoRegisterSystemState, (PFN) &bKdDebuggerEnabled, };
// Win98 Gold doesn't have WMILIB. It wouldn't do any good anyway, since WMI is broken // due to user-mode bugs.
//static char *wmilib = "wmilib.sys";
//static char* wminames[] = { // "WmiCompleteRequest", // };
//static WORD wmiordinals[] = { // 0, // };
//static PFN wmiaddresses[] = { // (PFN) WmiCompleteRequest, // };
__int64 GetZoneBias(); DWORD buildnum;
char** stubnames; // names of functions we stubbed PFN* stubaddresses; // addresses of the stub functions WORD* ordinals; // ordinal table to correlate the other two tables
LCID locale; // default locale LCID GetSystemLocale(); DWORD atox(char* s); int cvtnum(char*& p);
NTSTATUS CompletionRoutineWrapper(PDEVICE_OBJECT fdo, PIRP Irp, PCOMPLETION_CONTEXT ctx);
///////////////////////////////////////////////////////////////////////////////
#pragma warning(disable:4035)
UINT __declspec(naked) __cdecl UniToBCS(PBYTE pBCSPath, WCHAR* pUniPath, UINT length, UINT maxLength, UINT charSet) { VxDJmp(UniToBCS) }
#pragma warning(default:4035)
///////////////////////////////////////////////////////////////////////////////
#pragma INITCODE
#pragma warning(disable:4035)
BOOLEAN Test_Debug_Installed() { VMMCall(Test_Debug_Installed) _asm setnz al }
#pragma warning(default:4035)
extern "C" ULONG _fltused = 0;
// Flags in CR0:
//#define CR0_PG 0x80000000 // paging //#define CR0_ET 0x00000010 // extension type (80387) #define CR0_TS 0x00000008 // task switched #define CR0_EM 0x00000004 // emulate math coprocessor #define CR0_MP 0x00000002 // math present //#define CR0_PE 0x00000001 // protection enable //#define CR0_CD 0x40000000 // cache disable //#define CR0_NW 0x20000000 // not write-through //#define CR0_AM 0x00040000 // alignment mask //#define CR0_WP 0x00010000 // write protect //#define CR0_NE 0x00000020 // numeric error
BOOL CheckPrecisionErrata()
{ // CheckPrecisionErrata static double Dividend = 4195835.0; static double Divisor = 3145727.0; BOOL result = FALSE;
_asm { pushfd ; save flags cli mov eax, cr0 ; make sure flags are the way we need them mov ecx, eax and eax, not (CR0_TS or CR0_MP or CR0_EM) mov cr0, eax
fninit ; initialize coprocessor fld Dividend ; perform division to show up precision errata fdiv Divisor fmul Divisor fcomp Dividend fstsw ax ; capture floating point status sahf
jc noproblem jz noproblem mov result, 1 noproblem: mov cr0, ecx ; restore CR0 popfd ; restore flags (including enable state) }
return result; } // CheckPrecisionErrata
BOOLEAN DefineStubs() { // DefineStubs
// Construct the name, ordinal, and address tables for functions we're going // to stub. In various releases of Windows 98 and Millenium, some or all of // these functions will be supported by the operating system, and we don't // want to preempt the standard implementation.
stubnames = (char**) _HeapAllocate(sizeof(names), HEAPZEROINIT); // largest we might ever need if (!stubnames) return FALSE;
stubaddresses = (PFN*) _HeapAllocate(sizeof(addresses), HEAPZEROINIT); if (!stubaddresses) { _HeapFree(stubnames, 0); return FALSE; }
ordinals = (WORD*) _HeapAllocate((arraysize(names)) * sizeof(WORD), HEAPZEROINIT); if (!ordinals) { _HeapFree(stubaddresses, 0); _HeapFree(stubnames, 0); return FALSE; }
int i, istub; for (i = 0, istub = 0; i < arraysize(names); ++i) { // for each possible stub if (_PELDR_GetProcAddress((HPEMODULE) ntoskrnl, names[i], NULL) == 0) { // stub this function KdPrint((DRIVERNAME " - Stubbing %s\n", names[i])); stubnames[istub] = names[i]; ordinals[istub] = (WORD) istub; stubaddresses[istub] = addresses[i]; ++istub; } // stub this function else KdPrint((DRIVERNAME " - %s already implemented - not stubbing it\n", names[i])); } // for each possible stub
// We have a special problem with the remove lock functions, in that Win98SE leaves out // just IoRemoveLockAndWaitEx. We'll stub all of them if we find this function missing.
// Always replace the critical region functions to avoid having the IRQL raised
// Create an export table to provide for these functions
// See if debugger running
bKdDebuggerEnabled = Test_Debug_Installed();
// Get build number from HKLM\Software\Microsoft\Windows\CurrentVersion[VersionNumber]
VMMHKEY hkey; if (_RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SETUP, &hkey) == 0) { // get value char value[64]; DWORD size = sizeof(value); if (_RegQueryValueEx(hkey, "VersionNumber", NULL, NULL, (PBYTE) value, &size) == 0) { // parse value char* p = value; cvtnum(p); // major version number if (*p == '.') ++p; cvtnum(p); // minor version number if (*p == '.') ++p; buildnum = cvtnum(p); // build number } // parse value _RegCloseKey(hkey); } // get value
// In win98 gold, define the WMILIB functions
// Determine CPU feature flags
DWORD machineinfo; #undef Get_Machine_Info VMMCall(Get_Machine_Info) _asm mov machineinfo, ebx ; capture machine type flags if (machineinfo & GMIF_CPUID) { // cpuid supported _asm mov eax, 1 ; EAX = 1 => request for feature flags _asm cpuid _asm mov features, edx ; save feature flags } // cpuid supported
if (features & FEATURE_FPU) PrecisionErrata = (BOOLEAN) CheckPrecisionErrata();
// Determine the default locale for ZwQueryDefaultLocale
locale = GetSystemLocale();
return TRUE; } // DefineStubs
///////////////////////////////////////////////////////////////////////////////
#pragma PAGEDCODE
VOID UndefineStubs() { // UndefineStubs
if (ordinals) _HeapFree(ordinals, 0); if (stubaddresses) _HeapFree(stubaddresses, 0); if (stubnames) _HeapFree(stubnames, 0);
ordinals = NULL; stubaddresses = NULL; stubnames = NULL;
} // UndefineStubs
///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
PVOID PoRegisterSystemState(PVOID hstate, ULONG flags) { // PoRegisterSystemState ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); return NULL; } // PoRegisterSystemState
#pragma warning(disable:4035)
#pragma warning(default:4035)
void __cdecl MessageCallback(char* msg);
NTSTATUS WmiCompleteRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp, NTSTATUS Status, ULONG BufferUsed, CCHAR PriorityBoost) { // WmiCompleteRequest ASSERT(FALSE); // shouldn't be called because no callbacks are being called return STATUS_NOT_SUPPORTED; } // WmiCompleteRequest
///////////////////////////////////////////////////////////////////////////////
void __cdecl MessageCallback(char* msg) { // MessageCallback #pragma pack(2) struct { // MessageBox parameters WORD fuStyle; // style flags DWORD lpszTitle; // title string DWORD lpszText; // message text WORD hwndParent; // parent window handle } parms; // MessageBox parameters #pragma pack()
// Construct parameter list for call to MessageBox
parms.fuStyle = MB_OK | MB_ICONHAND; parms.lpszTitle = _SHELL_LocalAllocEx(LMEM_STRING, 0, "Windows - Operation Failed"); parms.lpszText = _SHELL_LocalAllocEx(LMEM_STRING, 0, msg); parms.hwndParent = 0; // Invoke MessageBox to display the message
if (parms.lpszTitle && parms.lpszText) _SHELL_CallDll("USER", "MESSAGEBOX", sizeof(parms), &parms);
// Cleanup
if (parms.lpszText) _SHELL_LocalFree(parms.lpszText); if (parms.lpszTitle) _SHELL_LocalFree(parms.lpszTitle); _HeapFree(msg, 0); } // MessageCallback
///////////////////////////////////////////////////////////////////////////////
__int64 GetZoneBias() { // GetZoneBias DWORD hkey; if (_RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_TIMEZONE, &hkey) != 0) return 0;
__int64 bias; LONG actbias; DWORD size = sizeof(actbias);
if (_RegQueryValueEx(hkey, REGSTR_VAL_TZACTBIAS, NULL, NULL, &actbias, &size) == 0) { // compute 100-ns bias actbias *= 60; // minutes to seconds _asm mov eax, actbias _asm mov ecx, 10000000 // seconds to 100-ns units _asm imul ecx _asm mov dword ptr bias, eax _asm mov dword ptr bias+4, edx
} // compute 100-ns bias else bias = 0;
_RegCloseKey(hkey); return bias; } // GetZoneBias
///////////////////////////////////////////////////////////////////////////////
DWORD atox(char* s) { // atox DWORD result = 0; char ch; while ((ch = *s++)) { // convert hex number BYTE hexit; if (ch >= '0' && ch <= '9') hexit = ch - '0'; else if (ch >= 'A' && ch <= 'F') hexit = ch - ('A' - 10); else if ( ch >= 'a' && ch <= 'f') hexit = ch - ('a' - 10); else break; // invalid hexit -- ignore
result <<= 4; result += hexit; } // convert hex number
return result; } // atox
/////////////////////////////////////////////////////////////////////////////// // Convert ascii string to number, skipping characters
int cvtnum(char*& p) { // cvtnum int result = 0; char ch; while ((ch = *p++) && ch >= '0' && ch <= '9') { result *= 10; result += (ch - '0'); } return result; } // cvtnum
///////////////////////////////////////////////////////////////////////////////
LCID GetSystemLocale() { // GetSystemLocale LCID lcid = LOCALE_SYSTEM_DEFAULT; // in case nothing found #define REGSTR_PATH_LOCALE TEXT("System\\CurrentControlSet\\Control\\Nls\\Locale")
// Query the registry to determine the default locale
DWORD hKey; if (_RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_LOCALE, &hKey) != 0) return lcid;
char szLocale[9]; DWORD size = sizeof(szLocale); DWORD type;
if (_RegQueryValueEx(hKey, NULL, NULL, &type, (PBYTE) szLocale, &size) == 0 && type == REG_SZ) lcid = atox(szLocale);
_RegCloseKey(hKey); return lcid; } // GetSystemLocale
///////////////////////////////////////////////////////////////////////////////
#pragma warning(disable:4035)
LONG __stdcall Get_System_Time() { // Get_System_Time VMMCall(Get_System_Time) } // Get_System_Time
#pragma warning(default:4035)
///////////////////////////////////////////////////////////////////////////////
NTSTATUS CompletionRoutineWrapper(PDEVICE_OBJECT junk, PIRP Irp, PCOMPLETION_CONTEXT ctx) { // CompletionRoutineWrapper ObReferenceObject(ctx->fdo); NTSTATUS status = (*ctx->CompletionRoutine)(junk, Irp, ctx->Context); ObDereferenceObject(ctx->fdo); _HeapFree((PVOID) ctx, 0); return status; } // CompletionRoutineWrapper
появились вопросы /// The Win98 implementation of KeEnterCriticalRegion incorrectly raises the IRQL to // APC_LEVEL, so we'll stub it no matter what
#pragma warning(disable:4273) // inconsistent dll linkage
// Addresses of stub functions (must line up with names array)
static PFN addresses[] = { (PFN) PoRegisterSystemState, (PFN) &bKdDebuggerEnabled, };
// Win98 Gold doesn't have WMILIB. It wouldn't do any good anyway, since WMI is broken // due to user-mode bugs.
static char *wmilib = "wmilib.sys";
static char* wminames[] = { "WmiCompleteRequest", };
static WORD wmiordinals[] = { 0, };
static PFN wmiaddresses[] = { (PFN) WmiCompleteRequest,
// In win98 gold, define the WMILIB functions
if (buildnum < 2222) { // define wmilib exports if (_PELDR_AddExportTable(&hWmilibExportTable, wmilib, arraysize(wminames), arraysize(wmiaddresses), 0, (PVOID*) wminames, wmiordinals, wmiaddresses, NULL) != 0) { KdPrint((DRIVERNAME " - Can't stub WMILIB functions\n")); UndefineStubs(); } KdPrint((DRIVERNAME " - Stubbing WmiSystemControl and WmiCompleteRequest\n")); } // define wmilib exports
// In win98 gold, define the WMILIB functions
// Determine CPU feature flags
DWORD machineinfo; #undef Get_Machine_Info VMMCall(Get_Machine_Info) _asm mov machineinfo, ebx ; capture machine type flags if (machineinfo & GMIF_CPUID) { // cpuid supported _asm mov eax, 1 ; EAX = 1 => request for feature flags _asm cpuid _asm mov features, edx ; save feature flags } // cpuid supported
if (features & FEATURE_FPU) PrecisionErrata = (BOOLEAN) CheckPrecisionErrata();
// Determine the default locale for ZwQueryDefaultLocale
locale = GetSystemLocale();
return TRUE; } // DefineStubs
чем отличаеться экспорт функций kernel от функций WMILIB static char *wmilib = "wmilib.sys"; static char* ntoskrnl = "ntoskrnl.exe" вижу что они используются в проверке наличия уже в системе а вот как загрузятся функции в систему в едином массиве или отделно... в общем вопрос в чем отличии и надо ли мне это сохранить это разделение... #include "stddcls.h" #include "driver.h" #include "NonStubs.h" для чего все это подгружаеться, куча импорта осталось знадьбы хоть приблизительно что нужно а что нет...
|
2.JPG (46.69 Кб - загружено 876 раз.)
|
« Последнее редактирование: 21-12-2012 12:34 от inf158704 »
|
Записан
|
|
|
|
inf158704
Участник
Offline
|
|
« Ответ #15 : 09-01-2013 06:27 » |
|
прошу прошения у специалистов... задам еще пару глупых вопросов... при компИляции VXD имею след ошибку Compiling... Stdvxd.cpp .\ntddk.h(370) : error C2146: syntax error : missing ';' before identifier 'Lock' .\ntddk.h(370) : error C2501: 'PULONG_PTR' : missing storage-class or type specifiers .\ntddk.h(370) : error C2501: 'Lock' : missing storage-class or type specifiers .\ntddk.h(824) : error C2146: syntax error : missing ';' before identifier 'KSPIN_LOCK' .\ntddk.h(824) : fatal error C1004: unexpected end of file found Error executing cl.exe. имею следующее в файле ntddk.h:
typedef struct _KDPC { CSHORT Type; UCHAR Number; UCHAR Importance; LIST_ENTRY DpcListEntry; PKDEFERRED_ROUTINE DeferredRoutine; PVOID DeferredContext; PVOID SystemArgument1; PVOID SystemArgument2; PULONG_PTR Lock; } KDPC, *PKDPC, *RESTRICTED_POINTER PRKDPC; ... typedef ULONG_PTR KSPIN_LOCK;
предпологаю что гдето чтото неописано... может даст ктото подсказочку
а вообще мнебы было интересно как составлять файл sources чтонибуть бы поподробнее
еще вопрос компиляция идет через ddk98 DDKXP получаеться неумеет VXD делать?
пытаюсь откомпилировать следующее ntddk.h из папки w2k копирую в папку проекта остальные пути вроде есть ntddk.h из папки xp дает ошибу версии
|
|
« Последнее редактирование: 09-01-2013 16:53 от Ochkarik »
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #16 : 09-01-2013 16:27 » |
|
эм... а там вообще ntddk.h нужен? Добавлено через 4 минуты и 20 секунд:сейчас глянул свой старый проект... честно, уже не помню чего там было, и вряд ли вспомню, но включал я следующее: #include <vxdlib.h> #include <vxdmain.h> //To be included in this file only #include <vpicd.h> #include <vxdwraps.h> #define WANTVXDWRAPS
#include <vmmreg.h> #include <configmg.h> #include <regstr.h> #include <memory.h> #include <conio.h> PS использовать DDKXP - скорее всего нет, VxD был только до Win98/me включительно. и уже в 98 была поддержка WDM. PPS про "как составлять файл sources чтонибуть бы поподробнее" - все и даже больше есть тут How to Use the Build Utility
|
|
« Последнее редактирование: 09-01-2013 16:58 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
inf158704
Участник
Offline
|
|
« Ответ #17 : 10-01-2013 09:26 » |
|
эм... а там вообще ntddk.h нужен? пытаюсь понять но похоже в ntddk.h какраз описаны некотроые функции, попытался отключить в Stdvxd.cpp компиляцию начало проходить, далее попытался отключить в NonStubs.cpp тут уже вылазит следующая ошибка... onStubs.cpp C:\WINDDK\WdmStub.VXD\NonStubs.cpp(11) : warning C4164: 'memset' : intrinsic function not declared это на #pragma intrinsic(memset) в принципе как нестрашно а вот далее идет NonStubs.h и дает ошибку c:\WINDDK\WdmStub.VXD\NonStubs.h(8 ) : error C2065: 'NTAPI' : undeclared identifier c:\WINDDK\WdmStub.VXD\NonStubs.h(8 ) : error C2065: 'PIO_WORKITEM_ROUTINE' : undeclared identifier c:\WINDDK\WdmStub.VXD\NonStubs.h(8 ) : error C2296: '*' : illegal, left operand has type ''unknown-type'' c:\WINDDK\WdmStub.VXD\NonStubs.h(8 ) : error C2297: '*' : illegal, right operand has type ''unknown-type'' c:\WINDDK\WdmStub.VXD\NonStubs.h(8 ) : error C2501: 'VOID' : missing storage-class or type specifiers c:\WINDDK\WdmStub.VXD\NonStubs.h(8 ) : fatal error C1903: unable to recover from previous error(s); stopping compilation на эту строку typedef VOID (NTAPI *PIO_WORKITEM_ROUTINE)(PDEVICE_OBJECT DeviceObject, PVOID Context); вот тут похоже мне и нужен ntddk.h толко для чего пытаюсь понять да и далше думаю ntddk понадобиться... чтото похожее нашел здесь буду ковыряться неспеша http://www.gamedev.ru/flame/forum?id=60601
|
|
« Последнее редактирование: 10-01-2013 09:58 от inf158704 »
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #18 : 10-01-2013 18:49 » |
|
когда возился с 95/98 пяток нужных функций пришлось выдирать с мясом и класть в свой h-файл... по хорошему надо открыть DDK от 95го и посмотреть были ли они там в VxD разделе, либо они там в принципе не описаны - тогда драть откуда есть) в частности если WORKITEM - это все что вам нужно... ну определите свой тип) путь это и не кошерно) либо посмотрите какая функция его еще использует и откуда она берет это определение. PS о че нашел! http://read.pudn.com/downloads186/sourcecode/embed/871957/C8051F34x/USB_Bulk/Driver_Source/bulkwdm98.cpp__.htm
|
|
« Последнее редактирование: 10-01-2013 18:54 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
inf158704
Участник
Offline
|
|
« Ответ #19 : 28-01-2013 09:00 » |
|
все с vxd драйвером сдаюсь 1 так и несмог разобраться, попробовал сделать по аналогии как подсказывали все никак 2 нашел интересное местечко в sys а именно: static char *wmilib = "wmilib.sys"; \\ вот эта строка меня особенно озадачила
static char* wminames[] = { "WmiSystemControl", "WmiCompleteRequest", };
static WORD wmiordinals[] = { 0, 1, };
static PFN wmiaddresses[] = { (PFN) WmiSystemControl, (PFN) WmiCompleteRequest, };
. . . if (buildnum < 2222) { // define wmilib exports if (_PELDR_AddExportTable(&hWmilibExportTable, wmilib, arraysize(wminames), arraysize(wmiaddresses), 0, (PVOID*) wminames, wmiordinals, wmiaddresses, NULL) != 0) { KdPrint((DRIVERNAME " - Can't stub WMILIB functions\n")); UndefineStubs(); } KdPrint((DRIVERNAME " - Stubbing WmiSystemControl and WmiCompleteRequest\n")); } // define wmilib exports . . . NTSTATUS WmiSystemControl(PWMILIB_CONTEXT WmiLibInfo, PDEVICE_OBJECT DeviceObject, PIRP Irp, PSYSCTL_IRP_DISPOSITION IrpDisposition) { // WmiSystemControl Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; IoCompleteRequest(Irp, IO_NO_INCREMENT); *IrpDisposition = IrpProcessed; return STATUS_SUCCESS; } // WmiSystemControl
NTSTATUS WmiCompleteRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp, NTSTATUS Status, ULONG BufferUsed, CCHAR PriorityBoost) { // WmiCompleteRequest ASSERT(FALSE); // shouldn't be called because no callbacks are being called return STATUS_NOT_SUPPORTED; } // WmiCompleteRequest
получаеться что kernel и wmi функции экспортируються отдельно... а не в общей таблице, и похоже static char *wmilib = "wmilib.sys" указывает к чему эт относятся... дале, я пытаюсь втюхать системе ndis функию, но в win98 часть функций в ndis.vxd попытался сделать по аналогии пока просто тупо повторив с изменением названий... // Добавление фукций NDIS
static char *ndislib = "ndis.vxd"; // в оригинале .sys
static char* ndisnames[] = { "NdisInitializeString", };
static WORD ndisordinals[] = { 0, };
static PFN ndisaddresses[] = { (PFN) NdisInitializeString, };
// конец обявления функций NDIS . . . // загрузка NDIS функции if (buildnum < 2222) { // define wmilib exports if (_PELDR_AddExportTable(&hWmilibExportTable, ndislib, arraysize(ndisnames), arraysize(ndisaddresses), 0, (PVOID*) ndisnames, ndisordinals, ndisaddresses, NULL) != 0) //arraysize(wmiaddresses), 0, (PVOID*) wminames, wmiordinals, wmiaddresses, NULL) != 0) { KdPrint((DRIVERNAME " - Can't stub NDIS functions\n")); UndefineStubs(); } KdPrint((DRIVERNAME " - Stubbing NdisInitializeString\n")); } // define wmilib exports // конец загрузки NDIS функции . . . // добавление тела NDIS
NTSTATUS NdisInitializeString(PDEVICE_OBJECT DeviceObject, PIRP Irp, NTSTATUS Status, ULONG BufferUsed, CCHAR PriorityBoost) { // NdisInitializeString ASSERT(FALSE); // shouldn't be called because no callbacks are being called return STATUS_NOT_SUPPORTED; } // NdisInitializeString
// конец добавление тела NDIS результат нулевой к сожалению компильнуть несмог C:\WINDDK\Newstub_0\wdmstub.cpp(211) : error C2065: 'NdisInitializeString' : undeclared identifier C:\WINDDK\Newstub_0\wdmstub.cpp(914) : error C2365: 'NdisInitializeString' : redefinition; previous definition was a 'formerly unknown identifier' есть тут еще расчет адресов stubnames = (char**) _HeapAllocate(sizeof(names) + sizeof(remlocknames), HEAPZEROINIT); // largest we might ever need if (!stubnames) return FALSE;
stubaddresses = (PFN*) _HeapAllocate(sizeof(addresses) + sizeof(remlockaddresses) + sizeof(critaddresses), HEAPZEROINIT); if (!stubaddresses) { _HeapFree(stubnames, 0); return FALSE; }
ordinals = (WORD*) _HeapAllocate((arraysize(names) + arraysize(remlocknames) + arraysize(critnames)) * sizeof(WORD), HEAPZEROINIT); if (!ordinals) { _HeapFree(stubaddresses, 0); _HeapFree(stubnames, 0); return FALSE; } хотя это относится толко к первому блоку загрузки ntkernel_овскому, полной уверенности нет сама функция которую мне нужно добавить на сайте МС описана так NdisInitializeString is implemented only on Windows 2000. A miniport that uses NdisInitializeString fails to load on Windows 98. A binary compatible miniport uses the following macro instead. #define NdisInitializeString(Destination,Source) \
{\ PNDIS_STRING _D = (Destination);\ UCHAR *_S = (Source);\ WCHAR *_P;\ _D->Length = (strlen(_S)) * sizeof(WCHAR);\ _D->MaximumLength = _D->Length + sizeof(WCHAR);\ NdisAllocateMemory((PVOID *)&(_D->Buffer), _D->MaximumLength, 0, (-1));\ _P = _D->Buffer;\ while(*_S != '\0'){\ *_P = (WCHAR)(*_S);\ _S++;\ _P++;\ }\ *_P = UNICODE_NULL;\ } но с этим буду потом разбираться понимаю, что отнимаю драгоценное время но если кто подскажет буду рад
|
|
« Последнее редактирование: 28-01-2013 09:36 от inf158704 »
|
Записан
|
|
|
|
inf158704
Участник
Offline
|
|
« Ответ #20 : 01-02-2013 11:44 » |
|
вроде как разобрался что нетак но вопросов стало еще больше обнаружил непонятку
static char* names[] = { "PoRegisterSystemState", //1 "NdisInitializeString", };
static PFN addresses[] = { (PFN) PoRegisterSystemState, //1 (PFN) NdisInitializeString, }; немогу поменять имя выходит как раз таже ошибка C:\WINDDK\Newstub1.1name\wdmstub.cpp(101) : error C2065: 'NdisInitializeString' : undeclared identifier тоесть как понимаю эти имена заявлены гдето...
где заявлены эти имена незнаю походе идут вместе с библиотеками правильно все понимаю?
в ndis.h вот нашел это, но вроде как совсем нето
EXPORT VOID NdisInitializeString( OUT PNDIS_STRING Destination, IN PUCHAR Source );
|
|
« Последнее редактирование: 01-02-2013 16:41 от inf158704 »
|
Записан
|
|
|
|
inf158704
Участник
Offline
|
|
« Ответ #21 : 14-03-2013 05:55 » |
|
продвинулся немного с мертвой точки. чтобы приняла имя добавил #include <ndis.h> в файл stddcls.h, для облегчения работы выделил загрузку моей функции в отделную секцию //NDIS static char *ndislib = "ndis.sys";
static char* ndisnames[] = { "NdisInitializeString", //ndis };
static WORD ndisordinals[] = { 0, };
static PFN ndisaddresses[] = { (PFN) NdisInitializeString, //ndis с проверкой условия проверки пока решил незаморачиваться если версия 2222 win98SE будет подгружать //NDIS if (buildnum = 2222) { // define ndislib exports if (_PELDR_AddExportTable(&hNdislibExportTable, ndislib, arraysize(ndisnames), arraysize(ndisaddresses), 0, (PVOID*) ndisnames, ndisordinals, ndisaddresses, NULL) != 0) { KdPrint((DRIVERNAME " - Can't stub ndislib functions\n")); UndefineStubs(); } KdPrint((DRIVERNAME " - Stubbing WmiSystemControl and WmiCompleteRequest\n")); } // define ndislib exports
теперь самое сложное с телом: пока обозначил его просто // ndis VOID NdisInitializeString(PNDIS_STRING destination, PUCHAR source) { // NdisInitializeString есть вопросики по этому поводу имена переменный взл из ndis.h destination и source по этому поводу вопрос небудет ли у меня с этим какихто проблем? Получил интересный совет по поводу тела, чтобы небыло болших сложностей с переделкой выдраных из иды кусков мне предложили не делать асемблерную вставку как таковую так как при этом возникают сложности с передачей аргумента через стек, тоесть асемблер сам вставляет работу со стеком POP и PUSH, тоесть их надо будет убирать и тут много головной боли. А посоветовали мне делавь вставочку при линковании. Тоесть функцию отдельно компилировать в OBJ а потом линковать вместе. переделочка при этом будет выглядить так: ; Exported entry 136. NdisInitializeString ; Attributes: bp-based frame ; __stdcall NdisInitializeString(x, x)
;public _NdisInitializeString@8 ;_NdisInitializeString@8 proc near
;---------------------------------------------------- ;ml /c ndis.asm .486 .model flat, stdcall option casemap:none externdef ExAllocatePoolWithTag@12:PROC .code NdisInitializeString@8 proc C ;----------------------------------------------------
arg_0= dword ptr 8 arg_4= dword ptr 0Ch
mov edi, edi push ebp mov ebp, esp push edi mov edi, [ebp+arg_4] mov eax, edi lea ecx, [eax+1]
loc_128C3: mov dl, [eax] inc eax test dl, dl jnz short loc_128C3 push esi mov esi, [ebp+arg_0] sub eax, ecx add eax, eax mov [esi], ax add eax, 2 mov [esi+2], ax movzx eax, ax push 7473444Eh push eax push 0
;call ds:__imp__ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x)
;---------------------------------------------------- call ExAllocatePoolWithTag@12 ;----------------------------------------------------
test eax, eax mov [esi+4], eax pop esi jz short loc_1290B
loc_128F5: mov cl, [edi] test cl, cl jz short loc_12907 movzx cx, cl mov [eax], cx inc edi inc eax inc eax jmp short loc_128F5
loc_12907: and word ptr [eax], 0
loc_1290B: pop edi pop ebp retn 8 ;_NdisInitializeString@8 endp
;---------------------------------------------------- NdisInitializeString@8 endp ;---------------------------------------------------- end NdisInitializeString@8
вот только теперя я непонимаю как у меня все это срастется, как будет передача аргументов идти в функцию, как линкер разберется с названием функции NdisInitializeString@8 = NdisInitializeString нужно ли мне вообще обявлять VOID NdisInitializeString(PNDIS_STRING destination, PUCHAR source) { // NdisInitializeString или при линкоке она вставится сама?
|
|
« Последнее редактирование: 15-03-2013 12:07 от inf158704 »
|
Записан
|
|
|
|
inf158704
Участник
Offline
|
|
« Ответ #22 : 18-04-2013 04:34 » |
|
всем спасибо продолжу свой монолог склероз замучил, хоть тут напишу, чтоб вспомнить потом... http://forum.ru-board.com/topic.cgi?forum=33&topic=4420#1тоесть в си задать сылку на тело мне надо приблизительно так: extern "C" void NdisInitializeString(PNDIS_STRING , PUCHAR) - здесь в переменных нужно указать тип или имя непонятно... еще одна болная точка: должно быть так call ds:__imp__ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x) это вызов из таблицы импорта сейчас я компилирую OBJ с вызовом externdef ExAllocatePoolWithTag@12:PROC . . . call ExAllocatePoolWithTag@12 у меня идет ошибка при сборке драйвера: Creating library objchk_wxp_x86\i386\wdmstub.lib and object objchk_wxp_x86\i386\wdmstub.exp ndis.obj : error LNK2019: unresolved external symbol __ExAllocatePoolWithTag@12 referenced in function __NdisInitializeString@8 Wdmstub.obj : error LNK2019: unresolved external symbol __imp__NdisInitializeString@8 referenced in function _$E5 objchk_wxp_x86\i386\wdmstub.sys : fatal error LNK1120: 2 unresolved externals Error executing link.exe. при дизасемблировании obj листинг такой push eax push 0 call _ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x) test eax, eax mov [esi+4], eax какже всетаки я должен вызывать ExAllocatePoolWithTag в асемблере
|
|
« Последнее редактирование: 18-04-2013 06:26 от inf158704 »
|
Записан
|
|
|
|
|