Я лучше тебя
-
Автор темы
- #1
Шалом.
Давненько не писал тем, ебался с детектами.
Щас распишу как сделать так, чтобы ваш поток был создан от имени другого модуля.
Допустим: Kernel32.dll
Для начала возьмем две простые функции для поисков простого паттерна.
Взял первое что попалось, подойдет.
Давненько не писал тем, ебался с детектами.
Щас распишу как сделать так, чтобы ваш поток был создан от имени другого модуля.
Допустим: Kernel32.dll
Для начала возьмем две простые функции для поисков простого паттерна.
Взял первое что попалось, подойдет.
Код:
BOOL CompareMem(const BYTE* pData, const BYTE* bMask, const char* szMask)
{
for (; *szMask; ++szMask, ++pData, ++bMask)
if (*szMask == 'x' && *pData != *bMask)
return false;
return (*szMask) == NULL;
}
DWORD FindPatternMem(DWORD dwAddress, DWORD dwLen, BYTE *bMask, char * szMask)
{
for (DWORD i = 0; i < dwLen; i++)
{
__try
{
if (CompareMem((BYTE*)(dwAddress + i), bMask, szMask))
{
return (DWORD)(dwAddress + i);
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return 0;
}
}
return 0;
}
Теперь перейдем к более сладкому.
Мы будем искать в нужном нам модуле, 7 пустых байт под наши инструкции.
Действо будет таким:
Мы будем искать в нужном нам модуле, 7 пустых байт под наши инструкции.
Действо будет таким:
- Находим 7 пустых байт.
- Записываем в них инструкцию call dword ptr [адресс нашей функции] + ret
- Вызываем CreateThread по адресу в который записали инструкцию.
- Фактически поток будет указывать на длл на которую мы хотим чтобы он указывал, при этом, выполняя наш код.
Код:
DWORD ScanAddressTable()
{
DWORD dwKernel32 = reinterpret_cast<DWORD>(GetModuleHandleW(L"kernel32.dll")); //Наш модуль, фактически может быть любым.
if (dwKernel32)
{
DWORD dwAddress = FindPatternMem(dwKernel32, 0x700000, (PBYTE)"\xCC\xCC\xCC\xCC\xCC\xCC\xCC", "xxxxxxx");
if (dwAddress)
{
return dwAddress;
}
DWORD dwAddress2 = FindPatternMem(dwKernel32, 0x700000, (PBYTE)"\x90\x90\x90\x90\x90\x90\x90", "xxxxxxx");
if (dwAddress2)
{
return dwAddress2;
}
}
return 0;
}
Теперь дописываем мелочи.
Патчинг памяти:
Патчинг памяти:
Код:
void WriteMemory(void *adr, void *ptr, int size)
{
DWORD OldProtection;
VirtualProtect(adr, size, PAGE_EXECUTE_READWRITE, &OldProtection);
memcpy(adr, ptr, size);
VirtualProtect(adr, size, OldProtection, &OldProtection);
}
Структура для хранения списка наших потоков и сам контейнер:
Код:
struct ThreadData
{
DWORD Adress;
void * func;
DWORD JumpAdress;
};
std::vector<ThreadData*> adress_list;
Расписываем создание потока:
Код:
HANDLE CreateThreadMemory(void * adress_func)
{
if (adress_func)
{
DWORD adress = ScanAddressTable();
if (adress) {
//с
CHAR ByteCode[] = "\xFF\x15\x00\x00\x00\x00\xC3";
ThreadData * threadData = new ThreadData();
threadData->Adress = adress;
threadData->func = adress_func;
threadData->JumpAdress = (DWORD)(adress_func);
*(DWORD*)(&ByteCode[2]) = (DWORD)(&threadData->JumpAdress);
WriteMemory((void*)adress, &ByteCode[0], 7);
adress_list.push_back(threadData);
return CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)adress, 0, 0, 0);
}
}
return NULL;
}
Создадим тестовый поток и выведем его айди через месадж бокс чтобы убедится что все сработало как надо:
Код:
DWORD WINAPI TestTherad(LPVOID)
{
std::string data = "айди потока: " + std::to_string(GetCurrentThreadId());
MessageBoxA(0, data.c_str(), "newThread", 0);
return 0;
}
int main()
{
CreateThreadMemory(reinterpret_cast<void*>(TestTherad));
system("pause");
return 0;
}
Открываем Process Hacker и сверяем айди потока с тем айдишником, который нам вывело.
Зависимости (для обезьянок):
Код:
#include <windows.h>
#include <vector>
#include <string>
using namespace std;