Microcorruption: Vladivostok

Wed 12 July 2023

The Scenario

On the plane from Algeria, I thought I'd have to do some Mission Impossible secret squirrel shit to reenter Russia after my last visit but it was surprisingly uneventful; I suppose Putin had more important matters to focus on. Nevertheless, after preparing myself I confronted my next opponent: revision c.05 of the Lockitall LockIT Pro equipped with a LockIT Pro HSM-2. The overview for this lock version touts the use of hardware randomization to improve lock security - I doubt that, but there's only one way to find out.

Understanding The Code

Scanning through the disassembly before I ran it, I noticed multiple functions that appeared to be ASLR-related and the presence of printf() which told me there's a high likelihood of needing to leak some pointers in order to successfully break this lock.

main() is once again largely a stub function, calling rand() to get new base addresses for the stack and code sections before calling aslr_main() which is itself also a stub that only calls _aslr_main() which performs the majority of the work. Here is where the engineers show they finally started trying though - the first thing _aslr_main() does is delete the code at the original location, making my disassembler useless. [1] After figuring out a method to negate ASLR during testing, I discovered _aslr_main() unsurprisingly has the same core loop as every other lock I've experienced so far: ask for a username and password, send both to the HSM for validation.

Exploiting The Code

The lock firmware echoes the username with a raw printf() call which practically confirmed some format string shenanigans would be required, and the buffer to store password input is undersized to the syscall receivin input, so I also knew I'd need a buffer overflow as well.

After spending an unreasonable amount of time trying to devise a format string that would give me something more useful than the address of printf(), I realized that was actually enough: ASLR might change the location of a function, but it doesn't change the distance between functions; with the address of printf() I could calculate the address of an interrupt function I wanted to return into, and the buffer overflow from the password input gives carte blanche to prepare the stack as necessary.

Once I realized this would be a two-stage attack, everything fell into place and the lock practically fell off by itself. Jetting off to India, I had some time to reflect on recent challenges - the heap corruption before and the decent ASLR now - and despite all odds I began to respect the Lockitall developers; the question then became whether or not they'd be able to keep it up.

[1]I guess if I used a better disassembler it would've disassembled the code at the new location, but finding a standalone disassembler I liked that worked on MSP360 was way more work than figuring out how to disable ASLR.