앱스토어에 업로드된 앱은 모두 암호화되어 있다.
따라서 암호화되지 않은 앱은 애플에 의해 검수되지 않은 앱이라고 볼 수 있고 위험하다고 판단할 수 있다.구글에 검색하면 iOS 앱 분석을 위해 암호화된 Mach-O 파일을 복호화하는 방법을 많이 찾아볼 수 있으며, 복호화를 위한 자동화 툴도 다양하게 존재한다.
본 포스팅헤서는 암호화된 바이너리를 복호화하는 원리를 통해 암호화되지 않은 Mach-O 파일을 탐지하는 방법에 대해 다루려 한다.
(최대한 간단하게..)
먼저 Mach-O 파일의 구조를 확인하지 않을 수 없다.
전체적인 구조는 검색하면 찾아볼 수 있으니 지금은 확인이 필요한 부분에 대해서만 언급하겠다. (wikipedia, mach-o/loader.h)
0xFEEDFACE
) or 64-bit (0xFEEDFACF
)load command 구조체의 시작 0 바이트부터 8 바이트까지는 cmd 와 cmdsize 인자가 반드시 존재한다.
아래에 loader.h
파일에 있는 구조체의 일부를 가져왔으나 추가 확인 필요 시 헤더 파일을 확인해보면 된다.
struct segment_command_64 {
uint32_t cmd; /* LC_SEGMENT_64 */
uint32_t cmdsize; /* includes sizeof section_64 structs */
char segname[16]; /* segment name */
uint64_t vmaddr; /* memory address of this segment */
uint64_t vmsize; /* memory size of this segment */
uint64_t fileoff; /* file offset of this segment */
uint64_t filesize; /* amount to map from the file */
vm_prot_t maxprot; /* maximum VM protection */
vm_prot_t initprot; /* initial VM protection */
uint32_t nsects; /* number of sections in segment */
uint32_t flags; /* flags */
};
struct dyld_info_command {
uint32_t cmd; /* LC_DYLD_INFO or LC_DYLD_INFO_ONLY */
uint32_t cmdsize; /* sizeof(struct dyld_info_command) */
uint32_t rebase_off; /* file offset to rebase info */
uint32_t rebase_size; /* size of rebase info */
uint32_t bind_off; /* file offset to binding info */
uint32_t bind_size; /* size of binding info */
uint32_t weak_bind_off; /* file offset to weak binding info */
uint32_t weak_bind_size; /* size of weak binding info */
uint32_t lazy_bind_off; /* file offset to lazy binding info */
uint32_t lazy_bind_size; /* size of lazy binding infs */
uint32_t export_off; /* file offset to lazy binding info */
uint32_t export_size; /* size of lazy binding infs */
};
복호화의 핵심은 LC_ENCRYPTION_INFO
Command 이며 64비트의 경우 LC_ENCRYPTION_INFO_64
Command 로 존재한다.
해당 구조체 형태와 설명은 아래와 같다. (대부분의 앱은 64비트니까 64비트로 진행)
/*
* The encryption_info_command_64 contains the file offset and size of an
* of an encrypted segment (for use in x86_64 targets).
*/
struct encryption_info_command_64 {
uint32_t cmd; /* LC_ENCRYPTION_INFO_64 */
uint32_t cmdsize; /* sizeof(struct encryption_info_command_64) */
uint32_t cryptoff; /* file offset of encrypted range */
uint32_t cryptsize; /* file size of encrypted range */
uint32_t cryptid; /* which enryption system, 0 means not-encrypted yet */
uint32_t pad; /* padding to make this struct's size a multiple of 8 bytes */
};
cryptid
인자가 0 이라면 아직 암호화되지 않았다는 것을 의미한다.
따라서 이 값을 통해 현재 실행 파일의 암호화 유무를 확인할 수 있다.
위 내용을 정리하여 암호화되지 않은 Mach-O 파일을 탐지하는 방법은 아래와 같다.
연락하고 싶은데 혹시 가능하실까요