Series 09 Nanocommands. 1 Nanocommands..hmmm.. what's that ? As you know, a decoder of a VideoCrypt system sends some instructions to the card or receives data from the card. The most important instruction is 74hex with the following 32 bytes to the card. This 32 byte data-packet includes all the needed information to descramble the video signal. Beside the encrypted seed for the PRBS (Pseudo-Random-Byte-Sequence) generator it includes channel-id, subchannel-id, an electronic signature, scramble status (soft- or hardscrambled) and, of course, the nanocommands with their parameters. The main reason to send nanocommands is to get control about what happens inside a genuine Sky Viewing Card. For example, with a specific nanocommand you can alter the value of a RAM address inside the card or read out parts of the ROM or RAM of the smartcard. If BSkyB sends one of this 'tricky bastards' we call it an ECM (Electronic-Counter-Measure). Every time Sky sends a new (and unknown) nanocommand or parameter for a known nanocommand, we have to find out what happens inside the card. The main reason to find out the function of every single nanocommand is, that they will be used for the decryption of the PRBS seed. 2 How to decrypt nanocommands A typical 74hex instruction: BUFFER + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ E8 4F 22 9A 0C 52 2C 92 F4 14 AB 00 E3 F1 9F DA 95 DA 95 AC 98 B5 ÀÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ BYTES TO DECRYPT NANOCOMMANDS ENCRYPTED NANOCOMMANDS BUFFER + 22 23 24 25 26 27 28 29 30 31 ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ 44 18 BF 7E E7 7A F4 5E 62 46 ÄÄÄÄÄÄÄÄÄÄÄÄÄÙ MAX. 15 BYTES Steps to decrypt the nanocommands: Examples: * load BUFFER + 1 and XOR with BUFFER + 2 -> 4F XOR 22 = 6D * swap Nibbles 0-3 with 4-7 -> SWAP 6D = D6 * save value -> VALUE1 = D6 * load BUFFER + 2 and store value -> VALUE2 = 22 * load VALUE2 -> 22 * rotate one bit left -> RL 22 = 44 * add VALUE1 -> D6 + 44 = 1A * store result in NANOBUFFER -> NANOBUFFER + 0 = 1A * store result in VALUE2 -> VALUE2 = 1A * load VALUE2 -> 1A * rotate one bit left -> RL 1A = 34 * add VALUE1 -> D6 + 34 = 0A * store result in NANOBUFFER -> NANOBUFFER + 1 = 0A * store result in VALUE2 -> VALUE2 = 0A * load VALUE2 -> 0A * rotate one bit left -> RL 0A = 14 * add VALUE1 -> D6 + 14 = EA * store result in NANOBUFFER -> NANOBUFFER + 2 = EA * store result in VALUE2 -> VALUE2 = EA * load VALUE2 -> EA * rotate one bit left -> RL EA = BA * add VALUE1 -> D6 + BA = 90 * store result in NANOBUFFER -> NANOBUFFER + 3 = 90 current NANOBUFFER -> 1A 0A EA 90 * load BUFFER + 3 and XOR with NANOBUFFER + 0 -> 9A XOR 1A = 80 If the last value is 80hex then the above 74hex data packet contain nanocommands, otherweise the data packet contain NO nanocommands ! * load NANOBUFFER + 2 -> VALUE3 = EA * in this last step you have to XOR fifteen bytes with VALUE3 starting with BUFFER + 12 and to store the results in the NANOBUFFER BYTECOUNT = 0 load BUFFER + 12 [+BYTECOUNT] <ÄÄÄÄÄÄÄÄÄÄ¿ XOR with VALUE3 ³ store into NANOBUFFER [+BYTECOUNT] ³ ³ BYTECOUNT = BYTECOUNT + 1 ³ BYTECOUNT = 15 ? if not GOTO ÄÄÄÄÄÄÄÄÄÄÄÙ For example, after executing the last step, the NANOBUFFER contain the following values: 09 1B 75 30 7F 30 7F 46 72 5F AE F2 55 94 0D ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ NANOCOMMANDS ³ GARBAGE 3 Detailed description 3.1. Nanocommand 03hex (1 byte) 03 Break and execute the last 64 Iterations with the current index into the NANOBUFFER 3.2 Nanocommand 09hex (3 bytes) 09 MSB LSB Set address for nanocommand 30hex, execute hash with value 63hex and 00hex. Example: POINTER_MSB = MSB POINTER_LSB = LSB VALUE = 63hex CALL HASH VALUE = 00hex CALL HASH INDEX_INTO_NANOBUFFER + 3 3.3 Nanocommand 0Chex (2 bytes) Execute hash with 00hex twice. Example: VALUE = 00hex CALL HASH VALUE = 00hex CALL HASH INDEX_INTO_NANOBUFFER + 2 3.4 Nanocommand 0Fhex (2 bytes) 0F XX Write value XX to card. The current address for this write command is stored in card address BFhex (MSB) and C0hex (LSB). After executing the write command, this nanocommand will act like nanocommand 03hex (Break and exit). Example: POINTER_HIGH = @BF ; load indirect from BFhex POINTER_HIGH = POINTER_HIGH AND 1Fhex ; only bit 0-4 POINTER_LOW = @C0 ; load indirect from C0hex @POINTER = XX ; store value into address 3.5 Nanocommand 11hex (4 bytes) 11 XX MSB LSB This nanocommand writes value XX into the card ram (addresses 00-FF). If the address is greater than 00FFhex, the write command will be skipped. Also this command sets the address for nanocommand 30hex. Example: POINTER_HIGH = MSB POINTER_LOW = LSB ; set pointer for card write If POINTER_HIGH <> 0 then ÄÄÄÄ¿ ; if address is greater 00FFhex ³ ; then skip write command @POINTER = XX ³ ; otherwise write value ³ VALUE = XX <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ CALL HASH VALUE = 00hex CALL HASH INDEX_INTO_NANOBUFFER + 4 Some known addresses: Cardram address 08hex WRITE-ONLY --------------------- Select ROMPAGE 1 or 2 depending on value XX, Bit 7 If bit 7 is set to one, ROMPAGE 1 will be used, if bit 7 is set to zero, ROMPAGE 2 will be used with nanocommand 30hex. After executing the page select, you have to AND value XX with B7hex and to set bit 6 (OR with 40hex). After that store the value into ram address 81hex. Cardram address 81hex READ/WRITE --------------------- This is very simple - just AND value XX with B7hex and set bit 6 (OR with 40hex) and write the value to address 81hex. Cardram address EEhex READ/WRITE --------------------- This address seems to be the internal pointer INTO the nanobuffer. First of all you have to write value XX to address EEhex, then value XX is the NEW pointer into the buffer. For example: Nanobuffer + 0 1 2 3 4 5 6 7 8 9 A B C ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ 11 80 00 88 30 00 11 0A 00 EE 30 00 03 ^ ³ current index into buffer (=6) INDEX_INTO_NANOBUFFER = 0Ahex (this is the new value) Nanobuffer + 0 1 2 3 4 5 6 7 8 9 A B C ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ 11 80 00 88 30 00 11 0A 00 EE 30 00 03 ^ ³ NEW index into buffer INDEX_INTO_NANOBUFFER = INDEX_INTO_NANOBUFFER - 2 Nanobuffer + 0 1 2 3 4 5 6 7 8 9 A B C ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ 11 80 00 88 30 00 11 0A 00 EE 30 00 03 ^ ³ NEW index into buffer After processing nanocommand 11hex (see above) INDEX_INTO_NANOBUFFER = INDEX_INTO_NANOBUFFER + 4 Nanobuffer + 0 1 2 3 4 5 6 7 8 9 A B C ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ 11 80 00 88 30 00 11 0A 00 EE 30 00 03 ^ ³ CURRENT index after nanoprocessing The above example will skip nanocommand 30hex 00hex ! After checking the above addresses 08hex, 81hex and EEhex you have to check for addresses LOWER than AAhex. If the current address is lower than AAhex, the write command will be skipped - this means all addresses LOWER than AAhex are READ-ONLY addresses. If the current address is HIGHER or equal AAhex, you have to write value XX to that address. 3.6 Nanocommand 14hex (5 bytes) 14 xx xx xx xx Execute hash with value 00hex TWICE. Example: VALUE = 00hex CALL HASH VALUE = 00hex CALL HASH INDEX_INTO_NANOBUFFER + 5 3.7 Nanocommand 19hex (1 byte) 19 Execute hash with current index into nanobuffer and execute hash with value 19hex. Example: VALUE = INDEX_INTO_NANOBUFFER CALL HASH VALUE = 19hex CALL HASH INDEX_INTO_NANOBUFFER + 1 3.8 Nanocommand 1Dhex (2 bytes) 1D xx Execute hash with value 00hex TWICE Example: VALUE = 00hex CALL HASH VALUE = 00hex CALL HASH INDEX_INTO_NANOBUFFER + 2 3.9 Nanocommand 24hex (3 bytes) 24 xx xx Execute hash with value 00hex TWICE Example: VALUE = 00hex CALL HASH VALUE = 00hex CALL HASH INDEX_INTO_NANOBUFFER + 3 3.10 Nanocommand 28hex (5 bytes) 28 AA BB CC DD First of all write all parameters from AA-DD to cardram addresses 8Dhex-90hex. After that execute hash with the last value DD, and execute hash again with the current index into the nanobuffer. Example: CARDRAM_ADDRESS 8Dhex = AA CARDRAM_ADDRESS 8Ehex = BB CARDRAM_ADDRESS 8Fhex = CC CARDRAM_ADDRESS 90hex = DD VALUE = DD CALL HASH VALUE = INDEX_INTO_NANOBUFFER CALL HASH INDEX_INTO_NANOBUFFER + 5 3.11 Nanocommand 30hex (2 bytes) 30 CNT This is the READ-COMMAND, this means, with this command you can read out the card RAM or ROM. The current address for this command was set from nanocommand 09hex or 11hex. The second byte CNT is the counter, how much bytes will be read from RAM or ROM. CNT is a 6-bit value, therefore a maximum of 127 bytes can be read with a single command. If CNT is zero, only one byte will be read. First of all you have to mask bits 0-6 with AND 7Fhex. After that you have to check, if the MSB of the current address is zero or not. If the MSB is zero (or in other words lower than 0100hex) the card RAM will be read. If the MSB is NOT zero, the card ROM (0100-1FFF) will be read. With every single byte the hash function will be executed. Example: COUNTER = CNT AND 7Fhex ; load bytecounter (bit 0-6) if POINTER <> 007Ehex then Ä¿<Ä¿ ; cardram address 7Ehex ? POINTER = 00FEhex ³ ³ ; yes -> set to address FEhex ! VALUE = @POINTER <ÄÄÄÄÄÄÄÄÙ ³ ; read from cardram or cardrom CALL HASH ³ ; execute hash with value ³ VALUE = COUNTER ³ ; store current counter COUNTER = COUNTER - 1 ³ ; decr. counter if VALUE <> 0 then ÄÄÄÄÄÄÄÄÄÄÙ ; counter <> 0 ? VALUE = @POINTER ; load last value CALL HASH ; execute hash VALUE = COUNTER ; load counter (= FFhex) CALL HASH ; execute hash INDEX_INTO_NANOBUFFER + 2 3.12 Nanocommand 34hex (4 bytes) 34 xx xx xx Execute hash with value 00hex TWICE Example: VALUE = 00hex CALL HASH VALUE = 00hex CALL HASH INDEX_INTO_NANOBUFFER + 4 3.13 Nanocommand 39hex (2 bytes) 39 XX Write value XX to cardaddress 92hex and execute hash with value XX, after that execute hash with value 00hex. Example: CARDRAM_ADDRESS 92hex = XX VALUE = XX CALL HASH VALUE = 00hex CALL HASH INDEX_INTO_NANOBUFFER + 2 3.14 Nanocommand 3Chex (1 byte) 3C Execute hash with value 3Chex TWICE Example: VALUE = 3Chex CALL HASH VALUE = 3Chex CALL HASH INDEX_INTO_NANOBUFFER + 1 3.15 Nanocommand 41hex (1 byte) 41 Execute hash with value 41hex and 00hex. Example: VALUE = 41hex CALL HASH VALUE = 00hex CALL HASH INDEX_INTO_NANOBUFFER + 1 3.16 Nanocommand 46hex (1 byte) 46 Exit nanoproccessing .. all done. 3.17 Nanocommand 49hex (1 byte) 49 Execute hash with value 60hex and 49hex. Example: VALUE = 60hex CALL HASH VALUE = 49hex CALL HASH INDEX_INTO_NANOBUFFER + 1 3.18 Nanocommand FFhex (1 byte) FF Execute hash with value 00hex TWICE Example: VALUE = 00hex CALL HASH VALUE = 00hex CALL HASH INDEX_INTO_NANOBUFFER + 1 *end of file*