使用windbg检查传递给函数的参数

时间:2015-10-09 22:01:42

标签: windows debugging winapi windbg

我在Windows系统编程第4版中完成了一些示例。使用windbg.exe我正在尝试检查传递给函数的参数(GetCurrentDirectoryA)。以下是来源。

int _tmain (int argc, LPTSTR argv [])
{
    /* Buffer to receive current directory allows for the CR,
        LF at the end of the longest possible path. */

    TCHAR pwdBuffer [DIRNAME_LEN];
    DWORD lenCurDir;
    lenCurDir = GetCurrentDirectory (DIRNAME_LEN, pwdBuffer);
    if (lenCurDir == 0)
        ReportError (_T ("Failure getting pathname."), 1, TRUE);
    if (lenCurDir > DIRNAME_LEN)
        ReportError (_T ("Pathname is too long."), 2, FALSE);

    PrintMsg (GetStdHandle (STD_OUTPUT_HANDLE), pwdBuffer);
    return 0;
}

首先,我使用dv -t -v转储局部变量。在这种情况下,我对pwdBuffer感兴趣。

0018ff3c          int argc = 0n1
0018ff40          char ** argv = 0x00582470
0018fe18          unsigned long lenCurDir = 0x775b994a
0018fe24          char [262] pwdBuffer = char [262] ""

然后我在Kernel32设置一个断点!GetCurrentDirectoryA。产生以下结果。

00 0018ff34 00428759 00000001 00582470 005824c0 kernel32!GetCurrentDirectoryA

我不明白的是函数参数的值。我期待看到0018fe24作为代表pwdbuffer的一个值。

我接下来要做的就是gu。哪个执行Kernel32!GetCurrentDirectoryA到它的结尾。 此后,我使用dv -v -t命令转储了我最初获得的pwdBuffer值。

0:000> da 0018fe24          
0018fe24  "C:\microsoft_press\WSP4_Examples"
0018fe44  "\Utility_4_dll"

这是我对缓冲区的期望。所以我的问题是为什么我没有看到这个0018fe24值传递给GetCurrentDirectory?

2 个答案:

答案 0 :(得分:3)

尝试单步执行GetCurrentDirectoryA开头的mov ebp, esp指令。您看到的数字看起来像_tmain函数中的值,特别是它的帧指针(EBP),它的返回地址,以及它的参数argc和argv(以及隐藏的envp参数)。一旦EBP加载了GetCurrentDirectoryA的正确帧指针,windbg就可以正确显示函数的参数。

答案 1 :(得分:1)

堆栈应该在点击断点时显示函数的参数,而不是单步后我只有类似的代码(没有crt窗口仅限Apis)并运行它并且windbg按预期工作 在分析未知或潜在的恶意软件二进制文件时,一个无意义的单一步骤可能导致致命的感染。如果存在逻辑,请不要使用幸运符。

我当前的目录

:\>echo %cd%
C:\temp\temp\temp\temp

当前目录的内容

:\>ls -l
total 12
-rwxrwxrwx  1 Admin 0 197 2015-10-10 16:29 compile.bat
-rw-rw-rw-  1 Admin 0 336 2015-10-10 16:13 getdir.cpp
-rw-rw-rw-  1 Admin 0 145 2015-10-10 16:47 wtf.txt

测试的src代码

:\>type getdir.cpp
#include <windows.h>
int main (void) {
  PCHAR buff=0;int bufflen=0;
  bufflen=GetCurrentDirectory(0,NULL);
  buff = (PCHAR)VirtualAlloc(NULL,bufflen,MEM_COMMIT,PAGE_READWRITE);
  if(buff){
    GetCurrentDirectory(bufflen,buff);
    MessageBox(NULL,buff,"Current Directory",MB_OK);
    VirtualFree(buff,0,MEM_RELEASE);
   }
}

编译
:\>type compile.bat
@call "C:\Program Files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86
cl /Zi /EHsc /O2 /nologo /W4 /analyze *.cpp /link /SUBSYSTEM:Windows /RELEASE /E
NTRY:main user32.lib kernel32.lib
pause
:\>compile.bat
Setting environment for using Microsoft Visual Studio 2010 x86 tools.
getdir.cpp
Press any key to continue . . .

执行
:\>cdb -cf wtf.txt getdir.exe

指向windbg / cdb的-cf命令行将获取一个文件,其内容将被执行,就像您在提示符下键入它们一样

wtf.txt的内容是

:\>type wtf.txt
bp kernel32!VirtualAlloc
g
gu
? @eax
bc *
bp kernel32!GetCurrentDirectoryA
g
dd @esp l3
r $t0 = poi(@esp+8)
? @$t0
gu
da @$t0;
g
q
第一次系统休息时

在virtualalloc上设置一个断点并运行二进制文件 当断点被点击时(我们只对这个函数的返回值感兴趣)并检查eax(从函数返回值)
清除所有断点
在GetCurrentDirectoryA中设置断点 在点击断点时用g再次执行二进制文件检查堆栈 与dd @esp l3
(在堆栈指针中显示三个双字,一个返回地址和两个函数参数到函数GetCurrentDirectoryA()
请注意,堆栈将包含我们之前在VirtualAlloc返回时使用的相同地址? @eax 将缓冲区的地址保存到伪变量并上升 从缓冲区da @ $ t0打印ascii字符串 退出会议

这个会话的结果如下:注意我们从虚拟alloc获得35000作为缓冲区的已分配内存地址,并确实传递给GetCurrentDirectory并保存字符串Current directory

:\>cdb -cf wtf.txt getdir.exe

0:000> bp kernel32!VirtualAlloc
0:000> g

Breakpoint 0 hit

kernel32!VirtualAlloc:
7c809af1 8bff            mov     edi,edi
0:000> gu

getdir!main+0x21:
00401021 8bf0            mov     esi,eax
0:000> ? @eax
Evaluate expression: 3473408 = 00350000 <--------
0:000> bc *
0:000> bp kernel32!GetCurrentDirectoryA
0:000> g
Breakpoint 0 hit

kernel32!GetCurrentDirectoryA:
7c83502e 8bff            mov     edi,edi
0:000> dd @esp l3
0013ffac  0040102b 00000017 00350000 <------
0:000> r $t0 = poi(@esp+8)
0:000> ? @$t0
Evaluate expression: 3473408 = 00350000 <----------
0:000> gu

getdir!main+0x2b:
0040102b 6a00            push    0
0:000> da @$t0;
00350000  "C:\temp\temp\temp\temp"
0:000> g

编辑所有其他相同的只是将一个kb命令添加到脚本文件并执行以显示堆栈跟踪

enter image description here