
Uma ferramenta para extrair informações de RTTI de executáveis Delphi, escrita em Python puro
Esta ferramenta examina um arquivo executável em busca de dados do Delphi, incluindo RTTI e tabelas de funções virtuais. Ela gera um arquivo JSON com informações sobre classes e funções identificadas, que pode ser usado para análises adicionais, por exemplo:
Um script IDAPython que pode carregar a saída no IDA é fornecido.
O script foi escrito para complementar outras ferramentas de engenharia reversa de Delphi.
Lançado como código aberto pela NCC Group Plc - http://www.nccgroup.com/
Desenvolvido por David Cannings (@edeca) [email protected]
http://www.github.com/nccgroup/pythia
Este projeto é lançado sob a licença AGPL. Consulte o arquivo LICENSE para mais informações.
O fluxo de alto nível é:
As vftables do Delphi são bem documentadas. Informações para a versão mais recente estão disponíveis na Embarcadero. Documentação não oficial está disponível para o Delphi 2005 (veja aqui).
O código-fonte do Free Pascal também é útil (espelho no Github).
O primeiro item em uma vftable é vmtSelfPtr, que aponta para o início da tabela de funções virtuais. O script examina cada segmento de código no arquivo PE em busca de qualquer local que aponte +0x4C bytes à frente. Observe que o compilador Delphi alinha as vftables em um limite de 4 bytes (para otimização).
Por exemplo, o seguinte VA 0x0046E1C8 contém o deslocamento 0x0046E214, que está 0x4C à frente do local atual. Como mostrado no IDA:
.text:0046E1C8 ; Classes::TComponent *vftable_TDCP_misty1
.text:0046E1C8 14 E2 46 00 vftable_TDCP_misty1 dd offset off_46E214
Essa abordagem pode gerar falsos positivos; portanto, outros campos da vftable são verificados em busca de valores plausíveis. Por exemplo, o vmtInstanceSize é verificado para garantir que não seja excessivo, e os ponteiros de função são verificados para garantir que estejam em uma seção executável. Durante os testes, a taxa de falsos positivos foi muito baixa, apesar do método de busca por força bruta.
Cada função encontrada em uma vftable é verificada para saber se é herdada da classe pai ou sobrescrita. O Delphi não suporta herança múltipla, então isso pode ser feito verificando o ponteiro na vftable da classe pai com o mesmo deslocamento.
Se ambos os ponteiros referenciam a mesma função, ela é herdada. Se o filho tiver um ponteiro diferente, então ela foi sobrescrita.
A saída principal da ferramenta é um arquivo JSON que pode ser alimentado em processamentos / ferramentas subsequentes. No entanto, alguns outros formatos de saída estão incluídos.
Use a opção --save-tree para gerar um arquivo como:
TObject (at 0x0040112c)
|-- Exception (at 0x004081f8)
| |-- EAbort (at 0x00408260)
| |-- EAbstractError (at 0x00408ad4)
| |-- EAssertionFailed (at 0x00408a74)
| |-- EBcdException (at 0x004bd110)
| | +-- EBcdOverflowException (at 0x004bd16c)
| |-- EBitsError (at 0x0041ab04)
| |-- EComponentError (at 0x0041abbc)
| |-- EConvertError (at 0x00408850)
| |-- EDCP_cipher (at 0x0046a0ac)
| | +-- EDCP_blockcipher (at 0x0046a29c)
| |-- EDCP_hash (at 0x00469f20)
.. etc ..
PACKAGEINFO ou DVCLAL) e ajustar a varredura para diferentes layouts de vftable.vmtTypeInfo na vftable)call [ecx+3Fh] a um método de instância)TComparer<System.Bindings.EvalProtocol.TPair<System.IInterface,System.Pointer>>, que são bastante indecifráveis no IDA.Por favor, envie-me exemplos de binários em que esta ferramenta não funciona, para que ela possa ser melhorada.