I recently found myself in situation where I had to analyze another process in order to understand what was really happening . In order to achieve this , I had to monitor the target process in one way or another. In the process I had to implement a simple hook just to do evil stuff 😈 .
For purposes of demonstration and for the blog I will simply look at how you can hook onto another process changing the flow of execution. In this case we will simply have a sleep program as the target and a hooking program that arguments the sleeping behavior of the sleep program .
Let’s get our hands dirty 😎 .
By definition
Hooking refers to the process of changing the behavior of software or its components. The code responsible of the aforementioned is referred to as a hook.
Target program
In this case we will have a simple sleep program that sleeps for 10 seconds.
|
|
Evil Function
|
|
Linux process basics
From the basics of processes , any program that is started has a process id (pid). Every process has its own Virtual Memory Area (VMA) which is using memory management schemes it translates into a physical address.
Understanding the target
In order do anything its important to always understand you target. This can be easily achieved using the File utility . In this case, the binary is an elf file . It is important to understand how the linker and the loader see this file. Won’t go into too much details since this could be another blogpost look at http://www.cirosantilli.com/elf-hello-world/ for a detailed insight on elf files (also look at PLT and GOT sections https://www.technovelty.org/linux/plt-and-got-the-key-to-code-sharing-and-dynamic-libraries.html)
GOT stands for global offset table which holds the various symbol offsets that are part of the binary and are from loaded the libraries
Game Plan
From the above we can easily formulate a plan 💡
i) First we need to monitor the process of interest in order to inspect registers etc.. more like a debugger. This can be easily achieved using ptrace
ii) Get the GOT offset of sleep symbol and calculate its address.
iii)Write our evil function into the target’s memory
iv) Patching GOT address with a pointer to our evil function.
i) The almighty debugger
In order to inspect contents of the remote target we need to use ptrace. So we will first attach ourselves to the target process.
Ptrace is very straight forward from its mans page.
ii) Get the G.O.T
In order to argument the sleep function we need to get its Global Offest so as we can overwrite it with a pointer to our evil function.
|
|
iii) Writing the evil function on target process
The big question here is how do we write data to a process we have no access to and and how do we affect the memory area of another process bearing in mind all the limitations thats are a result of Copy On Write (COW).
So far we have the GOT address and we have the ability to inspect the target’s memory. The aforementioned means that we can use registers of the attached process to do our dirty work 😁 .
Before we get lost in excitement it is important to understand and identify that no process is aware of the existence of the other or knows about the other processes’s VMA. Now with this fundamental principle comes another challenge how do we do a simple mmap (well this is important if we want to write into a memory region). The only option we have is to find a way to call functions from the target process 🤔 .
Remember we have control over the registers so we can do pretty much what we want to do as long as we are creative about it 💪 .
|
|
one important concept to understand is that android has both ARM and Thumb states it is important to always check which state is in use else this will haunt you trust me this is from experience . This deserves a blogpost too.
now since all is set lets create a function that calls mmap in the target process.
Still another problem we don’t know the address of mmap on target process so we cant call it. Now ASLR becomes a problem here 😩 .
So again we use what we have. Assuming we know where Libc is loaded and it’s distance from mmap is always the same that means we can calculate the address of mmap in the remote function assuming mathematically
Using the formula
and just like that we defeated ASLR 😎 .
Now lets progress and call mmap in the target processs
|
|
Now all we need to do is write into the maped memory our evil function . Once more Ptrace is BAE in this case since we will use PTRACE_POKETEXT which simply copies data into the provided address.
|
|
finally the last piece in the writing puzzle
Notice (uint8_t *)evil_function-1 has a minus one. Well if thats not there chaos erupt literally. Remember when I said Thumb and ARM may become a pain if not handled correctly ; this is what I meant.
Pointers to functions in thumb state
In order to allow interworking between the two states , If you have a thumb function the pointer to that function must have its least significant bit set. So that means a pointer to the function will have a plus one . So in order to get the actual pointer you have to subtract one from the pointer.
|
|
Patching our GOT with a pointer to evil function
Well just incase I missed this , the GOT holds a pointer to the target function ie sleep in our case so if we patch this by placing a pointer to our evil function.
We need to check whether the GOT address actually contains a pointer to sleep before we progress and once we confirm all we do is just write
|
|
And Voila we are DONE !!!!! 🎉🎉🎉 😎
The whole project can be found hereThe expected output is as shown below ENJOY
|
|