• 标 题:一个老MP3播放器的修改 (8千字)
  • 作 者:slangmgh
  • 时 间:2003-08-19 12:23:22
  • 链 接:http://bbs.pediy.com

Streaming Audio Player (SAP) v0.9是一个较老的MP3播放器,2000年7月份发布的。但其中的DJ功能我确非常喜欢,并且占用资源小,界面也非常漂亮,而且支持动画。不过在使用的时候发现几个不方便的地方,就修改了一下:
1. 当设置成DJ模式的时候,如果停止播放,在按Play,系统不会
   继续播放。
   
   解决方法:
       用Ollydbg打开SAP.EXE,查找ShuffleMaster,经过分析后发现
   ShuffleMaster为[436488],当该值为1时就是ShuffleMaster模式。
   设置在该地址读时中断,并且在DJ模式下按Play,代码如下:

   0040F945   |>  8B0D 88644300   MOV     ECX, [436488]
   0040F94B   |.  85C9            TEST    ECXECX
   0040F94D   |.  7E 0B           JLE     SHORT sap.0040F95A   如果不是DJ模式跳转
   0040F94F   |.  51              PUSH    ECX
   0040F950   |.  E8 6BAB0000     CALL    sap.0041A4C0
   0040F955   |.  83C4 04         ADD     ESP, 4
   0040F958   |.  5E              POP     ESI                              USER32.77D43FBE
   0040F959   |.  C3              RETN
   0040F95A   |>  8B0D 8C644300   MOV     ECX, [43648C]
   0040F960   |.  83F9 01         CMP     ECX, 1
   0040F963   |.  75 0A           JNZ     SHORT sap.0040F96F
   0040F965   |.  8A88 68030000   MOV     CL, [EAX+368]
   0040F96B   |.  84C9            TEST    CLCL
   0040F96D   |.  74 15           JE      SHORT sap.0040F984
   0040F96F   |>  8B0D 8C644300   MOV     ECX, [43648C]

   在地址0040F94D处判断如果不是DJ模式则跳转,是DJ模式就调用
   41A4C0,然后返回。查看41A4C0的代码发现是创建一个新的线程,
   显然这个线程是用于DJ的,而40F95A以下的代码则是来开始播放
   的,因而很简单,将40F958和40F959的代码NOP掉即可。

2. 系统在最小化到SysTray的时候显示ICON不对
   解决方法:
   用Ollydbg打开SAP.EXE,查找函数Shell_NotifyIconA的调用,到如下
   代码:
   0040A500   /$  8B4424 04       MOV     EAX, [ESP+4]                     sap.004107E4
   0040A504   |.  83EC 58         SUB     ESP, 58
   0040A507   |.  8B4C24 64       MOV     ECX, [ESP+64]                    ntdll.77F8CF62
   0040A50B   |.  53              PUSH    EBX                              USER32.GetMessageA
   0040A50C   |.  894424 08       MOV     [ESP+8], EAX
   0040A510   |.  56              PUSH    ESI                              USER32.WaitMessage
   0040A511   |.  894C24 10       MOV     [ESP+10], ECX
   0040A515   |.  57              PUSH    EDI                              USER32.PeekMessageA
   0040A516   |.  8B7424 74       MOV     ESI, [ESP+74]
   0040A51A   |.  8B4424 78       MOV     EAX, [ESP+78]
   0040A51E   |.  897424 20       MOV     [ESP+20], ESI                    USER32.WaitMessage
   0040A522   |.  85C0            TEST    EAXEAX
   0040A524   |.  C74424 0C 58000>MOV     DWORD PTR [ESP+C], 58
   0040A52C   |.  C74424 18 07000>MOV     DWORD PTR [ESP+18], 7
   0040A534   |.  C74424 1C 64800>MOV     DWORD PTR [ESP+1C], 8064
   0040A53C   |.  74 10           JE      SHORT sap.0040A54E
   0040A53E   |.  6A 40           PUSH    40                              /n = 40 (64.)
   0040A540   |.  50              PUSH    EAX                             |String2 = "H"
   0040A541   |.  8D4424 2C       LEA     EAX, [ESP+2C]                   |
   0040A545   |.  50              PUSH    EAX                             |String1 = 003C53E0
   0040A546   |.  FF15 18254500   CALL    [<&KERNEL32.lstrcpynA>]         \lstrcpynA
   0040A54C   |.  EB 05           JMP     SHORT sap.0040A553
   0040A54E   |>  C64424 24 00    MOV     BYTE PTR [ESP+24], 0
   0040A553   |>  8D4424 0C       LEA     EAX, [ESP+C]
   0040A557   |.  8B4C24 6C       MOV     ECX, [ESP+6C]
   0040A55B   |.  50              PUSH    EAX
   0040A55C   |.  51              PUSH    ECX
   0040A55D   |.  FF15 1C264500   CALL    [<&SHELL32.Shell_NotifyIconA>]   SHELL32.Shell_NotifyIconA
   0040A563   |.  8BF8            MOV     EDIEAX
   0040A565   |.  85F6            TEST    ESIESI                         USER32.WaitMessage
   0040A567   |.  74 07           JE      SHORT sap.0040A570
   0040A569   |.  56              PUSH    ESI                             /hIcon = 77D43FB2
   0040A56A   |.  FF15 A0264500   CALL    [<&USER32.DestroyIcon>]         \DestroyIcon
   0040A570   |>  8BC7            MOV     EAXEDI                         USER32.PeekMessageA
   0040A572   |.  5F              POP     EDI                              USER32.77D43FBE
   0040A573   |.  5E              POP     ESI                              USER32.77D43FBE
   0040A574   |.  5B              POP     EBX                              USER32.77D43FBE
   0040A575   |.  83C4 58         ADD     ESP, 58
   0040A578   \.  C3              RETN

   经查,该函数在下面的代码中被调用:
   0040A580   /$  53              PUSH    EBX
   0040A581   |.  A1 B0604300     MOV     EAX, [4360B0]
   0040A586   |.  56              PUSH    ESI
   0040A587   |.  57              PUSH    EDI
   0040A588   |.  8B78 0C         MOV     EDI, [EAX+C]
   0040A58B   |.  6A FA           PUSH    -6                              /Index = GWL_HINSTANCE
   0040A58D   |.  57              PUSH    EDI                             |hWnd = NULL
   0040A58E   |.  FF15 64264500   CALL    [<&USER32.GetWindowLongA>]      \GetWindowLongA
   0040A594   |.  8BF0            MOV     ESIEAX
   0040A596   |.  6A 00           PUSH    0
   0040A598   |.  6A 00           PUSH    0
   0040A59A   |.  68 57040000     PUSH    457
   0040A59F   |.  6A 00           PUSH    0
   0040A5A1   |.  57              PUSH    EDI
   0040A5A2   |.  E8 59FFFFFF     CALL    SAP.0040A500
   0040A5A7   |.  83C4 14         ADD     ESP, 14
   0040A5AA   |.  68 4C504300     PUSH    SAP.0043504C                     ASCII "SAP"
   0040A5AF   |.  6A 65           PUSH    65                              /RsrcName = 101.
   0040A5B1   |.  56              PUSH    ESI                             |hInst = 00000024
   0040A5B2   |.  FF15 88264500   CALL    [<&USER32.LoadIconA>]           \LoadIconA
   0040A5B8   |.  50              PUSH    EAX
   0040A5B9   |.  68 57040000     PUSH    457
   0040A5BE   |.  6A 01           PUSH    1
   0040A5C0   |.  57              PUSH    EDI
   0040A5C1   |.  E8 3AFFFFFF     CALL    SAP.0040A500
   0040A5C6   |.  83C4 14         ADD     ESP, 14
   0040A5C9   |.  5F              POP     EDI                              kernel32.77E7EB69
   0040A5CA   |.  5E              POP     ESI                              kernel32.77E7EB69
   0040A5CB   |.  5B              POP     EBX                              kernel32.77E7EB69
   0040A5CC   \.  C3              RETN

   经过跟踪后发现调用GetWindowLongA返回的hInstance为0,而不是
   正在的句柄,所以将该代码改成如下:
   0040A58B   |.  6A 00           PUSH    0                               /pModule = NULL
   0040A58D   |.  90              NOP                                     |
   0040A58E   |.  FF15 C8254500   CALL    [<&KERNEL32.GetModuleHandleA>]  \GetModuleHandleA

   通过GetModuleHandle来获取句柄就可以了。
   
3. 还有,在设置成Auto Hide模式时,当鼠标移到各个角落的时候,会自动显示,
   这些功能很烦,所以需要把它去掉。查找Auto Hide的代码发现是通过SetTimer
   实现的,代码如下:
   0041C86F   |.  6A 00           PUSH    0
   0041C871   |.  6A FF           PUSH    -1
   0041C873   |.  51              PUSH    ECX
   0041C874   |.  FFD6            CALL    ESI                              USER32.SetWindowPos
   0041C876   |.  6A 00           PUSH    0                               /Timerproc = NULL
   0041C878   |.  8B0D B0604300   MOV     ECX, [4360B0]                   |
   0041C87E   |.  68 2C010000     PUSH    12C                             |Timeout = 300. ms
   0041C883   |.  6A 00           PUSH    0                               |TimerID = 0
   0041C885   |.  8B51 0C         MOV     EDX, [ECX+C]                    |
   0041C888   |.  52              PUSH    EDX                             |hWnd = 7FFE0304
   0041C889   |.  FF15 B0264500   CALL    [<&USER32.SetTimer>]            \SetTimer
   0041C88F   |>  A1 BC604300     MOV     EAX, [4360BC]

   为简单起见,直接将代码41C876跳转到41C88F如下:
   0041C876      /EB 17           JMP     SHORT sap.0041C88F
   0041C878   |. |8B0D B0604300   MOV     ECX, [4360B0]                   |
   0041C87E   |. |68 2C010000     PUSH    12C                             |Timeout = 300. ms
   0041C883   |. |6A 00           PUSH    0                               |TimerID = 0
   0041C885   |. |8B51 0C         MOV     EDX, [ECX+C]                    |
   0041C888   |. |52              PUSH    EDX                             |hWnd = 7FFE0304
   0041C889   |. |FF15 B0264500   CALL    [<&USER32.SetTimer>]            \SetTimer
   0041C88F   |> \A1 BC604300     MOV     EAX, [4360BC]

========================================================================