0x01 前言 在日常对设备进行安全测试的过程中,可能会遇到需要频繁的手动输入密码情况,比如在对智能设备的人脸生物识别研究工作中的时候,发现设备的人脸解锁失败几次之后,就需要人工手动的去输入设备锁屏密码。为了解决这个问题,还专门去参观了那些制作仿真人脸头模绕过手机人脸识别厂商的实验室,发现虽然他们可以自动化的设置人脸生物识别实验室环境的亮度,头模角度,光线。但依旧没有解决每几次识别失败就需要输入密码以开启设备的步骤,非常影响效率和测试自动化的效果,因此需要一种能自动化输入设备锁屏密码的解决办法。
于是偶然在一则报道中,看到有人用一个特别小巧的,和硬币一般大小的开发板来爆破一些移动应用安全设置中的锁定密码,比如私密相册等,经过简单的检索之后,了解到是Digispark,那么这个廉价的板子可以用于解决人脸解锁失败后需要手动输入密码的问题。只要思想不滑坡,方法总比困难多。
0x02 关于Digispark Digispark是一种基于ATtiny85微控制器的微型开发板,通常用于创建小型嵌入式项目和原型设计。它由Digistump公司推出,是一个低成本、小巧的开发工具,适用于简单的电子项目、物联网设备、小型自动化等应用。 https://github.com/matteocelani/Digispark
Digispark开发板的特点包括:
微型尺寸: Digispark非常小巧,形状大小尺寸类似于一个USB插头,可以方便地连接到计算机或其他设备。
基于ATtiny85: Digispark使用了ATtiny85微控制器,具有8KB的闪存和512字节的SRAM,适合一些小规模项目。
USB接口: Digispark通过USB接口进行供电和通信,可以作为USB设备与计算机通信,也可以通过USB进行编程。
Arduino编程语言和库来开发项目。
开源: Digispark的设计是开源的,用户可以访问其GitHub仓库获取相关资料和资源。
适用于简单项目: 由于资源有限,Digispark适用于一些较为简单的嵌入式项目,例如小型传感器应用、自动化控制等。
Digispark 开发板 在淘宝里买来只需要要几十块钱,就可以拥有它,如下图所示:
另外对于PC或者手机来说,USB 设备的接入是不需要认证都可以用的,因此可以使用Digispark 来模拟鼠标和键盘做一些力所能及的事情。
搭建环境 系统: windows10 软件: Arduino 18.05
1、下载Digispark 兼容板的描述文件:http://digistump.com/package_digistump_index.json 直接在“首选项” – > “开发板管理器网址”的输入框中填入上面的URL。
然后下载开发板需要的包 在上方的菜单中找到工具->开发板->开发板管理器,在“类型”下选择“贡献”一栏,下载并安装下图中所示的包“Digistmup AVR Boards”。注意:下载时请科学上网, 否则速度可能会很慢。
下载驱动https://link.zhihu.com/?target=https%3A//github.com/digistump/DigistumpArduino/releases/download/1.6.7/Digistump.Drivers.zip 然后插上板子,在设备管理器中可以看到开发板
代码上传的时候,当出现整个的时候,记得要热插拔一次(热插拔就是物理上拔出来然后插进去)
Digispark 键盘库使用 当你正常将环境搭建完毕之后,可以在 DigiKeyboard.h中看到有关键盘的API 函数以供使用。但常见的API 如下。
API 函数原型 delay() 函数 void delay(long milli) 延迟,毫秒为单位
sendKeyStroke() 函数 void sendKeyStroke(byte KeyStroke) 发送按键并释放
void sendKeyStroke(byte KeyStroke, byte modifiers) 发送带有关联按键和释放,第一个参数是主键,第二个按键是组合键。
sendKeyPress() 函数 void sendKeyPress(byte KeyPress) 发送按键但不释放,若要释放再次调用此函数并参数KeyPress =0
void sendKeyPress(byte KeyPress, byte modifiers) 发送带有关联按键,但不释放,若要释放需再次调用此函数并且参数KeyPress = 0
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include "DigiKeyboard.h" # 打开微信输入 void setup () { DigiKeyboard.delay(2000 ); DigiKeyboard.sendKeyStroke(KEY_W,MOD_ALT_LEFT); DigiKeyboard.delay(300 ); DigiKeyboard.println("helloworld " ); } void loop () { }
键盘键码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 键 键码 A 65 B 66 C 67 D 68 E 69 F 70 G 71 H 72 I 73 J 74 K 75 L 76 M 77 N 78 O 79 P 80 Q 81 R 82 S 83 T 84 U 85 V 86 W 87 X 88 Y 89 Z 90 0 48 1 49 2 50 3 51 4 52 5 53 6 54 7 55 8 56 9 57 回车键 13 制表键 9 空格键 32 退格键 8 删除键 46 逗号键 44 句点键 46 上箭头键 38 下箭头键 40 左箭头键 37 右箭头键 39 功能键 F1 112 功能键 F2 113 功能键 F3 114 功能键 F4 115 功能键 F5 116 功能键 F6 117 功能键 F7 118 功能键 F8 119 功能键 F9 120 功能键 F10 121 功能键 F11 122 功能键 F12 123 ----------------------------------------- - `KEY_ENTER`: 回车键 - `KEY_TAB`: 制表键 - `KEY_ESC`: Esc键 - `KEY_SPACE`: 空格键 - `KEY_BACKSPACE`: 退格键 - `KEY_DELETE`: 删除键 - `KEY_ARROW_UP`: 上箭头键 - `KEY_ARROW_DOWN`: 下箭头键 - `KEY_ARROW_LEFT`: 左箭头键 - `KEY_ARROW_RIGHT`: 右箭头键 - `KEY_F1` 到 `KEY_F12`: 功能键 F1 到 F12
模拟键盘输入(用于手机) 首先对于手机来说,真实键盘按键输入密码的顺序如:
space – space — 密码 — enter —密码 — enter
实现代码,实际使用的时候,需要根据每次人脸识别模糊测试的时间间隔来判定大概多长时间输入一次正确密码,然后将具体的逻辑放到 loop 作用域中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include "DigiKeyboard.h " void setup () { DigiKeyboard.delay (2000 ); DigiKeyboard.sendKeyStroke (KEY_SPACE); DigiKeyboard.delay (300 ); DigiKeyboard.sendKeyStroke (KEY_SPACE); DigiKeyboard.delay (300 ); DigiKeyboard.println ("1234 "); DigiKeyboard.delay (300 ); DigiKeyboard.println ("2345 "); DigiKeyboard.delay (300 ); DigiKeyboard.println ("9876 "); DigiKeyboard.sendKeyStroke (KEY_ENTER); } void loop () { }
参考:打造廉价橡皮鸭 https://cloud.tencent.com/developer/article/1358453
模拟鼠标滑动和点击 我一个朋友问我如何给他女朋友的直播间不停的刷赞,于是我想到了Digispark, 同样的,在Digispark 库中也有对鼠标支持的API,并且实现功能的思路一样简单。
模拟鼠标https://blog.csdn.net/bjbz_cxy/article/details/120322499
有关鼠标的API 再DigiMouse.h 中 其中的readme 阐述了mouse 的代码主要借鉴了Digispark键盘库以及Raphaël Assénat使用atmega8作为任天堂Gamecube/N64控制器到USB桥接器的代码:http://www.raphnet.net/electronique/gc_n64_usb/index_en.php ,以及康奈尔大学的Yiyin Ma和Abby Lin的工作 https://instruct1.cit.cornell.edu/courses/ee476/FinalProjects/s2007/ayl26_ym82/ayl26_ym82/index.htm
其中提供可以模拟鼠标操作的API 有如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 class DigiMouseDevice { public : DigiMouseDevice () { rt_usbHidReportDescriptor = mouse_usbHidReportDescriptor; rt_usbHidReportDescriptorSize = sizeof (mouse_usbHidReportDescriptor); rt_usbDeviceDescriptor = usbDescrDevice; rt_usbDeviceDescriptorSize = sizeof (usbDescrDevice); } void begin () { cli (); usbDeviceDisconnect (); _delay_ms(200 ); usbDeviceConnect (); usbInit (); sei (); last_report_time = millis (); } void refresh () { update (); } void poll () { update (); } void update () { usbPoll (); unsigned long time_since_last_report = millis () - last_report_time; if (time_since_last_report >= (idle_rate * 4 )) { last_report_time += idle_rate * 4 ; must_report = 1 ; } if (memcmp (last_built_report, last_sent_report, REPORT_SIZE)) { must_report = 1 ; } if (must_report) { if (usbInterruptIsReady ()) { must_report = 0 ; buildReport (reportBuffer); clearMove (); usbSetInterrupt (reportBuffer, REPORT_SIZE); } } } void delay (long milli) { unsigned long last = millis (); while (milli > 0 ) { unsigned long now = millis (); milli -= now - last; last = now; update (); } } void moveX (char deltaX) { if (deltaX == -128 ) deltaX = -127 ; last_built_report[1 ] = *(reinterpret_cast <unsigned char *>(&deltaX)); } void moveY (char deltaY) { if (deltaY == -128 ) deltaY = -127 ; last_built_report[2 ] = *(reinterpret_cast <unsigned char *>(&deltaY)); } void scroll (char deltaS) { if (deltaS == -128 ) deltaS = -127 ; last_built_report[3 ] = *(reinterpret_cast <unsigned char *>(&deltaS)); } void move (char deltaX, char deltaY, char deltaS) { if (deltaX == -128 ) deltaX = -127 ; if (deltaY == -128 ) deltaY = -127 ; if (deltaS == -128 ) deltaS = -127 ; last_built_report[1 ] = *(reinterpret_cast <unsigned char *>(&deltaX)); last_built_report[2 ] = *(reinterpret_cast <unsigned char *>(&deltaY)); last_built_report[3 ] = *(reinterpret_cast <unsigned char *>(&deltaS)); } void move (char deltaX, char deltaY, char deltaS, char buttons) { if (deltaX == -128 ) deltaX = -127 ; if (deltaY == -128 ) deltaY = -127 ; if (deltaS == -128 ) deltaS = -127 ; last_built_report[0 ] = buttons; last_built_report[1 ] = *(reinterpret_cast <unsigned char *>(&deltaX)); last_built_report[2 ] = *(reinterpret_cast <unsigned char *>(&deltaY)); last_built_report[3 ] = *(reinterpret_cast <unsigned char *>(&deltaS)); } void rightClick () { last_built_report[0 ] = MOUSEBTN_RIGHT_MASK; } void leftClick () { last_built_report[0 ] = MOUSEBTN_RIGHT_MASK; } void middleClick () { last_built_report[0 ] = MOUSEBTN_RIGHT_MASK; } void setButtons (unsigned char buttons) { last_built_report[0 ] = buttons; } void setValues (unsigned char values[]) { memcpy (last_built_report, values, REPORT_SIZE); } };
关于在Arduino中使用这个代码,像使用其他库一样#include “DigiMouse.h”。