DllMain не вызывается из введенной dll
Я пытаюсь внедрить DLL в существующий процесс, используя подход LoadLibrary и CreateRemoteThread. Весь мой код работает прекрасно, за исключением того факта, что DllMain по какой-то причине не вызывается.
Я сломал свой мозг и провел столько интернет-исследований, сколько смог, но ни одно из предложений не помогло.
Когда я статически загружаю DLL в пример проекта, он прекрасно работает.
Когда я динамически загружаю dll в пример проекта, используя LoadLibrary, он прекрасно работает.
Единственный раз, когда DllMain не вызывается, это когда я пытаюсь внедрить его в процесс, используя подходы LoadLibrary и CreateRemoteThread. Я в своем уме!
Я проверил, что dll загружен в процесс notepad.exe из инжектора, потому что файл SimpleDLL.dll заблокирован и не может быть удален или перезаписан, пока я не закрою notepad.exe.
Кстати, мой идеал - Microsoft Visual Studio 2010 Ultimate.
// SimpleDLL.h
#pragma once
#include "Stdafx.h"
#ifdef COMPILE_MYLIBRARY
#define MYLIBRARY_EXPORT __declspec(dllexport)
#else
#define MYLIBRARY_EXPORT __declspec(dllimport)
#endif
,
//SimpleDLL.cpp
#include "Stdafx.h"
#include "SimpleDll.h"
extern "C" int __stdcall DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) {
printf("SimpleDll: DllMain called.\n");
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
printf("SimpleDll: DLL_PROCESS_ATTACH.\n");
break;
case DLL_PROCESS_DETACH:
printf("SimpleDll: DLL_PROCESS_DETACH.\n");
break;
case DLL_THREAD_ATTACH:
printf("SimpleDll: DLL_THREAD_ATTACH.\n");
break;
case DLL_THREAD_DETACH:
printf("SimpleDll: DLL_THREAD_DETACH.\n");
break;
}
return TRUE;
};
SimpleDLLCaller.cpp - работает правильно и печатает сообщения от DllMain. Это проект, который я построил, чтобы убедиться, что DLL построен правильно. Из вывода, который я вижу, похоже, что он работает правильно при загрузке таким образом.
// SimpleDLLCaller.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
LoadLibraryA( "C:\\SimpleDll.dll" );
_getch();
return 0;
}
Вывод из SimpleDllCaller:
SimpleDll: DllMain called.
SimpleDll: DLL_PROCESS_ATTACH.
Simple Injector.cpp - это отдельный проект от SimpleDLLCaller и успешно компилируется / запускается без предупреждений (если notepad.exe уже запущен), но сообщения от DllMain не отображаются.
// Simple Injector.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <tlhelp32.h>
#include <shlwapi.h>
#include <conio.h>
#include <stdio.h>
#define WIN32_LEAN_AND_MEAN
#define CREATE_THREAD_ACCESS (PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ)
BOOL Inject(DWORD pID, const char * dll_name )
{
HANDLE targetProcess, createdThread;
//HMODULE hLib;
char buf[50] = {0};
LPVOID myRemoteString, LoadLibAddy;
if( ! pID )
{
return FALSE;
}
targetProcess = OpenProcess( CREATE_THREAD_ACCESS, FALSE, pID );
if( ! targetProcess )
{
sprintf_s(buf, "OpenProcess() failed: %d", GetLastError());
MessageBox(NULL, buf, "Loader", MB_OK);
printf(buf);
return false;
}
LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if( ! LoadLibAddy )
{
printf( "ERROR: Problems with GetProcAddress. Error code: %d\n", GetLastError() );
return false;
}
// Allocate space in the process for the dll
myRemoteString = (LPVOID)VirtualAllocEx( targetProcess, NULL, strlen(dll_name), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if( ! myRemoteString )
{
printf( "ERROR: Problems with VirtualAllocEx. Error code: %d\n", GetLastError() );
return false;
}
// Write the string name of the dll in the memory allocated
if( ! WriteProcessMemory( targetProcess, (LPVOID)myRemoteString, dll_name, strlen(dll_name), NULL) )
{
printf( "ERROR: Problems with WriteProcessMemory. Error code: %d\n", GetLastError() );
return false;
}
// Load the dll
createdThread = CreateRemoteThread( targetProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)myRemoteString, NULL, NULL);
if( ! createdThread )
{
printf( "ERROR: Problems with CreateRemoteThread. Error code: %d\n", GetLastError() );
return false;
}
WaitForSingleObject(createdThread, INFINITE);
// Free the memory that is not being using anymore.
if( myRemoteString != NULL ) VirtualFreeEx( targetProcess, myRemoteString, 0, MEM_RELEASE );
if( createdThread != NULL ) CloseHandle( createdThread );
if( targetProcess != NULL ) CloseHandle( targetProcess );
//VirtualFreeEx(hProcess , (LPVOID)Memory , 0, MEM_RELEASE);
return true;
}
DWORD GetTargetThreadIDFromProcName(const char *ProcName)
{
PROCESSENTRY32 pe;
HANDLE thSnapShot;
BOOL retval, ProcFound = false;
thSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(thSnapShot == INVALID_HANDLE_VALUE)
{
//MessageBox(NULL, "Error: Unable <strong class="highlight">to</strong> create toolhelp snapshot!", "2MLoader", MB_OK);
printf("Error: Unable to create toolhelp snapshot!");
return false;
}
pe.dwSize = sizeof(PROCESSENTRY32);
retval = Process32First(thSnapShot, &pe);
while(retval)
{
if( !strcmp(pe.szExeFile, ProcName) )
{
return pe.th32ProcessID;
}
retval = Process32Next(thSnapShot, &pe);
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
// Retrieve process ID
DWORD pID = GetTargetThreadIDFromProcName("notepad.exe");
if( !pID )
{
printf( "ERROR: Could not find any process for notepad.exe.\n");
_getch();
return 0;
}
// Get the dll's full path name
char buf[MAX_PATH] = {0};
// GetFullPathName("..\\SimpleDLL.dll", MAX_PATH, buf, NULL);
sprintf_s(buf, "C:\\SimpleDLL.dll");
printf( "Dll path = %s\n", buf );
// Inject our main dll
if(!Inject(pID, buf))
{
printf("Dll not loaded.");
}
else
{
printf("Dll loaded.");
}
_getch();
return 0;
}
Выход из простого инжектора:
Dll path = C:\SimpleDLL.dll
Dll loaded.
Пожалуйста, скажите мне, что я делаю не так здесь. Любые отзывы приветствуются.
1 ответ
Ваша DLL может быть правильно загружена. Не ожидайте, что ваш printf сделает что-нибудь. Если вы хотите получить подтверждение, напишите ваше сообщение в текстовом файле, или используйте MessageBox, или используйте Process Explorer.