Aaron Giles<p>Of course, my CPU emulator didn't bother to support TF, since it was an edge case and not generally relevant to games. However, this discovery meant that I needed to bite the bullet and add support for tracing.</p><p>When the TF is set, the next instruction executes and then afterwards a <a href="https://corteximplant.com/tags/DB" class="mention hashtag" rel="nofollow noopener noreferrer" target="_blank">#<span>DB</span></a> (debug) fault is generated. This is interpreted by Windows as an EXCEPTION_SINGLE_STEP, which is handled by some fairly sophisticated logic in the SecuROM exception handler. </p><p>The basic gist is that once the TF is enabled, the handler continues to re-enable it and trace, instruction-by-instruction, until a special breakpoint instruction turns it off. It also has logic to detect when a <a href="https://corteximplant.com/tags/DB" class="mention hashtag" rel="nofollow noopener noreferrer" target="_blank">#<span>DB</span></a> instruction happens outside of the protected code (e.g., a system call), and automatically disables tracing by setting a hardware breakpoint on the return address of the function that was called.</p><p>This involved a whole lot of work implementing hardware instruction breakpoints and some precise details of the TF behavior in my emulator.</p><p>One additional quirk that bit me is that if a hardware instruction breakpoint is set, it generates a <a href="https://corteximplant.com/tags/DB" class="mention hashtag" rel="nofollow noopener noreferrer" target="_blank">#<span>DB</span></a> exception just like a single step. I originally thought that Windows was smart enough to translate this into an EXCEPTION_BREAKPOINT, but no, it still comes in as an EXCEPTION_SINGLE_STEP.</p><p>So after implementing all this, I see that the code extracts several files including cms32_nt.dll, which it then calls LoadLibrary on.</p><p>The DllMain funciton of cms32_nt.dll does a bunch of decompression/decryption logic before deliberately writing to offset 0 of the loaded image. On real NT-based system this causes a fault, but in my emulator, I wasn't explicitly protecting this area, so I was missing the fault. This led me to implement logic to mark certain pages as read-only so that I would catch errant writes here.</p><p>With that in place, I then landed in the exception handler for the entry point of cms32_nt.dll, which does some interesting things to ensure that it's only been called in the context of a LoadLibrary from a known accomplice....</p>