Win7下的计算器,程序员模式下默认是十进制,如下图所示,然而由于我平常使用16进制较多,所以就想改改这个计算器,使它默认为16进制
看雪上有两篇关于修改计算器的文章(在Reference里),不过都是XP下的,到Win7下不太一样了,那我们就来看看怎么样修改这个计算器
由于calc.exe是Windows自带的程序,所以它的调试符号pdb文件是可以在微软的符号服务器上下到的
在网上下载一个symsrv.dll和dbghelp.dll一起放到OD的目录下,然后把OD->Debug->Select path to symbols改一下,如果安装了SOD,ollydbg.ini里SOD配置下把LoadSym改成1,这样OD就可以自动加载calc.exe的符号了,第一次加载特别卡,加载完了以后可以关掉OD然后把SOD里的LoadSym改回0,之后再打开Symbol也是在的
OEP处下来有个循环
00CC2E3D > /8975 E0 MOV DWORD PTR SS:[EBP-0x20], ESI
00CC2E40 . |8A06 MOV AL, BYTE PTR DS:[ESI]
00CC2E42 . |3C 20 CMP AL, 0x20
00CC2E44 . |0F86 C6000000 JBE calc.00CC2F10
00CC2E4A > |3C 22 CMP AL, 0x22
00CC2E4C . |0F84 784E0000 JE calc.00CC7CCA
00CC2E52 > |0FB6C0 MOVZX EAX, AL
00CC2E55 . |50 PUSH EAX ; /c
00CC2E56 . |FF15 6815CB00 CALL DWORD PTR DS:[<&msvcrt._ismbblead>] ; \_ismbblead
00CC2E5C . |59 POP ECX
00CC2E5D . |85C0 TEST EAX, EAX
00CC2E5F . |0F85 DFAF0100 JNZ calc.00CDDE44
00CC2E65 > |46 INC ESI
00CC2E66 .^\EB D5 JMP SHORT calc.00CC2E3D
可以把这3个跳转到的地址都下断点,然后F9运行,前两次F9都是跑两条语句就又回循环了,第三次我们会来到下面这里
00CC2189 . 6A 0A PUSH 0xA
00CC218B . 58 POP EAX
00CC218C > 50 PUSH EAX
00CC218D . 56 PUSH ESI
00CC218E . 6A 00 PUSH 0x0
00CC2190 . 68 0000CB00 PUSH calc.00CB0000
00CC2195 . E8 9BF4FEFF CALL calc.WinMain
步入WinMain,下面不远处有一行
00CB1B09 . E8 B8990000 CALL calc.CContainer::AssembleDialogsWithoutToolset
步入,看到
00CBB569 . E8 7B090100 CALL calc.CContainer::LayoutProgrammerMode ; Case 2 of switch 00CBB54F
步入,看到
00CCBFAD |. E8 E7030000 CALL calc.CProgrammerMode::SetProgrammerModeButtons
这个函数就非常一目了然了
00CCC399 >/$ 8BFF MOV EDI, EDI
00CCC39B |. 56 PUSH ESI
00CCC39C |. 57 PUSH EDI
00CCC39D |. 6A 00 PUSH 0x0
00CCC39F |. FF35 4C40D000 PUSH DWORD PTR DS:[CContainer::m_iNumberBase]
00CCC3A5 |. BF 11010000 MOV EDI, 0x111
00CCC3AA |. BE 1042D000 MOV ESI, OFFSET calc.container
00CCC3AF |. 57 PUSH EDI
00CCC3B0 |. 8BCE MOV ECX, ESI
00CCC3B2 |. E8 7287FEFF CALL calc.CContainer::ProcessKeyPadInputs
00CCC3B7 |. 6A 00 PUSH 0x0
00CCC3B9 |. FF35 4840D000 PUSH DWORD PTR DS:[CContainer::m_iWordLength]
00CCC3BF |. 8BCE MOV ECX, ESI
00CCC3C1 |. 57 PUSH EDI
00CCC3C2 |. E8 6287FEFF CALL calc.CContainer::ProcessKeyPadInputs
00CCC3C7 |. 5F POP EDI
00CCC3C8 |. 5E POP ESI
00CCC3C9 \. C3 RETN
只要改掉这里的 CContainer::m_iNumberBase,计算器就可以默认16进制了
不过注意这个 CContainer::m_iNumberBase 里存的值是 13A,而不是我们想的 0A,这是因为这里面存的其实是默认进制的按钮对应的ID
在OD里点击工具栏上的W查看所有窗口,如下
这里就会发现13A对应的正是10进制,要改成16进制就要把这个值改成139
保存以后就大功告成了,从此以后计算器的Programmer Mode就是默认16进制了!
这里要说一下,其实我自己在分析的时候不是用OD动态调试的,而是IDA配合OD,把calc.exe用IDA打开以后,因为进制的英文是radix,而且有pdb文件,所以我直接搜索了radix,直接就定位到了修改进制的函数,然后在OD里下断看堆栈确定每层的函数调用才有了上面的分析
Reference: