使用 windbg 检查传递给函数的参数
Inspect Parameter passed to Functions with 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 的一个值。
接下来要做的就是蛊。执行 Kernel32!GetCurrentDirectoryA 直到结束。
此后,我转储了最初使用 dv -v -t 命令获得的 pwdBuffer 值。
0:000> da 0018fe24
0018fe24 "C:\microsoft_press\WSP4_Examples"
0018fe44 "\Utility_4_dll"
这是我对缓冲区的期望。所以我的问题是为什么我没有看到传递给 GetCurrentDirectory 的这个 0018fe24 值?
尝试单步执行 GetCurrentDirectoryA 开头的 mov ebp, esp
指令。您看到的数字看起来像来自 _tmain 函数的值,特别是它的帧指针 (EBP)、它的 return 地址和它的参数 argc 和 argv(以及隐藏的 envp 参数)。一旦 EBP 加载了 GetCurrentDirectoryA 的正确帧指针,windbg 就可以正确显示函数的参数。
堆栈应该显示函数的参数,而不是在你单步之后,我只是有类似的代码(没有 crt window API)和 运行 它通过和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
测试源码
:\>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
-cf 命令行到 windbg/cdb 获取一个文件,其内容将被执行,就像您在提示符下键入它们一样
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 和 运行 二进制
上设置断点
当断点命中时 goup(我们只对这个函数的 return 值感兴趣)并检查 eax(return 函数的值)
清除所有断点
在 GetCurrentDirectoryA
中设置断点
在遇到断点时用 g 再次执行二进制文件检查堆栈
用 dd @esp l3
(显示来自 Stack 指针一 return 地址的三个双字和函数 GetCurrentDirectoryA()
的两个函数参数
请注意,堆栈将包含我们之前在 VirtualAlloc 的 return 使用 ? @eax
将缓冲区的地址保存到一个伪变量中并向上
从缓冲区 da @$t0 打印 ascii 字符串
退出会话
这个会话的结果如下,注意我们从 virtual alloc 中得到了 35000 作为 buffer 的分配内存地址,它确实被传递给了 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 命令添加到脚本文件并执行以显示堆栈跟踪
我正在研究 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 的一个值。
接下来要做的就是蛊。执行 Kernel32!GetCurrentDirectoryA 直到结束。 此后,我转储了最初使用 dv -v -t 命令获得的 pwdBuffer 值。
0:000> da 0018fe24
0018fe24 "C:\microsoft_press\WSP4_Examples"
0018fe44 "\Utility_4_dll"
这是我对缓冲区的期望。所以我的问题是为什么我没有看到传递给 GetCurrentDirectory 的这个 0018fe24 值?
尝试单步执行 GetCurrentDirectoryA 开头的 mov ebp, esp
指令。您看到的数字看起来像来自 _tmain 函数的值,特别是它的帧指针 (EBP)、它的 return 地址和它的参数 argc 和 argv(以及隐藏的 envp 参数)。一旦 EBP 加载了 GetCurrentDirectoryA 的正确帧指针,windbg 就可以正确显示函数的参数。
堆栈应该显示函数的参数,而不是在你单步之后,我只是有类似的代码(没有 crt window API)和 运行 它通过和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
测试源码
:\>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
-cf 命令行到 windbg/cdb 获取一个文件,其内容将被执行,就像您在提示符下键入它们一样
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 和 运行 二进制
上设置断点
当断点命中时 goup(我们只对这个函数的 return 值感兴趣)并检查 eax(return 函数的值)
清除所有断点
在 GetCurrentDirectoryA
中设置断点
在遇到断点时用 g 再次执行二进制文件检查堆栈
用 dd @esp l3
(显示来自 Stack 指针一 return 地址的三个双字和函数 GetCurrentDirectoryA()
的两个函数参数
请注意,堆栈将包含我们之前在 VirtualAlloc 的 return 使用 ? @eax
将缓冲区的地址保存到一个伪变量中并向上
从缓冲区 da @$t0 打印 ascii 字符串
退出会话
这个会话的结果如下,注意我们从 virtual alloc 中得到了 35000 作为 buffer 的分配内存地址,它确实被传递给了 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 命令添加到脚本文件并执行以显示堆栈跟踪