An Objective Analysis of the Lockdown Protection System for Battle.net 12/2007 Skywing skywing@valhallalegends.com Abstract Near the end of 2006, Blizzard deployed the first major update to the version check and client software authentication system used to verify the authenticity of clients connecting to Battle.net using the binary game client protocol. This system had been in use since just after the release of the original Diablo game and the public launch of Battle.net. The new authentication module (Lockdown) introduced a variety of mechanisms designed to raise the bar with respect to spoofing a game client when logging on to Battle.net. In addition, the new authentication module also introduced run-time integrity checks of client binaries in memory. This is meant to provide simple detection of many client modifications (often labeled "hacks") that patch game code in-memory in order to modify game behavior. The Lockdown authentication module also introduced some anti-debugging techniques that are designed to make it more difficult to reverse engineer the module. In addition, several checks that are designed to make it difficult to simply load and run the Blizzard Lockdown module from the context of an unauthorized, non-Blizzard-game process. After all, if an attacker can simply load and run the Lockdown module in his or her own process, it becomes trivially easy to spoof the game client logon process, or to allow a modified game client to log on to Battle.net successfully. However, like any protection mechanism, the new Lockdown module is not without its flaws, some of which are discussed in detail in this paper. 1) Introduction The Lockdown module is a part of several schemes that attempt to make it difficult to connect to Battle.net with a client that is not a "genuine" Blizzard game. For the purposes of this paper, the author considers both modified/"hacked" Blizzard game clients, and third-party client software, known as "emubots", as examples of Battle.net clients that are not genuine Blizzard games. The Battle.net protocol also incorporates a number of schemes (such as a proprietary mechanism for presenting a valid CD-Key for inspection by Battle.net, and a non-standard derivative of the SRP password exchange protocol for account logon) that by virtue of being obscure and undocumented make it non-trivial for an outsider to successfully log a non-genuine client on to Battle.net. Prior to the launch of the Lockdown module, a different system took its place and filled the role of validating client software versions. The previous system was resistant to replay attacks (caveat: a relatively small pool of challenge response values maintained by servers makes it possible to use replay attacks after observing a large number of successful logon attempts) by virtue of the use of a dynamically-supplied checksum formula that is sent to clients (a challenge, in effect). This formula was then interpreted by the predecessor to the Lockdown module, otherwise known as the "ver" or "ix86ver" module, and used to create a one-way hash of several key game client binaries. The result response would then be sent back to the game server for verification, with an invalid response resulting in the client being denied access to Battle.net. While the "ver" module provides some inherent resistance to some types of non-genuine clients (such as those that modify Blizzard game binaries on disk), it does little to stop in-memory modifications to Blizzard game clients. Additionally, there is very little to stop an attacker from creating their own client software (an "emubot") that implements the "ver" module's checksum scheme, either by calling "ver" directly or through the use of a third-party, reverse-engineered implementation of the algorithm implemented in the "ver" module. It should be noted that there exists one basic protection against third party software calling the "ver" module directly; the "ver" series of modules are designed to always run part of the version check hash on the caller process image (as returned by the Win32 API GetModuleFileNameA). This poses a minor annoyance for third party programs. In order to bypass this protection, however, one need only hook GetModuleFileNameA and fake the result returned to the "ver" module. Given the existing "ver" module's capabilities, the Lockdown module represents a major step forward in the vein of assuring that only genuine Blizzard client software can log on to Battle.net as a game client. The Lockdown module is a first in many respects for Blizzard with respect to releasing code that actively attempts to thwart analysis via a debugger (and actively attempts to resist being called in a foreign process with non-trivial mechanisms). Despite the work put into the Lockdown module, however, it has proven perhaps less effective than originally hoped (though the author cannot state the definitive expectations for the Lockdown module, it can be assumed that a "hacking life" of more than several days was an objective of the Lockdown module). This paper discusses the various major protection systems embedded into the Lockdown module and associated authentication system, potential attacks against them, and technical counters to these attacks that Blizzard could take in a future release of a new version check/authentication module. Part of the problem the developers of the Lockdown module faced relates to constraints on the environment in which the module operates. The author has derived the following constraints currently in place for the module: 1. The server portion of the authentication system is likely static and does not generate challenge/response values in real time. Instead, a pool of possible values appear to be pregenerated and configured on the server. 2. The module needs to work on all operating systems supported by all Blizzard games, which spans the gamut from Windows 9x to Windows Vista x64. Note that there are provisions for different architectures, such as Mac OS, to use a different system than Windows architectures. 3. The module needs to work on all versions of all Blizzard Battle.net games, including previous versions. This is due to the fact that the module plays an integral part in Battle.net's software version control system, and thus is used on old clients before they can be upgraded. 4. Legitimate users should not see a high incidence of false positives, and it is not desirable for false positives to result in automated permanent action against legitimate users (such as account closure). As an aside, in the author's opinion, the version check and authentication system is not intended as a copy protection system for Battle.net, as it does nothing to discourge additional copies of genuine Blizzard game software from being used on Battle.net. In essence, the version check and authentication system is a system that is designed to ensure that only copies of the genuine Blizzard game software can log on to Battle.net. Copy protection measures on Battle.net are provided through the CD-Key feature, wherein the server requires that a user has a valid (and unique) CD-Key (for applicable products). 2) Protection Schemes of the Lockdown Module As a stark contrast to the old "ver" module, the Lockdown module includes a number of active defense mechanisms designed to significantly strengthen the module's resistance to attack (including either analysis or being tricked into providing a "good" response to a challenge to an untrusted process). The protection schemes in the Lockdown module can be broken up into several categories: 1. Mechanisms to thwart analysis of the Lockdown module itself and the secret algorithm it implements (anti-debugging/anti-reverse-engineering). 2. Mechanisms to thwart the successful use of Lockdown in a hostile process to generate a "good" response to a challenge from Battle.net (anti-emubot, and by extension anti-hack, where "anti-hack" denotes a counter to modifications of an otherwise genuine Blizzard game client). 3. Mechanisms to thwart modifications to an otherwise-genuine Blizzard game client that is attempting to log on to Battle.net (anti-hack). In addition, the Lockdown module is also responsible for implementing a reasonable facsimile of the original function of the "ver" module; that is, to provide a way to authoritatively validate the version of a genuine Blizzard game client, for means of software version control (e.g. the deployment of the correct software updates/patches to old versions of genuine Blizzard game clients connecting to Battle.net). In this vein, the following protection schemes are present in the Lockdown module and associated authentication system: 2.1) Clearing the Processor Debug Registers The x86 family of processors includes a set of special registers that are designed to assist in the debugging of programs. These registers allow a user to cause the processor to stop when a particular memory location is accessed, as an instruction fetch, as a data read, or as a data write. This debugging facility allows a user (debugger) to set up to four different virtual addresses that will trap execution when referenced in a particular way. The use of these debug registers to set traps on specific locations is sometimes known as setting a hardware breakpoint", as the processor's dedicated debugging support (in-hardware) is being utilized. Due to their obvious utility to anyone attempting to analyze or reverse engineer the Lockdown module, the module actively attempts to disable this debugging aid by explicitly zeroing the contents of the key debug registers in the context of the thread executing the Lockdown module's version check call, CheckRevision. All the requisite debug registers are cleared immediately after the call to the CheckRevision routine in the Lockdown module is made. This protection mechanism constitutes an anti-debugging scheme. 2.2) Memory Checksum Performed on the Lockdown Module The Lockdown module, contrary to the behavior of its predecessor, implements a checksum of several key game executable files in-memory instead of on-disk. In addition to the checksum over certain game executables, the Lockdown module includes itself in the list of modules to be checksumed. This provides several immediate benefits: 1. Attempts to set conventional software breakpoints on routines inside the Lockdown module will distort the result of the operation, frustrating reverse engineering attempts. This is due to the fact that so-called software breakpoints are implemented by patching the instruction at the target location with a special instruction (typically `int 3') that causes the processor to break into the debugger. The alteration to the module's executable code in memory causes the checksum to be distorted, as the `int 3' opcode is checksumed instead of the original opcode. 2. Attempts to bypass other protection mechanisms in the Lockdown module are made more difficult, as an untrusted process that is attempting to cause the Lockdown module to produce correct results via patching out certain other protection mechanisms will, simply by virtue of altering Lockdown code in-memory, inadvertently alter the end result of the checksum operation. The success of this aspect of the memory checksum protection is related to the fact that the Lockdown module attempts to disable hardware breakpoints as well. These two protection mechanisms thus complement eachother in a strong fashion, such that a naive attempt to compromise one of the protection schemes would usually be detected by the other scheme. In effect, the result is a rudimentary "defense in depth" approach to software protection schemes that is the hallmark of most relatively successful protection schemes. 3. The inclusion of the version check module itself in the result of the output of the checksum is entirely new to the version check and client authentication system, and as such poses an additional, unexpected "speed bump" to persons attempting to reimplement the Lockdown algorithm in their own code. This protection mechanism has characteristics of both an anti-debugging, anti-hack, and anti-emubot system. 2.3) Hardcoding of Module Base Addresses As mentioned previously, the Lockdown module now implements a checksum over game executables in-memory instead of on-disk. Taking advantage of this change, the Lockdown module can hardcode the base address of the main process executable at the default address of 0x00400000. This is safe because no Blizzard game executable includes base relocation information, and as a result will never change from this base address. By virtue of hardcoding this address, it becomes more difficult for an untrusted process to successfully call the Lockdown module. Unless the programmer is particularly clever, he or she may not notice that the Lockdown module is not actually performing a checksum over the main executable for the desired Blizzard game, but instead the main executable of the untrusted process (the default address for executables in the Microsoft linker program is the same 0x00400000 value used in Blizzard's main executables comprising their game clients). While it is possible to change the base address of a program at link-time, which could be done by a third-party process in an attempt to make it possible to map the desired Blizzard main executable at the 0x00400000 address, it is difficult to pull this off under Windows NT. This is because the 0x00400000 address is low in the address space, and the default behavior of the kernel's memory manager is to find new addresses for memory allocations starting from the bottom of the address space. This means that in virtually all cases, a virgin Win32 process will already have an allocation (usually one of the shared sections used for communication with CSRSS in the author's experience) that is overlapping the address range required by the Lockdown module for the main executable of the Blizzard game for which a challenge response is being computed. While it is possible to change this behavior in the Windows NT memory manager and cause allocations to start at the top of the address space and search downwards, this is not the default configuration and is also a relatively not-well-known kernel option. The fact that all users would need to be reconfigured to change the default allocation search preference for an untrusted process to typically successfully map the desired Blizzard game executable makes this approach relatively painful for a would-be attacker. The Lockdown module also ensures that the return value of the GetModuleHandleA(0) Win32 API corresponds to 0x00400000, indicating that the main process image is based at 0x00400000 as far as the loader is concerned. The restriction on the base address of the game main executable module has the unfortunate side effect that it will not be possible to take advantage of Windows Vista's ASLR attack surface reduction capabilities, negatively impacting the resistance of Blizzard games to certain classes of exploitation that might impact the security of users. This protection mechanism is primarily considered to be an anti-emubot scheme, as it is designed to guard against an untrusted process from succcessfully calling the Lockdown module. 2.4) Video Memory Checksum Another previously nonexistant component to the version check algorithm that is introduced by the Lockdown module is a checksum over the video memory of the process calling the Lockdown module. At the point in time where the module is invoked by the Blizzard game, the portion of video memory checksummed should correspond to part of the "Battle.net" banner in the log on screen for the Blizzard game. The Lockdown module is currently only implemented for so-called "legacy" game clients, otherwise known as clients that use Battle.snp and the Storm Network Provider system for multiplayer access. This includes all Battle.net-capable Blizzard games ranging from Diablo I to Starcraft and Warcraft II: BNE. Future games, such as Diablo II, are not supported by the Lockdown module. This represents an additional non-trivial challenge to a would-be attacker. Although the contents of the video memory to be checksummed is static, the way that the Lockdown module retrieves the video memory pointers is through an obfuscated call to several internal Storm routines (SDrawSelectGdiSurface, SDrawLockSurface, and SDrawUnlockSurface) that rely on a non-trivial amount of internal state initialized by the Blizzard game during startup. This makes the use of the internal Storm routines unlikely to simply work "out of the box" in an untrusted process that has not gone to all the trouble to initialize the Storm graphics subsystem and draw the appropriate data on the Storm video surfaces. This protection mechanism is primarily considered to be an anti-emubot scheme, as it is designed to guard against an untrusted process from succcessfully calling the Lockdown module. 2.5) Multiple Flavors of the Lockdown Module The original "ver" module scheme pioneered a system wherein there were multiple downloadable flavors of the version check module to be used by a client. The Battle.net server sends the client a tuple of (version check module filename, checksum formula and initialization parameters, version check module timestamp) that is used in order to version (and download, if necessary) the latest copy of the version check module. This mechanism provides for the possibility that the Battle.net server could support multiple "flavors" of version check module that could be distributed to clients in order to increase the amount of work required by anyone seeking to reimplement the version check and authentication system. The original "ver" module and associated authentication scheme in fact utilized such a scheme of multiple "ver" modules, and the Lockdown scheme expands upon this trend. In the original system, there were 8 possible modules to choose from; the Lockdown system, by contrast, expands this to a set of 20 possibilities. However, the version check modules in both systems are still very similar to one another. In both systems, each module has its own unique key (a 32-bit values in the "ver" system, and a 64-bit value in the Lockdown system) that is used to influence the result of the version check checksum (it should be noted that in the Lockdown system, the actual Lockdown module itself is in essence a second "key", as the added checksum over the module represents an additional adjustment to the final checksum result that changes with each Lockdown module). This single difference is disguised by other minor, superficial alterations to each module flavor; there are slight differences by which module base addresses are retrieved, for instance, and there are also other superficial differences that relate to differences like code being moved between functions or functions being re-arranged in the final binary in order to frustrate a simple "diff" of two Lockdown modules as being informative in revealing the functional differences between the said two modules. This protection mechanism is perhaps best classed as an anti-analysis scheme, as it attempts to create more work for anyone attempting to reverse engineer the authentication system as a whole. 2.6) Authenticity Check Performed on Lockdown Module Caller An additional new protection scheme introduced in the Lockdown module is a rudimentary check on the authenticity of the caller of the module's export, the CheckRevision routine. Specifically, the module attempts to ascertain whether the return address of the call to the CheckRevision routine points to a code location within the Battle.snp module. If the return pointer for the call to CheckRevision is not within the expected range, then an error is deliberately introduced into the checksum calculations, ultimately resulting in the result returned by the Lockdown module becoming invalidated. 3) Attacks (and Counter-Attacks) on the Lockdown System Though the Lockdown module introduces a number of new defensive mechanisms that attempt to thwart would-be attackers, these systems are far from fool-proof. There are a number of ways that these defensive systems could be attacked (or subverted) by a would-be attacker who wishes to pass the version and authentication check in the context of a non-genuine client for purposes of logging on to Battle.net. In addition, there are also a variety of different ways by which these proposed attacks could be thwarted in a future update to the version check and authentication system. 3.1) Interception of SetThreadContext As previously described, the Lockdown modules attempt to disable the use of the processor's complement of debug registers in order to make it difficult to utilize so-called hardware breakpoints during the process of reverse engineering or analyzing a Lockdown module. This scheme is, at present, relatively easily compromised, however. There are several possible attacks that could be used: 1. Hook the SetThreadContext API and block attempts to disable debug registers (programmatic). 2. Patch the import address table entry for SetThreadContext in the Lockdown module to point to a custom routine that does nothing (programmatic). 3. Patch the Lockdown module instruction code to not call SetThreadContext in the first place (programmatic). However, this is approach is considered to be generally untenable, due to the memory checksum protection scheme. 4. Set a conditional breakpoint on `kernel32!SetThreadContext' that re-applies the hardware breakpoint state after the call, or simply alters execution flow to immediately return (debugger). Depending on whether the attacker wants to make programmatic alterations to the behavior of the Lockdown module via hardware breakpoints, or simply wishes to observe the behavior of the module in the debugger unperturbed, there are several options available. The suggested counters include techniques such as the following: 1. Verify that the debug registers were really cleared. However, this could simply be patched out as well. More subtle would be to include the value of several debug registers in the checksum calculations, but this would also be fairly obvious to attackers due to the fact that debug registers cannot be directly accessed from user mode and require a call to Get/SetThreadContext, or the underlying NtGet/SetContextThread system calls. 2. Include additional calls to disable debug register usage in different locations within the Lockdown module. To be most effective, these would need to be inlined and use different means to set the debug register state. For example, one location could use a direct import, another could use a GetProcAddress dynamic import, a third could manually walk the EAT of kernel32 to find the address of SetThreadContext, and a fourth could make a call to NtSetContextThread in ntdll, and a fifth could disassemble the opcodes comprising NtSetContextThread, determine the system call ordinal, and make the system call directly (e.g. via `int 2e'). The goal here is to add additional work and eliminate "single points of failure" from the perspective of an attacker seeking to disable the anti-debugging feature. Note that the direct system call approach will require additional work in order to function under Wow64 (e.g. x64 computers running native Windows x64). 3. Verify that all IAT entries corresponding to kernel32 actually point to the same module in-memory. This is risky, though, as in some cases (such as when the Microsoft application compatibility layer module is in use), these APIs may be legitimately detoured. 3.2) Use of Hardware Breakpoints Assuming an attacker can compromise the anti-debugging protection scheme, then he or she is free to make clever use of hardware breakpoints to disable other protection systems (such as hardcoded base addresses of modules, checks on the authenticity of a CheckRevision caller, and soforth) by setting execute fetch breakpoints on choice code locations. Then, the attacker could simply alter the execution context when the breakpoints are hit, in order to bypass other protection mechanisms. For example, an attacker could set a read breakpoint on the hardcoded base address for the main process image inside the Lockdown module, and change the base address accordingly. The attacker would also have to patch GetModuleHandleA in order to complete this example attack. Suggested counters to attacks based on hardware breakpoints include: 1. Validation of the vectored exception handler chain, which might be used to intercept STATUSSINGLESTEP exceptions when hardware breakpoints are hit. This is risky, as there are legitimate reasons for there to be "foreign" vectored exception handlers, however. 2. Checks to stop debuggers from attaching to the process, period. This is not considered to be a viable solution since there are a number of legitimate reasons for a debugger to be attached to a process, many of them which may be unknown completely to the end user (such as profilers, crash control and reporting systems, and other types of security software). Attempting to block debuggers may also prevent the normal operation of Windows Error Reporting or a preconfigured JIT debugger in the event of a game crash, depending on the implementation used. Ways of detecting debuggers include calls to IsDebuggerPresent, NtQueryInformationProcess(...ProcessDebugPort..), checks against NtCurrentPeb()->BeingDebugged, and soforth. 3. Duplication of checks (perhaps in slightly altered forms) throughout the execution of the checksum implementation. It is important for this duplication to be inline as much as possible in order to eliminate single points of failure that could be used to short-circuit protection schemes by an attacker. 4. Strengthening of the anti-debugging mechanism, as previously described. 3.3) Main Process Image Module Base Address Restriction An attacker seeking to execute the Lockdown module in an untrusted process would need to bypass the restrictions on the base address of the main process image. The most likely approach to this would be a combination attack, whereby the attacker would use something like a set of hardware breakpoints to alter the hardcoded restrictions on module base addresses, and import table or code patch style hooks on the GetModuleHandleA API in order to defeat the secondary check on the module base address for the main executable image. Another approach would be to simply create the main executable image as a process, suspended, and then either create a new thread in the process or assume control of the initial thread in order to execute the Lockdown module. This gets the would-be attacker out of having to patch checks in the module, as there is currently no defense against this case implemented in the module. In order to strengthen this protection mechanism, the following approaches could be taken: 1. Manually traverse the loaded module list (and examine the PEB) in order to validate that the main process image is really at 0x00400000. All of these mechanisms could be compromised, but checking each one creates additional work for an attacker. 2. Verify that the game has initialized itself to some extent. This would make the approach of creating the game process suspended more difficult. It would also otherwise make the use of the Lockdown module in an untrusted process more difficult without tricking the module into believing that it is running in an initialized game process. The scope of determining how the game is initialized is outside of this paper, although an approach similar to the current one based on a checksum of Storm video memory (though with more "redundancy", or an additional matrix of requirements for a legitimate game process). 3.4) Minor Functional Differences Between Lockdown Module Flavors Presently, an attacker needs to implement all flavors of the Lockdown module in order to be assured of a successful connection to Battle.net. However, even with the 20 possibilities now available, this is still not difficult due to the minor functional differences between the different Lockdown flavors. Moreso, it is trivially possible to find the "magic" constants that constitute the only functional differences between each flavor of Lockdown. In the author's tests, two pattern matches and a small 200-line C program were all that were necessary to programmatically identify all of the magical constants that represent the functional differences between each flavor of Lockdown module, in a completely automated fashion. In fact, the author would wager that it took more time to implement all 20 different flavors of Lockdown modules than it took to devise and implement a rudimentary pattern matching system to automagically discover all 20 magical constants from the set of 20 Lockdown module flavors. Clearly, this is not desirable from the standpoint of effort put in to the protection scheme vs difficulty in attacking it. In order to address these weaknesses, the following steps could be implemented: 1. Implement true, major functional differences between Lockdown flavors. Instead of using a single constant value that is different between each flavor (probably a "" preprocessor constant), implement other, real functional differences. Otherwise, even with a number of different "non-functional" differences between module flavors, a pattern-matching system will be able to quickly locate the different constants for each module after a human attacker has discovered the constant for at least one module flavor. 2. Avoid using quick-to-substitute constants as the "meat" of the functional differences betwene flavors. While these are convenient from a development perspective, they are also convenient from an attacker perspective. If a bit more time were spent from a development perspective, attackers could be made to do real analysis of each module separately in order to determine the actual functional differences, greatly increasing the amount of time that is required for an attacker to defeat this protection scheme. 3.5) 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. 3.6) Limited Pool of Challenge/Response Tuples Presently, the Battle.net servers contain a fairly limited pool of possible challenge/response pairs for the version check and authentication system. Observations suggest that most products have a pool of around one thousand values that can be sent to clients. This has been used against Battle.net in the past, which was countered by an increase to 20000 possible values for several Battle.net products. Even with 20000 possible values, though, it is still possible to capture a large number of logon attempts over time and build a lookup table of possible values. This is an attractive option for an attacker, as he or she need only perform passive analysis over a period of time in order to construct a database capable of logging on to Battle.net with a fairly high success rate. Given the relative infrequency of updates to the pool of version check values (typically once per patch), this is considered to be a fairly viable method for an attacker to bypass the version check and authentication system. This limitation could easily be addressed by Blizzard, however, such as through the implementation of one or more of the below suggestions: 1. Periodically rotate the set of possible version check values so as to ensure that a database of challenge/response pairs would quickly expire and need to be rebuilt. Combined with a large pool of possible values, this approach would greatly reduce the practicality of this attack. Unfortunately, the author suspects that this would require manual intervention each time the pools were to be rotated by the part of Blizzard in the current Battle.net server implementation. 2. Implement dynamic generation of pool values at runtime on each Battle.net server. This would require the server to have access to the requisite client binaries, but is not expected to be a major challenge (especially since the author suspects that Battle.net is powered by Windows already, which would allow the existing Lockdown module code to be cleaned up and repackaged for use on the server as well). This could be implemented as a pool of possible values that is simply stirred every so often; new challenge/response values need not necessarily be generated on each logon attempt (and doing so would have undesirable performance implications in any case). 4) Conclusion Although the Lockdown module and associated authentication system represent a major break in Blizzard's ongoing battle against non-genuine Battle.net client software, there are still many improvements that could be made in a future release of the version check and authentication system which would fit within the constraints imposed on the version check system, and still pose a significant challenge to an adversary attempting to spoof Battle.net logons using a non-genuine clients. The author would encourage Blizzard to consider and implement enhancements akin to those described in this paper, particularly protections that overlap and complement each other (such as the debug register clearing and memory checksum schemes). In the vein of improving the Lockdown system, the author would like to stress the following principles as especially important in creating a system that is difficult to defeat and yet still workable and viable from a development and deployment perspective: - Defense in depth with respect to the various protection mechanisms in place within the module is a must. Protection systems need to be designed to complement and reinforce eachother, such that an attacker must defeat a number of layers of protection schemes for any one significant attack to succeed to the point of being a break in the system. - Countermeasures intended to frustrate reverse engineering or easy duplication of critical algorithms need to be viewed in the light of what an adversary might do in order to 'attack' (or duplicate, re-implement, or whatnot) a 'guarded' (or otherwise important) algorithm or section of code. For example, an attacker could ease the work of reimplementing parts of an algorithm or function of interest by wholesale copying of assembler code into a different module, or by loading an "authentic" module and making direct calls into internal functions (or the middle of internal functions) in an effort to bypass "upstream" protection checks. Keeping with this line of thinking, it would be advisible to interleave protection checks with code that performs actual useful work to a certain degree, such that it is less trivial for an adversary to bypass protection checks that are entirely done "up front" (leaving the remainder of a secret algorithm or function relatively "vulnerable", if the check code is skipped entirely). - Countermeasures intended to create "time sinks" for an adversary need to be carefully designed such that they are not easily bypassed. For instance, in the current Lockdown module implementation, there are twenty flavors of the Lockdown module; yet, in this implementation, it is trivially easy for an adversary to discover the differences (in a largely programmatic fashion), making this "time sink" highly ineffective, as the time for an adversary to breach it is likely much less than the time for the original developers to have created it. - Measures that depend on external, imported APIs are often relatively easy for an attacker to quickly pinpoint and disable (for example, the method that debug register breakpoints are disabled by the Lockdown module is immediately obvious to an adversary, if they are even the least bit familiar with the Win32 API (which must be assumed). In some cases (such as with the debug register breakpoint clearing code), this cannot be avoided, but in others (such as validation of module base addresses), the same effect could be potentially implemented by use of less-obvious approaches (for example manually traversing the loaded module list by locating the PEB and the loader data structures from the backlink pointer in the current thread's TEB). The author would encourage the developers of additional defensive measures to reduce dependencies on easily-noticible external APIs as much as possible (balanced, of course, against the need for maintainable code that executes on all supported platforms). In some instances, such as the manual resolution of Storm symbols, the current system does do a fair job of avoiding easily-detectable external API use. All things considered, the Lockdown system represents a major step forward in the vein of guarding Battle.net from unauthorized clients. Even so, there is still plenty of room for improvements in potential future revisions of the system. The author hopes that this article may prove useful in the strengthening of future defensive systems, by virtue of a thorough accounting of the strengths and weaknesses in the current Lockdown module (and pointed suggestions as to how to repair certain weaker mechanisms in the current implementation).