3

I am having trouble figuring out this microcorruption challenge in the link below: https://microcorruption.com/debugger/Halifax

Basically, the 0x7f interrupt has been disabled so I must reenable it before inserting a payload that will call it. The program says I need to call the 0x41 interrupt with the 16byte key that is stored in secure memory, which I seemingly don't have access to.

My main issue is that when I call the 0x41 interrupt, I am not sure which argument I need to supply the pointer to the password into. The second issue is, since I'm not sure I'm supplying the password into the correct argument, I am also unsure I have found the password at all.

Things I know: The sha256_internal calls the 0x41 interrupt as well, so I have tried to emulate this with my payloads. When I insert 0x1000 as the second argument (into r14 when using sha256_internal) it gives me the encryption that the program printed out to the screen. When I change that number, the encryption changes. Each time I reset the CPU, all of these encryptions change (except for when I insert 0x0, in which case the sha256 encryption of an empty string is outputted). The max number I can put in is 0x1000, into this argument, as well as into the third argument, and if I exceed 0x1000 then the "Exceeded SRAM length" exception is thrown.

Things I have tried:

-forcing the pc to restart all the instructions from the initialization of the program, but after having overwritten the instructions for disabling the interrupt. This didn't work since apparently after the interrupt is disabled, it can only be reenabled by using the 0x41 interrupt with the password.

-I have tried to insert the parts of the internal SRAM hash they keep printing to the screen, its 32bytes and the password is only 16bytes, but unsurprisingly this hasn't worked since its just a hash of the password which doesn't seem to be very useful.

An example payload I inserted:

800060301210473012e043301200103012000030124100b0125045301244453041

8000 refers to where the payload will be written to to be run later

60 refers to the length of the payload (I made a large length so I wouldn't have to set it every time)

301210473012e043301200103012000030124100 is for pushing all the arguments of the interrupt onto the stack. Here I tried putting the password address as a 5th argument instead

b0125045 is for calling the INT function to carry out the interrupt

30124445 is to push the address I want to go back to after my payload is about to finish

3041 return to the address I just pushed so the program can receive another payload

My biggest problem is that I am unsure if I am inserting the password tries into the right argument, so even if I have found the password, I am not sure it is being entered. I keep putting in a pointer to it as the third argument (into r15 in sh256_internal), but it seems wrong since this argument also has a length limit of 0x1000.

Any suggestions, hints, new things to try would be much appreciated.

1

4 Answers 4

1

Im also stuck. It is a bit weird that, according the the manual, INT 0x41 is to be used to unlock, but in the code it is used to produce a hash of the SRAM... This is what I've tried so far:

Other interrupts

Maybe there is an undocumented interrupt that would reverse the hardening mode? I couldn't find anything a part from 0x31 which seems to be identical to 0x41, but produces a hash of our working memory instead of the non-addressable SRAM. Can't see how this will help us..

Dissecting the SRAM

When calling the sha256_internal function, r14 is the length of the data you want to hash and r15 is the offset from start of SRAM. I figured out, by calculating the hash of long sequences of zeroes and comparing that to the output of the sha256_internal, that almost the entire SRAM is filled with zeroes. It seems that there's only non-zero data in the first ~0x100 bytes. I tried to find 16 byte sequences within these 0x100 bytes that didn't differ between tries. If I found any static 16 byte sequence, that must be the key! But no luck...

Watchdog

Just at the start of the program, there's a function named __watchdog_support. The program also writes 0x5a08 to 0x15c. The value 0x5a08 seems to be connected to the watchdog control register according to the user manual. I tried to fiddle around with this, but I don't think the watchdog is implemented. At least I didn't get anywhere..

As there's no information about how to unlock via the 0x41 Interrupt, I'm inclined to think that solving this is done by somehow reversing the hardening process and then issuing the 07f interrupt...

1

To add to your interrupt discussion, you can also do a sha1 hash with 0x30 or a sha512 hash with 0x32. Not sure how that would help, but maybe there are more interrupts out there?

1

I've managed to complete the other challenges but I'm also stalled on Halifax.

The other interrupts appear to be a dead end. All the interrupts used in St. John are available (sha1, sha256, sha512), but they only hash userspace memory. Maybe they need to be used to hash some data for the final solution once its pulled from SRAM, but none of those functions produce 16 byte outputs so no obvious hints.

Watchdog appears not to be implemented. If it was, you could potentially trigger a watchdog interrupt with an infinite loop, and overwrite the interrupt vector (in memory at ff80) to execute a handler. Tried it, but it does not work, and I'm not sure it would help if it did.

Dissecting the SRAM may be a dead end. In brief, using 0x41 interrupts we can get sha256 hashes of sections of the SRAM and we can use those hashes to create a dump. Happy to give more detail if anyone needs a few hints to make that work.

But here's where I'm stalled, since the SRAM is different on each reset. It's mostly 0's, but always starts with a section of apparently random data which is always one of two exact byte lengths. The non-zero byte lengths are strange values, that don't match any standard key or hash lengths.

So no obvious keys in SRAM, and even if there was one, I don't see a clear way to get a non static key value from SRAM into userspace without a live memory dump (so couldnt do it in the solver). Also, I don't see a way to call the 0x41 interrupt to accept a key as input.

Has anyone solved Halifax yet? The progress page is broken for the newer challenges. For me, it shows that I've solved Halifax already, but not Cold Lake, but it's actually the other way around.

0

There is an unfortunate typo in the challenge. You provide the key through the 0x42 interrupt, not the 0x41 interrupt.

The 16-byte key is actually stored in SRAM. It is not the hash.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.