默认用MASM表达式
最大的区别:
在MSAM表达式中,所有符号都被当作地址对待,C++表达式和真实的C++代码中一样,符号被当作适当的数据类型
有这样的规律:
MASM的符号值X,取它的指针大小的数据(poi(X)),刚好为C++的符号值Y,即poi(X) ==Y
比如char* g_char = "i am windbg":
0:000> ? g_char Evaluate expression: 15560768 = 00ed7040 0:000> .expr /s c++ // 切换到c++ Current expression evaluator: C++ - C++ source expressions 0:000> ? g_char Evaluate expression: 15554364 = 00ed573c 0:000> .expr /s masm Current expression evaluator: MASM - Microsoft Assembler expressions 0:000> dd 00ed7040 L1 00ed7040 00ed573c可以发现,MASM求得的g_char值,它的指针大小的数据,刚好就是C++求得的值
除了下面几种例外情况,所有命令和调试器信息窗口都通过默认表达式来解释他们的参数:
也就是有:
0:000> ? poi(g_char) Evaluate expression: 15554364 = 00ed573c
0:000> ? g_int Evaluate expression: 17330244 = 01087044 0:000> .expr /s c++ Current expression evaluator: C++ - C++ source expressions 0:000> ? g_int Evaluate expression: 12 = 0000000c这个就看得很清楚了,c++就表示数值,而MASM表示它地址,而如果g_int是个int指针,则masm要使用poi(poi(g_int)),c++使用*g_int
0:000> ? g_ClientLibraryOffset Evaluate expression: 8602736 = 00834470 0:000> dd 00834470 00834470 00000104 00000000 00000000 00000000 00834480 00000000 00000000 00000000 00000000 00834490 00000000 00000000 00000000 00000000 008344a0 00000000 00000000 00000000 00000000 008344b0 00000000 00000000 00000000 00000000 008344c0 00000000 00000000 00000000 00000000 008344d0 007772fc 008344d0 00000000 00000000 008344e0 0000001a 00000000 00000000 00000000 0:000> dd g_ClientLibraryOffset 00834470 00000104 00000000 00000000 00000000可以看到00834470就是g_ClientLibraryOffset的地址
一元地址运算符寻址时假定 DS 为缺省段。按运算符的优先级顺序计算表达式
+ | 正数 |
:
0:000> ? +1 Evaluate expression: 1 = 00000001 0:000> ? +eip Evaluate expression: 2838334 = 002b4f3e
- | 负数 |
0:000> ? -1 Evaluate expression: -1 = ffffffff 0:000> ? -eip Evaluate expression: -2838334 = ffd4b0c2
not | 如果参数为零返回 1;任何非零参数返回 0 |
0:000> ? not 1 Evaluate expression: 0 = 00000000 0:000> ? not 0 Evaluate expression: 1 = 00000001 0:000> ? not eip Evaluate expression: 0 = 00000000
hi | 高 16 位 |
0:000> ? hi eip Evaluate expression: 43 = 0000002b 0:000> r eip eip=002b4f3e 0:000> ? hi (eip) Evaluate expression: 43 = 0000002b
low | 低 16 位 |
0:000> ? low eip Evaluate expression: 20286 = 00004f3e 0:000> r eip eip=002b4f3e 0:000> ? (low eip) Evaluate expression: 20286 = 00004f3e
by | 指定地址处的低位字节--地址所对应内容的低位字节! |
:
0:000> ? by ebp Evaluate expression: 76 = 0000004c 0:000> r ebp ebp=00affad8 0:000> dd ebp 00affad8 00affc4c 002d7d94 00affe5c 00affc54
wo | 指定地址处的内容的低位字!不是字节 |
0:000> ? wo(eip) Evaluate expression: 15747 = 00003d83 0:000> dd eip 002b4f3e 44743d83
dwo | 指定地址处的内容的双字 |
0:000> ?dwo eip Evaluate expression: 1148468611 = 44743d83 0:000> dd eip 002b4f3e 44743d83 74000083 ebc03304 30a1643b
qwo | 指定地址处的内容的四字节 |
0:000> ? qwo eip Evaluate expression: 8358681472188824963 = 74000083`44743d83 0:000> dd eip 002b4f3e 44743d83 74000083 ebc03304 30a1643b
poi | 指定地址处的指针大小的数据。指针大小或者是 32 位或者是 64 位 |
<pre name="code" class="cpp">0:000> ? poi(eip) Evaluate expression: 1148468611 = 44743d83 0:000> dd eip 002b4f3e 44743d83 74000083 ebc03304 30a1643b
* / mod (或 %) | 乘法整数除法模数(余数) |
0:000> ? 4*2 Evaluate expression: 8 = 00000008 0:000> ? eip*2 Evaluate expression: 5676668 = 00569e7c 0:000> ? 4/2 Evaluate expression: 2 = 00000002 0:000> ? eip/2 Evaluate expression: 1419167 = 0015a79f 0:000> ? 5 mod 1 Evaluate expression: 0 = 00000000 0:000> ? 5mod1 Syntax error at '5mod1' 0:000> ? eip mod 2 Evaluate expression: 0 = 00000000 0:000> ? 5 mod 2 Evaluate expression: 1 = 00000001
注意mod要前后隔开
+ - |
加法 减法 |
0:000> ? 1+2 Evaluate expression: 3 = 00000003 0:000> ? 2+eip Evaluate expression: 2838336 = 002b4f40
<< >> >>> |
左移位 逻辑右移位 算术右移位 |
0:000> ? 4>>1 Evaluate expression: 2 = 00000002 0:000> ? 4<<1 Evaluate expression: 8 = 00000008 0:000> ? 4>>>1 Evaluate expression: 2 = 00000002 0:000> ? 4 << 1 Evaluate expression: 8 = 00000008
千万不要犯2:
0:000> ? 1<<10 Evaluate expression: 65536 = 00010000 0:000> ? 1<<a Evaluate expression: 1024 = 00000400注意到了吧,都是16进制的,所以10是表示左移16
= (or ==) < > <= >= != |
等于 小于 大于 小于等于 大于等于 不等于 |
0:000> ? 4>1 Evaluate expression: 1 = 00000001 0:000> ? 4<1 Evaluate expression: 0 = 00000000比较运算符 <, >, =, == 和 != 计算后如果为真则得到 1,如果为假则得到 0。单个等于号( =)和双等于号( ==)相同;在 MASM 表达式中不会产生副作用,也不会赋值
0:000> ? eip Evaluate expression: 2838334 = 002b4f3e 0:000> ? eip = 1 Evaluate expression: 0 = 00000000 0:000> r eip eip=002b4f3e
非法操作(例如除零)会返回给调试器命令窗口调试器命令窗口一个"Operand error"
0:000> ? 1/0 Operand error at '0'
and (或&) | 按位与 |
xor (或^) | 按位异或(不同于 OR) |
or (或|) | 按位或 |
异或是不同为1,相同为0
0:000> ? 5&1 Evaluate expression: 1 = 00000001 0:000> ? 5 xor 1 Evaluate expression: 4 = 00000004 0:000> ? 5 or 2 Evaluate expression: 7 = 00000007
$iment (Address) | 返回加载模块列表中映像入口点地址。Address 指定 PE 映像基地址。通过查找 Address 指定映像的 PE 头中的映像入口点找到入口点。 该函数既可以用在模块列表中已有的模块上,也可以通过bu命令设置未确定的断点 |
方使用从入口点跟进代码:
如:
0:000> lm start end module name 00030000 0089f000 VerifyTxSignDemo则可以用[00030000, 0089f000)中任一个地址取得:
0:000> r $exentry $exentry=0029cf7c 0:000> ? $iment(00030000+100) Evaluate expression: 2740092 = 0029cf7c那么下断点也很好:
0:000> bu $iment(00030000)
$scmp("String1", "String2") | 计算后得到 -1、0 或者 1;就像 C 函数中的 strcmp。 |
0:000> ? $scmp("c:", "c:") Evaluate expression: 0 = 00000000 0:000> ? $scmp("c:", "d:") Evaluate expression: -1 = ffffffff 0:000> ? $scmp("e:", "d:") Evaluate expression: 1 = 00000001
要让求值器按字面意思莱解释字符串,必须使用@"String" 语法
0:000> ? $scmp("c:\", "c:\") Syntax error at '("c:\", "c:\")' 0:000> ? $scmp(@"c:\", @"c:\") Evaluate expression: 0 = 00000000 0:000> ? $scmp(@"c:\", @"d:\") Evaluate expression: -1 = ffffffff
可以看到第一个报错
0:006> ? $scmp(@"c:\",@"C:\") Evaluate expression: 1 = 00000001 0:006> ? $sicmp(@"c:\",@"C:\") Evaluate expression: 0 = 00000000
$sicmp("String1", "String2") | 计算后得到 -1、0 或者 1;就像 Win32 函数 stricmp |
同于上面的,不多解释
0:000> ? $sicmp(@"C:\", @"c:\") Evaluate expression: 0 = 00000000
$spat("String", "Pattern") | 根据 String 是否匹配 Pattern 计算得到 TRUE 或 FALSE。Pattern 可以包含多种通配符和特定符(specifiers); |
0:000> ? $spat(@"c:\1.txt", "*.txt") Evaluate expression: 1 = 00000001 0:000> ? $spat(@"c:\1.txt", "*.tet") Evaluate expression: 0 = 00000000
$vvalid(Address, Length) | 判断一段起始地址为 Address 长度为 Length字节的内存范围是否有效。如果这段内存有效,$vvalid计算得到 1;否则,$vvalid 计算得到 0 |
0:000> ? $vvalid(0089e000, 1000) Evaluate expression: 1 = 00000001 0:000> ? $vvalid(0089e000, 1001) Evaluate expression: 0 = 00000000原因:
0:000> !vprot 0089efff BaseAddress: 0089e000 AllocationBase: 00030000 AllocationProtect: 00000080 PAGE_EXECUTE_WRITECOPY RegionSize: 00001000 State: 00001000 MEM_COMMIT Protect: 00000002 PAGE_READONLY Type: 01000000 MEM_IMAGE 0:000> !vprot 0089f000 BaseAddress: 0089f000 AllocationBase: 00000000 RegionSize: 00001000 State: 00010000 MEM_FREE Protect: 00000001 PAGE_NOACCESS一个是可读可写的,一个是不可访问的
如果你使用 C++ 表达式语法,这个 @ 前缀总是必需的。