Injecting code into 32bit binary with ASLR
Porting the example from "Practical binary Analysis" book to a more general case
Disclamer: I am currently reading PBA book, so this refers to the content presented there. The code can nonetheless be obtained freely. This "article" started mostly as personal notes, which I have decided to publish since I think it could help people starting in this field. I will assume you are reading/own the book and therefore you can reference this content with that.
IntroductionThe book illustrates various method to inject assembly code into an ELF file. It also provides a small tool (elfinject.c) to automatize the process. In particular we will use the "primary" method, meaning overwriting an existing section header that is not fundamental for the ELF correct execution (in our case
The objective is to inject a simple "Hello word" into
Since I am assuming that this method has already been presented many times - and in better ways -, the concept of this (and what might be useful) is to show you the thoughts that lead to resolve the problem.
The problemThe book presents already a tool called elfinject.c, which automatize the task. Peeking at the source code, it should also work on 32bit elf files. But, as in most of articles, the example provided did not take into consideration ASLR. Furthermore, the assembly code is for x64 architecture.
I will assume zero knowledge about ASLR presence and functionality.The machine I am working with is a virtualized Ubuntu (not the one used for the book), with default configuration, and no safety measure turned off.
michele@michele-VirtualBox:~/pba/code/chapter7$ uname -a
Obviously, just running the example does not work. The first problem we have to face is the wrong assembly code. The provided
The solutionHere's my 32bit version of the hello world assembly file:
Let's take a look at the new hello32.s, it starts with
The second important problem was the interrupt call. x86 does not use
1. provide the arguments
2. choose the number of the system call (with respect to the x64 example).
We cannot simply replace the 64bit registers with their 32bit part, because the order used is different (order). Furthermore, the call associated with write is not 1 but 4 (syscall list).
Another issue was regarding the address of strings. Simply porting the code provided did not work, because the memory pointed to (- for example for the string hello -) was not being updated, or corretly referenced relatively to the address. So to reference it correcty, I had to use a little trick:
mov ecx, [esp]
Another issue encountered was the presence of ASLR. As I said, I will assume zero knowledge about it, and how to work around it. Reading
michele@michele-VirtualBox:~/pba/code/chapter7$ readelf /bin/ls -h
(gdb) info file
We can find the distance debugging it, and then we can implement a relative jump, with a similar method as for the data addresses:
mov eax, [esp]
After all these modification, we are finally able to inject and run from the terminal. After having copied
nasm -f bin hello32.s -o hello32.bin
More resources - what is going on?What is happening is that due to ASLR, the addresses are being randomized. You can find more details here.
Debugging the binary with dbg disables ASLR. This is why we always get the same "original" entry point with gdb, and also why the injection would work without a relative jump. ASLR can be re-enabled in gdb with
The binary was listed as