Skip to content
KitploitKITPLOIT
FerramentasBlog
Log in
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
hwbp4mw — Mecanismo de hooking por hardware breakpoints para Windows que utiliza registradores de depuração para realizar hooks em funções, contornar ETW/AMSI e evadir o monitoramento de EDR em user-land. | Kitploit
Ferramentas/GitHubGitHub/rad9800/hwbp4mw
Evasão de IDS/IPSDepuradoresPós-ExploraçãoRed TeamingAtaque Adversário
GitHubrad9800/hwbp4mw

hwbp4mw

Mecanismo de hooking por hardware breakpoints para Windows que utiliza registradores de depuração para realizar hooks em funções, contornar ETW/AMSI e evadir o monitoramento de EDR em user-land.

Ver Repositório
2735419há 3 anosRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

Este artigo foi originalmente para a VX-Underground Black Mass Halloween Edition 2022.

Mecanismos de Hooking:

  • Mecanismo de hooking hwbp x86/x64 seguro para multi-thread c
  • Biblioteca de Breakpoints PAGE_GUARD/hwbp c++20
  • Biblioteca hwbp (exemplo de DLL) c++20

Técnica genérica de evasão em userland x64 utilizando registradores de depuração:

  • TamperingSyscalls2 c
  • TamperingSyscalls2 c++20

Exemplos de hooks ETW/AMSI disponíveis

  • rad9800/misc

Breakpoints de Hardware para Malware v 1.0

Nossa tarefa é hookar funções trivialmente e desviar o fluxo de código conforme necessário e, finalmente, remover o hook quando ele não for mais necessário.

Não podemos recorrer à aplicação de hooks de IAT, pois nem sempre são chamados e, portanto, não são confiáveis. Inline hooking é uma técnica poderosa; no entanto, requer que apliquemos um patch na memória onde o código reside. É uma técnica poderosa, mas ferramentas como PE-Sieve e Moneta conseguem distinguir a diferença entre a cópia do módulo residente na memória e a versão em disco e sinalizar isso. Isso nos deixa com a ferramenta perfeita para o trabalho: Registradores de Depuração, embora sejam bastante subestimados por autores de malware!```c CONTEXT context = { .ContextFlags = CONTEXT_DEBUG_REGISTERS }; GetThreadContext(thd, &context);

// set our debug information in the Dr registers

SetThreadContext(thd, &context);
Existem 8 registradores de depuração (Debug registers), de Dr0 até Dr7. Os que nos interessam são apenas
Dr0-3, onde armazenamos endereços nos quais gostaríamos de interromper (break), e Dr6 é apenas o status de
depuração. O mais importante é Dr7, que descreve as condições de breakpoints nas quais o processador
lançará uma exceção. Existem várias limitações ao usar registradores de depuração,
como um número limitado (4) e a não aplicação a todas as threads/threads recém-criadas.
Vamos procurar resolver algumas dessas limitações!

Quando a exceção é lançada, ela procurará por um tratador de exceção (exception handler) que podemos definir
e registrar em nosso programa [1]. Em nosso tratador de exceção definido, queremos que nosso código
associado (diferentes fluxos de código) seja executado quando o breakpoint correspondente for disparado.```c
LONG WINAPI ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
{
	if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP)
	{
		// Look for our associated code flow relative to our RIP 
		if (HWBP_ADDRESS_MAP.contains(ExceptionInfo->ContextRecord->Rip)) {
			HWBP_ADDRESS_MAP.at(ExceptionInfo->ContextRecord->Rip).func(ExceptionInfo);
			return EXCEPTION_CONTINUE_EXECUTION;
		}
	}
	return EXCEPTION_CONTINUE_SEARCH;
}

Isso é alcançado por uma função construtora que define o mapeamento entre uma função lambda "callback" e um endereço. using EXCEPTION_FUNC = std::function <void(PEXCEPTION_POINTERS)>;```c typedef struct { UINT pos; EXCEPTION_FUNC func; } HWBP_CALLBACK;

// Global std::unordered_map<uintptr_t, HWBP_CALLBACK> HWBP_ADDRESS_MAP{ 0 };

// Create our mapping HWBP_ADDRESS_MAP[address].func = function; HWBP_ADDRESS_MAP[address].pos = pos;

Precisamos iterar por todos os threads dos nossos processos e definir os ajustes correspondentes ao
contexto para eles. Isso pode ser alcançado usando as funções auxiliares do ToolHelp32:
CreateToolhelp32Snapshot e Thread32Next. Isso não é nada sofisticado, mas aborda uma
das nossas limitações de não anexar a todos os threads.```c
VOID SetHWBPS(const uintptr_t address, const UINT pos, const bool init = true)
{
	DWORD pid{ GetCurrentProcessId() };
	HANDLE h{ CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0) };
	if (h != INVALID_HANDLE_VALUE) {
		THREADENTRY32 te{ .dwSize = sizeof(THREADENTRY32) };
		if (Thread32First(h, &te)) {
			do {
				if ((te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
					sizeof(te.th32OwnerProcessID)) && te.th32OwnerProcessID == pid) {

					HANDLE thd = OpenThread(THREAD_ALL_ACCESS, FALSE, te.th32ThreadID);
					if (thd != INVALID_HANDLE_VALUE) {
						SetHWBP(thd, address, pos, init);
						CloseHandle(thd);
					}
				}
				te.dwSize = sizeof(te);
			} while (Thread32Next(h, &te));
		}
		CloseHandle(h);
	}
}

Ter breakpoints de hardware definidos é, sem dúvida, suspeito, pois podem indicar atividade maliciosa (embora nenhum EDR, que eu saiba, os procure ativamente). Eles podem ser usados contra nós como um possível IoC, então devemos remover seus rastros depois de terminarmos de usá-los.

Podemos implementar isso na nossa função de desconstrução!! Isso irá iterar por todas as threads e verificar se o registrador (&context.Dr0)[pos] aponta para o endereço no qual definimos inicialmente o breakpoint de hardware (pos é apenas um índice % 4 que nos dá acesso a context.Dr0-Dr3). Também podemos remover as condições necessárias no registrador Dr7. Devemos também lembrar de remover nossa entrada de mapeamento. Portanto, nosso breakpoint de hardware estará presente apenas pelo tempo necessário!```c SetHWBPS(address, pos, false); HWBP_ADDRESS_MAP.erase(address);

Um exemplo de breakpoint de hardware seria Sleep, onde apenas substituímos a duração do sleep
por 0.```c
HWBP HWBPSleep{ (uintptr_t)&Sleep, 0,	// Set Dr 0 
	([&](PEXCEPTION_POINTERS ExceptionInfo) {
		ExceptionInfo->ContextRecord->Rcx = 0;
		ExceptionInfo->ContextRecord->EFlags |= (1 << 16);	// continue execution
}) };

Sabemos que é preciso definir RCX devido à convenção de chamada fast-call de quatro registradores do Windows x64[1]. O primeiro argumento do construtor é o endereço onde interromper, o segundo é em qual registrador Dr0- 3 para armazenar (observe que só podemos ter 4 endereços para interromper por vez), e o terceiro é uma função lambda que capturará por referência PEXCEPTION_POINTERS que é a informação que um manipulador de exceções receberá. Isso, em última análise, nos permitirá controlar o fluxo de um programa de forma diferente dependendo de qual ponto de interrupção foi acionado.

Quando uma nova thread é criada, ela não herda o conjunto associado de Debug Registers a menos que consigamos, de alguma forma, interceptar a criação de uma nova thread! Um truque interessante que podemos usar seria capturar o endereço inicial real e desviar a nova thread para criar nossa própria thread. A maioria das novas threads acaba chamando NtCreateThreadEx.```c // Global Variable PVOID START_THREAD{ 0 };

Baixar ferramenta