iOS에서
task_info
함수를 통해 안티 디버깅, 메모리 보호 기능을 수행하는 보안 솔루션을 분석했다.
task_info
함수는 iOS 에서 메모리 정보를 가져올 수 있는 함수인데, 두번째 인자에 따라 얻어오는 정보가 달라진다.본 포스팅에서 탐지 및 우회하는 방법은 다루지 않고,
task_info
함수의 결과 값이KERN_SUCCESS
일 때 세팅되는 info 구조체에 대해 정리할 예정이다.시작에 앞서
task_info
함수의 리턴 값 및 파라미터 정보는 아래와 같다.kern_return_t task_info ( task_t task, task_flavor_t flavor, task_info_t task_info, mach_msg_type_number_t task_info_count );
그럼 이제 가보자잇~
TASK_DYLD_INFO
는 현재 메모리에 로드된 동적 라이브러리 관련 상수이며 해당 값이 두 번째 인자에 들어가면 세팅되는 info 구조체는 아래와 같다.
#define TASK_DYLD_INFO 17
struct task_dyld_info {
mach_vm_address_t all_image_info_addr;
mach_vm_size_t all_image_info_size;
integer_t all_image_info_format;
};
여기서 all_image_info_addr
멤버 변수는 dyld_all_image_infos
구조체이며, 구조는 아래와 같다.
struct dyld_all_image_infos {
uint32_t version; /* 1 in Mac OS X 10.4 and 10.5 */
uint32_t infoArrayCount;
const struct dyld_image_info* infoArray;
dyld_image_notifier notification;
bool processDetachedFromSharedRegion;
/* the following fields are only in version 2 (Mac OS X 10.6, iPhoneOS 2.0) and later */
bool libSystemInitialized;
const struct mach_header* dyldImageLoadAddress;
/* the following field is only in version 3 (Mac OS X 10.6, iPhoneOS 3.0) and later */
void* jitInfo;
/* the following fields are only in version 5 (Mac OS X 10.6, iPhoneOS 3.0) and later */
const char* dyldVersion;
const char* errorMessage;
uintptr_t terminationFlags;
/* the following field is only in version 6 (Mac OS X 10.6, iPhoneOS 3.1) and later */
void* coreSymbolicationShmPage;
/* the following field is only in version 7 (Mac OS X 10.6, iPhoneOS 3.1) and later */
uintptr_t systemOrderFlag;
/* the following field is only in version 8 (Mac OS X 10.7, iPhoneOS 3.1) and later */
uintptr_t uuidArrayCount;
const struct dyld_uuid_info* uuidArray; /* only images not in dyld shared cache */
/* the following field is only in version 9 (Mac OS X 10.7, iOS 4.0) and later */
struct dyld_all_image_infos* dyldAllImageInfosAddress;
/* the following field is only in version 10 (Mac OS X 10.7, iOS 4.2) and later */
uintptr_t initialImageCount;
/* the following field is only in version 11 (Mac OS X 10.7, iOS 4.2) and later */
uintptr_t errorKind;
const char* errorClientOfDylibPath;
const char* errorTargetDylibPath;
const char* errorSymbol;
/* the following field is only in version 12 (Mac OS X 10.7, iOS 4.3) and later */
uintptr_t sharedCacheSlide;
};
여기서 infoArray
멤버 변수는 dyld_image_info
구조체이며, 구조는 아래와 같다.
struct dyld_image_info {
const struct mach_header* imageLoadAddress; /* base address image is mapped into */
const char* imageFilePath; /* path dyld used to load the image */
uintptr_t imageFileModDate; /* time_t of image file */
/* if stat().st_mtime of imageFilePath does not match imageFileModDate, */
/* then file has been modified since dyld loaded it */
};
Frida 에서 사용할 수 있도록 삭 정리해두자.
Interceptor.attach(Module.findExportByName(null, 'task_info'), {
onEnter: function(args) {
this.flavor = args[1].toInt32();
this.info = args[2];
},
onLeave: function(retval) {
if(this.flavor == 17) {
// console.log('[-] task_dyld_info : ' + this.info);
var dyld_all_image_infos = this.info.readPointer();
// console.log('[-] dyld_all_image_infos : ' + dyld_all_image_infos);
var infoArrayCount = dyld_all_image_infos.add(4).readInt();
var infoArray = dyld_all_image_infos.add(8).readPointer();
// console.log('[-] infoArrayCount : ' + infoArrayCount);
for(var i=0; i<infoArrayCount; i++) {
var imageFilePath = infoArray.add(8).add(i*24).readPointer();
console.log('[-] imageFilePath : ' + imageFilePath.readUtf8String());
}
}
}
});
TASK_EXTMOD_INFO
는 현재 삽입된 쓰레드나 하이재킹된 프로세스 관련 상수이며 해당 값이 두 번째 인자에 들어가면 세팅되는 info 구조체는 아래와 같다.
#define TASK_EXTMOD_INFO 19
struct task_extmod_info {
unsigned char task_uuid[16];
vm_extmod_statistics_data_t extmod_statistics;
};
여기서 extmod_statistics
멤버 변수는 vm_statistics
구조체이며, 구조는 아래와 같다.
struct vm_extmod_statistics {
int64_t task_for_pid_count; /* # of times task port was looked up */
int64_t task_for_pid_caller_count; /* # of times this task called task_for_pid */
int64_t thread_creation_count; /* # of threads created in task */
int64_t thread_creation_caller_count; /* # of threads created by task */
int64_t thread_set_state_count; /* # of register state sets in task */
int64_t thread_set_state_caller_count; /* # of register state sets by task */
} __attribute__((aligned(8)));
마찬가지로 Frida 에서 사용할 수 있도록 삭 정리해두자.
Interceptor.attach(Module.findExportByName(null, 'task_info'), {
onEnter: function(args) {
this.flavor = args[1].toInt32();
this.info = args[2];
},
onLeave: function(retval) {
if(this.flavor == 19) {
// console.log('[-] task_extmod_info : ' + this.info);
var vm_extmod_statistics = this.info.add(16);
var task_for_pid_count = vm_extmod_statistics;
var task_for_pid_caller_count = vm_extmod_statistics.add(8);
var thread_creation_count = vm_extmod_statistics.add(16);
var thread_creation_caller_count = vm_extmod_statistics.add(24);
var thread_set_state_count = vm_extmod_statistics.add(32);
var thread_set_state_caller_count = vm_extmod_statistics.add(40);
// console.log('[-] task_for_pid_count : ' + task_for_pid_count.readInt());
// console.log('[-] task_for_pid_caller_count : ' + task_for_pid_caller_count.readInt());
// console.log('[-] thread_creation_count : ' + thread_creation_count.readInt());
// console.log('[-] thread_creation_caller_count : ' + thread_creation_caller_count.readInt());
// console.log('[-] thread_set_state_count : ' + thread_set_state_count.readInt());
// console.log('[-] thread_set_state_caller_count : ' + thread_set_state_caller_count.readInt());
}
}
});
오랜만에 포스팅을 쓴다. 보안 솔루션을 분석하면서 발견하고 배웠던 것들이 있는데, 바쁘다는 핑계로 소홀했던 것 같다. 앞으로 여유로울 때마다 하나씩 정리해야겠다.
https://opensource.apple.com/source/xnu/xnu-4570.41.2/osfmk/mach/task_info.h
https://opensource.apple.com/source/xnu/xnu-792/osfmk/mach/kern_return.h
https://opensource.apple.com/source/dyld/dyld-195.6/include/mach-o/dyld_images.h
https://opensource.apple.com/source/xnu/xnu-3789.51.2/osfmk/mach/vm_statistics.h
https://knight.sc/reverse%20engineering/2019/04/15/detecting-task-modifications.html
With its fast-paced gameplay and vibrant visuals, Slice Master challenges players to perfect their slicing skills as they progress through increasingly difficult levels, offering a satisfying blend of action and strategy that keeps players hooked.