使用CryptUnprotectData解密WEP wlan配置文件密钥

我正在尝试使用CryptUnprotectData解密WEP配置文件的密钥。 我获取配置文件密钥的方法是使用netsh导出配置文件。

netsh wlan export profile name="MyWEP" folder="./" 

现在,我手动将密钥材料从netsh命令生成的.xml文件复制到我的程序。 顺便说一下,我正在解密的是 –

 DATA_BLOB DataOut, DataVerify; DataOut.cbData = encryptData.length(); DataOut.pbData = (BYTE*)("I_Manually_Copy_The_WEP_Key_Here"); if (CryptUnprotectData( &DataOut, NULL, NULL, NULL, NULL, 0, &DataVerify)) { printf("The decrypted data is: %s\n", DataVerify.pbData); } else { printf("Failed. Error Code: %d", GetLastError()); } 

但我收到错误代码13引用无效数据。 我究竟做错了什么 ? 在Win 7及更高版本中,我可以直接使用WlanGetProfile和参数WLAN_PROFILE_GET_PLAINTEXT_KEY 。 但我在Vista没有选择使用CryptUnprotectData函数。 我在 这里看过类似的post,但是没有得到太多有用的信息。 此外,我使用相同的系统具有相同的用户登录凭据。 有人可以建议我怎么办?

PS:我在Windows桌面SDK论坛上发布了相同的问题,但还没有得到回复。 试试我的运气吧。

我喜欢有关Windows安全性的问题。 所以如果我偶尔看到这样的话,我会尝试解决它。

在您的情况下,您已经通过使用netsh.exe wlan export profile ...进行了第一步,以便从XML文件中的WLAN配置文件中导出数据。 该文件包含元素。 元素内部的数据是二进制数据,编码为hex:(类似于01000000D08C9DDF0115D1118C7A00C0... )。

所以你首先需要做的是将字符串解码为二进制数据。 您可以使用CryptStringToBinary和CRYPT_STRING_HEX参数将字符串解码为二进制。

下一步是用二进制数据填充DATA_BLOB并调用CryptUnprotectData来获得结果,但是……有一个小问题。 您如何阅读以下WlanGetProfile的文档

默认情况下, pstrProfileXml指向的配置文件中返回的keyMaterial元素已加密。 如果您的进程在同一台计算机上的LocalSystem帐户的上下文中运行,则可以通过调用CryptUnprotectData函数来解密密钥材料。

Windows Server 2008和Windows VistapstrProfileXml指向的概要文件架构中返回的keyMaterial元素始终是加密的。 如果您的进程在LocalSystem帐户的上下文中运行,则可以通过调用CryptUnprotectData函数来解密密钥材料。

因此,为了能够解密密钥,我们必须在LocalSystem安全上下文中调用CryptUnprotectData 。 如果您的程序已在LocalSystem上下文中运行,则可以直接执行此操作。 如果不是这样,但您具有管理权限或者您至少具有“调试”权限,则可以从计算机上运行的其他进程“借用” LocalSystem令牌。 例如,可以获取“winlogon.exe”进程的进程令牌并模拟它。

以下演示程序使用我个人喜欢的NtQuerySystemInformation方法(参见我的旧答案 )枚举进程。 可以使用EnumProcesses或其他众所周知的方法来做同样的事情。 这是代码对我有用

 #include  #include  #include  #pragma comment (lib, "Crypt32.lib") #define STATUS_SUCCESS ((NTSTATUS)0x00000000L) #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) typedef enum _SYSTEM_INFORMATION_CLASS { SystemProcessInformation = 5 } SYSTEM_INFORMATION_CLASS; typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING; typedef LONG KPRIORITY; // Thread priority typedef struct _SYSTEM_PROCESS_INFORMATION_DETAILD { ULONG NextEntryOffset; ULONG NumberOfThreads; LARGE_INTEGER SpareLi1; LARGE_INTEGER SpareLi2; LARGE_INTEGER SpareLi3; LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; LARGE_INTEGER KernelTime; UNICODE_STRING ImageName; KPRIORITY BasePriority; HANDLE UniqueProcessId; ULONG InheritedFromUniqueProcessId; ULONG HandleCount; BYTE Reserved4[4]; PVOID Reserved5[11]; SIZE_T PeakPagefileUsage; SIZE_T PrivatePageCount; LARGE_INTEGER Reserved6[6]; } SYSTEM_PROCESS_INFORMATION_DETAILD, *PSYSTEM_PROCESS_INFORMATION_DETAILD; typedef NTSTATUS (WINAPI *PFN_NT_QUERY_SYSTEM_INFORMATION)( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, IN OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT OPTIONAL PULONG ReturnLength ); // // The function changes a privilege named pszPrivilege for // the current process. If bEnablePrivilege is FALSE, the privilege // will be disabled, otherwise it will be enabled. // BOOL SetCurrentPrivilege (LPCTSTR pszPrivilege, // Privilege to enable/disable BOOL bEnablePrivilege) // to enable or disable privilege { HANDLE hToken; TOKEN_PRIVILEGES tp; LUID luid; TOKEN_PRIVILEGES tpPrevious; DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES); BOOL bSuccess = FALSE; if (!LookupPrivilegeValue(NULL, pszPrivilege, &luid)) return FALSE; if (!OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken )) return FALSE; // // first pass. get current privilege setting // tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = 0; AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious); if (GetLastError() == ERROR_SUCCESS) { // // second pass. set privilege based on previous setting // tpPrevious.PrivilegeCount = 1; tpPrevious.Privileges[0].Luid = luid; if(bEnablePrivilege) tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED); else tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes); AdjustTokenPrivileges( hToken, FALSE, &tpPrevious, cbPrevious, NULL, NULL); if (GetLastError() == ERROR_SUCCESS) bSuccess=TRUE; CloseHandle(hToken); } else { DWORD dwErrorCode = GetLastError(); CloseHandle(hToken); SetLastError(dwErrorCode); } return bSuccess; } DWORD GetProcessIdByProcessName (LPCWSTR pszProcessName) { SIZE_T bufferSize = 1024*sizeof(SYSTEM_PROCESS_INFORMATION_DETAILD); PSYSTEM_PROCESS_INFORMATION_DETAILD pspid = NULL; HANDLE hHeap = GetProcessHeap(); PBYTE pBuffer = NULL; ULONG ReturnLength; PFN_NT_QUERY_SYSTEM_INFORMATION pfnNtQuerySystemInformation = (PFN_NT_QUERY_SYSTEM_INFORMATION) GetProcAddress (GetModuleHandle(TEXT("ntdll.dll")), "NtQuerySystemInformation"); NTSTATUS status; int uLen = lstrlenW(pszProcessName)*sizeof(WCHAR); __try { pBuffer = (PBYTE) HeapAlloc (hHeap, 0, bufferSize); #pragma warning(disable: 4127) while (TRUE) { #pragma warning(default: 4127) status = pfnNtQuerySystemInformation (SystemProcessInformation, (PVOID)pBuffer, bufferSize, &ReturnLength); if (status == STATUS_SUCCESS) break; else if (status != STATUS_INFO_LENGTH_MISMATCH) { // 0xC0000004L _tprintf (TEXT("ERROR 0x%X\n"), status); return 1; // error } bufferSize *= 2; pBuffer = (PBYTE) HeapReAlloc (hHeap, 0, (PVOID)pBuffer, bufferSize); } for (pspid = (PSYSTEM_PROCESS_INFORMATION_DETAILD)pBuffer; ; pspid = (PSYSTEM_PROCESS_INFORMATION_DETAILD)(pspid->NextEntryOffset + (PBYTE)pspid)) { if (pspid->ImageName.Length == uLen && lstrcmpiW(pspid->ImageName.Buffer, pszProcessName) == 0) return (DWORD)pspid->UniqueProcessId; if (pspid->NextEntryOffset == 0) break; } } __finally { pBuffer = (PBYTE) HeapFree (hHeap, 0, pBuffer); } return 0; } int _tmain() { BOOL bIsSuccess, bImpersonated = FALSE; HANDLE hProcess = NULL, hProcessToken = NULL; DATA_BLOB DataOut, DataVerify; // !!! in the next line you should copy the string from  WCHAR szKey[] = L"01000000D08C9DDF0115D1118C7...."; BYTE byKey[1024]; DWORD cbBinary, dwFlags, dwSkip; DWORD dwProcessId = GetProcessIdByProcessName(L"winlogon.exe"); if (dwProcessId == 0) return 1; bIsSuccess = SetCurrentPrivilege(SE_DEBUG_NAME, TRUE); if (!bIsSuccess) return GetLastError(); __try { hProcess = OpenProcess(MAXIMUM_ALLOWED, FALSE, dwProcessId); if (!hProcess) __leave; bIsSuccess = OpenProcessToken (hProcess, MAXIMUM_ALLOWED, &hProcessToken); if (!bIsSuccess) __leave; bIsSuccess = ImpersonateLoggedOnUser(hProcessToken); if (!bIsSuccess) __leave; bImpersonated = TRUE; cbBinary = sizeof(byKey); bIsSuccess = CryptStringToBinary (szKey, lstrlenW(szKey), CRYPT_STRING_HEX, // CRYPT_STRING_HEX_ANY byKey, &cbBinary, &dwSkip, &dwFlags); if (!bIsSuccess) __leave; DataOut.cbData = cbBinary; DataOut.pbData = (BYTE*)byKey; if (CryptUnprotectData (&DataOut, NULL, NULL, NULL, NULL, 0, &DataVerify)) { _tprintf(TEXT("The decrypted data is: %hs\n"), DataVerify.pbData); } } __finally { if (bImpersonated) RevertToSelf(); if (hProcess) CloseHandle(hProcess); if (hProcessToken) CloseHandle(hProcessToken); } return 0; }