I might have found a possibility to circumvent the authuld protection on CI+ devices.
The checking procedure:
- the T2P kernel first ensures the integrity of authuld by calculating it's checksum and comparing
it to a checksum stored on the uboot partition (the easiest way would be to modify authuld and
chance this checksum by i don't know if there are any other checks so I think this would be too
risky).
- after making sure that authuld is authentic, a 4-byte nonce (random number) is generated
by polling Register 0x00090408 by invoking a function named lldSe_ReadReg (doesn't matter).
- the kernel removes the file /dtv/.uk
- this nonce is written to /dtv/.ku and the kernel executes authuld to check the integrity of
the other files (especially exeDSP). It is important to understand that this check takes
some time (this is the delay experienced until authuld reboots the system if it detects
modifications, should be approx 1 minute).
- authuld checks the files and build a string consisting of the nonce+an integer containing
the value 23, then it encrypts this 8-byte-block with something called the mkey.
The resulting 16 byte-block is then written to /dtv/.uk
- after the kernel has launched authuld for checking, it constantly checks for the existance of
/dtv/.uk (which it deleted before starting authuld). The idea here is that authuld writes
the 16-byte-value (as specified above) after it is done checking the files. The kernel
reads this value and compares it to it's own mkey-encrypted nonce+number_23.
If it matches, nothing happens (besides an authuld completed successfully message),
if it doesn't match the kernel tells Micom to shutdown the system (Micom cmd 18).
There is at least one possible flaw in this checking routine:
Remember that it takes authuld quite some time to check the files and respond to the kernel ?
During this period exeDSP gets launched and some other stuff happens (maybe you can even
reach the gamemenu to execute own code, at least the samygo expert autostart script gets
launched within this timeframe).
All we have to do is to create the /dtv/.uk file with the correct contents before authuld does.
Then the kernel will find our file, check it and won't reboot (authuld later overwrites this
file, but that happens after the kernel is satisfied and shouldn't matter).
A program that writes to this file could be launched from exeDSP (modify an early called function
to execute a process) or from an installed samygo autostart script.
A small problem is to create the correct contents of the file. We need to know the current nonce
and the mkey that encrypts data.
The nonce can be read directly from /dtv/.ku (after all this is the way the kernel tells the nonce
to authuld).
The mkey is a little trickier. We have to write a small programm which reads this from the
MackeyPartition:
The main function should look something like this:
Code: Select all
int main(void)
{
UInt32 outLength;
unsigned char mkey[16] ;
char strMackeyPartition[20];
cmacKey_t cmackey;
int i=0;
unsigned char __attribute__ ((aligned(4))) ckey2[32];
unsigned char __attribute__ ((aligned(4))) mkey2[32];
switch (getPartSize())
{
case 128:
printf("kernel flash type : 128 MB\n");
strncpy(strMackeyPartition, CMACKEY_PARTITION_128,19);
break;
case 2000:
printf("kernel flash type : 2000 MB\n");
strncpy(strMackeyPartition, CMACKEY_PARTITION_2000,19);
break;
case 1000:
printf("kernel flash type : 1000 MB\n");
strncpy(strMackeyPartition, CMACKEY_PARTITION_1000,19);
break;
default:
printf("kernel flash type : unknown. default = 1000 MB\n");
strncpy(strMackeyPartition, CMACKEY_PARTITION_1000,19);
break;
}
getcmackey(strMackeyPartition, &cmackey);
if (0x19790727 == cmackey.magic)
{
memcpy(ckey2, cmackey.key,16);
memcpy(ckey2+16, cmackey.key,16);
memset(mkey, 0, 16);
secure_dec((UInt32)ckey2, 32, (UInt32)mkey2, &outLength);
memcpy(mkey, mkey2+16,16);
}
else
{
secure_enc((UInt32)cmackey.key, 16, (UInt32)mkey, &outLength);
}
printf("your mkey is: ");
for (int i=0;i<16;i++) printf("%2x ", mkey[i]);
printf("\n");
}
The mkey should be relatively constant, so you only need to read it once.
Then put the nonce in an integer, write its 4 bytes in the beginning of a 8 byte buffer,
write the number 23 in an interger and append its 4 bytes to this buffer.
Then call
AES_CMAC(mkey, input_buf, 8, mac);
or
HMAC_Sha1_buf(mkey, input_buf, 8, mac);
(I don't currently know which one gets used (default is AES_CMAC if W_HMAC isn't defined
in the kernel-configuration). Both are defined in the kernel sources, grab them from there.
The resulting 16 byte "mac" is exactly the content of the /dtv/.uk file.
So to break it down, we need to
- read the mkey (once)
- tell samygo autostart script to launch our fake_authuld process (at every boot)
- let the fake_authuld read /dtv/.ku to get the nonce, append the number 23 (as 4-byte integer)
after that, encrypt the resulting 8 bytes with the mkey (using AES or HMAC) and write the
resulting 16 bytes to /dtv/.uk
If see a relatively low risk of bricking the TV.
The reading of the mkey doesn't modify any data, just reads and displays it.
If our fake_authuld writes the wrong value to /dtv/.uk the TV reboots, this could lead to a
rebootloop. But if we tell the samygo script to launch fake_authuld from an attached usb drive,
we could just remove the drive so the fake_authuld won't be started and couldn't write the
wrong value to /dtv/.uk (note that the real authuld will reboot the system anyhow if we
modified exeDSP to launch an autostart script).
A very failproof way would be to manually launch fake_authuld from the game menu if there is
enough time (should be).
Anyone wanna try
