The actual body of this function contains a loop that iterates through the characters in the char array an XOR(Exclusive OR)s each of them with the random number 83, adding the result to an integer variable named 'hash' and then multiplying the value of this by another random value, 839286441. Looking at the disassembly for the hash function would likely overwhelm beginners (who of which this post is targetted at) so instead we will cheat and have a sneak peak at the source code instead ).įrom the above code snippet we can understand that this 'hash' function takes in an array of chars (data) and returns an unsigned integer. This makes it pretty clear and obvious that the hash function is what is generating this number (if you didn't already guess). So how do we get that very specific value into R0? On ARM, function return values are passed in R0. However, if they are equal then we continue to the restricted area of the program which, by looking at the disassembly, gives us a welcome message and then spawns a shell. If the two are not equal, we branch to 0xbef0 which displays the 'invalid key' message and then exits. It jumps or 'branches' to a new location in memory (in this case the entry point of the hash function) and then it returns to its caller.įollowing the call to the hash function, there is a comparison between R0 and a very specific value, 0x203623b1. The BL instruction is the equivalent of a CALL type instruction. Firstly, R0 is being loaded with user-supplied key and then a function 'hash' is BL(Branch with Link)'d to. There are some interesting things happening here. We don't care too much about the 'usage' thing, so we'll continue on to the next stage of the program. The BGE (Branch if Greater than or Equal to) instruction following this comparison then determines whether we are given the 'usage' message or whether we proceed to the next part of the program. This is simply checking the number of arguments the user supplied when executing the program. These instructions just make up the generic function prologue that contains the standard things you'd see in most ARM assembly functions, such as setting up the stack for later returning.īelow that, we have a series of memory access instructions (LDRs and STRs) and then a CMP instruction, comparing the value of R0 to 0x2. The first few instructions aren't too interesting. We will start with the first chunk of instructions, up until the point of the first conditional branch. We will need to look deeper into how this program works, and we'll start by disassembling main(). So what now? It is clear that this challenge will not be as simple as finding a string and using it to get through the check. The only strings we can see are the 'usage' message, the 'invalid key' message, the path to /bin/sh and a 'You're in!' message. Unfortunately for us, the key is not stored in plain ASCII. We can do so by opening the patchme1 binary in Hopper disassembler for OS X (or another disassembler tool such as IDA or radare2) and navigating to the 'strings' section. So where do we go from here? Natural instinct for anyone with any kind of reversing knowlegde would be to scan the binary for strings to see if the key happens to be stored in plain ASCII text. Executing the program with zero arguments gives us a short 'usage' message that lets us know that we will need some kind of key in order to use this app.Įxecuting it again, this time with a random key as the first argument, gives us a red error message telling us that we have entered an incorrect key. The specific binary we will look at is named 'patchme1' and is a small program designed specifically for the purpose of this tutorial. By this beginner-friendly tutorial we will take a look at the process of reverse engineering a simple ARM binary and patching it.
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |