一、前言
小时候,我是个逃课去黑网吧的小学生。传说网吧老板,会在电脑背后的USB接口上安装一个小玩意,记录小学生们的网游账号。现在我知道了,那是个硬件的键盘记录器。
硬件键盘记录器
和软件的键盘记录器一样,它会记录下用户在键盘上的所有输入,比如账号密码、网址、手机号等等。
硬件版本的独特之处在于:即使现在各种防御措施,已经能防御大多数软件键盘记录器,但是基于硬件的键盘记录器,对于操作系统来说是无感知的,毕竟它就是一个标准的输入设备。识别和防御也就变得十分困难了。
图中有一个设备是键盘记录器,你能找到吗?
本文我们来讲讲硬件键盘记录器的原理。并从PCB和固件起,做一个可以通过Wi-Fi远程控制的硬件键盘记录器。
二、原理
硬件键盘记录器在国内外的电商上有很多成品,就是价格略贵。开源设计有spacehuhn的wifi_keylogger(https://github.com/spacehuhn/wifi_keylogger),Freebuf上的@anymous的作品(https://www.freebuf.com/geek/58895.html)等等。
我们以wifi_keylogger为例,它是一个基于Arduino的键盘记录器。带有Wi-Fi功能,可以存储记录到的键盘输入,并可以通过其发出的Wi-Fi网络查看记录数据
wifi_keylogger
不过,可能您会觉得它不太实用:它太大了,很难安装在电脑后面。
究其原因,是因为USB键盘使用了HID协议。对于Arduino来说,它的速度太快,没办法读取。所以除了Arduino,还得加上其它用于读取HID协议的设备。
wifi_keylogger的解决方法是使用了一个USB Host Shield模块(图中白色的部分),@anymous的方法是用转接器将USB键盘转成PS2键盘,分析PS2的协议。
这些解决方案有两个缺点:一个是大,再者是这些方案会对键盘造成一些影响,比如多媒体键用不了、不同键盘布局兼容性有问题等等。
要做到更紧凑和兼容的设计,就得换用其它芯片,并且重新设计PCB了。最好是能将HID协议转换、键盘数据解析记录、Wi-Fi功能做在一块板上,而且体积较为小巧。
本文就设计制作了这样的一个键盘记录器。
三、设计
本文中的键盘记录器,实现了USB键盘输入的分析和记录,并提供Wi-Fi功能。本章我们具体分析各部分的设计。
Wi-Fi部分
在渗透场景下,植入了硬件设备,过几天又回来取,可能会使您锒铛入狱。如果键盘记录器带有Wi-Fi功能,就能在远程读取键盘记录了,甚至可以配置它连接到目标办公室的Wi-Fi,直接把键盘记录传回攻击者的控制服务器。
通过Wi-Fi读取记录
Wi-Fi部分,我们使用著名的ESP8266芯片——廉价而功能强大的Wi-Fi SOC,广泛应用在物联网领域。本文中使用了ESP8266-07S模块,它非常小,而且引出了常用的引脚,可以满足本文所需。
ESP8266-07S模块
键盘记录部分
首先需要CH9350芯片,用于将HID协议转换为UART协议,以便分析记录键盘数据。后端的数据分析和记录在ESP8266上实现。
CH9350
CH9350是南京沁恒微公司生产的USB键鼠转串口通讯控制芯片,它可以将HID协议和UART协议互相转换,而且完成度很高,开发简单。
我们将要使用CH9350将USB键盘的HID协议转为UART协议,使用ESP8266解析和记录键盘输入内容,并且提供WI-FI访问功能。
电路整体设计
整个电路的原理图如图所示:
原理图
左下角是电源模块,由于ESP8266需要3.3V的供电,USB接口是5V的供电,因此使用AMS1117-3.3芯片进行转换。
正下方是ESP8266-07S模块,我们使用它UART接口的RX(接收端)来接收CH9350发出的数据。它连接到键盘端CH9350 UART的TX(发送端),“旁听”CH9350之间的通讯。
这样还有一个好处:键盘记录器的分析模块站在了“旁观者”的角度,即使它出现了解析速度慢,甚至宕机的情况,也不会对键盘产生任何影响。
正中央的两颗芯片是CH9350。根据官方文档,使用两颗CH9350分别作为连接键盘的下位机和连接电脑的上位机,统一使用3.3V供电。
两侧是USB接头和母座,用于插入电脑的USB接口,和连接USB键盘。
固件设计
具体的键盘数据解析、数据存储、Wi-Fi功能,需要我们在ESP8266模块中编写相关程序,也就是固件。
ESP8266支持通过Arduino开发,这为我们的固件开发提供了便利,因此本文在Arduino环境下完成开发。
ESP8266的固件,需要实现:
通过UART串口读取CH9350之间的键盘数据,并进行解析。
将数据储存进SPIFSS中,并提供读取和清空的功能。
提供通过Wi-Fi查看记录内容的功能
上电后,两颗CH9350会自动协商进入“模式1”,在UART接口上传输多种数据帧。具体的过程和数据帧信息,请查阅官方文档。其中我们需要的是“有效键值帧”,它包含了用户在键盘上按下的按键信息。其格式如下:
有效键值帧
由于我们截取的是USB键盘的数据,帧格式一般是这样的:
57AB 83 0C 12 01 00 00 04 00 00 00 00 00 12 17 //A键被按下
57AB 83 0C 12 01 00 00 00 00 00 00 00 00 13 14 //按键被放开
前面的6位固定,接下来的8位是标准的USB键盘数据,最后两位是序列号和校验。
前6位我们可以作为识别有效键值帧的特征,接下来读取后8位即可得到击键信息。
具体的数据表请参考USB HID Usage Table,连接在文末。
Arduino中,实现识别有效键值帧的示例代码如下:
void loop() {
while (Serial.available() > 0) { //串口缓冲区有数据
if (Serial.read() == 0x83){ //帧的第二位 83 是第一个特征
delay(10); //适当延迟,等待后续数据到达串口缓冲区
if (Serial.read() == 0x0C){
delay(10);
if (Serial.read() == 0x12){
delay(10);
if (Serial.read() == 0x01){
//此处读取8位键盘数据
}
}
}
}
}
}
ESP8266模块通过连接到上位机的CH9350的TX端口,接收键盘数据帧。并将其解码为按键信息。接下来将获得的数据保存在SPIFSS中。
SPIFSS(Serial Peripheral Interface Flash File System)是ESP8266模块自带的一个闪存,它的数据在断电后也不会丢失。ESP8266-07S模块中,这个闪存的大小为4M,足够我们保存相当多的键盘记录了。
通过FS.h我们可以对SPIFSS进行读取和修改,示例代码如下:
#include <FS.h>
File logFile; //创建文件对象
void setup() {
SPIFFS.begin();
logFile = SPIFFS.open("/keyLog.txt", "a+"); //打开一个文件
dataFile.println("Some Data Here,Maybe Keylog"); //写入数据
dataFile.close();
}
最后是Wi-Fi部分:创建一个Wi-Fi网络,攻击者连接后可以查看或清空键盘记录。这里参考了wifi_keylogger的部分思路,示例代码如下:
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
const char *ssid = "USBKeylogger"; //创建的接入点的名称
const char *password = "12345678"; //接入点的密码
AsyncWebServer server(80); //在80端口开启服务(ip为192.168.4.1)
void setup() {
WiFi.mode(WIFI_STA); //Wi-Fi为接入点模式
WiFi.softAP(ssid,password); //开启Wi-Fi
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ //当访问根目录时显示记录内容
request->send(SPIFFS, "/keyLog.txt", "text/plain");
});
server.on("/clear", HTTP_GET, [](AsyncWebServerRequest *request){ //当访问“/claer”时清空已有记录
logFile.close();
logFile = SPIFFS.open("/keyLog.txt", "w");
request->send(200, "text/plain", "Log File Cleared!");
});
server.begin(); //开启服务器
}
三者结合就是USBKeylogger的全部代码了。完整的固件源代码,可以在文末给出的链接处下载。
四、硬件制作
PCB设计与生产
为了将理论转为现实,我们要将原理图转换为PCB,并进行Layout。这里使用了立创EDA进行制作。
具体的Layout过程,受限于篇幅,在此不做叙述。笔者的PCB设计如图所示:
PCB设计(未显示铺铜)
USBKeylogger的原理图、PCB设计都是开源的,工程链接在文末可以获取。如果您希望参考、二次开发或者直接生产,欢迎fork笔者的项目。
完成设计后,将PCB工程导出为Gerber文件,提交给PCB生产厂商,即可投入生产。
您可以自行选择国内的打样厂,常见的有嘉立创、捷配、华强PCB等。现在国内PCB工业已经发达到了恐怖的地步:这种小的双层板,打样5张价格在5-30元左右,而且可以在2-3天内到货。
这里笔者选择了嘉立创。相关的生产参数如图所示:
生产参数
提交订单后,如果没有要求特殊工艺和杂色,一般48小时内就能拿到成品。生产出来的PCB是这样的:
PCB
烧录固件
您可能觉得下一步是焊接元器件了?还得等等,在焊接之前,我们首先需要烧录ESP8266的固件。
请注意ESP8266模块必须先烧写固件,再焊接到PCB上。否则要先断开ESP8266的RX触点和PCB的连接才可正常烧录,有亿点点麻烦。
烧录需要使用USB2TTL模块,淘宝买块CH340什么的就好,大概6块钱。
USB2TTL模块
烧录的方法是,将ESP8266的TXD0、RXD0、VCC、GND、GPIO0连接到USB2TTL上。连接方法如下:
ESP8266模块 |
USB2TTL模块 |
TXD0 |
RX |
RXD0 |
TX |
VCC |
3V3 |
GND |
GND |
GPIO0 |
GND |
ESP8266模块和USB2TTL应该如图所示接线(注意看线的颜色):
ESP8266模块的引线
USB2TTL模块的接线
(这里讲个坑,ESP-07和ESP-07S的区别不止在天线。两者的烧录方法完全不同,ESP-07S的针脚有内置的上/下拉电阻,只需要拉低GPIO0即可下载。但是ESP-07没有,需要手动连接。笔者最开始的板子还画错了。)
连接完成后,将USB2TTL连接到电脑。
烧录还需要安装Arduino环境,网上下载即可,比较简单这里不做赘述。麻烦的部分是要安装ESP8266的扩展,笔者这里的网络环境,相关的链接会被404,需要科学上网。
具体方法是,打开USBKeylogger的固件源码(文末有下载链接)。在进入了Arduino IDE后,点击“文件-首选项”,在“附加开发板管理器网址”中输入:
http://arduino.esp8266.com/stable/package_esp8266com_index.json
首选项
保存后打开“工具-开发板-开发板管理器”,在“贡献”类型中找到“esp8266”,点击安装
开发板管理器
现在您应该可以在“工具-开发板”中找到“Generic ESP8266 Module”。选择它,并将其它设置(如Flash Size等)调整到如下图所示:
开发板设置
最后,在端口菜单中,选择USB2TTL的COM口(绝对不是COM1,可能是COM3、COM4等),然后点击“项目-上传”,将代码烧录到开发板上。这个过程需要2-3分钟,如果您看到了以下的调试信息,说明固件已经烧录成功。
固件烧录成功
元件焊接
接下来是板上元器件的焊接,相关的BOM(物料清单)如下:
名称 |
编号 |
封装 |
单价(元) |
数量 |
CH9350L |
U1、U2 |
LQFP-48 |
14 |
2 |
电容100nF |
C1、2、3、4 |
C0603 |
4(100个) |
4 |
电容1uF |
C5、C6 |
C0603 |
5(100个) |
2 |
ESP-07S |
U4 |
|
8.5 |
1 |
AMS1117-3.3 |
U3 |
|
0.5 |
1 |
USB母座 |
USB1 |
USB-A |
0.2 |
1 |
USB插头 |
USB2 |
USB-A |
0.2 |
1 |
单成品成本:39元左右 |
焊接需要用到电烙铁、松香、锡丝和高温海绵。因为要焊接针脚较为密集的CH9350L,建议使用刀头的烙铁头。这一套下来大概在60元左右。
烙铁可以融化锡丝,用于焊接各项元器件。松香可以还原被长时间高温氧化的锡,高温海绵沾水后可以清理烙铁头。
笔者使用的是黄花907烙铁配合刀头。这款烙铁价格适中,可以调温,可以更换烙铁头,寿命较长。配合上面的几个工具,可以焊接大部分常见的元器件了。
黄花907烙铁和刀头
至于焊接的具体方法,仅凭笔者言语难以表达。如果您想要学习,在B站或者其它视频网站,可以找到相当多的视频教程,还有焊接特定元器件的技巧教程。
一点技巧:
焊接的顺序最好是CH9350-AMS1111-电容-USB插接件-ESP8266模块。ESP8266一定要先烧录。
焊接CH9350模块只需要很少的一点锡,配合比较多的松香。刀头贴到一侧的全部引脚,向外,或者向一侧拖过去,这个过程强迫症看得十分舒适。
这款烙铁最高可以开到400°,可以但没必要,太高温锡很容易氧化。一般250-300°足够。
焊接完后的黑色松香渍,拿小刀划碎,棉签蘸酒精就可以清理干净。
焊接好的成品是这样的:
成品
所有配件安装完成后,您可以视需求安装ESP8266-07S的天线,因为其自带的天线信号一般,距离不是很远。
五、测试
到现在,您已经得到了成品的USBKeylogger,将它安装在受害者电脑背后的USB接口上,连接上键盘,它就会记录下受害者的所有键盘记录了。
连接示意图
当它安装好后,应该可以搜索到一个名为“USBKeyLogger”的Wi-Fi网络,密码为“12345678”。(名称和密码可以在固件源码中修改)
Wi-Fi列表
接下来,打开浏览器,访问http://192.168.4.1/,就可以看到所有的键盘记录了。
查看记录内容
访问http://192.168.4.1/clear/,可以清空已保存的记录。
六、总结与更多
本文基本上实现了硬件键盘记录器的设计与生产。这个东西其实很久之前笔者就有所耳闻,但是实际的制作过程,还是和笔者想象的略有不同。
这个东西还可以有更多的优化,例如修改PCB设计,将其植入键盘的塑料外壳。或是换用其它的芯片,节约成本(例如CH376,但是那样代码量会大非常多)。
而且,现在它的固件还较为“简陋”,笔者未来将会继续开发。本项目已经开源,也欢迎您为其添砖加瓦!
附件和参考资料
USBKeylogger原理图、PCB、固件:https://oshwhub.com/PushEAX/USBKeylogger
CH9350官方资料和文档:http://www.wch.cn/products/CH9350.html
ESP8266-07S手册:http://wiki.ai-thinker.com/_media/esp8266/a000um00a3.pdf
HID Usage Tables:
https://usb.org.10-1-108-210.causewaynow.com/sites/default/files/hut1_12.pdf
SPIFFS操作介绍
http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/spiffs/spiffs-operation/