Playing with ptrace, Part II

In Part II of his series on ptrace, Pradeep tackles the more advanced topics of setting breakpoints and injecting code into running processes.

Injecting the Code into Free Space

In the previous example we injected the code directly into
the executing instruction stream. However, debuggers can get
confused with this kind of behaviour, so let's find the free space
in the process and inject the code there. We can find free space by
examining the /proc/pid/maps file of the traced process. The
following function will find the starting address of this
map:

The following program injects code into free space. It's similar to
the previous injection program except the free space address is
used for keeping our new code. Here is the source code for the main
function:

When a system call entry is done, the kernel checks this flag
and calls the trace system call if the process is being traced. The
gory assembly details can be found in arch/i386/kernel/entry.S.

Now, we are in the sys_trace() function as defined in
arch/i386/kernel/ptrace.c. It stops the child and sends a signal to
the parent notifying that the child is stopped. This wakes up the
waiting parent, and it does the ptrace magic. Once the parent is
done, and it calls ptrace(PTRACE_CONT, ..) or
ptrace(PTRACE_SYSCALL, ..), it wakes up the child by calling the
scheduler function wake_up_process(). Some other architectures can
implement this by sending a SIGCHLD to child.

Conclusion

ptrace may appear to be
magic to some people, because it can examine and modify a running
program. It is generally used by debuggers and system call tracing
programs, such as ptrace. It opens up interesting possibilities for
doing user-mode extensions as well. There have been a lot of
attempts to extend the operating system on the user level. See
Resources to read about UFO, a user-level extension to filesystems.
ptrace also is used to employ
security mechanisms.

Pradeep Padala
is currently working on his Master's degree at the University of
Florida. His research interests include Grid and distributed
systems. He can be reached via e-mail at
p_padala@yahoo.com
or through his web site
(www.cise.ufl.edu/~ppadala).

Comment viewing options

Hi Pradeep,
Nice article...but I did not completely understand the code injection part.

The example you have explained inserts the code for printing "hello world" into a running process.
1. I did not exactly understand why you did the jump forward and backward steps.
Can you please elaborate on that?

2. I wrote a normal C program to print hello world:

#include
int main()
{
printf("hello world\n");
return 0;
}

I generated the byte code for this program using gdb. I replaced the contents of
char insertcode[] array with this new bytecode and ran the program.
As you might have guessed, it didn't work . What is the difference between your and my implementation?

I carried out this experiment so as to be able to inject code without having to learn assembly language programming. How do I inject the code of normal C program, without having to use assembly coding?

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.