|
|
Overview
The teasz program below implements the same encryption scheme as used by the iPhone firmware when accessing the seczone. Specifically, it's TEA encryption used in CBC mode. It is used in the re-virginizer to encrypt a non-corrupt "virgin" lock table into your seczone.
Note about re-virginization
When the code below is incorporated into a program running on the baseband CPU, it has the ability to properly encrypt every part of the seczone. But such a program still needs to know what to encrypt. At this point, the differences between the anySIM 1.0x unlock and the IPSF unlock become important.
- The anySIM 1.0x unlock inadvertantly convinces the Apple baseband code to rewrite the lock tables at seczone+0xc88, away from their virgin locked status. That's okay as long as the anySIM 1.0x patch to the baseband is still in place, because that inconsistency is ignored (by the patch). The anySIM 1.0x unlock does not change the "token" at seczone+0x400.
- The IPSF unlock intentionally rewrites the lock tables at seczone+0xc88, away from their virgin locked status. They also zero out your 'token" at seczone+0x400. The zeroed-out token combined with the lock table changes convince your iPhone it's unlocked because of an RSA bug that Apple has in their code (RSA is used on the token).
Now, consider this:
- The decrypted lock table for a locked phone is identical in every iPhone. Encrypting the lock table makes it look different on every iPhone, but once decrypted it is identical.
- The "token" is unique to every iPhone. It uses RSA encryption and only Apple knows the private key used to encrypt. In other words, even after doing the initial TEA CBC decryption implemented below, your decrypted token is still a very unique RSA value specific to your iPhone.. If it gets wiped out, it is gone forever (unless you, or IPSF, saved a backup).
- The code on this page can be used to restore the virgin lock table to any iPhone, regardless of unlock method. That's because the data to encrypt is known (in fact, it's shown below).
- The code on this page cannot be used to restore the token on your iPhone unless you have a backup of the encrypted seczone. That sucks for IPSF users who didn't make such a backup, if Apple ever closes the RSA hole.
- IN SUMMARY: If you used anySIM 1.0x and became 0049'd, the source code on this page will help revirginize your phone. If you used IPSF, the source code here will help you only if Apple closes the RSA hole (otherwise, why bother to re-virginize) and if you (or IPSF) has a backup of your original seczone.
Getting your norID and HWID
In order to use this program, you need to know the norID (8 bytes) and HWID (12 bytes) of your iPhone. There are a few ways to get those.
LTOKEN extraction
You can capture the LTOKEN sent to IPSF when you unlock your iPhone (this was the method that I used). The LTOKEN itself is encrypted, and you need a program like depisf from geohot to decrypt it. Once you do decrypt it, the HWID is 0x18 bytes into the decrypted part and lasts for 12 bytes. The norID is 0x302 bytes into the decrypted part and lasts for 8 bytes.
- For anyone curious, you can tell the only 12 bytes of the HWID section that matter begin at 0x18 bytes into the HWID section because the RCE of their bbsimfree v1.6 shows they are interested in those bytes. See the code at 0xA0024818. That was a big tip-off.
Custom baseband program
HWID
A baseband program can access the HWID directly by reading from 0xF440006C through 0xF4400074
- For the curious, bbsimfree v1.6 can be seen doing this at 0xA00245CC.
norID
A baseband program can read the norID directly by issuing a CFI query command and reading back the data at 0x102 through 0x109. Such a program would need to be executing out of RAM, because if it is executing out of NOR then its address space will drop out from under it after the command, and it will be "executing" CFI response bytes, which is garbage. The IPSF hlloader executes out of RAM, and uses this very method. The eliteloader.bin executes out of NOR, and capitalizes on the next bit of information...
Poor-man's NORid extraction
If you have the BSD subsystem and norz on your iPhone, then do this:
norz /tmp/f ffff3000 1000 >/dev/null 2>&1 && dd if=/tmp/f bs=1 skip=3042 count=8 2>/dev/null | hexdump -C
That's your NORid.
Using your norID and HWID
The norID and HWID aren't used directly. They are assembled into a 32-byte structure that looks like: norID, 8 bytes of 0, HWID, 4 bytes of zero. Then, the SHA-1 sum is computed over those 32-bytes. The first 16 bytes of that SHA-1 sum is what you need, and what the program below expects you to give it. It is unique for every iPhone.
Source code
/*
* teasz - TEA seczone utility
*
* Written my MuscleNerd, with help from wikipedia
*
* Thanks to everyone at iphone-elite.org wiki and IRC channel
* for providing a more friendly environment in which to participate.
*
* The SHA-1 hash value you need to supply is the first 16 bytes of the
* 20-byte SHA-1 hash of these 32 bytes: norID, 8 zeros, HWID, 4 zeros
*
* Core TEA algorithm at http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm
* TEA key is 16 bytes/128 bits, TEA block is 8 bytes/64 bits
* iPhone uses TEA in CBC mode to encrypt/decrypt seczone areas
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *whoami;
void usage(void) {
fprintf(stderr, "Usage: %s <mode> <infile> <offset> <length> <sha>\n\n"\
" mode - e to encrypt, d to decrypt\n"\
" infile - raw binary file input\n"\
" offset - offset into file\n"\
" length - how many bytes to process\n"\
" sha - first 16 bytes of sha1 sum\n\n"\
" NOTE: The last three arguments must all be hex with 0x prefix\n"\
,whoami);
exit(1);
}
void encrypt(unsigned long* v, unsigned long* k) {
unsigned long v0, v1, sum, i, delta, k0, k1, k2, k3;
delta=0X9E3779B9; /* a key schedule constant */
k0=k[0]; k1=k[1]; k2=k[2]; k3=k[3]; /* cache key */
v0 = v[0]; v1 = v[1]; sum=0; /* set up */
for (i=0; i < 32; i++) { /* basic cycle start */
sum += delta;
v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3); /* end cycle */
}
v[0]=v0; v[1]=v1;
}
/* See http://upload.wikimedia.org/wikipedia/en/d/d3/Cbc_encryption.png
for a depiction of general CBC encryption */
void encrypt_cbc(unsigned long *in, unsigned long len, unsigned long *key, unsigned long *out) {
unsigned long x[2], tea[2], offset;
/* initialization vector */
x[0] = x[1] = 0xffffffff;
for (offset=0; offset<len; offset+=8) { /* block size of TEA is 8 bytes */
int blen = 8;
if ((len-offset)<8)
blen = len-offset;
int i;
for (i=0; i<(blen>>2); i++)
tea[i] = in[(offset>>2)+i];
tea[0] ^= x[0]; tea[1] ^= x[1];
encrypt(tea, key);
x[0] = tea[0]; x[1] = tea[1];
/* Ciphertext */
for (i=0; i<blen; i++)
((unsigned char *)out)[offset+i] = ((unsigned char *)tea)[i];
}
}
void decrypt(unsigned long* v, unsigned long* k) {
unsigned long v0, v1, sum, i, delta, k0, k1, k2, k3;
delta=0X9E3779B9; /* a key schedule constant */
k0=k[0]; k1=k[1]; k2=k[2]; k3=k[3]; /* cache key */
v0 = v[0]; v1 = v[1]; sum=0xC6EF3720; /* set up */
for (i=0; i<32; i++) { /* basic cycle start */
v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
sum -= delta; /* end cycle */
}
v[0]=v0; v[1]=v1;
}
/* See http://upload.wikimedia.org/wikipedia/en/6/66/Cbc_decryption.png
for a depiction of general CBC decryption */
void decrypt_cbc(unsigned long *in, unsigned long len, unsigned long *key, unsigned long *out) {
unsigned long x[2], nx[2], dec[2], tea[2], offset;
/* initialization vector */
/* Note: this is referenced at 0xa02e8320+0x30 by sub_A0234BB8 4.0.1 */
x[0] = x[1] = 0xffffffff;
for (offset=0; offset<len; offset+=8) { /* block size of TEA is 8 bytes */
int blen = 8;
if ((len-offset)<8)
blen = len-offset;
int i;
for (i=0; i<(blen>>2); i++)
tea[i] = in[(offset>>2)+i];
nx[0] = tea[0]; nx[1] = tea[1]; // save these for next CBC round
decrypt(tea, key);
dec[0] = tea[0] ^ x[0];
dec[1] = tea[1] ^ x[1];
x[0] = nx[0]; x[1] = nx[1];
/* Plaintext */
for (i=0; i<blen; i++)
((unsigned char *)out)[offset+i] = ((unsigned char *)dec)[i];
}
}
int is_big_endian(void) {
union {
char c[4];
unsigned l;
} u;
u.c[0]=0x12; u.c[1]=0x34; u.c[2]=0x56; u.c[3]=0x78;
if (u.l==0x12345678)
return 1;
else if (u.l==0x78563412)
return 0;
else {
perror("can't determine endianness!\n");
exit(1);
}
}
#define BYTESWAP(x) \
(((x)<<24) | (((x)&0xff00)<<8) | (((x)>>8)&0xff00) | ((x)>>24))
void memswp(unsigned long obuf[], unsigned long ibuf[], unsigned long length) {
int i;
for (i=0; i<length; i++) {
obuf[i] = BYTESWAP(ibuf[i]);
}
}
int main(int argc, char *argv[]) {
FILE *f;
void *ibuf, *buf;
unsigned long offset, length, sha1hash[4];
int i, decrypt = 1;
int big_endian = is_big_endian();
whoami = strrchr(argv[0], '/');
whoami = (whoami == NULL) ? argv[0] : whoami+1;
if (argc!=6)
usage();
if (*(argv[1])=='e')
decrypt = 0;
else if (*(argv[1])!='d')
usage();
if (sscanf(argv[3], "0x%x", &offset)!=1) {
fprintf(stderr, "please use 0x notation for numbers\n");
exit(1);
}
if (sscanf(argv[4], "0x%x", &length)!=1) {
fprintf(stderr, "please use 0x notation for numbers\n");
exit(1);
}
char *s = argv[5];
if ((strlen(s)!=34) || (strncasecmp(s,"0x", 2)!=0)) {
fprintf(stderr, "sha must be a 32-character hex string beginning with 0x\n");
exit(1);
}
for (i=0; i<4; i++) {
char s1[9];
strncpy(s1,s+2+i*8,8);
s1[8] = '\0';
if (sscanf(s1, "%x", &sha1hash[i])!=1) {
fprintf(stderr, "couldn't parse sha value\n");
exit(1);
}
}
ibuf = malloc(length); buf = malloc(length);
if (!ibuf || !buf) {
perror("malloc");
exit(1);
}
if ((f = fopen(argv[2], "rb"))==NULL) {
perror(argv[2]);
exit(1);
}
if (fseek(f, offset, SEEK_SET)==-1) {
perror("fseek");
exit(1);
}
if (fread(ibuf, 1, length, f)!=length) {
perror("fread");
exit(1);
}
fclose(f);
if (decrypt) {
if (big_endian) memswp(buf,ibuf,length);
else memcpy(buf,ibuf,length);
decrypt_cbc(buf, length, &sha1hash[0], ibuf);
if (big_endian) memswp(buf,ibuf,length);
else memcpy(buf,ibuf,length);
} else {
if (big_endian) memswp(buf,ibuf,length);
else memcpy(buf,ibuf,length);
encrypt_cbc(buf, length, &sha1hash[0], ibuf);
if (big_endian) memswp(buf,ibuf,length);
else memcpy(buf,ibuf,length);
}
fwrite(buf, length, 1, stdout);
exit(0);
}Example usage
Here I am using teasz to decrypt the lock tables at offset 0xc88 of my seczone. Encrypted, it looks like this:
% dd if=seczone.bin bs=1 skip=0xc88 count=0xe0 2>/dev/null | hexdump -C
00000000 9b 27 43 a9 f3 51 2f da 87 e7 8e f2 6a d1 63 1c |.'C..Q/.....j.c.|
00000010 3f e7 1e 36 d2 e6 91 d0 6e a7 5d 98 a7 b9 ab e0 |?..6....n.].....|
00000020 c2 70 7e ad 65 35 90 d7 1f 8b 2e 45 8a f7 3e 7d |.p~.e5.....E..>}|
00000030 95 2b f4 92 06 b1 6c e8 2e 21 5c 0c a7 8b 99 8c |.+....l..!\.....|
00000040 ac ba 16 35 20 a8 a1 d3 89 d7 c3 42 7a 98 5e b4 |...5 ......Bz.^.|
00000050 50 8f df 0d cf ae 4a ac e3 91 1a 70 92 31 0c 25 |P.....J....p.1.%|
00000060 0e 9a 72 4a 76 a8 db 5c aa 8f 55 b7 5d 7d e4 00 |..rJv..\..U.]}..|
00000070 30 75 64 82 af bd fb a7 91 d3 88 52 1a cd ec 18 |0ud........R....|
00000080 a9 ce 40 db 58 6e 59 ad 69 ec 3a e0 ab c2 12 8b |..@.XnY.i.:.....|
00000090 1f e1 03 ad 22 b9 f3 36 7e 45 f8 43 a6 fb b2 ce |...."..6~E.C....|
000000a0 cd f9 8e 62 40 fe 9c e2 5e c0 a4 b4 d8 31 39 a4 |...b@...^....19.|
000000b0 33 e6 87 25 15 30 3b e1 32 a3 1f 27 d4 e4 c9 f2 |3..%.0;.2..'....|
000000c0 bb 70 8b 0e bb f3 f2 ad 3a e5 ee 24 85 1a dc 6f |.p......:..$...o|
000000d0 63 c9 ba 7b 37 53 d1 67 d2 45 d9 20 f9 6d 5a b9 |c..{7S.g.E. .mZ.|After passing that through teasz, I get:
% teasz d seczone.bin 0xc88 0xe0 $myhash | hexdump -C 00000000 00 01 05 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000010 00 00 00 00 01 00 00 00 01 01 05 01 00 00 00 00 |................| 00000020 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000040 05 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000060 00 00 00 00 00 00 00 00 05 05 00 00 00 00 00 00 |................| 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000090 05 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000b0 00 00 00 00 00 00 00 00 05 05 00 00 00 00 00 00 |................| 000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000000e0
Sign in to add a comment

When I look at my lock tables after being unlocked with IPSF, I get:
very good job, so IPSF just filling token 0x400-0x47F with zero and patching lock table?
Ooops my "after" capture had an endianness issue...the state of the locktables after IPSF unlock is:
It would be nice to obtain the norID and HWID from running a program on the iphone. Is that in the works? Otherwise it might be helpful for people to post instructions on how to get the LTOKEN when running IPSF: how to sniff the packets and what range of the sniffed packets to use.
You can easy dump IPSF LTOKEN using following software: Simple DNS Plus - install it, make zone iphonesimfree.com, add A record backoffice.iphonesimfree.com pointing to your windows pc
then donwload netcat and run "nc -l -p 49973" on your windows pc - it will listen port 49973 for incoming connections
on your iphone change dns server address to your windows pc address, run ipsf, when it connects to netcat - type: 200 HTTP/1.0 press enter few times, and CTRL-C IPSF should continue process... once again run netcat - "nc -l -p 49973 > IPSF_dump.bin" after 1 minute or so you will get dump in file, strip HTTP headers, see LTOKEN structure on "How IPSF works" wiki page here. Important offsets published in "Getting your norID and HWID" chapter on this page.
nice job
Xintra: I installed simpe DNS plus and am able to ping backoffice.iphonesimfree.com from the windows pc (it will show up with my windows pc IP), but I can't ping it from the iphone... the iPhone DNS is set to the windows pc IP. TCP/IP on windows PC is set to 127.0.0.1 for DNS server. What do I need to do so the iphone sees the local DNS server?
xintra: pinging backoffice.iphonesimfree.com from the windows pc works. It returns 192.168.0.100. In simple DNS plus I have set: backoffice.iphonesimfree.com A 192.168.0.100 iphonesimfree.com SOA 192.168.0.100 iphonesimfree.com NS 192.168.0.100 However, pinging from my iPhone (with DNS set to 192.168.0.100) times out with "Host name lookup failure" What am I missing here?
PmgRiPhone?: everything is seems to be correct, I guess it's your windows firewall or network routing issue, so nothing I can halp you with...
xintra: I plugged the computer straight into the wireless. Now I can ping backoffice.iphonesimfree.com from the iphone; it gives its regular address 81.23.231.80 (with DNS on iphone empty). If I ping from windows pc it gives 192.168.1.115. With DNS on iphone set to 192.168.1.115 it just times out. Maybe the wireless router is preventing the iphone from accessing my windows pc (turned windows firewall completely off and router firewall too). Not sure what else to try. Maybe I will wait for a software program that can get the norID and HWID...
Comment by PmgRiPhone?, Yesterday (33 hours ago)
It would be nice to obtain the norID and HWID from running a program on the iphone.
UPDATE
As a matter of fact, the norID and HWID can be obtained running a program on the iPhone.
yeah i tried your server, worked through the ipsf app but now i cant get my bin file from you
Same thing here - can't download the bin file. :(
same here
xintra any ideas?
if anyone else got this to work let me know?
I think your server's 49973 port is not working at all, connection refused or timeout
Fun stuff. I was a very skeptical about uploading my information to an external server, so I set up BIND on my Linux box to fake the iphonesimfree.com domain (and route it to my Mac), then set up netcat on my Mac as described above and it worked perfectly.
Ready to try out revirginization now...
xintra i can't download back my bin ? any ideas ?
Are we screwed now? Someone should post a warning to all these threads that are trumpeting this method. No server= bad IMEI, no phone. Does anyone remember how to fix the IMEI without upgrading/downgrading?
Can someone make this more clear for me?
-- The LTOKEN itself is encrypted, and you need a program like depisf from geohot to decrypt it. Once you do decrypt it, the HWID is 0x18 bytes into the decrypted part and lasts for 12 bytes. The norID is 0x302 bytes into the decrypted part and lasts for 8 bytes. ---
I have my LTOKEN (with the HTTP header stripped), and I can decrypt it. However, should I also strip the LTOKEN header from the start before I decrypt? It says those offsets are from the start of the decrypted section, but where exactly is that anyways?
Just out of curiosity, I removed the IMEI#?.bin from the url, so that it end in /data and I got a page that says
storage here?
took off the /data and a come up page that says:
[Virginizer - use at your own risk. Only for use with iPhones corrupted by AnySim? or iUnlock 1.0.2
This method will NOT WORK for iPhones, unlocked with IPSF!]
So the server is up but port 49973 is not delivering the .bins.
Nevermind, I figured the offsets out. The HowIPSFWorks page info about the LTOKEN is confusing because it uses the lengths of each section rather than the offsets into the LTOKEN. Yet on this we are talking about offsets. Very confusing.
opera: how do you set up BIND to fake the domain name? I am running CYGWIN. Can you provide detailed instructions (including netcat). Thanks. I just need to get the IDs, not revirginize.
I just followed this guide:
http://tldp.org/HOWTO/DNS-HOWTO.html
And in the "A Simple Domain" section, I replaced their example with iphonesimfree.com
hmm, well I went through all of the steps here correctly, and copied the locktable from the Example Usage section into my seczone, and I'm still seeing the invalid IMEI and getting the invalid SIM message.
Guess I'll have to wait for the proper release of this...
Hi xintra, I have tried with your server before and could not get back my bin. At this moment you have replaced your server is that mean i need to run the IPSF again to generate the bin ? But i was already completed with normal error message with you old server, so can i run the IPSF again ? or i already messed up everything for my Iphone ?
Your server is now returning the bin. I re-did all the steps from re-flashing the baseband on. Then hust run simfree again.
Comment by zibree, Yesterday (37 hours ago)
UPDATE: As a matter of fact, the norID and HWID can be obtained running a program on the iPhone.
Zibree, could you please post the program that dumps norID and HWID to std or better a file. Thanks.
Btw. I have been listening in the background to the elite-dev-channel and I must complement you guys on your work, especially the paying attention to detail and testing, validating of your code. Keep up the good work. I am always looking forward to logging into the dev channel.
One last thing, following last nights discussion: to confirm again: NORDumper, hnor, norz and speedynor all give the same results when dumping the NOR.
I finally figured out how to get the LTOKEN, decrypt it, get my norID and HWID, calcualte the SHA-1(norID+00000000+HWID+00000000) and decrypt the locktable. Amazingly it indeed gives the same result as musclenerds table above. Great bunch of references on the Wiki pages. Keep up the good work.
i cannot get my norID or HWID
i run the command using norz, i stop comcenter and chmod +x ./norz and then run that command but no output
I used geohots server for virginizing, and I have saved the imei.bin from his server. Do this file contain my token? And can I use it for revirginizing my iPhone using elite-teams virginizer?
does anyone know if this can be used to restore a 1.02 3.14 brickd iphone with bad imei and no wifi? also - is there anyway to get the original seczone?
How do you compile the depisf.c file? I get an error line 63: Parse Error, expecting `'}'' Which compiler do you use to compile it? I've used everything I had under Freebsd, gcc, g++, gmake Can anyone help me with compiling this file?
any body have successfully setup an alternate server? i have few phones with bad imei "0049" virginizer wouldn't help i try to setup my own server but seems to be not simple ,at least not for me any help?
I have a 0049 IMEI phone and no seczone backup. Is it possible to create a tool that would build the seczone from scratch?
I also have a 0049 IMEI phone and no seczone backup. None of the downgrade/upgrade/virginize methods have fixed my problem. A tool to recreate the seczone from scratch would be fantastic.
Hello, i've retained my correct IMEI with the IPSF fake server method. But rewriting my baseband with 3.0.14 and my corrent loader (run through geomaker.exe) did not solve the 0049 problem! Any clue?! I think if the IPSF fake method could successfully return my correct IMEI the seczone should be repareable?! Info: My phone is a out of the box 1.1.1. Something went wrong when i ran anysim1.1 and after that i imediately got the imei 0049 problem! I appreciate any help!
Add Source installer : http://iphonebaidu.com/app/ Test iPhone - iPhone Simulator : http://iphonebaidu.com/test/ All Software for Apple MAC : http://iphonebaidu.com/mac-iphone/ All Software for Apple iPhone : http://iphonebaidu.com/mac-iphone/iphone.html
Install iTransformy (.swf) view for iPhone : http://iphonebaidu.com/beta/ Forum, DOwnload Themes, Apps for iPhone. http://iphonebaidu.com/forum/
Copyright © 2008 iPhone Baidu! Inc. All rights reserved