话说我在 新人交流投稿发不了帖,提示没有权限,所以发到求助问答区。
无意中发现用GodUp 导入Map文件以后找不到我代码中的一些变量的符号,于是反汇编了一下GodUp的相关代码,发现作者处理Map文件好像确实存在一些问题,我搜了一下论坛,貌似没有发现之前有人提到这个问题,于是发上来请大家验证一下。
首先来看GodUp的代码:
CODE:004C2031 mov fs:[eax], esp
CODE:004C2034 mov eax, 4
CODE:004C2039 call System::__linkproc__ GetMem(int)
CODE:004C203E mov [ebp+pbase], eax
CODE:004C2041 mov eax, 4
CODE:004C2046 call System::__linkproc__ GetMem(int)
CODE:004C204B mov [ebp+psize], eax
CODE:004C204E push 25 ; VAL_PROCESSNAME
CODE:004C2050 call _Plugingetvalue
CODE:004C2055 pop ecx
CODE:004C2056 mov [ebp+modulename], eax
CODE:004C2059 lea eax, [ebp+modulename_]
CODE:004C205F mov edx, [ebp+modulename]
CODE:004C2062 call System::__linkproc__ LStrFromPChar(System::AnsiString &,char *) ; BDS 2005-2007 and Delphi6-7 Visual Component Library
CODE:004C2067 mov eax, [ebp+modulename_]
CODE:004C206D call getlength
CODE:004C2072 test eax, eax
CODE:004C2074 jnz short havemodule
CODE:004C2076 push offset dword_4C24E8
CODE:004C207B push offset aMapconvErrorKA ; "MapConv ERROR: 没有要添加 map 信息的程?...
CODE:004C2080 push 1
CODE:004C2082 push 0
CODE:004C2084 call _Addtolist
CODE:004C2089 add esp, 10h
CODE:004C208C mov eax, offset aCUUSK_map ; "哦- 如果你没调试任何程序的话 - 你不需要"...
CODE:004C2091 call showAbut
CODE:004C2096 jmp loc_4C24AC
上面这一段,先取得当前调试进程的名字,如果没有程序被调试,则给出提示。
CODE:004C209B ; ---------------------------------------------------------------------------
CODE:004C209B
CODE:004C209B havemodule: ; CODE XREF: addLable_proc+64j
CODE:004C209B mov esi, offset a_ ; ".\\"
CODE:004C20A0 lea edi, [ebp+path]
CODE:004C20A6 mov ecx, 40h
CODE:004C20AB rep movsd
CODE:004C20AD push 0
CODE:004C20AF push offset a_map ; ".map"
CODE:004C20B4 lea eax, [ebp+path]
CODE:004C20BA push eax
CODE:004C20BB push offset aB_map ; "选择.map 文件 "
CODE:004C20C0 call _Browsefilename
CODE:004C20C5 add esp, 10h
CODE:004C20C8 lea eax, [ebp+pathcopy]
CODE:004C20CE lea edx, [ebp+path]
CODE:004C20D4 mov ecx, 100h
CODE:004C20D9 call System::__linkproc__ LStrFromArray(System::AnsiString &,char *,int) ; BDS 2005-2007 and Delphi6-7 Visual Component Library
CODE:004C20DE mov eax, [ebp+pathcopy]
CODE:004C20E4 mov edx, offset _str____0.Text
CODE:004C20E9 call System::__linkproc__ LStrCmp(void)
CODE:004C20EE jz loc_4C24AC
CODE:004C20F4 mov eax, ds:dword_4C5E08
CODE:004C20F9 push eax ; hWnd
CODE:004C20FA call UpdateWindow
CODE:004C20FF mov eax, [ebp+psize]
CODE:004C2102 push eax
CODE:004C2103 mov eax, [ebp+pbase]
CODE:004C2106 push eax
CODE:004C2107 call _Getdisassemblerrange ; 取得显示在当前反汇编窗口中内存块区域地址
CODE:004C210C add esp, 8
注意这里,取得当前反汇编中内存块区域的地址,注意这个地址就是你把CPU窗口拉到最上面显示的地址,对于一个模块来说,这一般是代码段的起始VA。也就是说如果当前模块不是MAP文件对应模块,那么标签就会导入到错误的模块里,请记住这个地址,这个地址为后面的错误埋下了伏笔。
……
……
省略了一些代码
CODE:004C2237 loop2: ; CODE XREF: addLable_proc+3D3j
CODE:004C2237 lea edx, [ebp+buf1]
CODE:004C223A lea eax, [ebp+aHandleMaybe]
CODE:004C2240 call System::__linkproc__ ReadLString(System::TTextRec &,System::AnsiString &)
CODE:004C2245 lea eax, [ebp+aHandleMaybe]
CODE:004C224B call System::__linkproc__ ReadLn(System::TTextRec &)
以上读取MAP文件的一行
……
……
省略一些代码,就是检测当前行是否有标签信息
……
……
注意这里……
CODE:004C22FD 提取地址
CODE:004C22FD lea eax, [ebp+catsouce2]
CODE:004C2303 push eax ; dst
CODE:004C2304 mov ecx, 8 ; 要复制的长度
CODE:004C2309 mov edx, 7 ; 起始位置
CODE:004C230E mov eax, [ebp+buf1] ; src
CODE:004C2311 call System::__linkproc__ LStrCopy(void) ; return [ESP+4]
CODE:004C2316 mov ecx, [ebp+catsouce2] ; src2
CODE:004C231C lea eax, [ebp+catdest] ; dst
CODE:004C231F mov edx, offset catsouce1.Text ; src1
CODE:004C2324 call System::__linkproc__ LStrCat3(void)
CODE:004C2329 mov eax, [ebp+catdest]
CODE:004C232C call Sysutils::StrToInt(System::AnsiString)
CODE:004C2331 提取标签名
CODE:004C2331 mov [ebp+intaddr], eax
CODE:004C2334 lea eax, [ebp+name_22]
CODE:004C2337 push eax ; dst
CODE:004C2338 mov eax, [ebp+buf1]
CODE:004C233B call getlength
CODE:004C2340 mov ecx, eax
CODE:004C2342 sub ecx, 15h ; 要复制的长度
CODE:004C2345 mov edx, 16h ; 起始位置
CODE:004C234A mov eax, [ebp+buf1] ; src
CODE:004C234D call System::__linkproc__ LStrCopy(void)
CODE:004C2352 cmp [ebp+lableorCommit], 0
判断是标签还是注释
CODE:004C2356 jnz short someNozero
CODE:004C2358 mov eax, [ebp+name_22]
CODE:004C235B call System::__linkproc__ LStrToPChar(System::AnsiString)
CODE:004C2360 push eax ; name
CODE:004C2361 push 31h ; type NM_LABEL
CODE:004C2363 mov eax, [ebp+pbase]
CODE:004C2366 mov eax, [eax]
CODE:004C2368 add eax, [ebp+intaddr]
CODE:004C236B push eax ; addr
CODE:004C236C call _Quickinsertname
CODE:004C2371 add esp, 0Ch
CODE:004C2374 jmp short afterinsert1
CODE:004C2376 ; ---------------------------------------------------------------------------
CODE:004C2376
CODE:004C2376 someNozero: ; CODE XREF: addLable_proc+346j
CODE:004C2376 mov eax, [ebp+name_22]
CODE:004C2379 call System::__linkproc__ LStrToPChar(System::AnsiString)
CODE:004C237E push eax
CODE:004C237F push 36h
CODE:004C2381 mov eax, [ebp+pbase]
CODE:004C2384 mov eax, [eax]
CODE:004C2386 add eax, [ebp+intaddr]
CODE:004C2389 push eax
CODE:004C238A call _Quickinsertname
CODE:004C238F add esp, 0Ch
CODE:004C2392
CODE:004C23ED call _Mergequicknames
……
……
以下显示成功信息
……
……
我们来总结一下,以下是一个MAP文件的示例
ConsoleApplication1
Timestamp is 515692f6 (Sat Mar 30 15:23:34 2013)
Preferred load address is 00400000
Start Length Name Class
0001:00000000 00010000H .textbss DATA
0002:00000000 00003b8fH .text CODE
0003:00000820 00000f0eH .rdata DATA
0003:00002099 00000000H .edata DATA
0004:00000000 00000158H .data DATA
0004:00000158 00000449H .bss DATA
0005:00000000 00000028H .idata$2 DATA
Address Publics by Value Rva+Base Lib:Object
0000:00000000 ___safe_se_handler_count 00000000 <absolute>
0000:00000000 ___ImageBase 00400000 <linker-defined>
0001:00000000 __enc$textbss$begin 00401000 <linker-defined>
0001:00010000 __enc$textbss$end 00411000 <linker-defined>
0002:000003d0 _main 004113d0 f Դ.obj
0004:00000000 ?largebuff@@3PADA 00418000 Դ.obj
,对于含有标签的行,比如这行
0002:000003d0 _main 004113d0 f Դ.obj
GodUp把从第七位开始的8八位截取出来转换成INT 再 加上之前取得的当前反汇编块的地址 作为 标签的地址,标签名为后面的全部。假设当前模块加载地址为0x00960000,
Getdisassemblerrange 返回的地址为0x00971000,那么上面的代码取得的标签为:
地址= 0x00971000 + 3d0 = 0x009713d0
名称= _main 004113d0 f Դ.obj
这一行处理的结果没有问题,看另外一行:
0004:00000000 ?largebuff@@3PADA 00418000 Դ.obj
处理的结果为:
地址= 0x00971000 + 0 = 0x00971000
名称= ?largebuff@@3PADA 00418000 Դ.obj
这里就出错了,0004表示DATA段,该段的起始加载地址是0x00978000
Largebuff 的地址应该是
0x00978000 + 0 = 0x00978000;
所以错误就在于GODUp把所有符号的地址都按TETX段地址加上偏移来计算。当符号不是TEXT段的符号时,就会得出错误的地址,而且我对于他 把后面的所有字符都当作标签名 这点很不理解,这样得到的标签名N长N长,不知道是不是因为之前的Map格式和现在的Map格式不一样造成的?
版本1.2。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课