暴力改造汽车遥控钥匙为手机APP控制
本帖最后由 HuaShine2015 于 2016-5-26 20:58 编辑前言:
免滚码破解,无需拆装,手机APP作为车门遥控钥匙。
屌丝车怎样简单粗暴的实现某V品牌汽车高大上B格,拎包入住步骤如下。
http://player.youku.com/player.php/sid/XMTU4NDcwNjg4OA==/v.swf
http://player.youku.com/player.php/sid/XMTU4NDcxMTU1Ng==/v.swf
主题:
这是本人代步小破车遥控钥匙原来的样子
(表和我说射频破解MCU加RF模块模拟啥啥的,现在遥控器都滚码433M哦,还双向验证。撇开破解难度不谈,你要是让你老婆知道你折腾半夜就为破解滚码这破玩意,估计得罚洗尿布半年)
然后加上翅膀配上航弹
配齐主要机组人员
准备起飞
背景:
原理图概述
模块特性
使用的TI公司CC254X平台BLE蓝牙模块DX-BT05,内部封装的固件版本较简陋(此模块未过MFi认证的)。 MCU使用pro mini
系统特性
软件流程图
MCU端代码
//2016-5-26 create by Shine.Hua
#include <Enerlib.h>
#include <EEPROM.h>
#define HWRSTPIN 7
#define LOCKPIN 4
#define UNLOCKPIN 5
#define DEFAULTPIN 6
#define DETECTPIN 2
#define MCULED 13
struct CellObject {
char mac0;
char mac1;
char mac2;
char pin;
};
Energy energy;
CellObject cob;
String pin_type = "AT+TYPE0";
String inputString = "";
boolean stringComplete = false;
boolean license = false;
boolean sts = false;
const unsigned long WAIT_TIME1 = 120000;
const unsigned long WAIT_TIME2 = 25000;
const unsigned long WAIT_TIME3 = 200000;
unsigned long connStop = 0;
unsigned long mcuSleep = 0;
CellObject get_Conn() {
CellObject getvaul;
EEPROM.get(0, getvaul);
return getvaul;
}
void set_Conn(CellObject setVar) {
EEPROM.put(0, setVar);
EEPROM.put(512, 1);
}
void clrEEPROM() {
for (int i = 0 ; i < EEPROM.length() ; i++) {
EEPROM.write(i, 0);
}
}
void default_set() { //MCU烧录后EEPROM均是清空状态,所以此函数功能是保留至少要能保存设置一个可以连接的MAC,能让手机APP连接后再修改
clrEEPROM();
delay(1000);
CellObject defaultVar = {
"", //发现官方EEPROM库函数有bug,创建对象时第一个属性值读写不全。此处创建结构体类时,第一个属性留空
"008012345678",
"EA3146CE9FF7",
"000000"
};
pin_type = "AT+TYPE0";
set_Conn(defaultVar);
root_bt();
}
void bt_hw_rst() { //蓝牙模块连接以后自动切换到透传模式,此时无法接收AT指令
digitalWrite(HWRSTPIN, HIGH); //所以此处使用切换蓝牙HW_RST PIN状态来强制断开蓝牙连接恢复到AT指令模式
delay(1500);
digitalWrite(HWRSTPIN, LOW);
delay(3500);
wakeup_bt();
sleep_bt();
}
void bt_sf_rst() {
Serial.println("AT+RESET\r");
delay(2500);
}
void sleep_bt() {
Serial.println("AT+SLEEP\r");
delay(1000);
}
void wakeup_bt() {
for (int i = 0; i <= 12; i++) {
Serial.print("WAKEUPBT");
}
Serial.println("\r");
delay(1500);
}
void root_bt() { //设置蓝牙模块
while (true) {
digitalWrite(MCULED, !digitalRead(MCULED));
if (digitalRead(DETECTPIN) == LOW) {
delay(30);
if (digitalRead(DETECTPIN) == LOW) {
break;
}
}
delay(250);
}
digitalWrite(MCULED, HIGH);
wakeup_bt();
//Serial.println("AT+NAMELIFAN320\r");
//delay(600);
Serial.print(pin_type); Serial.println("\r");
delay(500);
cob = get_Conn();
Serial.print("AT+PIN"); Serial.print(cob.pin); Serial.println("\r");
delay(800);
Serial.println("AT+ROLE0\r");
delay(500);
Serial.println("AT+NOTI1\r");
delay(500);
Serial.println("AT+NOTP1\r");
delay(500);
Serial.println("AT+IMME0\r");
delay(500);
Serial.println("AT+PWRM0\r");
delay(1000);
bt_sf_rst();
digitalWrite(MCULED, LOW);
}
void ctrl_login() { //控制MCU是否可以休眠
if (digitalRead(DETECTPIN) == LOW) {
delay(30);
if (digitalRead(DETECTPIN) == LOW) {
delay(30);
if (digitalRead(DETECTPIN) == LOW) {
sts = false;
license = false;
mcu_sleep();
}
}
}
}
void ctrl_timeout() { //连接超时控制
unsigned long currentMillis = millis();
if (digitalRead(DETECTPIN) == HIGH) {
delay(30);
if (digitalRead(DETECTPIN) == HIGH) {
delay(30);
if (digitalRead(DETECTPIN) == HIGH) {
if ( (license == false) && (currentMillis - connStop >= WAIT_TIME2)) {
connStop = currentMillis;
Serial.println("timeout1");
bt_hw_rst();
} else if (license == true && (currentMillis - connStop >= WAIT_TIME1) && stringComplete != true && (!Serial.available())) {
connStop = currentMillis;
Serial.println("timeout2");
bt_hw_rst();
}
}
}
}
}
void mcu_sleep() { //MCU休眠代码
unsigned long currentMillis = millis();
if (currentMillis - mcuSleep >= WAIT_TIME3) {
mcuSleep = currentMillis;
Serial.println("mcuslp");
wakeup_bt();
sleep_bt();
energy.PowerDown();
}
}
void base_case() { //业务主体代码
if (stringComplete) {
if (digitalRead(DETECTPIN) == HIGH) {
if (inputString.endsWith("close#") && license == true) {
connStop = millis(); //
mcuSleep = millis(); //
digitalWrite(LOCKPIN, HIGH);
delay(1100);
digitalWrite(LOCKPIN, LOW);
Serial.println("off");
} else if (inputString.endsWith("open#") && license == true) {
connStop = millis(); //
mcuSleep = millis(); //
digitalWrite(UNLOCKPIN, HIGH);
delay(1100);
digitalWrite(UNLOCKPIN, LOW);
Serial.println("on");
} else if (inputString.endsWith(";") && license == true) {
connStop = millis(); //
mcuSleep = millis(); //
cob = get_Conn();
String temp = inputString.substring((inputString.indexOf(';') - 6), inputString.indexOf(';'));
for (int i = 0; i < temp.length(); i++) {
cob.pin = temp;
}
Serial.println(cob.pin);
set_Conn(cob);
root_bt();
} else if (inputString.endsWith("admin#") && license == true) {
connStop = millis(); //
mcuSleep = millis(); //
Serial.print("{\"user1\":\"");Serial.print(cob.mac1);Serial.print("\",\"user2\":\""); //返回JSON格式
Serial.print(cob.mac2);Serial.print("\",\"PIN\":\"");Serial.print(cob.pin);Serial.print("\"}");
} else if (inputString.endsWith("}") && license == true) {
connStop = millis(); //
mcuSleep = millis(); //
cob = get_Conn();
String temp = inputString.substring((inputString.indexOf('}') - 12), inputString.indexOf('}'));
for (int i = 0; i < temp.length(); i++) {
cob.mac1 = temp;
}
Serial.println(cob.mac1);
set_Conn(cob);
} else if (inputString.endsWith("]") && license == true) {
connStop = millis(); //
mcuSleep = millis(); //
cob = get_Conn();
String temp = inputString.substring((inputString.indexOf(']') - 12), inputString.indexOf(']'));
for (int i = 0; i < temp.length(); i++) {
cob.mac2 = temp;
}
Serial.println(cob.mac2);
set_Conn(cob);
} else if (inputString.endsWith("skoff#") && license == true) {
connStop = millis(); //
mcuSleep = millis(); //
pin_type = "AT+TYPE0";
Serial.println(pin_type);
root_bt();
} else if (inputString.endsWith("skon#") && license == true) {
connStop = millis(); //
mcuSleep = millis(); //
pin_type = "AT+TYPE3";
Serial.println(pin_type);
root_bt();
} else if (license == false) {
Serial.println("ghost");
}
}
inputString = "";
stringComplete = false;
}
delay(50);
}
void wakeISR() { //唤醒后执行代码
if (energy.WasSleeping()) {
digitalWrite(MCULED, HIGH);
Serial.println("mcuwk");
connStop = millis();
mcuSleep = millis();
delay(1000);
digitalWrite(MCULED, LOW);
} else {
}
}
void setup() { //MCU初始化
digitalWrite(HWRSTPIN, LOW);
digitalWrite(DEFAULTPIN, HIGH);
digitalWrite(LOCKPIN, LOW);
digitalWrite(UNLOCKPIN, LOW);
pinMode(HWRSTPIN, OUTPUT);
pinMode(DEFAULTPIN, OUTPUT);
pinMode(DETECTPIN, INPUT_PULLUP);
pinMode(LOCKPIN, OUTPUT);
pinMode(UNLOCKPIN, OUTPUT);
pinMode(MCULED, OUTPUT);
digitalWrite(HWRSTPIN, LOW);
digitalWrite(DEFAULTPIN, HIGH);
digitalWrite(LOCKPIN, LOW);
digitalWrite(UNLOCKPIN, LOW);
digitalWrite(MCULED, LOW);
Serial.begin(9600);
inputString.reserve(200);
if (digitalRead(DEFAULTPIN) == LOW) {
delay(20);
if (digitalRead(DEFAULTPIN) == LOW) {
default_set();
}
}
if (EEPROM.read(512) != 1) {
default_set();
}
attachInterrupt(0, wakeISR, RISING);
}
void loop() { //主循环代码
base_case();
ctrl_login();
ctrl_timeout();
delay(500);
}
void serialEvent() { //串口事件响应代码
cob = get_Conn();
char str;
int idx = 0;
boolean mc1 = false;
boolean mc2 = false;
boolean back = true;
while (Serial.available()) {
char inChar = (char)Serial.read();
inputString += inChar;
if (inputString.indexOf('x') != -1 && idx < 13 && sts == false) {
str = inChar;
}
if (idx >= 13 && sts == false) {
mc1 = true;
mc2 = true;
/*for (int i = 0; i < 12; i++) {
Serial.print(cob.mac1);
Serial.print("-");
}
Serial.println();
for (int i = 0; i < 12; i++) {
Serial.print(cob.mac2);
Serial.print("+");
}
Serial.println();
for (int i = 0; i < 6; i++) {
Serial.print(cob.pin);
Serial.print("*");
}*/
for (int i = 0; i < 12; i++) {
if (cob.mac1 != str) {
mc1 = false;
break;
}
}
for (int i = 0; i < 12; i++) {
if (cob.mac2 != str) {
mc2 = false;
break;
}
}
if (mc1 == true || mc2 == true) {
license = true;
sts = true;
} else if((mc1 == true || mc2 == true)&&(back == true)) {
Serial.print("login:");
for (int i = 0; i < 12; i++) {
Serial.print(str);
}
Serial.println();
back = false;
}
}
if ((inChar == '#') || (inChar == '}')
|| (inChar == ']') || (inChar == ';')) {
stringComplete = true;
}
}
}
MCU端封装的软件接口明细
手机APP端UI
使用BLE GATT协议通讯,代码见所附下载地址,不详述
附言:
1.如需实践,切记关机后充电,也就是断开输出负载
其实供电部分可以用MOS管加Attiny控制来实现和手机一样的开机充电
2.此蓝牙模块有几个bug
--和IOS系统可以正常连接和GATT协议通讯,但应该是未过MFi认证的原因,底层固件无权限取得IOS端设备MAC。
此时会用一种随机算法虚拟一个MAC地址抛给MCU,这比较讨厌 。
--此模块固件如设置上电后等待MCU指令模式,MCU给休眠指令后,无法正常休眠。只适合上电自运行模式
3.如不考虑能耗问题,可以使用此蓝牙的主模式,搜索附近指定MAC的RSSI值来判断是否车主接近和离开。
这样可以实现免操作自动开关门,代码实现不难,有兴趣的可以尝试一下。
本文所有源码下载路径
http://pan.baidu.com/s/1eSJNoHk
厂商参考资料下载路径
http://pan.baidu.com/s/1eSJNoHk 土豪,我帮你捡肥皂~ 土豪,我帮你捡肥皂~ 支持支持支持支持 真乃神人也 灰常实用啊!完事具备只欠汽车了:lol 思路决定出路啊!
楼主下次搞个NFC,拍一拍就开门。
页:
[1]