Anatomy of an Optical Medium Authentication (Part 1)
Each data frame has a size of 2064 bytes; 16 bytes more than the payload. The first 4 bytes of each data frame is called ID, and contains, next to some flags, the Physical Sector Number (PSN). Each data frame, and, as we see later, all other frames, have an associated, hopefully unique, PSN. Several ranges of PSNs are reserved for special data (more about that… yes, later), but let’s just say that the data frame containing the first user sector has the PSN 0x30000, the second one 0x30001 etc. You get the idea.
When the drive searches for a specific sector, it will decode the ID values of the incoming datastream until it reaches the requested PSN (additional seek algorithms might move the pickup if the PSN is too far away, or already passed). Because the drive needs to decode the correct ID on the fly, it must be protected with an error-correction code. Thus, the next 2 bytes, called IED (ID Error Detection Code), store a rs(6,4)-code (Reed-Solomon) of the ID field. This helps the drive to correct read errors of the ID field.The next 6+2048 bytes are payload. The final 4 remaining bytes is an error detection code, called EDC. It cannot be used to recover broken data, but it serves as a last way to detect uncorrected data. It’s calculated over the rest of the data, including ID, IED, the magic 6 bytes and the 2048 bytes of payload data.
The 2048 bytes, starting at offset 12, are the user payload. The magic 6 bytes are not really documented. They are used in DVD-Video applications, but we don’t need to care about them. They are just there.The 2048 main bytes have an additional property; they are scrambled with an LFSR-based bitstream, to prevent DC. The LFSR-sequence is documented in section 17 of the ECMA-docs, and have one parameter, the “initial pre-set value”, or “seed”. This value is based on some bits of the PSN, so the scrambling pattern isn’t completely static.
The EFM+-decoded data is then NRZI-encoded and written to disc; here, pits and lands are created.
Now GODs use the same scrambling string, however, with an additional offset of 0x3C00. Thus, 0x30000 is scrambled with bytes 0x3c00..0x43ff. Furthermore, ID7..4 must be XORed with a per-game constant when reading PSN >= 0x30010. The game-specific constant is based on a simple checksum of the first 6 bytes of the user-image (“gameid”) - the first ECC block (PSN 0x30000) uses zero instead. Thus, the offset for a sector into the scrambling table isn’t ID7..4*0x800 anymore, but 0x3c00 + (ID7..4 ^ gameid-checksum) *0x800. (Yes, this might be > 32767. Just repeat the string in these case)For PSNs less than 0x30000, i.e. the lead in, the original DVD scrambling seed is used. (As a side note, “NR-Media”, i.e. DVD-Rs specially burned for development, don’t have the 0x3C00-offset, but instead use a XOR value of 0x9 for the whole media, including the lead-in. That makes it so much more complicated to dump those discs using a PC drive, because it cannot even read the PFI/DMI.)
But all of this is just obfuscation. It makes it harder, but still possible, to read the actual content from the disc using a PC DVD-ROM.
0xA9, 0x20, 0x98, 0x65, 0x92, 0xF5, 0x12, 0x2C,
0xB6, 0xBE, 0x05, 0x37, 0x1C, 0x0C, 0x08, 0x5D,
0x3B, 0x48, 0x69, 0x6E, 0x67, 0xA4, 0xB5, 0x6A,
0xE8, 0x14, 0xE2, 0x78, 0x3E, 0xFF, 0x15, 0x17,
0x40, 0x46, 0x31, 0xE6, 0xF0, 0x8F, 0x42, 0x43,
0xE4, 0x87, 0xCD, 0xAB, 0x9B, 0x3E, 0x9C, 0x26,
0xC5, 0x8E, 0x38, 0x04, 0xBF, 0x6B, 0x3D, 0xD7,
0x37, 0xFB, 0xFE, 0xC0, 0x33, 0x05, 0xC5, 0xC0,
0x0E, 0x43, 0x6E, 0x82, 0x12, 0xB2, 0x3A, 0xF3,
0x76, 0xFD, 0x1A, 0xC7, 0x2B, 0xCD, 0x78, 0x87,
0xAF, 0x4B, 0xD6, 0xA5, 0xC3, 0xFF, 0x2B, 0x7F,
0x05, 0x93, 0x2C, 0xAA, 0xD5, 0x82, 0x17, 0xB6,
0x89, 0xD9, 0xE7, 0x52, 0xAC, 0x2E, 0x38, 0xA9,
0x44, 0x24, 0xE9, 0x2B, 0xA9, 0x4D, 0x23, 0xFA,
0xEE, 0x07, 0x03, 0xF3, 0xED, 0xDC, 0xC6, 0x00,
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x4B, 0x47, 0x53, 0x43, 0x01, 0x04, 0x95, 0x17,
0x21, 0x00, 0x11, 0x7D
| decryption key | | data0 |
a9 20 98 65 92 f5 12 2c b6 be 05 37 1c 0c 08 5d
| data 1 | | decrypted data .. ..
3b 48 69 6e 67 a4 b5 6a*19 d4 03 2c 1c 02 45 aa
23 17 03 2c 03 ff 3c 30 49 43 03 2c 25 ff 3b 55
0e 26 03 2c 0d ff 3c 54 2e d7 03 2c 12 ff 4c 8c
25 c0 03 2c 17 ff 46 da*15 f3 27 ed c2 ff 3b 63
ed 87 bb 89 58 ff aa 10 db 7f 0a 48 89 ff 9e 5b
d1 b6 f4 5e 6f ff a3 15 d6 a9 d1 84 f5 ff f9 b8
.. .. | | BCA_78 | | user data
86 fa eb 78 5e ff 15 de ff ff 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
.. .. |
4b 47 53 43 01 04 95 17 21 00 11 7d
19d4 032c1c 02 45 aa
2317 032c03 ff 3c 30
4943 032c25 ff 3b 55
0e26 032c0d ff 3c 54
2ed7 032c12 ff 4c 8c
25c0 032c17 ff 46 da
Using my previous hack, I could capture the bitstream of these PSNs. I modified my bitstream decoder to dump out the raw recording frames of the PSNs in question. If we, for example, look at PSN 0x32c17, we notice the following:
940 22 24 41 04 88 09 09 10 49 09 09 24 11 01 02 12
950 22 40 40 92 10 92 42 04 89 11 11 21 02 48 92 21
960 02 20 92 20 40 08 91 10 42 12 10 28*40 00 00 00 << mind the zeros
970 00 00 00 00 00*29 02 00 10 11 11 08 42 44 08 24
980 48 48 22 14 24 14 28 51 45 12 00 a2 08 50 84 24
The obviously interesting thing here are the string of zeros, which begins approx. at offset 0x96D. It consists of at least 68 bits of zeros, which is an otherwise forbidden value - the used EFM+ encoding makes sure that there is a maximum of 11 subsequent zeros are allowed between ones. This is done to keep the receiver clock in sync with the bitstream. This long string of zeros is definitely a violation of the encoding specifications. If we calculate the relative position inside the sector, it starts at bit 0x96D*8, which is 19304. Measured in payload bits, i.e. after EFM+, this would be half of it, which is 9652. If we compare this to the value in the BCA challenge (0x25c0=9664), we notice that’s it’s very close to this. Random conincidence? Let’s take a look at the other sectors. The left side is the result of searching zeros strings within the recording frames, using a simple tool. The right side is the information encoded in the BCA, and the diff between the found value and the encoded value:
PSN 00032c03, 30 zeros @231e , BCA: 0x2317 (diff=-7)
PSN 00032c08, 40 zeros @18e0
PSN 00032c0d, 3c zeros @0e2a , BCA: 0x0e26 (diff=-4)
PSN 00032c12, 4b zeros @2ed1 , BCA: 0x2ed7 (diff=6)
PSN 00032c17, 44 zeros @25c2 , BCA: 0x25c0 (diff=-2)
PSN 00032c1c, 45 zeros @19d4 , BCA: 0x19d4 (diff=0)
PSN 00032c21, 3f zeros @07ec
PSN 00032c25, 30 zeros @494a , BCA: 0x4943 (diff=-7)
PSN 00032c2a, 31 zeros @3e96
PSN 00032c30, 40 zeros @13b2
PSN 00032c35, 46 zeros @0a9c
[...]
Isn’t this beatiful? In case you wonder, an additional, fixed offset of 0x1E has been applied, which probably accounts for the sync length.
Such a mark is also much longer than the width of the track. Thus, not only one sector is affected, but a number of sectors which are all at the same angular position. It is unclear if the drive is able to detect the angular position of a certain bit, but this would be an additional (and important!) anti-copy measure: It’s nearly impossible to predict which sector bit positions align next to each other.
Actually, we can see in the log above, a much larger number of sectors is affected. To verify our theory that all of these affected bit positions are in fact from the same six marks, we can calculate the distance between zeros from two sectors. Actually we will assume that six consecutive zero-strings starting at n are from the six marks, and the n+6th string is next to the first one, just a revolution later:
(picture missing, sorry)
Based on this assumption, let’s assign a bit position of pos_mark_in_bits=PSN*19344+offset_in_payload_bits to each zero-string; 19344 is the length of a sector after EFM+-decode. The begin of the n’th-zero-string should lie right next to the beginof the n+6’th zero string. If we calculate these distances, they should correspond to the circumference of the track at the specified position. We can also assume that it will slightly increase with increasing PSNs because they are more outer, thus the circumference increases slightly.
Let’s take a look at the output - the last value is the difference between this zero-string and six zero-strings ago, divided by the sector length:
PSN 00032c70, 40 zeros @201a <29.642525>
PSN 00032c75, 3a zeros @143a <29.642680>
PSN 00032c7a, 3b zeros @0256 <29.642887>
PSN 00032c7e, 3b zeros @43ba <29.643455>
PSN 00032c83, 38 zeros @390e <29.643300>
PSN 00032c89, 4c zeros @0e36 <29.643507>
PSN 00032c8e, 4c zeros @0529 <29.643455>
PSN 00032c92, 40 zeros @44da <29.643507>
PSN 00032c97, 3e zeros @32f9 <29.643662>
PSN 00032c9c, 30 zeros @28d2 <29.643921>
PSN 00032ca1, 46 zeros @1e25 <29.643869>
PSN 00032ca6, 40 zeros @3ee2 <29.644127>
PSN 00032cab, 48 zeros @35da <29.644386>
PSN 00032cb0, 3b zeros @2a01 <29.644696>
PSN 00032cb5, 30 zeros @1826 <29.645006>
PSN 00032cba, 33 zeros @0dfd <29.644903>
PSN 00032cbf, 3d zeros @0350 <29.644903>
PSN 00032cc4, 4d zeros @240e <29.644955>
PSN 00032cc9, 4d zeros @1b08 <29.645058>
PSN 00032cce, 46 zeros @0f31 <29.645161>
PSN 00032cd2, 3e zeros @48e9 <29.645316>
PSN 00032cd7, 35 zeros @3ec4 <29.645523>
PSN 00032cdc, 3e zeros @3420 <29.645988>
PSN 00032ce2, 4e zeros @0952 <29.646195>
PSN 00032ce7, 4e zeros @0051 <29.646454>
PSN 00032ceb, 3c zeros @4009 <29.646402>
PSN 00032cf0, 3b zeros @2e32 <29.646454>
PSN 00032cf5, 39 zeros @240e <29.646505>
PSN 00032cfa, 3c zeros @196e <29.646712>
PSN 00032cff, 53 zeros @3a2a <29.646402>
What we see is the a measurement of the circumference; let’s calculate the radius of the track at the PSN position. 29.64 sectors x (2 x 19344) bits/sector are approx. 1146712 bits per revolution. The nominal width of one bit is 133.3nm again, so we are at a circumference of 152894972 nm, or 152mm. This corresponds to a radius of 24.33mm; this is right next to the BCA, which ends at 22.5mm (see J.4.3). This also aligns with the additional marks you can see when holding the disc against light.