
순수 Python으로 작성된 Delphi 실행 파일에서 RTTI 정보를 추출하는 도구
이 도구는 실행 파일에서 RTTI 및 가상 함수 테이블을 포함한 Delphi 데이터를 스캔합니다. 식별된 클래스와 함수에 대한 정보가 담긴 JSON 파일을 출력하며, 이는 추가 분석에 사용할 수 있습니다. 예를 들어:
출력 결과를 IDA에 로드할 수 있는 IDAPython 스크립트가 제공됩니다.
이 스크립트는 Delphi 리버스 엔지니어링을 위한 다른 도구들을 보완하기 위해 작성되었습니다.
NCC Group Plc가 오픈 소스로 공개했습니다 - http://www.nccgroup.com/
개발: David Cannings(@edeca) [email protected]
http://www.github.com/nccgroup/pythia
이 프로젝트는 AGPL 라이선스로 배포됩니다. 자세한 내용은 LICENSE를 참조하세요.
전체적인 흐름은 다음과 같습니다:
Delphi vftable은 잘 문서화되어 있습니다. 최신 버전에 대한 정보는 Embarcadero에서 확인할 수 있습니다. Delphi 2005용 비공식 문서도 제공됩니다(여기 참조).
Free Pascal의 소스 코드도 유용합니다(Github 미러).
vftable의 첫 번째 항목은 vmtSelfPtr이며, 이는 가상 함수 테이블의 시작을 가리킵니다. 스크립트는 PE 파일의 각 코드 세그먼트에서 +0x4C 바이트 앞을 가리키는 위치를 스캔합니다. 참고로 Delphi 컴파일러는 vftable을 4바이트 경계에 정렬합니다(최적화 목적).
예를 들어, 다음 VA 0x0046E1C8에는 현재 위치에서 0x4C 앞인 오프셋 0x0046E214가 포함되어 있습니다. IDA에 표시된 대로:
.text:0046E1C8 ; Classes::TComponent *vftable_TDCP_misty1
.text:0046E1C8 14 E2 46 00 vftable_TDCP_misty1 dd offset off_46E214
이 방식은 오탐(false positive)을 생성할 수 있으므로, vftable의 다른 필드가 합리적인 값을 가지는지 확인합니다. 예를 들어 vmtInstanceSize가 과도하게 크지 않은지 확인하고, 함수 포인터가 실행 가능한 섹션에 있는지 검증합니다. 테스트 중 오탐 발생률은 무차별 검색 방식임에도 불구하고 매우 낮았습니다.
vftable에서 발견된 각 함수는 부모로부터 상속되었는지 아니면 오버로드되었는지 확인합니다. Delphi는 다중 상속을 지원하지 않으므로, 부모 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 리소스)을 식별하고 다양한 vftable 레이아웃에 맞게 스캔을 조정합니다.call [ecx+3Fh]를 인스턴스 메서드와 매칭)TComparer<System.Bindings.EvalProtocol.TPair<System.IInterface,System.Pointer>>와 같은 이름을 사용하며, 이는 IDA에서 상당히 해독하기 어렵습니다.이 도구가 작동하지 않는 바이너리 예시를 보내주시기 바랍니다. 개선에 도움이 됩니다.