C/C++, Hacking, Post-Exploitation, Programming

Generating a unique machine id

The following code snippets is from Post-recon project. This project is a work in progress.

You can check Github for the full source code, here I will just point out the most interesting parts.

Current source code

Generate computer unique ID

  • Architecture
  • Windows OS version
  • Cpu
  • Gpu
  • is admin?
  • MotherBoard
  • Chassis Type
  • Username
  • PC name
  • Total Ram
  • Bios
  • First MAC address
HRESULT Core::UniqueID(char **id)
{
 
{...}
 
//get cpu
    if ((tmp = getValue(_services, &cpu, L"SELECT * FROM Win32_Processor", L"Name")) > 0) {
        totalSize += tmp;
    }
 
    //get architecture
    architecture = Architecture();
    totalSize += Common::NumOfDigits(architecture);
 
    //get os version(windowns)
    winOS = WinVer();
    totalSize += Common::NumOfDigits(winOS);
 
    //get gpu
    if ((tmp = getValue(_services, &gpu, L"SELECT Caption FROM Win32_VideoController", L"Caption")) > 0) {
        totalSize += tmp;
    }
 
    //is admin?
    isadmin = isAdmin() ? 2 : 1;
    totalSize += Common::NumOfDigits(isadmin);
 
    //get motherBoard
    if ((tmp = getValue(_services, &motherBoard, L"Select * from Win32_BaseBoard", L"Manufacturer", L"Product", L"SerialNumber")) > 0) {
        totalSize += tmp;
    }
 
    //get chassis type
    chassisType = getValue(_services, L"SELECT ChassisTypes FROM Win32_SystemEnclosure", L"ChassisTypes");
    totalSize += Common::NumOfDigits(chassisType);
 
    //get username
    if ((tmp = getUser(&username)) > 0) {
        totalSize += tmp;
    }
 
    //get pcname
    if ((tmp = getPc(&pcname)) > 0) {
        totalSize += tmp;
    }
 
    //get ram
    ram = getRam();
    totalSize += Common::NumOfDigits(ram);
 
    //get bios
    if ((tmp = getValue(_services, &bios, L"Select * from Win32_BIOS", L"Caption", L"Manufacturer", L"SerialNumber")) > 0) {
        totalSize += tmp;
    }
 
    //get first mac address
    if ((tmp = getFirstMacAddress(&mac)) > 0) {
        totalSize += tmp;
    }
 
{...}
 
if (Common::FormatString(output, totalSize, "%u%u%s%s%u%s%u%s%s%lu%s%s",
                architecture, winOS, cpu, gpu, isadmin, motherBoard, chassisType, username, pcname, ram, bios, mac) != -1)
            {
 
                //calc sha-2 hash
                result = LibHash::sha256((unsigned char *)output, totalSize - 1, id) ? S_OK : S_FALSE;
            }
 
{...}
 
}

WMI

{...}
 
static CLSID CLSID_WbemLocator2 = { 0x4590F811, 0x1D3A, 0x11D0,{ 0x89, 0x1F, 0, 0xAA, 0, 0x4B, 0x2E, 0x24 } };
 
// .:: WMI ::.
 
//initialize wmi
static bool wmiInitialize(void)
{
    HRESULT result = S_FALSE;
 
    result = CoInitializeEx(0, COINIT_MULTITHREADED);
    if (FAILED(result)) {
        return false;
    }
 
    result = CoInitializeSecurity(
        NULL, -1, NULL, NULL,
        RPC_C_AUTHN_LEVEL_DEFAULT,
        RPC_C_IMP_LEVEL_IMPERSONATE,
        NULL, EOAC_NONE, NULL);
 
    if (FAILED(result)) {
        return false;
    }
 
    return true;
}
 
//execute wmi query
static void* wmiExecQuery(IWbemServices *services, wchar_t *query, bool forwardOnly)
{
    if (services == NULL || query == NULL || SysStringLen(query) == 0) return NULL;
 
    HRESULT result = S_FALSE;
    IEnumWbemClassObject *pEnumerator = NULL;
    wchar_t *language;
 
    if ((language = SysAllocString(L"WQL")) == NULL) {
        return NULL;
    }
 
    result = services->ExecQuery(
        language,
        query,
        forwardOnly ? (WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY) : WBEM_FLAG_RETURN_IMMEDIATELY,
        NULL,
        &pEnumerator);
 
    Common::SysFreeStr(language);
 
    if (FAILED(result)) {
        return NULL;
    }
 
    if (result != WBEM_S_NO_ERROR || pEnumerator == NULL) {
        return NULL;
    }
 
    return pEnumerator;
}
 
//retrieve unisgned short from array
static unsigned short wmiGetUShortFromArrayField(IEnumWbemClassObject *enumerator, const wchar_t *fieldname)
{
    if (enumerator == NULL || fieldname == NULL || wcslen(fieldname) == 0) return 0;
 
    IWbemClassObject *pclsObj = NULL;
    unsigned long uReturn = 0;
    HRESULT result = S_FALSE;
    HRESULT hres = WBEM_S_NO_ERROR;
    int val = 0;
    VARIANT v;
    long lLower = 0;
    long lUpper = 0;
    long i = 0;
    SAFEARRAY *pSafeArray;
 
    hres = enumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
    if (FAILED(hres) || uReturn == 0) {
        return 0;
    }
 
    result = pclsObj->Get(fieldname, 0, &v, 0, 0);
    if (FAILED(result)) {
        pclsObj->Release();
        return 0;
    }
 
    if ((v.vt & VT_ARRAY))
    {
        pSafeArray = v.parray;
        SafeArrayGetLBound(pSafeArray, 1, &lLower);
        SafeArrayGetUBound(pSafeArray, 1, &lUpper);
 
        result = SafeArrayGetElement(pSafeArray, &i, &val);
        if (FAILED(result)) {
            SafeArrayDestroy(pSafeArray);
            pclsObj->Release();
            return 0;
        }
    }
 
    SafeArrayDestroy(pSafeArray);
    pclsObj->Release();
 
    return val;
}
 
//retrieve string field value
static unsigned int wmiGetStringField(IEnumWbemClassObject *enumerator, char **buf, const wchar_t *fieldname)
{
    if (enumerator == NULL || fieldname == NULL || wcslen(fieldname) == 0) return 0;
 
    IWbemClassObject *pclsObj = NULL;
    unsigned long uReturn = 0;
    HRESULT result = S_FALSE;
    HRESULT hres = WBEM_S_NO_ERROR;
    unsigned int size = 0;
    unsigned int totalSize = 0;
    char *tmp = 0;
    VARIANT v;
 
    while (enumerator && hres == WBEM_S_NO_ERROR)
    {
        hres = enumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
 
        if (FAILED(hres) || uReturn == 0) {
            break;
        }
 
        result = pclsObj->Get(fieldname, 0, &v, 0, 0);
        if (FAILED(result) /*|| V_VT(&vtProp) != VT_BSTR*/) {
            pclsObj->Release();
            continue;
        }
 
        size = wcslen(v.bstrVal);
        tmp = Common::WcharToChar(v.bstrVal, size);
 
        if (*buf == NULL) {
            totalSize = size + 1;
 
            if ((*buf = (char*)Common::hAlloc(totalSize * sizeof(char))) == NULL) {
                VariantClear(&v);
                pclsObj->Release();
                return 0;
            }
 
            if (Common::CopyString(*buf, totalSize, tmp) != 0) {
                Common::hFree(*buf);
                VariantClear(&v);
                pclsObj->Release();
                return 0;
            }
 
        }
        else {
            totalSize += strlen(*buf) + size + 2;
 
            if ((*buf = (char*)Common::hReAlloc(*buf, totalSize)) == NULL) {
                Common::hFree(*buf);
                VariantClear(&v);
                pclsObj->Release();
                return 0;
            }
 
            if (Common::ConcatString(*buf, totalSize, ",") == S_FALSE) {
                Common::hFree(*buf);
                VariantClear(&v);
                pclsObj->Release();
                return 0;
            }
 
            if (Common::ConcatString(*buf, totalSize, tmp) == S_FALSE) {
                Common::hFree(*buf);
                VariantClear(&v);
                pclsObj->Release();
                return 0;
            }
        }
 
        VariantClear(&v);
        pclsObj->Release();
    }
 
    return totalSize - 1;
}
 
//create wmi instance/interface
static void* wmiCreate(void)
{
    HRESULT result = S_FALSE;
    IWbemLocator *locator = NULL;
 
    result = CoCreateInstance(
        CLSID_WbemLocator2, NULL,
        CLSCTX_INPROC_SERVER | CLSCTX_NO_FAILURE_LOG | CLSCTX_NO_CODE_DOWNLOAD,
        IID_IWbemLocator, (LPVOID *)&locator);
 
    if (FAILED(result)) {
        return NULL;
    }
 
    if (result != S_OK || locator == NULL) {
        return NULL;
    }
 
    return locator;
}
 
//connect to wmi services
static void* wmiConnect(IWbemLocator *locator, wchar_t *resource)
{
    if (locator == NULL || resource == NULL || SysStringLen(resource) == 0) return NULL;
 
    HRESULT result = S_FALSE;
    IWbemServices *services = NULL;
 
    result = locator->ConnectServer(
        resource, NULL,
        NULL, NULL,
        0, NULL,
        NULL, &services
    );
 
    if (FAILED(result)) {
        return NULL;
    }
 
    result = CoSetProxyBlanket(
        (IUnknown *)services,
        RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE,
        NULL, RPC_C_AUTHN_LEVEL_CALL,
        RPC_C_IMP_LEVEL_IMPERSONATE, NULL,
        EOAC_NONE
    );
 
    if (FAILED(result)) {
        services->Release();
        return NULL;
    }
 
    return services;
}
 
{...}