Как защитить ?
Скорей просто защита от ав, не пускать же просто голый только что скомпиленный файлПо-разному, мне кажется, что ответ на этот вопрос будет тянуть на целую статью.
Но если в кратце, то виртуализация и обфускация для анализа.
Для антидебага существует множество техник. Все они конечно обходятся дефолтными плагинами того же х64дбг, но там есть свои варианты, как сделать так, чтобы не обходили.
Тут необходимо задаваться вопросом от кого ты защититься пытаешься?
Аверам скорее всего не надо полностью реверсить твой файл, если это что-то типа обычного троя. Вот если это условный итв 0дэй, то да, будет полный реверс.
Если ты пытаешься защититься от человека, который намеренно пытается именно зареверсить полностью, то равно или поздно он всё равно зареверсит. Тут все способы просто сделают его работу сложнее и дольше.
Если длл заинжекчена мануал мапом, то не будет находиться.GetModuleHandleA
Если готовое, то обфускатор на llvm. Но там есть чуток детектов.Или заюзать уже готовое хотяб для начала по типу темиды ?
Я тебе так скажу у меня обход авера патчем 2х байтов в дллке винды и не сносит на рантайме exeЕсли длл заинжекчена мануал мапом, то не будет находиться.
Если готовое, то обфускатор на llvm. Но там есть чуток детектов.
Ты уточнил, что это нужно для защиты от аверов. Скажу тебе, что аверам в большинстве случаев поебать какие у тебя там сигнатуры.
Сигнатурный детект обходится всем чем можно. (хотя его тоже можно разделить на 2 стадии: когда сканят файл на диске и когда его сканят в памяти после распаковки). Обход: пакеры, протекторы, обфускаторы, морферы.
Есть поведенческий детект. Это просто вызовы функций в нужной последовательности с нужными параметрами. Если есть поведенческий детект, то уже без разницы какая у тебя там сигнатура)
От поведенческого детекта спасёт, наверное, только редактирование кода, либо разбавление его каким-то мусором с вызовами хукнутых апи функций, чтобы прервать цепочку вызовов, которые влекут детект.
Само собой есть техники, которые позволяют обойти хуки авера и использовать задетекченную цепочку вызовов, но информации по этому поводу мало.
Кроме, конечно, говно техники с установкой хардварного бряка на сисколе))))) Почему говно не буду говорить, потому что и так уже много букв написал. Но чтобы понять почему достаточно немного потестить на каких-то проектах, где есть многопоток
Пакеры ав любой вскроет как нехуй делатьЕсли длл заинжекчена мануал мапом, то не будет находиться.
Если готовое, то обфускатор на llvm. Но там есть чуток детектов.
Ты уточнил, что это нужно для защиты от аверов. Скажу тебе, что аверам в большинстве случаев поебать какие у тебя там сигнатуры.
Сигнатурный детект обходится всем чем можно. (хотя его тоже можно разделить на 2 стадии: когда сканят файл на диске и когда его сканят в памяти после распаковки). Обход: пакеры, протекторы, обфускаторы, морферы.
Есть поведенческий детект. Это просто вызовы функций в нужной последовательности с нужными параметрами. Если есть поведенческий детект, то уже без разницы какая у тебя там сигнатура)
От поведенческого детекта спасёт, наверное, только редактирование кода, либо разбавление его каким-то мусором с вызовами хукнутых апи функций, чтобы прервать цепочку вызовов, которые влекут детект.
Само собой есть техники, которые позволяют обойти хуки авера и использовать задетекченную цепочку вызовов, но информации по этому поводу мало.
Кроме, конечно, говно техники с установкой хардварного бряка на сисколе))))) Почему говно не буду говорить, потому что и так уже много букв написал. Но чтобы понять почему достаточно немного потестить на каких-то проектах, где есть многопоток
ну кстати не совсем. Условно есть самопальный пакер, который берет ключ для расшифровки данных с сервера. Обычно в песочницах инет не работает -> распаковать нельзя.Пакеры ав любой вскроет как нехуй делать
Не, самое пиздатое это когда твоя программа создает виртуальную среду и в ней выполняется в зашифрованном виде. Или просто запрещает системе к ней доступ.ну кстати не совсем. Условно есть самопальный пакер, который берет ключ для расшифровки данных с сервера. Обычно в песочницах инет не работает -> распаковать нельзя.
Но в целом я согласен, что пакер это херня. Вот пакер с виртуализацией это уже другое дело
Если говорить о винде, то всякие касперские и авасты находятся на kernel уровне и просто "запретить системе к ней доступ" невозможноНе, самое пиздатое это когда твоя программа создает виртуальную среду и в ней выполняется в зашифрованном виде. Или просто запрещает системе к ней доступ.
#include <windows.h>
#include <string.h>
#include <wchar.h>
#include <tlhelp32.h>
#include <stdio.h>
DWORD g_dwDebuggerProcessId = -1;
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM dwProcessId)
{
DWORD dwWindowProcessId;
GetWindowThreadProcessId(hwnd, &dwWindowProcessId);
if (dwProcessId == dwWindowProcessId)
{
int windowTitleSize = GetWindowTextLengthW(hwnd);
if ( windowTitleSize <= 0 )
{
return TRUE;
}
wchar_t* windowTitle = (wchar_t*)malloc((windowTitleSize + 1) * sizeof(wchar_t));
GetWindowTextW(hwnd, windowTitle, windowTitleSize + 1);
if (wcsstr(windowTitle, L"dbg") != 0 ||
wcsstr(windowTitle, L"debugger") != 0 )
{
g_dwDebuggerProcessId = dwProcessId;
return FALSE;
}
return FALSE;
}
return TRUE;
}
DWORD IsDebuggerProcess(DWORD dwProcessId)
{
EnumWindows(EnumWindowsProc, (LPARAM)dwProcessId);
return g_dwDebuggerProcessId == dwProcessId;
}
DWORD SuspendDebuggerThread()
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
{
printf("Failed to create snapshot\n");
return 1;
}
THREADENTRY32 te32;
te32.dwSize = sizeof(THREADENTRY32);
if (!Thread32First(hSnapshot, &te32))
{
printf("Failed to get first thread\n");
CloseHandle(hSnapshot);
return 1;
}
do
{
HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION | THREAD_SUSPEND_RESUME, FALSE, te32.th32ThreadID);
if (hThread != NULL)
{
DWORD dwProcessId = GetProcessIdOfThread(hThread);
if ( IsDebuggerProcess(dwProcessId) )
{
printf("Debugger found with pid %i! Suspending!\n", dwProcessId);
DWORD result = SuspendThread(hThread);
if ( result == -1 )
{
printf("Last error: %i\n", GetLastError());
}
}
CloseHandle(hThread);
}
} while (Thread32Next(hSnapshot, &te32));
CloseHandle(hSnapshot);
return 0;
}
int main(void)
{
SuspendDebuggerThread();
printf("12333");
getchar();
}
на самом деле в таком треде единственный правильный ответ. Крякуют виндусы и фотожопы, а крякнуть какой-то мутный софт - дел на пару дней.Тебя всё равно крякнут, просто делай софт которому нужна постоянная поддержка, хоть на подписке "пару дошиков" намутишь.
BOOL IsIntelHardwareBreakpointPresent(VOID)
{
BOOL bFlag = FALSE;
PCONTEXT Context = NULL;
Context = (PCONTEXT)VirtualAlloc(NULL, sizeof(CONTEXT), MEM_COMMIT, PAGE_READWRITE);
if (Context == NULL)
return FALSE;
RtlZeroMemory(Context, sizeof(Context));
Context->ContextFlags = CONTEXT_DEBUG_REGISTERS;
if (!GetThreadContext(GetCurrentThreadNoForward(), Context))
goto EXIT_ROUTINE;
if (Context->Dr0 || Context->Dr1 || Context->Dr2 || Context->Dr3)
bFlag = TRUE;
EXIT_ROUTINE:
if (Context)
VirtualFree(Context, 0, MEM_RELEASE);
return bFlag;
}
BOOL IsDebuggerPresentEx(VOID)
{
return GetPeb()->BeingDebugged;
}
BOOL CheckRemoteDebuggerPresent2(_In_ HANDLE hHandle, _Inout_ PBOOL pbDebuggerPresent)
{
NTQUERYINFORMATIONPROCESS NtQueryInformationProcess = NULL;
NTSTATUS Status = 0;
DWORD dwProcessDebugPort = 0, dwReturnValue = 0;
*pbDebuggerPresent = FALSE;
if (hHandle == NULL)
return FALSE;
HMODULE hModule = GetModuleHandleW(L"ntdll.dll");
if (hModule == NULL)
return FALSE;
NtQueryInformationProcess = (NTQUERYINFORMATIONPROCESS)GetProcAddressA((DWORD64)hModule, "NtQueryInformationProcess");
if (!NtQueryInformationProcess)
return FALSE;
Status = NtQueryInformationProcess(hHandle, ProcessDebugPort, &dwProcessDebugPort, sizeof(DWORD), &dwReturnValue);
if (NT_SUCCESS(Status) && dwProcessDebugPort == -1)
return TRUE;
*pbDebuggerPresent = TRUE;
NtQueryInformationProcess = NULL;
return TRUE;
}
BOOL AdfOpenProcessOnCsrss(VOID)
{
HMODULE hNtdll = NULL;
CSRGETPROCESSID CsrGetProcessId = NULL;
HANDLE hCsrHandle = NULL;
hNtdll = GetModuleHandleW(L"ntdll.dll");
if (hNtdll == NULL)
return FALSE;
CsrGetProcessId = (CSRGETPROCESSID)GetProcAddressA((DWORD64)hNtdll, "CsrGetProcessId");
if (CsrGetProcessId == NULL)
return FALSE;
hCsrHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, CsrGetProcessId());
if (hCsrHandle == NULL)
return FALSE;
if (hCsrHandle)
CloseHandle(hCsrHandle);
CsrGetProcessId = NULL;
return TRUE;
}
There's no real point in allocating a memory page for the context with VirtualAlloc, you'd better allocate it on the stack or the heap.Context = (PCONTEXT)VirtualAlloc