#include <sys/ptrace.h> //For ptrace()
#include <sys/wait.h>   //For waitpid()
#include <stdio.h> //For printf()

#ifdef __cplusplus
extern "C" {
#endif

int main () {
	printf("Starting to int...");
	int errno = 0;
    int pid = 1337; //The process id you wish to attach to
    int address = 0xb51b7c; //The address you wish to read in the process

    //First, attach to the process
    //All ptrace() operations that fail return -1, the exceptions are
    //PTRACE_PEEK* operations
    printf("Starting to ptrace...");
    if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1) {
    	printf("Read the value of errno for details.");
        //Read the value of errno for details.
        //To get a human readable, call strerror()
        //strerror(errno) <-- Returns a human readable version of the
        //error that occurred
        return 0;
    }
    
    //Now, attaching doesn't mean we can read the value straight away
    //We have to wait for the process to stop
    int status;
    //waitpid() returns -1 on failure
    //W.I.F, not W.T.F
    //WIFSTOPPED() returns true if the process was stopped when we attached to it
    if (waitpid(pid, &status, 0) == -1 || !WIFSTOPPED(status)) {
    	printf("Failed, read the value of errno or strerror(errno)");
        //Failed, read the value of errno or strerror(errno)
        return 0;
    }

    errno = 0; //Set errno to zero
    //We are about to perform a PTRACE_PEEK* operation, it is possible that the value
    //we read at the address is -1, if so, ptrace() will return -1 EVEN THOUGH it succeeded!
    //This is why we need to 'clear' the value of errno.
    int value = ptrace(PTRACE_PEEKDATA, pid, (void*)address, NULL);
    if (value == -1 && errno != 0) {
    	printf("Failed, read the value of errno or strerror(errno)");
        //Failed, read the value of errno or strerror(errno)
        return 0;
	
	errno = 0; //Set errno to zero
    //We are about to perform a PTRACE_PEEK* operation, it is possible that the value
    //we read at the address is -1, if so, ptrace() will return -1 EVEN THOUGH it succeeded!
    //This is why we need to 'clear' the value of errno.
    int value = ptrace(PTRACE_PEEKDATA, pid, (void*)address, NULL);
    if (value == -1 && errno != 0) {
    	printf("Failed, read the value of errno or strerror(errno)");
        //Failed, read the value of errno or strerror(errno)
        return 0;
    } else {
    	printf("Success! Read the value");
        //Success! Read the value
    }

    //Now, we have to detach from the process
    ptrace(PTRACE_DETACH, pid, NULL, NULL);
    return 0;
}
}