首页
社区
课程
招聘
[原创]让代码飞出一段钢琴曲(freepiano小助手)(全局键盘钩子+dll劫持)+有码
发表于: 2017-5-1 15:46 7932

[原创]让代码飞出一段钢琴曲(freepiano小助手)(全局键盘钩子+dll劫持)+有码

2017-5-1 15:46
7932

突然想玩一下键盘弹曲子,就找到了freepiano,专业的东西不懂,就找了写简谱来玩玩,感觉挺不错的,哈哈~~

玩疯了之后,突然想到,我平时写代码,是不是可以弹出一段曲子呢,是不是心情会变得非常好,代码也写的更有节奏呢~~

说不定还搞出来一个什么《代码之歌》的钢琴曲~~ 嘎嘎

突然被自己这个想法吸引住了,不管咋样,每敲下代码的一个字符,后面想起了背景音乐,真是不错的,程序员也可以是“钢琴师”啊~~

有了想法,就开整!!!

有下面几点问题:

忘了说,freepiano长这样: img


开搞

先简单整理下思路:

首先想到的就是DLL劫持和修改freepiano的导入表,后者不够优雅,果断要选择dll劫持。

然后就用depends看了下freepiano的导入信息,发现几个可以劫持的(dsound.dll,d3d9.dll等),简单代码确认了一下,freepiano可以劫持这两个模块,选择了d3d9.dll(函数少)。

img


然后偷懒用了aheadlib导出了d3d9.dll的导出函数信息,简单方便,飞快得就搞定了劫持。

代码很简单,就贴一点(都不需要手写):

一试,OK,模块起来了,freepiano正常工作。


2. 安装钩子

选择了安装全局WH_KEYBOARD钩子,这个代码网上也太多了,就不细说了,看看就行

首先想到的就是在钩子函数里给freepiano发送WM_KEYDOWN/WM_KEYUP消息就行了。

先找到freepiano的窗口,spy++上,找到窗口标题和类型信息,然后代码:

然后就是发消息:

测试,失败了,没有预想的效果。

分析原因:

然后发现居然没有对WM_KEYDOWN/WM_KEYUP/WM_CHAR之类的消息进行处理,那是怎么接受的按键信息


img进钩子函数一下,各种按键状态记录的处理,不深究了。基本确认他使用这种方式来接受按键信息。

那就不能直接PostMessage发送消息了。

通过一个线程,循环查找freepianp窗口(可能还没起来),然后hook窗口响应函数

自己的函数中加入对WM_COPYDATA的消息处理,调用freepiano的钩子函数g_LowLevelKeyboardProc发键盘消息过去。

g_LowLevelKeyboardProc地址这里使用硬编码,图方便

功能到这里基本搞定。

测试通过。

手指立马不受控制的在编辑器里、浏览器、文件浏览器里各种按键,然后耳边响起了悠扬(忽略乱打的节奏的话)的钢琴声~~

然后录了一段程序员启蒙歌-《hello world》!你们感受一下:

在线试听:https://pan.baidu.com/s/1cIlPOM

由于手抽,打错了几个字,所以可以听到多次短暂的退格琴声,表介意~~~

可能的优化:

有兴趣的同学可以去折腾,我这里就不继续了~~



[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 3
支持
分享
最新回复 (13)
雪    币: 24
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感觉自己成艺术生了
2017-5-1 16:25
0
雪    币: 6
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
知识的最高境界恐怕就是哲学和艺术了
2017-5-1 18:09
0
雪    币: 10072
活跃值: (3003)
能力值: ( LV15,RANK:515 )
在线值:
发帖
回帖
粉丝
4
foresen 感觉自己成艺术生了[em_13]
程序员都是搞艺术的
2017-5-1 18:34
0
雪    币: 362
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
我也前几天才发现的看视频学习弹了小星星。1155665
2017-5-1 20:49
0
雪    币: 6112
活跃值: (1212)
能力值: (RANK:30 )
在线值:
发帖
回帖
粉丝
6

看了标题,我以为代码也可以写乐谱了哈哈~赞一个

2017-5-1 21:13
0
雪    币: 10072
活跃值: (3003)
能力值: ( LV15,RANK:515 )
在线值:
发帖
回帖
粉丝
7
哆啦咪 看了标题,我以为代码也可以写乐谱了哈哈~赞一个
谢版主赞赏
2017-5-1 21:26
0
雪    币: 1422
活跃值: (3841)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
8

freepiano  x86在x64系统下打不开,说初始化显卡失败,
能否提供一个x64位freepiano用的

2017-5-1 23:20
0
雪    币: 10072
活跃值: (3003)
能力值: ( LV15,RANK:515 )
在线值:
发帖
回帖
粉丝
9
方向感 freepiano  x86在x64系统下打不开,说初始化显卡失败,能否提供一个x64位freepiano用的
我就是在x64下使用的,如果不行,可能是d3d9劫持版本有问题,有源码,自己修改一下把
2017-5-2 08:12
0
雪    币: 12848
活跃值: (9142)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
10
其实构造参数并直接call  fnHkINLPKBDLLHOOKSTRUCT也可以,他内部会帮你call  注册的hookproc
2017-5-2 08:26
0
雪    币: 10072
活跃值: (3003)
能力值: ( LV15,RANK:515 )
在线值:
发帖
回帖
粉丝
11
hzqst 其实构造参数并直接call fnHkINLPKBDLLHOOKSTRUCT也可以,他内部会帮你call 注册的hookproc
大神能否说详细点,没看明白,,,自己构造参数?构造按键的参数?
2017-5-2 10:53
0
雪    币: 12848
活跃值: (9142)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
12

就是PEB->KernelCallbackTable里的一个东西,用PCHUNTER可以直接看到地址

int __stdcall __fnHkINLPKBDLLHOOKSTRUCT(int a1)
{
  (*(void (__stdcall **)(_DWORD, _DWORD, int, _DWORD))(a1 + 12))(
    *(_DWORD *)a1,
    *(_DWORD *)(a1 + 4),
    a1 + 16,
    *(_DWORD *)(a1 + 8));
  return XyCallbackReturn(0);
}

所有键盘钩子回调从内核回到用户层的时候都是先走到fnHkINLPKBDLLHOOKSTRUCT

他会call ntdll里的某个分发函数,然后分发函数会重新组织参数,帮你call 真正的KeyboardHookProc

*(_DWORD *)a1,
    *(_DWORD *)(a1 + 4),
    a1 + 16,
    *(_DWORD *)(a1 + 8)

以上是部分KeyboardHookProc的参数,还包括区分该钩子是否是全局钩子的flags(具体&多少忘了,好像0x400来着)

由于这个函数非常简单,你完全可以构造一个a1的结构体,模仿他的样子call一波。

2017-5-2 12:43
0
雪    币: 10072
活跃值: (3003)
能力值: ( LV15,RANK:515 )
在线值:
发帖
回帖
粉丝
13
hzqst 就是PEB->KernelCallbackTable里的一个东西,用PCHUNTER可以直接看到地址int __stdcal ...
明白了,谢指教!
2017-5-2 12:56
0
雪    币: 191
活跃值: (237)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
好东东
2017-5-2 21:46
0
游客
登录 | 注册 方可回帖
返回
//