runtime data manipulation with ptrace()
in the first ptrace() i did, i really didn’t do anything fancy other than to find out the number of the system call that i’m currently tracing. in this activity, i modified the parameter to sys_write() which is “stephanie” (lowercase) and changed every letter to uppercase before the actual soft interrupt (int 0x80) happens. i still used the asm program found here.
/** runtime data manipulation - an example ptrace() program
*
* this program intercepts the write call of another program (see traceme)
* then modifies the data passed in that program's sys_write() call.
* normal output should be small letters.
* modified output is shown as capital letters.
*
* 04/09/06 stephanie
*/
#include <sys/ptrace.h>
#include <linux/user.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#define is_syswrite(x) (x) == 4 ? 1 : 0
static void get_data(pid_t child, long addr, char *str, int len);
static void put_data(pid_t child, long addr, char *str, int len);
static void uppercase(char *str);
int main(int argc, char **argv)
{
pid_t cpid;
int status;
int entry;
struct user_regs_struct ureg_t;
struct user_regs_struct *ureg = &ureg_t;
entry = 1;
if (!(cpid = fork())) {
/* the program i'm tracing */
ptrace(PTRACE_TRACEME, NULL, NULL, NULL);
execl("./traceme", "traceme", NULL);
} else {
while (1) {
char *str;
wait(&status);
if (WIFEXITED(status)) break;
/* dump registers */
ptrace(PTRACE_GETREGS, cpid, NULL, ureg);
if (is_syswrite(ureg->orig_eax)) {
if (entry) {
str = (char *)malloc((ureg->edx) * sizeof(char)+1);
get_data(cpid, ureg->ecx, str, ureg->edx);
uppercase(str);
put_data(cpid, ureg->ecx, str, ureg->edx);
free(str);
} else {
/* don't do anything */
printf("sys_write() %ld\n", ureg->eax);
}
/* toggle entry status */
entry = entry ? 0 : 1;
}
ptrace(PTRACE_SYSCALL, cpid, NULL, NULL);
}
}
return 0;
}
/**
* i already know the format of the string inside traceme.asm
* so i'll just need to uppercase everything before the newline
* there is no need to call toupper()
*/
void uppercase(char *str)
{
while (*str != 0xa) *str++ -=32;
}
void put_data(pid_t child, long addr, char *str, int len)
{
long word;
long i;
i = 0;
long *lptr = (long *) str;
while (i < len) {
word = *lptr++;
ptrace(PTRACE_POKEDATA, child, addr + i, word);
i += 4;
}
}
void get_data(pid_t child, long addr, char *str, int len)
{
long *laddr;
long i;
long word;
laddr = (long *)str;
i = 0;
while(i < len) {
word = ptrace(PTRACE_PEEKDATA, child, addr + i , NULL);
*laddr++ = word;
i+=4;
}
str[len] = '\0';
}
