|
The iPhone Wiki is no longer updated. Visit this article on The Apple Wiki for current information. |
Difference between revisions of "GenPass"
ChronicDev (talk | contribs) |
m (→GenPass Usage: This actually has to be lowercase.) |
||
| (16 intermediate revisions by 9 users not shown) | |||
| Line 1: | Line 1: | ||
| + | GenPass generates the RootFS keys for the filesystem image of an iDevice. It requires a decrypted [[ramdisk]]. |
||
| − | <pre> |
||
| − | // genpass |
||
| − | // get asr key for 3.x firmware |
||
| − | // |
||
| − | // by posixninja, geohot, and chronic |
||
| + | == Notices == |
||
| − | #include <stdio.h> |
||
| + | * The decryption happens in <code>/usr/sbin/asr</code> in the decrypted ramdisk. |
||
| − | #include <stdlib.h> |
||
| + | * Mounting the decrypted ramdisk messes with the structure of the image rending GenPass's keys false. |
||
| − | #include <string.h> |
||
| − | #include <unistd.h> |
||
| − | #include <sys/types.h> |
||
| − | #include <sys/stat.h> |
||
| − | #include <openssl/sha.h> |
||
| − | #include <openssl/evp.h> |
||
| + | == GenPass Usage == |
||
| − | #define BUF_SIZE 0x100000 |
||
| + | ./genpass <platform> <ramdisk> <filesystem> |
||
| − | #define SHA256_DIGEST_LENGTH 32 |
||
| + | Platform is the applications processor (i.e.- [[S5L8900|s5l8900]]x, [[S5L8720|s5l8720]]x, [[S5L8920|s5l8920]]x, [[S5L8922|s5l8922]]x, [[S5L8930|s5l8930]]x, [[S5L8940|s5l8940]]x) |
||
| + | == See also == |
||
| − | typedef unsigned char uint8; |
||
| + | * [[0rangefreeze]] |
||
| − | typedef unsigned int uint32; |
||
| − | typedef unsigned long long uint64; |
||
| + | == External Links == |
||
| − | uint64 u32_to_u64(uint32 msq, uint32 lsq) { |
||
| + | * [https://github.com/posixninja/genpass Source] |
||
| − | uint64 ms = (uint64)msq; |
||
| − | uint64 ls = (uint64)lsq; |
||
| − | return ls | (ms << 32); |
||
| − | } |
||
| + | [[Category:Decryption]] |
||
| − | uint64 hash_platform(const char* platform) { |
||
| + | [[Category:Hacking Software]] |
||
| − | uint8* md = malloc(SHA_DIGEST_LENGTH); |
||
| − | SHA1(platform, strlen(platform), md); |
||
| − | |||
| − | uint64 hash = u32_to_u64( |
||
| − | ((md[0] << 24) | (md[1] << 16) | (md[2] << 8) | md[3]), |
||
| − | ((md[4] << 24) | (md[5] << 16) | (md[6] << 8) | md[7]) |
||
| − | ); |
||
| − | free(md); |
||
| − | return hash; |
||
| − | } |
||
| − | |||
| − | uint64 ramdisk_size(const char* ramdisk) { |
||
| − | struct stat filestat; |
||
| − | if(stat(ramdisk, &filestat) < 0) { |
||
| − | return 0; |
||
| − | } |
||
| − | |||
| − | return (uint64)filestat.st_size; |
||
| − | } |
||
| − | |||
| − | void keydump(uint8* passphrase,int l) { |
||
| − | int i=0; |
||
| − | for(i=0; i<l; i++) { |
||
| − | printf("%02x", passphrase[i]); |
||
| − | } printf("\n"); |
||
| − | } |
||
| − | |||
| − | |||
| − | int compare(const uint32* a, const uint32* b) { |
||
| − | if(*a < *b) return -1; |
||
| − | if(*a > *b) return 1; |
||
| − | return 0; |
||
| − | } |
||
| − | |||
| − | const char platform[]="s5l8900x"; |
||
| − | const char ramdisk[]="ramdisk.dmg"; |
||
| − | |||
| − | |||
| − | int main(int argc, char* argv[]) { |
||
| − | |||
| − | if(argc<3) {printf("%s: <platform> <ramdisk> <main>\n", argv[0]); return -1;} |
||
| − | |||
| − | uint32 saltedHash[4]; |
||
| − | uint64 salt[4]; |
||
| − | |||
| − | salt[0] = 0xad79d29de5e2ac9e; |
||
| − | salt[1] = 0xe6af2eb19e23925b; |
||
| − | salt[2] = 0x3f1375b4bd88815c; |
||
| − | salt[3] = 0x3bdff4e5564a9f87; |
||
| − | |||
| − | FILE* fd = fopen(argv[2], "rb"); |
||
| − | int i = 0; |
||
| − | int x = 0; |
||
| − | SHA256_CTX ctx; |
||
| − | uint8* buffer = NULL; |
||
| − | uint8* passphrase = NULL; |
||
| − | uint64 totalSize = ramdisk_size(argv[2]); |
||
| − | uint64 platformHash = hash_platform(argv[1]); |
||
| − | |||
| − | /*printf("size: %I64x plat: %s plathash %I64x\n", totalSize, |
||
| − | platform,platformHash);*/ |
||
| − | |||
| − | for(i=0;i<4;i++) |
||
| − | { |
||
| − | salt[i]+=platformHash; |
||
| − | //printf("%d: %I64x\n", i, salt[i]); |
||
| − | } |
||
| − | |||
| − | for(i = 0; i < 4; i++) { |
||
| − | saltedHash[i] = ((uint32)(salt[i] % totalSize)) & 0xFFFFFE00; |
||
| − | } |
||
| − | |||
| − | qsort(&saltedHash, 4, 4, &compare); |
||
| − | |||
| − | SHA256_Init(&ctx); |
||
| − | SHA256_Update(&ctx, salt, 32); |
||
| − | |||
| − | |||
| − | int r=0; |
||
| − | i=0; //hash count |
||
| − | |||
| − | buffer = malloc(BUF_SIZE); |
||
| − | passphrase = malloc(SHA256_DIGEST_LENGTH); |
||
| − | |||
| − | while(r<totalSize) { |
||
| − | x = fread(buffer, 1, BUF_SIZE, fd); |
||
| − | SHA256_Update(&ctx, buffer, x); |
||
| − | |||
| − | if(i<4) //some salts remain |
||
| − | { |
||
| − | if(r >= (saltedHash[i]+0x4000)) i++; |
||
| − | else if( r < saltedHash[i] && saltedHash[i] < (r+x) ) |
||
| − | { |
||
| − | if( (saltedHash[i]+0x4000) < r ) |
||
| − | SHA256_Update(&ctx, buffer, saltedHash[i]-r); |
||
| − | else SHA256_Update(&ctx, buffer+(saltedHash[i]-r), |
||
| − | ( (x-(saltedHash[i]-r))<0x4000) ? (x-(saltedHash[i]-r)) : 0x4000 ); |
||
| − | } |
||
| − | } |
||
| − | r+=x; |
||
| − | } |
||
| − | |||
| − | fclose(fd); |
||
| − | |||
| − | SHA256_Final(passphrase, &ctx); |
||
| − | printf("passphrase: "); |
||
| − | keydump(passphrase, SHA256_DIGEST_LENGTH); |
||
| − | |||
| − | if(buffer) free(buffer); |
||
| − | |||
| − | if(argc==4) //do main as well |
||
| − | { |
||
| − | fd=fopen(argv[3],"rb"); |
||
| − | EVP_CIPHER_CTX ctx; |
||
| − | |||
| − | int offset=0x1D4; |
||
| − | uint8 data[0x30]; |
||
| − | uint8 out[0x30]; int outlen,tmplen; |
||
| − | int a; |
||
| − | for(a=0;a<7;a++) |
||
| − | { |
||
| − | fseek(fd, offset, SEEK_SET); offset+=0x268; |
||
| − | fread(data, 1, 0x30, fd); |
||
| − | EVP_CIPHER_CTX_init(&ctx); |
||
| − | EVP_DecryptInit_ex(&ctx, EVP_des_ede3_cbc(), |
||
| − | NULL, passphrase, &passphrase[24]); |
||
| − | EVP_DecryptUpdate(&ctx, out, &outlen, data, 0x30); |
||
| − | if(!EVP_DecryptFinal_ex(&ctx, out + outlen, &tmplen)) |
||
| − | printf("not block %d\n", a); |
||
| − | else |
||
| − | break; |
||
| − | } |
||
| − | printf("vfdecryptk: "); |
||
| − | keydump(out, 0x24); |
||
| − | } |
||
| − | |||
| − | if(passphrase) free(passphrase); |
||
| − | |||
| − | return 0; |
||
| − | } |
||
| − | </pre> |
||
Latest revision as of 23:02, 4 January 2016
GenPass generates the RootFS keys for the filesystem image of an iDevice. It requires a decrypted ramdisk.
Notices
- The decryption happens in
/usr/sbin/asrin the decrypted ramdisk. - Mounting the decrypted ramdisk messes with the structure of the image rending GenPass's keys false.
GenPass Usage
./genpass <platform> <ramdisk> <filesystem>
Platform is the applications processor (i.e.- s5l8900x, s5l8720x, s5l8920x, s5l8922x, s5l8930x, s5l8940x)