Часть первая. Dll Injection
Предположим что мы хотим добавить какую то новую возможность в клиент от какой либо онлайн игры, но не можем поскольку у нас нету исходного кода, и мы слишком ленивые чтобы добавить её при помощи изменения уже готово исполняемого файла. Казалось бы - у нас нету никакой возможности этого сделать...
Порывшись в MSDN мы можем обнаружить что у нас есть возможность редактировать исполняемый файл прямо в памяти - используя WriteProcessMemory/ReadProcessMemory. Это уже хоть что-то, но это не очень удобно в случае если нам надо вставить туда достаточно большой кусок кода и причём желательно на ЯВУ.
К счастью програмисты из мастдая всё уже придумали за нас - дали нам возможность создавать треды в удалённом процессе при помощи CreateRemoteThread, а также дав нам функцию LoadLibrary(и FreeLibrary), принимающую всего 1 параметр(ровно столько должна принимать функция треда).
Итак - наш план действий:
1. Открыть или создать нужный процесс.
2. Выделить в нём кусочек памяти который будет содержать имя нашей Dll. *
3. Записать в этот кусочек памяти имя.
4. Создать удалённый тред в процессе с точкой старта равной LoadLibrary, и в качестве параметра передать ей аддресс имени нашей библиотеки.
5. Дождаться завершения нашего треда.
6. Создать удалённый тред в процессе с точкой старта равной FreeLibrary, и в качестве параметра передать ей аддресс имени нашей библиотеки.
* - Мы не можем оставить его в своей памяти, поскольку тогда чужой процесс не сможет его прочитать.
Код инъектора:
Код:
#include <winsock2.h>
#pragma comment ( lib , "kernel32.lib" )
#pragma comment ( lib , "user32.lib" )
#pragma comment ( lib , "advapi32.lib" )
#pragma comment ( lib , "ws2_32.lib" )
//Мой "стандартный" заголовок =)
/*Функция создания процесса
* Cmd - строка содержащая название приложения которое надо запустить и параметры коммандной строки (Например: l2.exe -log)
* Suspended - Если тру, тред процесса будет при создании процесса остановлен.
* pi - Информация о процессе */
BOOL ProcessCreate(LPCSTR Cmd, BOOL Suspended, PROCESS_INFORMATION& pi)
{
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
if(!CreateProcessA(NULL, (LPSTR)Cmd, NULL, NULL, FALSE, (Suspended)?CREATE_SUSPENDED:0, NULL, NULL, &si, &pi))return TRUE;
return TRUE;
}
/*Функция для выделения памяти в чужом процессе
* Process - хэндл процесса
* Size - сколько требуется выделить памяти */
LPVOID ProcessMemoryAlloc(HANDLE Process, UINT Size)
{
return VirtualAllocEx(Process,NULL,Size,MEM_COMMIT,PAGE_READWRITE);
}
/*Функция для освобождения памяти
* Process - хэндл процесса
* Addr - адресс */
VOID ProcessMemoryFree(HANDLE Process, LPVOID Addr)
{
VirtualFreeEx(Process, Addr, 0, MEM_DECOMMIT);
}
/*Функция для записи в память процесса
* Process - хэндл процесса
* Addr - адресс в памяте процесса
* Data - указатель на данные для записи
* Length - количество байт для записи */
BOOL ProcessWrite(HANDLE Process, LPVOID Addr, LPCVOID Data, UINT Length)
{
DWORD written;
if(!WriteProcessMemory(Process, Addr, Data, Length, &written))return FALSE;
return written == Length;
}
/*Функция создающая удалённый трэд (ака CreateRemoteThread)
* Process - хэндл процесса
* ThreadProc - адресс точки входа треда в памяти процесса
* Param - параметр который будет передан трэду
* Result - место куда будет помещён результат выполнения трэда */
BOOL ProcessExecute(HANDLE Process, LPTHREAD_START_ROUTINE ThreadProc, LPVOID Param, LPDWORD Result)
{
DWORD ThreadId;
HANDLE hThread = CreateRemoteThread(Process,NULL,0,ThreadProc, Param, 0, &ThreadId);
WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, Result);
return TRUE;
}
/* Удалённая загрузка длльки
* Process - хэндл процесса
* DllPath - путь до длл
* Length - длинна пути до длл, если равна 0 - функция сама воспользуется lstrlen и определит длинну */
HMODULE ProcessLoadLibrary(HANDLE Process,LPCSTR DllPath,UINT Length)
{
if(!Length)Length = lstrlen(DllPath) + 1;
LPTHREAD_START_ROUTINE LoadLibraryAddr = (LPTHREAD_START_ROUTINE)GetProcAddress(LoadLibrary("kernel32.dll"),"LoadLibraryA");
LPVOID MemAddr = ProcessMemoryAlloc(Process,Length);
if(!MemAddr)return NULL;
if(!ProcessWrite(Process, MemAddr, (LPCVOID)DllPath, Length))return NULL;
DWORD Result;
if(!ProcessExecute(Process, LoadLibraryAddr, MemAddr, &Result))return NULL;
ProcessMemoryFree(Process, MemAddr);
return (HMODULE)Result;
}
BOOL ProcessFreeLibrary(HANDLE Process,LPCSTR DllPath,UINT Length)
{
if(!Length)Length = lstrlen(DllPath) + 1;
LPTHREAD_START_ROUTINE FreeLibraryAddr = (LPTHREAD_START_ROUTINE)GetProcAddress(LoadLibrary("kernel32.dll"),"FreeLibraryA");
LPVOID MemAddr = ProcessMemoryAlloc(Process,Length);
if(!MemAddr)return NULL;
if(!ProcessWrite(Process, MemAddr, (LPCVOID)DllPath, Length))return FALSE;
DWORD Result;
if(!ProcessExecute(Process, FreeLibraryAddr, MemAddr, &Result))return FALSE;
ProcessMemoryFree(Process, MemAddr);
return TRUE;
}
char Program[] = "notepad.exe";
char Library[] = "D:\\fcc\\bin\\lib0.dll";
/*В данном случае приходится использовать абсолютный путь - поскольку notepad "не видит" lib.dll по относительному пути */
void Injector()
{
PROCESS_INFORMATION pi;
if(!ProcessCreate(Program, TRUE, pi))
{
MessageBox(0,"Cannot create process!","Error!",0);
return;
}
if(!ProcessLoadLibrary(pi.hProcess,Library,0))
{
MessageBox(0,"Cannot load library!","Error!",0);
return;
}
ProcessFreeLibrary(pi.hProcess,Library,0);
ResumeThread(pi.hThread);
}
И код либы:
Код:
#include <winsock2.h>
#pragma comment ( lib , "kernel32.lib" )
#pragma comment ( lib , "user32.lib" )
#pragma comment ( lib , "advapi32.lib" )
#pragma comment ( lib , "ws2_32.lib" )
HANDLE hThread;
DWORD ThreadId;
DWORD WINAPI ThreadProc(LPVOID p)
{
MessageBox(0, "Injected =)", 0, 0);
return TRUE;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if(fdwReason == DLL_PROCESS_ATTACH)
{
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc, NULL, 0, &ThreadId);
DisableThreadLibraryCalls(hinstDLL);
}
return TRUE;
}
Зачем я создавал новый тред в dll? - По не понятным мне причинам из созданного нами треда dll нельзя использовать никакие функции user32.dll.
Продолжение следует(молюсь богу чтобы меня по айпи не забанили за немного кривой запрос(проверял сайт на мускуль инйекции =))... Хотя прокси и рулят но акк терять не хочу), не забудьте нажать на [СПАСИБО] если я вам помог =)
Linos добавил 16.03.2007 в 15:58
Ps. Короче всё - вроде пример работает =)
Следующие в серии статьи:
Хуки и с чем их едят?
Нижний уровень С++ - устройство классов на пальцах.
И ещё - компилирую я всё в консоле - из ВС2005 использую только компилятор
cl /c injector.cpp
link /entry:Injector /subsystem:windows /align:32 injector.obj
cl /c lib.cpp
link /dll /entryllMain /subsystem:windows lib.obj
rem смайл в строке выше надо заменить на ": D" без кавычек и пробела.