Прямой доступ к портм ввода-вывода из USERMODE

Тема в разделе "WASM.WIN32", создана пользователем Lolmen, 30 май 2009.

  1. Lolmen

    Lolmen New Member

    Публикаций:
    0
    Регистрация:
    30 май 2009
    Сообщения:
    3
    Пытаюсь вот уже который день получить прямой доступ к портам из UserSpace, что не так?
    Код (Text):
    1. typedef struct
    2. {
    3.     DWORD Offset;
    4.     WORD Selector;
    5. }FAR_CALL, *PFAR_CALL;
    6.  
    7. FAR_CALL FarCall;
    8.  
    9. DWORD Param; // какой должен быть параметр?
    10. DWORD Ring0Proc; // как взять адрес процесса ?
    11.  
    12. DWORD Ring0ProcAdr;
    13.  
    14. // отправка на порт
    15. __declspec(naked) void SendToPort( WORD port, CHAR value )
    16. {
    17.     __asm
    18.     {
    19.         mov al, value
    20.         mov dx, port
    21.         out dx, al
    22.     }
    23. }
    24.  
    25. __declspec(naked) void GateToRing0( void ) {
    26.     //{ перезагрузка регистра FS и вызов Ring0 кода  }
    27.  
    28.     _asm
    29.     {
    30.             lea esi, lab
    31.             lea eax, FarCall
    32.             mov dword ptr [esi], eax
    33.             mov eax, Ring0Proc
    34.  
    35. ; вылетает тут с Unhandled exception at 0x012c17ba : 0xC0000005:
    36. ; Access violation writing location 0x012c17cd.
    37.  
    38.             mov Ring0ProcAdr, eax
    39.             mov eax, Param
    40.             _emit 0xFF
    41.             _emit 0x1D
    42. lab:
    43.                 _emit 0x00
    44.             _emit 0x00
    45.             _emit 0x00
    46.             _emit 0x00
    47.     }
    48. }
    49.  
    50.  
    51. // Тестовая программка
    52. int main( int argc, char **argv ) {
    53.  
    54.     GateToRing0();
    55.         SendToPort( 0x03f2, 0 ); // try write something to floppy port
    56.         return 0;
    57. }
    Вобщем чего я не понимаю, как можно пробиться в Ring0 :)
    Ибо дельфовый асм не совсем понимаю, да и вообще знаю его поверхностно...

    Помогите разрешить обращение к портам :lol:
     
  2. megaaa

    megaaa New Member

    Публикаций:
    0
    Регистрация:
    29 май 2009
    Сообщения:
    51
    код вроде из Kyrgiz trojan, если нет то ищи его, должен быть на http://vxchaos.official.ws/ в сорцах
     
  3. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Можно открыть битовую карту в TSS, либо установить флажёк IOPL в 3(для любых портом будет открыт доступ, планировщик сохраняет это поле). Из юзермода делалось вторым способом, сервис NtSetInformatiuonProcess(ProcessUserModeIOPL) с соответствующими привилегиями. В ядре просто установить два бита в флажках(в вашем случае да, нормально в регистровом фрейме, который будет загружен в процессор при возврате).
    0xFF, 0x1D это вызов калгейта инструкцией Call far ptr ds:[XXXX]. Предварительно шлюз вызова должен быть создан в GDT на всех процессорах. По этому адресу должн быть записан описатель шлюза как смещение:селектор, у вас описывается структурой FAR_CALL, собственно адрес в инструкцию динамически записывается(тут у вас и исключение), тоесть этот код должен быть в памяти доступной на запись. Код вызываемый через шлюз для установки IOPL должен выглядеть следующим образом:
    Код (Text):
    1.     push 3000h
    2.     popfd
    3.     retf
    1. Если код вызываемый через шлюз вызова находится в юзермодном диапазоне адресов, необходимо создать в этой странице тред захватывающий её, просто в цикле обращающийся к этой странице, иначе при выгруженной в своп странице вы вспыхнет голубой огонет со IRQL_NOT_LESS_OR_EQUAL.
    2. Загрузить ядерные селекторы, сформировать регистровый фрейм(KTRAP_FRAME), если предполагается вызывать чтолибо при разрешённых прерываниях.
     
  4. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Упс сори, забыл прерывания разрешить:
    Код (Text):
    1.     push 3202h
    2.     popfd
    3.     retf
     
  5. Lolmen

    Lolmen New Member

    Публикаций:
    0
    Регистрация:
    30 май 2009
    Сообщения:
    3
    Clerk
    т.е ?
    Код (Text):
    1. void set_iop3() {
    2. __asm {
    3. push 3202h
    4.     popfd
    5.     retf;  <- получаю Access violation reading location
    6. }
    7. }
    Этот код, должен выставить IOPL в 3?
    или для выполения out, in нужно ещё что-то?

    NtSetInformatiuonProcess() - случаем не из DDK ?
     
  6. je_

    je_ New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2004
    Сообщения:
    143
    Код (Text):
    1. push 3202h
    2.     popfd
    3.     retf
    то Ring0 код
     
  7. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Сервис из ядра, нтос, про ддк ничего не знаю.)
    Если калгейт вызван, то после отработки кода при возврате восстанавливаются валидные Cs, Ss и Esp. Исключения не может быть. Переписать код на нормальный асм, писать драйвера на дельфи это извращение.
     
  8. Clerk

    Clerk Забанен

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

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Вот набросал кодес для формирования регистрового фрейма:
    Код (Text):
    1. ; Формирование регистрового фрейма для вызова через калгейт.
    2. ; При переходе через шлюз вызова стек переключается на ядерный из TSS.
    3.  
    4. ;   +12 Eip <- Current Esp 
    5. ;   +8  Cs
    6. ;   +4  Esp
    7. ;   +0  Ss
    8. ; (TSS.Esp0):   ...
    9.  
    10. TsSegGs equ 00030H
    11.  
    12. CALLGATE_ENTRY macro
    13. ; o При входе прерывания разрешены.
    14. ; o Вызов из юзермода(при возврате прерывания размаскируются).
    15. ; o Шлюз не имеет параметров(иначе необходимо корректировать стек, восстанавливая его из TSS).
    16.     cli
    17.     pushfd
    18.     sub esp,4
    19.     push NULL   ; Error code.
    20.     push ebp
    21.     push ebx
    22.     push esi
    23.     push edi
    24.     push fs
    25.     sub esp,2*4
    26.     push eax
    27.     push ecx
    28.     push edx
    29.     push ds
    30.     push es
    31.     push gs
    32.     mov eax,KGDT_R0_PCR
    33.     sub esp,TsSegGs
    34.     mov ecx,KGDT_R3_DATA or RPL_MASK
    35.     mov ebp,esp
    36.     mov fs,ax
    37.     push 2
    38.     mov ds,cx
    39.     mov es,cx
    40.     popfd   ; Очищаем DF и пр.
    41.     assume ebp:PKTRAP_FRAME
    42.     mov eax,[ebp].rSegCs    ; Eip
    43.     mov ecx,[ebp].rEip      ; EFlags
    44.     xor edx,edx
    45.     and ecx,NOT(EFLAGS_VM or EFLAGS_RF)
    46. ; Корректируем флажки.
    47.     mov [ebp].rSegCs,KGDT_R3_CODE or RPL_MASK
    48. ; Перед возвратом в юзермод прерывания необходимо размаскировать.
    49.     or ecx,EFLAGS_IF
    50.     mov ebx,dword ptr fs:[PcPrcbData + PbCurrentThread]
    51.     mov [ebp].rEip,eax
    52.     mov [ebp].rEFlags,ecx
    53.     push dword ptr fs:[PcExceptionList]
    54. ; Отладочные регистры не сохраняем, сбрасываем регистр управления на случай.
    55.     mov Dr7,edx
    56. ; Сохраняем сех-фрейм.
    57.     mov dword ptr fs:[PcExceptionList],EXCEPTION_CHAIN_END
    58.     pop [ebp].ExceptionList
    59. ; - Сохраняем указатель на регистровый фрейм.
    60.     $LOAD Ecx, ThTrapFrame
    61.     $LOAD Edx, ThPreviousMode
    62.     mov dword ptr [ebx + ecx],ebp       ; ETHREAD.TrapFrame
    63. ; - Устанавливаем предыдущий режим.
    64.     mov byte ptr [ebx + edx],UserMode
    65. ; Разрешаем прерывания.
    66.     sti
    67.    
    68.     ;...
    69.  
    70. ; Маскируем прерывания перед возвратом.
    71.     cli
    72.     lea esp,[ebp + TsSegGs]
    73.     pop gs
    74.     pop es
    75.     pop ds
    76.     pop edx
    77.     pop ecx
    78.     pop eax
    79. ; Удаляем PreviousPreviousMode и ExceptionList.
    80.     lea esp,[esp + 2*4]
    81.     pop fs
    82.     pop edi
    83.     pop esi
    84.     pop ebx
    85.     pop ebp
    86.     lea esp,[esp + 4]   ; Удаляем код ошибки.
    87.     iretd
    88. endm
    Не тестил, но вроде правильно должно быть. Смещения ThTrapFrame и ThPreviousMode вычислять динамически, ибо разные в версиях. Макро $LOAD для пикода:
    Код (Text):
    1. $LOAD macro Reg32, Variable
    2. Local dt_
    3.     Call dt_
    4. dt_:
    5.     pop Reg32
    6.     mov Reg32,dword ptr [Reg32 + (offset Variable - offset dt_)]
    7. endm
    Инклуды и код для поиска смещений есть на вирустеке у меня в папке.
     
  10. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Смещения ThTrapFrame и ThPreviousMode вычислять динамически, ибо в разных версиях отличаются.
     
  11. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Clerk
    Еще нужно сохранять DRx и V86, иначе это не будет работать при отлаживаемых процессах и при запущенных дос сеансах.
    И, кстати говоря, даже полноценный вариант у меня не работал.

    И вообще, зачем это нужно? Есть же IoConnectInterrupt, она возволяет полноценно устанавливать обработчики с такими впрапперами. Можно поставить левое прерывание, дернуть оттуда DispatchCode и потом удалить его. А код себе скопировать. Я так делаю у себя в отладчике - универсально.
     
  12. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Great
    Почемуже не будет это работать, это не обработчик прерывания, это вызывается шерез шлюз вызова и не из VDM.
    Для прерываний да, сохранять остальную чать фрейма необходимо.
     
  13. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Great
    И вообще, зачем это нужно??
     
  14. Lolmen

    Lolmen New Member

    Публикаций:
    0
    Регистрация:
    30 май 2009
    Сообщения:
    3
    Clerk
    мне нужно просто набросать две функи:

    byte inp( short port )
    void outp( short port, byte data )

    и дать им привилегии работать из ring3
    такие работали из под DOS, были в поставке Turbo C 3.0
    и умерли в Win32 и VS.NET

    Собственно вопрос, как это организовать,
    если наше приложение не имеет функциональности сервиса.
     
  15. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Дурацкий вопрос, inpout32.dll уже не рулит?

    Clerk
    Я запутался уже, я давно последний раз писал ручное создание треп фрейма. И вот не помню, в каких случаях не работало. Вообщем это надо посмотреть снова, а это сейчас мне не в тему.
    В любом случае, это незачем делать - IoConnectInterrupt и KINTERRUPT::lol: ispatchCode позволяют это все сделать автоматически
     
  16. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    Lolmen
    Был простой способ – NtSetInformationProcess(ProcessUserModeIOPL) – позволяющий при наличии привилегии SeTcbPrivilege ("Act as part of the operating system") включить возможность писать в порты из третьего ринга. Но сейчас посмотрели – в vista sp1 функция после проверки привилегии просто возвращает STATUS_NOT_IMPLEMENTED.

    Таким образом, необходимость писать свой \ использовать стороний драйвер (inpout32.dll) держит правду.
     
  17. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Имхо лучше будет всю обработку в ядре исполнить, чем юзать дров который прямой ввод-вывод откроет, где был топик там додумались в юзермоде прерывания от оборудования обрабатывать :-!
     
  18. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    о_0 дай линк на поржать))