Проблема чтения fs:18h

Тема в разделе "WASM.BEGINNERS", создана пользователем AlexSpl, 6 окт 2008.

  1. AlexSpl

    AlexSpl New Member

    Публикаций:
    0
    Регистрация:
    6 окт 2008
    Сообщения:
    8
    Помогите, пожалуйста, решить следующую проблему:

    Процесс А вызывает функцию GetTlsValue. Соответственно выполняется команда mov eax, large fs:18h. Может ли другой процесс (моя программа) прочитать это значение? Если да, то как это сделать. Перебор значений 7FFDF000, 7FFDE000 и т.д. не подходит.
     
  2. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    читай про внедрение в адресное пространство чужого процесса, есть и у Рихтера и здесь в статьях.
     
  3. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Если известен селектор fs, то можно и без внедрения определить базу через GetThreadSelectorEntry
     
  4. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Через NativeAPI - можно, NtQueryInformationThread с классом информации ThreadBasicInformation=0 возвращает по хэндлу потока в числе прочего TebBaseAddress (поле по смещению +4). Далее - ReadProcessMemory.
    Через WinAPI - можно, если "другой процесс" - отладчик для процесса A: отладчику приходят извещения, в том числе о создании потоков; в числе прочего в этом извещении опять же содержится lpThreadLocalBase - то же, что и TebBaseAddress.
     
  5. AlexSpl

    AlexSpl New Member

    Публикаций:
    0
    Регистрация:
    6 окт 2008
    Сообщения:
    8
    2diamond: Откуда импортировать NtQueryInformationThread и какой индекс не подскажите?

    Может есть другие решения? Неужели только ОС может получить доступ к fs? TlsIndex известен. Всё упирается в fs:18h!

    Внедряться в процесс в моем случае недопустимо, можно только читать RAM.
     
  6. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Из ntdll.lib - можно найти в куче мест, начиная с DDK. На всякий случай предупреждаю, что NativeAPI - это такая вещь, которая, с одной стороны, довольно полезна, а с другой, сильно связана с внутренностями системы и не рекомендуется Microsoft к использованию (теоретически может меняться в следующих версиях системы, хотя на практике довольно стабильно). Кроме того, их нет под линейкой 9x, хотя вряд ли это сейчас кого-то интересует.
    Как уже посоветовал leo, можно GetThreadContext + GetThreadSelectorEntry.
     
  7. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    diamond
    Ха ну ты и скозал, GetThreadContext - а как она работает ???
     
  8. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    А Microsoft не документирует, как именно она работает. Сегодня, в XP и Vista, она сводится к NtGetContextThread, а завтра, в Windows 7, Microsoft может NativeAPI переделать - все "честные" программы, использующие документированную GetThreadContext, останутся работать, а всё, использующее NtGetContextThread, перестанет.
    P.S. Я в курсе, что это исключительно маловероятно и на практике можно ими пользоваться.
     
  9. AlexSpl

    AlexSpl New Member

    Публикаций:
    0
    Регистрация:
    6 окт 2008
    Сообщения:
    8
    2diamond: А можно примерный код чтения fs:18h другого процесса через GetThreadContext + GetThreadSelectorEntry?
     
  10. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Ну, например, так (fasm):
    Код (Text):
    1. TlsGetValueEx:
    2. ; in: ebx=thread handle,
    3. ;     edi=process handle,
    4. ;     esi=tls index
    5. ; out: eax=tls value, CF cleared if OK
    6.  
    7. ; allocate CONTEXT structure
    8.     sub esp, 2CCh-4
    9.     push    10004h      ; CONTEXT_SEGMENTS
    10. ; get FS value
    11.     push    esp
    12.     push    ebx
    13.     call    [GetThreadContext]
    14.     test    eax, eax
    15.     jz  .error
    16. ; [esp+90h] = FS; get FS base
    17.     push    esp
    18.     push    dword [esp+4+90h]   ; CONTEXT.SegFs
    19.     push    ebx
    20.     call    [GetThreadSelectorEntry]
    21.     test    eax, eax
    22.     jz  .error
    23.     mov ah, [esp+7]
    24.     mov al, [esp+4]
    25.     shl eax, 16
    26.     mov ax, [esp+2]
    27. ; eax = FS base = [fs:18h]; now get TLS value
    28.     cmp esi, 40h
    29.     jae .1
    30.     lea eax, [eax+esi*4+0xE10]
    31. .doread:
    32.     call    .read_dword
    33.     jc  .error
    34. .ok:
    35.     add esp, 2CCh
    36.     ret
    37. .error:
    38.     add esp, 2CCh
    39.     xor eax, eax
    40.     stc
    41.     ret
    42. .1:
    43.     cmp esi, 440h
    44.     jae .error
    45.     add eax, 0xF94
    46.     call    .read_dword
    47.     jc  .error
    48.     test    eax, eax
    49.     jz  .ok
    50.     lea eax, [eax+esi*4-0x100]
    51.     jmp .doread
    52.  
    53. .read_dword:
    54. ; in: eax = address, edi = process handle
    55. ; out: eax = value, CF set if error
    56.     push    eax
    57.     mov ecx, esp
    58.     push    eax
    59.     push    esp
    60.     push    4
    61.     push    ecx
    62.     push    eax
    63.     push    edi
    64.     call    [ReadProcessMemory]
    65.     test    eax, eax
    66.     pop ecx
    67.     pop eax
    68.     jz  .readerr
    69.     cmp ecx, 4
    70.     jnz .readerr
    71.     ret
    72. .readerr:
    73.     stc
    74.     ret
    Замечания:
    1. Это код-аналог TlsGetValue, ему нужен tls index и работает он с динамическим TLS; ещё бывает статический TLS (который обходится без Tls*-функций и работает через [fs:2Ch] - для него подход такой же).
    2. Нужно иметь открытые хэндлы процесса, в котором всё это происходит, и потока, у которого считывается TLS (на то он и Thread Local Storage, чтобы быть зависимым от потока). Получить их можно кучей разных способов, в том числе OpenProcess/OpenThread по известным идентификаторам, Process32First/Process32Next/Thread32First/Thread32Next из toolhelp API, GetWindowThreadProcessId по хэндлу окна, созданного потоком.
    3. Константы 0xE10 и 0xF94 вообще-то потенциально могут меняться в будущих версиях (в 2k, XP, Vista - значения одинаковые), но вряд ли будут; для точности можно либо проверять работоспособность в будущих версиях, либо прямо на месте встраивать в прогу дизассемблирование (либо сигнатурный поиск, это детали реализации) и поиск этих констант в функции TlsGetValue из текущей работающей системы). Кроме того, в Win64 для 64-битных процессов они другие (равно как и tls-данные занимают по 8 байт вместо 4), для обычных 32-битных - такие же. Кстати, их можно вытащить из winternl.h из SDK - соответственно offsetof(TEB, TlsSlots) и offsetof(TEB, TlsExpansionSlots).
     
  11. AlexSpl

    AlexSpl New Member

    Публикаций:
    0
    Регистрация:
    6 окт 2008
    Сообщения:
    8
    2diamond: Спасибо огромное! Никак не мог закончить проект из-за проблемы чтения fs:18h. Надеюсь, теперь всё будет в порядке. Сейчас занимаюсь дизассемблированием win32 приложений. А о TLS так мало полезной инфы. Может посоветуете, где почитать?
     
  12. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    diamond
    Да будет вам известно что нормальное приложение не должно юзать GetThreadContext(), GetThreadSelectorEntry() -темболее и выполнять операции с блоком потока недолжно напрямую обращаясь к нему, минуя функционал винапи.
     
  13. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Угу, мне это известно. Равно как и то, что нормальное приложение не должно быть написано на ассемблере и даже иметь ассемблерные вставки - ведь это (о ужас!) приводит к потере переносимости (дважды ужас!) :lol:
    Если серьёзно - я ведь не говорил, что NativeAPI использовать нельзя; иногда их и знания внутренней структуры использовать просто необходимо. Я всего лишь предупредил, чем это может быть чревато. Ну а использование архитектурно-зависимой GetThreadContext() на ассемблерном форуме, да ещё и в топике про [fs:18h], не должно смущать читателей :)
    С точки зрения высокоуровневого программиста (что это вообще такое и как его использовать) - как и о многом другом, об этом хорошо написано у Рихтера (в 4-м издании "Создание эффективных Win32-приложений..." это глава 21). Что находится под капотом - здесь есть статья http://www.wasm.ru/print.php?article=tls (общая теория там тоже есть, но у Рихтера IMHO лучше).
     
  14. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    diamond
    Мне всёравно, я не юзаю винапи.