ctfshow-php特性(web102-web115)

目录

web102

web103

web104

web105

web106

web107

web108

web109

web110

web111

web112

web113

web114

web115


实践是检验真理的 要多多尝试

web102

<?php
highlight_file(__FILE__);
$v1=$_POST['V1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v4=is_numeric($v2)and is_numeric($v3);
if($v4){
	$s=substr($v2,2);#获取字符串从第二个字符开始的子串
	$str=call_user_func($v1,$s);#执行函数 $v1作为函数名 $s作为参数
	echo $str;#输出变量
	file_put_contents($v3,$str);#将数据写文件
}
else{
	die('hacker');
}

首先就是v2必须是全数字的 v3任意

获取v2的第二个字符开始的字串作为$str的值 也就是为了获得正确的payload最前方要填充两个无用字符 从而获得除了前两个无用字符后的有用字符

call_user_func($v1,$s) 可以理解为执行函数 $v1($s) 

也就是说$v1($s)  输出的结果是我们要的payload

知识点

1 php5(php7.1一下)下is_numeric可识别16进制(如果0x开头 就会识别为十六进制字符串 从而绕过),如0x2e,然后调用hex2bin转成字符串写入任意木马

十六进制字符串转换二进制字符串也就是相当于

但是这道题环境用的是php7.0以上的环境所以就不能用0x开头从而绕过is_numeric函数 导致大多

为了能绕过is_numeric函数 目前构造一个很神奇的字符串

5044383959474e6864434171594473

十六进制转换字符串

PD89YGNhdCAqYDs

base64解码

<?=`cat *`;

因为开头不能使用0x所以 目前只有这一个字符串能满足要求 里面的e会被函数当成科学计数法从而绕过死亡函数

但是十六进制转换字符串需要用一个函数 base64解码又要用一个函数 但是题目只有一个函数位置

于是写文件的时候可以通过过滤器来对写的内容进行过滤php://filter/write=convert.base64-
decode/resource=2.php(该过滤器可以在文件操作函数中使用,起到过滤作用)变成了

file_put_contents(php://filter/write=convert.base64-decode/resource=2.php,$str); 

简单解释 将数据$str利用过滤器进行base64解码写入文件2.php中

这样只需要十六进制转换字符串的函数就可以了

访问2.php文件

2 <?=`cat *`;  cat * 是一个shell命令如果一个php文件中存在该内容 它会执行 cat * 命令并将结果输出到页面上

3 等号的优先级大于and

web103

<?php
highlight_file(__FILE__);
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
$v4 = is_numeric($v2) and is_numeric($v3);
if($v4){
    $s = substr($v2,2);
    $str = call_user_func($v1,$s);
    echo $str;
    if(!preg_match("/.*p.*h.*p.*/i",$str)){
        file_put_contents($v3,$str);
    }
    else{
        die('Sorry');
    }
}
else{
    die('hacker');
}

?>

过滤了payload中 php 且不区分大小写 这么一看对我们没影响

尝试一波发现确实没影响  上一道题其实不是那么做的 上一道题就是让你写任意的木马 但是环境配成7.1了 只能按照这道题的方式去做 就算上一题用的5.2版本且也使用者这个正则 写任意木马 也不影响 因为$str是base64编码后的字符串 匹配字符串中存在php的概率很小

web104

<?php
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['v1']) && isset($_GET['v2'])){
    $v1 = $_POST['v1'];
    $v2 = $_GET['v2'];
    if(sha1($v1)==sha1($v2)){
        echo $flag;
    }
}
?>

sha1就是将字符串进行哈希加密使用SHA1的方式

第一种正常解 函数没有判断传参的两个值是否不相等

使v2v1值相等即可 他们的哈希加密值也相等

第二种解法 

这道题和md5加密那道题一样 就i是换了一个函数 

加密函数的参数必须传入字符串 否则函数返回值为false 传入从数组而实现false==false

第三种解法

大佬跑出来的

aaK1STfY
0e76658526655756207688271159624026011393
aaO8zKZF
0e89257456677279068558073954252716165668

在==比较的时候 对字符串形式的数值,PHP 会尝试将其转换为数值类型进行比较恰巧这个payload中除了e全是数字 成功转换为数值类型 0的任意次方还是等于0 所以0==0

web105

<?php
highlight_file(__FILE__);
include("flag.php");
error_reporting(0);#安全级别为0 不输出任何报错信息
$error="你还想要flag嘛";#如果有报错不输出报错语句而输出该语句
$suces="既然你想要就给你吧";
# 遍历变量中的键值对  对于http来说就是遍历传入的参数名以及参数值
foreach($_GET as $key=>$value){
	if($key==='error'){
		die("what are you doing");
	}
	$$key=$$value;#将变量value值作为变量名 
}
foreach($_POST as $key=>$value){
	if($key==='error'){
		die("what are you doing");
	}
	$$key=$$value;
}
if(!($_POST['flag']==$flag)){
	die($error);#输出
}
echo "are you good".$flag."\n"
die($suces);

有个死亡函数 必须让post中的falg参数的值为flag 才能绕过死亡函数 这有点过分了 我要知道那还做啥题了哈哈

$$key=$$value; 很关键 先看GET参数

如果想要获取到flag $value=flag -----$$key=$flag

参数名随便来一个x $key=x  -----$x=$flag

$$key=$$value;  再看POST参数

现在flag值已经存在于$x中了  使$value=x -----$$key=$x

到这我想了好久如何对POST参数进行赋值 他是将post参数遍历存入key中的 反赋值只靠-$$key代表$post['flag']不存在呀

从新审核一下代码 没必要绕过死亡函数 直接让die输出错误error即可

所有让$key=error --------$error=$x

第二种方法

?suces=flag&flag=

这个也比较好理解 先把flag值放入suces中 然后 让$flag=$  php会将$视为空字符串 从而$flag为空

因为post中没有flag参数 所有 post['flag']也为空 

web106

和web104一个样 就是增加了v1!=v2

方法一

传数组 使得函数返回值为false

大佬方法

aaK1STfY
0e76658526655756207688271159624026011393
aaO8zKZF
0e89257456677279068558073954252716165668

web107

<?php
highlight_file(__FILE__);
error_reporting(0);
include("flag.php");
if(isset($_POST['v1'])){
	$v1=$_POST['v1'];
	$v3=$_GET['v3'];
	parse_str($v1.$v2);
	if($v2['flag']==md5($v3)){
		echo $flag;
	}
}

首先我想到 $v2['flag']==md5($v3) 是不可能的 只能让md5返回值为false

在php中未定义的值被转换为布尔值时会被视为 false 所以无需定义v2中的flag即可 但是要注意 必须还要给v1随便传值 否则v2没被定义 就会出现报错等问题

第二种方法 弱类型比较  flag=0  让md5函数返回一个0e开头的即可 这样0=0

GET: ?v3=240610708 POST: v1=flag=0

web108

<?php
highlight_file(__FILE__);
error_reporting(0);
include("flag.php");
if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE)  {
    die('error');

}
//只有36d的人才能看到flag
if(intval(strrev($_GET['c']))==0x36d){#经过反转再转换整形是否等于十六进制的0x36d 也就是877
    echo $flag;
}

?>

intval函数本来想着将十六进制转换十进制可不可以 不可以 必须给定第二个参数intval($str, 16);

ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE) 必须a-z开头 a-z结尾 如果没匹配上 执行语句块

为了让他不执行语句块 只能让他匹配上 a%00778 只能使用截断了 ereg函数就有这个漏洞 识别%00也就是空字符就不往下识别了 从而绕过了死亡函数

经过反转877空字符a 就转换为了877 所以最终能得到flag

知识点:

==弱比较 十进制877和十六进制0x36进行比较的时候 是相等的 因为php会将其中十六进制自动转换为十进制

web109

<?php
highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
    $v1 = $_GET['v1'];
    $v2 = $_GET['v2'];

    if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){
            eval("echo new $v1($v2());");
    }
}

#但是这道题没给类所以要使用内置类
#死记硬背 有个mysqli内置类 用于mysql连接的 需要传递很多参数用于连接数据库 如果这时传递一个函数作为参数 也会执行 比如phpinfo 

这个页面还在加载也就是还在连接数据库中 显然他肯定连接不上

 既然能执行phpinfo 那肯定就能执行system('ls')

知识点system('ls')()()多几个括号不报错

知识点题外话 php可能有很多内置类 在phpinfo中是可以看到的

 exception类也如此 这东西就是死记硬背简单理解就行 记住这个类实例化时传入函数可以被执行 前提是实例化的对象被echo输出

小知识 echo phpinfo() 会输出php信息 不使用echo也可以输出php信息

echo system('ipconfig'); 也是一个道理 不使用echo也是可以将结果输出到页面来

但是字符串必须要echo才能输出到页面来因为出发了tostring 有return的返回值 使用echo输出

这道题弄了将近两个点 很多很多基础知识都是很基础的

web110

<?php
highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
    $v1 = $_GET['v1'];
    $v2 = $_GET['v2'];

    if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v1)){
            die("error v1");
    }
    if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v2)){
            die("error v2");
    }

    eval("echo new $v1($v2());");

}

?>

和上一道题同理 但是传参的时候禁用了很多字符 貌似没影响

尝试一下看看有什么影响

?v1=mysqli&v2=phpinfo 成功

?v1=mysqli&v2=system(ls) 不成功查看后发现禁用了()  

看来条件很苛刻 看来只能使用正常的$v1($v2() 函数调用 只能使用内置类然后无参进行rce

rce远程命令执行

?v1=FilesystemIterator&v2=getcwd

DirectoryInterator:遍历目录的类
FilesystemIterator:遍历文件的类

getcwd函数获取当前目录的路径返回一个字符串

web111

<?php
highlight_file(__FILE__);
error_reporting(0);
include("flag.php");

function getFlag(&$v1,&$v2){
    eval("$$v1 = &$$v2;");
    var_dump($$v1);
}
if(isset($_GET['v1']) && isset($_GET['v2'])){
    $v1 = $_GET['v1'];
    $v2 = $_GET['v2'];

    if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v1)){
            die("error v1");
    }
    if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v2)){
            die("error v2");
    }
    if(preg_match('/ctfshow/', $v1)){
            getFlag($v1,$v2);
    }
}
?>

本来以为没什么难度 正常传值 ?v1=ctfshow&v2=falg 但是输出NULL也就是没有值 这是为什么呢

因为在方法外部进行的文件包含 在方法内部不能直接调用文件包含的文件中的变量的 不光是文件包含的变量 只要是方法外部的变量就不能在方法内使用 除非传参

那就使用全局变量$GLOBALS 将全局变量的所有值赋值给$ctfshow 然后进行输出

知识点 死记硬背即可

1 eval("$$v1 = &$$b;"); 可以

eval("$v1 = &$b;"); 不可以 

ai说是eval函数的原因无法直接处理引用 但是对$$又有特殊规则

2 $GLOBALS 全局变量 是一个数组里面存着所有变量的名和值

web112

<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($file){
    if(preg_match('/\.\.\/|http|https|data|input|rot13|base64|string/i',$file)){
        die("hacker!");
    }else{
        return $file;
    }
}
$file=$_GET['file'];
if(! is_file($file)){
    highlight_file(filter($file));
}else{
    echo "hacker!";
}

有一个判断 参数不能是个文件 这该如何绕过 

直接用过滤器 过滤器不影响 伪协议不影响file_get_contents,和highlight_file。

php://filter/resource=flag.php
php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=flag.php
php://filter/read=convert.quoted-printable-encode/resource=flag.php
compress.zlib://flag.php

web113

和上一题同理就是不能使用filter php过滤器了 

它试图打开并读取经过 zlib 压缩的 flag.php 文件,并返回解压后的内容 不是压缩文件也可以 简单记住就是远程读取文件 是一个伪协议compress.zlib://flag.php 不影响file_get_contents,和highlight_file。

<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($file){
    if(preg_match('/filter|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
        die('hacker!');
    }else{
        return $file;
    }
}
$file=$_GET['file'];
if(! is_file($file)){
    highlight_file(filter($file));
}else{
    echo "hacker!";
} <?php

预期解就是目录溢出
预期解payload:

file=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php

在linux中/proc/self/root是指向根目录的,也就是如果在命令行中输入ls /proc/self/root,显示的内容是根目录下的内容
原理:利用函数所能处理的长度限制进行目录溢出: 原理:/proc/self/root代表根目录,进行目录溢出,超过is_file能处理的最大长度就不认为是个文件了

知识点 highlight_file 不能高亮显示数组

web114

<?php
error_reporting(0);
highlight_file(__FILE__);
function filter($file){
    if(preg_match('/compress|root|zip|convert|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
        die('hacker!');
    }else{
        return $file;
    }
}
$file=$_GET['file'];
echo "师傅们居然tql都是非预期 哼!";
if(! is_file($file)){
    highlight_file(filter($file));
}else{
    echo "hacker!";
}

无法使用目录溢出 禁用了root

无法使用读取压缩文件的伪协议compress.zlib://flag.php

但是发现他并没有禁用filter过滤器 php://filter/resource=flag.php

web115

<?php
include("flag.php");
highlight_file(__FILE__);
error_reporting(0);
function filter($num){
	$num=str_replace("0x","1",$num);
	$num=str_replace("0","1",$num);
	$num=str_replace(".","1",$num);
	$num=str_replace("e","1",$num);
	$num=str_replace("+","1",$num);
	return $num;
}
$num=$_GET['num'];
# 必须是数字或者数字字符串  不能完全等于字符36  函数返回值等于字符36
if(is_numeric($num)and $num!=='36'and trim($num)!=='36'and filter($num)=='36'){
	if($num=='36'){
		echo $flag;
	}
	else{
		echo "hacker";
	}
}
else{
	echo"hacker";
}

%0c36 

is_numeric($num) ‘   36’ 在数字前加空格 也会认为是数字字符串

$num!=='36'  不完全等于‘36’ 因为有个tab

trim($num)!=='36' 去空格 但是不去除%0c

filter($num)=='36' ‘36’与‘    36’ 进行弱类型比较是相等的

知识点

  1. \t 的意思是 :水平制表符。将当前位置移到下一个tab位置。%09

  2. \r 的意思是: 回车。将当前位置移到本行的开头。%0D

  3. \n 的意思是:回车换行。将当前位置移到下一行的开头。%0A

  4. \f的意思是:换页。将当前位置移到下一页的开头。%0C

  5. \0的意思是:空字符 %00

  6. \v的意思是:垂直制表符 和制表符差不多意思%0B

  7. 空格是%20

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

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

相关文章

EMNLP 2023精选:Text-to-SQL任务的前沿进展(下篇)——Findings论文解读

导语 本文记录了今年的自然语言处理国际顶级会议EMNLP 2023中接收的所有与Text-to-SQL相关&#xff08;通过搜索标题关键词查找得到&#xff0c;可能不全&#xff09;的论文&#xff0c;共计12篇&#xff0c;包含5篇正会论文和7篇Findings论文&#xff0c;以下是对这些论文的略…

英语语法之句法(一)

英语语法可能是很多人童年的噩梦&#xff0c;笔者就是其中之一&#xff0c;从小学学到高中&#xff0c;这么多年从来没有理解过英语语法&#xff0c;什么谓语&#xff0c;非谓语&#xff0c;副词&#xff0c;状语&#xff0c;等等概念混淆在一起&#xff0c;傻傻分不清。本来以…

JavaScript 事件循环:Event Loop

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;《爱蹦跶的大A阿》 &#x1f525;当前正在更新专栏&#xff1a;《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》 ​ ​ ✨ 前言 事件循环 是 web 开发中的一个核心概念&#xff0c;它是 JavaScript…

MyBatis篇----第二篇

系列文章目录 文章目录 系列文章目录前言一、MyBatis 框架适用场合二、MyBatis 与 Hibernate 有哪些不同?三、#{}和${}的区别是什么?四、当实体类中的属性名和表中的字段名不一样 ,怎么办?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一…

VScode上无法运行TSC命令,Typescript

如何解决问题 第一步&#xff1a;使用 winx 快捷键&#xff0c;会出现如下弹窗&#xff0c;鼠标左键单击Windows PowerShell 即可打开shell 第二步&#xff1a;运行 set-ExecutionPolicy RemoteSigned 命令&#xff0c;在询问更改执行策略的时候选择敲Y或者A 第三步&#xff…

博途PI控制器(完整SCL代码)

博途PID算法和SCL代码在PID专栏有详细介绍,这里作为参考补充和完善给出稍微不同的写法。给大家作为一个参考。增量式PID详细代码和算法公式可以参看下面链接文章: 博途增量式PID https://rxxw-control.blog.csdn.net/article/details/124363197https://rxxw-control.blog.c…

产品交付双轮驱动思维模型下的思考的研发工具

一、产品交付双轮驱动思维模型 之前读过这样双轮驱动思维模型&#xff0c;其思维模型如下图所示&#xff0c;双轮驱动思维模型是一个产品价值交付模型&#xff0c;总的理念是以“真北业务价值”为导向&#xff0c;以“产品快速交付”为动力&#xff0c;将“业务价值”与“产品…

【51单片机】串口(江科大)

8.1串口通信 1.串口介绍 2.硬件电路 3.电平标准 电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种: 电平标准是数据1和数据O的表达方式,是传输线缆中人为规定的电 压与数据的对应关系,串口常用的电平标准有如下…

GO语言笔记4-标识符、关键字与运算符

标识符 什么是标识符 变量名、方法名等我们起的名字都是标识符 标识符定义规则 字母、数字、下划线组成不可以数字开头&#xff0c;严格区分大小写&#xff0c;不能带有空格&#xff0c;不可以是go的关键字不能单独使用 下划线&#xff0c;因为下划线在GO中是一个特殊标识符&…

Excel一键导入导出-EasyPOI

EasyPOI是一款优秀的开源Java库&#xff0c;专为简化和优化Excel文件的导入导出操作而设计。下面&#xff0c;我会介绍EasyPOI在项目中使用EasyPOI&#xff0c;实现Excel文件的高效操作。帮助读者全面了解和掌握这一工具。 EasyPOI简介 官网&#xff1a; http://www.wupaas.co…

Android实现底部导航栏方法(Navigation篇)

Navigation实现底部导航栏 前言导入和基本使用导入基础使用创建nav文件编辑Nav文件添加页面&#xff08;代码版&#xff09;添加页面&#xff08;图解版&#xff09; 创建导航动作 action创建action&#xff08;代码版&#xff09;创建action&#xff08;图解版&#xff09; 编…

【数据结构】链表OJ面试题3《判断是否有环》(题库+解析)

1.前言 前五题在这http://t.csdnimg.cn/UeggB 后三题在这http://t.csdnimg.cn/gbohQ 记录每天的刷题&#xff0c;继续坚持&#xff01; 2.OJ题目训练 9. 给定一个链表&#xff0c;判断链表中是否有环。 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成…

算法沉淀——链表(leetcode真题剖析)

算法沉淀——链表 01.两数相加02.两两交换链表中的节点03.重排链表04.合并 K 个升序链表05.K个一组翻转链表 链表常用技巧 1、画图->直观形象、便于理解 2、引入虚拟"头节点" 3、要学会定义辅助节点&#xff08;比如双向链表的节点插入&#xff09; 4、快慢双指针…

树状菜单(利用映射-bootstrap+jQuery实现折叠功能)

效果&#xff08;默认全部展开&#xff09;&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><…

一、Docker部署MySQL

Docker部署MySQL 一、安装Docker二、拉取MySQL镜像1.选择拉取版本2.拉取镜像 三、启动MySQL1.确定好挂载目录2.启动3.查看是否启动4.开启远程访问权限 一、安装Docker 安装教程&#xff1a;https://qingsi.blog.csdn.net/article/details/131270071 二、拉取MySQL镜像 1.选择…

【C语言】实现双向链表

目录 &#xff08;一&#xff09;头文件 &#xff08;二&#xff09; 功能实现 &#xff08;1&#xff09;初始化 &#xff08;2&#xff09;打印链表 &#xff08;3&#xff09; 头插与头删 &#xff08;4&#xff09;尾插与尾删 &#xff08;5&#xff09;指定位置之后…

html的格式化标签和图片(img)标签

格式化标签 加粗: strong标签和b标签倾斜: em标签和i标签删除线: del标签和s标签下划线: ins标签和u标签 <strong>stong 加粗</strong><b>b 加粗</b><em>倾斜</em><i>倾斜</i><del>删除线</del><s>删除线…

nodejs学习计划--(十)会话控制及https补充

一、会话控制 1.介绍 所谓会话控制就是 对会话进行控制 HTTP 是一种无状态的协议&#xff0c;它没有办法区分多次的请求是否来自于同一个客户端&#xff0c; 无法区分用户 而产品中又大量存在的这样的需求&#xff0c;所以我们需要通过 会话控制 来解决该问题 常见的会话控制…

论文阅读:GamutMLP A Lightweight MLP for Color Loss Recovery

这篇文章是关于色彩恢复的一项工作&#xff0c;发表在 CVPR2023&#xff0c;其中之一的作者是 Michael S. Brown&#xff0c;这个老师是加拿大 York 大学的&#xff0c;也是 ISP 领域的大牛&#xff0c;现在好像也在三星研究院担任兼职&#xff0c;这个老师做了很多这种类似的工…

苹果Mac键盘如何将 F1 到 F12 取消按Fn

苹果电脑安装了Win10操作系统之后&#xff0c;F1到F12用不了怎么办的解决方法。本文将介绍一些解决方法&#xff0c;帮助您解决无法使用F1到F12功能键的问题。 使用 Mac系统的人都知道&#xff0c;Mac系统默认是没有开启 F1-F12 的使用的&#xff0c;平时我们使用的系统都可以使…
最新文章