Microcorruption: Novosibirsk

Wed 17 May 2023

The Scenario

Touching down in Russia, I am greeted by the Lockitall LockIT Pro revision c.02 whose manual states "[w]e have added features from b.03 to the new hardware." So another Ethiopian-style format string attack is in the cards. The HSM-2 connected to the lock could potentially have been an issue, were it not for the fact the lock is directly connected to the deadbolt allowing for the potential of a complete bypass; I'm sure I'll find more facepalms when I get into the assembly:

Understanding The Code

The biggest issue with the HSM-2 compared to the HSM-1 is that it is ostensibly capable of controlling the deadbolt itself, so main() doesn't have an unlock_door() function I can hijack for my own purposes, but also it doesn't end with a ret instruction so I don't know how useful overwriting some pointer would be:

A screenshot of the disassembly of the main function

Throwing some garbage input at the lock to see how much of it I could control for how long was largely unsuccessful; sure I knew I would have to exploit printf() somehow but I wasn't seeing any sentinel values or flags that would give me control of the deadbolt. At this point, I remembered there were other functions in the firmware and decided to give them a look:

A screenshot of the disassembly of the conditional_unlock_door function

conditional_unlock_door() has been in every firmware connected to an HSM-2 I can remember [1], but I had a brain blast inspecting it this time: I originally planned to write my own shellcode to open the door, but the only difference between the shellcode I would write and using conditional_unlock_door() the "right" way is the interrupt, which I should be able to overwrite with a format string vuln...

Exploiting The Code

The manual says the interrupt to trigger the deadbolt is 0x7f, so I had to figure out how to write that byte to the right location; targeting the correct location was simple enough, but getting enough characters into printf() to write the correct value was a bit tedious [2]. Nevertheless, 129 bytes later I was jetting off to Algeria with a stack of bonds that were under new ownership.

[1]Since I've always bypassed the HSM I hadn't given it much thought the last few times I saw it
[2]Supposedly there's supposed to be a way to use $ with format strings so you don't have to include a bunch of dummy bytes in your shellcode, but I can't figure out how to make it work here