An interview with CrackZ and (incomplete) source code to Contract Killer “trainer”

I just found a nice interview with CrackZ here. He nails the point that curiosity and intellectual challenge trumps above everything else but also demonstrates the process from not caring about the impact of his acts to something more “ethical”. His site is still one of the best resources for Windows reversing, especially regarding dongles.

I have also decided to publish an incomplete version of my trainer for Contract Killer. I see that cheating is widespread so I think there’s not much impact from doing this. If the authors disagree on this feel free to contact me and I will immediately remove it. This code can fully “decrypt” the save file but encryption is missing the crc32 part, so you have to reverse a little if you want to make it work 🙂 No pain, no gain!

Have fun,

SHA256(decrypt.nonworking.c)= 321b641e6c0f3c73417e97420fe6c10baea39c1c262f414b4e00f626db0d7993

P.S.: Updated the source code. I had a stupid bug in a fread where I was reading 4 x int, resulting in overwriting the offset variable when compiled in 32bits. Stupid typo 😉 This new version works fine when compiled either in 32 or 64bits.

P.S.2: Added a new version, which adds error checking and fix a bug when adding the crc32. If you are trying to show an example at least try to do it right 😉

9 thoughts on “An interview with CrackZ and (incomplete) source code to Contract Killer “trainer”

  1. I’m getting a segmentation fault on decrypt at line 108: fprintf(file_out, “%s”, decrypteddata). Haven’t figured out why though…

  2. Hmm, working through reversing Contract Killer and while I managed to successfully reverse the encryption and decryption methods on my own, I’m having trouble with the crc. Is the table initialized in Init_Crc32? I’m also having a hard time understanding how CHash::find and CHash::LookUp fit in and why they’re called before Init_Crc32.

    I have a feeling more clearly understanding the instructions at loc_50FBA would help. Any help/comments would be much appreciated though.

    1. Hello,

      You just need to worry with CCrc32::Crc32 and CCrc32::Init_Crc32.
      The init function is initializing the crc32 table with a loop like for (i=0; i < 256; i++). You could use some source code around the net to have a good reference about how it's done.
      Then the crc32 routine is also pretty easy to reverse – I tried some implementations and got different results so it's better to reverse it. You will probably have to invert the endian order of the crc32 result.
      Just focus on those two methods and you should be fine 🙂

  3. Thanks. I’ve gotten a bit farther. The table creation made more sense to me than the actual crc. Here is where I’m at

    The table creation may not be perfect but I know the main issues are in the crc function. I really can’t figure out what r1 is used for. I think it points to the second parameter passed into the function which I though was length but now I’m not so sure… Any other suggestions?

    1. That maybe ok code is correct 😉 (please remove that pastbin).
      R0 is the pointer to the crc table, R1 is the data to be crc’ed and R2 is its length. You should be able to reverse it very quickly.

  4. Great, thanks. I made the pastebin without an account so I can’t immediately delete it but I’ve reported it and it should disappear soon. If you feel the need, feel free to delete my previous post.

Leave a Reply

Your email address will not be published. Required fields are marked *