перехват console i/o

Тема в разделе "WASM.BEGINNERS", создана пользователем red_mould, 12 авг 2011.

  1. red_mould

    red_mould New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2010
    Сообщения:
    34
    Доброго времени суток форумчане. Возник такой вопрос, каким образом перехватить ввод/вывод консольного приложения на уровне ядра. Суть в чем, есть консольная прога, которая выводит например отладочные выводы или еще что-то в консоль, каким образом этот вывод перехватить из драйвера? Как выловить что программа загружается я в курсе. Можно конечно решить проблему с инжектом длл в процесс, но что-то мне кажется это не особо по феншую. Пошерстил по форуму, толкового ничего не нашел (хз, может плохо искал). Подскажите плиз...
     
  2. shchetinin

    shchetinin Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    715
    Console IO это пайп, но только не именнованный ..

    Остается вопрос как достать хендлы
    GetStdHandle
    Код (Text):
    1. .text:7D85BBC1                 push    ebp
    2. .text:7D85BBC2                 mov     ebp, esp
    3. .text:7D85BBC4                 cmp     [ebp+nStdHandle], 0FFFFFFF4h
    4. .text:7D85BBC8                 push    esi
    5. .text:7D85BBC9                 jz      short loc_7D85BC2C
    6. .text:7D85BBCB                 cmp     [ebp+nStdHandle], 0FFFFFFF5h
    7. .text:7D85BBCF                 jz      short loc_7D85BC06
    8. .text:7D85BBD1                 cmp     [ebp+nStdHandle], 0FFFFFFF6h
    9. .text:7D85BBD5                 jz      short loc_7D85BBDC
    10. .text:7D85BBD7                 or      esi, 0FFFFFFFFh
    11. .text:7D85BBDA                 jmp     short loc_7D85BC40
    12. .text:7D85BBDC ; ---------------------------------------------------------------------------
    13. .text:7D85BBDC
    14. .text:7D85BBDC loc_7D85BBDC:                           ; CODE XREF: GetStdHandle(x)+16j
    15. .text:7D85BBDC                 mov     eax, large fs:18h
    16. .text:7D85BBE2                 mov     eax, [eax+30h]
    17. .text:7D85BBE5                 mov     eax, [eax+10h]
    18. .text:7D85BBE8                 test    dword ptr [eax+68h], 200h
    19. .text:7D85BBEF                 jz      short loc_7D85BBF5
    20. .text:7D85BBF1
    21. .text:7D85BBF1 loc_7D85BBF1:                           ; CODE XREF: GetStdHandle(x)+5Aj
    22. .text:7D85BBF1                 xor     esi, esi
    23. .text:7D85BBF3                 jmp     short loc_7D85BC4A
    24. .text:7D85BBF5 ; ---------------------------------------------------------------------------
    25. .text:7D85BBF5
    26. .text:7D85BBF5 loc_7D85BBF5:                           ; CODE XREF: GetStdHandle(x)+30j
    27. .text:7D85BBF5                 mov     eax, large fs:18h
    28. .text:7D85BBFB                 mov     eax, [eax+30h]
    29. .text:7D85BBFE                 mov     eax, [eax+10h]
    30. .text:7D85BC01                 mov     esi, [eax+18h]
    31. .text:7D85BC04                 jmp     short loc_7D85BC3B
    32. .text:7D85BC06 ; ---------------------------------------------------------------------------
    33. .text:7D85BC06
    34. .text:7D85BC06 loc_7D85BC06:                           ; CODE XREF: GetStdHandle(x)+10j
    35. .text:7D85BC06                 mov     eax, large fs:18h
    36. .text:7D85BC0C                 mov     eax, [eax+30h]
    37. .text:7D85BC0F                 mov     eax, [eax+10h]
    38. .text:7D85BC12                 test    dword ptr [eax+68h], 400h
    39. .text:7D85BC19                 jnz     short loc_7D85BBF1
    40. .text:7D85BC1B                 mov     eax, large fs:18h
    41. .text:7D85BC21                 mov     eax, [eax+30h]
    42. .text:7D85BC24                 mov     eax, [eax+10h]
    43. .text:7D85BC27                 mov     esi, [eax+1Ch]
    44. .text:7D85BC2A                 jmp     short loc_7D85BC3B
    Код (Text):
    1. #define STD_INPUT_HANDLE    ((DWORD)-10)
    2. #define STD_OUTPUT_HANDLE   ((DWORD)-11)
    3. #define STD_ERROR_HANDLE    ((DWORD)-12)
    Ну думаю теперь понятно ...
     
  3. red_mould

    red_mould New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2010
    Сообщения:
    34
    Угу, в принципе понятно, спасибо за пояснение, сейчас буду пробовать перехватить это все добро и перенаправлять на себя...
     
  4. red_mould

    red_mould New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2010
    Сообщения:
    34
    Или лыжи не едут или я, без пяти минут академик. Ну хендлы вроде как я в свое дровере достал. Только прикол в том что там ничего нет.... Мож я что-то не так делаю...
    Вот кодес как я достаю хендлы i/o
    Код (Text):
    1. ntStatus = ZwQueryInformationProcess(NtCurrentProcess(), ProcessBasicInformation, &pi, sizeof(PROCESS_BASIC_INFORMATION), &retLen);
    2.    if (!NT_SUCCESS(ntStatus))
    3.    {
    4.       DPRINT("ZwQueryInformationProcess was failed\n");
    5.       return ntStatus;
    6.    }
    7.    hStdin = pi.PebBaseAddress->ProcessParameters->StandardInput;
    8.    hStdout = pi.PebBaseAddress->ProcessParameters->StandardOutput;
    Ну и смотрю в отладчике - все нормально, достаются хендлы... Только вот теперь каким образом мне вытянуть что именно печатается на консоли и что-то туда написать?
     
  5. h0t

    h0t Member

    Публикаций:
    0
    Регистрация:
    3 апр 2011
    Сообщения:
    735
    я бы read/write пакеты айпа перехватывал...
     
  6. red_mould

    red_mould New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2010
    Сообщения:
    34
    дык уже по всякому пытался... Что-то никак... Уже практически целый день убил...
     
  7. shchetinin

    shchetinin Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    715
    Ну прекрастно раз достал, теперь надо создать свои и подсунуть(пайпы соедененные с пайп сервером из драйвера) и когда по ним предут данные(которые вы подсунули), обработать их у себя и отправить дальше. (Потребуется делать СsrCall )
    Что бы их обработать надо будет транслейт им сделать.

    Да уж ... получилось довольно таки сложно ... Можно конечно перехватить СsrCall, но если был редирект к файлам(или по пайпам) то соответсвенно вызова не будет, так что много предется перехватывать(СsrCall,Read,Write как минимум, ну и конечно смотреть что это за хендлы).
     
  8. red_mould

    red_mould New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2010
    Сообщения:
    34
    shchetinin
    Спасибо большое за консультации...
    Что-то возникли проблемы с созданием пайпа на уровне ядра(или лыжи не едут или я без пяти минут академик...), уже попытался использовать несколько методов (ядро оказывается не экспортирует эту ф-ю а с IoCreateFile вылазят проблемы, ну и пайпа не создается). Решил попробовать дернуть эту ф-ю через ssdt, но покамесь не знаю чем это все дело закончиться. Есть ли какой-то еще метод создание пайпы в kernel mode? Уже несколько ночей морочусь. Заранее спасибо за помощь.
     
  9. shchetinin

    shchetinin Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    715
    Через IoCreateFile реализовываеш NtCreateNamedPipe.

    Кому давно кидал ипл:

    Код (Text):
    1. typedef struct _NAMED_PIPE_CREATE_PARAMETERS
    2. {
    3. ULONG NamedPipeType;
    4. ULONG ReadMode;
    5. ULONG CompletionMode;
    6. ULONG MaximumInstances;
    7. ULONG InboundQuota;
    8. ULONG OutboundQuota;
    9. LARGE_INTEGER DefaultTimeout;
    10. UCHAR TimeoutSpecified;
    11. } NAMED_PIPE_CREATE_PARAMETERS,
    12. *PNAMED_PIPE_CREATE_PARAMETERS;
    13.  
    14. NTSTATUS
    15. NtCreateNamedPipeFile (
    16. OUT PHANDLE FileHandle,
    17. IN ULONG DesiredAccess,
    18. IN POBJECT_ATTRIBUTES ObjectAttributes,
    19. OUT PIO_STATUS_BLOCK IoStatusBlock,
    20. IN ULONG ShareAccess,
    21. IN ULONG CreateDisposition,
    22. IN ULONG CreateOptions,
    23. IN ULONG NamedPipeType,
    24. IN ULONG ReadMode,
    25. IN ULONG CompletionMode,
    26. IN ULONG MaximumInstances,
    27. IN ULONG InboundQuota,
    28. IN ULONG OutboundQuota,
    29. IN PLARGE_INTEGER DefaultTimeout OPTIONAL
    30. )
    31. {
    32. NAMED_PIPE_CREATE_PARAMETERS NamedPipeParms;
    33. NTSTATUS Status;
    34. __try
    35. {
    36. if ( DefaultTimeout ) {
    37. NamedPipeParms.TimeoutSpecified = TRUE;
    38. NamedPipeParms.DefaultTimeout.QuadPart = DefaultTimeout->QuadPart;
    39. }
    40. else {
    41. NamedPipeParms.TimeoutSpecified = FALSE;
    42. }
    43. NamedPipeParms.NamedPipeType = NamedPipeType;
    44. NamedPipeParms.ReadMode = ReadMode;
    45. NamedPipeParms.CompletionMode = CompletionMode;
    46. NamedPipeParms.MaximumInstances = MaximumInstances;
    47. NamedPipeParms.InboundQuota = InboundQuota;
    48. NamedPipeParms.OutboundQuota = OutboundQuota;
    49. Status = IoCreateFile (
    50. FileHandle,
    51. DesiredAccess,
    52. ObjectAttributes,
    53. IoStatusBlock,
    54. NULL,
    55. 0,
    56. ShareAccess,
    57. CreateDisposition,
    58. CreateOptions,
    59. NULL,
    60. 0,
    61. CreateFileTypeNamedPipe,
    62. &NamedPipeParms,
    63. 0
    64. );
    65. return Status;
    66. }
    67. __except (EXCEPTION_EXECUTE_HANDLER)  {
    68.   KdPrint ((«NtCreateNamedPipeFile: Exception occured.\n»));
    69. return STATUS_UNSUCCESSFUL;
    70. }
    71. }
    Ну и пример вызова:
    Код (Text):
    1. Status = NtCreateNamedPipeFile(
    2. &PipeHandle,                                  // Out pipe handle
    3. SYNCHRONIZE | GENERIC_WRITE | GENERIC_READ,    // Desired access mask to pipe instance
    4. &ObjectAttributes,                             // Attributes of the pipe instance
    5. &Iosb,                                         // Status of the IO Block
    6. FILE_SHARE_WRITE | FILE_SHARE_READ,            // Share access mask to pipe instance
    7. FILE_OPEN_IF,
    8. 0,
    9. FILE_PIPE_BYTE_STREAM_TYPE,
    10. FILE_PIPE_BYTE_STREAM_MODE,
    11. FILE_PIPE_QUEUE_OPERATION,
    12. 255, //max instance
    13. 800,
    14. 800,
    15. &DefaultTimeOut
    16. );
    Атрибуты для пайпа, очень важно так как не все приложения будут иметь большие права их нужно занулить:)
    Код (Text):
    1. Status = RtlCreateSecurityDescriptor (
    2. &SecurityDescriptor,
    3. SECURITY_DESCRIPTOR_REVISION
    4. );
    5.  
    6. Status = RtlSetDaclSecurityDescriptor (
    7. &SecurityDescriptor,
    8. TRUE,
    9. NULL,
    10. FALSE
    11. );
    12.  
    13. InitializeObjectAttributes(
    14. &ObjectAttributes,
    15. &NamedPipeName,
    16. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
    17. NULL,
    18. &SecurityDescriptor
    19. );
     
  10. red_mould

    red_mould New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2010
    Сообщения:
    34
    2 shchetinin
    Большое спасибо за консультацию. Пробовал я такой метод. Ну даже еще раз решил уже тупо скопипастить с примерчика... Короче говоря постоянно IoCreateFile возвращает статус -1073741773. Уже блин не знаю что делать. По разному пробовал... Ну тему дернуть из SSDT что-то тоже макросы не помогают.
    Мож я что-то прощелкал? Вот как я юзаю это все дело:
    Код (Text):
    1.   RtlInitUnicodeString(&usStdinName, L"\\??\\device\\NamedPipe\\PipeStdin");
    2.    UNICODE_STRING usStdoutName = RTL_CONSTANT_STRING(L"\\??\\pipe\\PipeStdout");
    3.    LARGE_INTEGER DefaultTimeOut = {0};
    4.    
    5.    //for pipe
    6.    SECURITY_DESCRIPTOR SecurityDescriptor;
    7.  
    8.    DriverObject->DriverUnload = UnloadDriver;
    9.  
    10.    status = RtlCreateSecurityDescriptor (
    11.       &SecurityDescriptor,
    12.       SECURITY_DESCRIPTOR_REVISION
    13.       );
    14.    status = RtlSetDaclSecurityDescriptor (
    15.       &SecurityDescriptor,
    16.       TRUE,
    17.       NULL,
    18.       FALSE
    19.       );
    20.    InitializeObjectAttributes(&oaAttributes,&usStdinName,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL, &SecurityDescriptor);
    21.  
    22.    status = CreateNamedPipeFile(&hNewStdin,     // Out pipe handle
    23.                            SYNCHRONIZE | GENERIC_WRITE | GENERIC_READ,    // Desired access mask to pipe instance
    24.                            &oaAttributes,
    25.                            &iosbStatus,
    26.                            FILE_SHARE_READ | FILE_SHARE_WRITE ,
    27.                            FILE_OPEN_IF,
    28.                            0,
    29.                            FILE_PIPE_BYTE_STREAM_TYPE,
    30.                            FILE_PIPE_BYTE_STREAM_MODE,
    31.                            FILE_PIPE_QUEUE_OPERATION,
    32.                            255,     //max instance
    33.                            800,
    34.                            800,
    35.                            &DefaultTimeOut);
    36.    if (!NT_SUCCESS(status))
    37.    {
    38.       DPRINT("Can not open pipe stdin\n");
    39.       return status;
    40.    }
    Ну а сама ф-я просто скопипащена... Проверяю на ХР... Помогите плиз, уже хз сколько времени убил, кажется на вроде как простенькую задачу...
     
  11. shchetinin

    shchetinin Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    715
    Error = STATUS_OBJECT_NAME_INVALID
    L"\\??\\device\\NamedPipe\\PipeStdin" не правильно
    Переделайте на
    L"\\??\\pipe\\PipeStdin"
    Должно работать.
     
  12. red_mould

    red_mould New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2010
    Сообщения:
    34
    В общем прикол в том что я так пробовал. По большому счету L"\\??\\pipe\\PipeStdin" это просто сслка на \\??\\device\\NamedPipe. В общем выдает ошибку STATUS_OBJECT_NAME_NOT_FOUND... Это я пытался делать из DriverEntry. Если попытаться создать именнованный пайп в процессе(когда я вытягиваю хендлы), то вылизит STATUS_ACCESS_VIOLATION...
     
  13. shchetinin

    shchetinin Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    715
    По ходу где то с параметрами ошибся смотрите :
    http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/NtCreateNamedPipeFile.html

    Это какой пайп создаешь? Новый или пытаешся добратся до существующего?
     
  14. red_mould

    red_mould New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2010
    Сообщения:
    34
    Ну планирую создать новый и подсунуть дескриптор нового пайпа заместо существующего стандартного. Ну например StandardInput
     
  15. shchetinin

    shchetinin Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    715
    red_mould
    Проверяйте входные параметры и этот хендел должен остатся в ядре, а вот к нему который должен присоединится уйтед в приложения.
     
  16. red_mould

    red_mould New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2010
    Сообщения:
    34
    shchetinin
    Еще раз большое спасибо за консультации и за помощь, разобрался я как создать пайп в ядре =). И уже нормально создается. Там проблемы были с параметрами...
     
  17. red_mould

    red_mould New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2010
    Сообщения:
    34
    <<del>> сори за офтоп, решил проблему
     
  18. red_mould

    red_mould New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2010
    Сообщения:
    34
    Всем форумчанам доброго времени суток. У меня опять или лыжи не едут или сам без 5 минут академик. В общем проблема в следующем. Создаю пайп в DriverEntry
    Код (Text):
    1. UNICODE_STRING usStdinName;
    2.    RtlInitUnicodeString(&usStdinName, L"\\??\\PIPE\\StdinPipe");
    3.  
    4.    LARGE_INTEGER DefaultTimeOut;
    5.    
    6.    //for pipe
    7.    SECURITY_DESCRIPTOR SecurityDescriptor = {SECURITY_DESCRIPTOR_REVISION,0,SE_DACL_PRESENT};
    8.  
    9.    DriverObject->DriverUnload = UnloadDriver;
    10.  
    11.    BPOINT;
    12.    
    13.    KeInitializeEvent(&evKill, SynchronizationEvent, FALSE);
    14.    KeInitializeEvent(&evGetHandle, SynchronizationEvent, FALSE);
    15.    DefaultTimeOut.QuadPart=-1;
    16.    InitializeObjectAttributes(&oaAttributes,&usStdinName, OBJ_CASE_INSENSITIVE|/*OBJ_INHERIT|*/OBJ_KERNEL_HANDLE, NULL, &SecurityDescriptor);
    17.    ntStatus = NtCreateNamedPipeFile(&hNewStdin,     // Out pipe handle
    18.                                  FILE_READ_ATTRIBUTES|FILE_READ_DATA|/*FILE_WRITE_ATTRIBUTES|FILE_WRITE_DATA|*/FILE_CREATE_PIPE_INSTANCE,
    19.                                  &oaAttributes,
    20.                                  &iosbStatus,
    21.                                  FILE_SHARE_READ/*|FILE_SHARE_WRITE*/,
    22.                                  FILE_OPEN_IF,
    23.                                  0,
    24.                                  FILE_PIPE_BYTE_STREAM_TYPE,
    25.                                  FILE_PIPE_BYTE_STREAM_MODE,
    26.                                  FILE_PIPE_QUEUE_OPERATION,
    27.                                  255,
    28.                                  800,//PAGE_SIZE,
    29.                                  800,//PAGE_SIZE,
    30.                                  &DefaultTimeOut);
    31.  
    32.    if (!NT_SUCCESS(ntStatus))
    33.    {
    34.       DPRINT("Can not open pipe stdin\n");
    35.       return ntStatus;
    36.    }
    37.    
    38.    ntStatus = ZwFsControlFile(hNewStdin, NULL, NULL, NULL, &iosbStatus, FSCTL_PIPE_LISTEN, NULL, 0, NULL, 0);
    39.    if (ntStatus == STATUS_PENDING)
    40.    {
    41.       if (!NT_SUCCESS(ZwWaitForSingleObject(hNewStdin, FALSE, NULL)))
    42.       {
    43.          DPRINT("ZwWaitForSingleObject was failed\n");
    44.       }
    45.      
    46.    } else if (!NT_SUCCESS(ntStatus))
    47.    {
    48.       DPRINT("ZwFsControlFile was failed\n");
    49.       return ntStatus;
    50.    }
    Все бы хорошо, хендел создается, возправщается STATUS_PENDING и когда начинаю ожидать пайп при помощи ZwWaitForSingleObject, начинает ждать и можно так проторчать немерянно времени. Ну ясен пень если не подписываться на прослушку пайпа тоже толку от этого не будет. Подскажите плиз, мож есть еще какой-то метод, бо уже перелопатил дофига доков, но там в основном вода или ring 3
     
  19. shchetinin

    shchetinin Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    715
    red_mould
    У тебя не подсоединяется клиент? или хочешь иметь возможность сделать обрыв соединения?
     
  20. red_mould

    red_mould New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2010
    Сообщения:
    34
    Ну мысля такая, создать пайп, и дескриптор подсунуть в консольную приложуху. Ну и чтоб контролировать ввод и вывод на консоль. Дескрипторы процесса я вытягиваю из PEB этого процесса.