Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

targeted injection on Linux via ptrace #37

Open
derekbruening opened this issue Nov 27, 2014 · 3 comments
Open

targeted injection on Linux via ptrace #37

derekbruening opened this issue Nov 27, 2014 · 3 comments

Comments

@derekbruening
Copy link
Contributor

From [email protected] on February 24, 2009 09:59:58

we should implement targeted injection a la drinject on Linux, via ptrace,
as an alternative when LD_PRELOAD is unavailable (due to security policies)

Original issue: http://code.google.com/p/dynamorio/issues/detail?id=37

@derekbruening
Copy link
Contributor Author

From [email protected] on February 24, 2009 07:00:15

this was PR 248204

@derekbruening
Copy link
Contributor Author

From [email protected] on December 03, 2012 10:49:44

I've implemented most of the pieces of this over a series of weekends. I've been working on it off and on, so it hasn't been reviewed incrementally.

Here's an outline of the approach. Now that we're libc independent ( issue #46 ) and can do early injection ( issue #47 ), libdynamorio.so doesn't need to be relocated, so long as it's loaded at its preferred base. That makes injection really easy, so long as the preferred base is open. We just need to execute the right mmap() and mprotect() syscalls.

ptrace provides a way to read and write registers and memory, but it doesn't provide a way to execute syscalls in the traced process. We can build syscall execution with those primitives, though. In the injector, I wrote some code that uses DR's standalone decoder to encode some code snippets that execute a single syscall and then break. With ptrace, we can insert the code into the process, run it, regain control, and then put back the original code and registers.

Using that, I built up injectee_map_file(), injectee_prot(), and injectee_unmap() primitives that I could use with our private loader. We can call into our private loader with these function pointers, and it will map DR into the injectee.

Once we've done that, we can push the initial mcontext and other takeover data onto the app's current stack and go to a takeover PC somewhere in DR. For now I'm using _start in x86.asm since it's easy to find in the ELF header and it already sets up a real stack frame.

Owner: [email protected]

@derekbruening
Copy link
Contributor Author

From [email protected] on March 12, 2013 06:46:23

Moved from https://code.google.com/p/dynamorio/issues/detail?id=38#c5 Testing on modern distros is made more difficult by the ptrace_scope stuff that's been done recently. I want to add a test for attach, but I don't want to require devs to set /proc/sys/kernel/yama/ptrace_scope to 0 in order to get the test to pass.

The new restrictions say that you can only ptrace a child process. I think I can adequately test our injection if I do the following:

  • master process: fork+execve injector
  • injector process: fork+execve app
  • injector process: wait for app to do something interesting
  • injector process: execve drrun -attach
  • master process: wait on injector, wait on app (can't waitpid on grandchild, need a pipe or file)

derekbruening added a commit that referenced this issue Jul 5, 2023
8 of the 13 tests on Mac AArch64 labeled "OSX" fail prior to this PR.
Here we fix the following:

+ Syscall success is indicated by the carry flag just like x86 Mac
+ Handle sigreturn with its extra parameters just like x86 Mac
+ Fix signal handler parameters
+ Fix stolen register support in signal contexts
+ Use MAP_JIT and pthread_jit_write_protect_np for +rwx gencode in tests
+ Use DYLD_LIBRARY_PATH on Mac in tests

Now all 13 tests pass:
---------------------------------------------------------------------------------------
ctest -j 5 -L OSX
 1/13 Test  #13: code_api|common.fib ................................  Passed  0.59 sec
 2/13 Test #243: code_api|libutil.frontend_test .....................  Passed  0.63 sec
 3/13 Test #231: code_api|api.ir ....................................  Passed  0.67 sec
 4/13 Test   #9: code_api|linux.sigaction.native ....................  Passed  0.25 sec
 5/13 Test  #31: code_api|linux.signal0000 ..........................  Passed  0.10 sec
 6/13 Test #240: code_api|api.ir-static .............................  Passed  0.34 sec
 7/13 Test #241: code_api|api.drdecode ..............................  Passed  0.38 sec
 8/13 Test #245: code_api|api.dis-a64 ...............................  Passed  1.15 sec
 9/13 Test #264: no_code_api,no_intercept_all_signals|linux.sigaction  Passed  0.08 sec
10/13 Test  #33: code_api|linux.signal0010 ..........................  Passed  0.34 sec
11/13 Test  #35: code_api|linux.signal0100 ..........................  Passed  0.42 sec
12/13 Test  #37: code_api|linux.signal0110 ..........................  Passed  0.45 sec
13/13 Test   #7: samples_proj .......................................  Passed  1.89 sec
100% tests passed, 0 tests failed out of 13
---------------------------------------------------------------------------------------

Issue: #5383
github-merge-queue bot pushed a commit that referenced this issue Jul 7, 2023
8 of the 13 tests on Mac AArch64 labeled "OSX" fail prior to this PR.
Here we fix the following:

+ Syscall success is indicated by the carry flag just like x86 Mac
+ Handle sigreturn with its extra parameters just like x86 Mac
+ Fix signal handler parameters
+ Fix stolen register support in signal contexts
+ Use MAP_JIT and pthread_jit_write_protect_np for +rwx gencode in tests
+ Use DYLD_LIBRARY_PATH on Mac in tests

Now all 13 tests pass:
```
---------------------------------------------------------------------------------------
$ ctest -j 5 -L OSX
 1/13 Test  #13: code_api|common.fib ................................  Passed  0.59 sec
 2/13 Test #243: code_api|libutil.frontend_test .....................  Passed  0.63 sec
 3/13 Test #231: code_api|api.ir ....................................  Passed  0.67 sec
 4/13 Test   #9: code_api|linux.sigaction.native ....................  Passed  0.25 sec
 5/13 Test  #31: code_api|linux.signal0000 ..........................  Passed  0.10 sec
 6/13 Test #240: code_api|api.ir-static .............................  Passed  0.34 sec
 7/13 Test #241: code_api|api.drdecode ..............................  Passed  0.38 sec
 8/13 Test #245: code_api|api.dis-a64 ...............................  Passed  1.15 sec
 9/13 Test #264: no_code_api,no_intercept_all_signals|linux.sigaction  Passed  0.08 sec
10/13 Test  #33: code_api|linux.signal0010 ..........................  Passed  0.34 sec
11/13 Test  #35: code_api|linux.signal0100 ..........................  Passed  0.42 sec
12/13 Test  #37: code_api|linux.signal0110 ..........................  Passed  0.45 sec
13/13 Test   #7: samples_proj .......................................  Passed  1.89 sec
100% tests passed, 0 tests failed out of 13
---------------------------------------------------------------------------------------
```
Issue: #5383
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant