0

I want to create a simple tool (with C) which can do this tiny subset of gdbs features:

  1. Attach to an already running program (with PID)
  2. Inject instructions into it like this:

dup2(open("/tmp/my_stdout", 1089, 0777), 1)

GDB can do this without issues, but it has a massive source.

What Im looking for is some kind of starting point of guidance.

There are tons of information on Google but all of them are 10ish years old, and I need to make this work on aarch64 arch which was not existed by that time.

Really, any help is greatly appreciated.

I tried to strace gdb while it is attaching to a process, but my terminal blowed up literally.

Daniel
  • 2,318
  • 2
  • 22
  • 53
  • 2
    You've tagged `ptrace` so clearly you have some idea that that is what is needed. Have you read the [ptrace manual](https://man7.org/linux/man-pages/man2/ptrace.2.html) and searched for examples. After that you should try some code and narrow down what specifically about using `ptrace` you have issue with. – kaylum May 01 '22 at 07:54
  • @kaylum: I couldn't reach too far, can you please check two related questions of mine: https://stackoverflow.com/questions/72076261/how-can-i-use-ptrace-pokeuser-to-fill-parameters-of-nr-mmap-on-an-attached-p https://stackoverflow.com/questions/72076404/how-can-i-inject-code-to-attached-process – Daniel May 01 '22 at 13:12

1 Answers1

1

Im looking for is some kind of starting point of guidance.

Take a look at the unwind-pid example here. It uses ptrace to unwind the stack of an alien process, identified by PID.

Note: you could ignore all the unw_* calls. The "attach to pid" part is rather trivial:

    pid_t pid = atoi(argv[1]);
    if (ptrace(PTRACE_ATTACH, pid, 0, 0) != 0)
        die("ERROR: cannot attach to %d\n", pid);
...
    (void) ptrace(PTRACE_DETACH, pid, 0, 0);

Inject instructions into it like this: dup2(open("/tmp/my_stdout", 1089, 0777), 1)

Search for "Linux inject code into running process". Here is one example.

Update:

That will not work, I think. I don't want to dup2 the tracer's stdout. I want to dup2 the tracee's stdout!

Yes you do, and yes it will.

Well, maybe not quite (you could do it with code injection, but you don't have to).

What you want to do is construct (on the stack and in registers) the state of the tracee as if it just called open("/tmp/my_stdout", ...) itself. Then set a breakpoint after open returns, set IP to open and resume the tracee. The tracee will run until the breakpoint, at which point you will have an open fd in the results register. Now repeat the same process for dup2, and you are done.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • Attachment is done. But I don't know how to proceed. – Daniel May 01 '22 at 15:42
  • That will *not* work, I think. I don't want to dup2 the tracer's stdout. I want to dup2 the *tracee*'s stdout! For that tracee has to open the `/tmp/my_stdout` and tracee has to call dup2 on that opened FD. – Daniel May 01 '22 at 17:53
  • "That will not work ..." -- yes it will. I've updated the answer again. – Employed Russian May 01 '22 at 19:26