暴力破解算法
可用于如下场景:
1、密码猜测
2、对于罗拉模块的数据请求,当发现模块么有回应数据时,往往考虑是否模块所处位置导致信号无法到达,此时可借助其他模块作为中继来进行通讯。
当然无论用于哪种场景,都需要自己实现代码,本代码只是写出了核心算法。
算法描述:从1位密码开始,或者说从1个中继开始,从数组中获取每一种值,取到最后一个数据后,翻转到第一个值,增加1位,取第一个值。
比如密码组合有[1,2,3,4]四个数字,密码最多4位,那么组合规律如下:
1
2
3
4
11
12
13
14
…
4444
代码如下:
#include <stdio.h> #include <string.h> #include <iostream> #include <string> #include <time.h> using namespace std; typedef unsigned int BOOL; typedef unsigned short u16; #define TRUE 1 #define FALSE 0 #define DEVICE_COUNT 4 // 设备数量 #define MAX_RELAY_NUM 3 // 最大中继数量 int relayNum = 0; // 当前中继数量 int devices[DEVICE_COUNT] = {1,2,3,4}; // 设备地址数组 int relayIndexArr[DEVICE_COUNT] = {0}; // 中继索引数组,存储设备序号,如0,1 int relayDevices[DEVICE_COUNT] = {0}; // 中继数组,存储设备地址,如1,2 /** * @brief 改变中继地址,策略为暴力算法,先尝试1个中继,然后2个,与暴力破解密码是一个逻辑 * * 比如有设备1/2/3/4共4台设备,要访问设备4,但是没返回数据,这时开始中继。 * 首先尝试1个中继,有4种可能:分别为1/2/3/4. * 然后考虑2个中继,有4 * 4 = 16种可能,分别为:11,12,13,14,21,22...,44 * 然而上述排序中应该排除2种情况: * 情况1:中继中不能存在自己; * 情况2:中继中不能重复设备; * 排除的情况单独用函数判断,如果被排除,再获取下一种情况即可。这样做能让改变中继函数变得简单。 * @return BOOL 获取到中继返回TRUE,否则返回FALSE; */ static BOOL ChangeDeviceRelayAddrs() { int relayIndex = relayNum - 1; // 注意数据类型,第一次为-1 while (relayIndex >= 0) { // 所有设备都用过了,返回使用第一个设备作为中继,然后修改前面一个中继设备的地址(前面一个中继的序号加1) // 比如设备1,2,3,4共4台设备,当2个中继时:为14组合,那么下一次应该为21组合。 if (relayDevices[relayIndex] == devices[DEVICE_COUNT - 1]) { relayIndexArr[relayIndex] = 0; relayDevices[relayIndex] = devices[relayIndexArr[relayIndex]]; --relayIndex; continue; } // 当前中继还未达到最后那台设备,修改当前中继为下一台设备,并返回TRUE ++relayIndexArr[relayIndex]; relayDevices[relayIndex] = devices[relayIndexArr[relayIndex]]; return TRUE; } // 循环完成还没有找到有效中继,说明所有中继都已经回滚为第一台设备了,那么中继数量加1。 relayNum++; if (relayNum <= MAX_RELAY_NUM) { relayIndex = relayNum - 1; relayIndexArr[relayIndex] = 0; relayDevices[relayIndex] = devices[relayIndexArr[relayIndex]]; return TRUE; } // 如果已经超过最大中继数量,就将设备重置为无中继状态 memset(relayIndexArr, 0, sizeof relayIndexArr); memset(relayDevices, 0, sizeof relayDevices); relayNum = 0; return TRUE; } /** * @brief 改变中继地址,策略为暴力算法,先尝试1个中继,然后2个,与暴力破解密码是一个逻辑 * * 比如有设备1/2/3/4共4台设备,要访问设备4,但是没返回数据,这时开始中继。 * 首先尝试1个中继,有4种可能:分别为1/2/3/4. * 然后考虑2个中继,有4 * 4 = 16种可能,分别为:11,12,13,14,21,22...,44 * 然而上述排序中应该排除2种情况: * 情况1:中继中不能存在自己; * 情况2:中继中不能重复设备; * 排除的情况单独用函数判断,如果被排除,再获取下一种情况即可。这样做能让改变中继函数变得简单。 * @param deviceIndex 需要中继的设备序号。 * @return BOOL 获取到中继返回TRUE,否则返回FALSE; */ static BOOL IsRelayAddrValid(u16 deviceIndex) { for (int i = 0; i < relayNum; i++) { if (relayIndexArr[i] == deviceIndex) { return FALSE; // 包含了自己 } } for (int i = 0; i < relayNum; i++) { for (int j = i + 1; j < relayNum; j++) { if (relayIndexArr[i] == relayIndexArr[j]) { return FALSE; // 两个中继重复了 } } } return TRUE; } static void PrintRelays(BOOL valid) { if (relayNum == 0) { cout << "无中继" << endl; return; } cout << (valid ? "发现有效中继:" : "无效中继:"); for (int i = 0; i < relayNum; i++) { cout << relayDevices[i]; } cout << endl; } int main(int, char **) { int deviceIndex = 0; do { while (1) { ChangeDeviceRelayAddrs(); if (IsRelayAddrValid(deviceIndex)) { PrintRelays(TRUE); break; } else { PrintRelays(FALSE); } } } while (relayNum != 0); return 0; }