⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trace-x86.c

📁 It s a Linux disassemble, can set break point, disassemble ELF file.
💻 C
📖 第 1 页 / 共 2 页
字号:
   * All went well   */  return (1);} /* x86stepIntoDebug() *//*x86stepOverDebug()  Single step our program, stepping past any subroutinesInputs: ws   - debug workspace        num  - number of instructions to step over        data - modified to contain info depending on the return               result, see belowReturn: 0 if unsuccessful        1 if successful        2 if program stops due to a signal        3 if breakpoint encountered        4 if program terminatesSide effects: If the process stops due to a signal, data is              modified to contain the signal number.              If the process stops due to a breakpoint, data is              modified to contain the breakpoint number.              If the process terminates normally, data is modified              to contain the exit status.*/intx86stepOverDebug(struct debugWorkspace *ws, int num, int *data){  int ii,      dret,             /* return value from dump memory routine */      pret;             /* return value from a ptrace function */  unsigned long slen;   /* length of subroutine call opcode */  unsigned char *opbuf; /* contains potential call opcode */  assert(num > 0);  if (ws->pid == NOPID)  {    int ret;    ret = x86execDebug(ws);    if (ret == 2)      return (6); /* not an executable file */    else if (ret == 0)      return (0); /* something went wrong */  }  dbSetRunning(ws);  for (ii = 0; ii < num; ++ii)  {    slen = 0;    opbuf = 0;    /*     * Dump 20 bytes of memory so we can tell if we are about     * to enter a subroutine     */    dret = x86dumpMemoryDebug(ws, &opbuf, ws->instructionPointer, 20);    if (opbuf)    {      if (dret > 0)        slen = IsSubroutine(opbuf);      free(opbuf);    }    if (slen)    {      int bret;      unsigned long baddr;      /*       * We are about to enter a subroutine - set a breakpoint       * at location ws->instructionPointer + slen.       */      baddr = (unsigned long) (ws->instructionPointer + slen);      bret = setAndSaveBreakpoint(ws, baddr, BK_TEMPORARY | BK_STEPOVER);      /*       * Now continue until we hit the breakpoint       */      pret = x86DoContinue(ws, data);      if (pret == 3)      {        if (*data == 0)        {          /*           * A value of 0 means we hit the temporary breakpoint           * at the address after the call instruction - so we           * do not need to inform the user about it. Continue           * stepping.           */          continue;        }        /*         * It is most likely a breakpoint which was set inside         * of the subroutine we were trying to step over. It         * could also be a breakpoint at the exact address we set         * our temporary breakpoint.         */        return (3);      }      else      {        /*         * 'data' will have been set appropriately by         * x86GetDebugProcessStatus()         */        return (pret);      }    } /* if (slen) */    /*     * We are not about to enter a subroutine - just step     * one instruction     */    pret = x86DoSingleStep(ws, data);    if (pret != 1)    {      /*       * Something happened (signal, breakpoint, exit, etc)       */      return (pret);    }  } /* for (ii = 0; ii < num; ++ii) */  /*   * All went well   */  return (1);} /* x86stepOverDebug() *//*x86continueDebug()  Continue the debugged process where it left offInputs: ws   - debug workspace        data - modified to contain info depending on return valueReturn: 0 if unsuccessful        1 if successful        2 if program stops due to a signal (signal put into data)        3 if breakpoint encountered (brk pt number put into data)        4 if program terminates (exit status put into data)        6 if program is not executable        7 if program terminates due to a signal (signal num put into data)*/intx86continueDebug(struct debugWorkspace *ws, int *data){  if (ws->pid == NOPID)  {    int ret;    ret = x86execDebug(ws);    if (ret == 2)      return (6); /* not an executable file */    else if (ret == 0)      return (0); /* something went wrong */  }  dbSetRunning(ws);  return (x86DoContinue(ws, data));} /* x86continueDebug() *//*x86attachDebug()  Attach to a currently running processInputs: ws  - debug workspace        pid - process idReturn: 1 if successful, 0 if not*/intx86attachDebug(struct debugWorkspace *ws, int pid){  int err;  int waitval;  if (ptrace(PT_ATTACH, pid, 0, 0) != 0)    return (0); /* something went wrong */  wait(&waitval);  ws->pid = (pid_t) pid;  /*   * Set the instruction pointer to the program's current position   */  err = 0;  ws->instructionPointer = x86getCurrentInstruction(ws, &err);  if (err)  {    /*     * The most likely cause of this is that the file is not     * executable     */    ws->pid = NOPID;    return (0);  }  dbSetAttached(ws);  dbSetRunning(ws);  return (1);} /* x86attachDebug() *//*x86detachDebug()  Detach from current processInputs: ws - debug workspaceReturn: -1 if not currently attached        0 if ptrace fails        pid of detached process if successful*/intx86detachDebug(struct debugWorkspace *ws){  int waitval;  int pid;  if (!dbIsAttached(ws))    return (-1);  if (ptrace(PT_DETACH, ws->pid, 0, 0) != 0)    return (0); /* something went wrong */  wait(&waitval);  pid = ws->pid;  ws->pid = NOPID;  dbClearAttached(ws);  dbClearRunning(ws);  return (pid);} /* x86detachDebug() *//*x86killDebug()  Kill current debugged processReturn: 1 if successful        0 if not*/intx86killDebug(struct debugWorkspace *ws){  int ret;  int waitval;  if (ws->pid != NOPID)  {    ret = ptrace(PT_KILL, ws->pid, 0, 0);    if (ret == 0)      wait(&waitval);  }  return (1);} /* x86killDebug() *//*x86saveBreakpoint()  Save the contents of a breakpoint's memory location, so we can restore it laterInputs: ws   - debug workspace        bptr - breakpoint structure containing infoReturn: 1 if successful        0 if not*/intx86saveBreakpoint(struct debugWorkspace *ws, struct Breakpoint *bptr){  int saved; /* saved instruction */  assert(bptr != 0);  assert(ws->pid != NOPID);#if 0  if (ws->pid == NOPID)  {    if (x86execDebug(ws) == 0)      return (0); /* something went wrong */  }#endif  /*   * Save lowest byte of the dword at the break address   */  saved = PtraceRead(ws->pid, bptr->address, 0);  if (saved == (-1))    return (0); /* error - most likely EIO */  bptr->svdinsn = saved;  return (1);} /* x86saveBreakpoint() *//*x86enableBreakpoint()  Enable breakpoint by setting the first byte of it'smemory address to the breakpoint instructionReturn: 1 if successful        0 if not*/intx86enableBreakpoint(struct debugWorkspace *ws, struct Breakpoint *bptr){  int insn;  int data;  assert(ws->pid != NOPID);  assert(bptr != 0);  /*   * We must read the contents of bptr->address again, even though we have   * previously saved the contents of that location. The reason for this is   * the following scenario: If we set 2 breakpoints, within 4 bytes of each other,   * when we enable the first, we stick a 0xCC in the first byte of it's location.   * If the second breakpoint occurs before the first in memory, we will overwrite   * the original 0xCC when writing the modified word for the second breakpoint.   * Unfortunately, ptrace cannot be used to write a single byte without disturbing   * adjacent bytes.   */  data = PtraceRead(ws->pid, bptr->address, 0);  if (data == (-1))    return (0); /* error - most likely EIO */  /*   * This is little-endian specific   */  insn = (data & ~0x000000FF) | BRKPT_INSN;#if 0  insn = (bptr->svdinsn & ~0xFF) | BRKPT_INSN;#endif  /*   * Replace the instruction with our breakpoint instruction   */  if (PtraceWrite(ws->pid, bptr->address, insn) != 0)    return (0);  return (1);} /* x86enableBreakpoint() *//*x86disableBreakpoint()  Restore breakpoint address with it's original instructionReturn: 1 if successful        0 if not*/intx86disableBreakpoint(struct debugWorkspace *ws, struct Breakpoint *bptr){  assert(ws->pid != NOPID);  assert(bptr != 0);  /*   * Replace the instruction with our saved instruction   */  if (PtraceWrite(ws->pid, bptr->address, bptr->svdinsn) != 0)    return (0);  return (1);} /* x86disableBreakpoint() *//*x86dumpMemoryDebug()  Dump memory contents of debugged processInputs: ws    - debug workspace        buf   - buffer to store memory bytes in        start - address to start dump        bytes - number of bytes to dumpReturn: number of bytes dumped - if this is less than 'bytes',        an error occurred, and errno should be set appropriately.Side effects: space is allocated for 'buf', so it must be freed by              the calling function*/longx86dumpMemoryDebug(struct debugWorkspace *ws, unsigned char **buf,                   unsigned long start, unsigned long bytes){  int wordval;  unsigned long addr, /* current address we are examining */                end;  /* last address to examine */  unsigned char *bufptr;  long ret;           /* return value */  if (ws->pid == NOPID)  {    if (x86execDebug(ws) == 0)      return (0); /* something went wrong */  }  addr = start;  end = start + bytes;  if (end < start)    return (0); /* integer overflow */  if ((bytes + 1) == 0)    return (0); /* integer overflow */  *buf = (char *) malloc(bytes + 1);  if (*buf == NULL)    return (0);  bufptr = (unsigned char *) *buf;  ret = 0;  while (addr < end)  {    wordval = PtraceRead(ws->pid, addr, 0);    if ((wordval == (-1)) && (errno == EIO))    {      /*       * Input/output error       */      return (ret);    }    /*     * The ptrace() call will return a 2 byte (word) value on     * intel systems, and little-endian will put the byte at     * the address 'addr' last, so anding with 0xff will separate     * that byte.     */    *bufptr++ = (unsigned char) (wordval & 0xff);    ++addr;    ++ret;  } /* while (addr <= end) */  *bufptr = '\0';  return (ret);} /* x86dumpMemoryDebug() *//*x86setMemoryDebug()  Set the contents of memory location 'address' to 'value'Inputs: ws      - debug workspace        address - memory address        value   - value to setReturn: 0 if unsuccessful (ptrace error)        number of bytes written if successful*/intx86setMemoryDebug(struct debugWorkspace *ws, unsigned long address, unsigned long value){  int wordval;  int ret;  unsigned int mask;  if (ws->pid == NOPID)  {    if (x86execDebug(ws) == 0)      return (0); /* something went wrong */  }  /*   * An interesting note about ptrace() - although it is documented   * to return a "word", it actually returns the size of an int,   * in this case 32 bits, when it should actually return 16 bits,   * the size of an intel word.   * This works for PtraceWrite() too - it writes a 32 bit quantity   * to the address you specify.   */  wordval = PtraceRead(ws->pid, address, 0);  if (wordval == (-1))    return (0);  ret = 0;  /*   * Determine how many bytes the calling program wants to write   * to memory - if we simply try to write the 32 bit quantity   * 'value', and it is a 1 byte number, we will overwrite 3 bytes   * of memory with zeros   */  if ((value & 0xff) == value)  {    ret = 1; /* we are setting 1 byte */    mask = 0xffffff00;  }  else if ((value & 0xffff) == value)  {    ret = 2; /* we are setting 2 bytes */    mask = 0xffff0000;  }  else if ((value & 0xffffff) == value)  {    ret = 3; /* we are setting 3 bytes */    mask = 0xff000000;  }  else  {    ret = 4; /* we are setting 4 bytes */    mask = 0x00000000;  }  /*   * Clear the byte(s) we are about to change   */  wordval &= mask;  /*   * Set the new byte(s)   */  wordval |= value;  if (PtraceWrite(ws->pid, address, wordval) != 0)    return (0);  return (ret);} /* x86setMemoryDebug() */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -