最近买了台新机器,装上了VS2008,ACAD2009,另外下载了一个ObjectARX2008.准备在家有空也可以玩玩ARX,哈哈。
好了,回到正题,这里记录下一些关键步骤。
这里以SDK中的ARXDBG为例。
首先,编译刚开始肯定能过的。但必然不能被CAD加载,因为连接的库版本不对。
在工具设置中添加mfc80u.lib和mfcs80u.lib,忽略对应90的库。这2个文件可以从装过VS2005的朋友那获得:)。相当感谢给我这个库的朋友,嘿嘿。其实如果有mfc80u.def应该也能产生出对应的lib.但有mfc80u.dll却不行,原因是它是由序号导出的,而非名字,之前的blog文也有提到。相信没有人会不想用名字,而用#XXX数字来做开发。所以库相当重要,找到这些库再继续。
这里编译,会发现报错了。着实搞了我好久,出了三个Link Error.开始一直以为是库的问题,其实是头文件。2008中CWND类多了GetMenu和SetMenu这2个虚函数- -b,所以删除这2行,保存到SDK的INC下,同名文件(这样的好处是不影响新的VS自己的.h文件。还有一个错类似,是Cfiledialog的,多了一个默认参数。处理方法相同。这样,编译就没有问题了。
接下来是加载。我试了半天,用Appload,失败,但拖放,可以加载成功,会有提示说和CAD不兼容。。。。但加载以后运行,未发现任何问题。
由于之前调试过ARX的加载模块,所以今天想一试,看下到底哪里有问题。参考之前的blog设置断点。APPLOAD.arx会调用acdb17.dll::loadmoudle()方法来加载ARX。中间有很多CALL,发现最外面出问题的CALL是
631FEEA4 . E8 E7CD0600 CALL acdb17.6326BC90
返回值不正确,跟进去。
6326BCEE . E8 3C09F9FF CALL acdb17.631FC62F
6326BCF3 . 85C0 TEST EAX,EAX
返回值不对,跟进
631FC96B . E8 C022FEFF CALL acdb17.631DEC30
631FC970 . 84C0 TEST AL,AL ; 这里问题
返回值不对,跟进
631DEC3C . 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
631DEC3F . E8 CCFFFFFF CALL acdb17.631DEC10 //返回不对
631DEC44 3C 08 CMP AL,8
跟进。。。
631DEC10 $ 8B48 10 MOV ECX,DWORD PTR DS:[EAX+10]
631DEC13 . 85C9 TEST ECX,ECX
631DEC15 . 74 0E JE SHORT acdb17.631DEC25
631DEC17 . 8078 05 00 CMP BYTE PTR DS:[EAX+5],0
631DEC1B . 0F84 34CC4000 JE acdb17.635EB855
631DEC21 . 8A41 02 MOV AL,BYTE PTR DS:[ECX+2]//数值不对。。。09,应该08可以加载。数字代表撒?需要倒过来查,从ECX的出处
631DEC24 . C3 RETN
631DEC25 > 32C0 XOR AL,AL
631DEC27 . C3 RETN
ECX通过EAX来,然后跟到外面查EAX从EBP+8来,再跟到外面
631FC968 . FF75 E8 PUSH DWORD PTR SS:[EBP-18]
631FC96B . E8 C022FEFF CALL acdb17.631DEC30
631FC970 . 84C0 TEST AL,AL ; 这里问题
数字就是从DWORD PTR SS:[EBP-18]来的,再往前找。(硬件断点)
631FC7DB . E8 60D2FEFF CALL acdb17.631E9A40
631FC7E0 > 834D FC FF OR DWORD PTR SS:[EBP-4],FFFFFFFF
631FC7E4 . 897D D8 MOV DWORD PTR SS:[EBP-28],EDI
631FC7E7 > 3BFB CMP EDI,EBX
631FC7E9 . 0F84 13354000 JE acdb17.635FFD02
631FC7EF . 8B47 04 MOV EAX,DWORD PTR DS:[EDI+4]
631FC7F2 > 3BC3 CMP EAX,EBX
631FC7F4 . 8945 E8 MOV DWORD PTR SS:[EBP-18],EAX//这里设置值,而EAX值从EDI来,EDI+4的内容在上面的CALL里赋值。
调试发现EAX其实只是一个指针,关键要查它对应内存里面的数值是何时赋值的。
同样硬件断点,发现EAX其实是一个new出来的内存。
631E9B1C > /6A 34 PUSH 34
631E9B1E . |E8 91930C00 CALL <JMP.&MSVCR80.??2@YAPAXI@Z> //new函数,乱码我也不懂。。。用VS带的undname工具。
631E9B23 . |3BC3 CMP EAX,EBX
631E9B25 . |59 POP ECX
631E9B26 . |74 19 JE SHORT acdb17.631E9B41
631E9B28 . |8BF0 MOV ESI,EAX
631E9B2A . |8B47 10 MOV EAX,DWORD PTR DS:[EDI+10]
631E9B2D . |885E 04 MOV BYTE PTR DS:[ESI+4],BL
631E9B30 . |8946 08 MOV DWORD PTR DS:[ESI+8],EAX
631E9B33 . |E8 98370100 CALL acdb17.631FD2D0 ; 这里面把数据放入New出来的内存+10处
跟到里面看看
631FD341 . 8B46 18 MOV EAX,DWORD PTR DS:[ESI+18]
631FD344 . 83C0 18 ADD EAX,18
631FD347 . 8946 10 MOV DWORD PTR DS:[ESI+10],EAX//EAX为数值。出处是ESI,继续找。
后面不再列了。查看内存,直接可以发现631FD341 . 8B46 18 MOV EAX,DWORD PTR DS:[ESI+18]这行,对应的是“PE”这个字符串,结合前面观察结果,可以断定,这里是一段读取PE文件头的操作。而从PE处开始往后0x18个字节。查看文件头定义,Ollydbg也有这功能。
结果如下:
10000118 50 45 00 00>ASCII "PE" ; PE signature (PE)
1000011C 4C01 DW 014C ; Machine = IMAGE_FILE_MACHINE_I386
1000011E 0500 DW 0005 ; NumberOfSections = 5
10000120 35878048 DD 48808735 ; TimeDateStamp = 48808735
10000124 00000000 DD 00000000 ; PointerToSymbolTable = 0
10000128 00000000 DD 00000000 ; NumberOfSymbols = 0
1000012C E000 DW 00E0 ; SizeOfOptionalHeader = E0 (224.)
1000012E 0221 DW 2102 ; Characteristics = DLL|EXECUTABLE_IMAGE|32BIT_MACHINE
10000130 0B01 DW 010B ; MagicNumber = PE32
10000132 09 DB 09 ; MajorLinkerVersion = 9 //就是这里,这个9就是从这里拿来的。还不明显吗,VS2008文件夹叫Microsoft Visual Studio 9.0 ,链接器的版本号。
10000133 00 DB 00 ; MinorLinkerVersion = 0
综上所述,决定修改ACDB17.dll,去掉那讨厌的警告:)。回到下面
631DEC3C . 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
631DEC3F . E8 CCFFFFFF CALL acdb17.631DEC10 //返回不对
631DEC44 3C 08 CMP AL,8 // 可以把这里改成CMP AL,9?发现CAD自己的库不行了,所以改XOR al,al,正好2个字节机器码为0x32C0
尝试加载,成功,不再报警告了。
http://blog.sina.com.cn/s/blog_41299a970100mg04.html