1

I'm working on a Linux application incorporating ptrace to observe another process which had been created by fork() system call.

Strictly speaking: I want to implement a fault injection into forked process (chile process or "tracee").

As you can see in the figure below:

enter image description here

enter image description here

the tracer gets the regs (struct_user_regs) structure from the tracee by using PTRACE_GETREGS request. after that, tracer modifies the EIP value of the tracee (when kernel switch into tracee, order execution will be violate so-called control flow error CFE). then PTRAC E_CONT request will send to tracee to continue its execution.

Unfortunately, after modifying the EPI's tracee, the tracee doesn't continue its execution due to (segmentation fault). How I can give an another suitable vaule to the tracee EIP?

here is the code

#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include<sys/user.h>
#include<sys/reg.h>
#include<stdlib.h>
#include<stdio.h>
#include <asm/ptrace-abi.h>

 int main()

 { 

  pid_t child;
  int status;
  int sum=0;
  struct user_regs_struct regs;


    child = fork();
    if(child == 0) {
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);

         printf("hello world 1\n");
         printf("hello world 2\n");
         raise (SIGINT); // just to move control to the tracer 
         printf("hello world 3\n");
         printf("hello world 4\n");
         printf("hello world 5\n");

         exit(EXIT_SUCCESS);
     }
    else {

          wait(NULL);
          ptrace(PTRACE_GETREGS, child,NULL, &regs);
          printf("\n EIP @  0x %#lx\n",regs.eip);
          //get the tracee EIP
          long int new_eip=ptrace(PTRACE_PEEKTEXT, child,regs.eip,NULL);
          //chabge EIP and poke it again
          new_eip += ???; // make change that let to jump to another tracee instruction address (say to print hello world 5)
          ptrace(PTRACE_POKETEXT, child,regs.eip,new_eip);
          ptrace(PTRACE_CONT, child, NULL, NULL);

          }

    return 0;
}

Any thoughts? Thank you for all your assistance.

2 Answers2

1

You're not modifying the EIP, you're adding something to the value of the instruction at EIP, and probably resulting in a bad address reference. To change EIP, use PTRACE_SETREGS

      wait(NULL);
      ptrace(PTRACE_GETREGS, child,NULL, &regs);
      printf("\n EIP @  0x %#lx\n",regs.eip);
      regs.eip += ???;
      ptrace(PTRACE_SETREGS, child, NULL, &regs);
      ptrace(PTRACE_CONT, child, NULL, NULL);
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Yes you are correct. But what is the suitable value to add it to the EIP to point to the next or any instruction. I tried it : unsigned instruction_=ptrace(PTRACE_PEEKTEXT,child,regs.eip.NULL); then, regs.eip+=sizeof(instruction); I declared also the instruction_ as long int, but it didn't work too. – husin alhaj ahmade Aug 06 '16 at 18:58
  • Add the number of bytes in an instruction. That depends on the CPU architecture, and would even depend on what the instruction at the current EIP is, if instructions have different lengths. – Barmar Aug 06 '16 at 19:38
0

Yes, it is completely platform-specific. I read a lot of materials which described ptrace syscall and how we can use it to capture the EIP of the next instruction that is going to execute after the ptrace send some request (like PTRACE_CONT) to the suspended tracee. I always see that the EIP value is something like this :

 80484a6:
 80484a7:   
 80484ac:   
 80484b2:
 80484b4:
 80484b6:
 80484b8:

I test a simple code (just print the value of EIP and the corresponding executed instruction). but the result was as you shown below:

EIP: b773cbe0 Instruction executed: c3595a5d
EIP: b773cbe1 Instruction executed: ccc3595a
EIP: b773cbe0 Instruction executed: c3595a5d
hello world 5
EIP: b773cbe0 Instruction executed: c3595a5d
EIP: b773cbe1 Instruction executed: ccc3595a
EIP: b773cbe0 Instruction executed: c3595a5d
hello world 6
EIP: b773cbe0 Instruction executed: c3595a5d
EIP: b773cbe1 Instruction executed: ccc3595a
EIP: b773cbe0 Instruction executed: c3595a5d

what is this (b773cbe0) ??!!! I moved to gdb and viewed the dump file using this command line (objdump -d a.out) the result is something different with previous results

 8048864:   8b 6c 24 20             mov    0x20(%esp),%ebp
 8048868:   8d b3 0c ff ff ff       lea    -0xf4(%ebx),%esi
 804886e:   e8 41 fb ff ff          call   80483b4 <_init>
 8048873:   8d 83 08 ff ff ff       lea    -0xf8(%ebx),%eax
 8048879:   29 c6                   sub    %eax,%esi
 804887b:   c1 fe 02                sar    $0x2,%esi
 804887e:   85 f6                   test   %esi,%esi
 8048880:   74 23                   je     80488a5 <__libc_csu_init+0x55>
 8048882:   8d b6 00 00 00 00       lea    0x0(%esi),%esi
 8048888:   83 ec 04                sub    $0x4,%esp
 804888b:   ff 74 24 2c             pushl  0x2c(%esp)
 804888f:   ff 74 24 2c             pushl  0x2c(%esp)
 8048893:   55                      push   %ebp
 8048894:   ff 94 bb 08 ff ff ff    call   *-0xf8(%ebx,%edi,4)
 804889b:   83 c7 01                add    $0x1,%edi
 804889e:   83 c4 10                add    $0x10,%esp
 80488a1:   39 f7                   cmp    %esi,%edi
 80488a3:   75 e3                   jne    8048888 <__libc_csu_init+0x38>
 80488a5:   83 c4 0c                add    $0xc,%esp
 80488a8:   5b                      pop    %ebx
 80488a9:   5e                      pop    %esi
 80488aa:   5f                      pop    %edi
 80488ab:   5d                      pop    %ebp
 80488ac:   c3                      ret    
 80488ad:   8d 76 00                lea    0x0(%esi),%esi

I'm really confused about this.