• 标 题:我的第一篇增加PE文件功能的文章,献丑了。 (4千字)
  • 作 者:lzqgj  
  • 时 间:2003-08-17 00:40:46
  • 链 接:http://bbs.pediy.com

Winamp有个迷你歌词插件,可以方便地下载、管理歌词。但用了总觉得有个地方不顺手,就是如果winamp显示歌曲为“xxx -  无标题 ”时,总是要将后边的词去掉才能正常下载。偏偏我的大多数歌曲都是这种情况。于是就向插件下手了,目标是在搜索歌词前自动去掉“ -  无标题”。
经过跟踪得知winamp是调用MiniLyrics.dll,如果搜索不到歌词,则弹出对话框“不能找到相匹配的歌词,请您试试用其他歌曲名搜索!”,打开中文菜单文件mschs.ini,找到这句,前面的英文是:Can't find any match lyrics, please try other name!
好了,用OD载入winamp,运行,查看MiniLyrics.dll模块,搜索Can't find any match lyrics, 设断点。然后在下载对话框中点击“搜索”按钮,中断在OD中。仔细跟踪找到如下代码:
00FF2E40  SUB ESP,100
00FF2E46  PUSH ESI
00FF2E47  PUSH 100
00FF2E4C  LEA EAX,DWORD PTR SS:[ESP+8]
00FF2E50  PUSH EAX
00FF2E51  MOV ESI,ECX
00FF2E53  MOV ECX,DWORD PTR DS:[ESI+4]
00FF2E56  PUSH 44E
00FF2E5B  PUSH ECX
00FF2E5C  CALL DWORD PTR DS:[<&USER32.GetDlgItemTe>; USER32.GetDlgItemTextA
00FF2E62  MOV AL,BYTE PTR SS:[ESP+4]   --->歌曲名
00FF2E66  TEST AL,AL
00FF2E68  JNZ SHORT MiniLyri.00FF2EA0  --->有歌名就跳
00FF2E6A  MOV EDX,DWORD PTR DS:[ESI+4]
00FF2E6D  PUSH 0
00FF2E6F  PUSH 40
00FF2E71  PUSH EDX
00FF2E72  PUSH MiniLyri.010368F0                    ASCII "Please input the song name!"
00FF2E77  MOV ECX,MiniLyri.01043898
00FF2E7C  CALL MiniLyri.00FE96D0
00FF2E81  PUSH EAX
00FF2E82  CALL MiniLyri.00FE7BC0
程序跳到这:
00FF2EA0  PUSH EBX
00FF2EA1  PUSH EBP
00FF2EA2  PUSH EDI
00FF2EA3  PUSH 7F02
00FF2EA8  PUSH 0
00FF2EAA  CALL DWORD PTR DS:[<&USER32.LoadCursorA>>; USER32.LoadCursorA
00FF2EB0  MOV EDI,EAX
00FF2EB2  CALL DWORD PTR DS:[<&USER32.GetCursor>]   USER32.GetCursor
00FF2EB8  MOV EBP,DWORD PTR DS:[<&USER32.SetCursor>; USER32.SetCursor
00FF2EBE  PUSH EDI
00FF2EBF  MOV EBX,EAX
00FF2EC1  CALL EBP
00FF2EC3  PUSH 1
00FF2EC5  LEA ECX,DWORD PTR SS:[ESP+14]
00FF2EC9  PUSH ECX
00FF2ECA  MOV ECX,ESI
00FF2ECC  CALL MiniLyri.00FF2B40
00FF2ED1  TEST EAX,EAX
00FF2ED3  PUSH EBX
00FF2ED4  JNZ SHORT MiniLyri.00FF2F03
00FF2ED6  CALL EBP
00FF2ED8  MOV EDX,DWORD PTR DS:[ESI+4]
00FF2EDB  PUSH 0
00FF2EDD  PUSH 40
00FF2EDF  PUSH EDX
00FF2EE0  PUSH MiniLyri.010368BC                    ASCII "Can't find any match lyrics, please try other name!"
00FF2EE5  MOV ECX,MiniLyri.01043898
00FF2EEA  CALL MiniLyri.00FE96D0

修改如下:
00FF2EA0  JMP MiniLyri.01033490     --->跳到修改的代码
00FF2EA5  NOP                       --->补充字节,下同
00FF2EA6  NOP
00FF2EA7  NOP
跳到这修改:
01033490  PUSHAD                    --->保存堆栈数据
01033491  MOV EBX,25                --->esp减小了20,故应加回
01033496  MOV AL,BYTE PTR DS:[ESP+EBX]  --->歌曲名第二字节
0103349A  CMP AL,0                      --->没有?
0103349C  JE SHORT MiniLyri.010334D0    --->跳到结束
0103349E  INC BL                        
010334A0  CMP AL,20                     --->等于20?(空格)
010334A2  JE SHORT MiniLyri.010334A6    --->进一步判断
010334A4  JMP SHORT MiniLyri.01033496   --->循环
010334A6  MOV AL,BYTE PTR SS:[ESP+EBX]  --->下一字节
010334A9  INC BL
010334AB  CMP AL,2D                     --->等于2D?即"-"号
010334AD  JE SHORT MiniLyri.010334B1
010334AF  JMP SHORT MiniLyri.01033496
010334B1  MOV AL,BYTE PTR SS:[ESP+EBX]
010334B4  INC BL
010334B6  CMP AL,20
010334B8  JE SHORT MiniLyri.010334BC
010334BA  JMP SHORT MiniLyri.01033496
010334BC  MOV AL,BYTE PTR SS:[ESP+EBX]
010334BF  INC BL
010334C1  CMP AL,20
010334C3  JE SHORT MiniLyri.010334C7
010334C5  JMP SHORT MiniLyri.01033496
010334C7  SUB BL,4                      --->下面不想判断了,有“ -  "四个字节就当作无用的,将其置0,先回到第一个空格
010334CA  NOP
010334CB  NOP
010334CC  NOP
010334CD  NOP
010334CE  NOP
010334CF  NOP
010334D0  NOP
010334D1  NOP
010334D2  NOP
010334D3  MOV DWORD PTR SS:[ESP+EBX],0      --->四个字节置0
010334DA  POPAD                             --->恢复堆栈数据
010334DB  PUSH EBX                    --->恢复原代码,下同
010334DC  PUSH EBP
010334DD  PUSH EDI
010334DE  PUSH 7F02
010334E3  JMP MiniLyri.00FF2EA8       --->返回原程序继续执行


再次运行,OK!
首次用汇编代码修改PE功能,花了5个多小时,中间走了些弯路,真的好累!


--------------------------------------------------------------------------------

标 题:顺便帖一下让winamp任务栏滚动文字正常显示中文 (1千字)
发信人:lzqgj  
时 间:2003-08-17 23:26:06
详细信息:



winamp任务栏可以滚动显示歌名,但如果是中文,将会时而出现乱码,因为中文是双字节,而winamp并没有考虑,仍当作单字节处理。当滚过第一字节后,第二字节就无法正常显示。
用OD载入winamp,下断点:setwindowtexta,中断后回到这里:
0042EE53  LEA EAX,DWORD PTR [EBP-1000]    --->[EBP-1000]为任务栏中要显示的文字
0042EE59  PUSH EAX                        
0042EE5A  PUSH DWORD PTR DS:[453320]      --->HWnd
0042EE60  CALL DWORD PTR DS:[<&USER32.SetWindo>; \SetWindowTextA
向上分析文字是怎么滚动的:
0042ED40  PUSH ESI                             --->文字  
0042ED41  STOS BYTE PTR ES:[EDI]               
0042ED42  CALL             --->长度
0042ED47  POP ECX
0042ED48  MOV ECX,DWORD PTR DS:[451248]        --->重要:取第几字节的记数器
0042ED4E  CMP ECX,EAX
0042ED50  JGE SHORT Winamp.0042EDA9            --->大于就跳,计数器重新置0
0042ED52  LEA EAX,DWORD PTR DS:[ECX+4538C0]    --->[4538C0]中放置完整的文字
0042ED58  PUSH EAX                             
0042ED59  LEA EAX,DWORD PTR SS:[EBP-1000]      
0042ED5F  PUSH EAX                             
0042ED60  CALL             --->取得文字复制到[EBP-1000]中
下略。
明显程序用[451248]记忆取到第几位数,然后取得文字复制到[EBP-1000]中让任务栏显示,只要判断取得的第一个文字是否中文,是则将计数器加1,就可跳过该中文的第二字节。

修改程序如下:
0042EE53  JMP Winamp.0043D4E0        --->在任务栏显示前先处理文字
0043D4E0  MOV AL,BYTE PTR SS:[EBP-1000]   --->取第一字节
0043D4E6  CMP AL,9F                  --->中文一般大于9F?我猜的
0043D4E8  JB SHORT Winamp.0043D4F0   --->是则跳
0043D4EA  INC DWORD PTR DS:[451248]  --->计数器加1
0043D4F0  LEA EAX,DWORD PTR SS:[EBP-1000]   --->恢复原代码
0043D4F6  JMP Winamp.0042EE59        --->回原程序继续执行   看雪学院技术论坛(www.pediy.com) 并保持文章的完整性! 


--------------------------------------------------------------------------------