PDA

Просмотр полной версии : Пишем свой инжектор с выгрузкой [LoadLibraryA]


CleanLegend
09.05.2019, 01:27
Привет, сегодня напишем простой инжектор с выгрузкой, с использованием функций LoadLibraryA и FreeLibrary

Алгоритм инжекта:

- получаем хэндл процесса в который будем инжектить

- получаем путь до нашей dll

- выделяем память для нашего пути

- записываем его

- получаем адрес LoadLibraryA и вызываем его через CreateRemoteThread​- ожидаем завершения выполнения DllMain DLL_PROCESS_ATTACH

получаем id процесса:

C++:






DWORD
GetProcId
(
const
char
*
procname
)
{
PROCESSENTRY32 pe
;
HANDLE hSnap
;
pe
.
dwSize
=
sizeof
(
PROCESSENTRY32
)
;
hSnap
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPPROCESS
,
NULL
)
;
if
(
Process32First
(
hSnap
,
&
pe
)
)
{
do
{
if
(
strcmp
(
pe
.
szExeFile
,
procname
)
==
0
)
break
;
}
while
(
Process32Next
(
hSnap
,
&
pe
)
)
;
}
return
pe
.
th32ProcessID
;
}




C++:






// получаем хэндл процесса
HANDLE hProcess
=
OpenProcess
(
PROCESS_ALL_ACCESS
,
FALSE
,
GetProcId
(
"gta_sa.exe"
)
)
;
// Указываем путь до нашей dll
const
char
*
DllPath
=
"C:\\test.dll"
;
// получаем размер строки нашего пути
size_t SizePatch
=
strlen
(
DllPath
)
+
1
;
// выделяем память в gta_sa с размером нашей строки
LPVOID pDllPath
=
VirtualAllocEx
(
hProcess
,
NULL
,
SizePatch
,
MEM_COMMIT
,
PAGE_READWRITE
)
;
// записываем наш путь в выделенную память
WriteProcessMemory
(
hProcess
,
pDllPath
,
(
LPVOID
)
DllPath
,
SizePatch
,
NULL
)
;
HMODULE kernel
=
GetModuleHandleA
(
"Kernel32.dll"
)
;
// Получаем адрес kernel32
DWORD Adr
=
(
DWORD
)
GetProcAddress
(
kernel
,
"LoadLibraryA"
)
;
// получаем адрес функции LoadLibraryA
// Вызываем LoadLibraryA в gta_sa.exe с аргументом "C:\\test.dll" и возвращаем адрес нашего потока
HANDLE hThread
=
CreateRemoteThread
(
hProcess
,
0
,
0
,
(
LPTHREAD_START_ROUTINE
)
Adr
,
pDllPath
,
0
,
0
)
;
// Ожидаем завершение нашего потока(ждем завершения DllMain с аргументом DLL_PROCESS_ATTACH)
WaitForSingleObject
(
hThread
,
INFINITE
)
;
// Закрываем дескриптор потока
CloseHandle
(
hThread
)
;
// Освобождаем выделенную память
VirtualFreeEx
(
hProcess
,
pDllPath
,
SizePatch
,
MEM_RELEASE
)
;
// Закрываем дескриптор процесса
CloseHandle
(
hProcess
)
;




Алгоритм выгрузки:

- получаем хэндл процесса в который будем инжектить

- получаем адрес нашей загруженной библиотеки

- получаем адрес FreeLibrary и вызываем его через CreateRemoteThread

- ожидаем завершения выполнения DllMain DLL_PROCESS_DETACH

функция для получения адреса dll в другом процессе:

C++:






HMODULE
GetModuleHandleExtern
(
const
char
*
szModuleName
,
DWORD dwProcessId
)
{
if
(
!
szModuleName
||
!
dwProcessId
)
{
return
NULL
;
}
HANDLE hSnap
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPMODULE
,
dwProcessId
)
;
if
(
hSnap
==
INVALID_HANDLE_VALUE
)
{
return
NULL
;
}
MODULEENTRY32 me
;
me
.
dwSize
=
sizeof
(
MODULEENTRY32
)
;
if
(
Module32First
(
hSnap
,
&
me
)
)
{
while
(
Module32Next
(
hSnap
,
&
me
)
)
{
if
(
!
strcmp
(
me
.
szModule
,
szModuleName
)
)
{
CloseHandle
(
hSnap
)
;
return
me
.
hModule
;
}
}
}
CloseHandle
(
hSnap
)
;
return
NULL
;
}




C++:






// получаем хэндл процесса
HANDLE hProcess
=
OpenProcess
(
PROCESS_ALL_ACCESS
,
FALSE
,
GetProcId
(
"gta_sa.exe"
)
)
;
// получаем адрес нашей загруженной библиотеки
HMODULE module
=
GetModuleHandleExtern
(
"test.dll"
,
GetProcId
(
"gta_sa.exe"
)
)
;
HMODULE kernel
=
GetModuleHandleA
(
"Kernel32.dll"
)
;
// Получаем адрес kernel32
DWORD Adr
=
(
DWORD
)
GetProcAddress
(
kernel
,
"FreeLibrary"
)
;
// получаем адрес функции FreeLibrary
// Вызываем FreeLibrary в gta_sa.exe с адресом нашей библиотеки и возвращаем адрес нашего потока
HANDLE hThread
=
CreateRemoteThread
(
hProcess
,
0
,
0
,
(
LPTHREAD_START_ROUTINE
)
Adr
,
module
,
0
,
0
)
;
// Ожидаем завершение нашего потока(ждем завершения DllMain с аргументом DLL_PROCESS_DETACH)
WaitForSingleObject
(
hThread
,
INFINITE
)
;
// Закрываем дескриптор потока
CloseHandle
(
hThread
)
;
// Закрываем дескриптор процесса
CloseHandle
(
hProcess
)
;

RIPJake
09.05.2019, 01:31
LLA метод хороший

Но почему то в нашем мире все используют MMAP

Cake_
09.05.2019, 02:11
сф прокатит?

silence
09.05.2019, 12:34
Где ссылка на то что получилось?

#Rin
09.05.2019, 13:26
сф прокатит?


Да.

Azller Lollison
09.05.2019, 13:28
Где ссылка на то что получилось?


Сам скомпиль

SiTrak
09.05.2019, 14:45
А хуки снимать надо же?

DarkP1xel
09.05.2019, 15:52
А хуки снимать надо же?


Где ты здесь хуки увидел?

SiTrak
09.05.2019, 16:56
Где ты здесь хуки увидел?


Если я допустим хочу выгрузить свою dll мне надо снимать хуки при выгрузке ?

#Rin
09.05.2019, 20:40
Если я допустим хочу выгрузить свою dll мне надо снимать хуки при выгрузке ?


Логично что да. Но все ли хуки ты сможешь снять?

Например хуки виртуальных таблиц DirectX/RakNet определенно у тебя будут конфликтовать.

SPEKA009
15.05.2019, 17:31
Луа прокатит?

corruptmemory
28.10.2020, 08:39
Луа прокатит?


как ты заинжектишь скрипт в игру?

dekname
09.12.2020, 10:36
Так понимаю, что код вообще не компилировал.

Код:






typedef struct tagPROCESSENTRY32W
{
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID; // this process
ULONG_PTR th32DefaultHeapID;
DWORD th32ModuleID; // associated exe
DWORD cntThreads;
DWORD th32ParentProcessID; // this process's parent process
LONG pcPriClassBase; // Base priority of process's threads
DWORD dwFlags;
WCHAR szExeFile[MAX_PATH]; // Path
} PROCESSENTRY32W;




szExeFile - WCHAR, а параметр принимаешь в const char *. Конкретно я, то пофиксил так:

C++:






DWORD
GetProcId
(
std
::
string_view procname
)
{
PROCESSENTRY32 pe
;
HANDLE hSnap
;
pe
.
dwSize
=
sizeof
(
PROCESSENTRY32
)
;
hSnap
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPPROCESS
,
NULL
)
;
if
(
Process32First
(
hSnap
,
&
pe
)
)
{
do
{
if
(
std
::
wstring
(
pe
.
szExeFile
)
==
std
::
wstring
(
procname
.
begin
(
)
,
procname
.
end
(
)
)
)
break
;
}
while
(
Process32Next
(
hSnap
,
&
pe
)
)
;
}
return
pe
.
th32ProcessID
;
}

CleanLegend
09.12.2020, 12:56
Так понимаю, что код вообще не компилировал.

szExeFile - WCHAR, а параметр принимаешь в const char *. Конкретно я, то пофиксил так:


Еще напиши, что гайд просто скопировал и вставил.

В проекте использовалась многобайтовая кодировка и по дефолту функции Process32First переходили в Process32FirstA. а ты скинул структуру для Process32FirstW