Skip to content

Instantly share code, notes, and snippets.

@FergusInLondon
Created March 28, 2017 07:02
Show Gist options
  • Save FergusInLondon/fec6aebabc3c9e61e284983618f40730 to your computer and use it in GitHub Desktop.
Save FergusInLondon/fec6aebabc3c9e61e284983618f40730 to your computer and use it in GitHub Desktop.
snoopy.c - process_vm_readv() demonstration.
/**
* 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;
}
@Frago9876543210
Copy link

Frago9876543210 commented Nov 29, 2022

@Frago9876543210

To bypass permission checking you can exec sudo sysctl kernel.yama.ptrace_scope=0 in bash

Hey I'm having permission issues, but this line seems to not do anything for me, it gives me:

sysctl: cannot stat /proc/sys/kernel/yama/ptrace_scope: No such file or directory

Is this a kernel config or something that i am missing or perhaps something else?

@SpieringsAE
What's linux is it? I tested this on x84_64 Ubuntu

@SpieringsAE
Copy link

SpieringsAE commented Nov 29, 2022

@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

@JiajunDu
Copy link

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