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. Почему тогда фокус с получением адреса библиотечной функции из своего процесса работает?

#Rin 01.05.2019 23:55

Цитата:

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

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

Спроси разработчиков виндовс. Если бы так было, то тот же АнтиСтилер ставил свои хуки не только внутри гта, а на весь комп в целом. А изменение кода в какой-то функции могло бы уронить систему.

Цитата:

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

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

Большинство библиотек (как правило системные) загружаются по одинаковому адресу, но виндовс не гарантирует этого.

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

https://forum.antichat.xyz/attachments/27331951/

SR_team 02.05.2019 12:54

Цитата:

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

Спроси разработчиков виндовс. Если бы так было, то тот же АнтиСтилер ставил свои хуки не только внутри гта, а на весь комп в целом. А изменение кода в какой-то функции могло бы уронить систему.

Большинство библиотек (как правило системные) загружаются по одинаковому адресу, но виндовс не гарантирует этого.

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

да ты прав. Кстати, что касаемо адресов, в PE можно указать желаемое адрессное пространство для библиотеки, и если оно не занято, то библиотека всегда будет грузится в него. По дефолту вроде адрес 0x10000000

Vadim.dll 08.05.2019 12:45

При попытке выполнения этого кода gta просто выключается, без ошибок, как будто завершается процесс

LUCHARE 22.06.2019 06:03

круто конечно

жаль что баян (the CreateRemoteThread & WriteProcessMemory technique старше меня)

и перепизжено на разные форумы тысячу раз

Цитата:

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

да ты прав.

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

Цитата:

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

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

Цитата:


Kernel32 is required to be at the same base address because there are a number of internal kernel32 routines that, similar to ntdll!DbgUiRemoteBreakIn, are used in cross-process thread injection. One example of this used to be the console control event handler In the case of console events, during kernel32.dll initialization, the address of the Ctrl-C event dispatcher is passed to WinSrv.dll (in CSRSS space).
...
By the time this change to WinSrv and Ctrl-C processing was made, though, the application compatibility impact of removing the kernel32 base address to be the same system-wide would have been too severe to eliminate the restriction (virtually all third party code injection code now relies heavily on this assumption). Thus, for this (and other) reasons, kernel32 still remains with the restriction that it may not be relocated to a different base address cross-process.


ntharbinger 22.06.2019 07:11

Проблемy с разным адресом процедуры из-за релокаций можно решить так

C++:





Код:

DWORD RVA
=
(
(
DWORD_PTR
)
GetProcAddress
(
GetModuleHandleA
(
"kernel32.dll"
)
,
"CreateRemoteThread"
)
-
(
DWORD_PTR
)
GetModuleHandleA
(
"kernel32.dll"
)
)
;
auto
ObtainRemoteBase
=
[
]
(
HANDLE hProc
,
const
char
*
dllName
)
->
DWORD_PTR
{
HMODULE hMods
[
1024
]
;
DWORD cbNeeded
;
EnumProcessModules
(
hProc
,
hMods
,
sizeof
(
hMods
)
,
&
cbNeeded
)
;
for
(
unsigned
int
i
=
0
;
i

(
hMods
[
i
]
)
;
}
}
}
;
auto
FindProcessId
=
[
]
(
char
*
processName
)
->
DWORD
{
char
*
p
=
strrchr
(
processName
,
'\\'
)
;
if
(
p
)
processName
=
p
+
1
;
PROCESSENTRY32 processInfo
;
processInfo
.
dwSize
=
sizeof
(
processInfo
)
;
HANDLE processesSnapshot
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPPROCESS
,
NULL
)
;
if
(
processesSnapshot
==
INVALID_HANDLE_VALUE
)
return
0
;
Process32First
(
processesSnapshot
,
&
processInfo
)
;
if
(
!
strcmp
(
processName
,
processInfo
.
szExeFile
)
)
{
CloseHandle
(
processesSnapshot
)
;
return
processInfo
.
th32ProcessID
;
}
while
(
Process32Next
(
processesSnapshot
,
&
processInfo
)
)
{
if
(
!
strcmp
(
processName
,
processInfo
.
szExeFile
)
)
{
CloseHandle
(
processesSnapshot
)
;
return
processInfo
.
th32ProcessID
;
}
}
CloseHandle
(
processesSnapshot
)
;
return
0
;
}
;
DWORD procID
=
GetProcID
(
"имя_процесса.ехе"
)
;
if
(
procID
==
NULL
)
return
;
HANDLE hProc
=
OpenProcess
(
PROCESS_ALL_ACCESS
,
FALSE
,
procID
)
;
if
(
hProc
!=
NULL
)
{
DWORD_PTR funcAddr
=
RVA
+
ObtainRemoteBase
(
hProc
,
"kernel32.dll"
)
;
CloseHandle
(
hProc
)
;
}


_Vine_ 22.06.2019 16:21

Цитата:

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

Проблемy с разным адресом процедуры из-за релокаций можно решить так

C++:





Код:

DWORD RVA
=
(
(
DWORD_PTR
)
GetProcAddress
(
GetModuleHandleA
(
"kernel32.dll"
)
,
"CreateRemoteThread"
)
-
(
DWORD_PTR
)
GetModuleHandleA
(
"kernel32.dll"
)
)
;
auto
ObtainRemoteBase
=
[
]
(
HANDLE hProc
,
const
char
*
dllName
)
->
DWORD_PTR
{
HMODULE hMods
[
1024
]
;
DWORD cbNeeded
;
EnumProcessModules
(
hProc
,
hMods
,
sizeof
(
hMods
)
,
&
cbNeeded
)
;
for
(
unsigned
int
i
=
0
;
i

(
hMods
[
i
]
)
;
}
}
}
;
auto
FindProcessId
=
[
]
(
char
*
processName
)
->
DWORD
{
char
*
p
=
strrchr
(
processName
,
'\\'
)
;
if
(
p
)
processName
=
p
+
1
;
PROCESSENTRY32 processInfo
;
processInfo
.
dwSize
=
sizeof
(
processInfo
)
;
HANDLE processesSnapshot
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPPROCESS
,
NULL
)
;
if
(
processesSnapshot
==
INVALID_HANDLE_VALUE
)
return
0
;
Process32First
(
processesSnapshot
,
&
processInfo
)
;
if
(
!
strcmp
(
processName
,
processInfo
.
szExeFile
)
)
{
CloseHandle
(
processesSnapshot
)
;
return
processInfo
.
th32ProcessID
;
}
while
(
Process32Next
(
processesSnapshot
,
&
processInfo
)
)
{
if
(
!
strcmp
(
processName
,
processInfo
.
szExeFile
)
)
{
CloseHandle
(
processesSnapshot
)
;
return
processInfo
.
th32ProcessID
;
}
}
CloseHandle
(
processesSnapshot
)
;
return
0
;
}
;
DWORD procID
=
GetProcID
(
"имя_процесса.ехе"
)
;
if
(
procID
==
NULL
)
return
;
HANDLE hProc
=
OpenProcess
(
PROCESS_ALL_ACCESS
,
FALSE
,
procID
)
;
if
(
hProc
!=
NULL
)
{
DWORD_PTR funcAddr
=
RVA
+
ObtainRemoteBase
(
hProc
,
"kernel32.dll"
)
;
CloseHandle
(
hProc
)
;
}



В funcAddr можно записать адрес WinApi функции текущего процесса, базовый адрес системных библиотек во процессах(одинаковой архитектуры) одинаковый.

Так же находят адрес LoadLibraryA инжекторы

ntharbinger 22.06.2019 18:08

Цитата:

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

В funcAddr можно записать адрес WinApi функции текущего процесса, базовый адрес системных библиотек во процессах(одинаковой архитектуры) одинаковый.
Так же находят адрес LoadLibraryA инжекторы

а вот и нихуя, про ASLR слышал? Ну вот)

LUCHARE 23.06.2019 01:40

Цитата:

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

а вот и нихуя, про ASLR слышал? Ну вот)

он генерирует одинаковые адреса во всех процессах для системных библиотек

iqvw64e.sys 23.07.2019 21:13

Цитата:

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

Спроси разработчиков виндовс. Если бы так было, то тот же АнтиСтилер ставил свои хуки не только внутри гта, а на весь комп в целом. А изменение кода в какой-то функции могло бы уронить систему.

Большинство библиотек (как правило системные) загружаются по одинаковому адресу, но виндовс не гарантирует этого.

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

Копирование при записи — Википедия

ru.wikipedia.org


hint: PspAllocateProcess

ALF 14.08.2019 14:33

Цитата:

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

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() {}

Цитата:

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

(DWORD_PTR)RemoteThread_end - (DWORD_PTR)RemoteThread

только вот ты забыл сказать, что при таком варианте должна быть отключена оптимизация, иначе мы можем получить неопределённое поведение

DivineSomeone 05.10.2019 05:42

А получить координаты костей можно как-то через удалённый способ? :/

Vintik 06.07.2020 00:26

@CleanLegend помоги братец

C++:





Код:

#include
#include
#include
#include
int
processId
;
int
GetProcessIdByWindowName
(
std
::
string windowName
)
{
HWND window
=
FindWindowA
(
NULL
,
reinterpret_cast

(
windowName
.
c_str
(
)
)
)
;
int
pId
=
0
;
GetWindowThreadProcessId
(
window
,
reinterpret_cast

(
&
pId
)
)
;
return
pId
;
}
template

T
readMem
(
int
address
)
{
T buf
;
HANDLE h
=
OpenProcess
(
PROCESS_VM_READ
,
false
,
processId
)
;
ReadProcessMemory
(
h
,
reinterpret_cast

(
address
)
,
&
buf
,
sizeof
(
T
)
,
NULL
)
;
CloseHandle
(
h
)
;
return
buf
;
}
template

void
writeMem
(
int
address
,
T buf
)
{
HANDLE h
=
OpenProcess
(
PROCESS_VM_WRITE
,
false
,
processId
)
;
int
oldProtect
=
0
;
VirtualProtectEx
(
h
,
reinterpret_cast

(
address
)
,
sizeof
(
T
)
,
PAGE_READWRITE
,
reinterpret_cast

(
&
oldProtect
)
)
;
WriteProcessMemory
(
h
,
reinterpret_cast

(
address
)
,
&
buf
,
sizeof
(
T
)
,
NULL
)
;
VirtualProtectEx
(
h
,
reinterpret_cast

(
address
)
,
sizeof
(
T
)
,
oldProtect
,
reinterpret_cast

(
&
oldProtect
)
)
;
CloseHandle
(
h
)
;
}
struct
AddMessageArg
{
DWORD arg1
;
int
arg2
;
const
char
*
arg3
;
int
arg4
;
int
arg5
;
int
arg6
;
}
;
typedef
void
(
__cdecl
*
AddMessage
)
(
DWORD
,
int
,
const
char
*
,
int
,
int
,
int
)
;
DWORD __stdcall
RemoteThread
(
AddMessageArg
*
arg
)
{
AddMessage msg
=
(
AddMessage
)
(
reinterpret_cast

(
GetModuleHandleA
(
"samp.dll"
)
+
0x64010
)
)
;
// передаем адрес
msg
(
arg
->
arg1
,
arg
->
arg2
,
arg
->
arg3
,
arg
->
arg4
,
arg
->
arg5
,
arg
->
arg6
)
;
// вызываем
return
0
;
}
void
__stdcall
RemoteThread_end
(
)
{
}
void
AddSampMessage
(
std
::
string message
,
int
color
)
{
AddMessageArg funcArg
;
funcArg
.
arg1
=
readMem

(
reinterpret_cast

(
GetModuleHandleA
(
"samp.dll"
)
+
0x21A0E4
)
)
;
funcArg
.
arg2
=
4
;
funcArg
.
arg3
=
message
.
c_str
(
)
;
funcArg
.
arg4
=
0
;
funcArg
.
arg5
=
color
;
funcArg
.
arg6
=
0
;
HANDLE h
=
OpenProcess
(
PROCESS_ALL_ACCESS
,
false
,
processId
)
;
LPVOID pRemoteThread
=
VirtualAllocEx
(
h
,
NULL
,
reinterpret_cast

(
RemoteThread_end
)
-
reinterpret_cast

(
RemoteThread
)
,
MEM_COMMIT
|
MEM_RESERVE
,
PAGE_EXECUTE_READWRITE
)
;
WriteProcessMemory
(
h
,
pRemoteThread
,
reinterpret_cast

(
RemoteThread
)
,
(
reinterpret_cast

(
RemoteThread_end
)
-
reinterpret_cast

(
RemoteThread
)
)
,
0
)
;
AddMessageArg
*
myArg
=
reinterpret_cast

(
VirtualAllocEx
(
h
,
NULL
,
sizeof
(
AddMessageArg
)
,
MEM_COMMIT
,
PAGE_READWRITE
)
)
;
writeMem

(
reinterpret_cast

(
myArg
)
,
funcArg
)
;
HANDLE h2
=
CreateRemoteThread
(
h
,
0
,
0
,
(
LPTHREAD_START_ROUTINE
)
pRemoteThread
,
myArg
,
0
,
0
)
;
CloseHandle
(
h2
)
;
VirtualFreeEx
(
h
,
myArg
,
sizeof
(
AddMessageArg
)
,
MEM_RELEASE
)
;
CloseHandle
(
h
)
;
}
int
main
(
)
{
processId
=
GetProcessIdByWindowName
(
"GTA:SA:MP"
)
;
AddSampMessage
(
"This is C++, wow!"
,
0
)
;
}



Укажите на ошибки, почему сообщение в чат не отправляется, непон.

И да, на эту строку

C++:





Код:

VirtualFreeEx
(
h
,
myArg
,
sizeof
(
AddMessageArg
)
,
MEM_RELEASE
)
;



Выдаёт пред, очково

Код:





Код:

Предупреждение    C6333    Недопустимый параметр:  передача MEM_RELEASE и ненулевого параметра dwSize в "VirtualFreeEx" не допускается.  Это приведет к сбою вызова.

CleanLegend 06.07.2020 14:22

Цитата:

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

@CleanLegend помоги братец

C++:





Код:

DWORD __stdcall
RemoteThread
(
AddMessageArg
*
arg
)
{
AddMessage msg
=
(
AddMessage
)
(
reinterpret_cast

(
GetModuleHandleA
(
"samp.dll"
)
+
0x64010
)
)
;
// передаем адрес
msg
(
arg
->
arg1
,
arg
->
arg2
,
arg
->
arg3
,
arg
->
arg4
,
arg
->
arg5
,
arg
->
arg6
)
;
// вызываем
return
0
;
}



GetModuleHandleA не может быть вызвана таким путем, нужно получить адрес на него через GetProcAdress и позже уже передать в структуру.

Тоже самое и с текстом: "samp.dll", в памяти игры у тебя его нет, поэтому тоже ошибка, передавай в структуру.

Цитата:

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

C++:





Код:

HANDLE h2
=
CreateRemoteThread
(
h
,
0
,
0
,
(
LPTHREAD_START_ROUTINE
)
pRemoteThread
,
myArg
,
0
,
0
)
;
CloseHandle
(
h2
)
;
VirtualFreeEx
(
h
,
myArg
,
sizeof
(
AddMessageArg
)
,
MEM_RELEASE
)
;



Ошибка с освобождением памяти. Нужно ждать пока поток закончится, а только после освобождать память:

C++:





Код:

WaitForSingleObject
(
h2
,
INFINITE
)
;
// после CreateRemoteThread



Цитата:

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

C++:





Код:

VirtualFreeEx
(
h
,
myArg
,
sizeof
(
AddMessageArg
)
,
MEM_RELEASE
)
;



Выдаёт пред, очково

Код:





Код:

Предупреждение    C6333    Недопустимый параметр:  передача MEM_RELEASE и ненулевого параметра dwSize в "VirtualFreeEx" не допускается.  Это приведет к сбою вызова.


Вместо размера нужно указывать 0, компилятор тебе об это написал.

Vintik 06.07.2020 17:18

@CleanLegend опять какая-то ерунда.

1594114830318.pngVintik · 6 Июл 2020 в 16:18' data-fancybox="lb-post-524694" data-lb-caption-extra-html="" data-lb-sidebar-href="" data-single-image="1" data-src="https://www.blast.hk/attachments/61639/" style="cursor: pointer;" title="1594114830318.png">
https://forum.antichat.xyz/attachments/27524694/

Что уж теперь не так то? Я всё пофиксил из того, что ты сказал.

Цитата:

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


C++:





Код:

#include
#include
#include
#include
int
processId
;
DWORD sampdll
;
int
GetProcessIdByWindowName
(
std
::
string windowName
)
{
HWND window
=
FindWindowA
(
NULL
,
reinterpret_cast

(
windowName
.
c_str
(
)
)
)
;
int
pId
=
0
;
GetWindowThreadProcessId
(
window
,
reinterpret_cast

(
&
pId
)
)
;
return
pId
;
}
DWORD
GetModuleBaseAddress
(
DWORD pid
,
const
char
*
name
)
{
HANDLE snapshot
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPMODULE
,
pid
)
;
MODULEENTRY32 mEntry
;
mEntry
.
dwSize
=
sizeof
(
MODULEENTRY32
)
;
do
{
if
(
!
strcmp
(
(
const
char
*
)
mEntry
.
szModule
,
name
)
)
{
CloseHandle
(
snapshot
)
;
return
(
DWORD
)
mEntry
.
modBaseAddr
;
}
}
while
(
Module32Next
(
snapshot
,
&
mEntry
)
)
;
}
template

T
readMem
(
int
address
)
{
T buf
;
HANDLE h
=
OpenProcess
(
PROCESS_VM_READ
,
false
,
processId
)
;
ReadProcessMemory
(
h
,
reinterpret_cast

(
address
)
,
&
buf
,
sizeof
(
T
)
,
NULL
)
;
CloseHandle
(
h
)
;
return
buf
;
}
template

void
writeMem
(
int
address
,
T buf
)
{
HANDLE h
=
OpenProcess
(
PROCESS_VM_WRITE
,
false
,
processId
)
;
int
oldProtect
=
0
;
VirtualProtectEx
(
h
,
reinterpret_cast

(
address
)
,
sizeof
(
T
)
,
PAGE_READWRITE
,
reinterpret_cast

(
&
oldProtect
)
)
;
WriteProcessMemory
(
h
,
reinterpret_cast

(
address
)
,
&
buf
,
sizeof
(
T
)
,
NULL
)
;
VirtualProtectEx
(
h
,
reinterpret_cast

(
address
)
,
sizeof
(
T
)
,
oldProtect
,
reinterpret_cast

(
&
oldProtect
)
)
;
CloseHandle
(
h
)
;
}
struct
AddMessageArg
{
DWORD arg1
;
int
arg2
;
const
char
*
arg3
;
int
arg4
;
int
arg5
;
int
arg6
;
DWORD addr
;
}
;
typedef
void
(
__cdecl
*
AddMessage
)
(
DWORD
,
int
,
const
char
*
,
int
,
int
,
int
)
;
DWORD __stdcall
RemoteThread
(
AddMessageArg
*
arg
)
{
AddMessage msg
=
(
AddMessage
)
arg
->
addr
;
msg
(
arg
->
arg1
,
arg
->
arg2
,
arg
->
arg3
,
arg
->
arg4
,
arg
->
arg5
,
arg
->
arg6
)
;
return
0
;
}
void
__stdcall
RemoteThread_end
(
)
{
}
void
AddSampMessage
(
std
::
string message
,
int
color
)
{
AddMessageArg funcArg
;
funcArg
.
arg1
=
readMem

(
sampdll
+
0x21A0E4
)
;
funcArg
.
arg2
=
4
;
funcArg
.
arg3
=
message
.
c_str
(
)
;
funcArg
.
arg4
=
0
;
funcArg
.
arg5
=
color
;
funcArg
.
arg6
=
0
;
funcArg
.
addr
=
sampdll
+
0x64010
;
HANDLE h
=
OpenProcess
(
PROCESS_ALL_ACCESS
,
false
,
processId
)
;
LPVOID pRemoteThread
=
VirtualAllocEx
(
h
,
NULL
,
reinterpret_cast

(
RemoteThread_end
)
-
reinterpret_cast

(
RemoteThread
)
,
MEM_COMMIT
|
MEM_RESERVE
,
PAGE_EXECUTE_READWRITE
)
;
WriteProcessMemory
(
h
,
pRemoteThread
,
reinterpret_cast

(
RemoteThread
)
,
(
reinterpret_cast

(
RemoteThread_end
)
-
reinterpret_cast

(
RemoteThread
)
)
,
0
)
;
AddMessageArg
*
myArg
=
reinterpret_cast

(
VirtualAllocEx
(
h
,
NULL
,
sizeof
(
AddMessageArg
)
,
MEM_COMMIT
,
PAGE_READWRITE
)
)
;
writeMem

(
reinterpret_cast

(
myArg
)
,
funcArg
)
;
HANDLE h2
=
CreateRemoteThread
(
h
,
0
,
0
,
reinterpret_cast

(
pRemoteThread
)
,
myArg
,
0
,
0
)
;
WaitForSingleObject
(
h2
,
INFINITE
)
;
CloseHandle
(
h2
)
;
VirtualFreeEx
(
h
,
myArg
,
0
,
MEM_RELEASE
)
;
CloseHandle
(
h
)
;
}
int
main
(
)
{
processId
=
GetProcessIdByWindowName
(
"GTA:SA:MP"
)
;
sampdll
=
GetModuleBaseAddress
(
processId
,
"samp.dll"
)
;
AddSampMessage
(
"This is C++, wow!"
,
0
)
;
}





CleanLegend 14.07.2020 20:19

Цитата:

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

@CleanLegend опять какая-то ерунда.

Цитата:

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


C++:





Код:

#include
struct
AddMessageArg
{
DWORD arg1
;
int
arg2
;
const
char
*
arg3
;
int
arg4
;
int
arg5
;
int
arg6
;
DWORD addr
;
}
;





скорее всего из за того, что ты передаешь в указатель arg3 строку из локального процесса, но в самом процессе gta_sa по этому указатлю такого нет, поэтому лучше заполнить буфер: char arg3[256]. в гайде у меня пример на этом построен

Vintik 14.07.2020 22:16

Цитата:

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

скорее всего из за того, что ты передаешь в указатель arg3 строку из локального процесса, но в самом процессе gta_sa по этому указатлю такого нет, поэтому лучше заполнить буфер: char arg3[256]. в гайде у меня пример на этом построен

Хорошо, спасибо, проверю. И еще скажи, пожалуйста, а как узнавать количество аргументов функций? Чтобы вызвать функцию, надо знать все её аргументы (и, соответственно, их количество).

Второй второй. Я сделал на DLL коллбэк (обычный 5-байтовый jmp в начале функции) на исходящее от тебя в чат сообщение и хотел бы понять, как игнорировать (не пропускать сообщение) в некоторых случаях (например, если текст содержит мат) – пытался сделать jmp в конец функции, но краш.

CleanLegend 14.07.2020 22:40

Цитата:

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

Хорошо, спасибо, проверю. И еще скажи, пожалуйста, а как узнавать количество аргументов функций? Чтобы вызвать функцию, надо знать все её аргументы (и, соответственно, их количество).
Второй второй. Я сделал на DLL коллбэк (обычный 5-байтовый jmp в начале функции) на исходящее от тебя в чат сообщение и хотел бы понять, как игнорировать (не пропускать сообщение) в некоторых случаях (например, если текст содержит мат) – пытался сделать jmp в конец функции, но краш.

самый простой вариант через IDA.

что бы игнорировать функцию просто поставь ret(если функция не возвращает никаких аргументов)

Vintik 15.07.2020 00:13

Цитата:

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

самый простой вариант через IDA.

что бы игнорировать функцию просто поставь ret(если функция не возвращает никаких аргументов)

1) IDA в CE норм? как конкретно?

2) а если возвращает чтот?

CleanLegend 15.07.2020 12:08

Цитата:

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

1) IDA в CE норм? как конкретно?
2) а если возвращает чтот?

1. у IDA есть декомпилятор, она покажет псевдокод

2. анализируй функцию, если возврат идет в виде true/false , то будет примерно так:

C++:





Код:

true
:
mov eax
,
0x1
ret
false
(
обычно используется второй вариант
)
:
mov eax
,
0x0
ret

либо
xor
eax
,
eax
ret


p1cador 22.07.2020 00:20

Также следует добавить, что взвращаемое функцией значение можно получить, разместив следуюищий код между созданием удаленного потока и закрытием хендла процесса:

C:





Код:

unsigned
__int32 retValue
=
0
;
while
(
WaitForSingleObject
(
hThread
,
0
)
!=
0
)
{
}
GetExitCodeThread
(
hThread
,
&
retValue
)
;


_NeliN_ 09.01.2024 17:17

У меня ошибка, @CleanLegend живой, поможешь?

Вообщем такое же окошко вылезает, без понятия что делать

Цитата:

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

@CleanLegend опять какая-то ерунда.

Что уж теперь не так то? Я всё пофиксил из того, что ты сказал.
Цитата:

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


C++:





Код:

#include
#include
#include
#include
int
processId
;
DWORD sampdll
;
int
GetProcessIdByWindowName
(
std
::
string windowName
)
{
HWND window
=
FindWindowA
(
NULL
,
reinterpret_cast

(
windowName
.
c_str
(
)
)
)
;
int
pId
=
0
;
GetWindowThreadProcessId
(
window
,
reinterpret_cast

(
&
pId
)
)
;
return
pId
;
}
DWORD
GetModuleBaseAddress
(
DWORD pid
,
const
char
*
name
)
{
HANDLE snapshot
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPMODULE
,
pid
)
;
MODULEENTRY32 mEntry
;
mEntry
.
dwSize
=
sizeof
(
MODULEENTRY32
)
;
do
{
if
(
!
strcmp
(
(
const
char
*
)
mEntry
.
szModule
,
name
)
)
{
CloseHandle
(
snapshot
)
;
return
(
DWORD
)
mEntry
.
modBaseAddr
;
}
}
while
(
Module32Next
(
snapshot
,
&
mEntry
)
)
;
}
template

T
readMem
(
int
address
)
{
T buf
;
HANDLE h
=
OpenProcess
(
PROCESS_VM_READ
,
false
,
processId
)
;
ReadProcessMemory
(
h
,
reinterpret_cast

(
address
)
,
&
buf
,
sizeof
(
T
)
,
NULL
)
;
CloseHandle
(
h
)
;
return
buf
;
}
template

void
writeMem
(
int
address
,
T buf
)
{
HANDLE h
=
OpenProcess
(
PROCESS_VM_WRITE
,
false
,
processId
)
;
int
oldProtect
=
0
;
VirtualProtectEx
(
h
,
reinterpret_cast

(
address
)
,
sizeof
(
T
)
,
PAGE_READWRITE
,
reinterpret_cast

(
&
oldProtect
)
)
;
WriteProcessMemory
(
h
,
reinterpret_cast

(
address
)
,
&
buf
,
sizeof
(
T
)
,
NULL
)
;
VirtualProtectEx
(
h
,
reinterpret_cast

(
address
)
,
sizeof
(
T
)
,
oldProtect
,
reinterpret_cast

(
&
oldProtect
)
)
;
CloseHandle
(
h
)
;
}
struct
AddMessageArg
{
DWORD arg1
;
int
arg2
;
const
char
*
arg3
;
int
arg4
;
int
arg5
;
int
arg6
;
DWORD addr
;
}
;
typedef
void
(
__cdecl
*
AddMessage
)
(
DWORD
,
int
,
const
char
*
,
int
,
int
,
int
)
;
DWORD __stdcall
RemoteThread
(
AddMessageArg
*
arg
)
{
AddMessage msg
=
(
AddMessage
)
arg
->
addr
;
msg
(
arg
->
arg1
,
arg
->
arg2
,
arg
->
arg3
,
arg
->
arg4
,
arg
->
arg5
,
arg
->
arg6
)
;
return
0
;
}
void
__stdcall
RemoteThread_end
(
)
{
}
void
AddSampMessage
(
std
::
string message
,
int
color
)
{
AddMessageArg funcArg
;
funcArg
.
arg1
=
readMem

(
sampdll
+
0x21A0E4
)
;
funcArg
.
arg2
=
4
;
funcArg
.
arg3
=
message
.
c_str
(
)
;
funcArg
.
arg4
=
0
;
funcArg
.
arg5
=
color
;
funcArg
.
arg6
=
0
;
funcArg
.
addr
=
sampdll
+
0x64010
;
HANDLE h
=
OpenProcess
(
PROCESS_ALL_ACCESS
,
false
,
processId
)
;
LPVOID pRemoteThread
=
VirtualAllocEx
(
h
,
NULL
,
reinterpret_cast

(
RemoteThread_end
)
-
reinterpret_cast

(
RemoteThread
)
,
MEM_COMMIT
|
MEM_RESERVE
,
PAGE_EXECUTE_READWRITE
)
;
WriteProcessMemory
(
h
,
pRemoteThread
,
reinterpret_cast

(
RemoteThread
)
,
(
reinterpret_cast

(
RemoteThread_end
)
-
reinterpret_cast

(
RemoteThread
)
)
,
0
)
;
AddMessageArg
*
myArg
=
reinterpret_cast

(
VirtualAllocEx
(
h
,
NULL
,
sizeof
(
AddMessageArg
)
,
MEM_COMMIT
,
PAGE_READWRITE
)
)
;
writeMem

(
reinterpret_cast

(
myArg
)
,
funcArg
)
;
HANDLE h2
=
CreateRemoteThread
(
h
,
0
,
0
,
reinterpret_cast

(
pRemoteThread
)
,
myArg
,
0
,
0
)
;
WaitForSingleObject
(
h2
,
INFINITE
)
;
CloseHandle
(
h2
)
;
VirtualFreeEx
(
h
,
myArg
,
0
,
MEM_RELEASE
)
;
CloseHandle
(
h
)
;
}
int
main
(
)
{
processId
=
GetProcessIdByWindowName
(
"GTA:SA:MP"
)
;
sampdll
=
GetModuleBaseAddress
(
processId
,
"samp.dll"
)
;
AddSampMessage
(
"This is C++, wow!"
,
0
)
;
}






Vintik 09.01.2024 20:03

Цитата:

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

без понятия что делать

Я жив, попробую помочь.

Код свой скинь

_NeliN_ 09.01.2024 22:02

C++:





Код:

#include
#include
#include
#include
#include
using
namespace
std
;
#define FUNC_CMessages__AddMessageJumpQ 0x69F1E0
DWORD
GetProcessIdByName
(
const
std
::
wstring
&
proc_name
)
{
PROCESSENTRY32 entry
;
entry
.
dwSize
=
sizeof
(
PROCESSENTRY32
)
;
DWORD ids
;
DWORD mids
;
HANDLE snapshot
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPPROCESS
,
NULL
)
;
if
(
Process32First
(
snapshot
,
&
entry
)
)
{
while
(
Process32Next
(
snapshot
,
&
entry
)
)
if
(
entry
.
szExeFile
==
proc_name
)
{
mids
=
entry
.
th32ModuleID
;
ids
=
entry
.
th32ProcessID
;
cout

pAdr
;
// передаем адрес
msg
(
sArg
->
text
,
sArg
->
time
,
sArg
->
flag
,
sArg
->
bPreviousBrief
)
;
// вызываем
return
0
;
}
void
__stdcall
RemoteThread_end
(
)
{
}
int
main
(
)
{
setlocale
(
LC_ALL
,
"Russian"
)
;
strcpy_s
(
FuncArgs
.
text
,
"Hello world!"
)
;
FuncArgs
.
time
=
500
;
FuncArgs
.
flag
=
NULL
;
FuncArgs
.
bPreviousBrief
=
false
;
FuncArgs
.
pAdr
=
0x69F1E0
;
// получаем хэндл процесса
HANDLE hProcess
=
OpenProcess
(
PROCESS_ALL_ACCESS
,
FALSE
,
GetProcessIdByName
(
L
"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
)
;
}



практически не отличается от кода в заголовке, разве что функция получения pID другая (но 100 процентов рабочая), и strcpy заменил на strcpy_s, т.к. на что то ругался

я так то новичок в c++, пытаюсь постепенно понять значения неизвестных функций

UPD: нашел способ поставить strcpy как у автора темы, но все равно получаю ошибку.

SA-MP 0.3.7

Exception At Address: 0x13500013

Base: 0x041E0000

ОЙ ахахаах переключил на x86 и заработало). Не подскажите, а почему раньше не работало?

_SendMSG msg = (_SendMSG)sArg->pAdr; // передаем адрес . В этой строчке мы передаем адрес функции нашему прототипу функции, верно?

А для чего нужна пустая функция void __stdcall RemoteThread_end() {}?

CleanLegend 10.01.2024 00:23

Цитата:

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

ОЙ ахахаах переключил на x86 и заработало). Не подскажите, а почему раньше не работало?

если собирал в x64, то отличие в инструкциях, регистрах и механике вызова функций. код x64 в x86 процессе запарно выполнять

Цитата:

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

А для чего нужна пустая функция void __stdcall RemoteThread_end() {}?

для расчет размера функции RemoteThread

C++:





Код:

(
DWORD_PTR
)
RemoteThread_end
-
(
DWORD_PTR
)
RemoteThread

например
:
RemoteThread_end
=
0x19100
adr
RemoteThread
=
0x19000
adr
0x19100
-
0x19000
=
0x100
размер
0x100


etereon 10.01.2024 00:55

Цитата:

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

для расчет размера функции RemoteThread

C++:





Код:

(
DWORD_PTR
)
RemoteThread_end
-
(
DWORD_PTR
)
RemoteThread

например
:
RemoteThread_end
=
0x19100
adr
RemoteThread
=
0x19000
adr
0x19100
-
0x19000
=
0x100
размер
0x100



Лучше по идее бежать по байтам функции RemoteThread и искать \xCC\xCC\xCC в конце, потому что нет гарантии, что RemoteThread_end будет после неё (наверно)


Время: 14:53