CreateRemoteThread возвращает ERROR_ACCESS_DENIED - инъекция Windows 7 DLL
Я пытаюсь написать программу, которая использует CreateRemoteThread
ввести DLL.
Проблема в том, что CreateRemoteThread отказывается работать. GetLastError() возвращает 5, которое равно ERROR_ACCESS_DENIED. Я не могу понять, почему!
Я работаю с этим видео 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;
После достаточного количества поисков я не могу найти причину, почему это не должно работать.
Разве CreateRemoteThread не работает под Windows 7? Если это произойдет, я сделал какие-либо очевидные ошибки?
5 ответов
Причиной сбоя является то, что ваш код 32-битный, а целевой процесс - 64-битный.
Неважно, сколько у вас привилегий. Windows не допустит этого.
У меня такая же проблема. Либо вы запускаете системный 32-битный exe и внедряете его, либо переносите свой код на 64-битный (что означает, что он не будет работать на 32-битных системах).
РЕДАКТИРОВАТЬ
Давным-давно я нашел хороший способ внедрения кода в любой целевой режим процессора и из него. Это включает в себя динамическое переключение режима процессора в режим (любой) цели. Называется "небесные ворота". Для этого вам нужно использовать встроенную сборку. Таким образом, в основном вы можете иметь как 64-битный, так и 32-битный код в 32-битном exe-файле, определить, является ли машина 64-битной, затем перейти в 64-битный режим и запустить 64-битный код. Затем вы пройдете по импорту, чтобы найти ntdll и загрузить 64-битный kernel.dll и другие библиотеки. Вот ссылка на примеры для любого, кому это будет интересно: http://bit.ly/19P0Lh3
Непосредственные проблемы, которые я вижу, состоят в том, что вы не получаете токен доступа, что должно быть сделано так:
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 );
У меня нет времени просматривать весь ваш код прямо сейчас, но вот что-то, что я вырвал из одного из моих предыдущих проектов:
// 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;
}
Посмотрите, поможет ли это. Посмотрим позже.
Итак, ваш код может завершиться сбоем в Windows 7 и Vista из-за "Защищенных процессов", то есть процессов, которыми могут манипулировать только другие Защищенные процессы, такие как explorer.exe и т. Д. В Windows 7 x32 есть способ: так как вы можете загружать неподписанные драйверы,... что ж, все готово (ищите Алекса Ионеску в google). В Windows 7 x64, однако, вы не можете (дух!)
"Четвертый параметр CreateRemoteThread() - это адрес. В вашем случае это адрес LoadLibraryA. Однако в Windows 7 базовый адрес Kernel32.dll/LoadLibraryA будет отличаться в разных процессах;"
Что ж, это не совсем так, потому что DLL совместно используются по одним и тем же адресам в каждом процессе, несмотря на ASLR. DLL могут быть перебазированы, но вы можете вызвать GetProcAddress перед вызовом CreateRemoteThread, так что очень маловероятно, что DLL будет перебазирован тем временем.
Функция CreateRemoteThread не работает в Win Vista/7. Для этого вы должны использовать недокументированную функцию NTCreateThread.
Я думаю, что метод инъекции CreateRemoteThread() DLL не может работать в Windows 7.
Четвертый параметр CreateRemoteThread() - это адрес. В вашем случае это адрес LoadLibraryA. Однако в Windows 7 базовый адрес Kernel32.dll/LoadLibraryA будет различным в разных процессах; Следовательно, CreateRemoteThread() не будет работать, поскольку адрес не соответствует ожидаемому. Это моё собственное мнение, надеюсь, оно поможет.:)
TLDR: ваш код ОКЕЙ, изменить Visual Studio отладки / цель компиляции в x64.
Раньше я сталкивался с той же проблемой, ваш код - Okey. Проблема в том, что Visual Studio(или любой здравомыслящий человек) по умолчанию выполняет свои программы в режиме x86 (32 бит), потому что было бы неплохо скомпилировать вашу программу в способ, который работает как в архитектуре x86, так и в архитектуре x64, но не в сценарии внедрения процесса! из-за его системных вызовов.
В случае внедрения кода вам следует изменить настройки сборки и отладки VS для компиляции / отладки для процессора x64 в свойствах вашего проекта в проводнике проекта, или, если вы перекрестно компилируете свою программу, вы должны использовать компилятор x64.
Если вы ищете метод внедрения глобального процесса, то есть метод под названием Heaven's Gate или The 0x33 Segment Selector, который использовался в банковской вредоносной программе Vawtrak.
Вы можете увидеть эту ссылку о методе Heaven's Gate, в которой говорится:
Другими словами, он дает возможность создавать "голый" 64-битный код, который сможет работать скрытно, включая системные вызовы, без того, чтобы большинство продуктов могли перехватить и / или проанализировать его выполнение.