-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathYOPAPackage.m
executable file
·146 lines (124 loc) · 4.56 KB
/
YOPAPackage.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//
// YOPAPackage.m
// yopa
//
#import "YOPAPackage.h"
#ifndef CLUTCH_VERSION
#import "LZMAExtractor.h"
#endif
static NSString * genRandStringLength(int len) {
NSMutableString *randomString = [NSMutableString stringWithCapacity: len];
NSString *letters = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
for (int i=0; i<len; i++) {
[randomString appendFormat: @"%c", [letters characterAtIndex: arc4random()%[letters length]]];
}
return randomString;
}
@implementation YOPAPackage
- (id)initWithPackagePath:(NSString*) packagePath {
if (self = [super init]) {
_packagePath = packagePath;
_package = fopen([packagePath UTF8String], "r");
}
return self;
}
-(struct yopa_segment) findCompatibleSegmentforVersion:(NSInteger) version {
//version should be 0 if there's nothing
uint32_t magic, offset;
struct yopa_segment segment;
for(int i = 0; i < sizeof(_header.segment_offsets) / sizeof(uint32_t); i++)
{
offset = _header.segment_offsets[i];
fseek(_package, CFSwapInt32(offset), SEEK_SET);
fread(&magic, sizeof(uint32_t), 1, _package);
if (magic != YOPA_SEGMENT_MAGIC) {
DebugLog(@"Rogue segment detected at %u", CFSwapInt32(offset));
continue;
}
fread(&segment, sizeof(struct yopa_segment), 1, _package);
if (version == segment.required_version) {
DebugLog(@"Found compatible segment at %u", CFSwapInt32(offset));
return segment;
}
}
DebugLog(@"Error couldn't find any segment");
return segment;
}
-(NSString*)lipoPackageFromSegment:(struct yopa_segment)segment {
fseek(_package, segment.offset, SEEK_SET);
NSString *lipoPath = [_tmpDir stringByAppendingPathComponent:@"package-lipo"]; // assign a new lipo path
FILE *lipoOut = fopen([lipoPath UTF8String], "w+"); // prepare the file stream
void *tmp_b = malloc(0x1000); // allocate a temporary buffer
NSUInteger remain = CFSwapInt32(segment.size);
while (remain > 0) {
if (remain > 0x1000) {
// move over 0x1000
fread(tmp_b, 0x1000, 1, _package);
fwrite(tmp_b, 0x1000, 1, lipoOut);
remain -= 0x1000;
} else {
// move over remaining and break
fread(tmp_b, remain, 1, _package);
fwrite(tmp_b, remain, 1, lipoOut);
break;
}
}
fclose(lipoOut);
return lipoPath;
}
- (YOPAPackageType)packageType
{
static dispatch_once_t pred;
static YOPAPackageType type = UNKNOWN;
dispatch_once(&pred, ^{
if (_package == NULL) {
return;
}
uint32_t magic;
fseek(_package, -4, SEEK_END);
fread(&magic, 4, 1, _package);
if (magic == YOPA_HEADER_MAGIC) {
fseek(_package, -4 - sizeof(struct yopa_header), SEEK_END);
NSLog(@"YOPA fat Magic detected!");
type = YOPA_FAT_PACKAGE;
}
else if (magic == YOPA_SEGMENT_MAGIC) {
NSLog(@"segment magic detected!");
type = YOPA_SEGMENT_MAGIC;
}
NSLog(@"Couldn't find YOPA Magic.. huh");
});
return type;
}
-(NSString*) processPackage {
#ifndef CLUTCH_VERSION
switch (_header.segment_offsets[0]){
case SEVENZIP_COMPRESSION: {
NSLog(@"7zip compression, extracting");
_tmpDir = [NSString stringWithFormat:@"/tmp/yopa-%@", genRandStringLength(8)];
NSLog(@"tmp dir %@", _tmpDir);
if (![[NSFileManager defaultManager] removeItemAtPath:_tmpDir error:nil]) {
NSLog(@"Could not remove temporary directory? huh");
}
[[NSFileManager defaultManager] createDirectoryAtPath:_tmpDir withIntermediateDirectories:YES attributes:nil error:nil];
//BOOL result = [LZMAExtractor extractArchiveEntry:_packagePath archiveEntry:@".ipa" outPath:[_tmpDir stringByAppendingPathComponent:@".ipa"]];
NSArray *result = [LZMAExtractor extract7zArchive:_packagePath dirName:_tmpDir preserveDir:NO];
NSString *item = nil;
for (NSString *path in result) {
if ([[[path pathExtension] lowercaseString] isEqualToString:@"ipa"]) {
NSLog(@"found IPA in extracted 7z");
item = path;
break;
}
}
return item;
break;
}
}
#endif
return nil;
}
-(NSString*)getTempDir {
return _tmpDir;
}
@end