Created
March 28, 2017 07:02
-
-
Save FergusInLondon/fec6aebabc3c9e61e284983618f40730 to your computer and use it in GitHub Desktop.
snoopy.c - process_vm_readv() demonstration.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* snoopy.c - Snoop on another tasks memory. | |
* Fergus In London <[email protected]> | |
* | |
* This is a pretty basic demo of the process_vm_readv syscall, a syscall which | |
* provides a nicer interface than ptrace for accessing memory used by another | |
* task. | |
* | |
* To play with simply use `ps` to get a PID for the process you'd like to snoop | |
* on, and `pmap` for the relevant memory address. | |
* | |
* Wrote whilst eating a bagel during breakfast.. probably not the nicest code. | |
* | |
* Requires a Linux Kernel > 3.2. | |
* https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html | |
*/ | |
#define _GNU_SOURCE | |
#include <sys/uio.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <errno.h> | |
int main(int argc, char **argv) { | |
if (argc < 3) { | |
printf("usage: %s <pid> <mem address> [len]\n", argv[0]); | |
printf(" <pid> - PID of process to target\n"); | |
printf(" <mem> - Memory address to target\n"); | |
printf(" [len] - Length (in bytes) to dump\n"); | |
return -1; | |
} | |
// PARSE CLI ARGS | |
pid_t pid = strtol(argv[1], NULL, 10); | |
printf(" * Launching with a target PID of: %zd\n", pid); | |
void *remotePtr = (void *)strtol(argv[2], NULL, 0); | |
printf(" * Launching with a target address of 0x%llx\n", remotePtr); | |
size_t bufferLength = (argc > 3) ? strtol(argv[3], NULL, 10) : 20; | |
printf(" * Launching with a buffer size of %d bytes.\n", bufferLength); | |
// Build iovec structs | |
struct iovec local[1]; | |
local[0].iov_base = calloc(bufferLength, sizeof(char)); | |
local[0].iov_len = bufferLength; | |
struct iovec remote[1]; | |
remote[0].iov_base = remotePtr; | |
remote[0].iov_len = bufferLength; | |
// Call process_vm_readv - handle any error codes | |
ssize_t nread = process_vm_readv(pid, local, 2, remote, 1, 0); | |
if (nread < 0) { | |
switch (errno) { | |
case EINVAL: | |
printf("ERROR: INVALID ARGUMENTS.\n"); | |
break; | |
case EFAULT: | |
printf("ERROR: UNABLE TO ACCESS TARGET MEMORY ADDRESS.\n"); | |
break; | |
case ENOMEM: | |
printf("ERROR: UNABLE TO ALLOCATE MEMORY.\n"); | |
break; | |
case EPERM: | |
printf("ERROR: INSUFFICIENT PRIVILEGES TO TARGET PROCESS.\n"); | |
break; | |
case ESRCH: | |
printf("ERROR: PROCESS DOES NOT EXIST.\n"); | |
break; | |
default: | |
printf("ERROR: AN UNKNOWN ERROR HAS OCCURRED.\n"); | |
} | |
return -1; | |
} | |
printf(" * Executed process_vm_ready, read %zd bytes.\n", nread); | |
printf("%s\n", local[0].iov_base); | |
return 0; | |
} |
Sorry to bother you. There is one thing in the code that I don't quite understand: why is the value of liovcnt
equal to 2 when calling process_vm_readv
? Shouldn't it be 1?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@Frago9876543210
I'm running debian 11 on an arm64 embedded linux system
https://askubuntu.com/questions/146160/what-is-the-ptrace-scope-workaround-for-wine-programs-and-are-there-any-risks
i found this page but I turned the process_vm_readv and process_vm_writev into a python library and when i try
:~# setcap cap_sys_ptrace=eip /usr/moduline/python/read_test.py
Failed to set capabilities on file `/usr/moduline/python/read_test.py' (Operation not supported)
The value of the capability argument is not permitted for a file. Or the file is not a regular (non-symlink) file
Okay I compiled snoopy, and that seems to work. so there seems to be an issue where my python module/shared library is not getting the right permissions