Перехват API в ядре (NtWriteVirtualMemory).

Тема в разделе "WASM.WIN32", создана пользователем WaterGhost, 15 июн 2007.

  1. WaterGhost

    WaterGhost New Member

    Публикаций:
    0
    Регистрация:
    15 июн 2007
    Сообщения:
    130
    Всем привет. Я тут новенький и программирую по вашим меркам не очень. В ядре копаюсь меньше недли :)
    У меня возникли некоторые сложности с перехватом 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):
    1. function GetProcExe(PID: DWORD): string;
    2. var
    3.   Handle: THandle;
    4. begin
    5.   Result := '';
    6.   Handle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PID);
    7.   if Handle <> 0 then
    8.     try
    9.       SetLength(Result, MAX_PATH);
    10.       if GetModuleFileNameEx(Handle, 0, PChar(Result), MAX_PATH) > 0 then
    11.         begin
    12.           SetLength(Result, StrLen(PChar(Result)));
    13.           if Pos('\??\',result) = 1 then Delete(result,1,4);
    14.           if pos('\SystemRoot\',result) = 1 then
    15.             begin
    16.               delete(result, 1, 12);
    17.               insert(GetWinDir, result, 1);
    18.             end;
    19.         end else Result := '';
    20.     finally
    21.       CloseHandle(Handle);
    22.     end;
    23. end;
    Так вот... в конце концов все проделанное возвращает мне пустую строку, и вообще полученный ProcessInfo.UniqueProcessId не существует (все полученные PID'ы очень большие - 1244564 (пример)).

    Еще я заметил что для разных HANDLE'ов соответствуют одни и те же PID'ы =\

    Помогите пожалуйста мне с этой проблемой. Все то же я реализовал в 3ем кольце и все работает. А в нулевом никак не получается. Буду очень благодарен.
     
  2. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    что ты хочешь сделать.
     
  3. WaterGhost

    WaterGhost New Member

    Публикаций:
    0
    Регистрация:
    15 июн 2007
    Сообщения:
    130
    Я хочу получить правильный PID процесса В который пишут информацию при помощи NtWriteVirtualMemory и путь до EXE файла этого приложения.
     
  4. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Ясен пень, можно несколько раз открыть один и тот же процесс.
    Вообще рекомендую делать ObReferenceObjectByHandle для хендла, извлекать PEPROCESS и сразу скидывать на диск уже PID, потому что хендлы имеют свойство (не ядерные) быть уникальными для каждого контекста, поэтому хендл в другом контексте скорее всего будет невалидным, как у тебя и получается.
    Проблема в том, что ты скидываешь хендл на диск в режиме ядра в контексте процесса, который хочет записывать, а дальше в ринг3 читаешь хендл и работаешь с ним в контексте уже СВОЕГо процесса, поэтому хендл в нем будет неверным. Скорее всего, ZwQueryInformationProcess возвращает тебе STATUS_INVALID_PARAMETER или что-то в этом роде.

    Вывод: Скидывай на диск PID'ы, они уникальны в пределах системы.
     
  5. WaterGhost

    WaterGhost New Member

    Публикаций:
    0
    Регистрация:
    15 июн 2007
    Сообщения:
    130
    О! Спасибо за конкретный ответ. Щас буду пробовать) О результатах сообщу.
     
  6. WaterGhost

    WaterGhost New Member

    Публикаций:
    0
    Регистрация:
    15 июн 2007
    Сообщения:
    130
    Возвращаемое значение PID опять каке-то старнное...

    Process HANDLE: 2544; Process PID: 1697541224

    Получаю следующим образом :

    Код (Text):
    1. ULONG GetPid(HANDLE PHanlde)
    2. {
    3. NTSTATUS st = 15;
    4. PEPROCESS process = 0;
    5. ULONG pId;
    6.  
    7. st = ObReferenceObjectByHandle(PHanlde, 0, NULL, UserMode, &process, NULL);
    8.  
    9. if (st == STATUS_SUCCESS)
    10. {
    11. pId = *(PULONG)(((ULONG)process) + pIdOffset);
    12.  
    13. ObDereferenceObject(process);
    14.  
    15. return pId;
    16. }
    17. return 0;
    18. }
    19. /////////////////////////////
    20. pIdOffset получаю так:
    21.  
    22. void GetProcessNameOffset()
    23. {
    24.     PEPROCESS curproc;
    25.     int i;
    26.     curproc = PsGetCurrentProcess();
    27.     for( i = 0; i < 3*PAGE_SIZE; i++ )
    28.     {
    29.         if( !strncmp( "System", (PCHAR) curproc + i, strlen("System") ))
    30.         {
    31.             pIdOffset = i;
    32.         }
    33.     }
    34. }
     
  7. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    омг)) оно же возвращает смещение ProcessName, а не PID =))))
    Вот у тебя в PID и оказываются первые 4 буквы названия процесса.

    1697541224 = 652E6C68 = "hl.e"
    судя по всему это какойто hl.exe
     
  8. WaterGhost

    WaterGhost New Member

    Публикаций:
    0
    Регистрация:
    15 июн 2007
    Сообщения:
    130
    Я просто в это еще не врубаю толком. А не подскажешь как твоим методом получить PID? =\
     
  9. WaterGhost

    WaterGhost New Member

    Публикаций:
    0
    Регистрация:
    15 июн 2007
    Сообщения:
    130
    Нашел ответ...

    Прочитал вот тут

    http://www.nowa.cc/showpost.php?s=e05bb1a635c50e755d5f443052aba588&p=612977&postcount=11

    что PidOffset для Win 200 = $09C а для Win Xp = $084.

    Все работает отлично, все ПИДЫ валидные.

    Теперь возникает вопрос - является ли значение PidOffset константой для каждой из систем. Или оно может меняться у одной и той же операционной системы?
     
  10. Nouzui

    Nouzui New Member

    Публикаций:
    0
    Регистрация:
    17 ноя 2006
    Сообщения:
    856
    как? это?? не падало???
     
  11. WaterGhost

    WaterGhost New Member

    Публикаций:
    0
    Регистрация:
    15 июн 2007
    Сообщения:
    130
    Неа, не падало =\ а что должно? В BSOD? =\
     
  12. Nouzui

    Nouzui New Member

    Публикаций:
    0
    Регистрация:
    17 ноя 2006
    Сообщения:
    856
    WaterGhost
    ну типа того.. как мне, наивному, раньше казалось..
     
  13. WaterGhost

    WaterGhost New Member

    Публикаций:
    0
    Регистрация:
    15 июн 2007
    Сообщения:
    130
    А никто не знает, если осуществлять перехват методом замены кодов в начале функции. Вот если перехватываемая функция не экспортирована в ntddk.h то чтобы ее экспортировать в свой драйвер для перехвата что нада сделать ?

    Я делал так :
    Код (Text):
    1. extern
    2. NTSYSAPI
    3. NTSTATUS
    4. NTAPI
    5. NtWriteVirtualMemory(
    6.     IN HANDLE ProcessHandle,
    7.     IN PVOID BaseAddress,
    8.     IN PVOID Buffer,
    9.     IN ULONG BufferLength,
    10.     OUT PULONG ReturnLength OPTIONAL
    11.     );
    При компиляции пишет:

    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
     
  14. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    она не экспортируется.
    а про сплайсинг у того же MsRem'a почитать можешь.
     
  15. WaterGhost

    WaterGhost New Member

    Публикаций:
    0
    Регистрация:
    15 июн 2007
    Сообщения:
    130
    Про перехват методом замены в таблице адреса я читал. У меня все получается перехватывать, но я хочу попробовать сделать тоже самое методом замены кодов в начале функции. Это невозможно сделать для NtWriteVirtualMemory ? =\
     
  16. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    я же говорю, MsRem не только про правку SDT писал, но и про сплайсинг.
    А для NtWriteVirtualMemory тоже возможно его сделать, только адрес надо брать из SDT.
     
  17. Deyton

    Deyton Member

    Публикаций:
    0
    Регистрация:
    7 мар 2007
    Сообщения:
    94
    Код (Text):
    1. HANDLE  PsGetProcessId(IN PEPROCESS  Process);
    2. 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