Кратко: 1. регистрирую новый обработчик 2. вызываю багу 3. мне дали CONTEXT 4. Меняю как мне надо регистры drX 5. правлю команду которая предамерено вызвала исключение 6. делаю попытку выполнить результат: прога падает, почему?
nobodyzzz Ты скажи вызвав исключение и попрвив CONTEXT и сказав return ExceptionContinueExecution; система поправит под тот CONTEXT что я попрвил, а я его я взял от сюда: Код (Text): EXCEPTION_DISPOSITION __cdecl _except_handler( struct _EXCEPTION_RECORD *ExceptionRecord, void * EstablisherFrame, struct _CONTEXT *ContextRecord, void * DispatcherContext ) или она не поправит?
nobodyzzz Раз уж коснулся SEH, не буду создавать еще одну тему и задам касательно него здесь: Код (Text): xor eax,eax call $+5 add dword[esp],Protect-$ push dword[fs:eax] mov [fs:eax],esp inc dword[eax] Protect: mov ebx,[esp+0x0C] mov esi,Protect mov edi,OutProgramm mov ecx,SizeProtect / 4 @@: lodsd xor eax,0x3ABC3291 not eax xor eax,[ebx+0x04] ; dr0 ror eax,0x3 sub eax,[ebx+0x08] ; dr1 not eax add eax,[ebx+0x0C] ; dr2 xor eax,0xF7B93CDF xor eax,[ebx+0x10] ; dr3 stosd dec ecx jnz @B add esp,0x14 mov eax,[esp] mov [fs:0],eax add esp,0x8 mov edi,OutProgramm push edi retn как ты думаешь под включенным DEP будет ли какая бага? По идее не должно причем тут он?!
Вот тебе цитата из Разработка больших проектов на ассемблере (http://wasm.ru/article.php?article=biprjasm) : Так что возми за правило в тех функция, которые вызываються системой сохранять регистры ebx, esi, edi
nobodyzzz Имеет смысл если в обычном коде, а у меня esi,ebx,edi все равно обычный расшированный код сделает так как надо!
Код (Text): push edi retn Это callback-функция. Куда из неё управление должно передаваться? На васме много статей про SEH.
EvilsInterrupt Если память по адресу OutProgram разрешена для исполнения, то DEP отдыхает Но "бага" может быть в другом - непонятно, что ты хочешь сделать после add esp,0x14. Если восстановить стек и предыдущий SEH, то mov eax,[esp] это неправильно, т.к. на момент вызова твоего обработчика в стеке содержится куча "мусора", оставленная виндовыми функциями (в т.ч. и структура CONTEXT тоже сидит в стеке). Поэтому значение esp на момент вызова исключения нужно брать либо из [esp+8] либо из контекста [ebx+0xС4] И вообще не возвращать управление винде после обработки исключения - это дурной "червивый" тон
когда-то этот код постился здесь Код (Text): ;; debug registers clearing example by dr.golova ;; mailto: dr_golova#pisem.net ;; fully multihreaded and position-independent code ;; compile it with netwide assembler ;; e.g. nasmw.exe -o drx_clr.bin -f bin -O4 drx_clr.asm bits 32 section .text global _start _start: ;; int 3 call .pbase ;; push code address .pbase: xor eax, eax add dword [esp], (.x_hnd - .pbase) ;; update handler offset push dword [fs:eax] ;; save old exception handler mov dword [fs:eax], esp ;; setup new handler frame mov eax, [eax] ;; exception here pop dword [fs:eax] ;; restore old frame pop eax retn .x_hnd: xor eax, eax mov ecx, [esp+00Ch] ;; context ptr mov dword [ecx], 010017h ;; set context flags add dword [ecx+0B8h], 02h ;; exception address mov dword [ecx+018h], 0101h ;; setup dr7 flags mov [ecx+04h], eax ;; clear dr0-dr3 mov [ecx+08h], eax mov [ecx+0Ch], eax mov [ecx+10h], eax retn ;; return to host end
Dimson Я писал выше, что это расшифровщик, следовательно push edi/retn это переход на расшифрованный код! К тому же обработчики можно не только поставить, но и убрать, а также попачить любое значение другого обработчика на себя, была бы фанатазия
Asterix Мне тут в голову пришло: sub [esp],eax ; eax is CONTEXT.dr0 т.е. взять значение из дубужных и если они в нуле, то стек они не попортят!
Это понятно. Но после обработчика исключения у тебя выход должен быть обратно в ntdll в ExecuteHandler и выше по цепочке. Т.е., если хочешь вернуться из обработчика исключения прямо в код то esp надо увеличивать не на 0x14, а гораздо на больше (не забыв при этом убрать обработчик исключения, который ExecuteHandler ставит) или, как вариант, в расшифрованном коде должно учитываться всё то, что в данный момент на стеке лежит (включая адреса возврата в функции ntdll и весь остальной хлам). А так, можно предположить, что у тебя указатель стека не туда указывает на выходе, поэтому и валится всё.
В коде выше: Код (Text): Protect: mov ebx,[esp+0x0C] берем адрес на CONTEXT, блин, самое интересное dr0,dr1 etc находятся! Находятся и сегментные регистры ) А вот между ними eax,ebx,ecx etc не фига! )) Че за дурь? или в результате mov [0],1(псевдо) не сохраняются РОНы ?
Рабочий пример использования SEH (правда на flat асме и с использованием _except_handler2). Может пригодится... format PE GUI 4.0 entry WinMain include 'c:\windows\fasm\fixes.inc' include 'c:\windows\fasm\win32.inc' section '.data' data readable szFilter db 'Filter',0 szExcept db 'Except',0 section '.code' readable executable install_handler: pop ecx pop eax push 0 push ebp push -1 push eax push [_except_handler2] mov eax,[fs:00] push eax mov DWORD [fs:00],esp jmp ecx LABEL test_seh_scope_table dd -1, test_seh_filter1, test_seh_except1 proc test_seh use_seh stdcall install_handler, test_seh_scope_table local .var1:lDWORD, .var2:lDWORD, .stack_frame:EXCEPTION_REGISTRATION push ebx edi esi mov [.stack_frame.m_esp],esp mov DWORD [.var1],1 mov DWORD [.var2],2 .try1: mov [.stack_frame.try_level],0 sub eax,eax mov eax,[eax] mov DWORD [.stack_frame.try_level],-1 jmp test_seh_end_except1 test_seh_filter1: invoke MessageBox, 0,szFilter,szFilter,0 mov eax,1 retn test_seh_except1: mov esp,[.stack_frame.m_esp] invoke MessageBox, 0,szExcept,szExcept,0 cmp DWORD [.var1],1 jz .check_var2 invoke MessageBox, 0,szExcept,szExcept,0 .check_var2: cmp DWORD [.var2],2 jz test_seh_end_except1 invoke MessageBox, 0,szExcept,szExcept,0 jmp test_seh_end_except1 test_seh_end_except1: pop esi edi ebx mov ecx,[.stack_frame.hPrev] mov [fs:00],ecx ret endp WinMain: call test_seh invoke MessageBox, 0,szFilter,szFilter,0 invoke ExitProcess, 0 section '.idata' import data readable library \ user,'USER32.DLL', \ kernel,'KERNEL32.DLL', \ crtdll,'crtdll.dll' import user, \ MessageBox,'MessageBoxA' import kernel, \ ExitProcess,'ExitProcess' import crtdll, \ _except_handler2,'_except_handler2'