Last active
December 25, 2024 04:38
-
-
Save wizardy0ga/65b18ac57500473f16739f4e1804fb47 to your computer and use it in GitHub Desktop.
A PoC DRM protected program for windows
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| Description: | |
| Program is a PoC DRM implementation. The program will only execute on the windows device that it first executed | |
| on. If it's copied to another device, it will delete itself on execution. | |
| A signature is kept in the rdata section of the binary. On fisrt exection, if the signature is the default signature, | |
| DRM will be initialized. This process consists of hashing the BIOS's UUID, & replacing the default signature with this | |
| hash. When the program executes again, it will check the BIOS's UUID hash against the signature stored in the | |
| .rdata section. If the hash doesn't match, the program deletes itself. | |
| NOTE: Disable compiler optimization in Visual studio when compiling on Release config or else it won't work. | |
| Author: | |
| Wizardy0ga | |
| Date: | |
| Novemeber 2024 | |
| */ | |
| #define _WIN32_DCOM | |
| #include <windows.h> | |
| #include <stdio.h> | |
| #include <winternl.h> | |
| #include <combaseapi.h> | |
| #include <Wbemidl.h> | |
| #pragma comment(lib, "wbemuuid.lib") | |
| #define NEW_STREAM L":%x%x\x00" | |
| #define DEFAULT_HASH 0xDEADBEEF | |
| CONST DWORD g_UuidHash = DEFAULT_HASH; | |
| DWORD HashSdbmW(LPCWSTR String) | |
| { | |
| ULONG Hash = 0; | |
| INT c; | |
| while (c = *String++) | |
| Hash = c + (Hash << 6) + (Hash << 16) - Hash; | |
| return Hash; | |
| } | |
| PBYTE ReadSelfFromDisk(PDWORD pdwSize) | |
| { | |
| HANDLE hFile = INVALID_HANDLE_VALUE; | |
| PBYTE pImage = NULL; | |
| DWORD dwFileSize = 0x00; | |
| DWORD dwBytesRead = 0x00; | |
| LPWSTR szImageName = NULL; | |
| if ((szImageName = (LPWSTR)(((PPEB)__readgsqword(0x60))->ProcessParameters->ImagePathName.Buffer))) { | |
| if ((hFile = CreateFileW(szImageName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) { | |
| if ((dwFileSize = GetFileSize(hFile, NULL)) != INVALID_FILE_SIZE) { | |
| if ((pImage = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwFileSize))) { | |
| if (ReadFile(hFile, pImage, dwFileSize, &dwBytesRead, NULL)) { | |
| *pdwSize = dwFileSize; | |
| CloseHandle(hFile); | |
| return pImage; | |
| } | |
| } | |
| HeapFree(GetProcessHeap(), 0, pImage); | |
| } | |
| CloseHandle(hFile); | |
| } | |
| } | |
| return NULL; | |
| } | |
| BOOL SelfDelete() | |
| { | |
| HANDLE hFile = INVALID_HANDLE_VALUE; | |
| PWSTR szImageName = NULL; | |
| FILE_DISPOSITION_INFO DisposalInfo = { .DeleteFile = TRUE }; | |
| SIZE_T BufferSize = sizeof(FILE_RENAME_INFO) + MAX_PATH + 1; | |
| PFILE_RENAME_INFO RenameInfo = NULL; | |
| RenameInfo = malloc(sizeof(FILE_RENAME_INFO) + MAX_PATH + 1); | |
| if (RenameInfo) | |
| { | |
| RenameInfo->FileNameLength = sizeof(NEW_STREAM); | |
| RenameInfo->ReplaceIfExists = FALSE; | |
| RenameInfo->RootDirectory = 0x00; | |
| swprintf(RenameInfo->FileName, MAX_PATH, NEW_STREAM, rand(), rand() * rand()); | |
| if ((szImageName = (LPWSTR)(((PPEB)__readgsqword(0x60))->ProcessParameters->ImagePathName.Buffer))) { | |
| if ((hFile = CreateFileW(szImageName, DELETE | SYNCHRONIZE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) { | |
| if (SetFileInformationByHandle(hFile, FileRenameInfo, RenameInfo, sizeof(RenameInfo) + MAX_PATH + 1)) { | |
| CloseHandle(hFile); | |
| if ((hFile = CreateFileW(szImageName, DELETE | SYNCHRONIZE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) { | |
| if (SetFileInformationByHandle(hFile, FileDispositionInfo, &DisposalInfo, sizeof(DisposalInfo))) { | |
| if (CloseHandle(hFile)) { | |
| free(RenameInfo); | |
| return TRUE; | |
| } | |
| } | |
| CloseHandle(hFile); | |
| } | |
| } | |
| CloseHandle(hFile); | |
| } | |
| } | |
| free(RenameInfo); | |
| } | |
| return FALSE; | |
| } | |
| BOOL WriteImageToDisk(PVOID pImageBase, DWORD dwSize) | |
| { | |
| HANDLE hFile = INVALID_HANDLE_VALUE; | |
| DWORD dwBytesWritten = 0x00; | |
| PWCHAR szImageName = (PWCHAR)(((PPEB)__readgsqword(0x60))->ProcessParameters->ImagePathName.Buffer); | |
| if ((hFile = CreateFileW(szImageName, GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) { | |
| if (WriteFile(hFile, pImageBase, dwSize, &dwBytesWritten, NULL) && dwBytesWritten == dwSize) { | |
| CloseHandle(hFile); | |
| return TRUE; | |
| } | |
| CloseHandle(hFile); | |
| } | |
| return FALSE; | |
| } | |
| PDWORD GetDefaultSignature(PBYTE pImage) | |
| { | |
| DWORD Size = 0x00; | |
| PDWORD pDwordArray = 0x00; | |
| DWORD dwOffset = 0x00; | |
| PIMAGE_DOS_HEADER pDosHeader = NULL; | |
| PIMAGE_NT_HEADERS pNtHeader = NULL; | |
| PIMAGE_SECTION_HEADER pSection = NULL; | |
| pDosHeader = (PIMAGE_DOS_HEADER)pImage; | |
| if (pDosHeader->e_magic == IMAGE_DOS_SIGNATURE) { | |
| pNtHeader = (PIMAGE_NT_HEADERS)(pImage + pDosHeader->e_lfanew); | |
| if (pNtHeader->Signature == IMAGE_NT_SIGNATURE) { | |
| pSection = IMAGE_FIRST_SECTION(pNtHeader); | |
| for (int i = 0; i < pNtHeader->FileHeader.NumberOfSections; i++) { | |
| if ((strcmp(".rdata", (PCHAR)(pSection->Name))) == 0) { | |
| pDwordArray = (PDWORD)(pImage + pSection->PointerToRawData); | |
| for (unsigned int i = 0; i < pSection->SizeOfRawData / sizeof(DWORD); i++) { | |
| if (*pDwordArray == g_UuidHash) { | |
| return pDwordArray; | |
| } | |
| pDwordArray += sizeof(DWORD); | |
| } | |
| break; | |
| } | |
| pSection++; | |
| } | |
| printf("not found\n"); | |
| } | |
| } | |
| return NULL; | |
| } | |
| PWCHAR GetBiosUuid() | |
| { | |
| HRESULT result = 0; | |
| ULONG uReturned = 0; | |
| IWbemLocator* pIWbemLocator = NULL; | |
| IWbemServices* pIWbemServices = NULL; | |
| IEnumWbemClassObject* pIEnumWbemClassObject = NULL; | |
| IWbemClassObject* pIWbemClassObject = NULL; | |
| VARIANT UUID; | |
| PWCHAR szUUID = 0; | |
| VariantInit(&UUID); | |
| result = CoInitializeEx(0, COINIT_MULTITHREADED); | |
| if (result != S_OK) | |
| return FALSE; | |
| result = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); | |
| if (result != S_OK) | |
| return FALSE; | |
| result = CoCreateInstance(&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, &IID_IWbemLocator, (LPVOID*)&pIWbemLocator); | |
| if (result != S_OK) | |
| goto Cleanup; | |
| result = pIWbemLocator->lpVtbl->ConnectServer(pIWbemLocator, L"ROOT\\CIMV2", NULL, NULL, 0, 0, 0, 0, &pIWbemServices); | |
| if (result != S_OK) | |
| goto Cleanup; | |
| result = pIWbemServices->lpVtbl->ExecQuery(pIWbemServices, L"WQL", L"SELECT UUID FROM Win32_ComputerSystemProduct", WBEM_FLAG_BIDIRECTIONAL, 0, &pIEnumWbemClassObject); | |
| if (result != S_OK) | |
| goto Cleanup; | |
| result = pIEnumWbemClassObject->lpVtbl->Next(pIEnumWbemClassObject, WBEM_INFINITE, 1, &pIWbemClassObject, &uReturned); | |
| if (result != S_OK) | |
| goto Cleanup; | |
| result = pIWbemClassObject->lpVtbl->Get(pIWbemClassObject, L"UUID", 0, &UUID, 0, 0); | |
| if (result == S_OK) { | |
| szUUID = (PWCHAR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (lstrlenW(UUID.bstrVal) * sizeof(WCHAR))); | |
| wsprintf(szUUID, UUID.bstrVal, (lstrlenW(UUID.bstrVal) + 1 * sizeof(WCHAR))); | |
| } | |
| Cleanup: | |
| if (pIWbemLocator) | |
| pIWbemLocator->lpVtbl->Release(pIWbemLocator); | |
| if (pIWbemServices) | |
| pIWbemServices->lpVtbl->Release(pIWbemServices); | |
| if (pIWbemClassObject) | |
| pIWbemClassObject->lpVtbl->Release(pIWbemClassObject); | |
| if (pIEnumWbemClassObject) | |
| pIEnumWbemClassObject->lpVtbl->Release(pIEnumWbemClassObject); | |
| VariantClear(&UUID); | |
| return szUUID; | |
| } | |
| BOOL InitDrm() | |
| { | |
| PBYTE pImage = NULL; | |
| PWCHAR szUUID = GetBiosUuid(); | |
| DWORD dwSize = 0x00, | |
| PDWORD pdwSignature = 0x00; | |
| if (szUUID) | |
| if ((pImage = ReadSelfFromDisk(&dwSize))) /* Read process image file into memory */ | |
| if ((pdwSignature = GetDefaultSignature(pImage))) { /* Get a pointer to the signture */ | |
| *pdwSignature = HashSdbmW((LPCWSTR)szProductId); /* Change the value to hashed bios uuid */ | |
| if (SelfDelete()) /* Delete current image from disk */ | |
| if (WriteImageToDisk((PVOID)pImage, dwSize)) /* Write image in memory with modified signature to disk */ | |
| return TRUE; | |
| } | |
| return FALSE; | |
| } | |
| int main() | |
| { | |
| if (g_UuidHash == DEFAULT_HASH) { | |
| printf("[+] First execution detected. Initializing DRM..."); | |
| if (InitDrm()) { | |
| printf("Success!\n"); | |
| } | |
| else { | |
| printf("Failed!\n"); | |
| return -1; | |
| } | |
| } | |
| else | |
| { | |
| printf("[-] DRM already initialized. Verifying this is the correct computer.\n"); | |
| if (g_UuidHash == HashSdbmW(GetBiosUuid())) { | |
| printf("[+] Executing on the correct system. Execution will continue.\n"); | |
| getchar(); | |
| } | |
| else { | |
| SelfDelete(); | |
| printf("[-] Program is not running on correct system. Program has deleted itself\n"); | |
| return -1; | |
| } | |
| } | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment