이 도구는 RTTI 및 가상 기능 테이블을 포함하여 델파이 데이터 용 실행 파일을 스캔합니다. 식별 된 클래스 및 기능에 대한 정보가 포함 된 JSON 파일을 출력하여 추가 분석에 사용할 수 있습니다.
출력을 IDA에로드 할 수있는 idapython 스크립트가 제공됩니다.
이 스크립트는 리버스 엔지니어링 델파이를위한 다른 도구를 보완하기 위해 작성되었습니다.
NCC Group Plc -http://www.nccgroup.com/의 오픈 소스로 출시
David Cannings (@edeca) [email protected]에 의해 개발되었습니다
http://www.github.com/nccgroup/pythia
이 프로젝트는 AGPL 라이센스에 따라 릴리스됩니다. 자세한 내용은 라이센스를 참조하십시오.
높은 수준의 흐름은 다음과 같습니다.
Delphi Vftables는 잘 문서화되어 있습니다. 최신 버전에 대한 정보는 Embarcadero에서 제공됩니다. 비공식 문서는 Delphi 2005에서 사용할 수 있습니다 (여기 참조).
Free Pascal의 소스 코드도 유용합니다 (Github Mirror).
vftable의 첫 번째 항목은 vmtSelfPtr 이며 가상 기능 테이블의 시작을 가리 킵니다. 스크립트는 PE 파일의 각 코드 세그먼트를 앞으로 +0x4C 바이트를 가리키는 모든 위치에 대해 스캔합니다. 델파이 컴파일러는 vftables를 4 바이트 경계 (최적화)로 정렬합니다.
예를 들어, 다음 va 0x0046E1C8 에는 오프셋 0x0046E214 포함되며, 이는 현재 위치보다 0x4C 입니다. IDA에 표시된대로 :
.text:0046E1C8 ; Classes::TComponent *vftable_TDCP_misty1
.text:0046E1C8 14 E2 46 00 vftable_TDCP_misty1 dd offset off_46E214
이 접근법은 잘못된 양성을 생성 할 수 있으므로 vftable의 다른 필드는 현명한 값을 확인합니다. 예를 들어 vmtInstanceSize 는 과도하지 않도록 확인하고 기능 포인터가 실행 파일 섹션에있는 것으로 확인되었습니다. 테스트하는 동안 무차별 인력 검색 방법에도 불구하고 잘못된 양의 속도는 매우 낮았습니다.
VFTable에서 발견 된 각 기능은 부모로부터 상속되었는지 또는 과부하 된 지 확인하기 위해 확인됩니다. Delphi는 다중 상속을 지원하지 않으므로 동일한 오프셋으로 Parent Vftable의 포인터를 확인하여 달성 할 수 있습니다.
두 포인터가 동일한 함수를 참조하면 상속됩니다. 아이가 다른 포인터를 가지고 있다면 과부하가 발생했습니다.
이 도구의 기본 출력은 후속 처리 / 도구로 공급 될 수있는 JSON 파일입니다. 그러나 몇 가지 다른 출력 형식이 포함되어 있습니다.
--save-tree 옵션을 사용하여 다음과 같은 파일을 생성하십시오.
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 또는 DVCLAL Resource에서)을 식별하고 다양한 vftable 레이아웃에 대한 스캔을 조정하십시오.call [ecx+3Fh] 은 인스턴스 메소드)TComparer<System.Bindings.EvalProtocol.TPair<System.IInterface,System.Pointer>> 와 같은 이름을 사용합니다.이 도구가 작동하지 않는 바이너리의 예를 보내 주시면 개선 될 수 있습니다.