DEV Community

Ahmet Can Gulmez
Ahmet Can Gulmez

Posted on

Simple Code Injection into ELF Executable

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;
}
Enter fullscreen mode Exit fullscreen mode

Compile this source file and then run it:

$ gcc main.c -o main ; ./main
Enter fullscreen mode Exit fullscreen mode

After that, you will see:

#0
#1
#2
#3
#4
#5
#6
#7
#8
#9
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)