Return CreateRemoteThread ERROR_ACCESS_DENIED - Installing DLL for Windows 7

I am trying to write a program that uses CreateRemoteThread to input a dll.

The problem is that CreateRemoteThread refuses to work. GetLastError () returns 5, i.e. ERROR_ACCESS_DENIED. I can’t understand why!

I am working with this video http://www.youtube.com/watch?v=H3O3hmXkt1I .

 #include <iostream> #include <direct.h> #include <Windows.h> #include <TlHelp32.h> using namespace std; char* GetCurrentDir() { char* szRet = (char*)malloc(MAX_PATH); _getcwd(szRet, MAX_PATH); return szRet; } LPCTSTR SzToLPCTSTR(char* szString) { LPTSTR lpszRet; size_t size = strlen(szString)+1; lpszRet = (LPTSTR)malloc(MAX_PATH); mbstowcs_s(NULL, lpszRet, size, szString, _TRUNCATE); return lpszRet; } void WaitForProcessToAppear(LPCTSTR lpcszProc, DWORD dwDelay) { HANDLE hSnap; PROCESSENTRY32 peProc; BOOL bAppeared = FALSE; while(!bAppeared) { if((hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) != INVALID_HANDLE_VALUE) { peProc.dwSize = sizeof(PROCESSENTRY32); if(Process32First(hSnap, &peProc)) while(Process32Next(hSnap, &peProc) && !bAppeared) if(!lstrcmp(lpcszProc, peProc.szExeFile)) bAppeared = TRUE; } CloseHandle(hSnap); Sleep(dwDelay); } } DWORD GetProcessIdByName(LPCTSTR lpcszProc) { HANDLE hSnap; PROCESSENTRY32 peProc; DWORD dwRet = -1; if((hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) != INVALID_HANDLE_VALUE) { peProc.dwSize = sizeof(PROCESSENTRY32); if(Process32First(hSnap, &peProc)) while(Process32Next(hSnap, &peProc)) if(!lstrcmp(lpcszProc, peProc.szExeFile)) dwRet = peProc.th32ProcessID; } CloseHandle(hSnap); return dwRet; } BOOL InjectDll(DWORD dwPid, char* szDllPath) { DWORD dwMemSize; HANDLE hProc; LPVOID lpRemoteMem, lpLoadLibrary; BOOL bRet = FALSE; if((hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid)) != NULL) { dwMemSize = strlen(szDllPath); if((lpRemoteMem = VirtualAllocEx(hProc, NULL, dwMemSize, MEM_COMMIT, PAGE_READWRITE)) != NULL) if(WriteProcessMemory(hProc, lpRemoteMem, szDllPath, dwMemSize, NULL)) { lpLoadLibrary = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA"); if(CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)lpLoadLibrary, lpRemoteMem, 0, NULL) != NULL) { bRet = TRUE; } cout << GetLastError(); } } CloseHandle(hProc); return bRet; } int main() { char szProc[MAX_PATH], szDll[MAX_PATH]; char* szDllPath = (char*)malloc(MAX_PATH); LPTSTR lpszProc = NULL; for(;;) { cout << "Process: "; cin >> szProc; cout << "DLL: "; cin >> szDll; szDllPath = GetCurrentDir(); strcat_s(szDllPath, MAX_PATH, "\\"); strcat_s(szDllPath, MAX_PATH, szDll); cout << "Waiting for process.. ." << szDllPath << " " << szDll << endl; WaitForProcessToAppear(SzToLPCTSTR(szProc), 100); if(InjectDll(GetProcessIdByName(SzToLPCTSTR(szProc)), szDllPath)) cout << "Injection Succeeded!" << endl; else cout << "Injection Failed!" << endl; cout << "\n"; } return 0; 

After enough search queries, I can’t find the reason why this should not work.

Does CreateRemoteThread work under Windows 7? If so, have I made any obvious mistakes?

+6
source share
5 answers

The reason it fails is because your code is 32-bit and the target process is 64-bit.

No matter how many privileges you have. Windows will not allow this to happen.

I had the same problem. Either you create a 32-bit version of the system and enter it, or transfer the code to 64-bit (which means that it will not work on 32-bit systems).

EDIT

Once upon a time, I found a good way to enter code into and from any target processor mode. It includes the dynamic switching of processor mode to (any) target mode. Duplicated the "heavenly gate." To do this, you need to use the built-in assembly. So basically you can have both 64-bit and 32-bit code in the 32-bit version of exe, determine if the machine is 64-bit, and then go into 64-bit mode and run the 64-bit code. You will then search for imports to find ntdll and load 64-bit kernel.dll and other libraries. Here is a link to examples for anyone who would be interested: http://bit.ly/19P0Lh3

+14
source

The immediate problems that I see are that you are not getting an access token, which should be executed like this:

 HANDLE hToken; TOKEN_PRIVILEGES tp; HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId() ); tp.PrivilegeCount = 1; LookupPrivilegeValue( NULL, _T("SeDebugPrivilege"), &tp.Privileges[0].Luid ); tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; OpenProcessToken( hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken ); AdjustTokenPrivileges( hToken, FALSE, &tp, NULL, NULL, NULL ); CloseHandle( hToken ); 

I don’t have time to view all your code right now, but here is what I pulled out of one of my previous projects:

 // returns open process handle HANDLE InjectDLL( DWORD dwPID, LPCWSTR szDLLPath, HMODULE* lphInjected ) { int cszDLL; LPVOID lpAddress; HMODULE hMod; HANDLE hThread; HANDLE hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, dwPID ); if( hProcess == NULL ) { return NULL; } cszDLL = ( wcslen( szDLLPath ) + 1 ) * sizeof( WCHAR ); // Injection lpAddress = VirtualAllocEx( hProcess, NULL, cszDLL, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); if( lpAddress == NULL ) { return NULL; } WriteProcessMemory( hProcess, lpAddress, szDLLPath, cszDLL, NULL ); hMod = GetModuleHandle( L"kernel32.dll" ); if( hMod == NULL ) { return NULL; } hThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)( GetProcAddress( hMod, "LoadLibraryW" ) ), lpAddress, 0, NULL ); // Locate address our payload was loaded if( hThread != 0 ) { WaitForSingleObject( hThread, INFINITE ); GetExitCodeThread( hThread, ( LPDWORD )lphInjected ); VirtualFreeEx( hProcess, lpAddress, 0, MEM_RELEASE ); CloseHandle( hThread ); } return hThread != 0 ? hProcess : NULL; } 

See if this helps. Let's see later.

+2
source

OK, your code is likely to fail in Windows 7 and Vista due to "Protected Processes", that is, processes that can only be processed by other protected processes, such as explorer.exe, etc. .... On Windows 7 x32 there is a way: since you can download unsigned drivers ... well, you're done (look for Alex Ionescu on google). However, on Windows 7 x64 you cannot (duh!)

"The fourth CreateRemoteThread () parameter is the address. In your case, this is the address of LoadLibraryA. However, in Windows 7, the base address of Kernel32.dll / LoadLibraryA will be different in different processes:"

Well, this is not remotely true, because DLLs are shared at the same addresses in every process, despite the ASLR. However, DLLs can be reinstalled, but you can call GetProcAddress before calling CreateRemoteThread, so it is very unlikely that the DLL will be recreated at the same time.

+2
source

I think the injection method using the CreateRemoteThread () DLL method cannot work on Windows 7.

The fourth CreateRemoteThread () parameter is the address. In your case, this is the address of LoadLibraryA. However, in Windows 7, the base address of Kernel32.dll / LoadLibraryA will be different in different processes; Therefore, CreateRemoteThread () will not work because the address does not match what was expected. This is my personal opinion, hope this helps. :)

0
source

The CreateRemoteThread function does not work in Win Vista / 7. To do this, you need to use the NTCreateThread function, which is not documented.

0
source

Source: https://habr.com/ru/post/909404/


All Articles