Uninformed: Informative Information for the Uninformed

Vol 9» 2008.Jan


Spoofed Return Address for CheckRevision Calls

Due to how the x86 architecture works, it is trivially easy to spoof the return address pointer for a procedure call. All that one must do is push the spoofed return address on the stack, and then immediately execute a direct jump to the target procedure (as opposed to a standard call).

As a result, it is fairly trivial to bypass this protection mechanism at run-time. One need only search for a `ret' opcode in the code space of the Battle.snp module in memory, and use the technique described previously to simply "bounce" the call off of Battle.snp via the use of a spoofed return address. To the Lockdown module, the call will appear to originate from the context of Battle.snp, but in reality the call will immediately return from Battle.snp to the real caller in the untrusted process.

To counter this, the following could be attempted:

  1. Verify two return addresses deep, although due to the nature of the x86 calling conventions (at least __stdcall and __fastcall, the two used by Blizzard code frequently), it is not guaranteed that four bytes past the return address will be a particularly meaningful value.
  2. Verify that the return address does not point directly to a `ret', `jmp', `call' or similar instruction, assuming that current Battle.snp variations do not use such patterns in their call to the module. This only slightly raises the bar for an attacker, though; he or she would only need pick a more specific location in Battle.snp through which to stage a call, such as the actual location used in normal calls to the Lockdown module.