/* * jailer - main goal to jail a task afterwards * functions: * ./jailer chroot pid path * ./jailer setuid pid uid * ./jailer setgid pid uid */ #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 #define EWRONGFUNC 9 int main(int argc, char **argp) { long int pid; struct user_regs_struct uregs; struct user_regs_struct oregs; unsigned long esp; int ascall=0; char *newcmd; char *ept; unsigned char b4[4]; char buf[256]; int scall; int ln; if(argc!=4) { printf("Usage: %s function pid parameter\n\nchroot: parameter = path\nsetuid: parameter = uid\nsetgid: parameter = gid\n\ndone.",argp[0]); exit(ENOTENUFFPERM); } if(!strcmp(argp[1],"chroot")) { scall=__NR_chroot; } else if(!strcmp(argp[1],"setuid")) { scall=__NR_setuid; } else if(!strcmp(argp[1],"setgid")) { scall=__NR_setgid; } else { printf("Function %s unknown\n",argp[1]); exit(EWRONGFUNC); } pid=strtoul(argp[2],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 %s now\n",argp[1]); /* 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); memcpy(&oregs,&uregs,sizeof(oregs)); /* now, lets corrupt the stack */ switch(scall) { case __NR_setuid: case __NR_setgid: oregs.eax=scall; oregs.ebx=atoi(argp[3]); break; case __NR_chroot: oregs.eax=scall; esp=uregs.esp; esp-=20; esp-=strlen(argp[3]); oregs.eax=scall; oregs.ebx=esp; /* copy the task to be called */ newcmd=(char *)calloc(1,strlen(argp[3])+4); strcpy(newcmd,argp[3]); ept=newcmd; ln=0; while(*ept) { ptrace(PTRACE_POKETEXT,pid,esp+ln,*(unsigned long *)ept); ept+=4; ln+=4; } break; default: exit(0x0); } /* reset the registers */ if(ptrace(PTRACE_SETREGS,pid,&oregs,&oregs)) { ptrace(PTRACE_DETACH,pid,0L,0L); perror("setregs"); } if(ptrace(PTRACE_SINGLESTEP,pid,0L,0L)) { ptrace(PTRACE_DETACH,pid,0L,0L); perror("singlestep"); exit(ENOGETREGS); } waitpid(pid,NULL,WUNTRACED); /* reset 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); }