Java教程

暴力破解算法

本文主要是介绍暴力破解算法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

暴力破解算法

可用于如下场景:
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;
}

这篇关于暴力破解算法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!