Сискол из под х86 ( используя Heaven's gate ) кидает Access Violation на возврате в х86 контекст

Тема в разделе "WASM.BEGINNERS", создана пользователем Hooker, 11 дек 2022.

  1. Hooker

    Hooker New Member

    Публикаций:
    0
    Регистрация:
    8 апр 2022
    Сообщения:
    11
    Всем привет

    Взял отсюда код https://gist.github.com/coldfusion39/87ac72c083bca73cad809d1f4653061a#file-wow64_call-cpp-L61 который с х86 процесса переключается в х64 и вызывает syscall инструкцию после чего обратно переключается в х86 режим

    Немножко сделал под себя для теста, вручную вписал номера из ntdll ( win 10 home, 19044 ), NtOpenFile=0x33 NtClose=0xF и обнаружил что работает такой механизм через "раз" то есть я иногда получаю access violation exception почему-то. Вот мой код: https://pastebin.com/ujVWpGvw

    Я решил чтоб разобраться зациклить:

    Код (Text):
    1.  while (true) {
    2.    
    3.   DWORD Status = x64_Syscall(0x33, Args, 6);
    4.   printf("NtOpenFile: Status = 0x%.8x, FileHandle = 0x%.8x\n", Status, (HANDLE)Params->FileHandle);
    5.    
    6.   DWORD64 Args2[1];
    7.   Args2[0] = Params->FileHandle;
    8.   Status = x64_Syscall(0xF, Args2, 1);
    9.   printf("NtClose: Status = 0x%.8x\n", Status);
    10.   Sleep(100);
    11.   }
    И вообщем-то вот результат в windbg:

    sz1.png

    Как видите якобы
    Код (Text):
    1. mov     esp,dword ptr [ebp-8]
    даёт access violation с записью по адресу 0 ( не представляю откуда это может взяться )
    При этом на момент эксепшена состояние регистров вот такое

    Сначала я подумал что может действительно выравнивание стека играет роль но! Выравнивае есть в коде: https://gist.github.com/coldfusion39/87ac72c083bca73cad809d1f4653061a#file-wow64_call-cpp-L93

    Как видно делается and а оригинал esp сохраняется в локальной переменной

    Это какой-то защитный механизм от такого рода манипуляций в x86 процессе? Сталкивался ли кто-то с подобным?

    Для чистоты эксперимента:
    Код (Text):
    1. while(true)
    2. {
    3.  
    4.         DWORD64 Args2[1];
    5.         Args2[0] = 0;
    6.         Status = x64_Syscall(0xF, Args2, 1);
    7.         printf("NtClose: Status = 0x%.8x\n", Status);
    8.         Sleep(100);
    9. }
    сискол с 1им параметром числовым в цикле даёт такой же виолейшен в том же месте, спустя рандомное число итераций ( это может быть 10 а может быть 20 )

    Я собираю бинарь с отключёнными проверками стека,sdl, cfg и тд - только црт прилинкован.

    При этом если гонять это под дебагером и скипнуть эксепшон то сисколы отрабатывают - я получаю хендл на открытый файл и тд

    Почему такое может происходить? Было ли такое у кого-нибудь и может ли кто сделать репродьюс такого же результата у себя?
     
  2. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    875
    Hooker нравится это.
  3. Hooker

    Hooker New Member

    Публикаций:
    0
    Регистрация:
    8 апр 2022
    Сообщения:
    11
    Всё заработало, как и написал инди надо было восстановить ss