
Script Python do IDA para desofuscar a DLL injetora Astaroth/Guildma
Script Python para IDA para desofuscar a DLL injetora Astaroth/Guildma
Ao tentar analisar a DLL injetora de uma campanha recente do Astaroth/Guildma (graças a este diário do SANS ISC), deparei-me com uma tentativa realmente irritante de ofuscação.
Uma função (que chamei de time_waster_3000 na imagem abaixo) é chamada mais de 1.000 vezes (!!!) em toda a DLL. Essa função recebe seis strings hardcoded como argumentos, juntamente com uma word aleatória. A função em si é um labirinto de aritmética que, pelo que pude perceber, não serve a nenhum propósito prático (além de desperdiçar o tempo de um reverser). Veja como a DLLEntry fica com essas chamadas irritantes no lugar:
O objetivo deste script Python para IDA é ocultar todos os blocos de código que envolvem uma chamada a essa função inútil, bem como seus argumentos. Veja como a DLLEntry fica depois que o script é executado:
O script funciona encontrando uma chamada para a função de preenchimento, representada por call sub_CHANGEME no script. Portanto, você precisa renomeá-la no script com o nome da função encontrado na amostra com a qual está lidando. Por exemplo, alterando idc.print_operand(x, 0) == 'sub_CHANGEME' para idc.print_operand(x, 0) == 'sub_431000'.
Escolhi iterar sobre a instrução call sub_CHANGEME em vez de iterar sobre os pushes de argumentos. A razão é simples: as strings hardcoded estão presentes em vários lugares do binário; portanto, quando tentei buscar por instruções push envolvendo os offsets dessas strings, o script não encontrava todas as instâncias desses dados inúteis.
O script costumava funcionar ocultando cada instância da passagem de argumentos e da chamada à função de preenchimento como um bloco recolhido. Como a função é chamada várias vezes seguidas, isso resultava em enormes espaços em branco na visão do disassembly. Atualizei-o para ocultar instâncias sequenciais desse preenchimento em um único bloco recolhido, o que realmente melhora a legibilidade.