0

I'm new to stack and relatively new to C. I try to read a process memory from another process with the use of ptrace. So far I managed to read and alter numbers from another process . But with strings I could not find a way. Here is my code:

int errno;
//the string we want to read is 8 bytes long
long len = 8;
const int buflen = (len / sizeof(long)) + 1;
void *buffer;
long *base;
char *data;
int i;
//the process pid i want to track
pid_t pid = 2984;
//the address that the string we want to read resides 
void *addr = (unsigned long int*) 0x7ffe03f6e088 ;

buffer = calloc(buflen, sizeof(long));
if (NULL == buffer)
{
    perror("Fault at allocation: ");    
}

base = (long *) buffer; 

ptrace(PTRACE_ATTACH, pid, NULL, NULL);

for (i = 0; i < buflen; i++) {
    if(ptrace(PTRACE_PEEKDATA, pid , addr + (sizeof(long) * i),NULL) !=  -1)
    {
    *(base + i) = ptrace(PTRACE_PEEKDATA, pid , addr + (sizeof(long) * i),
                     NULL);
    }else
    {
        fprintf(stderr, "Value of errno: %s\n", strerror(errno));
    }
}

ptrace(PTRACE_DETACH, pid, NULL, NULL);

/* Pop a null at the end, since we're printing this string. */
*((char *) buffer + len) = '\0';

data = (char *)buffer;  

printf("%p[\"%s\"]\n",addr, data);
free(buffer);

And the output:

Value of errno: No such process
Value of errno: No such process
0x7ffe03f6e088[""]

However the process id is correct and similar code works when the addr points to a number. Please help me.

[EDIT]
Bellow is the tracee process code:

char *a = "lala";
pid_t child;
printf("Char length: %ld\n", strlen(a));
printf("Char value: %s\n", a);
//the address I use to read variable
printf("Char address: %p\n", &a);
//make the process sleep so I can halt it manually
sleep(3);
  • Are you sure the PID is correct, because a PID is not guaranteed to be the same when you restart a program. – Alexguitar Dec 19 '15 at 14:26
  • yes Im sure cause I stop the target process before running the tracer process...so only for test purposes I hardcode the PID number and the string's address of the halted process. – bill marko Dec 19 '15 at 14:34
  • What is the return value of `ptrace(PTRACE_ATTACH, pid, NULL, NULL);`? – Mark Plotnick Dec 19 '15 at 14:38
  • sorry for the delay... @MarkPlotnick the result of ptrace(PTRACE_ATTACH, pid, NULL, NULL) is -1. However after some retries without altering the code just the tracee proceess and its hardcoded PID and address I get the result : 0x7fff1d224748["�@"]. ptrace(PTRACE_ATTACH, pid, NULL, NULL) is still -1. – bill marko Dec 20 '15 at 13:53
  • If you change that statement to `if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) { perror("Cannot attach"); }`, what error message do you get? – Mark Plotnick Dec 21 '15 at 00:04
  • no error message is shown this time... however still the the result is rubbish : 0x7fff9bde4e58[" @"] I dont get it...... – bill marko Dec 21 '15 at 10:18
  • why it keeps showing rubbish... please help.... – bill marko Dec 22 '15 at 15:27
  • You said you're "altering the tracee process" and as a result, ptrace is no longer returning -1. How are you altering it? – Mark Plotnick Dec 22 '15 at 16:02
  • If you run `gdb -p the-process-id`, then do `(gdb) print *(char *)0xthe-addr`, do you see the expected value? – Mark Plotnick Dec 22 '15 at 16:09
  • By altering meant restarting...sorry...i did what you said and the output is: $1 = 84 'T' and its not the expected value . The variable a want to read is of type char *. – bill marko Dec 22 '15 at 16:49
  • i tried to use an array in my tracee process to do the same thing and i succeded in reading its char contents. However i need to read a char * type.... – bill marko Dec 22 '15 at 16:54
  • Can you clarify something for me? When you read the 8 bytes from the target process, are you trying to read an 8-byte char * variable, or are you trying to read the first 8 characters of a string? – Mark Plotnick Dec 23 '15 at 18:20
  • οκ.... I tried to read a char of size 8 bytes or smaller... – bill marko Dec 23 '15 at 19:09
  • correction... a char* type of 8 bytes or smaller – bill marko Dec 23 '15 at 19:19
  • Can you show the source code of the tracee process? – Mark Plotnick Dec 23 '15 at 23:52
  • OK, that's what I thought. Your tracee process is printing the address of the char* pointer itself, not the address of the beginning of the character string. – Mark Plotnick Dec 26 '15 at 23:58
  • 2
    Here are two choices: (1) have the tracee print `printf("Char address: %p\n", a);` and run your tracer code as-is (2) leave the tracee code as-is and modify your tracer process so it reads in `sizeof(char *)` bytes from the target, stores that result (after appropriate numeric shifts if you needed to use several ptrace requests to read it all in) in `addr`, then continue as-is. – Mark Plotnick Dec 27 '15 at 00:09
  • Oh...so stupid of me! Thank you very much, thats what i needed! – bill marko Dec 28 '15 at 15:27

2 Answers2

1

Your tracee process is printing the address of the char* pointer itself, not the address of the beginning of the character string.

Here are two choices: (1) have the tracee print printf("Char address: %p\n", a); and run your tracer code as-is (2) leave the tracee code as-is and modify your tracer process so it reads in sizeof(char *) bytes from the target, stores that result (after appropriate numeric shifts if you needed to use several ptrace requests to read it all in) in addr, then continue as-is.

– Mark Plotnick

Armali
  • 18,255
  • 14
  • 57
  • 171
0

man pages says:

PTRACE_ATTACH Attach to the process specified in pid, making it a tracee of the calling process. The tracee is sent a SIGSTOP, but will not necessarily have stopped by the completion of this call; use waitpid(2) to wait for the tracee to stop. See the "Attaching and detaching" subsection for additional information. (addr and data are ignored.)

just append a wait() function to wait child enter stopped status.

mlchen
  • 1
  • 1