bri3d / VW_Flash

Flashing tools for VW AG control units over UDS. Compression, encryption, RSA bypass, and checksums are supported for Simos18.1/6/10, DQ250-MQB, DQ381-MQB, and Haldex4Motion-Gen5-MQB.
Other
322 stars 83 forks source link

O30 ASW3 hook #2

Closed psobiech closed 3 years ago

psobiech commented 3 years ago

Hi! wow, great work, I am still trying to wrap my head around the code and all the documentation, but it is indeed very interesting. Thank you very much for sharing all your effort!

I got my hands on matching file for my ECU and I just wonder how should I approach finding out a good address to place the hook in ASW3 with version O30 (111SC8E0O300), since otherwise my CBOOT seems to be matching (NB0 SC841-111SC8E0).

1) Is this enough to dereming if CBOOT is indeed correct/compatible? 2) Are you using some tools to determine a valid address to place the hook in ASW3 or analyze the data? Ghidra does not seem to support TC179x and in my version 0x8088962c seems to contain data (I dont have O20 to compare). 3) After patching CBOOT and removing restrictions, would it be possible to dump the current contents of the flash? I am interested in making a backup first, since my calibration area is different than the one from factory and I would like to keep that.

Best regards, sorry if any questions are dumb, I am very new to reversing firmware.

bri3d commented 3 years ago

1) No, there's a little more to it. The easiest thing to verify the patch I have created will work verbatim is to see if the CBOOT you have contains the bytes DA 00 3C 02 at offset 0x8D1E in CBOOT - that's what gets patched (indirectly, in RAM) in my mechanism.

It's part of a method that's checked to put the ECU in an "engineering" / "development" mode essentially. If you're disassembling the ECU or want a reliable way to make the patch work on other CBOOTs, you can also find this method's entry point by looking for xrefs to a memory location 0xB000218C . I might extend either my patch itself or build a tool that can look for some "needles" and inject the patch more universally going forward.

2) TC176x or 167x settings in Ghidra will work fine, the instruction set is the same, just you will miss some control registers and the memory maps need a little grooming. If you download the free Tricore toolchain, the header packages have the right addresses and you can either make a new Ghidra preset (working on this) or just hack in any missing offsets as necessary.

3) This is really pretty hard to do with the restriction that you'd like to back up your calibration area itself.

The bit "gotcha" problem you will have is that rewriting CBOOT erases CAL (due to an implementation detail in how the CBOOT_temp -> CBOOT promotion works), and that there's a "coherency check" applied to all blocks to ensure that the version numbers match. So you can't "mix n match" firmware versions and you need to avoid ever erasing CBOOT, meaning you'd have to patch exactly what's on your ECU already (for example, erase and reflash ASW2 and then send in an ASW3 patch) and then see if the ECU will reboot into ASW without also reflashing CBOOT.

I think that maybe you could write an additional patch on top of mine which patches CBOOT in RAM to add a "read memory" primitive to a CAN handler, flash only two ASW blocks, and then use the "read memory" primitive to either either painstakingly read X bytes at a time (depending on how you implemented your CAN handler) or use the CAN handler to dump the Tricore boot passwords at 8001420C (they're just in order there - PWD1/2 for USR1 for Read access followed by PWD1/2 for USR2 for Read/Write access) and then read flash on the bench.

But, because I haven't tried it, there may be an additional issue somewhere in the coherency check that prohibits this partial flash method. If the version headers all match, I think it will check out, but I'm not 100% sure.

The hazard here isn't a brick, the worst thing that will happen is you'll end up trapped in CBOOT. But at that point without a commercial bench tool which can dump the boot passwords through some other (yet unknown) mechanism, you're left with reflashing to stock as your only recovery option, and you'll lose your custom calibration.

One other thing to look into is that if you already have a commercial tune, which it sounds like you do, there may be a ReadMemory primitive attached to a CAN handler already. Try sending 3E 00 followed by a memory address and see if something fun comes back :)

bri3d commented 3 years ago

For #2, I did open source my register dump for TC179x in Ghidra: https://github.com/bri3d/ghidra_tc1791_registers .

The way I usually find a good hook is by searching for 4+ nop instructions in a code area using the Ghidra search tool - since it's only really safe to write over 8 bytes or more of 00 data using the write exploit. You can also look for isync and dsync as they are usually surrounded by nop-sleds to purge the instruction pipeline. Coincidentally these procedures are usually in the startup code and are usually already running with interrupts disabled, which makes them extra ideal. You can really put the hook anywhere as long as interrupts are disabled - since what you're descending into is a boot loader, it does its own setup and doesn't really care what's going on when it starts. To write over smaller data, you have to try to craft an ECC collision too, and you risk a super nasty ECC brick which can only be recovered with a decent bootstrap loader and not most commercial tools.

As for the reading calibration thing - you should definitely check out bench read at this point :)