PDA

Просмотр полной версии : Вызываем удаленно игровую функцию и WinAPI


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
)
;




Получаем:




https://i.imgur.com/b4aX9ze.png




Пример с 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
а самое интересное не написал. Переключение процессов планировщиком происходит в момент вызова CreateRemoteThread или по истечению кванта? Т.е. поток выполняется сразу или отложено, при переключение процесса?


Сразу

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

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


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

iAmerican
16.04.2019, 20:32
клёвый гайд , взял себе

#Rin
25.04.2019, 08:39
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
Но адрес библиотеки в разных процессах может и будет отличаться.


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

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


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

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

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


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

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

#Rin
01.05.2019, 23:55
1. на*** они тогда нужны в винде?


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



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


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

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

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

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

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

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


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

Vadim.dll
08.05.2019, 12:45
При попытке выполнения этого кода gta просто выключается, без ошибок, как будто завершается процесс

LUCHARE
22.06.2019, 06:03
круто конечно

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

и перепизжено на разные форумы тысячу раз (https://www.blast.hk/redirect/aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS9zZWFyY2g_cT1jJTJCJT JCK2NvZGUrY2F2aW5nJnNwZWxsPTEmc2E9WCZ2ZWQ9MGFoVUtF d2pnbE5tcDJQdmlBaFZGbUlzS0hWVDVCbm9RQlFnc0tBQSZiaX c9MTkyMCZiaWg9OTM3)



да ты прав.


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



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





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 (https://www.blast.hk/redirect/aHR0cDovL3d3dy5ueW5hZXZlLm5ldC8_cD0xOTc) 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.


http://www.nynaeve.net/?p=198 (https://www.blast.hk/redirect/aHR0cDovL3d3dy5ueW5hZXZlLm5ldC8_cD0xOTg)​

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


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

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


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

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

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

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



Копирование при записи — Википедия (https://www.blast.hk/redirect/aHR0cHM6Ly9ydS53aWtpcGVkaWEub3JnL3dpa2kvJUQwJTlBJU QwJUJFJUQwJUJGJUQwJUI4JUQxJTgwJUQwJUJFJUQwJUIyJUQw JUIwJUQwJUJEJUQwJUI4JUQwJUI1XyVEMCVCRiVEMSU4MCVEMC VCOF8lRDAlQjclRDAlQjAlRDAlQkYlRDAlQjglRDElODElRDAl Qjg)

ru.wikipedia.org


hint: PspAllocateProcess

ALF
14.08.2019, 14:33
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() {}





(DWORD_PTR)RemoteThread_end - (DWORD_PTR)RemoteThread



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

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

Vintik
06.07.2020, 00:26
@CleanLegend (https://www.blast.hk/members/268/) помоги братец

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
@CleanLegend (https://www.blast.hk/members/268/) помоги братец

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", в памяти игры у тебя его нет, поэтому тоже ошибка, передавай в структуру.



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






C++:






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




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

Код:






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





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

Vintik
06.07.2020, 17:18
@CleanLegend (https://www.blast.hk/members/268/) опять какая-то ерунда.

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
@CleanLegend (https://www.blast.hk/members/268/) опять какая-то ерунда.




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


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

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

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


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

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

Vintik
15.07.2020, 00:13
самый простой вариант через IDA.

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


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

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

CleanLegend
15.07.2020, 12:08
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 (https://www.blast.hk/members/268/) живой, поможешь?

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



@CleanLegend (https://www.blast.hk/members/268/) опять какая-то ерунда.

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



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_
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
ОЙ ахахаах переключил на x86 и заработало). Не подскажите, а почему раньше не работало?


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



А для чего нужна пустая функция 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
для расчет размера функции 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 будет после неё (наверно)