-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMS08-067-Demo.cpp
167 lines (129 loc) · 4.3 KB
/
MS08-067-Demo.cpp
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#include <wchar.h>
// This is the decompiled function sub_5B86A51B in netapi32.dll on XP SP3
// and sub_6EA11D4D on Vista SP1
int ms08_067(wchar_t* path)
{
wchar_t* p;
wchar_t* q;
wchar_t* previous_slash = NULL;
wchar_t* current_slash = NULL;
wchar_t ch;
#ifdef VISTA
int len = wcslen(path);
wchar_t* end_of_path = path + len;
#endif
// If the path starts with a server name, skip it
if ((path[0] == L'\\' || path[0] == L'/') &&
(path[1] == L'\\' || path[1] == L'/'))
{
p = path + 2;
while (*p != L'\\' && *p != L'/') {
if (*p == L'\0')
return 0;
p++;
}
p++;
// make path point after the server name
path = p;
// make sure the server name is followed by a single slash
if (path[0] == L'\\' || path[0] == L'/')
return 0;
}
if (path[0] == L'\0') // return if the path is empty
return 1;
// Iterate through the path and canonicalize ..\ and .\
p = path;
while (1) {
if (*p == L'\\') {
// we have a slash
if (current_slash == p - 1) // don't allow consequtive slashes
return 0;
// store the locations of the current and previous slashes
previous_slash = current_slash;
current_slash = p;
}
else if (*p == L'.' && (current_slash == p - 1 || p == path)) {
// we have \. or ^.
if (p[1] == L'.' && (p[2] == L'\\' || p[2] == L'\0')) {
// we have a \..\, \..$, ^..\ or ^..$ sequence
if (previous_slash == NULL)
return 0;
// example: aaa\bbb\..\ccc
// ^ ^ ^
// | | &p[2]
// | |
// | current_slash
// |
// previous_slash
ch = p[2];
#ifdef VISTA
if (previous_slash >= end_of_path)
return 0;
wcscpy_s(previous_slash, (end_of_path - previous_slash) / 2, p + 2);
#else // XP
wcscpy(previous_slash, &p[2]);
#endif
if (ch == L'\0')
return 1;
current_slash = previous_slash;
p = previous_slash;
// find the slash before p
// BUG: if previous_slash points to the beginning of the
// string, we'll go beyond the start of the buffer
//
// example string: \a\..\
q = p - 1;
while (*q != L'\\' && q != path)
q--;
if (*p == L'\\')
previous_slash = q;
else
previous_slash = NULL;
}
else if (p[1] == L'\\') {
// we have \.\ or ^.\
#ifdef VISTA
if (current_slash != NULL) {
if (current_slash >= end_of_path)
return 0;
wcscpy_s(current_slash, (end_of_path - current_slash) / 2, p + 2);
goto end_of_loop;
}
else { // current_slash == NULL
if (p >= end_of_path)
return 0;
wcscpy_s(p, (end_of_path - p) / 2, p + 2);
goto end_of_loop;
}
#else // XP
if (current_slash != NULL) {
wcscpy(current_slash, p + 2);
goto end_of_loop;
}
else { // current_slash == NULL
wcscpy(p, p + 2);
goto end_of_loop;
}
#endif
}
else if (p[1] != L'\0') {
// we have \. or ^. followed by some other char
if (current_slash != NULL) {
p = current_slash;
}
*p = L'\0';
return 1;
}
}
p++;
end_of_loop:
if (*p == L'\0')
return 1;
}
}
// Run this program to simulate the MS08-067 vulnerability
int main()
{
wchar_t PathName[] = L"\\c\\..\\..\\AAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
return ms08_067(PathName);
}