代码改变世界

判断设备是否越狱

2012-03-06 11:59  白山  阅读(638)  评论(0编辑  收藏  举报
 1 #import <Foundation/Foundation.h>
2 #import <mach-o/dyld.h>
3 #import <sys/sysctl.h>
4
5 #define FAT_CIGAM 0xbebafeca
6
7 #define ARMV6 6
8 #define ARMV7 9
9
10 #define LC_CODE_SIGNATURE 0x1d
11 #define LC_ENCRYPTION_INFO 0x21
12
13 #define LC_SEGMENT 0x1
14
15 struct fat_arch {
16 uint32_t cputype;
17 uint32_t cpusubtype;
18 uint32_t offset;
19 uint32_t size;
20 uint32_t align;
21 };
22
23 @interface CheckCracked : NSObject {
24
25 }
26
27 +(int) CheckIfCracked:(NSString*)filename ;
28 int get_local_arch(void);
29 int dump_binary(FILE *origin, FILE *target, uint32_t top);
30 @end
#import "CheckCracked.h"

@implementation CheckCracked

int get_local_arch() {
int i;
int len = sizeof(i);

sysctlbyname("hw.cpusubtype", &i, (size_t *) &len, NULL, 0);

return i;
}

int dump_binary(FILE *origin, FILE *target, uint32_t top) {

struct linkedit_data_command ldid; // LC_CODE_SIGNATURE load header (for resign)
struct encryption_info_command crypt ={0}; // LC_ENCRYPTION_INFO load header (for crypt*)
struct mach_header mach; // generic mach header
struct load_command l_cmd; // generic load command
struct segment_command __text; // __TEXT segment

BOOL foundCrypt = FALSE;

fseek(target, top, SEEK_SET); // go the top of the target

fread(&mach, sizeof(struct mach_header), 1, target); // read mach header to get number of load commands
for (int lc_index = 0; lc_index < mach.ncmds; lc_index++) { // iterate over each load command
fread(&l_cmd, sizeof(struct load_command), 1, target); // read load command from binary
if (l_cmd.cmd == LC_ENCRYPTION_INFO) { // encryption info?
fseek(target, -1 * sizeof(struct load_command), SEEK_CUR);
fread(&crypt, sizeof(struct encryption_info_command), 1, target);
foundCrypt = TRUE; // remember that it was found
} else if (l_cmd.cmd == LC_CODE_SIGNATURE) { // code signature?
fseek(target, -1 * sizeof(struct load_command), SEEK_CUR);
fread(&ldid, sizeof(struct linkedit_data_command), 1, target);
} else if (l_cmd.cmd == LC_SEGMENT) {
// some applications, like Skype, have decided to start offsetting the executable image's
// vm regions by substantial amounts for no apparant reason. this will find the vmaddr of
// that segment (referenced later during dumping)
fseek(target, -1 * sizeof(struct load_command), SEEK_CUR);
fread(&__text, sizeof(struct segment_command), 1, target);

fseek(target, l_cmd.cmdsize - sizeof(struct segment_command), SEEK_CUR);
} else {
fseek(target, l_cmd.cmdsize - sizeof(struct load_command), SEEK_CUR); // seek over the load command
}

if (foundCrypt)// && foundSignature && foundStartText)
break;
}


// NSLog(@"cryptid=%i", crypt.cryptid) ;
// NSLog(@"cryptoff=%i", crypt.cryptoff) ;
// NSLog(@"cryptsize=%i", crypt.cryptsize) ;

// we need to have found both of these
if (!foundCrypt) {
NSLog(@"dumping binary: some load commands were not found");
return -1;
}

return crypt.cryptid;
}

+(int) CheckIfCracked:(NSString*)filename {
uint32_t bin_magic ;
int crackid = 0 ;

bin_magic = 0xbebafeca ;

FILE *oldbinary, *newbinary;
oldbinary = fopen([filename UTF8String], "r");
newbinary = fopen([filename UTF8String], "r");
if ( oldbinary == NULL ) {
perror( "fopen error" ) ;
return -1 ;
}

fread(&bin_magic, 4, 1, oldbinary) ;

if (bin_magic == FAT_CIGAM) {
//fat binary

uint32_t bin_nfat_arch ;
fread(&bin_nfat_arch, 4, 1, oldbinary) ;

bin_nfat_arch = CFSwapInt32(bin_nfat_arch) ;

//check if the architecture requirements of the fat binary are met
//should be two architectures
if (bin_nfat_arch != 2) {
printf("Invalid architectures or headers.\n") ;
return -1 ;
}

int local_arch = get_local_arch() ;

//get the following fat architectures and determine which is which
struct fat_arch armv6, armv7 ;
fread(&armv6, sizeof(struct fat_arch), 1, oldbinary) ;
fread(&armv7, sizeof(struct fat_arch), 1, oldbinary) ;

if( local_arch != ARMV6 ) {//ARMV6
// crack the armv7 portion
crackid = dump_binary(oldbinary, newbinary, CFSwapInt32(armv7.offset)) ;
} else {
crackid = dump_binary(oldbinary, newbinary, CFSwapInt32(armv6.offset)) ;
}
} else {
//thin binary, portion begins at top of binary (0)
crackid = dump_binary(oldbinary, newbinary, 0) ;
}

fclose( oldbinary ) ;
fclose( newbinary ) ;

return crackid ;// <0 : error; =0 : cracked; =1 : non-cracked
}

@end