Pages: [1] 2 3 4
Author Topic: VAG Seed - Key Algorithm Challenge Response via CAN bus  (Read 42416 times)
Basano
Full Member
***

Karma: +68/-1
Offline Offline

Posts: 176


« on: November 12, 2013, 02:09:04 AM »

Hello everyone,

Would anyone be able to share knowledge on the Seed - Key Algorithm in the Bosch MED9.1 ECU's?

Please excuse the length of my post, I've tried to include as much detail and information as I can.

I'm interested to explore my car and have build a little test rig that handles CAN bus and the Transport Protocol 2.0 :-)

KWP Diagnostics are working nicely and I can read and compute measuring blocks, but I'm being brave and trying for something complex!

After careful reading, I've found a couple of sources of information which I've listed here for reference.


1) Seed - Key via K-Line
http://www.freediag.org/opendiag/4983.html
<attached>

2) Corporate Group Requirement Specification For Programming Control Units with Keyword Protocol 2000 Transport Protocol 2.0.pdf
<attached>


So what I've tried are the steps described in 1). Even though it's KWP over K-Line, I'm hoping it's similar for KWP over CAN bus. I've sent my ECU a request for Vendor ID (KWP 0x1A 0x92) and it's happily responded (KWP 0x5A 0x92 0x30 0x32 0x36 0x31 0x53 0x30 0x32 0x33 0x34 0x32) (ascii 0261S02342).

ms   ID   Len   D0   D1   D2   D3   D4   D5   D6   D7
82343   740   5   18   0   2   1A   92         
82348   300   1   B9                     
82355   300   8   25   0   C   5A   92   30   32   36
82360   300   8   16   31   53   30   32   33   34   32
82363   740   1   B7                     

Now in the K-Line example in the above link, only the first five bytes are used (0x30 0x32 0x36 0x31 0x53), so I've used the same for my calculations.

(0x30 + 0x32 + 0x36 + 0x31 + 0x53) & 0x3F = 0x1C

USing 0x1C as an index to the lookup table (count from the beginning until you reach the 0x1C/28dec value):

0x0A221289,0x144890A1,0x24212491,0x290A0285,0x42145091,0x504822C1,0x0A24C4C1,0x14252229,
0x24250525,0x2510A491,0x28488863,0x29148885,0x422184A5,0x49128521,0x50844A85,0x620CC211,
0x124452A9,0x18932251,0x2424A459,0x29149521,0x42352621,0x4A512289,0x52A48911,0x11891475,
0x22346523,0x4A3118D1,0x64497111,0x0AE34529,0x15398989,0x22324A67,0x2D12B489,0x132A4A75,
0x19B13469,0x25D2C453,0x4949349B,0x524E9259,0x1964CA6B,0x24F5249B,0x28979175,0x352A5959,
0x3A391749,0x51D44EA9,0x564A4F25,0x6AD52649,0x76493925,0x25DE52C9,0x332E9333,0x68D64997,
0x494947FB,0x33749ACF,0x5AD55B5D,0x7F272A4F,0x35BD5B75,0x3F5AD55D,0x5B5B6DAD,0x6B5DAD6B,
0x75B57AD5,0x5DBAD56F,0x6DBF6AAD,0x75775EB5,0x5AEDFED5,0x6B5F7DD5,0x6F757B6B,0x5FBD5DBD

Returns 0x15398989.

Next I send my ECU a seed request (KWP 0x27 0x01) and it responds back with a seed! (KWP 0x67 0x01 0x01 0xAA 0x20 0xC4)

ms   ID   Len   D0   D1   D2   D3   D4   D5   D6   D7
11176   740   5   12   0   2   27   1         
11181   300   1   B3                     
11186   300   8   2A   0   6   67   1   1   AA   20
11192   300   2   1B   C4                  
11198   740   1   BC                     


I use this seed as follows. I shift and add the bytes together and run the result through a loop that shifts and xor's. Same as in the K-Line example.

            SEED = ((RX_STR[4] << 24) + (RX_STR[5] << 16) + (RX_STR[6] << 8) + RX_STR[7]); // (0x01 << 24) + (0xAA << 16) + (0x20 << 8) + 0xC4 = 0x01AA20C4
            for (byte i = 0; i < 5; i++) {
              if ((SEED & 0x80000000) == 0) {
                SEED = 0x15398989 ^ (SEED << 1); // here I'm using the entry I got from the above lookup table
              }
              else {
                SEED = (SEED << 1);
              }             
            }   

After this, I have a value of SEED = 0x1B185F96E

I take this modified seed and decompose it back into bytes

            TX_STR[0] = 0x00;       
            TX_STR[1] = 0x06;         
            TX_STR[2] = 0x27;
            TX_STR[3] = 0x02;
            TX_STR[4] = (SEED >> 24) & 0xFF; //B1
            TX_STR[5] = (SEED >> 16) & 0xFF; //85
            TX_STR[6] = (SEED >> 8) & 0xFF; //F9
            TX_STR[7] = SEED & 0xFF; //6E


Finally, I now transmit this back to my ECU (KWP 0x27 0x02 0xB1 0x85 0xF9 0x6E), which responds back with (KWP 0x7F 0x27 0x35) Invalid Key

ms   ID   Len   D0   D1   D2   D3   D4   D5   D6   D7
11209   740   8   23   0   6   27   2   B1   85   F9
11220   740   2   14   6E                  
11225   300   1   B5                     
11496   300   6   1C   0   3   7F   27   35      
11499   740   1   BD                     


Invalid Key!

What am I missing?

Can anyone share details of the algorithms or starting points for this? Hugely appreciated!

Thanks


My car:
Audi S3 2.0TFSI 265HP 8P Model Year 2008

VCDS scan:
Monday,11,November,2013,13:02:26:53506
VCDS Version: Release 12.12.0 (x64)
                Address 01: Engine
Control Module Part Number: 8P0 907 115 H
  Component and/or Version: 2.0l R4/4V TFSI     0050
           Software Coding: 01030003180F0060
            Work Shop Code: WSC 06314

Advanced Identification
     Serial number: AUX7Z0GNFNQ0NG
     Identification: RB8-658
     Revision: 5BH16---
     Date: 13.11.07
     Test stand number: 1360
     Manufacturer number: 0129
Flash Status
     Programming Attempts: 0
     Successful Attempts: 0
     Programming Status: 00000000
     Required Conditions: 00000000
Software
     A000
     A4.8.6
Misc.
     Hardware number: 8P0 907 115 B
     Immo Challenge: AB 17 95 39

Bosch ECU Hardware ID: 0261S02342








Logged
airtite
Hero Member
*****

Karma: +12/-1
Offline Offline

Posts: 654


« Reply #1 on: November 12, 2013, 03:01:44 AM »

I cant provide any help but I am sure someone on here will step up....... I do like where this is going though.
Logged
nyet
Administrator
Hero Member
*****

Karma: +385/-44
Offline Offline

Posts: 8817


WWW
« Reply #2 on: November 12, 2013, 01:01:02 PM »

I don't know anything about seeds, but perhaps your byte order is wrong? have you tried sending the low order seed byte first?
Logged

ME7.1 tuning guide (READ FIRST)
ECUx Plot
ME7Sum checksum checker/corrrector for ME7.x

Please do not ask me for tunes. I'm here to help people make their own.

Do not PM me technical questions! Please, ask all questions on the forums! Doing so will ensure the next person with the same issue gets the opportunity to learn from your experience.
n0ble
Full Member
***

Karma: +2/-0
Offline Offline

Posts: 192


« Reply #3 on: November 12, 2013, 01:48:39 PM »

Impressive first post!!
Logged
Basano
Full Member
***

Karma: +68/-1
Offline Offline

Posts: 176


« Reply #4 on: November 13, 2013, 02:56:25 AM »

Hi all,

Thanks for the comments  Cheesy

I've got a lot of useful information out of this forum (e.g. KWP1281 formulas for calculating measuring blocks values) so I wanted to try and put something back.

Sometimes the first posts are pretty brief and don't give much to go on, so I tried to give as much information as I could!

I'll try swapping around the MSB/LSB and see what happens.

I've also seen suggestions about looking in the .bin. At a very high level:

1) Get hold of a .bin for this ECU (people have posted them on this forum, so OK)
2) Open the .bin up in a hex editor (also OK)
3) Somewhere in there would be a sequence of assembler, probably with some XOR's ...

If only it was so simple! 1) and 2) are OK, but 3) has taken peoples ages and ages. Where to even start  Grin Still, getting there is half the fun. It's a hobby for me.

Thanks
Logged
Basano
Full Member
***

Karma: +68/-1
Offline Offline

Posts: 176


« Reply #5 on: January 15, 2014, 03:48:16 AM »

Hello everyone,

Happy New Year to you all  Smiley

I’ve made some small progress. I got an clone from eBay and put together a sniffer which shows the CANBUS communications between the clone tool and the ECU.

All I’ve done at the moment is an ECU read. I’m not confident enough to try any writes!

So this is what I saw in the ECU read log.

It starts with reading some basic info about the ECU:

1A 86 – Extended ECU-Ident
1A 92 – systemSupplierECUHardwareNumber
1A 94 – systemSupplierECUSoftwareNumber
1A 9B - Item number / ECU-Ident
1A 9C – Flash Status

Then it does the Seed Key handshake:

27 03 (tool -> ECU)
67 03 3E F2 6B 40 (ECU -> tool, seed is 3E F2 6B 40)
27 04 3E F3 7C B0 (tool -> ECU, key is 3E F3 7C B0)
67 04 34 (ECU -> tool, access granted)

Worth pointing out the seed/keys are 3/4 rather than the default 1/2. Perhaps a different level of access?

Then it goes on to start a diagnostic session and read out the data, but I’m just looking at the seed/keys right now. You can see the rest of the communication in the attached log. I normally open the text file in Excel which formats the columns a bit nicer and lets me filter on what I want to see.

I did this a few times and collected the keys/seeds:

3E F2 6B 40 seed
3E F3 7C B0 key

E6 94 31 80 seed
E6 95 42 F0 key

B7 52 04 80 seed
B7 53 15 F0 key

In each case, key = (seed + 0x00011170)

0x00011170 / 70000 dec

Now VCDS also has a security access screen, where you can input a login code for a controller. If I connect to the engine ECU with my VCDS and use this value of 70000dec, security access is successful!!

But this is a very basic algorithm (key = (seed + 0x00011170). I assume this is just for read access. I guess write access would be a more challenging algorithm?

I’m a bit wary of doing a write in case I break my ecu! (I don’t have much experience with this)

I’ve attached the log file of the ecu read, some KWP docs that help explain the protocol and the bin.

 Grin
« Last Edit: January 21, 2014, 04:52:32 AM by Basano » Logged
prj
Hero Member
*****

Karma: +269/-15
Online Online

Posts: 3374


« Reply #6 on: January 15, 2014, 03:58:32 PM »

Get yourself a tool that can do BDM.
After that make a full backup of your ECU, this involves opening the ECU and making the backup.

After this, no matter WHAT you do with the ecu bar hardware damage, you will always be able to restore from backup Smiley
Logged
terok
Full Member
***

Karma: +4/-1
Offline Offline

Posts: 84


« Reply #7 on: January 16, 2014, 08:25:12 AM »

Haven't tested, but for write i'm guessing 50000 (0xC350).
Logged
Basano
Full Member
***

Karma: +68/-1
Offline Offline

Posts: 176


« Reply #8 on: January 17, 2014, 04:21:13 AM »

Get yourself a tool that can do BDM.
After that make a full backup of your ECU, this involves opening the ECU and making the backup.

After this, no matter WHAT you do with the ecu bar hardware damage, you will always be able to restore from backup Smiley

Yep, seen a cheap one on eBay. Backups are ALWAYS a good idea  Cheesy

Haven't tested, but for write i'm guessing 50000 (0xC350).

Thanks very much!

I will give this a try this evening and let you know the result.

I have feeling that there are two 'access' levels here, for want of a different word.

Seed/Key exchange 27 01/02 xx xx xx xx and Seed/Key exchange 27 03/04 xx xx xx xx

Certainly the clone tool used 27 03/04 xx xx xx xx for the ECU read. I have some ideas about how to trick the clone tool into starting an ECU write dialogue (plugging it into a simulator instead of my ECU) so I don't have to abuse my ECU.

Thanks

Logged
Basano
Full Member
***

Karma: +68/-1
Offline Offline

Posts: 176


« Reply #9 on: January 19, 2014, 02:06:24 PM »

Nope, 50000dec (0x0000C350) didn't work  Sad

Here's the trace:

R0 91201 740 5 15 0 2 27 3
R0 91203 300 1 B6
R0 91209 300 8 23 0 6 67 3 BB 32 4B
R0 91214 300 2 14 0
R0 91217 740 1 B5
R0 91379 740 8 26 0 6 27 4 BB 33 E
R0 91411 740 2 17 50
R0 91412 300 1 B8
R0 91691 300 6 15 0 3 7F 27 35 <- invalidKey
R0 91695 740 1 B6

For comparison, here's the trace of a succesful login with 70000dec (0x00011170)

R0 57186 740 5 15 0 2 27 3
R0 57188 300 1 B6
R0 57196 300 8 23 0 6 67 3 6D 2C F8
R0 57201 300 2 14 C0
R0 57205 740 1 B5
R0 57364 740 8 26 0 6 27 4 6D 2E A
R0 57404 740 2 17 30
R0 57406 300 1 B8
R0 57412 300 6 15 0 3 67 4 34 <- securityAccessAllowed
R0 57416 740 1 B6


Hmmm.
Logged
nyet
Administrator
Hero Member
*****

Karma: +385/-44
Offline Offline

Posts: 8817


WWW
« Reply #10 on: January 19, 2014, 08:57:49 PM »

Well, if it's always a multiple of decimal 10000 (what a strange choice), have you tried each one from 10000 to 90000?
Logged

ME7.1 tuning guide (READ FIRST)
ECUx Plot
ME7Sum checksum checker/corrrector for ME7.x

Please do not ask me for tunes. I'm here to help people make their own.

Do not PM me technical questions! Please, ask all questions on the forums! Doing so will ensure the next person with the same issue gets the opportunity to learn from your experience.
Basano
Full Member
***

Karma: +68/-1
Offline Offline

Posts: 176


« Reply #11 on: January 20, 2014, 03:34:41 AM »

Thanks,

I can try it. I found out (the hard way) that the timeout between incorrect attempt is 10 minutes and if you switch the ignition off, the timer simply stops and restarts once you switch it back on!

But I have an update that may lead in another direction…  Grin

I finally lashed the ecu-simulator together (at least, something that simulates the ecu role in the dialogue between ecu and clone tool). Fortunately the security access happens right after the ECU ID messages, so I don’t have to simulate very much before the seed/key stuff starts. The simulator is pretty crude but at least I don’t have to keep running out to the car with all the cables and laptop etc. (plus it’s cold!)

Now I can safely plug the clone tool into the sim and push the write button without worrying about my car.

So this is what I’ve found:

Read from ECU
Uses Security Access 27 03 xx xx xx xx
Simple algorithm (key = seed + 0x00011170) dec 70000

Write to ECU
Uses Security Access 27 01 xx xx xx xx
Complex algorithm Huh

Hmm. Different Security Accesses for read and write!

I’ve harvested some seeds from my car (just by sending it a few 27 01) and I can feed them to the clone tool using the sim.

Here are the resulting pairs (clone tool requests a seed, I send it a seed and it replies with a key)

Security Access 27 01
0C F4 23 3D Seed
C1 39 3A 1C  Key

0E F5 90 FF Seed
81 0F 42 5C Key

10 66 74 01 Seed
B3 B4 3B 58 Key

03 32 95 2C Seed
66 52 A5 80 Key

01 93 1E CA Seed
32 63 D9 40 Key

All the login codes (70000dec) use Security Access 27 03, hence why I say I think this is going in another direction for writing to the ECU.

I believe Security Access 27 01 (writing) uses the more complex revolving XOR type of algorithm, rather than the very simple addition algorithm used by Security Access 27 03 (reading)
Logged
Basano
Full Member
***

Karma: +68/-1
Offline Offline

Posts: 176


« Reply #12 on: January 21, 2014, 03:34:30 AM »

Ahha, now we are getting somewhere!

So I decided to feed some seeds to the clone tool that have easy patterns. I’m no cryptographer, but this seemed to make sense 

You can see what happens with the first simple seed below. Everything gets shifted to the left five times:

            Hex                 Binary
Seed     01 01 01 01     0000 0001   0000 0001   0000 0001   0000 0001
Key       20 20 20 20     0010 0000   0010 0000   0010 0000   0010 0000

Then I tried this seed. From the above, I now know it shifts five times. So what I’ve done here is arrange another seed with the bit pattern so the left most bit will be shifted out on the fifth shift:

            Hex                  Binary
Seed     08 01 01 01      0000 1000   0000 0001   0000 0001   0000 0001
Key       5F 9D 7D 9C     0101 1111   1001 1101   0111 1101   1001 1100

Totally transformed, but how? XOR is the operation all the examples talk about, so let’s play a bit. Start with:

Hex                 Binary
08 01 01 01     0000 1000   0000 0001   0000 0001   0000 0001

Shift this five times to the left. NB, this is a rotate. So the bit that get shifted out on the left gets shifted in on the right.

Hex                 Binary
00 20 20 21     0000 0000   0010 0000   0010 0000   0010 0001

Now XOR. We know what the input is (00 20 20 21) and we know what the output is (5F 9D 7D 9C) so we can solve for the value you XOR the input with:

          Hex                        Binary
          00 20 20 21            0000 0000   0010 0000   0010 0000   0010 0001
XOR    5F BD 5D BD          0101 1111   1011 1101   0101 1101   1011 1101
          5F 9D 7D 9C           0101 1111   1001 1101   0111 1101   1001 1100

So, we get a value of 5F BD 5D BD.

Not only does this value of 5F BD 5D BD show up in the .bin from the ECU, but it’s also present in the example algorithm posted at the beginning of the thread. Coincidence, maybe not!

Putting it all together I get this algorithm:

              for (byte i = 0; i < 5; i++) {
                if ((SEED & 0x80000000) == 0x80000000) { // can’t check the bit overflow / carry bit directly, but if the MSB is high then we can infer the next shift will set the carry bit
                  SEED = (0X5FBD5DBD ^ ((SEED << 1) | (SEED >> 31))); // since C doesn’t have a rotate as such, OR the << and >> to make a rotate
                }
                else {
                  SEED = ((SEED << 1) | (SEED >> 31)) ;
                }             
              }         

Very similar to the example algorithm and aligns with the corporate specification I posted at the beginning of the thread as well  Grin

I’ll test it out and let you know.
 
Logged
nyet
Administrator
Hero Member
*****

Karma: +385/-44
Offline Offline

Posts: 8817


WWW
« Reply #13 on: January 21, 2014, 10:00:59 AM »

Well done!

Nice to be able to send any seed you want for testing Smiley
Logged

ME7.1 tuning guide (READ FIRST)
ECUx Plot
ME7Sum checksum checker/corrrector for ME7.x

Please do not ask me for tunes. I'm here to help people make their own.

Do not PM me technical questions! Please, ask all questions on the forums! Doing so will ensure the next person with the same issue gets the opportunity to learn from your experience.
Basano
Full Member
***

Karma: +68/-1
Offline Offline

Posts: 176


« Reply #14 on: January 23, 2014, 03:29:41 AM »

OK, so I coded it up and tested it out against my MED9.1 ECU.

It works!  Grin

In summary then:

Security Access 27 01 xx xx xx xx (for writing to the ECU)

for (byte i = 0; i < 5; i++) {
    if ((SEED & 0x80000000) == 0x80000000) { /* Can’t check the bit overflow / carry
                                                                           bit directly, but if the MSB is high
                                                                           then we can infer the next shift will
                                                                           set the carry bit
                                                                     */

        SEED = (0X5FBD5DBD ^ ((SEED << 1) | (SEED >> 31))); /* Since C doesn’t have a rotate as
                                                                                                  such, OR the << and >> to make a
                                                                                                  rotate
                                                                                              */

    }
    else {
        SEED = ((SEED << 1) | (SEED >> 31)) ;
    }            
}
KEY = SEED;

Security Access 27 03 xx xx xx xx (for reading from the ECU)

KEY = (SEED + 0x00011170);

Enjoy!
Logged
Pages: [1] 2 3 4
  Print  
 
Jump to:  

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Page created in 0.032 seconds with 17 queries. (Pretty URLs adds 0s, 0q)