Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Проектирование экзоскелета. Монография
.pdf
201
current=p;
}
/*********************************
* Get string from ptraced child *
*********************************/
static inline void get_string_from_child(const unsigned int addr, char*
buf,int max) {
int i=0;
char *b=buf;
while (b<buf+max) {
AS_UINT(*b)=ptrace(PTRACE_PEEKDATA,pid,addr+i,0);
if (AS_UINT(*b)==-1) {
*b=0;
return; // Lame, but what can I do? For strings, acceptable.
}
if (b[0] && ((!isprint(b[0])) || (b[0]=='"'))) b[0]='?';
if (b[1] && ((!isprint(b[1])) || (b[1]=='"'))) b[1]='?';
if (b[2] && ((!isprint(b[2])) || (b[2]=='"'))) b[2]='?';
if (b[3] && ((!isprint(b[3])) || (b[3]=='"'))) b[3]='?';
if (!(b[0] && b[1] && b[2] && b[3])) return;
b+=4; i+=4;
}
buf[max-1]=0;

202
}
static inline int issuit(const char c) {
if (isprint(c)) return 1;
if (/*c=='\n' || */ c=='\t') return 1;
return 0;
}
static inline void print_string(const unsigned int addr,const char*
where) {
char b[5] = {0,0,0,0,0};
int miau=0;
AS_UINT(b) = ptrace(PTRACE_PEEKDATA,pid,addr,0);
if (issuit(b[0]) && issuit(b[1]) && issuit(b[2]) && issuit(b[3])) {
debug(" \"%s",b);
miau=4;
while (strlen(b)==4) {
AS_UINT(b) = ptrace(PTRACE_PEEKDATA,pid,addr+miau,0);
if (b[0] && !isprint(b[0])) b[0]='?';
if (b[1] && !isprint(b[1])) b[1]='?';
if (b[2] && !isprint(b[2])) b[2]='?';
if (b[3] && !isprint(b[3])) b[3]='?';
if (miau<MAXUNKNOWN) debug("%s",b);
miau+=strlen(b);
}
debug("\"");
if (miau>=MAXUNKNOWN) debug("...");
}
if (miau) add_mem(addr,miau+1,2,where,0);
}

203
/****************************
* Get memory from child :> *
****************************/
static inline void get_mem_from_child(const unsigned int addr,
char* buf,int max) {
int i=0;
char *b=buf;
while (max % 4) max--;
while (b<buf+max) {
AS_UINT(*b)=ptrace(PTRACE_PEEKDATA,pid,addr+i,0);
b+=4; i+=4;
}
}
/*******************
* Check for error *
*******************/
char errbuf[64];
static inline char* toerror(int q) {
if (q<0) sprintf(errbuf,"%d (%s)",q,strerror(-q));
else sprintf(errbuf,"%d",q);
return errbuf;

204
}
/************************
* Quick fork() handler *
************************/
static void trace_fork(void) {
int p=0,q=0,off,ser;
struct user u;
off=(unsigned int)&u.regs.eax - (unsigned int)&u;
errno=1234;
// This is the speed zone.
ptrace(PTRACE_SINGLESTEP,pid,1,0);
while (errno) p=ptrace(PTRACE_PEEKUSER,pid,off, errno=0);
if (p>0) q=ptrace(PTRACE_ATTACH,p,0,0);
// End of speed zone.
ser=errno;
indent(0);
debug("%sfork () = %s\n",in_libc?"[L] ":"",toerror((int)p));
if (q) fatal("PTRACE_ATTACH failed",ser);
debug("+++ New process %d attached +++\n",p);
clone_process(p);
r.eax=p;
}

205
/****************************************************
* Handle int $0x80 calls - no matter why and where *
****************************************************/
static inline void want_ret(void) {
current->syscall=r.eax;
memcpy(¤t->pr,&r,sizeof(r));
}
/********************
* "Before" handler *
********************/
static void handle_syscall(void) {
char buf[MAXFNAME];
unsigned int addr;
if (current->nest>=-1) current->syscalls++;
switch (r.eax) {
case __NR_clone:
debug("*******************************************************
********\n"
"* This application uses clone(). This is probably a sign of *\n"
"* multi-threaded application. Multi-threading involves shared *\n"
"* memory segments, file descriptors and such, and I am not *\n"
"* able to handle it properly for now. Sorry... *\n"

206
"*************************************************************
**\n");
fatal("clone() is not supported",0);
break;
case __NR_fork:
#ifdef __NR_vfork
case __NR_vfork:
#endif /* __NR_vfork */
if (T_forks) trace_fork(); else {
remove_traps();
want_ret();
}
break;
case __NR_exit:
indent(0);
debug("%sSYS exit (%d) = ???\n",in_libc?"[L] ":"",
(int)r.ebx);
while (--current->nest>= -1 ) {
indent(0);
debug("...function never returned (program exited before).\n");
if (current->nest<0 || current->isfnct[current->nest]) {
dump_memchg(0);
if (current->fntop) current->fntop--;
}
if (T_dostep) break_nestdown();

207
}
break;
case __NR_execve:
indent(0);
get_string_from_child(r.ebx,buf,MAXFNAME);
RD();
debug("%sSYS execve (%x \"%s\", 0x%x, 0x%x) = ",in_libc?"[L] ":"",
Xv(r.ebx),buf,Xv(r.ecx),Xv(r.edx));
DD();
current->syscall=__NR_execve;
break;
case __NR_sigaction:
#ifdef __NR_rt_sigaction
case __NR_rt_sigaction:
#endif /* __NR_rt_sigaction */
// Modify address in memory structure.
addr=ptrace(PTRACE_PEEKDATA,pid,r.ecx,0);
if (!addr) break;
if ((addr >> 24) == CODESEG)
ptrace(PTRACE_POKEDATA,pid,r.ecx,addr-1);
else break;

208
goto aftersig;
case __NR_signal:
// Simply adjust address in register.
addr=r.ecx;
if (!addr) break;
if ((addr >> 24) == CODESEG || INLIBC(addr)) r.ecx--;
else break;
ptrace(PTRACE_SETREGS,pid,0,&r);
r.ecx++;
// So __NR_signal handler won't have to do anything.
aftersig:
// Inject int3 into code.
if (addr)
if ((addr >> 24) == CODESEG || INLIBC(addr)) {
unsigned int chg,c2;
chg=ptrace(PTRACE_PEEKDATA,pid,addr-1,0);
if ((current->signals < r.ebx) && (r.ebx < MAXSIG))
current->signals=r.ebx;
if (((chg & 0xff) != 0x90) && ((chg & 0xff) != 0xc3) && ((chg & 0xff) !=
0xcc)) {
c2=ptrace(PTRACE_PEEKDATA,pid,addr-3,0);
if ((c2 & 0xffffff) != 0x00768d) // Stupid gcc -O9 lea
debug("* WARNING: Handler for sig %d (%x) w/o leading NOP or RET,
problems!\n",(int)r.ebx,addr);
}

209
if ((chg & 0xff) == 0xc3) set_withret(r.ebx,1); else
if ((chg & 0xff) == 0x90) set_withret(r.ebx,0);
chg = ( chg & 0xffffff00 ) + 0xcc; /* cc: int3 */
ptrace(PTRACE_POKEDATA,pid,addr-1,chg);
}
default:
want_ret();
}
if (T_dostep && current) {
fflush(0);
break_syscall(r.eax);
}
}
/************************
* Add item to fd table *
************************/
static void add_filedes(const int fd,const char* fname,char* who,int
p) {
char tmpbuf[MAXDESCR];
if (!current->fd) {
current->fd=malloc(TABINC*sizeof(struct fenris_fd));
current->fdtop=TABINC;

210
}
while (current->fdtop<=fd) {
current->fdtop+=TABINC;
current->fd=realloc(current->fd,current->fdtop*sizeof(struct
fenris_fd));
}
(*current->fd)[fd].special=0;
(*current->fd)[fd].name=strdup(fname);
snprintf(tmpbuf,MAXDESCR,"opened in %s",who);
(*current->fd)[fd].descr=strdup(tmpbuf);
(*current->fd)[fd].p=p;
if (current->nest>=-1 && !T_nodesc) {
indent(0);
debug("@ created fd %d (%s)\n",fd,fname);
}
}
/***********************
* Add unknown filedes *
***********************/
static void unknown_filedes(const int fd,const char* fname) {
char tmpbuf[MAXDESCR];
if (!current->fd) {
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
