|
The iPhone Wiki is no longer updated. Visit this article on The Apple Wiki for current information. |
GenPass
// genpass
// get asr key for 3.x firmware
//
// by posixninja, geohot, and chronic
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#define BUF_SIZE 0x100000
#define SHA256_DIGEST_LENGTH 32
typedef unsigned char uint8;
typedef unsigned int uint32;
typedef unsigned long long uint64;
uint64 u32_to_u64(uint32 msq, uint32 lsq) {
uint64 ms = (uint64)msq;
uint64 ls = (uint64)lsq;
return ls | (ms << 32);
}
uint64 hash_platform(const char* platform) {
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;
}