多维时空 发表于 2017-6-2 13:31:49

基础调试命令 - u/ub/uf

原文:http://www.cnblogs.com/developersupport/p/windbgcommand-u.html在调试过程中难免会遇到需要反编译代码来分析逻辑的时候,在windbg中,需要反编译代码就要用到u/ub/uf这三个命令。本文这里分别介绍这三个命令各自的用途。以下是一个quick sort的实例代码,将其编译成可执行文件,然后通过windbg运行。#include <stdio.h>
#include <string.h>

#define MAXLINES 5000
#define MAXLEN 1000
#define ALLOCSIZE 10000

static char allocbuf;
static char *allocp = allocbuf;
char *lineptr;

int readlines(char *lineptr[], int nlines);
void writelines(char *lineptr[], int nlines);

void qsort(void *lineptr[], int left, int right, int(*comp)(void *, void *));
int numcmp(char *, char *);

main(int argc, int *argv[])
{
    int nlines;
    int numeric = 0;

    if((argc > 1) &amp;&amp; strcmp(argv, "-n")==0)
      numeric = 1;
    if((nlines = readlines(lineptr, MAXLINES)) >= 0){
      qsort((void **) lineptr, 0, nlines-1,
                (int (*)(void*, void*))(numeric ? numcmp : strcmp));
      writelines(lineptr, nlines);
      return 0;
    } else {
      printf("input too big to sort\n");
      return 1;
    }
}

void qsort(void *v[], int left, int right,
      int (*comp)(void *, void *))
{
    int i, last;
    void swap(void *v[], int, int);

    if(left >= right)
      return;
    swap(v, left, (left+right)/2);
    last = left;
    for( i = left+1; i <= right; i++)
      if((*comp)(v, v) < 0)
            swap(v, ++last, i);
    swap(v, left, last);
    qsort(v, left, last-1, comp);
    qsort(v, last+1, right, comp);
}

char *alloc(int n)
{
    if(allocbuf + ALLOCSIZE - allocp >= n){
      allocp += n;
      return allocp - n;
    } else
      return 0;
}

int getline(char s[], int lim)
{
    int c, i;
    i = 0;
    while(--lim > 0 &amp;&amp; (c=getchar()) != EOF &amp;&amp; c != '\n')
      s = c;
    if(c == '\n')
      s = c;
    s = '\0';
    return i;
}

int readlines(char *lineptr[], int maxlines)
{
    int len, nlines;
    char *p, line;
    nlines = 0;
    while((len = getline(line, MAXLEN)) > 0)
      if((nlines >= maxlines|| (p = alloc(len)) == NULL))
            return -1;
      else{
            line = '\0';
            strcpy(p, line);
            lineptr = p;
      }
    return nlines;
}

void writelines(char *lineptr[], int nlines)
{
    int i;

    for(i = 0; i < nlines; i++)
      printf("%s\n", lineptr);
}

int numcmp(char *s1, char *s2)
{
    double v1, v2;

    v1 = atof(s1);
    v2 = atof(s2);
    if(v1 < v2)
      return -1;
    else if(v1 > v2)
      return 1;
    else
      return 0;
}

void swap(void *v[], int i, int j)
{
    void *temp;

    temp = v;
    v = v;
    v = temp;
}u命令u命令的作用就是反编译指定地址参数之后的代码,如果不指定地址参数,即只输入u命令执行,那么默认就是反编译当前线程的当前指令。我们来做个实验,在运行起实例代码之后,在main函数上设断点,然后通过u命令来反编译eip(instruction pointer)中的地址指向的方法地址,即当前函数的执行地址,可以查看接下来当前线程要执行的汇编代码。关于x86各个寄存器的含义可以参考x86 Architecture。0:000> x qsort!main000c12e0qsort!main (int, int **)0:000> bp000c12e00:000> gBreakpoint 0 hiteax=004e8228 ebx=00000000 ecx=00000001 edx=00000000 esi=00000000 edi=00000000eip=000c12e0 esp=0027f7d4 ebp=0027f818 iopl=0 nv up ei pl zr na pe nccs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246qsort!main:000c12e0 55 push ebp0:000>u @eipqsort!main :000c12e0 55 push ebp000c12e1 8bec mov ebp,esp000c12e3 83ec0c sub esp,0Ch000c12e6 c745f800000000 mov dword ptr ,0000c12ed 837d0801 cmp dword ptr ,1000c12f1 7e27 jle qsort!main+0x3a (000c131a)000c12f3 6804b00e00 push offset qsort!allocp+0x4 (000eb004)000c12f8 b804000000 mov eax,4uf命令uf命令是用来反编译整个函数的汇编代码,比如我希望反编译整个main函数,可以通过uf函数。0:000>uf @eipqsort!main :19 000c12e0 55 push ebp19 000c12e1 8bec mov ebp,esp19 000c12e3 83ec0c sub esp,0Ch21 000c12e6 c745f800000000 mov dword ptr ,023 000c12ed 837d0801 cmp dword ptr ,123 000c12f1 7e27 jle qsort!main+0x3a (000c131a)qsort!main+0x13 :23 000c12f3 6804b00e00 push offset qsort!allocp+0x4 (000eb004)23 000c12f8 b804000000 mov eax,423 000c12fd c1e000 shl eax,023 000c1300 8b4d0c mov ecx,dword ptr 23 000c1303 8b1401 mov edx,dword ptr 23 000c1306 52 push edx23 000c1307 e854080000 call qsort!strcmp (000c1b60)23 000c130c 83c408 add esp,823 000c130f 85c0 test eax,eax23 000c1311 7507 jne qsort!main+0x3a (000c131a)qsort!main+0x33 :24 000c1313 c745f801000000 mov dword ptr ,1qsort!main+0x3a :25 000c131a 6888130000 push 1388h25 000c131f 68e0020f00 push offset qsort!lineptr (000f02e0)25 000c1324 e8f5fcffff call qsort!ILT+25(_readlines) (000c101e)25 000c1329 83c408 add esp,825 000c132c 8945fc mov dword ptr ,eax25 000c132f 837dfc00 cmp dword ptr ,025 000c1333 7c47 jl qsort!main+0x9c (000c137c)qsort!main+0x55 :27 000c1335 837df800 cmp dword ptr ,027 000c1339 7409 je qsort!main+0x64 (000c1344)qsort!main+0x5b :27 000c133b c745f414100c00 mov dword ptr ,offset qsort!ILT+15(_numcmp) (000c1014)27 000c1342 eb07 jmp qsort!main+0x6b (000c134b)qsort!main+0x64 :27 000c1344 c745f4601b0c00 mov dword ptr ,offset qsort!strcmp (000c1b60)qsort!main+0x6b :27 000c134b 8b45f4 mov eax,dword ptr 27 000c134e 50 push eax27 000c134f 8b4dfc mov ecx,dword ptr 27 000c1352 83e901 sub ecx,127 000c1355 51 push ecx27 000c1356 6a00 push 027 000c1358 68e0020f00 push offset qsort!lineptr (000f02e0)27000c135de8adfcffff call qsort!ILT+10(_qsort) (000c100f)27 000c1362 83c410 add esp,10h28 000c1365 8b55fc mov edx,dword ptr 28 000c1368 52 push edx28 000c1369 68e0020f00 push offset qsort!lineptr (000f02e0)28 000c136e e8bafcffff call qsort!ILT+40(_writelines) (000c102d)28 000c1373 83c408 add esp,829 000c1376 33c0 xor eax,eax29 000c1378 eb14 jmp qsort!main+0xae (000c138e)qsort!main+0x9c :31 000c137c 6808b00e00 push offset qsort!allocp+0x8 (000eb008)31 000c1381 e80c060000 call qsort!printf (000c1992)31 000c1386 83c404 add esp,432 000c1389 b801000000 mov eax,1qsort!main+0xae :34 000c138e 8be5 mov esp,ebp34 000c1390 5d pop ebp34 000c1391 c3 ret另外uf还有一个比较常用的参数项/c,通过/c可以查看这个函数中的函数调用(call)都有哪些,当一个函数反编译代码过长的时候,我们可以通过这个参数来过滤所有的方法调用,方便查找。0:000>uf /c @eipqsort!main (000c12e0) qsort!main+0x27 (000c1307) :call to qsort!strcmp (000c1b60) qsort!main+0x44 (000c1324) :call to qsort!ILT+25(_readlines) (000c101e)qsort!main+0x7d (000c135d) :call to qsort!ILT+10(_qsort) (000c100f)qsort!main+0x8e (000c136e) :call to qsort!ILT+40(_writelines) (000c102d)qsort!main+0xa1 (000c1381) :call to qsort!printf (000c1992) ub命令ub命令与u的不同之处在于它是用来查看线程当前指令之前的汇编代码,b这里就是代表向后查看(backward)的意思。在调用qsort!qsort方法之前设置断点,执行到这个断点的时候,如果希望看到前面执行的代码是什么样的,这时可以通过ub函数查看,通过对比就可以发现ub列出的汇编代码恰好是调用qsort!qsort方法之前的指令。0:000>bp000c135d0:000> gBreakpoint 1 hiteax=000c1b60 ebx=00000000 ecx=00000002 edx=00000000 esi=00000000 edi=00000000eip=000c135d esp=0027f7b4 ebp=0027f7d0 iopl=0 nv up ei pl nz na po nccs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202qsort!main+0x7d:000c135d e8adfcffff call qsort!ILT+10(_qsort) (000c100f)0:000>ub 000c135dqsort!main+0x64 :000c1344 c745f4601b0c00 mov dword ptr ,offset qsort!strcmp (000c1b60)000c134b 8b45f4 mov eax,dword ptr 000c134e 50 push eax000c134f 8b4dfc mov ecx,dword ptr 000c1352 83e901 sub ecx,1000c1355 51 push ecx000c1356 6a00 push 0000c1358 68e0020f00 push offset qsort!lineptr (000f02e0)希望以上内容对您有所帮助Aaron Zhang
页: [1]
查看完整版本: 基础调试命令 - u/ub/uf