Jump to content
  • Flags de Depuração: NtGlobalFlag

       (0 reviews)

    paulosgf

    Introdução 

    Olá pessoal! Este é mais um artigo da série onde falo sobre técnicas de anti-engenharia reversa. Neles compartilho um pouco dos tutoriais práticos que desenvolvi ao longo das minhas pesquisas e estudos. No primeiro artigo, falei sobre a categoria de anti-debugging TLS Callback. Agora vou falar um pouco sobre as técnicas da categoria que utilizam flags de depuração do próprio processo para detectar o debugger. Antes de mais nada, vale entender o que são essas flags. 

     

    O que são flags de depuração?

    Estas flags são valores presentes dentro do espaço de endereço do processo, permanecendo na memória até o encerramento deste programa. A presença e/ou determinado valor destes bits podem indicar que o processo está em um ambiente de depurador. Como estas técnicas são válidas apenas para o ambiente Windows, seu significado e valores são definidos na documentação oficial do SO (WinAPI) [1], entretanto algumas flags podem não ser documentadas e, neste caso, somente se encontra informação em livros como o Windows Internals [2].

    A primeira que vamos analisar é a NtGlobalFlag, desenvolvida na época do antigo Windows NT. Esta flag é definida no cabeçalho do Process Environment Block (PEB) de todos processos no sistema e é usada especificamente para indicar se o processo está executando ou não em depurador.

    Antes de aprofundar nas particularidades desta flag, precisamos entender o que é a PEB, que foi citada anteriormente. De forma resumida, é uma estrutura que existe em cada processo do Windows e é apontada por outra estrutura chamada TEB (Thread Environment Block), que por sua vez contém informações em relação às threads do processo.

    O código da PEB é composto por uma struct e sua versão para 32 bits no header windows.h ou winternl.h é a seguinte:

    typedef struct _PEB { 
    
      BYTE                          Reserved1[2]; 
    
      BYTE                          BeingDebugged; 
    
      BYTE                          Reserved2[1]; 
    
      PVOID                         Reserved3[2]; 
    
      PPEB_LDR_DATA          Ldr; 
    
      PRTL_USER_PROCESS_PARAMETERS  ProcessParameters; 
    
      PVOID                         Reserved4[3]; 
    
      PVOID                         AtlThunkSListPtr; 
    
      PVOID                         Reserved5; 
    
      ULONG                         Reserved6; 
    
      PVOID                         Reserved7; 
    
      ULONG                         Reserved8; 
    
      ULONG                         AtlThunkSListPtr32; 
    
      PVOID                         Reserved9[45]; 
    
      BYTE                          Reserved10[96]; 
    
      PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; 
    
      BYTE                          Reserved11[128]; 
    
      PVOID                         Reserved12[1]; 
    
      ULONG                         SessionId; 
    
    } PEB, *PPEB;

    *O 3º byte desta estrutura é o campo BeingDebugged e este é definido pelo Windows para todo binário que está sendo executado, sendo 0 (padrão) para indicar que o processo não está sendo depurado e 1 para depurado. Este byte é avaliado na técnica abordada no Curso de Engenharia Reversa Online (CERO) através da função IsDebuggerPresent() e por conta disto esta técnica não será abordada neste artigo.

    A Aula 24 - Anti-debug, do CERO, aborda a PEB de forma prática. Uma referência completa sobre a PEB também pode ser acessada em [3].

    NtGlobalFlag

    Esta flag também é um campo da PEB e se encontra no offset 0x68 em ambientes 32 bits, ou offset 0xBC em 64 bits, contados a partir do seu início. Esta flag é usada para rastreamento e depuração de programas. Seu valor é 0 por padrão, indicando que não há depurador no ambiente.

    Caso se inicie o programa primeiro e depois de já iniciado, se analise seu processo no depurador, os campos da NtGlobalFlag não são alterados, deixando esta abordagem sem efeito. No entanto, caso se execute o programa diretamente  em um depurador, as seguintes flags serão definidas:    

    FLG_HEAP_ENABLE_TAIL_CHECK    (0x10)
    
        FLG_HEAP_ENABLE_FREE_CHECK    (0x20)
    
        FLG_HEAP_VALIDATE_PARAMETERS  (0x40)

     

    A presença de um depurador no ambiente é confirmada ao se verificar o valor 0x70 resultante da operação OR entre estas flags.

    Disassemble de processo 32 Bits:

    mov eax, fs:[30h]     // acessa a PEB no registrador de segmento
    
    mov al, [eax+68h]    // a partir da PEB acessa a flag NtGlobalFlag
    
    and al, 70h           // soma as flags FLG_HEAP_*
    
    cmp al, 70h           // verifica se o valor da soma é 0x70
    
    call  being_debugged  // caso positivo, avisa sobre depuração

     

    Disassemble de processo 64 Bits:

    mov rax, gs:[60h]     // acessa a PEB no registrador de segmento
    
    mov al, [rax+BCh]     // a partir da PEB acessa a flag NtGlobalFlag
    
    and al, 70h
    
    cmp al, 70h
    
    call  being_debugged

    Disassemble de processo WOW64 (64 Bits que aceita também 32 bits):

    mov eax, fs:[30h]     // acessa a PEB no registrador de segmento
    
    mov al, [eax+10BCh]   // a partir da PEB acessa a flag NtGlobalFlag
    
    and al, 70h
    
    cmp al, 70h
    
    call  being_debugged

     

    Código de exemplo:

    #include <windows.h>
    
    #include <iostream>
    
    using namespace std;
    
    
    
    // define o valor das flags
    
    #define FLG_HEAP_ENABLE_TAIL_CHECK   0x10
    
    #define FLG_HEAP_ENABLE_FREE_CHECK   0x20
    
    #define FLG_HEAP_VALIDATE_PARAMETERS 0x40
    
    // executa a operação OR entre o valor de todas as flags
    
    #define NT_GLOBAL_FLAG_DEBUGGED (FLG_HEAP_ENABLE_TAIL_CHECK | FLG_HEAP_ENABLE_FREE_CHECK | FLG_HEAP_VALIDATE_PARAMETERS)
    
    
    
    // se não for 64 bits
    
    #ifndef _WIN64
    
    PVOID pPeb = (PVOID)__readfsdword(0x30);    // PEB
    
    DWORD dwNtGlobalFlag = *(PDWORD)((PBYTE) pPeb + 0x68); // flag
    
    #else // o mesmo procedimento para 64 bits
    
    PVOID pPeb = (PVOID)__readgsqword(0x60);
    
    DWORD dwNtGlobalFlag = *(PDWORD)((PBYTE)pPeb + 0xBC);
    
    #endif // _WIN64
    
    
    
    // função que acusa depurador e sai
    
    void being_debugged()
    
    {
    
        std::cout << "Stop debugging program!" << std::endl;
    
        exit(-1);
    
    }
    
    
    
    int main()
    
    { // se em ambiente de depurador chama função de saída
    
        if (dwNtGlobalFlag & NT_GLOBAL_FLAG_DEBUGGED)
    
            being_debugged();
    
        eles  // senão segue normalmente
    
            std::cout << "Hello World!\n";
    
    
    
        return 0;
    
    }

    Desabilitando a Técnica

    Para desviar desta verificação, basta definir o campo NtGlobalFlag da estrutura PEB com 0 antes que este valor seja verificado pela proteção anti-depuração. Abaixo são alguns exemplos de como zerar esta flag:

    No x64dgb com o plugin ScyllaHide: 

    Plugins → ScyllaHide → Options -> NtGlobalFlag  [x]

     

    Manualmente no x64dbg:

    1. Ctrl+G → peb()+0x68 (32 bits) ou Ctrl+G → peb()+0xBC (64 bits)

    2. Trocar o valor do byte de 0x70 para zero

     

    No OllyDbg com o plugin Command Line:

    1. Plugins → Command Line →  Command Line

    2. dump fs:[30]+0x68 (32 bits) ou dump gs:[60]+0xBC (64 bits)

    3. No painel dump de memória selecionar o 1º byte → Binary → Fill with 00's

    *Também é possível usar o plugin Olly-Advanced 

     

    Bom, iniciei aqui uma nova categoria de técnicas Anti-Debug, a das flags de depuração, iniciando com a flag NtGlobalFlag. No próximo artigo vou falar sobre uma técnica que usa 2 flags em conjunto, a Heap Flags e a ForceFlags.

     

    Espero que tenham gostado. 

    Forte abraço & até o próximo!

     

    Referências:

    [1] https://docs.microsoft.com/en-us/windows/win32/apiindex/windows-api-list

    [2] https://docs.microsoft.com/en-us/sysinternals/resources/windows-internals

    [3] https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/pebteb/peb/index.htm

     



    User Feedback

    Join the conversation

    You can post now and register later. If you have an account, sign in now to post with your account.
    Note: Your post will require moderator approval before it will be visible.

    Guest

    • This will not be shown to other users.
    • Add a review...

      ×   Pasted as rich text.   Paste as plain text instead

        Only 75 emoji are allowed.

      ×   Your link has been automatically embedded.   Display as a link instead

      ×   Your previous content has been restored.   Clear editor

      ×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...