Login Register

Vida CEM swapping

A mid-size luxury crossover SUV, the Volvo XC90 made its debut in 2002 at the Detroit Motor Show. Recognized for its safety, practicality, and comfort, the XC90 is a popular vehicle around the world. The XC90 proved to be very popular, and very good for Volvo's sales numbers, since its introduction in model year 2003 (North America). P2 platform.
Post Reply
sirloins
Posts: 43
Joined: 5 November 2020
Year and Model: 2010 V50 T5 AWD M66
Location: Ottawa, Canada
Been thanked: 3 times

Re: Vida CEM swapping

Post by sirloins »

Wired everything up to try this on a P1 CEM.

Here is the table after the first byte is attempted. This is with 60 samples @ 720MHz
0: 00 = 745842
1: 01 = 689474
2: 20 = 679683
3: 02 = 669757
4: 40 = 663192
5: 80 = 646146
6: 10 = 644802
7: 06 = 644233
8: 04 = 642060
9: 82 = 640920
10: 30 = 634416
11: 08 = 630059
12: 03 = 628131
13: 60 = 626381
14: 41 = 624963
15: 18 = 620912
16: 12 = 614366
17: 38 = 612569
18: 14 = 612036
19: 28 = 611523
20: 16 = 610421
21: 34 = 609595
22: 78 = 608717
23: 32 = 608479
24: 24 = 608364

Seems very suspicious that single bit entries come up first (01, 20, 40, 80, 10 etc).

Unless someone knows where this is stored in flash/eeprom. Another option would be to potentially take all 6 byte sequences from flash/eeprom. Then write a program to switch the order around and try them all.

Back of the napkin math, assuming 256K flash, that is approx 256 different sequences of 6 bytes. The re-ordering is 720 different combinations per 6-byte sequence. So 256000 * 720 = 184 million. 1200 keys/sec gives about 42 hours.

Update: Wanted to see why my numbers varied so much compared to vtl's video.

I decided to continually send the read part number command:
good.jpg
good.jpg (300.84 KiB) Viewed 2408 times
Timing is very consistent of course.

Here is what the unlock command returns:
bad.jpg
bad.jpg (109.01 KiB) Viewed 2408 times
I believe perhaps they fixed the security issue with this command.

vtl
Posts: 4727
Joined: 16 August 2012
Year and Model: 2005 XC70
Location: Boston
Has thanked: 114 times
Been thanked: 606 times

Post by vtl »

You need to know the order of the bytes in PIN sequence comparison code. For CEM-L the order is not 0 through 5. Timing attack relies on that knowledge. If you have a P1 CEM dump (any, not from your car specifically) it is possible to disassemble it and find the routine. P2 CEM has a simple routine consisting of "compare" + "jump-if-not-equal" opcodes, 6 pairs.

The periodic latency jitter is a good sign that the timing attack still can be mounted.
Last edited by vtl on 10 Nov 2020, 18:52, edited 1 time in total.

sirloins
Posts: 43
Joined: 5 November 2020
Year and Model: 2010 V50 T5 AWD M66
Location: Ottawa, Canada
Been thanked: 3 times

Post by sirloins »

Thanks vtl. I actually have 3 complete dumps from the CEM which has been useful for comparison purposes.

I put them up here if anyone else is interested: https://drive.google.com/drive/folders/ ... sp=sharing

I have been playing around with IDA etc mostly learning new things. I'll dig into the disassembly some more and let you guys know what I find.

Again, thanks for your help and code!

vtl
Posts: 4727
Joined: 16 August 2012
Year and Model: 2005 XC70
Location: Boston
Has thanked: 114 times
Been thanked: 606 times

Post by vtl »

Would you be so kind to add a disassembly for one of the dumps? =) I don't have anything set up...

sirloins
Posts: 43
Joined: 5 November 2020
Year and Model: 2010 V50 T5 AWD M66
Location: Ottawa, Canada
Been thanked: 3 times

Post by sirloins »

I will as soon as I have something. I am new to using this program.

The P1 CEM architecture has two MC91S12 processors. All of the information so far I have found has been on the second (or right) processor. It is 256K of Flash, 4K EEPROM, 12K ram. It is only 16-bit though, so in order to access all of that Flash, it has a "page window" that points to a block of flash.
It has 32K of this flash "Fixed" and then a 16k window that can be mapped to any of the other flash areas.

Anyway, all that to say, once I have at least the fixed portion of Flash done, I will share it.

vtl
Posts: 4727
Joined: 16 August 2012
Year and Model: 2005 XC70
Location: Boston
Has thanked: 114 times
Been thanked: 606 times

Post by vtl »

Datasheet: http://www.ece.utep.edu/courses/web3376 ... 6BDGV2.pdf On page 22 it says about the device memory map:

$0000 - $0FFF EEPROM
$1000 - $3FFF RAM
$4000 - $7FFF Fixed Flash EEPROM array incl. 0.5K, 1K, 2K or 4K Protected Sector at start
$8000 - $BFFF Flash EEPROM Page Window
$C000 - $FFFF Fixed Flash EEPROM arrayincl. 0.5K, 1K, 2K or 4K Protected Sector at end and 256 bytes of Vector Space at $FF80 - $FFFF

"Note that after reset the bottom 1k of the EEPROM ($0000 - $03FF) are hidden by the register space." - clobbered by IO ports, like serial and CAN.

MCU2-EEPROM has all FFs in that range, so MCU2 might be the one having the PIN.

Now the question: is the P1 PIN BCD-encoded, like in P2? Or is it in full byte range, 0x00-0xFF?

sirloins
Posts: 43
Joined: 5 November 2020
Year and Model: 2010 V50 T5 AWD M66
Location: Ottawa, Canada
Been thanked: 3 times

Post by sirloins »

Yep, I have it all loaded up. I have the vector map and everything setup and found the can receive functions etc.

Basically, there are 16 pages of 16K memory and so now I get to the point where the code is calling into functions on the non-fixed flash storage window. Ideally, I would somehow have all the pages loaded dynamically into that window..

Example:

USER_VEC:FF92 _CAN4_receive: fdb $410E
Goes to 410E...
ROM:410E jmp loc_50ED
Goes to 50ED...

ROM:50ED loc_50ED: ; CODE XREF: ROM:410E↑j
ROM:50ED ldd #$671F
ROM:50F0 call $84B0, #$3B
ROM:50F4 rti

The call $84B0, #$3B basically sets the page window to 0x3B, then calls into 0x84B0.

So I just don't have a good way to load page 0x3B dynamically like that, but it might not matter. I am going to create a new instance, load page 3B into the window and take it from there.

If there are calls to other pages, I will then create more instances.. It won't be pretty, but I should be able to trace the can receive functionality.

sirloins
Posts: 43
Joined: 5 November 2020
Year and Model: 2010 V50 T5 AWD M66
Location: Ottawa, Canada
Been thanked: 3 times

Post by sirloins »

I found the key order and code on the P1 CEM.

I will post the disassembly, but I ended up finding a function (as you described) that was comparing 6 bytes. A bunch of cmp, bne etc.

Details:

It is still BCD as with the P2 CEM. (so each pin byte is 0x00->0x99)
It is located at ROM address 0xFBEF8

The order is: 5, 2, 1, 4, 0, 3

So in my dump:
0xFBEF8: 66 49 55 54 05 19

Now re-ordering it:
19 55 49 05 66 54

./cansend can0 000FFFFFE#50EB195549056654
can0 00000003 [8] 50 B9 00 00 00 00 00 00

Response byte 2 is 00, normally with failed attempts it will be:
can0 00000003 [8] 50 B9 02 00 00 00 00 00
Pin_location_P1.jpg
Pin_location_P1.jpg (137.33 KiB) Viewed 2374 times

Also here is a comparison of two different modules at this address, there is also something at 0xFBEF5 that is different on both.
cem_pin2.jpg

vtl
Posts: 4727
Joined: 16 August 2012
Year and Model: 2005 XC70
Location: Boston
Has thanked: 114 times
Been thanked: 606 times

Post by vtl »

sirloins wrote: 11 Nov 2020, 08:20 I found the key order and code on the P1 CEM.

I will post the disassembly, but I ended up finding a function (as you described) that was comparing 6 bytes. A bunch of cmp, bne etc.

Details:

It is still BCD as with the P2 CEM. (so each pin byte is 0x00->0x99)
It is located at ROM address 0xFBEF8

The order is: 5, 2, 1, 4, 0, 3
Excellent! :)
sirloins wrote: 11 Nov 2020, 08:20 ./cansend can0 000FFFFFE#50EB195549056654
./ - ah, I see a Unix(-like) fellow... ;)

sirloins
Posts: 43
Joined: 5 November 2020
Year and Model: 2010 V50 T5 AWD M66
Location: Ottawa, Canada
Been thanked: 3 times

Post by sirloins »

I will work on an update to the Arduino code you posted.

I noticed a couple of differences with trying to get it to work on the P1 CEM. The responses come in sort of two time periods. Also, the pin does not need to be shuffled when sent (it is checked in the order it is received, but against the shuffled Flash location). I am confident that this method will work on the P1 CEM with a few tweaks.

There is a grouping around 80us and another around 140us. This is what is causing all of my 'lat' numbers to be similar/varying. I can visually tell that there is more variance with the correct byte in terms of response time so I will offer up a new algorithm once I have verified it.

Here is the code that checks the PIN on the P1:

Code: Select all

ROM:FE38 ; =============== S U B R O U T I N E =======================================
ROM:FE38
ROM:FE38
ROM:FE38 check_pin:
ROM:FE38                 pshx
ROM:FE39                 pshy
ROM:FE3A                 tfr     d, y
ROM:FE3C                 ldx     #$FEF8          ; Load pin from Flash
ROM:FE3F                 ldaa    1,y+
ROM:FE41                 cmpa    5,x
ROM:FE43                 bne     return_false
ROM:FE45                 ldaa    1,y+
ROM:FE47                 cmpa    2,x
ROM:FE49                 bne     return_false
ROM:FE4B                 ldaa    1,y+
ROM:FE4D                 cmpa    1,x
ROM:FE4F                 bne     return_false
ROM:FE51                 ldaa    1,y+
ROM:FE53                 cmpa    4,x
ROM:FE55                 bne     return_false
ROM:FE57                 ldaa    1,y+
ROM:FE59                 cmpa    0,x
ROM:FE5B                 bne     return_false
ROM:FE5D                 ldaa    0,y
ROM:FE5F                 cmpa    3,x
ROM:FE61                 beq     return_true
ROM:FE63
ROM:FE63 return_false:                           ; CODE XREF: check_pin+B↑j
ROM:FE63                                         ; check_pin+11↑j ...
ROM:FE63                 ldab    #0
ROM:FE65                 bra     return
ROM:FE67 ; ---------------------------------------------------------------------------
ROM:FE67
ROM:FE67 return_true:                            ; CODE XREF: check_pin+29↑j
ROM:FE67                 ldab    #1
ROM:FE69
ROM:FE69 return:                                 ; CODE XREF: check_pin+2D↑j
ROM:FE69                 puly
ROM:FE6A                 pulx
ROM:FE6B                 rts
ROM:FE6B ; End of function check_pin
ROM:FE6B
ROM:FE6B ; ---------------------------------------------------------------------------

Post Reply
  • Similar Topics
    Replies
    Views
    Last post