Windows下利用钩子函数抓取声卡数据

 

利用本文介绍的知识可以实现优酷网等播放视频时声音的抓取,及所有以wave系列API为渲染接口的软件声音的抓取。

 

Windows下的声音播放函数有两类,一类是旧的winmm.dll 里面的API,另一类是比较新的DirectSound。

 

录音的策略可以分为三类:

 

第一类是利用windows的Mixer系列API(适用于DirectSound),稍微差一点的录音软件会用这种(这种方法的好处是可以抓取wave系列及Direct系列的声音,不足之处是只能通过混音抓取,这样的缺点就是万一有麦克风开起来,效果可能比较差)

 

第二类是利用钩子函数,当系统调用某个函数进行播放时,我们对其数据进行抓取,获得其中的数据后,将数据返还给系统调用(只适用与winmm.dll里的函数,DirectSound的API我没有找到直接对数据操作的,DirectSound是用了两个缓冲,然后系统会自动混音,没有找到类似于wave系列的数据接口),今天准备介绍这种方法。

 

第三类是编写虚拟声卡(专业级都是利用这种),所有流到物理声卡的数据,都会先进入虚拟声卡,Total Recorder等比较著名的录音软件都是采取这个策略。这个还不会,驱动程序没写过。

 

对于旧的多媒体接口,通过dumpbin.exe -exports winmm.dll ,我们可以看到这个dll导出了很多函数,

 

包括混音类API(第一类录音策略用下面的API,国内有一些商业化的软件就是这么搞得),如下:    

      115   70 000094F8 mixerClose
     116   71 000107E1 mixerGetControlDetailsA
     117   72 0000A479 mixerGetControlDetailsW
     118   73 00010456 mixerGetDevCapsA
     119   74 0000A183 mixerGetDevCapsW
     120   75 0000928F mixerGetID
     121   76 000106B2 mixerGetLineControlsA
     122   77 0000A05B mixerGetLineControlsW
     123   78 000105F3 mixerGetLineInfoA
     124   79 0000A25F mixerGetLineInfoW
     125   7A 00010116 mixerGetNumDevs
     126   7B 0000A02A mixerMessage
     127   7C 000095E1 mixerOpen
     128   7D 000102D4 mixerSetControlDetails

 

以及传统的Wave系列API等,今天我们准备用钩子函数来抓取这些API,其中参考了VC知识库的Skype答录机这篇文章,其实主要也是人家的思路,如下:

    169   A6 0001C291 waveInAddBuffer
    170   A7 0001C0DD waveInClose
    171   A8 0001BE87 waveInGetDevCapsA
    172   A9 00009C40 waveInGetDevCapsW
    173   AA 0001BB4A waveInGetErrorTextA
    174   AB 0001C0A1 waveInGetErrorTextW
    175   AC 0001C4AC waveInGetID
    176   AD 00005FED waveInGetNumDevs
    177   AE 0001C3C5 waveInGetPosition
    178   AF 0000896A waveInMessage
    179   B0 00008EA9 waveInOpen
    180   B1 0001C18C waveInPrepareHeader
    181   B2 0001C376 waveInReset
    182   B3 0001C2FA waveInStart
    183   B4 0001C338 waveInStop
    184   B5 0001C203 waveInUnprepareHeader
    185   B6 0001BC42 waveOutBreakLoop
    186   B7 00005726 waveOutClose
    187   B8 0001B784 waveOutGetDevCapsA
    188   B9 00007E94 waveOutGetDevCapsW
    189   BA 0001BB4A waveOutGetErrorTextA
    190   BB 0001C0A1 waveOutGetErrorTextW
    191   BC 0001C4F9 waveOutGetID
    192   BD 00005FB6 waveOutGetNumDevs
    193   BE 0001BCD3 waveOutGetPitch
    194   BF 0001BD63 waveOutGetPlaybackRate
    195   C0 0001BC80 waveOutGetPosition
    196   C1 0001B9B2 waveOutGetVolume
    197   C2 00006110 waveOutMessage
    198   C3 00005201 waveOutOpen
    199   C4 0001BB77 waveOutPause
    200   C5 000059D9 waveOutPrepareHeader
    201   C6 0001BBF3 waveOutReset
    202   C7 0001BBB5 waveOutRestart
    203   C8 0001BD24 waveOutSetPitch
    204   C9 0001BDB4 waveOutSetPlaybackRate
    205   CA 0001BA3F waveOutSetVolume
    206   CB 000057C8 waveOutUnprepareHeader
    207   CC 00005A4A waveOutWrite

 

虚拟声卡需要驱动程序,我是个门外汉,很不幸最近还没精力去学习,所以将来一段时间都是门外汉。

 

下面我们进入正题,来看看如何用钩子函数抓取 wave系列API,使系统播放声音时,我们的程序能够偷偷的将要发送到声卡的数据备份一份,

然后在返还给系统。

因此涉及到了几方面知识,钩子函数的编写,dll的注入,如何修改函数的地址(IAT表(Import Address Table))等。

 

关于钩子函数与dll编写,大家可以看一下孙鑫的VC教程最后两课,看完之后,基本就算入门了。

 

学了孙鑫的VC之后,我们来编写声音抓取程序还是有很大难度,可以查看如下链接的信息http://www.vckbase.com/document/viewdoc/?id=1842

这篇文章基本阐述了如何抓取声卡数据,也给我们描绘了一个比较好的使用前景,比如抓取skype的数据,实际上优酷,Google音乐等都是调用wave系列API的,

所以他们的声音均可通过这种方法进行抓取。

 

看了上面的链接里的文章,基本就明白了如何用钩子函数来抓取声卡数据,有两个我当时不大明白的东西在这里说明一下,

因为skype答录机是商业化软件,所以它是部分开源的,实际上已经够用了,里面有个CShareMemory类,这个类做的工作我猜想主要是内存的映射(CMapView)及互斥访问等,实际上,我们并不要管这个类,可以自己用简单的文件读写,在Hook_waveOutWrite 系列函数内将数据写入文件,得到的数据不是wave类型的,是pcm,用声音转换软件可以转换为wav及mp3格式。

 

CAPIHook类实现了函数地址的修改,方法是通过修改函数的IAT表,关于这方面的资料可以查看网上的一篇文章API Hook完全手册,      

 

钩子的类型为全局钩子,设置的消息为WM_GETMESSAGE,如果自己不懒,加上一个lame_enc.dll转换为mp3也不错。

 

整个软件做成一个dll,然后导出一个接口,在另外一个程序内导入上面编写好的dll,就可以实现声卡的录音了,

 

好像没写什么,因为别人已经写得非常好了,仅做个整理,给需要做声卡录音的朋友做个参考,

我当时跌跌撞撞的花了不少时间,所以知道学技术不容易,^_^不一定正确,仅供参考,

 

呵呵,第一次在这上面写文章,以马斌读报里的台词结尾:到这里吧,就到这里了^_^

 

大家如果觉得这篇文章有用,欢迎点击http://feed.feedsky.com/superbigdog里面的广告,呵呵

 要是你觉得广告里面的游戏好玩,也可以试玩一下^_^

 

 

转载于:https://www.cnblogs.com/superbigdog/archive/2009/06/20/1507478.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Hook(钩子)并不是一项很难的技术,但对于初学者来说还是一个不小的门槛。为此,我将鼠标Hook做成了一个可视化的控件,通过简单的设置几个属性,就可以截获或跟踪其它应用程序的鼠标动作。**********控件介绍:【属性】1.Blocked: Boolean;确定是截获还是跟踪鼠标动作,True对应截获,False对应跟踪。默认值为False2.HookedExeName: string;指定被Hook的应用程序名称。为空时对所有的应用程序起作用。默认值为空3.Active: Boolean;是否处于Hook状态,只读。4.DllName: string;Mouse钩子的dll名称,默认为MouseHook.dll,只读。5.DLLLoaded: Boolean;MouseHook.dll是否被加载,只读。【方法】1.function Start: Boolean;开始Hook2.procedure Stop;停止Hook【事件】 WM_LBUTTONDBLCLK, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_RBUTTONDBLCLK, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_MBUTTONDBLCLK, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_NCLBUTTONDBLCLK, WM_NCLBUTTONDOWN, WM_NCLBUTTONUP, WM_NCRBUTTONDBLCLK, WM_NCRBUTTONDOWN, WM_NCRBUTTONUP, WM_NCMBUTTONDBLCLK, WM_NCMBUTTONDOWN, WM_NCMBUTTONUP, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_NCMOUSEMOVE, WM_MOUSEACTIVATE, WM_NCHITTEST, WM_CAPTURECHANGED我处理了如上的鼠标事件,注意其中有几个事件我在测试时发现无法Hook,它们为WM_MBUTTONDBLCLK,WM_NCMBUTTONDBLCLK,WM_MOUSEACTIVATE,WM_NCHITTEST,WM_CAPTURECHANGED建议:不要将HookedExeName:=''; 和 Blocked:=True; 同时设置**********【使用说明】1.首先安装“鼠标Hook控件”目录下的控件2.必须将mousehook.dll拷贝到你开发的应用程序目录下,或系统目录下,如system32【多说几句】1.我提供了一个名为test.exe的demo,该例子是对notepad.exe进行Hook的,因此,使用前先启动notepad.exe,再点击界面上的“开始”,否则会提示“找不到指定的进程”!2.你可以参考我的控件设计模式来设计自己的Hook控件,如键盘Hook。3.本来想写一个组件包的,其中包括各种Hook控件,以及读写端口的控件,以方便初学者的使用,可是要些论文,以后再说吧。 黄晓斌 hxb_leiyuan2000@163.net QQ:478522325
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值