dylib 인젝션 방법 2가지
먼저 동적라이브러리 삽입 방식부터 다시 상기시켜 보자.
코드 인젝션 방법 2가지- 환경변수를 건드릴 수 있는 경우는 탈옥된 장치밖에 없으므로 환경변수 검사는 탈옥 장치에서만 유효하다.
- 라이브러리 삽입의 두번째 방법으로, IPA자체에 라이브러리를 포함시키고 re-sign하는 경우가 있었다.
탈옥,비탈옥 장치에서도 가능한 방법이며, Mach-O 헤더 자체를 라이브러리를 로드하도록 패치한 경우이므로 환경변수를 활용하지 않으므로 환경변수 검사로는 걸러지지 않는다.
라이브러리 탐지에 사용되는 함수
dyld 관련 함수들로 이상 동적라이브러리를 탐지한다.
- _dyld_image_count()
- _dyld_get_image_name()
현재 로드된 dylibs 개수와 이름 등을 조사하여 후킹 여부를 판단하는 것이다.
앱 자체 바이너리를 패치하지 않고는 일반적으로 후킹을 통해 각종 로직을 우회하므로 효과적인 탐지방법이 된다.
패치 자체가 dylib 삽입으로 진행되므로 공격자 입장에선 상당히 귀찮아진다.
1. 블랙박스 리스트 검사 — 비추천
#import <mach-o/dyld.h> //현재 메모리에 올라온 동적라이브러리 개수 파악 uint32_t count = _dyld_image_count(); //전체 라이브러리를 검사하며 MobileSubstrate.dylib가 있는지 검사 for(uint32_t i=0; i<count; ++i){ char* substrate = "Library/MobileSubstrate/MobileSubstrate.dylib"; //NSLog(@"%s", _dyld_get_image_name(i)); if(strcmp(_dyld_get_image_name(i), substrate)==0){ return YES; } }
우회
이름만 다르게 하면 되므로 그닥 추천되진 않음.
툴키드를 거르는 데에는 유용한 방식이 될 순 있다.
2. 화이트박스 리스트 검사 + 경로검증 — 추천
bool HKCheckWhitelist(){ //동적라이브러리 총 개수 int count = _dyld_image_count(); //모든 동적라이브러리 검사 for (int i = 0; i < count; i++) { //라이브러리 이름 받아옴. const char * imageName = _dyld_get_image_name(i); //화이트리스트에 명시된 라이브러리인지 + 라이브러리가 샌드박스 경로에서 온 건지 (BundleID는 매번 바뀌므로 Application/ 까지만 검사하는 것) if (!strstr(libraries, imageName)&&!strstr(imageName, "/var/containers/Bundle/Application")) { printf ("This library is not in the white list!!\n%s", imageName); return NO; } } return YES; }
int count = _dyld_image_count();
현재 앱에서 올라와 있는 dylib 파일의 총 개수를 반환받고, 이 횟수만큼 반복문을 돌리며 검사한다.
const char * imageName = _dyld_get_image_name(i);
: 현재 보고있는 라이브러리의 이름을 가져온다.
!strstr(libraries, imageName)
: 화이트박스에 명시된 라이브러리 중 하나인지 검사한다.
!strstr(imageName, "/var/containers/Bundle/Application")
: 라이브러리의 위치가 앱의 샌드박스 경로에서 온 것인지까지 검사한다.
: BundleID는 앱 설치 시마다 변경되므로 고정 경로까지만 검사하는 것.