ANTICHAT

ANTICHAT (https://forum.antichat.xyz/index.php)
-   С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby (https://forum.antichat.xyz/forumdisplay.php?f=24)
-   -   Вызываем удаленно игровую функцию и WinAPI (https://forum.antichat.xyz/showthread.php?t=1333035)

CleanLegend 16.04.2019 00:21

Привет, сегодня мы будем вызывать игровую функцию из exe.
Пример вызова в dll:

C++:





Код:

#define FUNC_CMessages__AddMessageJumpQ 0x69F1E0
void
AddMessageJumpQ
(
char
*
text
,
unsigned
int
time
,
unsigned
short
flag
,
bool
bPreviousBrief
)
{
(
(
void
(
__cdecl
*
)
(
char
*
,
unsigned
int
,
unsigned
short
,
bool
)
)
FUNC_CMessages__AddMessageJumpQ
)
(
text
,
time
,
flag
,
bPreviousBrief
)
;
}
AddMessageJumpQ
(
"hello"
,
500
,
NULL
,
false
)
;
// вызываем



Для вызова из exe мы будем использовать:

-OpenProcess

-VirtualAllocEx

-WriteProcessMemory

-CreateRemoteThread

Создаем структуру для передачи аргументов в удаленный поток(CreateRemoteThread):

C++:





Код:

struct
Struct
{
char
text
[
256
]
;
unsigned
int
time
;
unsigned
short
flag
;
bool
bPreviousBrief
;
DWORD pAdr
;
}
FuncArgs
;



Создаем прототип:

C++:





Код:

typedef
void
(
__cdecl
*
_SendMSG
)
(
char
*
,
unsigned
int
,
unsigned
short
,
bool
)
;



Создаем нашу функцию, которую будем вызывать. Под ней создаем еще одну, для получения размера

C++:





Код:

DWORD __stdcall
RemoteThread
(
Struct
*
sArg
)
{
_SendMSG msg
=
(
_SendMSG
)
sArg
->
pAdr
;
// передаем адрес
msg
(
sArg
->
text
,
sArg
->
time
,
sArg
->
flag
,
sArg
->
bPreviousBrief
)
;
// вызываем
return
0
;
}
void
__stdcall
RemoteThread_end
(
)
{
}



Заполняем структуру:

C++:





Код:

strcpy
(
FuncArgs
.
text
,
"Hello world!"
)
;
FuncArgs
.
time
=
500
;
FuncArgs
.
flag
=
NULL
;
FuncArgs
.
bPreviousBrief
=
false
;
FuncArgs
.
pAdr
=
0x69F1E0
;



Функция для получения 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"
)
)
;
// Выделяем память под наш поток в gta_sa
LPVOID pRemoteThread
=
VirtualAllocEx
(
hProcess
,
NULL
,
(
DWORD_PTR
)
RemoteThread_end
-
(
DWORD_PTR
)
RemoteThread
,
MEM_COMMIT
|
MEM_RESERVE
,
PAGE_EXECUTE_READWRITE
)
;
// Записываем его
WriteProcessMemory
(
hProcess
,
pRemoteThread
,
(
LPVOID
)
RemoteThread
,
(
(
DWORD_PTR
)
RemoteThread_end
-
(
DWORD_PTR
)
RemoteThread
)
,
0
)
;
// Выделяем память для нашего объекта в gta_sa
Struct
*
myArg
=
(
Struct
*
)
VirtualAllocEx
(
hProcess
,
NULL
,
sizeof
(
Struct
)
,
MEM_COMMIT
,
PAGE_READWRITE
)
;
// Записываем его
WriteProcessMemory
(
hProcess
,
myArg
,
&
FuncArgs
,
sizeof
(
Struct
)
,
NULL
)
;
// Запускаем наш поток pRemoteThread с аргументами myArg
HANDLE hThread
=
CreateRemoteThread
(
hProcess
,
0
,
0
,
(
LPTHREAD_START_ROUTINE
)
pRemoteThread
,
myArg
,
0
,
0
)
;
// Закрываем дескриптор потока
CloseHandle
(
hThread
)
;
// Освобождаем выделенную память
VirtualFreeEx
(
hProcess
,
myArg
,
sizeof
(
Struct
)
,
MEM_RELEASE
)
;
// Закрываем дескриптор процесса
CloseHandle
(
hProcess
)
;



Получаем:

Цитата:

Сообщение от Спойлер

Пример с WinAPI(Beep):

Создаем структуру и прототип:

C++:





Код:

typedef
BOOL
(
__stdcall
*
__Beep
)
(
DWORD
,
DWORD
)
;
struct
sBeep
{
DWORD Freq
;
DWORD Duration
;
DWORD pAdr
;
}
myBeep
;



Заполняем структуру:

C++:





Код:

myBeep
.
Freq
=
500
;
myBeep
.
Duration
=
50
;
HMODULE kernel
=
LoadLibrary
(
"Kernel32.dll"
)
;
// Получаем адрес kernel32
myBeep
.
pAdr
=
(
DWORD
)
GetProcAddress
(
kernel
,
"Beep"
)
;
// получаем адрес функции Beep
FreeLibrary
(
kernel
)
;



C++:





Код:

DWORD __stdcall
RemoteThread
(
sBeep
*
sArg
)
{
__Beep msg
=
(
__Beep
)
sArg
->
pAdr
;
msg
(
sArg
->
Freq
,
sArg
->
Duration
)
;
return
0
;
}
void
__stdcall
RemoteThread_end
(
)
{
}



C++:





Код:

HANDLE hProcess
=
OpenProcess
(
PROCESS_ALL_ACCESS
,
FALSE
,
GetProcId
(
"gta_sa.exe"
)
)
;
// Выделяем память под наш поток в gta_sa
LPVOID pRemoteThread
=
VirtualAllocEx
(
hProcess
,
NULL
,
(
DWORD_PTR
)
RemoteThread_end
-
(
DWORD_PTR
)
RemoteThread
,
MEM_COMMIT
|
MEM_RESERVE
,
PAGE_EXECUTE_READWRITE
)
;
// Записываем его
WriteProcessMemory
(
hProcess
,
pRemoteThread
,
(
LPVOID
)
RemoteThread
,
(
(
DWORD_PTR
)
RemoteThread_end
-
(
DWORD_PTR
)
RemoteThread
)
,
0
)
;
// Выделяем память для нашего объекта в gta_sa
sBeep
*
myArg
=
(
sBeep
*
)
VirtualAllocEx
(
hProcess
,
NULL
,
sizeof
(
sBeep
)
,
MEM_COMMIT
,
PAGE_READWRITE
)
;
// Записываем его
WriteProcessMemory
(
hProcess
,
myArg
,
&
myBeep
,
sizeof
(
sBeep
)
,
NULL
)
;
// Запускаем наш поток pRemoteThread с аргументами myArg
HANDLE hThread
=
CreateRemoteThread
(
hProcess
,
0
,
0
,
(
LPTHREAD_START_ROUTINE
)
pRemoteThread
,
myArg
,
0
,
0
)
;
// Закрываем дескриптор потока
CloseHandle
(
hThread
)
;
// Освобождаем выделенную память
VirtualFreeEx
(
hProcess
,
myArg
,
sizeof
(
sBeep
)
,
MEM_RELEASE
)
;
// Закрываем дескриптор процесса
CloseHandle
(
hProcess
)
;


SR_team 16.04.2019 10:28

а самое интересное не написал. Переключение процессов планировщиком происходит в момент вызова CreateRemoteThread или по истечению кванта? Т.е. поток выполняется сразу или отложено, при переключение процесса?

CleanLegend 16.04.2019 11:24

Цитата:

Сообщение от SR_team

а самое интересное не написал. Переключение процессов планировщиком происходит в момент вызова CreateRemoteThread или по истечению кванта? Т.е. поток выполняется сразу или отложено, при переключение процесса?

Сразу

CleanLegend 16.04.2019 12:17

Обновил. Изменил реализацию, добавил пример с WinAPI

SR_team 16.04.2019 13:05

Цитата:

Сообщение от CleanLegend

Обновил. Изменил реализацию, добавил пример с WinAPI

вот это уже выглядит круто, но компилятор может расположить функции в ином порядке

iAmerican 16.04.2019 20:32

клёвый гайд , взял себе

#Rin 25.04.2019 08:39

Цитата:

Сообщение от CleanLegend

HMODULE kernel = LoadLibrary("Kernel32.dll"); // Получаем адрес kernel32 myBeep.pAdr = (DWORD)GetProcAddress(kernel,"Beep"); // получаем адрес функции Beep FreeLibrary(kernel);

Может windows и гарантирует загрузку такой системной библиотеки по одинаковому адресу. Но адрес библиотеки в разных процессах может и будет отличаться.

Поэтому что бы найти адрес функции относительно другого процесса, нужно:

Использовать CreateToolhelp32Snapshot, Module32First, Module32Next для нахождения адреса библиотеки в чужом процессе.

Затем загрузить туже библиотеку в свой процесс через LoadLibrary.

А после найти адрес функции относительно своего процесса через GetProcAddress.

Затем просто вычисляем: адрес_библиотеки_в_чужом процессе + адрес_функции_в_нашем_проце ссе - адрес_библиотеки_в_нашем_пр оцессе.

SR_team 28.04.2019 14:53

Цитата:

Сообщение от Rinat_Namazov

Но адрес библиотеки в разных процессах может и будет отличаться.

фича библиотек в том, что один и тот же код, один раз загруженный в память, используется всеми процессами. Различаются лишь данные

#Rin 28.04.2019 15:03

Цитата:

Сообщение от SR_team

фича библиотек в том, что один и тот же код, один раз загруженный в память, используется всеми процессами. Различаются лишь данные

Я читал что в Линуксе, библиотека загруженная в память, используется всеми процессами.

Но в Виндоусе на каждый процесс свой экземпляр библиотеки.

SR_team 01.05.2019 22:15

Цитата:

Сообщение от Rinat_Namazov

Я читал что в Линуксе, библиотека загруженная в память, используется всеми процессами.
Но в Виндоусе на каждый процесс свой экземпляр библиотеки.

1. на*** они тогда нужны в винде?

2. Почему тогда фокус с получением адреса библиотечной функции из своего процесса работает?


Время: 20:25