How on earth that "master" branch shows RACISM?

On June 12th, 2020, GitHub CEO Nat Friedman announced that the default branch on GitHub will switch from master to main. (source, web archive)

However, the default branch master has been there since the very beginning of git and it has nothing to do with RACISM. It's just a simple term. Yet the forbiddance of using this word, master, renders RACISM to it. If you seek any reason that makes master branch RACISM, you cannot really find one. The word master in this scenario just happens to be the same word master in terms of the Atlantic slave trade.

Otherwise, shall we change Mastercard to Maincard, Master Degree to Main Degree or Masterpiece to Mainpiece? The word master is a plain term in these scenarios. They are not designed to express any disrespect or racism to the black people. And if we really erase out all the words that contain master, wouldn't that becomes a solid evidence that master degree and / or master branch do express racism? (Despite that they do not)

As the proverb goes, if you are a hammer, everything looks like a nail.

Don't let numbers make one numb to others feelings

Today is my first time going home from work after 9 PM in this company, but that's not important. What I want to talk about and matters is that, one of my colleague seems to be emotionally hurt by another colleague from our quants depts.

People in quants depts usually deal with data, lots of data. And of course, most, if not all, are numbers. However, if one work with numbers for a really long time, it can magically make people numb to others feelings.

In this morning, I heard that a colleague from quants depts (will use Q for shorthand) talked with our ops (will use O for short). There seemed to be a log analyser should be changed by O to meet the standard in Q's depts. But the task contains some specific terms in quants, and O cannot be sure about the meaning for some fields with these quant terms. Then Q said something really harsh to O, "I feel it's very difficult to have you understood", "Why don't you ask me for explanation earlier?!", "It almost makes me feel angry to talk with you!".

Well, I don't really think that Q was trying to communicate with others at that time. Intentionally or not, Q seemed to be numb with others feelings. Though O wasn't starting any argument with Q, O became depressed a day long. Moreover, during the weekly meeting in this afternoon, O looked his own phone for a few seconds, and the big boss asked him to stop looking at the phone with a little bit anger.

Yes, the second one is really a small case. But it is the last straw that breaks the camel's back. After the weekly meeting, our leader also found that O was in depress and wanted to have a talk with him. It not to my surprise that O refused the talk and said to the leader, "If you or boss is unhappy with my work, you or he can just fire me, that OK. It's late and I don't want to talk anything now. I just want to go home, otherwise I'll miss the last subway."

It may sound childish, but IMHO, it's better than numb / indifference in some way.

As a matter of fact, I'm thinking about to learn some quant skills recently. But I don't want to be numb or indifference to others. Are numbers making one numb? Or themselves? Perhaps both, perhaps we are just making excuse so that numbers are the ones to be blamed instead of ourselves.

Rust Learning from Zero (21) —— All I need is a dlsym | Exploit macOS application with Rust

It has been a long time since my last reverse engineering on macOS, and that was about Netease Cloud Music. 

But I always write that in Objective-C, perhaps I should try something different, let's say, Rust.

  1. Compile a .dylib that macOS recognises
  2. Build a Constructor Function that Invokes on dylib Loading
  3. All I need is a dlsym
    1. Find the Symbol You Want
    2. Casting to Function Pointer
  4. Compile and Hook

1. Compile a .dylib that macOS recognises

The first step is to tell cargo that what we need is a library

cargo new --lib exploit

And cargo will create these files for us.

├── Cargo.toml
└── src
    └── lib.rs

However, if we compile this project, the output library has a suffix .rlib. which suggests that this is a Rust library. Yet we need a dylib that macOS recognises.

Therefore the hint for producing a .dylib library should be added in Cargo.toml, which is shown below.

crate-type = ["dylib"]

This tells cargo out crate type is a dylib, which satisfies the format requirements of macOS dynamic library.

Continue reading Rust Learning from Zero (21) —— All I need is a dlsym | Exploit macOS application with Rust







買了一些會用到的東西,燈還是被我咕咕咕了,要不直接在網上買、快遞過來好了。一回來就已經下午 5 點半了,明天又是週一了呢,又要開始 5 天的上班了><

WebP Server in Rust

Generate WebP images for JPG / PNG files on-the-fly with Rust! webp_server_rs

Speaking of switching to WebP image, at the first glance, I just did it in a very naive approach.

Then @Nova wrote a Node.JS server that can serve JPG/PNGs as WebP format on-the-fly. You can find that at n0vad3v/webp_server.

A few days ago, @Nova and @Benny rewrite the WebP Server in Golang, webp-sh/webp_server_go

And that looks really promising, the size of the webp server, according to its description, had greatly reduced from 43 MB to 15 MB, and it is a single binary instead of webp_server with node_modules.

I cloned that project and added a tiny feature. However, I just found that although it is absolutely easy to implement the tiny feature, there is a potential design issue with the `fasthttp` module. In order to get everything work, it took me about 4 hours to debug on it.

Finally, it turned out to be a pointer of an internal variable (ctx.Request.uri, or so) was directly returned from ctx.Path(), and if users invoke ctx.SendFile(filepath), the ctx.Request.uri will be set to filepath, which will also propagate to all variables that hold the shared value of ctx.Path(). You may visit my previous blog post for details.

Well, in aforementioned blog post, I said that it would be better if it was written in Rust. Now, let's make it come true and push the WebP server even further.

There are some comparisons among n0vad3v/webp_server, webp-sh/webp_server_go and webp_server_rs.

As for size,

  • webp_server(nodejs) with node_modules takes 43 MB
  • webp-server(go) has reduced to 15 MB, and it's single binary
  • webp-server(Rust) pushes that even further, only 3.6 MB on macOS and 6.4 MB on Linux

In terms of convenience, you can just download the binary file and run if you choose either webp-server(go) or webp-server(Rust). However, webp_server(nodejs) requires pm2 to run.

Performance, to be honest, I haven't got time to run some benchmarks on them. But IMHO it (webp-server(Rust)) should be as fast as golang version.

记 Golang 下遇到的一回「毫无由头」的内存更改

前两天看到 @Nova Kwok@BennyThink 做了一个 WebP Server,于是 clone 下来玩了一下,发现貌似没有做“原始图像更新后,重新生成相应的 WebP 图像”的功能。好的,这个说起来简单,做起来也很简单,就是 os.Stat 一下,然后取到图像最后修改时间的 UNIX timstamp,STAT.ModTime().Unix(),最后再跟先前生成好的 WebP 文件名比较一下就好(timestamp 会放在生成的 WebP 文件名里)。

上面为止真的都很简单,在 macOS 上测试了一下,看起来没问题~于是就提交 Pull Request

然而 Nova 告诉我说,

Nice PR, but there seems a little problem that the older converted images are not deleted after the change of the original image, this might cause a possible leakage of the original one's content.

显然我是一头雾水,一开始还以为自己提交 PR 的时候是不是手滑删掉了几行,检查了一下之后发现并没有!然后姑且先把 macOS 上测试的截图 comment 在了 PR 下面。

接着我估计 Nova 应该是在 Linux 下跑的测试,于是就在一台新的 VPS 上安装了 go,把我 fork 且修改过的那份代码 clone 在 VPS 里测试。本来我预估的时候要么是我搞错了文件,要么也许是 Nova 不小心用了以前编译好的文件。然后一测试我就惊了,居然真的没有删除以前生成的 WebP 图像 Σ(・□・;)?!

由于没有 Linux 机器,也懒得安装虚拟机了,只能一头雾水的在 VPS 用 fmt.Println 输出来简易 debug 了。根据 fmt.Println 的输出,发现 ImgName 不知道为什么就突然之间被改了!

[1]ImgName: webp_server.png
[2]ImgName: webp_server.png
[3]ImgName: webp_server.png
[4]ImgName: webp_server.png
[5]ImgName: root/webp_serve

上面是在 5 处不同的地方 fmt.Println("ImgName", ImgName) 的输出,虽然我放了这么多,但是实际上在代码里 ImgName 在其作用域内只有过一次赋值,

ImgPath := c.Path()
// ... 略去 10 行左右判断文件扩展名的代码
ImgName := path.Base(ImgPath)

然后就没写过了,仅有读的操作,没有任何赋值,中间只有一次被用来当作 Sprintf 的一个参数

WebpImgPath := fmt.Sprintf("%s/%s.%d.webp", DirPath, ImgName, ModifiedTime)

但显然这个也不会更改 ImgName 的内存嘛。“这不科学!” 虽然想这么叫出来,但是想想这个肯定还是有原因的!

Continue reading 记 Golang 下遇到的一回「毫无由头」的内存更改


昨天和今天看到推特上有在玩把人加入到「可愛」清單的遊戲,我自己的話,既沒有被任何人加到這樣的清單裡,也並不在意這些的說,但是剛有看到 @FiveYellowMicepost 說 ——





不知道為什麼,突然間就想到了內田彩的「Merry Go」裡的一段歌詞

何だって 裏表だね
裏だって 表なら
表だったさ 裏なんです!

从零开始的 Rust 学习笔记(19) —— Rewrite insert_dylib in Rust

最近鹹魚了蠻長一段時間,發現大約有一個多月沒有寫這個系列了,今天繼續學習 Rust 好啦!雖然有在看「The Rust Programming Language」,但是還是得寫寫的~想了一會兒之後,決定把在「另一种方法获取 macOS 网易云音乐的正在播放」裡用過的 insert_dylib 用 Rust 重寫一下(^O^)/

insert_dylib 本身來說並不複雜,但因為不像 C/C++/Objective-C 裡那樣可以直接 #import <mach-o/loader.h> 等,於是 MachO 的一些 struct 就需要自己在 Rust 中重寫一遍~

當然,實際上也可以用 Rust 寫個 Parser,然後去 parse 這些 header 文件,並且自動生成 Rust 的 struct。可是我太懶了,留到下次試試看好啦(咕咕咕) 這次的就放在 GitHub 上了,insert_dylib_rs

不過需要注意的就是有個 BigEndian 和 LittleEndian 的問題,不同的 MachO 使用的可能不一樣,因此就增加了一個 swap_bytes! 的 macro 和一個 FixMachOStructEndian 的 trait

src/macho/macho.rs 裡隨機選一個 struct 出來展示的話,大約就是如下這樣子

use super::prelude::*;

macro_rules! swap_bytes {
    ($self:ident, $field_name:ident) => {
        $self.$field_name = $self.$field_name.swap_bytes();

pub trait FixMachOStructEndian {
    fn fix_endian(&mut self);

pub struct SymtabCommand {
    pub cmd: u32,
    pub cmdsize: u32,
    pub symoff: u32,
    pub nsyms: u32,
    pub stroff: u32,
    pub strsize: u32,

impl SymtabCommand {
    pub fn from(buffer: [u8; 24], is_little_endian: bool) -> SymtabCommand {
        let sc_buffer: [u32; 6] =
            unsafe { std::mem::transmute_copy::<[u8; 24], [u32; 6]>(&buffer) };
        let mut symtab_command = SymtabCommand {
            cmd: sc_buffer[0],
            cmdsize: sc_buffer[1],
            symoff: sc_buffer[2],
            nsyms: sc_buffer[3],
            stroff: sc_buffer[4],
            strsize: sc_buffer[5],

        if is_little_endian {


    pub fn to_u8(&self) -> [u8; 24] {
        let mut data: [u32; 6] = [0u32; 6];
        data[0] = self.cmd;
        data[1] = self.cmdsize;
        data[2] = self.symoff;
        data[3] = self.nsyms;
        data[4] = self.stroff;
        data[5] = self.strsize;

        unsafe { std::mem::transmute_copy::<[u32; 6], [u8; 24]>(&data) }

impl FixMachOStructEndian for SymtabCommand {
    fn fix_endian(&mut self) {
        swap_bytes!(self, cmd);
        swap_bytes!(self, cmdsize);
        swap_bytes!(self, symoff);
        swap_bytes!(self, nsyms);
        swap_bytes!(self, stroff);
        swap_bytes!(self, strsize);
Continue reading 从零开始的 Rust 学习笔记(19) —— Rewrite insert_dylib in Rust

另一种方法获取 macOS 网易云音乐的正在播放

虽然标题里面写的是“另一种”,但是先前的方法其实不是我写的?而是来自可爱少女 Makito 的两篇 post ——

于是就看到了直接从 Mach 内核入手的方法,是賢い、かわいい Makito~!不过今天跑去 clone 代码下来尝试的时候似乎会 crash 的样子,毕竟距离上次 update 代码也过去了 9 个月左右了,猜想可能是网易云音乐有所修改导致(在我用别的方法尝试的时候,也是莫名 crash 了)

于是这里就写一个另一种获取 macOS 网易云音乐的正在播放的方法吧~

Continue reading 另一种方法获取 macOS 网易云音乐的正在播放