我正在尝试编写一个使用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下无效吗? 如果确实如此,我是否犯过任何明显的错误?
答案 0 :(得分:15)
失败的原因是因为您的代码是32位且目标进程是64位。
您拥有多少权限并不重要。 Windows不会让这种情况发生。
我遇到了同样的问题。您生成一个系统32位exe并注入或将您的代码移植到64位(这意味着它不能在32位系统上运行)。
修改强>
很久以前,我发现了一种向任何处理器模式目标注入代码的好方法。它涉及将处理器模式动态切换到(任何)目标的模式。被称为“天堂之门”。为此,您必须使用内联汇编。所以基本上你可以在32位exe中同时拥有64位和32位代码,检测机器是否为64位,然后跳转到64位模式并运行64位代码。然后,您将遍历导入以查找ntdll并加载64位kernel.dll和其他库。以下是任何感兴趣的人的示例链接:http://bit.ly/19P0Lh3
答案 1 :(得分:2)
我看到的直接问题是你没有获得应该这样做的访问令牌:
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;
}
看看它是否有帮助。稍后再看。
答案 2 :(得分:2)
好吧,你的代码很可能在Windows 7和Vista中失败,因为“受保护的进程”,即只能被其他受保护进程操纵的进程,例如explorer.exe等...在Windows 7 x32中有一种方法:因为你可以加载未签名的驱动程序,...好吧,你已经完成了(在谷歌搜索Alex Ionescu)。但是,在Windows 7 x64中,你不能(呃!)
“CreateRemoteThread()的第四个参数是一个地址。在你的情况下它是LoadLibraryA地址。但是,在Windows 7中,Kernel32.dll / LoadLibraryA基地址将在不同的过程中各种各样;”
嗯,这并不是真的,因为尽管有ASLR,但DLL在每个进程中都在相同的地址共享。但是,DLL可以重新定位,但是你可以在调用CreateRemoteThread之前调用GetProcAddress,因此DLL不太可能同时进行重新定位。
答案 3 :(得分:0)
我认为CreateRemoteThread()dll注入方法无法在Windows 7中工作。
CreateRemoteThread()的第四个参数是一个地址。在您的情况下,它是LoadLibraryA地址。但是,在Windows 7中,Kernel32.dll / LoadLibraryA的基地址将在不同的进程中进行各种处理;因此,CreateRemoteThread()将无法工作,因为地址不是您所期望的。这是我自己的看法,希望它会有所帮助。 :)
答案 4 :(得分:0)
CreateRemoteThread函数在Win Vista / 7中不起作用。您必须使用NTCreateThread函数,该函数未记录。
答案 5 :(得分:0)
TLDR :您的代码正确,将Visual Studio调试/编译目标更改为x64。
我之前也遇到过同样的问题,您的代码是Okey,问题是Visual Studio(或任何理智的人)默认以x86模式(32位)执行其程序,因为编译您的代码会很好程序可以在x86或x64体系结构中运行,但不能在进程注入方案中运行!由于其系统调用。
在代码注入的情况下,您应该在项目浏览器的项目属性中更改VS的构建和调试设置,以针对x64处理器进行编译/调试, 或者如果您交叉编译程序,则应使用x64编译器。
如果您正在寻找全局过程注入方法,可以使用 Heaven's Gate 或 The 0x33 Segment Selector 的方法,该方法已在 Vawtrak < / strong>银行恶意软件。
您可能会看到关于“天堂之门”方法的this链接,内容为:
换句话说,它赋予了创建“裸” 64位的能力 代码,它将能够秘密运行,包括发行系统 呼叫,而大多数产品都无法拦截和/或 反思其执行情况