我的 dll 注入。编译为 32 位时成功,但编译为 64 位时失败
my dll injection . succeed when compiled as 32 bit , but failed when compiled as 64 bit
我的 OS 是 Windows 8.1 64 位。我的程序是向目标进程注入一个DLL
文件,当这个DLL文件附加到一个进程时,它会在D:
上创建一个.txt
文件,并在其中写入一些单词,然后保存。它只是一个 test.But 当我将我的程序编译为 32 位程序并且我的 DLL 代码被编译为 32 位时,它成功了,它可以创建文件并保存内容。但是当我将我的 DLL 代码和我的程序编译为 64 位时,它没有抛出任何异常,一切似乎都成功了。但是您找不到它创建的 .txt
文件。所以,它失败了,没有执行你想做的事情。
下面是我的DLL代码
#include "stdafx.h"
#include<Windows.h>
#include<stdio.h>
#include<stdlib.h>
BOOL create();
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
create();
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
BOOL create()
{
wchar_t FileName[] = L"D:\x64injecttest.txt";
HANDLE hFile = ::CreateFile(FileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, NULL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("createfile fails,the error code is:%u\n", GetLastError());
system("PAUSE");
return 0;
}
char str[] = "if you see this file,then you have success\n";
WriteFile(hFile, str, strlen(str) + 1, NULL, NULL);
CloseHandle(hFile);
return TRUE;
}
下面是我的程序代码
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include<TlHelp32.h>
LPTHREAD_START_ROUTINE lpThreadProc; //pointes to the address of LoadLibraryW API
typedef DWORD(WINAPI *pFunction)(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, BOOL CreateSuspended, DWORD dwStackSize, DWORD dw1, DWORD dw2, LPVOID pUnknown); //I inject DLL to other process with the NtCreateThreadEx API , and this function pointer would point to the address of this API
DWORD SearchForTarget(wchar_t target[])
{
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == INVALID_HANDLE_VALUE)
{
printf("fails when createtoolhelp32snapshot,the error code is:%u\n", GetLastError());
system("PAUSE");
exit(-1);
}
BOOL b = ::Process32First(hSnap, &pe32);
while (b)
{
printf("the process name is:%ws\n", pe32.szExeFile);
printf("the process id is:%u\n", pe32.th32ProcessID);
if (wcscmp(pe32.szExeFile, target) == 0)
return pe32.th32ProcessID;
b = Process32Next(hSnap, &pe32);
}
return -1;
}
BOOL InjectDLL(DWORD pid)
{
wchar_t DLLPath[] = L"C:\Users\Dell-pc\Desktop\x64InjectTest\Debug\DLL.dll";
DWORD length = wcslen(DLLPath);
DWORD trueLength = length * 2 + 2;
HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (hProcess == INVALID_HANDLE_VALUE)
{
printf("openprocess fails,the error code is:%u\n", GetLastError());
system("PAUSE");
exit(-1);
}
LPVOID pBaseAddress = ::VirtualAllocEx(hProcess, NULL, trueLength, MEM_COMMIT, PAGE_READWRITE);
if (pBaseAddress == NULL)
{
printf("virtualallocex fails,the error code is:%u\n", GetLastError());
system("PAUSE");
exit(-1);
}
BOOL b = WriteProcessMemory(hProcess, pBaseAddress, DLLPath, trueLength, NULL);
if (b == 0)
{
printf("writeprocessmemory fail,the error code is:%u\n", GetLastError());
system("PAUSE");
exit(-1);
}
HMODULE hModule = ::LoadLibrary(L"kernel32.dll");
lpThreadProc = (LPTHREAD_START_ROUTINE)::GetProcAddress(hModule, "LoadLibraryW");
HMODULE hNtdll = ::LoadLibrary(L"ntdll.dll");
pFunction pFunc = (pFunction)GetProcAddress(hNtdll, "NtCreateThreadEx");
printf("it is ready to create thread\n");
HANDLE hRemoteThread;
pFunc(&hRemoteThread, 0x1FFFFF, NULL, hProcess, lpThreadProc, pBaseAddress, FALSE, NULL, NULL, NULL, NULL);
if (hRemoteThread == NULL)
{
printf("nrcreateprocessex fails,the error code is:%u\n", GetLastError());
system("PAUSE");
exit(-1);
}
WaitForSingleObject(hRemoteThread, INFINITE);
return TRUE;
}
int main()
{
wchar_t target[] = L"notepad.exe"; //inject my DLL to notepad.exe
DWORD pid = SearchForTarget(target);
if (pid == -1)
{
printf("not find the target \n");
system("PAUSE");
return -1;
}
InjectDLL(pid);
system("PAUSE");
return 0;
}
我将我的代码(我的程序和我的 DLL)编译为 32 位,并且 运行 它在我的 Windows 8.1 64 位 OS 上,它成功了。但是当我将它(我的程序和我的 DLL)编译为 64 位时,它没有抛出任何异常,而且它似乎成功了,只是它没有创建文件并向其中写入一些单词(这是应该做的当 DLL 附加到进程时)。那么,有人知道问题出在哪里吗?还有一件事,我使用 Visual Studio 2013 .
我猜想在您的示例中导致 32/64 位问题的行如下。
lpThreadProc = (LPTHREAD_START_ROUTINE)::GetProcAddress(hModule,
"LoadLibraryW");
这会为您提供当前进程中 LoadLibraryW 的地址,而不是目标进程中的地址。鉴于目标进程是 64 位,地址是 99.99999% 会有所不同。
即使在 32 位进程中,您通常也不应假设 DLL 将始终加载到相同的地址空间。
要解决您的问题,您可能必须枚举目标进程中的模块并从那里找到您的入口点。有 API 可以帮助解决这个问题。 GetRemoteProcAddress
的 google 也会为您指明正确的方向。
除此之外,您的加载程序还有许多其他问题。就我个人而言,我建议您使用其他人已经编写的。过去有很多很好的加载器,它们涵盖了许多注意事项,并且也有多种注入机制。
谢谢大家,问题已经解决了。关于函数NtCreateThreadEx
,第8、9、10个参数(stacksize
参数,dw1
参数,dw2
参数)的类型应该是SIZE_T
,而不是 DWORD
。如果是DWORD
,编译成32位的代码没问题,编译成64位的就不行了。
所以,这行代码应该写成下面的样子
typedef NTSTATUS (WINAPI *pFunction)(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, BOOL CreateSuspended, SIZE_T dwStackSize, SIZE_T dw1, DWORD SIZE_T, LPVOID pUnknown);
我的 OS 是 Windows 8.1 64 位。我的程序是向目标进程注入一个DLL
文件,当这个DLL文件附加到一个进程时,它会在D:
上创建一个.txt
文件,并在其中写入一些单词,然后保存。它只是一个 test.But 当我将我的程序编译为 32 位程序并且我的 DLL 代码被编译为 32 位时,它成功了,它可以创建文件并保存内容。但是当我将我的 DLL 代码和我的程序编译为 64 位时,它没有抛出任何异常,一切似乎都成功了。但是您找不到它创建的 .txt
文件。所以,它失败了,没有执行你想做的事情。
下面是我的DLL代码
#include "stdafx.h"
#include<Windows.h>
#include<stdio.h>
#include<stdlib.h>
BOOL create();
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
create();
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
BOOL create()
{
wchar_t FileName[] = L"D:\x64injecttest.txt";
HANDLE hFile = ::CreateFile(FileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, NULL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("createfile fails,the error code is:%u\n", GetLastError());
system("PAUSE");
return 0;
}
char str[] = "if you see this file,then you have success\n";
WriteFile(hFile, str, strlen(str) + 1, NULL, NULL);
CloseHandle(hFile);
return TRUE;
}
下面是我的程序代码
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include<TlHelp32.h>
LPTHREAD_START_ROUTINE lpThreadProc; //pointes to the address of LoadLibraryW API
typedef DWORD(WINAPI *pFunction)(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, BOOL CreateSuspended, DWORD dwStackSize, DWORD dw1, DWORD dw2, LPVOID pUnknown); //I inject DLL to other process with the NtCreateThreadEx API , and this function pointer would point to the address of this API
DWORD SearchForTarget(wchar_t target[])
{
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == INVALID_HANDLE_VALUE)
{
printf("fails when createtoolhelp32snapshot,the error code is:%u\n", GetLastError());
system("PAUSE");
exit(-1);
}
BOOL b = ::Process32First(hSnap, &pe32);
while (b)
{
printf("the process name is:%ws\n", pe32.szExeFile);
printf("the process id is:%u\n", pe32.th32ProcessID);
if (wcscmp(pe32.szExeFile, target) == 0)
return pe32.th32ProcessID;
b = Process32Next(hSnap, &pe32);
}
return -1;
}
BOOL InjectDLL(DWORD pid)
{
wchar_t DLLPath[] = L"C:\Users\Dell-pc\Desktop\x64InjectTest\Debug\DLL.dll";
DWORD length = wcslen(DLLPath);
DWORD trueLength = length * 2 + 2;
HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (hProcess == INVALID_HANDLE_VALUE)
{
printf("openprocess fails,the error code is:%u\n", GetLastError());
system("PAUSE");
exit(-1);
}
LPVOID pBaseAddress = ::VirtualAllocEx(hProcess, NULL, trueLength, MEM_COMMIT, PAGE_READWRITE);
if (pBaseAddress == NULL)
{
printf("virtualallocex fails,the error code is:%u\n", GetLastError());
system("PAUSE");
exit(-1);
}
BOOL b = WriteProcessMemory(hProcess, pBaseAddress, DLLPath, trueLength, NULL);
if (b == 0)
{
printf("writeprocessmemory fail,the error code is:%u\n", GetLastError());
system("PAUSE");
exit(-1);
}
HMODULE hModule = ::LoadLibrary(L"kernel32.dll");
lpThreadProc = (LPTHREAD_START_ROUTINE)::GetProcAddress(hModule, "LoadLibraryW");
HMODULE hNtdll = ::LoadLibrary(L"ntdll.dll");
pFunction pFunc = (pFunction)GetProcAddress(hNtdll, "NtCreateThreadEx");
printf("it is ready to create thread\n");
HANDLE hRemoteThread;
pFunc(&hRemoteThread, 0x1FFFFF, NULL, hProcess, lpThreadProc, pBaseAddress, FALSE, NULL, NULL, NULL, NULL);
if (hRemoteThread == NULL)
{
printf("nrcreateprocessex fails,the error code is:%u\n", GetLastError());
system("PAUSE");
exit(-1);
}
WaitForSingleObject(hRemoteThread, INFINITE);
return TRUE;
}
int main()
{
wchar_t target[] = L"notepad.exe"; //inject my DLL to notepad.exe
DWORD pid = SearchForTarget(target);
if (pid == -1)
{
printf("not find the target \n");
system("PAUSE");
return -1;
}
InjectDLL(pid);
system("PAUSE");
return 0;
}
我将我的代码(我的程序和我的 DLL)编译为 32 位,并且 运行 它在我的 Windows 8.1 64 位 OS 上,它成功了。但是当我将它(我的程序和我的 DLL)编译为 64 位时,它没有抛出任何异常,而且它似乎成功了,只是它没有创建文件并向其中写入一些单词(这是应该做的当 DLL 附加到进程时)。那么,有人知道问题出在哪里吗?还有一件事,我使用 Visual Studio 2013 .
我猜想在您的示例中导致 32/64 位问题的行如下。
lpThreadProc = (LPTHREAD_START_ROUTINE)::GetProcAddress(hModule,
"LoadLibraryW");
这会为您提供当前进程中 LoadLibraryW 的地址,而不是目标进程中的地址。鉴于目标进程是 64 位,地址是 99.99999% 会有所不同。
即使在 32 位进程中,您通常也不应假设 DLL 将始终加载到相同的地址空间。
要解决您的问题,您可能必须枚举目标进程中的模块并从那里找到您的入口点。有 API 可以帮助解决这个问题。 GetRemoteProcAddress
的 google 也会为您指明正确的方向。
除此之外,您的加载程序还有许多其他问题。就我个人而言,我建议您使用其他人已经编写的。过去有很多很好的加载器,它们涵盖了许多注意事项,并且也有多种注入机制。
谢谢大家,问题已经解决了。关于函数NtCreateThreadEx
,第8、9、10个参数(stacksize
参数,dw1
参数,dw2
参数)的类型应该是SIZE_T
,而不是 DWORD
。如果是DWORD
,编译成32位的代码没问题,编译成64位的就不行了。
所以,这行代码应该写成下面的样子
typedef NTSTATUS (WINAPI *pFunction)(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, BOOL CreateSuspended, SIZE_T dwStackSize, SIZE_T dw1, DWORD SIZE_T, LPVOID pUnknown);