сэмулировать файл.

Тема в разделе "WASM.WIN32", создана пользователем letopisec, 22 апр 2010.

  1. letopisec

    letopisec New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2004
    Сообщения:
    228
    Как без дрова и сплайсинга отвечать File Management функциям (ReadFile, SetFilePointer, GetFileInformationByHandle)?
    Хочеца на лету ганерировать данные и отдавать сторонней проге.
     
  2. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Трассировка до входа в сервис с последующей эмуляцией. Где начать трейс это оснавная задача видимо.
     
  3. mrcrown

    mrcrown Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    227
    Так если задача тривиальная, то достаточно будет перехватить юзермодные ф-ции доступа к файлам.
     
  4. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Прикинул вобщем так.
    1. Захват апи. Так как их много, все они в kernel32, по сему нормальный способ следующий.
    Для работы с обьектом нужен его описатель. Если описатель не валидный, функи будут возвращать ошибку, это нам и нужно. Если сервисы возвращают ошибку, то функции загружают код ошибки(NT и WIN32) в TEB. Тут работает следубщий механизм, дабы не описывать стопяцот раз одно и тоже, просто скопирую матчасть:
    Тогда поток вызывает апи, она вызывает сервис, тот возвращает ошибку, так как описатель обьекта не валидный, прогружаются коды ошибок, проверяется переменная g_dwLastErrorToBreakOn на значение ERROR_INVALID_HANDLE(Win32, а не ядерный код!), куда мы его прежде загрузим, соответственно он и будет установлен, так как ядро вернёт STATUS_INVALID_HANDLE, коды совпадают и выполняется брейк(Int 3). При этом диспетчер исключений, либо отладочный порт(если процесс не текущий) получает сообщение.
    Теперь нужно обработать останов. Мы выполняем бактрейс и заменяем адрес возврата из апи на свой. После чего поток отпускаем, при возврате управление будет передано на наш код. Он может непосредственно выполнить дальнейшую обработку, либо сгенерить сепшен для удалённой обработки. В стеке параметры функи, там мы восстанавливаем описатель и вызываем есчо раз эту функу, также подменив адрес возврата из неё. Она успешно отработает. Как она отработает это уже чисто ваш вопрос - выполните вы трейс её до вызова сервиса, эмуляцию её и пр.
    2. Описатель файла возвратит функа CreateFileW(). Нужно её захватить. Вот деограмка:
    Код (Text):
    1. CreateFileW() -\
    2.                |
    3.                + RtlDosPathNameToNtPathName_Ustr() -\
    4.                |                                    |
    5.                |                                    + RtlAllocateHeap()
    6.                |                                    |
    7.                |                                    + RtlAcquirePebLock() -> RtlEnterCriticalSection()
    8.                |
    9.                + RtlFreeHeap()
    Опишу в начале общий принцип. Необходимо сгенерировать исключение какимто образом внутри апи. Это исключение обрабатывается, выполняется бактрейс и захват адреса возврата из апи. Это позволяет вызвать её повторно либо контролировать все параметры как входные, так и возвращаемые. При этом мы должны сохранить созданный описатель(если нужен) и возвратить инвалидный.
    Таким образом самые простые способы:
    o RtlAllocateHeap() - захват описан у меня в логе:
    o RtlAcquirePebLock() - это вход в критическую секцию FastPebLock. Захват:
    Подобные вопросы описаны в этом топике http://wasm.ru/forum/viewtopic.php?id=34151&p=1, там и примеры есть. Только не знаю зачем это вам. Классические способы это всякие изменения в секциях кода: джампы, брейки IAT и пр.
     
  5. Cr4sh

    Cr4sh New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2006
    Сообщения:
    668
    Clerk
    А можно просто перехватить вызовы API для работы с файлами, и в итоге получить тот же самый результат, но с более простой, надёжной реализацией которая, к тому же, в меньшей степени будет завязана на недокументированные внутренности ОС.
     
  6. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Cr4sh
    Код менять можно как угодно. Вот только обнаружить и снять это не составляет труда. Подумал если автор не желает юзать ядро и изменять код(джампы), то должно быть скрытно.
     
  7. Cr4sh

    Cr4sh New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2006
    Сообщения:
    668
    Твой способ применительно к данной задаче имеет существенную загвоздку: перехваты (кстати, это не обязательно должен быть сплайсинг) всё равно понадобятся, иначе как ты собрался в целевом приложении спровоцировать передачу в, к примеру, ReadFile невалидного дескриптора?
     
  8. Cr4sh

    Cr4sh New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2006
    Сообщения:
    668
    Clerk
    Короче, вот тебе код приложения:
    Код (Text):
    1. int main()
    2. {
    3.     HANDLE hFile = CreateFile("C:\\WINDOWS\\explorer.exe", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
    4.     if (hFile != INVALID_HANDLE_VALUE)
    5.     {
    6.         DWORD dwSize = GetFileSize(hFile, NULL);
    7.         printf("File size is %d bytes\n", dwSize);
    8.  
    9.         CloseHandle(hFile);
    10.     }
    11.  
    12.     return 0;
    13. }
    Опиши пошагово, как ты без каких-либо перехватов собираешься эмулировать файловые операции, которое это приложение выполняет.
     
  9. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Cr4sh
    Думал я понятно описал. Это и есть перехват, для некоторых трассировка не является способом захвата кода.. :)
    Укорочиваю смысл до предельно возможного: гдето внутри функи возникает состояние, при котором поток прерывается, это исключения, бесконечные циклы, ожидание на обьектах и пр. Тогда мы выполняем бактрейс и замену адреса возврата в нужном нам стековом фрейме. Либо трассировку до необходимого места. Чатсный случай этого:
    Описан в #2.
     
  10. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Cr4sh
    Чтоб не лезть в дебри, покажу на рабочем примере http://wasm.ru/forum/viewtopic.php?id=36993
    Эмулируется создание файловой секции. Каким образом - полностью трассируется загрузчик, тоесть каждую инструкцию его и контекст потока я имею и могу менять как угодно ход исполнения.
     
  11. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Cr4sh
    Хорошо, на описанном примере решения:
    o Регаю VEH.
    o Делаю инвалидной сигну HEAP.Signature.
    o Жду пока диспетчер получит управление.
    o В нём выполняю бактрейс и смотрю откуда был вызов. Если не из CreateFile() отпускаю тред.
    o Иначе выполняю бактрейс и заменяю адрес возврата, после чего отпускаю тред.
    o Получю управление при возврате из CreateFile(). Возвращаю в hFile инвалидное значение.
    o Регаю код ошибки в g_dwLastErrorToBreakOn.
    -
    Вызывается GetFileSize():
    o Срабатывает останов в DbgBreakPoint(). Смотрю причину, если не наша отпускаю тред.
    o Иначе выполняю бактрейс и заменяю адрес возврата, после чего отпускаю тред.
    o Получаю управление при возврате из GetFileSize().
    o Обрабатываю функу как угодно.
     
  12. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    (Прим.: инвалидный описатель это не -1, а Magic, например 0xABCDEF.)
     
  13. Cr4sh

    Cr4sh New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2006
    Сообщения:
    668
    Clerk
    Спасибо, теперь всё ясно. Способ действительно жизнеспособный, просто с длинного описания я сходу не врублился в суть манипуляций с хипом.
     
  14. gorodon

    gorodon New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2009
    Сообщения:
    301
    Clerk
    Будет-ли работать вышеописанная схема, если код приложения #8 выполняется в обработчике SEH?
    (типа конструкции __try - __except - __finally... или SetUnhandledExceptionFilter)
     
  15. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    gorodon
    Да. Ведь нельзя спутать к примеру #AV с #DB. Даже если хватать функи средствами IDP_Engine(помните там по ссыли), то всёравно известен адрес инструкции которая должна сгенерить исключение(и целевой диапазон также).
     
  16. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Вот код для поиска нужно окружения и обработки брейка и отладочного вывода при инвалидации сигнатуры хипа:
    http://indy-vx.narod.ru/Bin/Heap.zip
    o xLdrParseRtlpCheckHeapSignature()
    o xHmgrDispatchException()
    (Лишнее можно удалить.)
     
  17. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Лог:
    Если инвалидация сигнатуры хипа универсальна, тоесть работает во всей линейке NT(и в W7), то останов на g_dwLastErrorToBreakOn работает только в XP, описанный способ лучший(не знаю как с совместимостью).
    Запускаем трейс описателей с помощью ProcessHandleTracing. После этого передача в ядро инвалидного описателя будет генерит #STATUS_INVALID_HANDLE. Тру хек ;)
     
  18. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    До кучи кодес. Ищет описатель директории первой:
    Код (Text):
    1. xCompareStringSensitiveInternal proc uses ebx UnicodeString:PUNICODE_STRING, AnsiString:PSTR, StringLength:ULONG
    2.     mov ebx,StringLength
    3.     mov edx,UnicodeString
    4.     lea eax,[ebx*2]
    5.     assume edx:PUNICODE_STRING
    6.     cmp [edx]._Length,ax
    7.     jne Exit
    8.     mov ecx,AnsiString
    9.     mov edx,[edx].Buffer
    10. @@:
    11.     movzx eax,byte ptr [ecx + ebx - 1]
    12.     cmp word ptr [edx + ebx*2 - 2],ax
    13.     jne Exit
    14.     dec ebx
    15.     jnz @b
    16.     xor eax,eax
    17. Exit:
    18.     ret
    19. xCompareStringSensitiveInternal endp
    20.  
    21. ; +
    22. ; Опредедяет указатель на ETHREAD текущего потока.
    23. ;
    24. BASE_REGION_SIZE    equ 10000H
    25.  
    26. xQueryKnownDllsDirectory proc uses ebx esi edi Directory:PVOID
    27. Local SystemInformation:PVOID, SystemInformationLength:ULONG
    28. Local $Directory[12]:CHAR
    29. Local ObjectName[sizeof(UNICODE_STRING) + (10*2 + 4)]:BYTE
    30.     mov SystemInformationLength,0
    31.     invoke ZwQueryObject, NULL, ObjectAllTypesInformation, NULL, NULL, addr SystemInformationLength
    32.     .if Eax != STATUS_INFO_LENGTH_MISMATCH
    33. ; def. 224 bytes.
    34.     mov SystemInformationLength,PAGE_SIZE
    35.     .endif
    36.     mov SystemInformation,NULL
    37.     invoke ZwAllocateVirtualMemory, NtCurrentProcess, addr SystemInformation, 0, addr SystemInformationLength, MEM_COMMIT, PAGE_READWRITE
    38.     test eax,eax
    39.     jnz Exit
    40.     invoke ZwQueryObject, NULL, ObjectAllTypesInformation, SystemInformation, SystemInformationLength, Eax
    41.     test eax,eax
    42.     mov edi,SystemInformation
    43.     jnz Parse
    44.     mov esi,OBJECT_ALL_TYPES_INFORMATION.NumberOfTypes[edi]
    45.     mov dword ptr $Directory[0],"eriD"
    46.     mov dword ptr $Directory[4],"rotc"
    47.     mov dword ptr $Directory[2*4],"y"
    48.     mov ebx,esi
    49.     add edi,4
    50.     assume edi:POBJECT_TYPE_INFORMATION
    51. @@:
    52.     invoke xCompareStringSensitiveInternal, Edi, addr $Directory, 9
    53.     movzx ecx,[edi].TypeName._Length
    54.     je Parse
    55.     and ecx,NOT(3)
    56.     mov edi,[edi].TypeName.Buffer
    57.     lea edi,[edi + ecx + 4]
    58.     dec esi
    59.     jnz @b
    60.     mov eax,STATUS_UNSUCCESSFUL
    61. Parse:
    62.     push eax
    63.     invoke ZwFreeVirtualMemory, NtCurrentProcess, addr SystemInformation, addr SystemInformationLength, MEM_RELEASE
    64.     pop eax
    65.     sub ebx,esi ; ObjectTypeNumber
    66.     test eax,eax
    67.     mov esi,BASE_REGION_SIZE
    68.     jnz Exit
    69.     inc ebx
    70. NextRegion:
    71.     mov SystemInformationLength,esi
    72.     mov SystemInformation,NULL
    73.     invoke ZwAllocateVirtualMemory, NtCurrentProcess, addr SystemInformation, 0, addr SystemInformationLength, MEM_COMMIT, PAGE_READWRITE
    74.     test eax,eax
    75.     jnz Exit
    76.     invoke ZwQuerySystemInformation, SystemHandleInformation, SystemInformation, SystemInformationLength, Eax
    77.     test eax,eax
    78.     jz ParseInfo
    79.     push eax
    80.     invoke ZwFreeVirtualMemory, NtCurrentProcess, addr SystemInformation, addr SystemInformationLength, MEM_RELEASE
    81.     pop eax
    82.     cmp eax,STATUS_INFO_LENGTH_MISMATCH
    83.     jnz Exit
    84.     add esi,BASE_REGION_SIZE
    85.     cmp esi,32*BASE_REGION_SIZE
    86.     jb NextRegion
    87.     jmp Exit
    88. ParseInfo:
    89.     mov esi,SystemInformation
    90.     mov dword ptr $Directory[0],"onK\"
    91.     mov ecx,fs:[TEB.Cid.UniqueProcess]
    92.     mov edi,dword ptr [esi]
    93.     mov dword ptr $Directory[4],"lDnw"
    94.     mov dword ptr $Directory[2*4],"sl"
    95.     add esi,4
    96. NextEntry:
    97.     assume esi:PSYSTEM_HANDLE_INFORMATION
    98.     cmp [esi].ProcessId,ecx
    99.     jne @f
    100.     cmp [esi].ObjectTypeNumber,bl   ; def. 2: Directory.
    101.     jne @f
    102.     push ecx
    103.     lea edx,ObjectName
    104.     push NULL
    105.     push sizeof(UNICODE_STRING) + (10*2 + 4)
    106.     movzx ecx,[esi].Handle
    107.     push edx
    108.     push ObjectNameInformation
    109.     push ecx
    110.     Call ZwQueryObject
    111.     test eax,eax
    112.     pop ecx
    113.     jnz @f
    114.     cmp UNICODE_STRING._Length[ObjectName],14H
    115.     jne @f
    116.     push ecx
    117.     invoke xCompareStringSensitiveInternal, addr ObjectName, addr $Directory, 10
    118.     pop ecx
    119.     jne @f
    120.     mov edx,Directory
    121.     movzx ecx,[esi].Handle
    122.     mov dword ptr [edx],ecx
    123.     jmp ParseError
    124. @@:
    125.     add esi,sizeof(SYSTEM_HANDLE_INFORMATION)
    126.     dec edi
    127.     jnz NextEntry
    128.     mov eax,STATUS_NOT_FOUND
    129. ParseError:
    130.     push eax
    131.     invoke ZwFreeVirtualMemory, NtCurrentProcess, addr SystemInformation, addr SystemInformationLength, MEM_RELEASE
    132.     pop eax
    133. Exit:
    134.     ret
    135. xQueryKnownDllsDirectory endp
    136.  
    137. OBJECT_HANDLE_FLAG_INFORMATION struct
    138. Inherit         BYTE ?
    139. ProtectFromClose    BYTE ?
    140. OBJECT_HANDLE_FLAG_INFORMATION ends
    141. POBJECT_HANDLE_FLAG_INFORMATION typedef ptr OBJECT_HANDLE_FLAG_INFORMATION
    Собственно находит описатель директории "\KnownDlls". После этого его можно скопировать(не DUPLICATE_CLOSE_SOURCE!) и тутже создать новый, без разницы какой, но не типа Directory. Тогда в загрузчике будет возникать сепшен. Хидер:
    Код (Text):
    1. PROCESS_HANDLE_TRACING_ENABLE struct
    2. Flags       ULONG ?
    3. PROCESS_HANDLE_TRACING_ENABLE ends
    4.  
    5. PROCESS_HANDLE_TRACING_ENABLE_EX struct
    6. Flags       ULONG ?
    7. TotalSlots  ULONG ?
    8. PROCESS_HANDLE_TRACING_ENABLE_EX ends
    9.  
    10. PROCESS_HANDLE_TRACING_MAX_STACKS   equ 16
    11.  
    12. HANDLE_TRACE_DB_OPEN    equ 1
    13. HANDLE_TRACE_DB_CLOSE   equ 2
    14. HANDLE_TRACE_DB_BADREF  equ 3
    15.  
    16. PROCESS_HANDLE_TRACING_ENTRY struct
    17. Handle      HANDLE ?
    18. ClientId        CLIENT_ID <>
    19. _Type       ULONG ? ; HANDLE_TRACE_DB_*
    20. Stacks      PVOID PROCESS_HANDLE_TRACING_MAX_STACKS (<>)
    21. PROCESS_HANDLE_TRACING_ENTRY ends
    22.  
    23. PROCESS_HANDLE_TRACING_QUERY struct
    24. Handle      HANDLE ?
    25. TotalTraces ULONG ?
    26. HandleTrace PROCESS_HANDLE_TRACING_ENTRY 1 DUP (<>)
    27. PROCESS_HANDLE_TRACING_QUERY ends
    28.  
    29. ProcessHandleTracing    equ 32
    Надеюсь хоть ктото тут в теме :dntknw:
     
  19. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Тестовый семпл: http://indy-vx.narod.ru/Bin/LdrExts.zip
    Для кода:
    Код (Text):
    1.     invoke GetModuleFileName, NULL, addr Buffer, MAX_PATH
    2.     APIERR
    3.     invoke CreateFile, addr Buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL
    4.     mov ebx,eax
    5.     .if Eax == INVALID_HANDLE_VALUE
    6.     int 3
    7.     .endif
    8.     invoke GetFileSize, Ebx, NULL
    9.     APIERR
    10.     mov dword ptr [Buffer],0
    11.     invoke ReadFile, Ebx, addr Buffer, 2, addr Count, NULL
    12.     APIERR
    13.     invoke CloseHandle, Ebx
    14.     APIERR
    На XP:
    [​IMG]
     
  20. gorodon

    gorodon New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2009
    Сообщения:
    301
    Clerk, очень интересно, но тяжеловато для понимания.... пока ;)