我在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?
答案 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命令添加到脚本文件并执行以显示堆栈跟踪