In this article, I will explain an code injection technique into ELF executable.
Firstly, you need to understand the ELF executable, its contents, sections, symbol table or so on. I've written a dedicated article previously. So if you don't have any information about ELF, please read it firstly and then come here again.
Let's say we have the following source file:
/**
* Simple Code Injection
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int i, num;
num = 10;
for (i = 0; i < num; i++)
{
printf("#%d\n", i);
}
return EXIT_SUCCESS;
}
Compile this source file and then run it:
$ gcc main.c -o main ; ./main
After that, you will see:
#0
#1
#2
#3
#4
#5
#6
#7
#8
#9
In here, I will change the num = 10 to num = 5 so that the output will be #0 to #4.
To accomplish this, I need to find the corresponding machine instruction/s. According to your background, you need to know that num variable will be in the .text section of ELF executable. Because it is the local variable. To display the .text section of the program, objdump is the primarily tool:
$ objdump -j .text -d main
The output will be as following:
(...)
0000000000001149 <main>:
1149: f3 0f 1e fa endbr64
114d: 55 push %rbp
114e: 48 89 e5 mov %rsp,%rbp
1151: 48 83 ec 20 sub $0x20,%rsp
1155: 89 7d ec mov %edi,-0x14(%rbp)
1158: 48 89 75 e0 mov %rsi,-0x20(%rbp)
115c: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp)
1163: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp)
116a: eb 1d jmp 1189 <main+0x40>
116c: 8b 45 f8 mov -0x8(%rbp),%eax
116f: 89 c6 mov %eax,%esi
1171: 48 8d 05 8c 0e 00 00 lea 0xe8c(%rip),%rax # 2004 <_IO_stdin_used+0x4>
1178: 48 89 c7 mov %rax,%rdi
117b: b8 00 00 00 00 mov $0x0,%eax
1180: e8 cb fe ff ff call 1050 <printf@plt>
1185: 83 45 f8 01 addl $0x1,-0x8(%rbp)
1189: 8b 45 f8 mov -0x8(%rbp),%eax
118c: 3b 45 fc cmp -0x4(%rbp),%eax
118f: 7c db jl 116c <main+0x23>
1191: b8 00 00 00 00 mov $0x0,%eax
1196: c9 leave
1197: c3 ret
Which machine instruction/s corresponds to num = 10? You need to know reading the assembly instructions in here. The answer is the movl $0xa,-0x4(%rbp) assembly instruction. Because the stack pointer of the program was enlarged by 4 bytes (int holds 4 bytes of memory) to lower address and put the immediate 0xA value. So that I need to change the 0xA value to 0x5.
After the found required assembly instruction, I need to determine the memory address of it. If you look at center column, the machine instruction is c7 45 fc 0a 00 00 00. In here:
- c7: the opcode of movl register
- 45 fc: the displacement of -0x4(%rbp)
- 0a 00 00 00: the immediate value, 0xA (little-endian)
c7 byte resides at 0x115c address so that 0a byte at 0x115f.
To change that byte, I'm gonna use hexedit program:
$ hexedit ./main
You will see:
After that, you move to 0x115F address and change the 0x0A value to 0x05. Save the changes and then run the program again. You will see:
#0
#1
#2
#3
#4
That's it. You injected the new code in the ELF executable 🥳.
This technique is simple and powerful. But there are some limitations. The most important one is that you should not shift the byte addresses, just replace it. If you wanna change the entire ELF executable addresses, you need the other techniques. That's the next article's topic.

Top comments (0)