Всем привет. Я тут новенький и программирую по вашим меркам не очень. В ядре копаюсь меньше недли У меня возникли некоторые сложности с перехватом API функции NtWriteVirtualMemory в ядре. делал я это подменом адреса функции в таблице SST. Все что мне нужно это HANDLE процесса куда пишут. В перехвате я пихаю значение HANDLE в char* переменную: sprintf(s, "%d", HProcess); и пишу в файл : WriteToFile(s); Вот некоторые значения которые я получил перехватом : 1480, 612, 2280. Адрес NtWriteVirtualMemory в таблице я принял как 0x0115 (для Win XP). Файл в который я записываю все полученные HANDLE я открываю и по ним получаю PID процесса. Делаю я это следующим образом (код на Delphi): readln(f, h); // мой хэндл, прочитанный из текстового файла (каждый ХЭНДЛ на новой строке) ZwQueryInformationProcess(h, ProcessBasicInformation, @ProcessInfo, SizeOf(_PROCESS_BASIC_INFORMATION), nil); и потом посылаю полученный PID (ProcessInfo.UniqueProcessId) в функцию которая возвращает положение EXE файла на диске данного процесса: Код (Text): function GetProcExe(PID: DWORD): string; var Handle: THandle; begin Result := ''; Handle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PID); if Handle <> 0 then try SetLength(Result, MAX_PATH); if GetModuleFileNameEx(Handle, 0, PChar(Result), MAX_PATH) > 0 then begin SetLength(Result, StrLen(PChar(Result))); if Pos('\??\',result) = 1 then Delete(result,1,4); if pos('\SystemRoot\',result) = 1 then begin delete(result, 1, 12); insert(GetWinDir, result, 1); end; end else Result := ''; finally CloseHandle(Handle); end; end; Так вот... в конце концов все проделанное возвращает мне пустую строку, и вообще полученный ProcessInfo.UniqueProcessId не существует (все полученные PID'ы очень большие - 1244564 (пример)). Еще я заметил что для разных HANDLE'ов соответствуют одни и те же PID'ы =\ Помогите пожалуйста мне с этой проблемой. Все то же я реализовал в 3ем кольце и все работает. А в нулевом никак не получается. Буду очень благодарен.
Я хочу получить правильный PID процесса В который пишут информацию при помощи NtWriteVirtualMemory и путь до EXE файла этого приложения.
Ясен пень, можно несколько раз открыть один и тот же процесс. Вообще рекомендую делать ObReferenceObjectByHandle для хендла, извлекать PEPROCESS и сразу скидывать на диск уже PID, потому что хендлы имеют свойство (не ядерные) быть уникальными для каждого контекста, поэтому хендл в другом контексте скорее всего будет невалидным, как у тебя и получается. Проблема в том, что ты скидываешь хендл на диск в режиме ядра в контексте процесса, который хочет записывать, а дальше в ринг3 читаешь хендл и работаешь с ним в контексте уже СВОЕГо процесса, поэтому хендл в нем будет неверным. Скорее всего, ZwQueryInformationProcess возвращает тебе STATUS_INVALID_PARAMETER или что-то в этом роде. Вывод: Скидывай на диск PID'ы, они уникальны в пределах системы.
Возвращаемое значение PID опять каке-то старнное... Process HANDLE: 2544; Process PID: 1697541224 Получаю следующим образом : Код (Text): ULONG GetPid(HANDLE PHanlde) { NTSTATUS st = 15; PEPROCESS process = 0; ULONG pId; st = ObReferenceObjectByHandle(PHanlde, 0, NULL, UserMode, &process, NULL); if (st == STATUS_SUCCESS) { pId = *(PULONG)(((ULONG)process) + pIdOffset); ObDereferenceObject(process); return pId; } return 0; } ///////////////////////////// pIdOffset получаю так: void GetProcessNameOffset() { PEPROCESS curproc; int i; curproc = PsGetCurrentProcess(); for( i = 0; i < 3*PAGE_SIZE; i++ ) { if( !strncmp( "System", (PCHAR) curproc + i, strlen("System") )) { pIdOffset = i; } } }
омг)) оно же возвращает смещение ProcessName, а не PID =)))) Вот у тебя в PID и оказываются первые 4 буквы названия процесса. 1697541224 = 652E6C68 = "hl.e" судя по всему это какойто hl.exe
Нашел ответ... Прочитал вот тут http://www.nowa.cc/showpost.php?s=e05bb1a635c50e755d5f443052aba588&p=612977&postcount=11 что PidOffset для Win 200 = $09C а для Win Xp = $084. Все работает отлично, все ПИДЫ валидные. Теперь возникает вопрос - является ли значение PidOffset константой для каждой из систем. Или оно может меняться у одной и той же операционной системы?
А никто не знает, если осуществлять перехват методом замены кодов в начале функции. Вот если перехватываемая функция не экспортирована в ntddk.h то чтобы ее экспортировать в свой драйвер для перехвата что нада сделать ? Я делал так : Код (Text): extern NTSYSAPI NTSTATUS NTAPI NtWriteVirtualMemory( IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN PVOID Buffer, IN ULONG BufferLength, OUT PULONG ReturnLength OPTIONAL ); При компиляции пишет: 1>driver.obj : error LNK2019: unresolved external symbol __imp__NtWriteVirtualMemory@20 referenced in function _TrueNtWriteVirtualMemory@20 1>objfre\i386\ProtectProcess.sys : fatal error LNK1120: 1 unresolved externals
Про перехват методом замены в таблице адреса я читал. У меня все получается перехватывать, но я хочу попробовать сделать тоже самое методом замены кодов в начале функции. Это невозможно сделать для NtWriteVirtualMemory ? =\
я же говорю, MsRem не только про правку SDT писал, но и про сплайсинг. А для NtWriteVirtualMemory тоже возможно его сделать, только адрес надо брать из SDT.
Код (Text): HANDLE PsGetProcessId(IN PEPROCESS Process); LPSTR NTAPI PsGetProcessImageFileName(PEPROCESS Process); http://msdn2.microsoft.com/en-us/library/aa906762.aspx http://www.reactos.org/generated/doxygen/d2/d9f/ntoskrnl_2ps_2process_8c.html#a31 Далеко не лучший пример для подражания, особенно в kernel-mode (я имею ввиду именно сплайсинг) Лучше почитать MSDN. а есть ли в этом большая необходимость? если нет - перехватывай лучше в SSDT