Я лучше тебя
-
Автор темы
- #1
Помнится, обещал я пример простого анти-чита, появилась свободная минутка, таки своял на коленке заветную первую часть.
Первый урок мы начнем с детекта простых инжектов, для разколупывания которых, возьмем за основу навесные хуки. Читавшие статью об основной теории ссылка на которую указана выше, начинается дело с вхождения, с первого отклонения от нормы, от которого можно далее плясать.
Ставить эти хуки мы будем через MinHook, где брать и с чем жевать описано в моей давнешней теме про
>> модификацию процесса на старте << (Кликабельно)
Сделаем простую консольку с выводом данных.
Предполагается, что пользователь на той стороне, имеет базовые навыки работы с компилятором и хотя бы начальные знания, в связи с чем готового исходника публиковать не буду, так как весь код и так будет описан в статье. Разумеется это изичный баян и с последующими частями задача будет усложнятся, условия будут меняться. Но а для тех кто базовых знаний не имеет, можете пропустить тему мимо глаз,я направляю внимание на тех, кто хочет развиваться.
Такэ, приступим.Про общую теорию можно узнать в теме об >> Общей теории детекта << (Кликабельно)
Первый урок мы начнем с детекта простых инжектов, для разколупывания которых, возьмем за основу навесные хуки. Читавшие статью об основной теории ссылка на которую указана выше, начинается дело с вхождения, с первого отклонения от нормы, от которого можно далее плясать.
Ставить эти хуки мы будем через MinHook, где брать и с чем жевать описано в моей давнешней теме про
>> модификацию процесса на старте << (Кликабельно)
Сделаем простую консольку с выводом данных.
Определим зависимости. Я назвал этот файл "Include.h"
Код:
#include <windows.h>
#include <iostream>
#include <string>
#include <clocale>
#include "shlobj.h"
#include <Psapi.h>
#pragma comment(lib, "Psapi.lib")
using namespace std;
Определяем прототипы в удобном месте:
Код:
typedef _Ret_maybenull_ HMODULE (WINAPI* _LoadLibraryA)(_In_ LPCSTR);
typedef _Ret_maybenull_ HMODULE(WINAPI* _LoadLibraryW)(_In_ LPCWSTR);
Откуда они берутся, эти прототипы? В случае с WinAPI на прямую из документации, они там же определены.
В иных случаях краткий экскурс описан в моей теме про >> Перехват данных << (Кликабельно)
Расписываем необходимое для работы и отсеивания системных модулей:
В иных случаях краткий экскурс описан в моей теме про >> Перехват данных << (Кликабельно)
Расписываем необходимое для работы и отсеивания системных модулей:
Код:
cDetour<_LoadLibraryA>* t_LoadLibraryA;
cDetour<_LoadLibraryW>* t_LoadLibraryW;
//для LoadLibraryA
string system32;
string syswow64;
//для LoadLibraryW
wstring system32w;
wstring syswow64w;
//разрядность
BOOL x64 = FALSE;
И наконец, пишем сами хуки:
LoadLibraryA:
LoadLibraryA:
Код:
_Ret_maybenull_ HMODULE WINAPI myLoadLibraryA(_In_ LPCSTR lpLibFileName)
{
auto hReturn = t_LoadLibraryA->GetTrampoline()(_In_ lpLibFileName);
//маин
if (hReturn == NULL)
return hReturn;
//модуль инфо
MODULEINFO moduleInfo { };
if (GetModuleInformation(GetCurrentProcess(), hReturn, &moduleInfo, sizeof(MODULEINFO)) == NULL)
{
printf("Last Error: %d\n", GetLastError());
}
//загружаемый файл
char patch[2048];
GetModuleFileNameA(hReturn, patch, 2048);
//обработка
DataCheckA(moduleInfo.lpBaseOfDll, moduleInfo.SizeOfImage, moduleInfo.EntryPoint, patch);
return hReturn;
}
LoadLibraryW: (с описанием, ибо 1 и те же комментарии заебусь писать)
Код:
_Ret_maybenull_ HMODULE WINAPI myLoadLibraryW(_In_ LPCWSTR lpLibFileName)
{
//сразу выполняем оригинал функции, но не возвращаем результат
//выполнения вызывающему коду пока не получим нужные данные!
auto hReturn = t_LoadLibraryW->GetTrampoline()(_In_ lpLibFileName);
//если main модуль (наше приложение)
if (hReturn == NULL)
return hReturn;
//получаем модульинфо
MODULEINFO moduleInfo{};
if (GetModuleInformation(GetCurrentProcess(), hReturn, &moduleInfo, sizeof(MODULEINFO)) == NULL)
{
printf("Last Error: %d\n", GetLastError());
}
//получаем путь к файлу
wchar_t patch[2048];
GetModuleFileNameW(hReturn, patch, 2048);
//передаем данные на обработку
DataCheckW(moduleInfo.lpBaseOfDll, moduleInfo.SizeOfImage, moduleInfo.EntryPoint, patch);
//возвращаем результат выполнения функции
return hReturn;
}
Расписываем DataCheck для работы с полученными данными:
Код:
void DataCheckA(LPVOID _base, DWORD _size, LPVOID _entryPoint, CHAR* _patch)
{
//Вот тут у нас уже есть данные о модуле, можем чекать
//Если ОС х64 разрядная системные дллки будут грузится из папки syswow64
if (x64)
{
//Если путь к длл не содержит путь к системному каталогу - длл не системная.
if (!strstr(_patch, syswow64.c_str()))
{
printf("\n detected x64, Start: 0x%X, size: 0x%X, Entry: 0x%X, patch: %s\n", _base, _size, _entryPoint, _patch);
}
}
else //Если х32 разрядная дллки будут грузится из папки system32
{
//Если путь к длл не содержит путь к системному каталогу - длл не системная.
//Так же можно проверять формат, является ли это длл? пример strstr(_patch, ".dll")
if (!strstr(_patch, system32.c_str()))
{
//Далее можно манипулировать дллкой
if (file_exitsA(_patch))
{
//Если у нас есть файл на жестком диске
//можем сделать его копию и швырнуть на сервер
//или же проверить наличие цифровой подписи. гугли по запросу winVerifyTrust
}
//И вот оно вхождение найдено, мы можем располагать данными,
//Точка входа, базовый адрес, размер
//Имея базовый адрес мы можем проверить PE/DOS заголовки модуля на валидность
//Как получить заголовки насилуй гугл. Пример: С++ RtlImageNtHeader.
//И это только минимум информации))
//именно тут расписано как пример
printf("\n detected x86, Start: 0x%X, size: 0x%X, Entry: 0x%X, patch: %s\n", _base, _size, _entryPoint, _patch);
}
}
}
//Далее по накатаной
void DataCheckW(LPVOID _base, DWORD _size, LPVOID _entryPoint, WCHAR* _patch)
{
if (x64)
{
if (!wcsstr(_patch, syswow64w.c_str()))
{
wprintf(L"\n detected x64, Start: 0x%X, size: 0x%X, Entry: 0x%X, patch: %s\n", _base, _size, _entryPoint, _patch);
}
}
else
{
if (!wcsstr(_patch, system32w.c_str()))
{
printf("\n detected x86, Start: 0x%X, size: 0x%X, Entry: 0x%X, patch: %s\n", _base, _size, _entryPoint, _patch);
}
}
}
И вот, 5 минутная мастурбация дала немного эффекта.
Точка входа для завершения пазла:
Точка входа для завершения пазла:
Код:
int main()
{
SetConsoleTitleA("yougame meme anti shit");
//шобэ могли писать на рускам, а то заибали везде инеглеш делать.
setlocale(LC_ALL, "");
//Для LoadLibraryA
char system_folder[MAX_PATH];
//получаем путь к папке виндавус.
SHGetSpecialFolderPathA(0, system_folder, CSIDL_WINDOWS, true);
//папки систем 32 и сисвов 64
system32 = std::string(system_folder) + "\\system32\\";
syswow64 = std::string(system_folder) + "\\syswow64\\";
//для LoadLibraryW
wchar_t system_folderw[MAX_PATH];
//получаем путь к папке виндавус.
SHGetSpecialFolderPathW(0, system_folderw, CSIDL_WINDOWS, true);
system32w = std::wstring(system_folderw) + L"\\system32\\";
syswow64w = std::wstring(system_folderw) + L"\\syswow64\\";
x64 = wow64();
HMODULE hKernel = GetModuleHandleA("kernel32.dll");
if (hKernel) {
auto& pContext = cContext::GetInstance();
auto dwAdress_LoadLibraryA = GetProcAddress(hKernel, "LoadLibraryA");
pContext.ApplyDetour<_LoadLibraryA>(
reinterpret_cast<_LoadLibraryA>(dwAdress_LoadLibraryA),
reinterpret_cast<_LoadLibraryA>(myLoadLibraryA),
&t_LoadLibraryA);
auto dwAdress_LoadLibraryW = GetProcAddress(hKernel, "LoadLibraryW");
pContext.ApplyDetour<_LoadLibraryW>(
reinterpret_cast<_LoadLibraryW>(dwAdress_LoadLibraryW),
reinterpret_cast<_LoadLibraryW>(myLoadLibraryW),
&t_LoadLibraryW);
}
printf("Start\n");
system("pause");
//Снимаем хуки на выходе
if (t_LoadLibraryA)
t_LoadLibraryA->Remove();
if (t_LoadLibraryW)
t_LoadLibraryW->Remove();
return 0;
}
Прикладные функции:
Код:
BOOL DirectoryExistsA(const std::string& dirName_in)
{
DWORD attribute = ::GetFileAttributesA(dirName_in.c_str());
if (attribute == INVALID_FILE_ATTRIBUTES)
return false; //путь не верный!
return (attribute & FILE_ATTRIBUTE_DIRECTORY);
}
BOOL DirectoryExistsW(const std::wstring& dirName_in)
{
DWORD attribute = ::GetFileAttributesW(dirName_in.c_str());
if (attribute == INVALID_FILE_ATTRIBUTES)
return false; //путь не верный!
return (attribute & FILE_ATTRIBUTE_DIRECTORY);
}
bool file_exitsA(const std::string& path)
{
return (GetFileAttributesA(path.c_str()) != 0xFFFFFFFF);
}
bool file_exitsW(const std::wstring& path)
{
return (GetFileAttributesW(path.c_str()) != 0xFFFFFFFF);
}
BOOL wow64()
{
BOOL ret;
IsWow64Process(GetCurrentProcess(), &ret);
return ret;
}
Само собой разумеется, это лишь соринка тех мер, которые нужны чтобы разьебать читодела. В дальнейшем опишу как это обойти, и как усложнить задачу с обходом.
После создания темы, добавлю опрос, на тему того что делать следующим.
Если че забыл уточнить спросите в коментах.
UD: для тех кто будет базарить за "ноп на проверке",
я уже описывал статью как >> проверять целестность кода <<
читы от васьки этот код детектить будет.
Если че забыл уточнить спросите в коментах.
UD: для тех кто будет базарить за "ноп на проверке",
я уже описывал статью как >> проверять целестность кода <<
Показано, как я инжекчу сторонний модуль и системный, на сторонний ругается, системный - не трогает.
Последнее редактирование: