D
D
danij_com2017-02-04 19:05:46
C++ / C#
danij_com, 2017-02-04 19:05:46

How to parse numbers from different files?

Good day. Again I need help.
This time I need to get all the WiFi passwords (keyMaterial) that the device has.
There is a code that decrypts these keys, I want to modify it so that it decrypts all the keys that are stored on the device (C:\ProgramData\Microsoft\Wlansvc\Profiles\Interfaces\{XXXXXXXX-xxxx-xxxx-xxxx-XXXXXXXXXXXX}\{Random -GUID}.xml). As you can understand, the last folder and files can have absolutely random names, and I need to parse the keyMaterial value from them, and send it to be decrypted.
An example of the file itself is as follows:

<?xml version="1.0"?>
<WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1">
  <name>k13736</name>
  <SSIDConfig>
    <SSID>
      <hex>6B3133373336</hex>
      <name>k13736</name>
    </SSID>
  </SSIDConfig>
  <connectionType>ESS</connectionType>
  <connectionMode>auto</connectionMode>
  <MSM>
    <security>
      <authEncryption>
        <authentication>WPA2PSK</authentication>
        <encryption>AES</encryption>
        <useOneX>false</useOneX>
      </authEncryption>
      <sharedKey>
        <keyType>passPhrase</keyType>
        <protected>true</protected>
        <keyMaterial>01000000D08C9DDF0115D1118C7A00C04FC297EB01000000CC9B5CE1E88ED84FB3F7CCFFBC08295C000000000200000000001066000000010000200000006B6A65B2CDA40470AD1EF33285716ECD4E7E9D218F7C88E6BA81DC5C49AA8DB8000000000E8000000002000020000000ED1ADC624E33554777CE2604764D32DF90353952A5760D056739B66AE58AB8FF10000000DD0051EB55693FA81EBAD3C24E60C9C840000000000783DFE4B05F436A03C4295B7772DBA99487A9E72F1BDBFBC3A78D956EE0CB5E9078CF8B07C26799D4B0A8AEB2BD4297682571D38A1D58946FD84D7088BE0E</keyMaterial>
      </sharedKey>
    </security>
  </MSM>
  <MacRandomization xmlns="http://www.microsoft.com/networking/WLAN/profile/v3">
    <enableRandomization>false</enableRandomization>
  </MacRandomization>
</WLANProfile>

Well, here is the code that deals with decryption:
// ConsoleApplication5.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <Windows.h>
#include <tchar.h>
#include <stdio.h>
#include <iostream>
#include <conio.h>
#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 <keyMaterial>
  WCHAR szKey[] = L"01000000D08C9DDF0115D1118C7A00C04FC297EB01000000CC9B5CE1E88ED84FB3F7CCFFBC08295C000000000200000000001066000000010000200000006B6A65B2CDA40470AD1EF33285716ECD4E7E9D218F7C88E6BA81DC5C49AA8DB8000000000E8000000002000020000000ED1ADC624E33554777CE2604764D32DF90353952A5760D056739B66AE58AB8FF10000000DD0051EB55693FA81EBAD3C24E60C9C840000000000783DFE4B05F436A03C4295B7772DBA99487A9E72F1BDBFBC3A78D956EE0CB5E9078CF8B07C26799D4B0A8AEB2BD4297682571D38A1D58946FD84D7088BE0E";
  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);
  }


  _getch();
  return 0;
}

Thank you very much in advance!

Answer the question

In order to leave comments, you need to log in

1 answer(s)
Y
younghacker, 2017-02-06
@younghacker

Mom daragaya... You were able to compile it?
If all the files are the same, then we go through the files in the folder and in the files we look for a string using a regular expression.
In Linux, you can extract the code like this:
Go to the desired directory and run this
I would also add the name of the access point to the expression.
For Windows, you can do this on powershell and, of course, code in C ++ (use, for example, the XML parser library)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question