-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdecompkernelcache.c
More file actions
executable file
·2682 lines (2206 loc) · 98.7 KB
/
decompkernelcache.c
File metadata and controls
executable file
·2682 lines (2206 loc) · 98.7 KB
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <math.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOCFUnserialize.h>
#if defined(__linux__)
#define kCFBundleExecutableKey CFSTR("CFBundleExecutable")
#define kCFBundleIdentifierKey CFSTR("CFBundleIdentifier")
#endif /* Linux Support */
#if defined(__APPLE__)
#include <Availability.h>
#endif
#if defined(_WIN32) || defined(WIN32) || defined(WINDOWS) || defined(_WINDOWS)
#include <Windows.h>
#include <io.h>
#ifdef _MSC_VER
#include <direct.h>
#define mkdir(a,b) _mkdir(a)
#else
#define mkdir(a,b) mkdir(a)
#endif
#ifndef PATH_MAX
#define PATH_MAX MAX_PATH
#endif
#ifndef mode_t
#define mode_t int
#endif
#endif /* Windows Support */
#include "prelink.h"
#include "lzvn.h"
#if defined(__APPLE__) && defined(__MACH__)
#include <libkern/OSByteOrder.h>
#elif (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
inline uint32_t OSSwapInt32(uint32_t data)
{
__asm__ ("bswap %0" : "+r" (data));
return data;
}
#ifdef __x86_64__
inline uint64_t OSSwapInt64(uint64_t data)
{
__asm__ ("bswap %0" : "+r" (data));
return data;
}
#else /* Generic */
#define OSSwapInt32(x) \
((((x) & 0xff) << 24) | \
(((x) & 0xff00) << 8) | \
(((x) & 0xff0000) >> 8) | \
(((x) & 0xff000000) >> 24))
#define OSSwapInt64(x) \
((uint64_t)((((uint64_t)(x) & 0xff00000000000000ULL) >> 56) | \
(((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \
(((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \
(((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \
(((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \
(((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \
(((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \
(((uint64_t)(x) & 0x00000000000000ffULL) << 56)))
#endif /* Swap 64 */
#elif defined(_MSC_VER) && (defined(__i386__) || defined(_M_IX86) || defined(_X86_)) /* MSVC x86 (32-Bit) */
static __inline uint32_t OSSwapInt32(uint32_t data)
{
__asm
{
push eax
mov eax, data
bswap eax
mov data, eax
pop eax
};
return data;
}
#define OSSwapInt64(x) \
((uint64_t)((((uint64_t)(x) & 0xff00000000000000ULL) >> 56) | \
(((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \
(((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \
(((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \
(((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \
(((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \
(((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \
(((uint64_t)(x) & 0x00000000000000ffULL) << 56)))
#else /* Generic */
#define OSSwapInt32(x) \
((((x) & 0xff) << 24) | \
(((x) & 0xff00) << 8) | \
(((x) & 0xff0000) >> 8) | \
(((x) & 0xff000000) >> 24))
#define OSSwapInt64(x) \
((uint64_t)((((uint64_t)(x) & 0xff00000000000000ULL) >> 56) | \
(((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \
(((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \
(((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \
(((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \
(((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \
(((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \
(((uint64_t)(x) & 0x00000000000000ffULL) << 56)))
#endif /* Type of swap */
#ifndef FAT_MAGIC
#define FAT_MAGIC 0xcafebabe
#endif
#ifndef FAT_CIGAM
#define FAT_CIGAM 0xbebafeca /* OSSwapInt32(FAT_MAGIC) */
#endif
#ifndef FAT_MAGIC_64
#define FAT_MAGIC_64 0xcafebabf
#endif
#ifndef FAT_CIGAM_64
#define FAT_CIGAM_64 0xbfbafeca /* OSSwapInt32(FAT_MAGIC_64) */
#endif
/* Constant for the magic field of the mach_header (32-bit architectures) */
#ifndef MH_MAGIC
#define MH_MAGIC 0xfeedface /* the mach magic number */
#endif
#ifndef MH_CIGAM
#define MH_CIGAM 0xcefaedfe /* NXSwapInt(MH_MAGIC) */
#endif
/* Constant for the magic field of the mach_header_64 (64-bit architectures) */
#ifndef MH_MAGIC_64
#define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */
#endif
#ifndef MH_CIGAM_64
#define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */
#endif
#ifndef CPU_ARCH_MASK
#define CPU_ARCH_MASK 0xff000000 /* mask for architecture bits */
#endif
#ifndef CPU_ARCH_ABI64
#define CPU_ARCH_ABI64 0x01000000 /* 64 bit ABI */
#endif
#ifndef CPU_ARCH_ABI64_32
#define CPU_ARCH_ABI64_32 0x02000000 /* ABI for 64-bit hardware with 32-bit types; LP32 */
#endif
#ifndef KMOD_MAX_NAME
#define KMOD_MAX_NAME (64)
#endif
#ifndef CPU_IS_64BIT
#define CPU_IS_64BIT(CPU) ((CPU) & ((CPU_ARCH_ABI64) | (CPU_ARCH_ABI64_32)))
#endif
#ifndef CPU_IS_32BIT
#define CPU_IS_32BIT(CPU) (CPU_IS_64BIT(CPU) == 0)
#endif
typedef int32_t cpu_type_t;
typedef int32_t cpu_subtype_t;
typedef int vm_prot_t;
#ifndef CPU_TYPE_ANY
#define CPU_TYPE_ANY ((cpu_type_t) -1)
#endif
#ifndef CPU_TYPE_NONE
#define CPU_TYPE_NONE ((cpu_type_t) 0)
#endif
#ifndef CPU_TYPE_VAX
#define CPU_TYPE_VAX ((cpu_type_t) 1)
#endif
#ifndef CPU_TYPE_MC680x0
#define CPU_TYPE_MC680x0 ((cpu_type_t) 6)
#endif
#ifndef CPU_TYPE_I386
#define CPU_TYPE_I386 ((cpu_type_t) 7)
#endif
#ifndef CPU_TYPE_X86_64
#define CPU_TYPE_X86_64 (CPU_TYPE_I386 | CPU_ARCH_ABI64)
#endif
#ifndef CPU_TYPE_MC98000
#define CPU_TYPE_MC98000 ((cpu_type_t) 10)
#endif
#ifndef CPU_TYPE_HPPA
#define CPU_TYPE_HPPA ((cpu_type_t) 11)
#endif
#ifndef CPU_TYPE_ARM
#define CPU_TYPE_ARM ((cpu_type_t) 12)
#endif
#ifndef CPU_TYPE_ARM64
#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
#endif
#ifndef CPU_TYPE_ARM64_32
#define CPU_TYPE_ARM64_32 (CPU_TYPE_ARM | CPU_ARCH_ABI64_32)
#endif
#ifndef CPU_TYPE_MC88000
#define CPU_TYPE_MC88000 ((cpu_type_t) 13)
#endif
#ifndef CPU_TYPE_SPARC
#define CPU_TYPE_SPARC ((cpu_type_t) 14)
#endif
#ifndef CPU_TYPE_I860
#define CPU_TYPE_I860 ((cpu_type_t) 15)
#endif
#ifndef CPU_TYPE_ALPHA
#define CPU_TYPE_ALPHA ((cpu_type_t) 16)
#endif
#ifndef CPU_TYPE_POWERPC
#define CPU_TYPE_POWERPC ((cpu_type_t) 18)
#endif
#ifndef CPU_TYPE_POWERPC64
#define CPU_TYPE_POWERPC64 (CPU_TYPE_POWERPC | CPU_ARCH_ABI64)
#endif
#ifndef _MSC_VER
#define PACK_GNU __attribute__((aligned(1)))
#else /* GNUC/CLANG */
#define PACK_GNU
#endif /* PACK_DEF */
#ifndef LC_SEGMENT
#define LC_SEGMENT 0x1 /* segment of this file to be mapped */
#endif
#ifndef LC_SEGMENT_64
#define LC_SEGMENT_64 0x19 /* 64-bit segment of this file to be mapped */
#endif
#ifndef LC_CODE_SIGNATURE
#define LC_CODE_SIGNATURE 0x1d /* local of code signature */
#endif
#ifndef SEG_LINKEDIT
#define SEG_LINKEDIT "__LINKEDIT" /* the segment containing all structs */
#endif
#ifdef _MSC_VER
#pragma pack(1)
#endif
typedef struct fat_header {
uint32_t magic; /* FAT_MAGIC */
uint32_t nfat_arch; /* number of structs that follow */
} fat_header_t PACK_GNU;
#ifdef _MSC_VER
#pragma pack()
#endif
#ifdef _MSC_VER
#pragma pack(1)
#endif
typedef struct fat_arch {
cpu_type_t cputype; /* cpu specifier (int) */
cpu_subtype_t cpusubtype; /* machine specifier (int) */
uint32_t offset; /* file offset to this object file */
uint32_t size; /* size of this object file */
uint32_t align; /* alignment as a power of 2 */
} fat_arch_t PACK_GNU;
#ifdef _MSC_VER
#pragma pack()
#endif
#ifdef _MSC_VER
#pragma pack(1)
#endif
typedef struct fat_arch_64 {
cpu_type_t cputype; /* cpu specifier (int) */
cpu_subtype_t cpusubtype; /* machine specifier (int) */
uint64_t offset; /* file offset to this object file */
uint64_t size; /* size of this object file */
uint32_t align; /* alignment as a power of 2 */
uint32_t reserved; /* reserved */
} fat_arch_64_t PACK_GNU;
#ifdef _MSC_VER
#pragma pack()
#endif
#ifndef PLATFORM_NAME_LEN
#define PLATFORM_NAME_LEN (64)
#endif
#ifndef ROOT_PATH_LEN
#define ROOT_PATH_LEN (256)
#endif
#ifndef RESERVED_DWORDS
#define RESERVED_DWORDS (10)
#endif
/*
* prelinkVersion ((value) >= 1) => KASLR supported.
* prelinked kernel header size is 384 bytes.
*/
#ifdef _MSC_VER
#pragma pack(1)
#endif
typedef struct prelinked_kernel_header {
/* Compression signatures */
uint32_t signature; /* 0 - 3 */
uint32_t compressType; /* 4 - 7 */
/* Checksum */
uint32_t adler32; /* 8 - 11 */
/* Sizes */
uint32_t uncompressedSize; /* 12 - 15 */
uint32_t compressedSize; /* 16 - 19 */
/* Version */
uint32_t prelinkVersion; /* 20 - 23 */
/* Reserved */
uint32_t reserved[RESERVED_DWORDS]; /* 24 - 63 */
/* Platform name */
char platformName[PLATFORM_NAME_LEN]; /* 64 - 127 => unused */
/* Root path */
char rootPath[ROOT_PATH_LEN]; /* 128 - 383 => unused */
} PrelinkedKernelHeader PACK_GNU;
#ifdef _MSC_VER
#pragma pack()
#endif
#ifdef _MSC_VER
#pragma pack(1)
#endif
typedef struct platform_info
{
/* Platform name */
char platformName[PLATFORM_NAME_LEN];
/* Root path */
char rootPath[ROOT_PATH_LEN];
} PlatformInfo PACK_GNU;
#ifdef _MSC_VER
#pragma pack()
#endif
#ifdef _MSC_VER
#pragma pack(1)
#endif
typedef struct mach_header {
uint32_t magic; /* mach magic number identifier */
cpu_type_t cputype; /* cpu specifier */
cpu_subtype_t cpusubtype; /* machine specifier */
uint32_t filetype; /* type of file */
uint32_t ncmds; /* number of load commands */
uint32_t sizeofcmds; /* the size of all the load commands */
uint32_t flags; /* flags */
} mach_header_t PACK_GNU;
#ifdef _MSC_VER
#pragma pack()
#endif
#ifdef _MSC_VER
#pragma pack(1)
#endif
typedef struct mach_header_64 {
uint32_t magic; /* mach magic number identifier */
cpu_type_t cputype; /* cpu specifier */
cpu_subtype_t cpusubtype; /* machine specifier */
uint32_t filetype; /* type of file */
uint32_t ncmds; /* number of load commands */
uint32_t sizeofcmds; /* the size of all the load commands */
uint32_t flags; /* flags */
uint32_t reserved; /* reserved */
} mach_header_64_t PACK_GNU;
#ifdef _MSC_VER
#pragma pack()
#endif
#ifdef _MSC_VER
#pragma pack(1)
#endif
typedef struct load_command {
uint32_t cmd; /* type of load command */
uint32_t cmdsize; /* total size of command in bytes */
} load_command_t PACK_GNU;
#ifdef _MSC_VER
#pragma pack()
#endif
#ifdef _MSC_VER
#pragma pack(1)
#endif
typedef struct segment_command { /* for 32-bit architectures */
uint32_t cmd; /* LC_SEGMENT */
uint32_t cmdsize; /* includes sizeof section structs */
char segname[16]; /* segment name */
uint32_t vmaddr; /* memory address of this segment */
uint32_t vmsize; /* memory size of this segment */
uint32_t fileoff; /* file offset of this segment */
uint32_t filesize; /* amount to map from the file */
vm_prot_t maxprot; /* maximum VM protection */
vm_prot_t initprot; /* initial VM protection */
uint32_t nsects; /* number of sections in segment */
uint32_t flags; /* flags */
} segment_command_t PACK_GNU;
#ifdef _MSC_VER
#pragma pack()
#endif
#ifdef _MSC_VER
#pragma pack(1)
#endif
typedef struct segment_command_64 { /* for 64-bit architectures */
uint32_t cmd; /* LC_SEGMENT_64 */
uint32_t cmdsize; /* includes sizeof section_64 structs */
char segname[16]; /* segment name */
uint64_t vmaddr; /* memory address of this segment */
uint64_t vmsize; /* memory size of this segment */
uint64_t fileoff; /* file offset of this segment */
uint64_t filesize; /* amount to map from the file */
vm_prot_t maxprot; /* maximum VM protection */
vm_prot_t initprot; /* initial VM protection */
uint32_t nsects; /* number of sections in segment */
uint32_t flags; /* flags */
} segment_command_64_t PACK_GNU;
#ifdef _MSC_VER
#pragma pack()
#endif
#ifdef _MSC_VER
#pragma pack(1)
#endif
typedef struct section { /* for 32-bit architectures */
char sectname[16]; /* name of this section */
char segname[16]; /* segment this section goes in */
uint32_t addr; /* memory address of this section */
uint32_t size; /* size in bytes of this section */
uint32_t offset; /* file offset of this section */
uint32_t align; /* section alignment (power of 2) */
uint32_t reloff; /* file offset of relocation entries */
uint32_t nreloc; /* number of relocation entries */
uint32_t flags; /* flags (section type and attributes)*/
uint32_t reserved1; /* reserved (for offset or index) */
uint32_t reserved2; /* reserved (for count or sizeof) */
} section_t PACK_GNU;
#ifdef _MSC_VER
#pragma pack()
#endif
#ifdef _MSC_VER
#pragma pack(1)
#endif
typedef struct section_64 { /* for 64-bit architectures */
char sectname[16]; /* name of this section */
char segname[16]; /* segment this section goes in */
uint64_t addr; /* memory address of this section */
uint64_t size; /* size in bytes of this section */
uint32_t offset; /* file offset of this section */
uint32_t align; /* section alignment (power of 2) */
uint32_t reloff; /* file offset of relocation entries */
uint32_t nreloc; /* number of relocation entries */
uint32_t flags; /* flags (section type and attributes)*/
uint32_t reserved1; /* reserved (for offset or index) */
uint32_t reserved2; /* reserved (for count or sizeof) */
uint32_t reserved3; /* reserved */
} section_64_t PACK_GNU;
#ifdef _MSC_VER
#pragma pack()
#endif
#ifdef _MSC_VER
#pragma pack(1)
#endif
typedef struct linkedit_data_command {
uint32_t cmd; /* LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO,
LC_FUNCTION_STARTS, LC_DATA_IN_CODE,
LC_DYLIB_CODE_SIGN_DRS,
LC_LINKER_OPTIMIZATION_HINT,
LC_DYLD_EXPORTS_TRIE, or
LC_DYLD_CHAINED_FIXUPS. */
uint32_t cmdsize; /* sizeof(struct linkedit_data_command) */
uint32_t dataoff; /* file offset of data in __LINKEDIT segment */
uint32_t datasize; /* file size of data in __LINKEDIT segment */
} linkedit_data_command_t PACK_GNU;
#ifdef _MSC_VER
#pragma pack()
#endif
/* Convert CPU name string to CPU type value */
cpu_type_t cpu_type_for_name(const char *archstr)
{
if (strncmp("i860", archstr, 4) == 0)
{
return CPU_TYPE_I860;
}
if (strncmp("i386", archstr, 4) == 0)
{
return CPU_TYPE_I386;
}
if (strncmp("x86_64", archstr, 5) == 0)
{
return CPU_TYPE_X86_64;
}
if (strncmp("ppc64", archstr, 5) == 0)
{
return CPU_TYPE_POWERPC64;
}
if (strncmp("ppc", archstr, 5) == 0)
{
return CPU_TYPE_POWERPC;
}
if (strncmp("arm64_32", archstr, 8) == 0)
{
return CPU_TYPE_ARM64_32;
}
if (strncmp("arm64", archstr, 5) == 0)
{
return CPU_TYPE_ARM64;
}
if (strncmp("arm", archstr, 3) == 0)
{
return CPU_TYPE_ARM;
}
if (strncmp("vax", archstr, 3) == 0)
{
return CPU_TYPE_VAX;
}
if (strncmp("mc68k", archstr, 5) == 0)
{
return CPU_TYPE_MC680x0;
}
if (strncmp("mc88k", archstr, 5) == 0)
{
return CPU_TYPE_MC88000;
}
if (strncmp("mc98k", archstr, 5) == 0)
{
return CPU_TYPE_MC98000;
}
if (strncmp("sparc", archstr, 5) == 0)
{
return CPU_TYPE_SPARC;
}
if (strncmp("alpha", archstr, 5) == 0)
{
return CPU_TYPE_ALPHA;
}
printf("WARNING: Invalid architecture name %s found, using any architecture\n", archstr);
return CPU_TYPE_ANY;
}
/* Convert CPU name string to CPU type value */
const char *cpu_name_for_type(cpu_type_t cputype)
{
switch (cputype)
{
case CPU_TYPE_I860:
return "i860";
case CPU_TYPE_I386:
return "i386";
case CPU_TYPE_X86_64:
return "x86_64";
case CPU_TYPE_POWERPC64:
return "ppc64";
case CPU_TYPE_POWERPC:
return "ppc";
case CPU_TYPE_ARM64_32:
return "arm64_32";
case CPU_TYPE_ARM64:
return "arm64";
case CPU_TYPE_ARM:
return "arm";
case CPU_TYPE_VAX:
return "vax";
case CPU_TYPE_MC680x0:
return "m68k";
case CPU_TYPE_MC88000:
return "m88k";
case CPU_TYPE_MC98000:
return "m98k";
case CPU_TYPE_SPARC:
return "sparc";
case CPU_TYPE_ALPHA:
return "alpha";
case CPU_TYPE_ANY:
case CPU_TYPE_NONE:
default:
break;
}
printf("WARNING: Invalid cpu type 0x%x found, using any architecture\n", cputype);
return "any";
}
struct load_command *find_load_command(struct mach_header *machHeader, uint32_t targetCmd)
{
struct load_command *loadCommand;
size_t machHeaderSize = 0;
int is32bit = (int)((machHeader->magic == MH_MAGIC) || (machHeader->magic == MH_CIGAM));
int swapped = ((machHeader->magic == MH_CIGAM) || (machHeader->magic == MH_CIGAM_64));
// First LOAD_COMMAND begins after the mach header.
if (is32bit == true)
{
machHeaderSize = sizeof(struct mach_header);
} else {
machHeaderSize = sizeof(struct mach_header_64);
}
loadCommand = (struct load_command *)((uint64_t)machHeader + machHeaderSize);
while ((uintptr_t)loadCommand < (((uintptr_t)machHeader + ((swapped == 0) ? ((uintptr_t)machHeader->sizeofcmds) :
((uintptr_t)OSSwapInt32((uint32_t)machHeader->sizeofcmds)))) + machHeaderSize))
{
if (((swapped == 0) ? (loadCommand->cmd) : (OSSwapInt32(loadCommand->cmd))) == targetCmd)
{
return ((struct load_command *)loadCommand);
}
// Next load command.
loadCommand = (struct load_command *)((uintptr_t)loadCommand + ((swapped == 0) ?
(uintptr_t)loadCommand->cmdsize :
(uintptr_t)OSSwapInt32((uint32_t)loadCommand->cmdsize)));
}
// Return NULL on failure (not found).
return NULL;
}
void *find_segment(struct mach_header *aMachHeader, const char *aSegmentName, int *isSeg32)
{
struct load_command *loadCommand;
struct segment_command *segment32;
struct segment_command_64 *segment64;
size_t machHeaderSize = 0;
int is32bit = ((aMachHeader->magic == MH_MAGIC) || (aMachHeader->magic == MH_CIGAM));
int swapped = ((aMachHeader->magic == MH_CIGAM) || (aMachHeader->magic == MH_CIGAM_64));
// First LOAD_COMMAND begins straight after the mach header.
if (is32bit == 0)
{
machHeaderSize = sizeof(struct mach_header_64);
} else {
machHeaderSize = sizeof(struct mach_header);
}
loadCommand = (struct load_command *)((uintptr_t)aMachHeader + machHeaderSize);
while ((uintptr_t)loadCommand < (uintptr_t)aMachHeader + ((swapped == 0) ? (uintptr_t)aMachHeader->sizeofcmds : (uintptr_t)OSSwapInt32((uint32_t)aMachHeader->sizeofcmds)) + machHeaderSize)
{
if (((swapped == 0) ? loadCommand->cmd : OSSwapInt32(loadCommand->cmd)) == LC_SEGMENT)
{
// Check load command's segment name in case of a 32-bit segment.
segment32 = (struct segment_command *)loadCommand;
if (strncmp(segment32->segname, aSegmentName, sizeof(segment32->segname)) == 0)
{
if (isSeg32 != NULL)
{
*isSeg32 = 1;
}
return ((void *)segment32);
}
} else if (((swapped == 0) ? loadCommand->cmd : OSSwapInt32(loadCommand->cmd)) == LC_SEGMENT_64) {
// Check load command's segment name in case of a 64_bit segment.
segment64 = (struct segment_command_64 *)loadCommand;
if (strncmp(segment64->segname, aSegmentName, sizeof(segment64->segname)) == 0)
{
if (isSeg32 != NULL)
{
*isSeg32 = 0;
}
return ((void *)segment64);
}
}
// Next load command.
loadCommand = (struct load_command *)((uintptr_t)loadCommand + ((swapped == 0) ? (uintptr_t)loadCommand->cmdsize : (uintptr_t)OSSwapInt32((uint32_t)loadCommand->cmdsize)));
}
// Return NULL on failure (32/64 bit segment not found).
return NULL;
}
uint8_t is_prelinkedkernel(unsigned char *aFileBuffer)
{
struct segment_command_64 *prelinkTextSegment64 = NULL;
struct segment_command_64 *prelinkInfoSegment64 = NULL;
struct segment_command *prelinkTextSegment32 = NULL;
struct segment_command *prelinkInfoSegment32 = NULL;
int is32bit = 0;
struct mach_header *machHeader = (struct mach_header *)((unsigned char *)aFileBuffer);
if ((machHeader->magic != MH_MAGIC) && (machHeader->magic != MH_MAGIC_64) && (machHeader->magic != MH_CIGAM) && (machHeader->magic != MH_CIGAM_64))
{
return 0;
}
prelinkTextSegment64 = find_segment(machHeader, "__PRELINK_TEXT", &is32bit);
prelinkInfoSegment64 = find_segment(machHeader, "__PRELINK_INFO", &is32bit);
prelinkTextSegment32 = (struct segment_command *)prelinkTextSegment64;
prelinkInfoSegment32 = (struct segment_command *)prelinkInfoSegment64;
if (((prelinkTextSegment32) && (prelinkInfoSegment32->filesize)) &&
((prelinkTextSegment32) && (prelinkTextSegment32->filesize)) &&
(is32bit != 0))
{
return 1;
} else if (((prelinkTextSegment64) && (prelinkInfoSegment64->filesize)) &&
((prelinkTextSegment64) && (prelinkTextSegment64->filesize)) &&
(is32bit == 0)) {
return 1;
}
return 0;
}
/* List prelinked kexts */
uint8_t listKexts(unsigned char *aFileBuffer, const char *outfile)
{
struct segment_command_64 *prelinkTextSegment64 = NULL;
struct segment_command_64 *prelinkInfoSegment64 = NULL;
struct segment_command *prelinkTextSegment32 = NULL;
struct segment_command *prelinkInfoSegment32 = NULL;
struct mach_header *machHeader = (struct mach_header *)((unsigned char *)aFileBuffer);
//struct linkedit_data_command *codeSignature = NULL;
int is32bit = 0;
int swapped = ((machHeader->magic == MH_CIGAM) || (machHeader->magic == MH_CIGAM_64));
FILE *out = NULL;
prelinkTextSegment32 = find_segment(machHeader, "__PRELINK_TEXT", &is32bit);
prelinkInfoSegment32 = find_segment(machHeader, "__PRELINK_INFO", &is32bit);
prelinkTextSegment64 = (struct segment_command_64 *)prelinkTextSegment32;
prelinkInfoSegment64 = (struct segment_command_64 *)prelinkInfoSegment32;
if (((prelinkTextSegment32) && (prelinkInfoSegment32) && (is32bit != 0)) ||
((prelinkTextSegment64) && (prelinkInfoSegment64) && (is32bit == 0)))
{
const char *prelinkInfoBytes = (const char *)aFileBuffer + ((is32bit == 0) ? ((swapped == 0) ? prelinkInfoSegment64->fileoff : OSSwapInt64(prelinkInfoSegment64->fileoff)) : ((swapped == 0) ? prelinkInfoSegment32->fileoff : OSSwapInt32(prelinkInfoSegment32->fileoff)));
CFPropertyListRef prelinkInfoPlist = IOCFUnserialize(prelinkInfoBytes, kCFAllocatorDefault, 0, NULL);
if (outfile != NULL)
{
#if defined(_MSC_VER) && __STDC_WANT_SECURE_LIB__
fopen_s(&out, outfile, "wb");
#else
out = fopen(outfile, "wb");
#endif
}
if (prelinkInfoPlist)
{
printf("NOTICE: Unserialized prelink info\n");
if (out != NULL)
{
fprintf(out, "NOTICE: Unserialized prelink info\n");
}
CFArrayRef kextPlistArray = NULL;
kextPlistArray = (CFArrayRef)CFDictionaryGetValue(prelinkInfoPlist, CFSTR("_PrelinkInfoDictionary"));
CFIndex i = 0;
CFIndex kextCount = CFArrayGetCount(kextPlistArray);
printf("kextCount: %ld\n", (long)kextCount);
if (out != NULL)
{
fprintf(out, "kextCount: %ld\n", (long)kextCount);
}
//char kextIdentifierBuffer[64]; // KMOD_MAX_NAME = 64
char kextBundlePathBuffer[PATH_MAX];
//char kextPath[PATH_MAX];
//char kextPlistPath[PATH_MAX];
//char kextExecutablePath[PATH_MAX];
//struct stat st = {0};
for (i = 0; i < kextCount; i++)
{
CFDictionaryRef kextPlist = (CFDictionaryRef)CFArrayGetValueAtIndex(kextPlistArray, i);
CFStringRef bundlePath = (CFStringRef)CFDictionaryGetValue(kextPlist, CFSTR(kPrelinkBundlePathKey));
if (bundlePath)
{
CFStringGetCString(bundlePath, kextBundlePathBuffer, sizeof(kextBundlePathBuffer), kCFStringEncodingUTF8);
printf("%s\n", kextBundlePathBuffer);
if (out != NULL)
{
fprintf(out, "%s\n", kextBundlePathBuffer);
}
}
}
if (out != NULL)
{
fclose(out);
}
} else {
printf("ERROR: Can't unserialize _PrelinkInfoDictionary!\n");
return -1;
}
} else {
printf("ERROR: find_segment(\"__PRELINK_TEXT/__PRELINK_INFO\") failed!\n");
return -1;
}
return 0;
}
uint8_t saveKernel(unsigned char *aFileBuffer, const char *outfile)
{
struct segment_command_64 *lastSegment64 = NULL;
struct segment_command_64 *prelinkTextSegment64 = NULL;
struct segment_command_64 *prelinkInfoSegment64 = NULL;
struct segment_command_64 *linkeditSegment64 = NULL;
struct segment_command *lastSegment32 = NULL;
struct segment_command *prelinkTextSegment32 = NULL;
struct segment_command *prelinkInfoSegment32 = NULL;
struct segment_command *linkeditSegment32 = NULL;
struct section_64 *prelinkTextSection64 = NULL;
struct section_64 *prelinkInfoSection64 = NULL;
struct section *prelinkTextSection32 = NULL;
struct section *prelinkInfoSection32 = NULL;
struct mach_header *machHeader = (struct mach_header *)aFileBuffer;
int is32bitMachO = ((machHeader->magic == MH_MAGIC) || (machHeader->magic == MH_CIGAM));
int is32bit = 0;
int swapped = (int)((machHeader->magic == MH_CIGAM) || (machHeader->magic == MH_CIGAM_64));
if ((lastSegment64 = find_segment(machHeader, "__LAST", &is32bit)) == NULL)
{
printf("ERROR: find_segment(\"__LAST\") failed!\n");
return -1;
}
if ((prelinkTextSegment64 = find_segment(machHeader, "__PRELINK_TEXT", &is32bit)) == NULL)
{
printf("ERROR: find_segment(\"__PRELINK_TEXT\") failed!\n");
return -1;
}
if ((prelinkInfoSegment64 = find_segment(machHeader, "__PRELINK_INFO", &is32bit)) == NULL)
{
printf("ERROR: find_segment(\"__PRELINK_INFO\") failed!\n");
return -1;
}
if ((linkeditSegment64 = find_segment(machHeader, SEG_LINKEDIT, &is32bit)) == NULL)
{
printf("ERROR: find_segment(\"__LINKEDIT\") failed!\n");
return -1;
}
// 32 Bits
lastSegment32 = (struct segment_command *)lastSegment64;
prelinkTextSegment32 = (struct segment_command *)prelinkTextSegment64;
prelinkInfoSegment32 = (struct segment_command *)prelinkInfoSegment64;
linkeditSegment32 = (struct segment_command *)linkeditSegment64;
if ((is32bit == 0) && (is32bitMachO == 0))
{
prelinkTextSegment64->vmaddr = linkeditSegment64->vmaddr;
prelinkTextSegment64->vmsize = 0;
prelinkTextSegment64->fileoff = (swapped == 0) ? (lastSegment64->fileoff + lastSegment64->filesize) : (OSSwapInt64(OSSwapInt64(lastSegment64->fileoff) + OSSwapInt64(lastSegment64->filesize)));
prelinkTextSegment64->filesize = 0;
prelinkTextSection64 = (struct section_64 *)((uintptr_t)prelinkTextSegment64 + sizeof(struct segment_command_64));
prelinkTextSection64->addr = prelinkTextSegment64->vmaddr;
prelinkTextSection64->size = 0;
prelinkTextSection64->offset = (uint32_t)prelinkTextSegment64->fileoff;
prelinkInfoSegment64->vmaddr = linkeditSegment64->vmaddr;
prelinkInfoSegment64->vmsize = 0;
prelinkInfoSegment64->fileoff = (swapped == 0) ? (lastSegment64->fileoff + lastSegment64->filesize) : (OSSwapInt64(OSSwapInt64((lastSegment64->fileoff)) + OSSwapInt64(lastSegment64->filesize)));
prelinkInfoSegment64->filesize = 0;
prelinkInfoSection64 = (struct section_64 *)((uintptr_t)prelinkInfoSegment64 + sizeof(struct segment_command_64));
prelinkInfoSection64->addr = prelinkTextSegment64->vmaddr;
prelinkInfoSection64->size = 0;
prelinkInfoSection64->offset = (uint32_t)prelinkInfoSegment64->fileoff;
FILE *fp = NULL;
if (outfile == NULL)
{
#if defined(_MSC_VER) && __STDC_WANT_SECURE_LIB__
fopen_s(&fp, outfile, "wb");
#else
fp = fopen("kernel", "wb");
#endif
} else {
#if defined(_MSC_VER) && __STDC_WANT_SECURE_LIB__
fopen_s(&fp, outfile, "wb");
#else
fp = fopen(outfile, "wb");
#endif
}
fwrite(aFileBuffer, 1, (long)(((swapped == 0) ? linkeditSegment64->fileoff : OSSwapInt64(linkeditSegment64->fileoff)) + ((swapped == 0) ? linkeditSegment64->filesize : OSSwapInt64(linkeditSegment64->filesize))), fp);
printf("%ld bytes written\n", ftell(fp));
fclose(fp);
} else if ((is32bit == 1) || (is32bitMachO == 1)) {
prelinkTextSegment32->vmaddr = linkeditSegment32->vmaddr;
prelinkTextSegment32->vmsize = 0;
prelinkTextSegment32->fileoff = (swapped == 0) ? (lastSegment32->fileoff + lastSegment32->filesize) : (OSSwapInt32(OSSwapInt32(lastSegment32->fileoff) + OSSwapInt32(lastSegment32->filesize)));
prelinkTextSegment32->filesize = 0;
prelinkTextSection32 = (struct section *)((uintptr_t)prelinkTextSegment32 + sizeof(struct segment_command));
prelinkTextSection32->addr = prelinkTextSegment32->vmaddr;
prelinkTextSection32->size = 0;
prelinkTextSection32->offset = prelinkTextSegment32->fileoff;
prelinkInfoSegment32->vmaddr = linkeditSegment32->vmaddr;
prelinkInfoSegment32->vmsize = 0;
prelinkInfoSegment32->fileoff = (swapped == 0) ? (lastSegment32->fileoff + lastSegment32->filesize) : (OSSwapInt32(OSSwapInt32(lastSegment32->fileoff) + OSSwapInt32(lastSegment32->filesize)));
prelinkInfoSegment32->filesize = 0;
prelinkInfoSection32 = (struct section *)((uintptr_t)prelinkInfoSegment32 + sizeof(struct segment_command));
prelinkInfoSection32->addr = prelinkTextSegment32->vmaddr;
prelinkInfoSection32->size = 0;
prelinkInfoSection32->offset = prelinkInfoSegment32->fileoff;
FILE *fp = NULL;
if (outfile == NULL)
{
#if defined(_MSC_VER) && __STDC_WANT_SECURE_LIB__
fopen_s(&fp, "kernel", "wb");
#else
fp = fopen("kernel", "wb");