看流星社区

 找回密码
 注册账号
查看: 2291|回复: 0

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

[复制链接]

该用户从未签到

发表于 2017-6-2 13:31:49 | 显示全部楼层 |阅读模式
原文: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[ALLOCSIZE];
static char *allocp = allocbuf;
char *lineptr[MAXLINES];

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[1], "-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[i], v[left]) < 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[i++] = c;
    if(c == '\n')
        s[i++] = c;
    s[i] = '\0';
    return i;
}

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

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

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

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[i];
    v[i] = v[j];
    v[j] = 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 [c:\qsort.c @ 19]:000c12e0 55 push ebp000c12e1 8bec mov ebp,esp000c12e3 83ec0c sub esp,0Ch000c12e6 c745f800000000 mov dword ptr [ebp-8],0000c12ed 837d0801 cmp dword ptr [ebp+8],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 [c:\qsort.c @ 19]:19 000c12e0 55 push ebp19 000c12e1 8bec mov ebp,esp19 000c12e3 83ec0c sub esp,0Ch21 000c12e6 c745f800000000 mov dword ptr [ebp-8],023 000c12ed 837d0801 cmp dword ptr [ebp+8],123 000c12f1 7e27 jle qsort!main+0x3a (000c131a)qsort!main+0x13 [c:\qsort.c @ 23]: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 [ebp+0Ch]23 000c1303 8b1401 mov edx,dword ptr [ecx+eax]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 [c:\qsort.c @ 24]:24 000c1313 c745f801000000 mov dword ptr [ebp-8],1qsort!main+0x3a [c:\qsort.c @ 25]: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 [ebp-4],eax25 000c132f 837dfc00 cmp dword ptr [ebp-4],025 000c1333 7c47 jl qsort!main+0x9c (000c137c)qsort!main+0x55 [c:\qsort.c @ 27]:27 000c1335 837df800 cmp dword ptr [ebp-8],027 000c1339 7409 je qsort!main+0x64 (000c1344)qsort!main+0x5b [c:\qsort.c @ 27]:27 000c133b c745f414100c00 mov dword ptr [ebp-0Ch],offset qsort!ILT+15(_numcmp) (000c1014)27 000c1342 eb07 jmp qsort!main+0x6b (000c134b)qsort!main+0x64 [c:\qsort.c @ 27]:27 000c1344 c745f4601b0c00 mov dword ptr [ebp-0Ch],offset qsort!strcmp (000c1b60)qsort!main+0x6b [c:\qsort.c @ 27]:27 000c134b 8b45f4 mov eax,dword ptr [ebp-0Ch]27 000c134e 50 push eax27 000c134f 8b4dfc mov ecx,dword ptr [ebp-4]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 [ebp-4]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 [c:\qsort.c @ 31]: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 [c:\qsort.c @ 34]:34 000c138e 8be5 mov esp,ebp34 000c1390 5d pop ebp34 000c1391 c3 ret另外uf还有一个比较常用的参数项/c,通过/c可以查看这个函数中的函数调用(call)都有哪些,当一个函数反编译代码过长的时候,我们可以通过这个参数来过滤所有的方法调用,方便查找。0:000>uf /c @eipqsort!main (000c12e0) [c:\qsort.c @ 19]qsort!main+0x27 (000c1307) [c:\qsort.c @ 23]:call to qsort!strcmp (000c1b60) [f:\dd\vctools\crt_bld\SELF_X86\crt\src\INTEL\strcmp.asm @ 65]qsort!main+0x44 (000c1324) [c:\qsort.c @ 25]:call to qsort!ILT+25(_readlines) (000c101e)qsort!main+0x7d (000c135d) [c:\qsort.c @ 27]:call to qsort!ILT+10(_qsort) (000c100f)qsort!main+0x8e (000c136e) [c:\qsort.c @ 28]:call to qsort!ILT+40(_writelines) (000c102d)qsort!main+0xa1 (000c1381) [c:\qsort.c @ 31]:call to qsort!printf (000c1992) [f:\dd\vctools\crt_bld\self_x86\crt\src\printf.c @ 49]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 [c:\qsort.c @ 27]:000c1344 c745f4601b0c00 mov dword ptr [ebp-0Ch],offset qsort!strcmp (000c1b60)000c134b 8b45f4 mov eax,dword ptr [ebp-0Ch]000c134e 50 push eax000c134f 8b4dfc mov ecx,dword ptr [ebp-4]000c1352 83e901 sub ecx,1000c1355 51 push ecx000c1356 6a00 push 0000c1358 68e0020f00 push offset qsort!lineptr (000f02e0)希望以上内容对您有所帮助Aaron Zhang
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-4-20 16:12

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表