首页
社区
课程
招聘
[原创]利用DLL为程序增加背景音乐
发表于: 2006-9-6 11:39 8327

[原创]利用DLL为程序增加背景音乐

2006-9-6 11:39
8327

【文章标题】: 利用DLL为程序增加背景音乐
【文章作者】: laomms
【下载地址】: 看附件
【编写语言】: DELPHI
【使用工具】: OLLYDBG LOADPE
【操作平台】: WINXP
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  
      上次在论坛上看到有人问如何为程序添加背景音乐。我这里提供一种方案,将音乐资源写入DLL,利用DLL_PROCESS_ATTACH功能,当程序载入该DLL的进程时直接播放音乐。抽空写了这个过程。(以下代码在DELPHI下通过。)
  一、利用UFMOD创建DELPHI音乐。
      找个好听的XM,用eff转换为DELPHI单元以供DELPHI调用。如图:
  

  二、编写DLL文件
      用DELPHI新建一个DLL工程。我们开始写个PLAYSONG的输出函数,具体看代码:
  library playmusic;
  uses
    Windows,
    SysUtils,
    Classes,
    Unit1 in 'Unit1.pas';                     // Unit1单元
  
  procedure DllEntryPoint(dwReason:Word);     //Dll的入口函数
  begin
    case dwReason of
      DLL_PROCESS_ATTACH:playsong;  //当进入DLL进程空间时播放音乐
    end;
  end;
  
  exports
    PLAYSONG;                      //输出函数
  begin
    DllProc:=@DllEntryPoint;                //Dll的入口函数
    DllEntryPoint(DLL_PROCESS_ATTACH);      //附加进程
  end.
  end.
  
  再把XM转换后的单元引入到Unit1单元:
  由于代码比较长,就不贴了,看附件中的源码。
  最后编译成的playmusic.dll就是带有XM资源的DLL文件。
  
  三、加载到程序。
      这一步应该很简单了,用LOADPE或IIDking可以轻易做到。但是我们今天准备用手动将DLL显示加载到程序中。用LoadLibraryA装入DLL,然后用GetProcAddress函数检取其输出函数的地址,获得其指针来调用。原程序中已经有LoadLibraryA和GetProcAddress函数,所以可以直接调用,地址为:
  LoadLibraryA: CALL DWORD PTR DS:[45EB50]
  GetProcAddress:CALL DWORD PTR DS:[45E73C]
      OD载入目标文件test.exe。CTRL+B搜索大量的000000000000来到程序空余的空间。比如这里来到00457728处写代码。分别写入playmusic.dll和playsong函数的名称以供LoadLibraryA和GetProcAddress调用。具体代码:
  
  00457728 >  E8 10000000     CALL fix.0045773D                        ; 跳到45773D处调用LoadLibraryA
  0045772D    70 6C           JO SHORT fix.0045779B                    ; ASCII "playmusic.dll
  0045772F    61              POPAD
  00457730    79 6D           JNS SHORT fix.0045779F
  00457732    75 73           JNZ SHORT fix.004577A7
  00457734    6963 2E 646C6C0>IMUL ESP,DWORD PTR DS:[EBX+2E],6C6C64
  0045773B    0000            ADD BYTE PTR DS:[EAX],AL
  0045773D    68 2D774500     PUSH fix.0045772D                        ; ASCII "playmusic.dll"
  00457742    FF15 50EB4500   CALL DWORD PTR DS:[<&kernel32.LoadLibrar>; kernel32.LoadLibraryA
  00457748    E8 0E000000     CALL fix.0045775B                        ; 跳到45773D处调用GetProcAddress
  0045774D    70 6C           JO SHORT fix.004577BB                    ; ASCII "playsong"
  0045774F    61              POPAD
  00457750    79 73           JNS SHORT fix.004577C5
  00457752    6F              OUTS DX,DWORD PTR ES:[EDI]               ; I/O 命令
  00457753    6E              OUTS DX,BYTE PTR ES:[EDI]                ; I/O 命令
  00457754    67:0000         ADD BYTE PTR DS:[BX+SI],AL
  00457757    0000            ADD BYTE PTR DS:[EAX],AL
  00457759    0000            ADD BYTE PTR DS:[EAX],AL
  0045775B    50              PUSH EAX
  0045775C    FF15 3CE74500   CALL DWORD PTR DS:[<&kernel32.GetProcAdd>; kernel32.GetProcAddress
  00457762    83C4 0C         ADD ESP,0C
  00457765    FFD0            CALL EAX                                 ; 调用playmusic.dll中的playsong函数
  00457767    83EC 0C         SUB ESP,0C
  0045776A    68 D8764500     PUSH fix.004576D8                        ; 压入程序入口地址
  0045776F    C3              RETN                                     ; 返回到程序入口
  00457770    90              NOP
  00457771    0000            ADD BYTE PTR DS:[EAX],AL
  00457773    0000            ADD BYTE PTR DS:[EAX],AL
  
      写好保存后,用LOADPE更改程序的入口点为00457728,即先载入DLL再跳到程序原来的入口。一切弄好后,测试一下,优美的音乐响起。如果你想进一步完善,编写一个带音乐播放控制界面的DLL,那就更爽了。
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2006年09月06日 11:32:59


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (4)
雪    币: 267
活跃值: (44)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
2
支持!!!
2006-9-6 11:51
0
雪    币: 223
能力值: (RANK:130 )
在线值:
发帖
回帖
粉丝
3
不好意思。能不能介绍一下什么是XM文件?什么地方有下载的?谢谢了。
2006-9-7 00:09
0
雪    币: 560
活跃值: (359)
能力值: ( LV13,RANK:1370 )
在线值:
发帖
回帖
粉丝
4
XM音乐及播放器下载 :
http://bbs.pediy.com/showthread.php?s=&threadid=26881&highlight=XM%D2%F4%C0%D6
ufmod 1.19 :
http://sourceforge.net/project/showfiles.php?group_id=158498
2006-9-7 07:19
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
POPAD
  00457750    79 73           JNS SHORT fix.004577C5
  00457752    6F              OUTS DX,DWORD PTR ES:[EDI]               ; I/O 命令
  00457753    6E              OUTS DX,BYTE PTR ES:[EDI]                ; I/O 命令
  00457754    67:0000         ADD BYTE PTR DS:[BX+SI],AL
  00457757    0000            ADD BYTE PTR DS:[EAX],AL
  00457759    0000            ADD BYTE PTR DS:[EAX],AL
  0045775B    50              PUSH EAX

为什么push eax前的playsound的二进制,而不是push 它的是统服首地址,
像这样:
jmp xx

xx: push addr playsound
    push eax
    call GetProcAddress
毕竟GetProcAddress有两个参数,
小弟初学,望不吝赐教!
还有就是add esp 0c是为了回收先前的PUSH 45772D和push eax吗?
如果是,为什么call eax后又要sub esp 0c
2006-9-7 14:06
0
游客
登录 | 注册 方可回帖
返回
//