Show us what you've built? And how you crack the CEM: in car, on the bench?regula wrote: ↑17 Feb 2025, 00:43 I need help with getting cem pin from P2 2006. Cem number 30786889.
Using quality components i built the Teensy hardware by vtl diagram and it communicates with the cem with no problems. Only thing is that only the 0 byte (first pin number) is showing up with consistency. Byte [1] and [2] are always random and the pin is not cracked.
What could be wrong?
Vida CEM swapping
-
vtl
- Posts: 4723
- Joined: 16 August 2012
- Year and Model: 2005 XC70
- Location: Boston
- Has thanked: 114 times
- Been thanked: 603 times
Re: Vida CEM swapping
-
Treur
- Posts: 126
- Joined: 16 November 2024
- Year and Model: 2007 V70
- Location: Estonia
- Has thanked: 3 times
- Been thanked: 6 times
Something is already starting to form...
We built this miracle with CKaev
I would like to make j2534 out of it. It is already starting to process USB commands, but I need to figure out how to write an API.
It looks ugly, i know, but wires are not touching each other, everything is soldered, copper wires are used, CAN wires to OBD are twisted, quality 12V->5V step-down converter is used for sufficient power, nothing is ordered from Ali and are bought from local electronic shop.
Still only the [0] byte is found with 100% consistency, [1] and [2] are always different.
Still only the [0] byte is found with 100% consistency, [1] and [2] are always different.
Code: Select all
[1] byte latency runs
best candidates ordered by latency:
0: 07 lat = 87460
1: 00 lat = 87308
2: 88 lat = 87293
3: 78 lat = 87276
4: 98 lat = 87276
5: 82 lat = 87256
6: 54 lat = 87254
7: 30 lat = 87254
8: 74 lat = 87250
9: 38 lat = 87248
10: 50 lat = 87248
11: 84 lat = 87246
12: 02 lat = 87246
13: 80 lat = 87242
14: 60 lat = 87242
15: 70 lat = 87228
16: 81 lat = 87228
17: 41 lat = 87224
18: 94 lat = 87222
19: 03 lat = 87220
20: 90 lat = 87216
21: 08 lat = 87214
22: 68 lat = 87212
23: 83 lat = 87210
24: 28 lat = 87200
25: 44 lat = 87196
26: 01 lat = 87190
27: 10 lat = 87190
28: 58 lat = 87188
********************
best candidates ordered by latency:
0: 47 lat = 174782
1: 89 lat = 174742
2: 22 lat = 174737
3: 75 lat = 174736
4: 07 lat = 174720
5: 93 lat = 174712
6: 46 lat = 174692
7: 29 lat = 174672
8: 32 lat = 174668
9: 73 lat = 174648
10: 26 lat = 174610
11: 13 lat = 174528
12: 80 lat = 174528
13: 12 lat = 174486
14: 00 lat = 174464
15: 17 lat = 174460
16: 08 lat = 174458
17: 41 lat = 174344
18: 01 lat = 174336
19: 06 lat = 174288
20: 10 lat = 174284
21: 28 lat = 174278
22: 50 lat = 174266
23: 70 lat = 174244
24: 48 lat = 174234
25: 30 lat = 174234
26: 58 lat = 174232
27: 94 lat = 174230
28: 60 lat = 174212
**********************
best candidates ordered by latency:
0: 89 lat = 436973
1: 93 lat = 436834
2: 07 lat = 436757
3: 75 lat = 436746
4: 73 lat = 436696
5: 46 lat = 436648
6: 47 lat = 436648
7: 29 lat = 436584
8: 22 lat = 436582
9: 32 lat = 436564
10: 26 lat = 436444
11: 13 lat = 436340
12: 17 lat = 436318
13: 12 lat = 436188
14: 00 lat = 436162
15: 80 lat = 435904
16: 08 lat = 435814
17: 28 lat = 435752
18: 10 lat = 435720
19: 70 lat = 435608
20: 41 lat = 435604
21: 48 lat = 435528
22: 50 lat = 435466
23: 01 lat = 435465
24: 06 lat = 435456
**********************
best candidates ordered by latency:
0: 93 lat = 873767
1: 07 lat = 873662
2: 47 lat = 873631
3: 73 lat = 873463
4: 89 lat = 873434
5: 75 lat = 873420
6: 46 lat = 873352
7: 32 lat = 873300
8: 26 lat = 873254
9: 22 lat = 873178
10: 29 lat = 872958
11: 13 lat = 872598
********************
best candidates ordered by latency:
0: 73 lat = 1747664
1: 75 lat = 1747494
2: 47 lat = 1747438
3: 07 lat = 1747289
4: 89 lat = 1747157
5: 93 lat = 1746962
*******************
best candidates ordered by latency:
0: 75 lat = 2621155
1: 73 lat = 2620998
2: 47 lat = 2620783
******************
best candidates ordered by latency:
0: 75 lat = 3494636
1: 73 lat = 3494403
...
pin[1] choose candidate: 75
[2] byte latecny runs:
best candidates ordered by latency:
0: 86 lat = 87432
1: 19 lat = 87402
2: 46 lat = 87382
3: 29 lat = 87370
4: 15 lat = 87368
5: 76 lat = 87358
6: 26 lat = 87352
7: 92 lat = 87338
8: 95 lat = 87334
9: 85 lat = 87332
10: 51 lat = 87328
11: 38 lat = 87324
12: 62 lat = 87322
13: 96 lat = 87322
14: 23 lat = 87320
15: 94 lat = 87320
16: 72 lat = 87320
17: 99 lat = 87316
18: 13 lat = 87314
19: 39 lat = 87312
20: 22 lat = 87310
21: 75 lat = 87308
22: 49 lat = 87308
23: 24 lat = 87306
24: 93 lat = 87306
25: 56 lat = 87304
26: 91 lat = 87304
27: 36 lat = 87304
28: 60 lat = 87302
*******************
best candidates ordered by latency:
0: 60 lat = 174678
1: 96 lat = 174373
2: 70 lat = 174364
3: 56 lat = 174344
4: 09 lat = 174332
5: 48 lat = 174322
6: 39 lat = 174319
7: 67 lat = 174310
8: 13 lat = 174310
9: 65 lat = 174303
10: 34 lat = 174300
11: 29 lat = 174296
12: 62 lat = 174286
13: 76 lat = 174286
14: 22 lat = 174284
15: 36 lat = 174280
16: 17 lat = 174276
17: 11 lat = 174273
18: 21 lat = 174268
19: 72 lat = 174265
20: 61 lat = 174256
21: 51 lat = 174254
22: 77 lat = 174242
23: 12 lat = 174226
24: 44 lat = 174218
25: 15 lat = 174214
26: 38 lat = 174210
27: 57 lat = 174208
28: 66 lat = 174208
*******************
best candidates ordered by latency:
0: 60 lat = 436392
1: 70 lat = 435830
2: 77 lat = 435780
3: 17 lat = 435724
4: 34 lat = 435711
5: 96 lat = 435702
6: 51 lat = 435699
7: 65 lat = 435662
8: 36 lat = 435654
9: 39 lat = 435566
10: 44 lat = 435559
11: 11 lat = 435554
12: 21 lat = 435542
13: 09 lat = 435541
14: 22 lat = 435532
15: 72 lat = 435530
16: 67 lat = 435530
17: 29 lat = 435503
18: 12 lat = 435500
19: 48 lat = 435496
20: 62 lat = 435486
21: 13 lat = 435484
22: 76 lat = 435426
23: 56 lat = 435386
24: 61 lat = 435310
*********************
best candidates ordered by latency:
0: 60 lat = 873316
1: 70 lat = 871852
2: 17 lat = 871418
3: 51 lat = 871408
4: 77 lat = 871390
5: 36 lat = 871332
6: 65 lat = 871314
7: 11 lat = 871264
8: 44 lat = 871234
9: 39 lat = 871050
10: 34 lat = 871041
11: 96 lat = 870904
********************
best candidates ordered by latency:
0: 60 lat = 1746026
1: 70 lat = 1743214
2: 17 lat = 1742760
3: 77 lat = 1742627
4: 36 lat = 1742418
5: 51 lat = 1741912
*******************
best candidates ordered by latency:
0: 60 lat = 2619869
1: 70 lat = 2615543
2: 17 lat = 2613718
*******************
best candidates ordered by latency:
0: 60 lat = 3492739
1: 70 lat = 3487020
...
pin[2] choose candidate: 60
Candidate PIN 84 75 60 -- -- -- : brute forcing bytes 3 to 5 (3 bytes), will take up to 646 seconds
Progress: 0%..5%..10%..15%..20%..25%..30%..35%..40%..45%..50%..55%..60%..65%..70%..75%..80%..85%..90%..95%..
PIN is NOT cracked in 2077.82 seconds
done-
vtl
- Posts: 4723
- Joined: 16 August 2012
- Year and Model: 2005 XC70
- Location: Boston
- Has thanked: 114 times
- Been thanked: 603 times
Transceivers still can be fake.regula wrote: ↑18 Feb 2025, 13:17 It looks ugly, i know, but wires are not touching each other, everything is soldered, copper wires are used, CAN wires to OBD are twisted, quality 12V->5V step-down converter is used for sufficient power, nothing is ordered from Ali and are bought from local electronic shop.
Still only the [0] byte is found with 100% consistency, [1] and [2] are always different.
Things to try:
- set clock rate to 180 MHz
- sirloin's one_pass branch: https://github.com/cmolson/volvo-cem-cr ... e/one_pass
- cem_freq_align branch: https://github.com/vtl/volvo-cem-cracke ... freq_align
-
alfons38
- Posts: 4
- Joined: 26 April 2021
- Year and Model: s80
- Location: Denmark
- Has thanked: 1 time
- Been thanked: 1 time
Now is working 
But have questions about ground on schematics.
Where connection ground?
And can i have switch to change between master and p3 script without pc?
But have questions about ground on schematics.
Where connection ground?
And can i have switch to change between master and p3 script without pc?
- Attachments
-
- schematic_LCD.png (93.74 KiB) Viewed 4142 times
-
al1Volvo
- Posts: 34
- Joined: 22 March 2024
- Year and Model: Volvo V50 2011
- Location: France
- Has thanked: 3 times
- Been thanked: 13 times
You only need to connect all ground together with your power ground.
Regarding the switch you cannot switch between branch without refactoring the code to merge both branch in one.
Regarding the switch you cannot switch between branch without refactoring the code to merge both branch in one.
-
Treur
- Posts: 126
- Joined: 16 November 2024
- Year and Model: 2007 V70
- Location: Estonia
- Has thanked: 3 times
- Been thanked: 6 times
What are the differences between your code and the code of these forks?vtl wrote: ↑18 Feb 2025, 13:43Transceivers still can be fake.regula wrote: ↑18 Feb 2025, 13:17 It looks ugly, i know, but wires are not touching each other, everything is soldered, copper wires are used, CAN wires to OBD are twisted, quality 12V->5V step-down converter is used for sufficient power, nothing is ordered from Ali and are bought from local electronic shop.
Still only the [0] byte is found with 100% consistency, [1] and [2] are always different.
Things to try:
- set clock rate to 180 MHz
- sirloin's one_pass branch: https://github.com/cmolson/volvo-cem-cr ... e/one_pass
- cem_freq_align branch: https://github.com/vtl/volvo-cem-cracke ... freq_align
-
dikidera
- Posts: 1304
- Joined: 15 August 2022
- Year and Model: S60 2005
- Location: Galaxy far far away
- Has thanked: 67 times
- Been thanked: 175 times
Now that I have resumed my re work on the TCM, I have created a few logs with variables which I consider to be state changes of the physical transmission state. Of course might not be, but it does signal that the transmission is progressing along a shift or is holding a certain state steady.
Quite a few variables have a state that begins(usually) from h'A or 16 all the way to h'63 or 99. the increments are not linear from 16 to 17, but in particular steps, e'g from h'A to h'14 to h'1E or even h'18. I've seen 5E, 5D.
Well h'14 = A + A and h'14 += A = h'1E so maybe that is important but who knows.
Now this could be anything. My first thought was this represented the model of the valve body. E.g Shift valves, modulators, clutches, bands,sprags etc in various states, but it could entirely be something else. Of course there are at least 10 more I have not logged.

h'101 = 1-2 upshift process I've made a slight mistake in the image, and E2 is the next possible gear. The 3-2 process is actually something like h'207 so like the sign bit set, or something similar. In any case, anything h'1XX is upshift, anything h'2xx is downshift processing.
For anyone interested my 2-3 shift is measured at 2.5 seconds, 4.1 times longer than the standard 500-600ms it should only take.
I plan to optimize my logger to fetch RPM from the CAN bus rather than query the TCM and remove the torque logging as it isn't important for me to know it.
The limitation is that the TCM logic goes like so:
<main tcm loop for shifting>
<send state data to CAN for ECM>
<process D2 commands>
any state changes that happen within 'main tcm loop' for shifting will be overwritten by the time 'process D2 commands' is executed.
Here is an IDA python plugin which I requested the various AI tools to produce(since my time is better spent elsewhere). The purpose of the plugin is to find two strings or disassembled instructions within a single basic block. It doesn't do flow analysis, but it gets the job done.
Quite a few variables have a state that begins(usually) from h'A or 16 all the way to h'63 or 99. the increments are not linear from 16 to 17, but in particular steps, e'g from h'A to h'14 to h'1E or even h'18. I've seen 5E, 5D.
Well h'14 = A + A and h'14 += A = h'1E so maybe that is important but who knows.
Now this could be anything. My first thought was this represented the model of the valve body. E.g Shift valves, modulators, clutches, bands,sprags etc in various states, but it could entirely be something else. Of course there are at least 10 more I have not logged.

h'101 = 1-2 upshift process I've made a slight mistake in the image, and E2 is the next possible gear. The 3-2 process is actually something like h'207 so like the sign bit set, or something similar. In any case, anything h'1XX is upshift, anything h'2xx is downshift processing.
For anyone interested my 2-3 shift is measured at 2.5 seconds, 4.1 times longer than the standard 500-600ms it should only take.
I plan to optimize my logger to fetch RPM from the CAN bus rather than query the TCM and remove the torque logging as it isn't important for me to know it.
The limitation is that the TCM logic goes like so:
<main tcm loop for shifting>
<send state data to CAN for ECM>
<process D2 commands>
any state changes that happen within 'main tcm loop' for shifting will be overwritten by the time 'process D2 commands' is executed.
Here is an IDA python plugin which I requested the various AI tools to produce(since my time is better spent elsewhere). The purpose of the plugin is to find two strings or disassembled instructions within a single basic block. It doesn't do flow analysis, but it gets the job done.
Code: Select all
import idaapi
import idautils
import idc
def find_instructions_in_basic_blocks():
# Get search strings from user
str1 = idaapi.ask_str("", 0, "Enter first instruction pattern:")
if not str1:
return
str2 = idaapi.ask_str("", 0, "Enter second instruction pattern:")
if not str2:
return
str1_lower = str1.lower()
str2_lower = str2.lower()
matches = []
# Iterate through all functions
for func_ea in idautils.Functions():
function = idaapi.get_func(func_ea)
flowchart = idaapi.FlowChart(function)
# Check each basic block
for block in flowchart:
found_first = False
found_second = False
# Iterate through instructions in block
ea = block.start_ea
while ea < block.end_ea:
disasm = idc.GetDisasm(ea).lower()
if str1_lower in disasm:
found_first = True
if str2_lower in disasm:
found_second = True
# Early exit if both found
if found_first and found_second:
func_name = idc.get_func_name(func_ea)
matches.append((
func_name,
func_ea,
block.start_ea,
block.end_ea
))
break
ea = idc.next_head(ea, block.end_ea)
# Print results
print(f"\nFound {len(matches)} matching basic blocks:")
for idx, (name, func_ea, start, end) in enumerate(matches, 1):
print(f"\nMatch {idx}:")
print(f" Function: {name} ({func_ea:x})")
print(f" Block range: {start:x} - {end:x}")
# Print instructions from the matching block
print(" Instructions:")
ea = start
while ea < end:
print(f" {ea:x}: {idc.GetDisasm(ea)}")
ea = idc.next_head(ea, end)
if not matches:
print("\nNo blocks found containing both patterns")
# Execute the script
if __name__ == "__main__":
find_instructions_in_basic_blocks()
Last edited by dikidera on 25 Feb 2025, 16:21, edited 1 time in total.
-
vtl
- Posts: 4723
- Joined: 16 August 2012
- Year and Model: 2005 XC70
- Location: Boston
- Has thanked: 114 times
- Been thanked: 603 times
One_pass does something to interrupts, but I forgot what. It works better with P1 CEMs and some of P2 CEMs, but fails on others.Treur wrote: ↑21 Feb 2025, 03:13What are the differences between your code and the code of these forks?vtl wrote: ↑18 Feb 2025, 13:43 - sirloin's one_pass branch: https://github.com/cmolson/volvo-cem-cr ... e/one_pass
- cem_freq_align branch: https://github.com/vtl/volvo-cem-cracke ... freq_align
CEM freq align was an attempt to recover a latency precision lost in a chain of transitions through multiple clock domains.
MCU inside CEM runs at certain clock speed (clock domain), the latency we want to observe is originated in this domain. The signal is then passing through the CAN-bus, which works at a different, much lower clock speed. The original latency signal gets distorted by undergoing this transition in CAN transceiver. CAN transceiver on the receiving side is interlocked with the sender, but it has a significant jitter*. Latency signal gets distorted yet again. Next, there's ARM MCU in Teensy working at its own frequency, which adds more noise to the signal. What the cracker code operates with is a very dirty latency signal that it tries to detect using primitive statistic function. I wish I knew math better, the whole detection algorithm can be improved a lot.
Anyways, by knowing CEM MCU clock speed we can recalculate statistical buckets in that clock domain and place latency measured into the buckets in a manner that aligns with CEM's instructions execution rate better. Say, we have a signal jitter X, but we can't know how much jitter each part of the system contributed to the final X. By forcibly mapping the latency over frequency of originating domain we reduce uncertainty about how many more instructions did the CEM run for this pin code sequence. This algo cracked some hard to crack CEMs better, but, again, reduced the success rate for others.
No silver bullet.
[*] The pin 2 (where we measure the latency) was originally connected directly to CAN low signal just for the reason to avoid one clock domain transition, which improves detection probability, but is unsafe for MCU electrically.
Last edited by vtl on 16 Oct 2025, 08:51, edited 3 times in total.
-
dikidera
- Posts: 1304
- Joined: 15 August 2022
- Year and Model: S60 2005
- Location: Galaxy far far away
- Has thanked: 67 times
- Been thanked: 175 times
I have concluded that automotive MCUs are very resistant to electrical instability. You don't want to know what even happened to my ETM, as I was connected to the MCU pins directly. There was some ground issue. And it survived just fine.
-
- Similar Topics
- Replies
- Views
- Last post
-
- 1 Replies
- 6396 Views
-
Last post by RickHaleParker
-
- 5 Replies
- 8644 Views
-
Last post by forumoto






