int test_pal_thread_start( test_pal_thread_state_t *thread_state, struct test_pal_logical_processor *lp, test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state), void *thread_user_state ) { BOOL brv; DWORD thread_id; GROUP_AFFINITY ga; int rv = 0; LPPROC_THREAD_ATTRIBUTE_LIST attribute_list; SIZE_T attribute_list_length; assert( thread_state != NULL ); assert( lp != NULL ); assert( thread_function != NULL ); // TRD : thread_user_state can be NULL /* TRD : here we're using CreateRemoteThreadEx() to start a thread in our own process we do this because as a function, it allows us to specify processor and processor group affinity in the create call */ brv = InitializeProcThreadAttributeList( NULL, 1, 0, &attribute_list_length ); attribute_list = malloc( attribute_list_length ); brv = InitializeProcThreadAttributeList( attribute_list, 1, 0, &attribute_list_length ); ga.Mask = ( (KAFFINITY) 1 << lp->logical_processor_number ); ga.Group = (WORD) lp->windows_logical_processor_group_number; memset( ga.Reserved, 0, sizeof(WORD) * 3 ); brv = UpdateProcThreadAttribute( attribute_list, 0, PROC_THREAD_ATTRIBUTE_GROUP_AFFINITY, &ga, sizeof(GROUP_AFFINITY), NULL, NULL ); *thread_state = CreateRemoteThreadEx( GetCurrentProcess(), NULL, 0, thread_function, thread_user_state, NO_FLAGS, attribute_list, &thread_id ); DeleteProcThreadAttributeList( attribute_list ); free( attribute_list ); if( *thread_state != NULL ) rv = 1; return( rv ); }
int main() { std::cout << "Starting\n"; std::cout << "Gaining security privelages...\n"; //SetSecurityInfo(GetCurrentProcess(), // SE_PROCESS std::cout << "Finding window...\n"; LPWSTR window_name = L"Untitled - Unreal Development Kit (64-bit, DX9)"; HWND window_handle = FindWindowEx(nullptr, nullptr, nullptr, window_name); if(window_handle == nullptr) { GenerateWin32Error(); } else { std::cout << "Done.\n"; } std::cout << "Finding process and thread associated with window...\n"; DWORD proc_id = 0; DWORD thread = 0; thread = GetWindowThreadProcessId(window_handle, &proc_id); if(thread == 0) { GenerateWin32Error(); }; std::cout << "Getting the process handle...\n"; HANDLE proc_handle = OpenProcess(PROCESS_VM_OPERATION, false, proc_id); if(proc_handle == NULL) { GenerateWin32Error(); } std::cout << "Getting the address of LoadLibrary function...\n"; auto load_library = reinterpret_cast<LPVOID>(GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA")); if(load_library == NULL) { GenerateWin32Error(); } std::cout << "Allocating memory for dll name to load in remote process...\n"; std::string dllname("DXTestDll.dll"); auto remote_string = reinterpret_cast<LPVOID>(VirtualAllocEx(proc_handle, nullptr, dllname.size(), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE)); if(remote_string == NULL) { GenerateWin32Error(); } std::cout << "Writing dll name string to recently allocated memory...\n"; auto write_success = WriteProcessMemory(proc_handle, remote_string, dllname.c_str(), dllname.size(), nullptr); if(write_success == 0) { GenerateWin32Error(); // Error here because no privelage } std::cout << "Creating a remote thread in the process...\n"; auto success = CreateRemoteThreadEx(proc_handle, //process handle nullptr, //default security descriptor 0, //default stack size reinterpret_cast<LPTHREAD_START_ROUTINE>(load_library), // start the thread by loading our dll reinterpret_cast<LPVOID>(remote_string), //pass our dll name as paremeter 0, //run thread immediately 0, //Attribute list nullptr); // Don't need to receive the thread identifier system("pause"); return 0; }