Shell based RPC
Introduction
What exactly is shell based RPC? Why would anyone care? What the heck am I talking about? Shell based RPC is my terminology for a bit of black magic I'm calling (appropriately enough) black_magic.sh. black_magic.sh is a shell script which enables an interested party to inject arbitrary posix function executions into a running process for which you have the following:
- The running binary image
- The process ID
- Rights to execute ptrace() on that process
- Access to gdb
- A cooperative process
Provided all of these conditions are met, you may use the above script to inject arbitrary calls into your running processes (for instance, if you want to add some environment variables to, say, an email program after it's started). Let's start with some simple example - chdir()
chdir() is a C function call which will change the running process' CWD. In the bash world, it's 'cd'. So, lets try it out in our shell and see if we can use black_magic.sh to change our current working directory.
First, we'll execute '/bin/pwd' to get our cwd before we perform our black magic. Next, execute the following: './black_magic.sh --pid $$ --function chdir --string "/"'. Now, a final invocation of '/bin/pwd'. Notice something? Our current working directory is now / instead of the previous value. "But my shell still reports something different," says you. That is why this is called black magic, and not "the way."
But I can see you are unimpressed. Ok, what if we injected a thread into our running process using nothing but this program and our minds. How about a thread to constantly print "hello world" and sleep for a second? Ok, here's what we need:
- The C functionality to do such a thing coded
- the ability to load this into the executable
- The ability to execute this
Lets start by setting up the environment. We'll do a quick test by putting a string in memory and dumping it out.
Execute './black_magic.sh --pid $$ --function malloc --literal 20'. Your output should look like:
Setting PID: 16723
Will call: malloc
Black magic about to happen
---------------------------
Modify running image of: /bin/bash
Image PID: 16723
Function call looks like: malloc(20)
Temporary file: /tmp/tmp.bxP08df2ef
Pray!
GNU gdb (GDB) 7.1-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
Reading symbols from /bin/bash...(no debugging symbols found)...done.
[Thread debugging using libthread_db enabled]
0x00007fc405abff7e in __libc_waitpid (pid=
stat_loc=0x7ffff735395c, options=
at ../sysdeps/unix/sysv/linux/waitpid.c:32
32 ../sysdeps/unix/sysv/linux/waitpid.c: No such file or directory.
in ../sysdeps/unix/sysv/linux/waitpid.c
$1 = (void *) 0x25fc010
Done - hope it worked
In the above, the important part is the bolded and underlined part. This is the memory address we just allocated in memory. Let's now populate it.
Now we have a long journey ahead of us. We need to write each letter into the buffer.
Execute '~aconole/bin/black_magic.sh --pid $$ --function memset --literal 0x25fc010 --literal 104 --literal 1'
This will put 'h' into the first block of that buffer. In the above, notice that I used 0x25fc010. Your number will NOT be the same. Use the bolded output above as a guideline for what you need to use. The numbers for e,l,l,o,\n,0 are: 101,108,108,111,10,0 - so fill them in using the same technique, and remember to increment the 0x number by one each time. Also remember, this is in hex. You may convert it to decimal using bc or gdb if that is more familiar.
At this point, you've put the string in memory - lets try printing it.
Execute './black_magic.sh --pid $$ --function puts --literal 0x25fc010'
You should see output similar to:
Setting PID: 18104
Will call: puts
Black magic about to happen
---------------------------
Modify running image of: /bin/bash
Image PID: 18104
Function call looks like: puts(0x25fc010)
Temporary file: /tmp/tmp.hQ96JnH2co
Pray!
GNU gdb (GDB) 7.1-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
Reading symbols from /bin/bash...(no debugging symbols found)...done.
0x00007fa149b55f7e in __libc_waitpid (pid=
stat_loc=0x7fff9f0d5e8c, options=
at ../sysdeps/unix/sysv/linux/waitpid.c:32
32 ../sysdeps/unix/sysv/linux/waitpid.c: No such file or directory.
in ../sysdeps/unix/sysv/linux/waitpid.c
hello
$1 = 7
Done - hope it worked
Amazing we've put memory into the process, filled it with a value, and printed it out!