B
Hallo,
hatte was ähnliches schonmal programmiert und habe den code jetzt umgeschrieben, der sollte so funktionieren (zumindest tat er das bei icq und firefox):
Deine exe-datei muss folgende Funktion aufrufen:
bool InjectDllInProcess(DWORD dwProcessId)
{
HANDLE hProcess, hThread;
char szDllPathName[MAX_PATH];
DWORD dwDllStringSize;
void *pRemoteString;
PTHREAD_START_ROUTINE pfnThreadRoutine;
pfnThreadRoutine = (PTHREAD_START_ROUTINE)
GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA");
// could the address of LoadLibraryA function be found?
if(!pfnThreadRoutine)
return false;
// open remote process with threadcreation- and writing-flags
hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION
| PROCESS_VM_WRITE | PROCESS_VM_READ, false, dwProcessId);
if(!hProcess)
return false;
// get the whole path+name of dll file, then the size of this string:
wsprintfA(szDllPathName, "%s\\%s", g_szMyPath, g_szInjDll);
dwDllStringSize = lstrlenA(szDllPathName) + 1; // +1 = zero
// reserve memory in the remote thread for the name of phtm-dll:
pRemoteString = VirtualAllocEx(hProcess, 0, dwDllStringSize,
MEM_COMMIT, PAGE_READWRITE);
if(!pRemoteString)
{
// cleanup
CloseHandle(hProcess);
return false;
}
// copy dll string into the remote process:
if(!WriteProcessMemory(hProcess, pRemoteString, szDllPathName,
dwDllStringSize, 0))
{
// cleanup
VirtualFreeEx(hProcess, pRemoteString, dwDllStringSize, MEM_RELEASE);
CloseHandle(hProcess);
return false;
}
hThread = CreateRemoteThread(hProcess, 0, 0,
pfnThreadRoutine, pRemoteString, 0, 0);
if(!hThread)
{
// cleanup
VirtualFreeEx(hProcess, pRemoteString, dwDllStringSize, MEM_RELEASE);
CloseHandle(hProcess);
return false;
}
// wait until remote thread ends:
WaitForSingleObject(hThread, INFINITE);
// cleanup:
VirtualFreeEx(hProcess, pRemoteString, dwDllStringSize, MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
return true;
}
das geht aber nur unter WinNT/2k/xp!
windows.h zu includieren müsste reichen. Die ProcessId ist das einzige was du übergeben musst. die kriegst du z.b. indem du selbst den prozess erstellst oder wenn du n window handle hast mit GetWindowThreadProcessId oder mit den toolhelp-funktionen (CreateToolhelp32Snapshot) etc.
du brauchst für die funktion hier noch 2 globale variablen - g_szMyPath und g_szInjDll - die werden zu szDllPathName zusammengefügt, was der komplette Pfad+Dateiname (z.b. C:\dll.dll) sein muss. kannst ja bei dir anpassen.
Der Code deiner dll-datei:
#define APIH_LOADLIB 0x01
#define APIH_CONNECT 0x02
#pragma comment(lib, "user32")
#pragma comment(lib, "imagehlp")
#include <winsock2.h>
#include <windows.h>
#include <imagehlp.h>
#include <tlhelp32.h>
HANDLE hMod;
BOOL ReplaceFuncsInThisProcess(DWORD);
BOOL ReplaceFunctionIn1Mod(char*, void*, void*, HMODULE);
char szKernel32Dll[] = "kernel32.dll";
char szWinsockDll[] = "wsock32.dll";
char szWinsock2Dll[] = "ws2_32.dll";
// LoadLibrary:
// unicode/ANSI!
HMODULE WINAPI MyLoadLibraryW(LPCWSTR);
HMODULE WINAPI MyLoadLibraryA(LPCSTR);
const char szLoadLibraryW[] = "LoadLibraryW";
const char szLoadLibraryA[] = "LoadLibraryA";
void *pLoadLibraryASys, *pLoadLibraryWSys;
// connect from ws2_32.dll and wsock2.dll:
int FAR PASCAL MyConnect(SOCKET, const struct sockaddr FAR*, int);
const char szConnect[] = "connect";
void *pConnectSys, *pConnect2Sys;
// wsaconnect from ws2_32.dll:
int FAR PASCAL MyWSAConnect(SOCKET, const struct sockaddr FAR*,
int, LPWSABUF, LPWSABUF, LPQOS, LPQOS);
const char szWSAConnect[] = "WSAConnect";
void *pWSAConnectSys;
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
hMod = hModule;
// get system module references to our functions:
pLoadLibraryWSys = GetProcAddress(GetModuleHandle(szKernel32Dll), szLoadLibraryW);
pLoadLibraryASys = GetProcAddress(GetModuleHandle(szKernel32Dll), szLoadLibraryA);
pConnectSys = GetProcAddress(GetModuleHandle(szWinsockDll), szConnect);
pConnect2Sys = GetProcAddress(GetModuleHandle(szWinsock2Dll), szConnect);
pWSAConnectSys = GetProcAddress(GetModuleHandle(szWinsock2Dll), szWSAConnect);
ReplaceFuncsInThisProcess(APIH_LOADLIB | APIH_CONNECT);
break;
}
return true;
}
/*
Diese Funktion ruft für jedes Modul, das sich in diesem Prozess befindet,
die Funktion ReplaceFunctionIn1Mod auf. Da jedes Modul (dll-datei)
in diesem Prozess theoretisch die Funktion aufrufen könnte,
die wir einhaken wollen.
*/
BOOL ReplaceFuncsInThisProcess(DWORD dwFlags)
{
HANDLE hSnapshot;
MODULEENTRY32 me32;
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
if(hSnapshot == INVALID_HANDLE_VALUE)
{
// MessageBox(0, "Error: ToolhelpSnapshot", "", 0);
return false;
}
me32.dwSize = sizeof(MODULEENTRY32);
if(Module32First(hSnapshot, &me32))
{
do
{
// dont hook our own module and kernel32:
if(hMod != me32.hModule
&& strcmpi(me32.szModule, szKernel32Dll)
&& strcmpi(me32.szModule, szWinsockDll)
&& strcmpi(me32.szModule, szWinsock2Dll))
{
if(dwFlags & APIH_LOADLIB)
{
ReplaceFunctionIn1Mod(szKernel32Dll, pLoadLibraryASys,
MyLoadLibraryA, me32.hModule);
ReplaceFunctionIn1Mod(szKernel32Dll, pLoadLibraryWSys,
MyLoadLibraryW, me32.hModule);
}
if(dwFlags & APIH_CONNECT)
{
ReplaceFunctionIn1Mod(szWinsockDll, pConnectSys,
MyConnect, me32.hModule);
ReplaceFunctionIn1Mod(szWinsock2Dll, pConnect2Sys,
MyConnect, me32.hModule);
ReplaceFunctionIn1Mod(szWinsock2Dll, pWSAConnectSys,
MyWSAConnect, me32.hModule);
}
}
} while(Module32Next(hSnapshot, &me32));
}
else
{
// MessageBox(0, "Error: module32first", "", 0);
return false;
}
CloseHandle(hSnapshot);
return true;
}
/*
MS Windows Programmierung für Experten - Richter, S. 697, abgewandelt:
*/
BOOL ReplaceFunctionIn1Mod(char *pszDllName, void *pfnOld,
void *pfnNew, HMODULE hModCaller)
{
unsigned long ulSize;
PIMAGE_IMPORT_DESCRIPTOR pImpDesc;
pImpDesc = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(hModCaller, true,
IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);
if(!pImpDesc)
return false;
while(pImpDesc->Name)
{
char *pszMod = (char*)((BYTE*)hModCaller + pImpDesc->Name);
if(lstrcmpiA(pszMod, pszDllName) == 0)
break; // importaddress from pszDllName found
pImpDesc++;
}
if(!pImpDesc->Name)
return false;
PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)
((BYTE*)hModCaller + pImpDesc->FirstThunk);
while(pThunk->u1.Function)
{
PROC *ppfn = (PROC*)&pThunk->u1.Function;
if(*ppfn == pfnOld)
{
HANDLE hProcess;
hProcess = GetCurrentProcess();
// overwrite the function:
if(!WriteProcessMemory(hProcess, ppfn, &pfnNew, sizeof(pfnNew), 0)
&& GetLastError() == 998)
{
// set read-only page writeable:
DWORD dwOldProtect;
if(!VirtualProtectEx(hProcess, ppfn, sizeof(pfnNew),
PAGE_READWRITE, &dwOldProtect))
{
return false;
}
// write again:
if(!WriteProcessMemory(hProcess, ppfn, &pfnNew, sizeof(pfnNew), 0))
{
return false;
}
// write process was successful. now give old protection back:
VirtualProtectEx(hProcess, ppfn, sizeof(pfnNew), dwOldProtect, &dwOldProtect);
}
return true;
}
pThunk++;
}
return true;
}
HMODULE WINAPI MyLoadLibraryW(LPCWSTR lpLibFileName)
{
HMODULE hThisMod = LoadLibraryW(lpLibFileName);
ReplaceFunctionIn1Mod(szWinsockDll, pConnectSys,
MyConnect, hThisMod);
ReplaceFunctionIn1Mod(szWinsock2Dll, pConnect2Sys,
MyConnect, hThisMod);
ReplaceFunctionIn1Mod(szWinsock2Dll, pWSAConnectSys,
MyWSAConnect, hThisMod);
return hThisMod;
}
HMODULE WINAPI MyLoadLibraryA(LPCSTR lpLibFileName)
{
HMODULE hThisMod = LoadLibraryA(lpLibFileName);
ReplaceFunctionIn1Mod(szWinsockDll, pConnectSys,
MyConnect, hThisMod);
ReplaceFunctionIn1Mod(szWinsock2Dll, pConnect2Sys,
MyConnect, hThisMod);
ReplaceFunctionIn1Mod(szWinsock2Dll, pWSAConnectSys,
MyWSAConnect, hThisMod);
return hThisMod;
}
int FAR PASCAL MyConnect(SOCKET s, const struct sockaddr FAR * name, int namelen)
{
// if you want to connect:
// return connect(s, name, namelen);
// otherwise:
return 0;
}
int FAR PASCAL MyWSAConnect(SOCKET s, const struct sockaddr FAR * name,
int namelen, LPWSABUF lpCallerData, LPWSABUF lpCalleeData, LPQOS lpSQOS,
LPQOS lpGQOS)
{
return 0;
}
kannst eigentlich so kompilieren!
wird die dll in nen prozess injiziert überschreibt sie connect (aus ws2_32.dll und wsock2.dll) und WSAConnect (ws2_32.dll) damit zur laufzeit geladene module nicht verbinden können wird auch LoadLibraryA und LoadLibraryW überwacht.
man brauch hier auch win nt, 2k, xp
mfg