Before we get started, I must state clearly that this information is based on the guidance provided from corelan.be website as shown in the references section.
For some folks reading my material may be easier, for others reading the material from Corelan will be easier. Whichever you choose, please note that this is all based on the guidance provided by those folks and thus nothing here is my original work.
Now that the attribution stuff is out of the way, let's get going.
To help to drive home the understanding of SEH, the code below will help me out.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | /* This code is part of my learnings of SEH handling Author: Nik Alleyne Blog: securitynik.blogspot.com Date: 2018-01-12 */ #include <stdio.h> #include <string.h> #pragma warning(disable : 4996) int ExceptionHandler(void); void main(int argc, char *argv[]) { // Declare a buffer of size 512 bytes char myBuffer[512]; printf("Hey %s I'm running ... \n", argv[1]); // Setup the exception Handler __try { strcpy(myBuffer, argv[1]); } __except ( ExceptionHandler() ) { } return 0; } int ExceptionHandler(void) { printf("Just a head's up this exception is being handled ... \n"); return 0; } |
E:\Coding\SEH-Demo\Debug>SEH-Demo.exe SecurityNik
Hey SecurityNik I'm running ...
However, when ran without any command line arguments we get ...
Next step is to "Launch executable" in "WindDbg Preview", by opening the "SEH-Demo.exe". Once we launch the executable we see in WinDbg Preview:
1 2 3 4 5 6 7 8 9 10 11 | Executable search path is: ModLoad: 00d20000 00e2e000 SEH-Demo.exe ModLoad: 77df0000 77f7d000 ntdll.dll ModLoad: 74b80000 74c50000 C:\Windows\SysWOW64\KERNEL32.DLL ModLoad: 755f0000 757c7000 C:\Windows\SysWOW64\KERNELBASE.dll (cb4.1130): Break instruction exception - code 80000003 (first chance) eax=00000000 ebx=00000010 ecx=f6200000 edx=00000000 esi=007c3000 edi=77df6964 eip=77e9dadf esp=0096f91c ebp=0096f948 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246 ntdll!LdrpDoDebuggerBreak+0x2b: 77e9dadf cc int 3 |
Looking at the Windows Thread Information Block (TIB) at FS:[0] which contains the current Structured Exception Handler (SEH) frame to gain further insight into the SEH structure
1 2 3 4 5 6 7 8 9 | 0:000> d fs:[0] 0053:00000000 38 f9 96 00 00 00 97 00-00 e0 96 00 00 00 00 00 8............... 0053:00000010 00 1e 00 00 00 00 00 00-00 60 7c 00 00 00 00 00 .........`|..... 0053:00000020 b4 0c 00 00 30 11 00 00-00 00 00 00 2c 60 7c 00 ....0.......,`|. 0053:00000030 00 30 7c 00 32 00 00 00-00 00 00 00 00 00 00 00 .0|.2........... 0053:00000040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0053:00000050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0053:00000060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0053:00000070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ |
Our tree looks like:
[TEB] -> [0096f938]
From above we see the "38 f9 96 00" which points to the beginning of the TEB. Do remember that from an Intel architecture perspective, multi byte values are represented in little endian. Thus we need to reorder these bytes to get to the beginning of the SEH chain.
Still in WinDbg, when we dump the address at "0096f938" we get:
1 2 3 4 5 6 7 8 9 | 0:000> d 0096f938 0096f938 98 fb 96 00 20 6a e6 77-d6 50 f0 44 00 00 00 00 .... j.w.P.D.... 0096f948 a8 fb 96 00 f6 8b e9 77-86 54 88 33 00 00 00 00 .......w.T.3.... 0096f958 00 00 00 00 ff ff ff ff-4a 00 4c 00 c4 1e fe 02 ........J.L..... 0096f968 c8 fa 96 00 00 00 00 00-01 02 00 00 00 00 00 00 ................ 0096f978 c4 fa 96 00 00 00 00 00-a0 30 fe 02 00 00 00 00 .........0...... 0096f988 00 00 00 00 00 00 00 00-08 34 fe 02 01 00 00 00 .........4...... 0096f998 00 00 00 00 00 50 e2 00-00 10 00 00 01 00 00 00 .....P.......... 0096f9a8 00 00 00 00 d0 51 e2 00-02 00 00 00 00 00 00 00 .....Q.......... |
From above we now have "Next SEH Record" with a value of "0096fb98" and a pointer to the current handler of "0x776e6a20". Basically the first 8 bytes represent our SEH information. The first 4 bytes is the pointer to the next SEH record while the second 4 bytes is the pointer to our current handler.
Our structure now looks like:
1 2 3 | [TEB] -> [0096f938] |-> [ Next SEH Record ] -> [0x0096fb98] |-> [ SE Handler ] -> [0x776e6a20] |
Dumping the values at "0x0096fb98", we get:
1 2 3 4 5 6 7 8 9 | 0:000> d 0x0096fb98 0096fb98 f0 fb 96 00 20 6a e6 77-b6 44 f0 44 fe ff ff ff .... j.w.D.D.... 0096fba8 00 fc 96 00 d7 37 e5 77-2e 53 88 33 34 fc 96 00 .....7.w.S.34... 0096fbb8 00 00 df 77 00 30 7c 00-00 b0 f0 77 00 10 00 00 ...w.0|....w.... 0096fbc8 00 00 80 00 01 00 00 00-00 00 df 77 00 00 00 00 ...........w.... 0096fbd8 34 fc 96 00 00 30 7c 00-28 30 7c 00 00 00 00 00 4....0|.(0|..... 0096fbe8 b0 fb 96 00 00 00 00 00-ff ff ff ff 20 6a e6 77 ............ j.w 0096fbf8 5e 55 f0 44 00 00 00 00-10 fc 96 00 de 36 e5 77 ^U.D.........6.w 0096fc08 00 00 00 00 00 00 00 00-20 fc 96 00 8c 36 e5 77 ........ ....6.w |
From above we now have "Next SEH Record" with a value of "0x0096fbf0" and a pointer to the current handler of "0x776e6a20". From the above, it looks like this pointer is point to the same location as the previous one.
Therefore we have:
1 2 3 | [TEB] -> [0096f938] |-> [ Next SEH Record ] -> [0x0096fb98] |---------> [ Next SEH Record ] -> [0x0096fbf0] [ SE Handler ] -> [0x776e6a20] [ SE Handler ] -> [0x776e6a20] |
After dumping the address "0x0096fbf0" we get:
1 2 3 4 5 6 7 8 9 | 0:000> d 0x0096fbf0 0096fbf0 ff ff ff ff 20 6a e6 77-5e 55 f0 44 00 00 00 00 .... j.w^U.D.... 0096fc00 10 fc 96 00 de 36 e5 77-00 00 00 00 00 00 00 00 .....6.w........ 0096fc10 20 fc 96 00 8c 36 e5 77-00 00 00 00 6e 1a d6 bb ....6.w....n... 0096fc20 00 00 00 00 00 00 00 00-34 fc 96 00 00 00 df 77 ........4......w 0096fc30 00 00 00 00 3f 00 01 00-00 00 00 00 00 00 00 00 ....?........... 0096fc40 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0096fc50 7f 02 00 00 00 00 00 00-ff ff 00 00 00 00 00 00 ................ 0096fc60 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ............... |
This now brings us to the end of the chain as we see "0xffffffff".
Now our chain looks like:
1 2 3 | [TEB] -> [0096f938] |-> [ Next SEH Record ] -> [0x0096fb98] |---------> [ Next SEH Record ] -> [0x0096fbf0] |---------> [END OF CHAIN] -> [0xffffffff] [ SE Handler ] -> [0x776e6a20] [ SE Handler ] -> [0x776e6a20] [ SE Handler ] -> [0x776e6a20] |
Now that I have a better understanding of what SEH is and its structure, time to move on to the next post where I learn to exploit these.
References:
https://www.corelan.be/index.php/2009/07/25/writing-buffer-overflow-exploits-a-quick-and-basic-tutorial-part-3-seh/
https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
http://www.openrce.org/articles/full_view/21
https://www.tortall.net/projects/yasm/manual/html/objfmt-win64-exception.html
https://www.microsoft.com/msj/0197/Exception/Exception.aspx
No comments:
Post a Comment