добрый день господа подскажите пожалуйста, какова разница между ret и add esp,4 + jmp dword ptr [esp-4] в кернел моде (за исключением того что add изменяет флаги)? в юзер моде работает нормально, в кернеле почему то вылазят странные глюки.
vladqq Память ниже границы стека(Esp) юзать нельзя, она не ваша и там может быть что угодно после прерывания к примеру.
тоесть между add esp,4 и jmp dword ptr [esp-4] может быть вызвано прерывание которое будет юзать стек, который находится ниже текущего (для моего треда) значения esp ?
vladqq В ядре при прерываниях стек не переключается, так как CPL процедуры тотже самый(0). IRET-фрейм затрёт адрес возврата: Код (Text): [Esp - 3*4] xxxx rEip [Esp - 2*4] xxxx rCs [Esp - 4] rEip rEFlags [Esp]: xxxx xxxx Тогда после возврата на инструкцию jmp dword ptr [esp - 4] будет загружен rEFlags -> rEip, что есть переход вникуда и в лучшем случае возникнет #GP/#PF.
опа, спасибо большое! именно эта хрень и происходит. всё никак не мог понять откуда флаговый регистр появляется в eip. в юзер моде я так понимаю такое происходить не будет ?
CyberManiac А можно на этом по подробнее? Какие это callback-функции на это способны? AFAIK единственный вариант, когда ни с того ни с сего может потереться содержимое выше (меньше) esp, — это грязный инжект через SetThreadContext... ну и намеренная запись, конечно, но никто (особенно сама винда) этим обычно не занимается.
CyberManiac А любые, которые будут вызываться в том же потоке, — это либо плановые вроде EnumWindows, либо доставляющие юзермодные APC, которые не будут исполняться, пока поток сам этого не захочет, войдя в alertable состояние. Поэтому связка add esp,4 + jmp dword ptr [esp-4] должна в юзермоде гарантированно исполняться правильно.
на практике так и происходит - в юзермоде я не заметил проблем, тестил долго. в кернеле же сразу вылез флаговый регистр в EIP.
l_inc Верно только для кода изолированного от калбэков и исключений, которые доставляются в контексте текущего процесса. Нельзя использовать стек ниже, чем текущая граница.