These days in the re-look at the SEH mechanism, harvest quite abundant. Conveniently wrote a code to jump with SEH affixed to this mark as a souvenir.
When an exception occurs and the exception is caught, the exception filtering function is entered under the exception handling mechanism of the OS. The filter function can return one of the three exception_execute_handler/exception_continue_search/exception_continue_execution to determine the subsequent operation of the OS. If you return Exception_continue_execution,os that the exception has been resolved, you can continue running from the instruction where the exception occurred. This is typically used to troubleshoot access memory errors, such as:
int* ptr=null;int ex (exception_pointers* exceptioninfo) {exceptioninfo->contextrecord->eax= (DWORD) malloc ( sizeof (int)); return exception_continue_execution;} int main () {__try{*ptr = 0X00;//004010AC mov eax,[ptr (00422780)]//004010B1 mov dword ptr [eax],0 MessageBox (NULL, "", "", MB_OK);} __except (EX (GetExceptionInformation ())) {}}
When executing *ptr=0x00, because PTR points to null, the Mov DWORD ptr [eax],0 This sentence will cause an exception. In order for the code to continue to execute the popup dialog, just let eax point to valid memory. So how do you get eax to a valid address? As long as you create heap memory for EAX, you can open up space in the exception filtering function. According to the design of Windows, when an exception occurs, the OS presses the register value in the stack into the thread environment (via Kitrapframetocontext) and resumes execution with the saved thread environment recovery Register when returning from the exception ( Through Kicontexttotrapframe). So what is the so-called threading environment? The Exceptioninfo->contextrecord in the code is what you ask for. Therefore, I modify the context->eax in the filter function to point to the valid memory, which realizes the purpose of repairing the exception continuation instruction stream. In fact, this whole process is similar to Setthreadcontext/getthreadcontext.
In addition, it is worth mentioning that when an exception occurs, if the exception type is the failure of the memory, the error code is 0xc0000005,
exceptioninfo->exceptionrecord->numberparameters;
exceptioninfo->exceptionrecord->exceptionaddress;
exceptioninfo->exceptionrecord->exceptioninformation[1];
These fields contain important information.
See a common and egg-sore dialog box:
When you happy play the game, jump out of this, is not all ruined? If you look closely at the error message, the following information is given: the address of the wrong instruction -0x6f001080, the cause of the error -0xc0000005 (Access invalid memory), the address of the invalid memory 0xe2af524c. This information can be easily obtained after entering the kernel state, but is there any way to obtain the user Configuration? For example, want to do a user-state debugger? Of course, the 3 fields mentioned above correspond in turn: the number of elements in the exceptioninformation array at the time of the exception, the address of the failed instruction, and the address of the invalid memory access.
With these ancillary information, you start to discuss the topic. In fact, this is already here: Code obfuscation is generally through a variety of means to confuse the code execution process, put in this article, as long as the exception_continue_execution return address can be modified (note my words, is exception_ The return address of the continue_execution is not the return address of the exception, and if it is remembered that the return address of the vc++6.0 exception should be _except_handle3), further, it is the value of the EIP when the exception is triggered and the thread environment is saved.
List code: Code execution flow is 1)-5)
#include <windows.h> #include <stdio.h>int* ptr;//4) msg is called void Msg (int a,int b) {int c = a+b;printf ("%d\n", c) ; MessageBox (NULL, "", "", MB_OK); __asm{mov eax,c}}int ex (exception_pointers* exceptioninfo) {//3) ready to jump to msg//msg is a parametric function, The parameter is saved on the stack before the exception, i.e. ESP points to//at this point Exceptioninfo->contextrecord->eip[0] points to the address represented by LAB1//exceptioninfo-> CONTEXTRECORD->EIP[4]=0X01 exceptioninfo->contextrecord->eip[8]=0x02exceptioninfo->contextrecord- >eip = (DWORD) Msg;return exception_continue_execution;} int main () {int i=0;ptr = (int*) &main;__try{/* originally LAB2 to jmp, the result is "illegal jump into __try scope", so instead of */if (1) Goto LAB2 ; LAB1://5) returns the instruction stream from msg into the lab1i++;p rintf ("%d\n", I); ExitProcess (0); LAB2:__ASM{//1) The parameters and the return address of the MSG function. Simulates the process of C calling a function. After an exception is triggered to jump into msg execution//For the MSG function, he simply does not know who called him, he only cares if the parameters are correctly push 0x02;push 0x01;lea Eax,lab1;push eax;} 2) trigger the exception, give the code that really needs to be executed in LAB1 (*ptr) = 0x01;} __except (EX (GetExceptionInformation ())) {}return 0;}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Code obfuscation with SEH