GM 16216588 - Hacking

American Delco GM ECUs and PCMs, ALDL, OBD 1.5.
User avatar
Posts: 86
Joined: Wed Dec 02, 2015 4:13 am

GM 16216588 - Hacking

Postby quadstar87 » Sat Apr 23, 2016 4:19 am

Hi All!

After chatting with Antus, I wanted to start up a thread to get some insight on getting into this PCM. I'm attempting to pick up where a few others left off and first figure out the Seed/Key or security algorithm before I get an AVT cable and get into reading/writing at 4x speeds. I'm going to list every thing I have done so far and the specs on this unit and see where it goes. TIA!

The current dilemma i'm trying to sort through is why this PCM seems to respond to normal ELM 322/327 requests for a SEED and KEY response but doesn't unlock with any of the 256 GM algorithms. Maybe going back a few steps will help me better understand this? I have a great understanding of the OBD-I setup and the reverse/assembly and data mapping, but flash memory is all new to me.

GM 16216588
6.5L GM Diesel 4L80E 1996-2000 (OBD-2 J1850 VPW)

High Res Board Image:

(Following is quoted from an old site "1000cows" that is no longer active)
"Parts on the OBD-2 version of the board:
16055199 = voltage regulator
16166240 = quad driver module with diagnostics
16034993 = stepper motor driver
20686 = SAE J1850 transceiver and controller
66285 = PLCC-68, Delphi IOR, mapped at $1400
16202476 = PLCC-68, MC68HC11F1. 1024 RAM & 448k EEPROM
39985 = PLCC-68, timer I/O module
16183784 = Intel PLCC32 AN28F010 128k x 8 flash memory module
16206550 = ?

I/O Assignments:
AN2 = Transmission force current monitor
AN4 = battery voltage
AN5 = boost pressure, via Sallen-Key filter
AN6 = analogue mux
AN7 = EGR/baro pressure, via Sallen-Key filter
PAI = 4004 pulse per mile VSS input
TIC1 = Pin C15, VSS
TIC2 = Pin C12, transmission input shaft speed, through
84523 buffer
TIC3 = 8X CMP signal (low-res pump encoder signal). Also
fed into 16180988 IC.
TIC4 = 4X CKP signal (from engine CKP). Also fed into
16180988 IC.
TOC4 = backup injector pulse width generation
TOC3 = I/O pin disables injector from TIO chip, timer
channel used for 160 Hz task scheduler
TOC2 = TCC PWM generation
PD5 = powerdown to power supply IC
PG0 = ODM2-7
PG1 = ITS-9 (ITS phase)
PG2 = ITS-6 (ITS phase)
PG3 = Firmware bank selection

AN Mux:
MUX0 = pin B8, glow plug voltage monitor
MUX1 = pin B11, fuel temperature signal
MUX2 = pin A12, diagnostic switch input
MUX3 = Pin C8, ECTS voltage
MUX4 = pin B9, spare, 220k pulldown
MUX5 = pump calibration
MUX6 = QDM1-14 fault input
MUX7 = pin C13, glow plug relay supply voltage
MUX8 = QDM2-14 fault input
MUX9 = pin B4, A/C request
MUX10 = pin B12, intake air temperature
MUX11 = pin D10, optical sensor 5V power supply
MUX12 = Pin B5, unused, 20V range, 3k pullup to key power
MUX13 = pin C9, Transmission temperature sensor
MUX14 = APP 2 sensor 5V power supply
MUX15 = Flash memory Vpp monitor

1800.7 = PCS Low Drive
1800.6 = TCC on/off output (4L60E)
1800.5 = shift solenoid
1800.4 = shift solenoid
1800.3 = EGR vent valve
1800.2 = Service Throttle Lamp
1800.1 = ITS Enable
1800.0 = Glow plug relay enable
1802.7 = AMUX3
1802.6 = AMUX2
1802.5 = AMUX1
1802.4 = AMUX0
1802.3 = Pin E2 - 4WD axle switch
1802.2 = Pin E3 - Performance shift mode switch
1802.1 = Pin E4 - Manual shift mode switch
1802.0 = Pin F3 - cruise on/off
1804.7 = Pin F11 - cruise resume/accel
1804.6 = Pin F15 - cruise set/coast
1804.5 = Pin E10 - PRNDL B
1804.4 = Pin E9 - PRNDL C
1804.3 = Pin E8 - PRNDL A
1804.2 = Pin F5 - TCC Brake Switch
1804.1 = Pin A6 - Brake Switch
1804.0 = Pin A6 - PTO request
1807.3 = MIL
1807.2 = Read pump trim resistor enable
1807.1 = Pin C9 Transmission Temp Pullup Select
1807.0 = Pin C8 IATS Pullup Select
1808 (PWM) = PCS current control
180A (PWM) = Boost modulator control
180C (PWM) = spare, not sure what it is used for yet. Probably the 3-2 shift solenoid, 4L60E.
180E (PWM) = EGR frequency

16FA.1 = ODM chip select to retrieve diagnostic
16FA.2 = ODM chip select to retrieve diagnostic
1472 = closure time response
147C = timing delay counter
147E = fuel quantity counter
1480 = split pulse delay counter
1482 = pilot quantity counter (first pulse)
140C = MAF time-since-last-pulse (pin C3 of the 32 pin
BROWN connector, NOT pin E1 (or sometimes called pin C1 of connector C3). THIS
IS WRONG in some service schematics!
140A = MAF pulse counter

This is a 68HC11 processor which should be very similar to
that used in the OBD-I version. It is a bit unusual (to my mind) to use a 68HC11
on the OBD-II ECM when pretty much all of the OBD-II petrol ECM's went to
68332's. I guess Ford pushed the EEC-V (8065, a 8096 variant) just into the
2000's before going over to the PowerPC's so why not, I guess. Just to be a pain
in the arse, the flash memory has some of its address lines swapped around.
There's space for two 32k memory pages (bank swapped using pin PG3) and one 24k
non-banked page shared between calibration and common (non-banked) code.
Communication is via SAE J1850 instead of SCI."

Some of the address swapping info is on another site along with a direct flash dump done thru HC11 UART and the dos program prog11.exe:
See later posts in this thread for more info on this.

Deviations for different years:
-'96-'97 do not have EVO/Passlock
-'98+ has a security learn procedure and waits for go/no-go from the EVO/Passlock in the ignition key cylinder
-L56/Light Duty sometimes had a MAF but it can be tuned out since it was used for EGR
-Later years (unknown exactly) implemented real-time cylinder misfire detection

Added 4/23/2016 : Wiring pinouts for a '99 PCM. Thanks to Glagulator @ DieselPlace! Note, don't follow the service manuals for this unit...they aren't all correct but this is. I was able to repin a harness connector from a 350 truck and shave off the locating pins of the connector to make my bench test setup.
Connector C3 Pinout
(224.17 KiB) Downloaded 343 times
Connector C2 Pinout
(206.33 KiB) Downloaded 316 times
Connector C1 Pinout
(275.02 KiB) Downloaded 353 times
Last edited by quadstar87 on Fri Jun 24, 2016 8:41 am, edited 8 times in total.

User avatar
Posts: 86
Joined: Wed Dec 02, 2015 4:13 am

Re: GM 16216588 - Hacking

Postby quadstar87 » Sat Apr 23, 2016 4:28 am

The current setup i'm using to brute force the SEED/KEY is an old school ELM 322 that I have hooked up on a bench test setup.

Here's the Terminal syntax:
Code: Select all
>AT SH 6C 10 FO

>27 01
67 01 4F 99
*SEED is 4F 99

>27 02 [i]KEY[/i]
67 02 35
67 02 36

*I've also tried header AT SH 6C FE F1 and went thru all 256 GM algos for the matching KEY

[update]The PlanetHax tool does work with this PCM! I'll list the correct Key(s) once I verify on multiple PCM's

The OSID and VIN also spit out correctly when I use the PlanetHAX brute force tool and an ELM 322. Some goofy characters come back in the terminal but I was assuming those are just something the ELM doesn't know how to handle. They don't cause any issues with the brute force scan, however.
Last edited by quadstar87 on Tue Apr 26, 2016 1:06 am, edited 1 time in total.

Site Admin
User avatar
Posts: 6273
Joined: Sat Feb 28, 2009 8:34 pm

Re: GM 16216588 - Hacking

Postby antus » Sat Apr 23, 2016 9:47 am

From an initial look at that dump on gearhead it is defianatly rubbish data. None of it looks like calibration data, or HC11 code. If that prog11 is a Motorola tool its probably not able to support GM style bank switching which is required to map the 128kbyte flash in to 64kbyte of HC11 address space.

I think your going to need a starting point, a factory tool or something that can read it which you can use to see how it does it. Are you aware of any such thing existing?
Have you read the FAQ? For lots of information and links to significant threads see here: viewtopic.php?f=7&t=1396

Site Admin
User avatar
Posts: 6273
Joined: Sat Feb 28, 2009 8:34 pm

Re: GM 16216588 - Hacking

Postby antus » Sat Apr 23, 2016 11:35 am

I found a whole thread with some good info intermixed here: ... -2249.html

It seems tunercat winflash can write this pcm, but there is not a way to read it, so you need a bin file to begin with (and the one linked above is corrupt). If you have TIS access you might be able to flash an update and grab a bin out of a in intermediate temp directory or something like that.
Have you read the FAQ? For lots of information and links to significant threads see here: viewtopic.php?f=7&t=1396

User avatar
Posts: 86
Joined: Wed Dec 02, 2015 4:13 am

Re: GM 16216588 - Hacking

Postby quadstar87 » Sat Apr 23, 2016 11:45 am

The "can't be read" part is the piece I'm currently trying to shed light on. I figured if I could get past the security, then I would be able to enlighten the community on why it can't be read out, or dermtermine that it can be read out but the current tool available blocks you from doing it.

I know someone who has desoldered the flash and read it directly then used a utility program to rebuild the data. I'm not sure what that utility was however and the files were lost in a Hard Drive crash. It can be dumped to 2 64k files and readdressed for disassembly. The seed and key would be in EEPROM if I could figure that out too.

User avatar
Posts: 4304
Joined: Mon Jan 04, 2010 10:23 am

Re: GM 16216588 - Hacking

Postby The1 » Sat Apr 23, 2016 12:47 pm

I'm yet to find anything that handles doing disassembly and reAssembly of banked 128k Roms for 68hc11 so for my code I have just been making a hand comented notes for the mods I do and manually edit the bins. The only other thing I can think of doing is using tunerpro patch system.

Site Admin
User avatar
Posts: 6273
Joined: Sat Feb 28, 2009 8:34 pm

Re: GM 16216588 - Hacking

Postby antus » Sat Apr 23, 2016 4:50 pm

Ahh I get it now. Erikje states that "this is due to a non 1-to-1 matching of the address lines from the CPU to the flash. I have checked the mapping between the Flash (Intel N28F010) and the CPU (Motorola MC68HC11F1). The 17th address line has no direct connection to the CPU".

So pin 17 is connected to the bank switching hardware, this is expected. But the corruption is as he says, address line swapping. So there are 16 address lines, and some or all of them connect to different places on the cpu, which is a basic form of obfuscation. There are tools around to try and solve this kind of puzzle from the emulator scene.

The last line of the file is:

94 C5 1E 04 86 FF 23 F8 04 EB 04 C6 CE 1D 61 1F

and perhaps should be:

67 1A 7F 75 FF BF FF BF 62 36 62 38 62 38 62 3E

so now to try and figure out how the address lines are swapped/mapped and we can probably recover Erikje's file.

The file is attached to this post if anyone wants to have a go.
(128 KiB) Downloaded 321 times
Have you read the FAQ? For lots of information and links to significant threads see here: viewtopic.php?f=7&t=1396

User avatar
Posts: 86
Joined: Wed Dec 02, 2015 4:13 am

Re: GM 16216588 - Hacking

Postby quadstar87 » Sun Apr 24, 2016 1:02 am

I've created a list of the 256 possible keys for Seed 4F 99 also. This was created using the 256 possible GM algorithms that are out in cyberspace. Just attaching this to show the progression, I'm sure we'll lock it down to a specific one soon (actually we have but I need to get a few other PCM's to try it on)

*For the ones that are only 3 characters, they need a leading 0 added

256 Keys for Seed 4F 99 with Algo.txt
(2.73 KiB) Downloaded 370 times

4/23/2016: Adding Google Play Link for the GM Seed/Key app
This is a cool app the developer just updated for us to use. For anyone that hasn't seen it yet.

User avatar
Posts: 86
Joined: Wed Dec 02, 2015 4:13 am

Re: GM 16216588 - Hacking

Postby quadstar87 » Sun Apr 24, 2016 2:33 pm

I will come back and clean up this thread on Monday when I have a chance, but for now, the Planethax tool did get the matching seed/key tonight so I can check that off the list. :punk:

On to read/write and sending a few diagnostic commands I think may work.

One of the biggest annoyances on these things is needing a tool that can send commands that initiate a TDC offset learn for the injection pumps so I can try to sniff that out of a scan tool to implement also.

Site Admin
User avatar
Posts: 6273
Joined: Sat Feb 28, 2009 8:34 pm

Re: GM 16216588 - Hacking

Postby antus » Sun Apr 24, 2016 6:31 pm

I wrote up some code that could virtually re-map input pins, and began by randomly swapping any 2 pins and then checking if the last line was correct. This was a time optimization as I figured there might be some chance of brute forcing the mapping while I was out for the day. Not so. I had no luck implementing the C combination generators around the net as those I tried work only with a subset of the input data. This would have not been a problem in the end but I was assuming that all pins could be swapped and was going for a total solution. Then I recalled sabercatpuk's thread about the saturn pcm of a similar era here: ... =377#p4046 and specifically that he had swapped some address pins around to get a dump of that pcm. So I modified my code to not brute force and entered the pin mappings he had reported. Bingo! Descrambled copy of Erikje's bin attached, as well as the descrambling code I used. I could put the pin mappings in the initialisation but I'll leave it like this as its easier to use as a base that can be modified for further experimentation on the next address swapped bin we come across.

:punk: :driving:

Update: the original code missed the high bit, and the attached bin was corrupt. This code is now fixed and the good bin is on thread page 8.

Code: Select all
#include <stdio.h>

// Address line descrambler by antus/

int getbit(int data, int bit);
int setbit(int data, int bit);
int binarycompare(char *s, char *d, int length);
void bitmap(int data);

    char bin[128*1024];
    char target[128*1024];
    FILE *f;
    int i;
    int t;
    int g;
    char map[17]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};

    // load bin
    if ((f=fopen("16216588-addresslinesswapped.bin","rb"))==NULL) {
        printf("Couldnt open bin\n");
    for (i=0; i<128*1024; i++) bin[i]=fgetc(f);

    // Thanks to sabercatpuck
    // "by the way specifically it was the A1-A13, A2-A12, A3-A11, and A10-A14 pairs that were swapped"


    for (i=0x0; i<0x20000; i++) {
        // set each bit from the mapped source bit
        for (g=0;g<17;g++) { // include the high bit
            if (getbit(i, g)) {
                t=setbit(t, map[g]);
        target[i]=bin[t]; // save the new data

    // save bin   
    if ((f=fopen("16216588.bin","wb"))==NULL) {
        printf("Couldnt open bin\n");
    for (i=0; i<128*1024; i++) fputc(target[i], f);

int getbit(int data, int bit) {
    return data&(1<<bit)?1:0;

int setbit(int data, int bit) {
    int b=(1<<bit);
    return data+=b;

// function below are useful for development but are not needed
int binarycompare(char *s, char *d, int length)
    int i;
    for (i=0;i<length;i++) {
        if (s[i] != d[i]) return 0;
    return 1;

void bitmap(int data) {
    printf("bitmap of %04X: %c%c%c%c %c%c%c%c %c%c%c%c %c%c%c%c\n", data,
            getbit(data, 15)?'1':'0',
            getbit(data, 14)?'1':'0',
            getbit(data, 13)?'1':'0',
            getbit(data, 12)?'1':'0',
            getbit(data, 11)?'1':'0',
            getbit(data, 10)?'1':'0',
            getbit(data, 9)?'1':'0',
            getbit(data, 8)?'1':'0',
            getbit(data, 7)?'1':'0',
            getbit(data, 6)?'1':'0',
            getbit(data, 5)?'1':'0',
            getbit(data, 4)?'1':'0',
            getbit(data, 3)?'1':'0',
            getbit(data, 2)?'1':'0',
            getbit(data, 1)?'1':'0',
            getbit(data, 0)?'1':'0');
Have you read the FAQ? For lots of information and links to significant threads see here: viewtopic.php?f=7&t=1396


Return to US ALDL ECUs

Who is online

Users browsing this forum: No registered users and 1 guest