+ (void)load {
_dyld_register_func_for_add_image(&image_added);
_dyld_register_func_for_remove_image(&image_removed);
}
#pragma mark - Callbacks
static void image_added(const struct mach_header *mh, intptr_t slide) {
_print_image(mh, true);
}
static void image_removed(const struct mach_header *mh, intptr_t slide) {
_print_image(mh, false);
}
#pragma mark - Logger
static void _print_image(const struct mach_header *mh, bool added) {
Dl_info image_info;
int result = dladdr(mh, &image_info);
if (result == 0) {
printf("Could not print info for mach_header: %p\n\n", mh);
return;
}
const char *image_name = image_info.dli_fname;
const intptr_t image_base_address = (intptr_t)image_info.dli_fbase;
const uint64_t image_text_size = _image_text_segment_size(mh);
char image_uuid[37];
const uuid_t *image_uuid_bytes = _image_retrieve_uuid(mh);
uuid_unparse(*image_uuid_bytes, image_uuid);
const char *log = added ? "Added" : "Removed";
printf("%s: 0x%02lx (0x%02llx) %s <%s>\n\n", log, image_base_address, image_text_size, image_name, image_uuid);
/*
if (strstr(image_name, "MobileSubstrate.dylib")) {
// 自由發(fā)揮
exit();
}
*/
}
#pragma mark - Private
static uint32_t _image_header_size(const struct mach_header *mh) {
bool is_header_64_bit = (mh->magic == MH_MAGIC_64 || mh->magic == MH_CIGAM_64);
return (is_header_64_bit ? sizeof(struct mach_header_64) : sizeof(struct mach_header));
}
static void _image_visit_load_commands(const struct mach_header *mh, void (^visitor)(struct load_command *lc, bool *stop)) {
assert(visitor != NULL);
uintptr_t lc_cursor = (uintptr_t)mh + _image_header_size(mh);
for (uint32_t idx = 0; idx < mh->ncmds; idx++) {
struct load_command *lc = (struct load_command *)lc_cursor;
bool stop = false;
visitor(lc, &stop);
if (stop) {
return;
}
lc_cursor += lc->cmdsize;
}
}
static uint64_t _image_text_segment_size(const struct mach_header *mh) {
static const char *text_segment_name = "__TEXT";
__block uint64_t text_size = 0;
_image_visit_load_commands(mh, ^ (struct load_command *lc, bool *stop) {
if (lc->cmdsize == 0) {
return;
}
if (lc->cmd == LC_SEGMENT) {
struct segment_command *seg_cmd = (struct segment_command *)lc;
if (strcmp(seg_cmd->segname, text_segment_name) == 0) {
text_size = seg_cmd->vmsize;
*stop = true;
return;
}
}
if (lc->cmd == LC_SEGMENT_64) {
struct segment_command_64 *seg_cmd = (struct segment_command_64 *)lc;
if (strcmp(seg_cmd->segname, text_segment_name) == 0) {
text_size = seg_cmd->vmsize;
*stop = true;
return;
}
}
});
return text_size;
}
static const uuid_t *_image_retrieve_uuid(const struct mach_header *mh) {
__block const struct uuid_command *uuid_cmd = NULL;
_image_visit_load_commands(mh, ^ (struct load_command *lc, bool *stop) {
if (lc->cmdsize == 0) {
return;
}
if (lc->cmd == LC_UUID) {
uuid_cmd = (const struct uuid_command *)lc;
*stop = true;
}
});
if (uuid_cmd == NULL) {
return NULL;
}
return &uuid_cmd->uuid;
}
越獄檢測
extern char ** environ;
+ (BOOL)mgjpf_isJailbroken{//越獄檢測
//以下檢測的過程是越往下魁莉,越獄越高級(jí)
// /Applications/Cydia.app, /privte/var/stash
NSString *cydiaPath = @"/Applications/Cydia.app";
NSString *aptPath = @"/private/var/lib/apt/";
if ([[NSFileManager defaultManager] fileExistsAtPath:cydiaPath]) {
return YES;
}
if ([[NSFileManager defaultManager] fileExistsAtPath:aptPath]) {
return YES;
}
//可能存在hook了NSFileManager方法随闺,此處用底層C stat去檢測
struct stat stat_info;
if (0 == stat("/Library/MobileSubstrate/MobileSubstrate.dylib", &stat_info)) {
return YES;
}
if (0 == stat("/Applications/Cydia.app", &stat_info)) {
return YES;
}
if (0 == stat("/var/lib/cydia/", &stat_info)) {
return YES;
}
if (0 == stat("/var/cache/apt", &stat_info)) {
return YES;
}
char ** envir = environ;
int index = 0;
while(*envir)
{
int n;
char *s1 = *envir;
char *s2 = "MobileSubstrate";
while (*s1)
{
for (n = 0; *(s1 + n) == *(s2 + n); n ++)
{
if (!*(s2 + n + 1))
index++;
}
s1++;
}
envir++;
}
if (index >0) {
return YES;
}
//如果攻擊者給MobileSubstrate改名,但是原理都是通過DYLD_INSERT_LIBRARIES注入動(dòng)態(tài)庫
//那么可以爆班,檢測當(dāng)前程序運(yùn)行的環(huán)境變量
char *env = getenv("DYLD_INSERT_LIBRARIES");
if (env != NULL) {
return YES;
}
return NO;
}
想在main之前執(zhí)行
__attribute__((constructor)) void initFuc0()
{
printf("initFuc0 \n");
}
系統(tǒng)重啟時(shí)間
+ (long)bootTime{
#define MIB_SIZE 2
int mib[2];
size_t size;
struct timeval boottime;
mib[0] = CTL_KERN;
mib[1] = KERN_BOOTTIME;
size = sizeof(boottime);
if (sysctl(mib, MIB_SIZE, &boottime, &size, NULL, 0) != -1)
{
return boottime.tv_sec;
}
return 0;
}
參考
http://www.reibang.com/p/1de663f64c05
https://www.dllhook.com/post/154.html