Cocoa

从零开始的 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 上了,BlueCocoa/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);
}

#[derive(Debug)]
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 {
            symtab_command.fix_endian();
        }

        symtab_command
    }

    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 网易云音乐的正在播放

Copy List with Random Pointer

A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.

Return a deep copy of the list.

The Linked List is represented in the input/output as a list of n nodes. Each node is represented as a pair of [val, random_index] where:

  • val: an integer representing Node.val
  • random_index: the index of the node (range from 0 to n-1) where random pointer points to, or null if it does not point to any node.

Example 1:

Input: head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
Output: [[7,null],[13,0],[11,4],[10,2],[1,0]]

Example 2:

Input: head = [[1,1],[2,1]]
Output: [[1,1],[2,1]]

Example 3:

Input: head = [[3,null],[3,0],[3,null]]
Output: [[3,null],[3,0],[3,null]]

Example 4:

Input: head = []
Output: []
Explanation: Given linked list is empty (null pointer), so return null.

Constraints:

  • -10000 <= Node.val <= 10000
  • Node.random is null or pointing to a node in the linked list.
  • Number of Nodes will not exceed 1000.
Continue reading Copy List with Random Pointer

Integer to Roman

在家无聊到开始随便找算法题做,嘛,既然都做了,那就写在笔记本上好了~

Roman numerals are represented by seven different symbols: IVXLCD and M.

SymbolValue
I1
V5
X10
L50
C100
D500
M1000

For example, two is written as II in Roman numeral, just two one's added together. Twelve is written as, XII, which is simply X + II. The number twenty seven is written as XXVII, which is XX + V + II.

Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used:

  • I can be placed before V (5) and X (10) to make 4 and 9. 
  • X can be placed before L (50) and C (100) to make 40 and 90. 
  • C can be placed before D (500) and M (1000) to make 400 and 900.

Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 to 3999.

Continue reading Integer to Roman

一片祥和、歌舞升平有什么卵用?

2020 年 1 月 24 日到 25 日,是中国农历传统的除夕夜与大年初一,电视里春节联欢晚会歌舞升平,一片祥和,而在这个国家几乎中心的位置 —— 湖北,其最后一个市襄阳也同时宣布于 2020 年 1 月 25 日 00:00 起“封城”,至此湖北省完成了“封省”。这也意味着武汉市、湖北省和中共中央政府的失职、渎职而加深的肺炎疫情比上次 2003 年的 SARS 疫情还要严重得多。

歌舞升平、一片祥和既不能当疫苗使也不能当饭吃,这次已经这样了,普通人在捐款捐物的同时,为什么不能好好问责政府,难道问责政府的人是希望还有下一次?需谨记,若批评不自由,则赞美无意义。

Continue reading 一片祥和、歌舞升平有什么卵用?

当真相被隐瞒的时候

原来以为,自 SARS 过去了 10 多年之后的今天,“小汤山”只会存在于历史中,没想到 ——

越是隐瞒,越是想要“维稳”,延后到不得不承认的时候,造成的社会影响、恐慌越大。

对比一下这两种情况,「某省市 3、5 人确诊感染未知肺炎」和「634 例确诊,422 例疑似,仅 2 省市无疑似病例」。

前者早知晓、早控制,周边无论是医护还是民众也有时间做好预防与准备。同时民众在有及时的公开、透明信息的情况下,自身也会“趋利避害”地远离易感染的场所,疫情则不至于悄无声息的扩散。

而后者,疫情已经扩散开来,在政府隐瞒真实疫情的时候,多米诺骨牌一个一个倒下,现在已然来到了需要对源头甚至其周边城市“封城”的时间。

选择了后者,花出去的人力物力也必然大于前者,对经济的影响无疑也是巨大的。最重要的是,在“一片祥和”中感染了病毒的人数则可能大大增加,带来的后果现在大家有目共睹。

有人说,“都现在这个时候了,问责不是首要的”。

在某种程度上是 —— 对于疫区以及现在因为政府没有及时、有效、透明公开信息而感染的患者来说,他们现在连自己是否能撑过去,撑过去了是否会留下后遗症都不知道;对于在疫区第一线工作的医护人员来说,他们都是冒着可能被感染的风险 —— 而这些可能的后遗症与风险对于他们当中多数人来说本是可以避免的

但是对于我们,既不是医护人员,也不是感染了武汉肺炎 2019-nCoV 病毒的人来说,我们除了为疫区的朋友提供物资、信息之外,另一件还可以做的就是对政府问责!毕竟提供物资、信息等可以帮助减缓到这一次的疫情,可是却防不了下一次

Continue reading 当真相被隐瞒的时候

我們的敵人是遠比病毒可怕的愚昧和壞

我最早聽聞有武漢肺炎病毒「2019-nCoV」的時候,大約是在 2019 年 12 月初,當時在推特上已見到有不少人討論。然而那個時候國內還是摀得嚴嚴實實,到後來還有“闢謠”,甚至還逮捕了 8 個“散佈謠言者”。

同時,當有人在某網站上提問“武漢肺炎”時,該網站直接刪除掉用戶提問,而理由則是狗屁不通的“違反社區管理規定”

今天再回過頭來看這些,真的不禁讓人想問責武漢市的 CDC 和警方,為什麼沒有在第一時間通報疫情,為什麼民間自發傳遞信息第一時間想到的是“謠言”、“抓人”、“刪帖”?

不僅官方渠道失職,民間渠道被噤聲,甚至武漢市還舉辦“萬家宴席”!

四萬餘家庭的話,即便按每家去 2 人來計算,也有將近 8、9 萬人。這要是在“瘟疫公司”遊戲裡發生的話,玩家大概玩的是「白痴」難度,這種規模的活動傳播起病毒來真的不能再棒了!

官方自以為聰明的瞞報、謊報,權力不受約束的警方,沒有衛生健康常識的民眾,他們為這次病毒的傳播提供了絕佳的溫床。哪怕十多年前發生過「SARS」,這個國家從官方到民間不但未見得有總結多少經驗,反而相比以前更差了 —— 當有人在微博上紀錄下自己家人的不幸感染了這次的冠狀病毒時,被網絡暴力指責“製造恐慌”,被迫道歉。

在寫這篇 post 的時候,丁香園上的數據為「确诊 443 例 疑似 151 例 治愈 25 例 死亡 9 例(其中有 99 例确诊暂未明确地区 )」

世界數據如下

本以為現在 PRC 中國迫於國際壓力公布之後,疫情情況的公布會有所改善,然而

「我建議你自己查」

愚昧和壞遠比病毒可怕。

我们可以有无任何监管或审核的自由 App Store / Market 吗?

其实很早以前就考虑过这个问题了,我们能否构建一个没有任何监管/审核的自由 Store / Market?(「政治审核」类无论何时我都认为有多远就该滚多远)

其实听起来真的很棒,开发者做出来了好的应用,马上就可以 deliver 到用户那里去,没有任何的限制,也不需要等待。但是我们无法回避的一个问题则是,现实里并没有那么美好 —— 哪怕现在就把中国从地图上抹掉,做二次打包植入恶意代码盈利的也大有人在。

写的软件质量糟糕其实都是小问题,大问题是用户数据的安全。毕竟恶意代码的目的包括但不限于 blackmail、未经授权的转账、窃取用户隐私数据,无论是 iOS 还是 Android,都不可能是没有任何漏洞的。难道我们要把一切都简化为一句

“安装此软件造成的一切后果均由用户自行承担”

我相信我认识的和不认识的绝大多数做技术的人,只要想的话,写一个完全没有任何审核的自由 Store / Market 绝不是难事。无监管或审核的自由 Store / Market,对于开发者来说必然是非常快捷、便利的,但因此带来的对安全的考量就转移到了最终用户身上 ——

我们假设,开发者 A 做了一个很有特色的 X 软件,或者本身就是做了一个 X 软件的美化版 / 增强版之类的,并发布在了某自由 Store / Market 上;随后开发者 B 下载、植入恶意代码、二次打包后也发布了上来(可能还改个名之类的)。这个时候普通人应该如何分辨?

  1. 靠评论或者下载量?可是评论、下载量必然也是有黑产可以代刷❌
  2. 靠开发者可信度认证?但那不就是有一定程度的监管了吗❌
  3. 靠开发者 GPG 公钥签名?拜托,普通人连使用协议都很少有去看的,更别说对于他们而言过于专业的 GPG 签名验证❌
  4. 靠实名制?有了这个根本就不可能叫自由 Store / Market 了吧❌
  5. 靠口碑 / 懂这些的朋友?听起来真的很原始,但也许还算可行🤔
  6. 靠自己?以后普通人都自己去应用的官网下载,可那样的话,自由 Store / Market 又有什么存在的意义呢🤔

如果说自由 Store / Market 只是给一小部分人的话,那么现在 iOS 上可以在 Jailbreak 后自行安装,部分 Android 手机 root 后随意安装,部分 Android 本来也就没限制。

对于我们做技术相关的人来说,自己区分是否包含恶意代码还是可行的。然而,程序员以及技术爱好者不过是所有用户中的一部分,剩下很多人完全不懂的,哪天中招下载了包含恶意代码的软件,由此带来的物质 and / or 精神上的损失又该怎么办呢?

还是中国人最擅长骗中国人的钱。

到了迪拜之后的第二天,早上一上车,导游就说在阿联酋这边,有他们国旗的地方都不能拍照,因为一部分是政府机关,一部分是国营企业所以才挂国旗。一开始我也没有细听细想,现在回想起来,这便是骗局的伏笔了。

Continue reading

记得很久之前就看到有人说很多中餐(尤其是重庆、湖南、四川这一带)都是靠海椒的辣味掩盖食物本身的味道,于是今天再次体验了一下这一点。

在坐 Air China 去迪拜的时候,晚餐选了鱼肉饭,果然跟上次坐 Qatar 航空去多哈的时候提供的餐食完全没法比——

Air China 上的晚餐就是很普通的锡箔纸包装的,揭开之后也不过零星的有 3、4 块小小的鱼肉。

入口之后,辣,dominate 了味蕾的感受,只留下了我的视觉和舌头的触觉告诉我这大概是鱼肉。咽下之后能够回想起来的也就是海椒的辣带来的刺激。

辣,只不过是众多味道中的一种,但是却被很多中国人吹上天,从“无辣不欢”到“吃嘛,不辣”。以及出了国就是带/买上“老干妈”,然后还顺带嘲讽别的地方的食物——“不就是那样吗”。可是他们却不曾想过,他们自己喜欢的食物按照他们自己的标准来评价的话,也不过是“不就是辣吗”。

现在吃到中餐里辣的食物的时候,我觉得“辣”已经取代了很多食材本身的味道,食材几乎只剩下了口感。就像我今天在 Air China 上吃的那一盒鱼肉饭一样,就像我平时在大陆吃到的那些以辣为主的菜一样。

而将“辣”使用到极致的便是火锅。说实话,偶尔吃一次牛油火锅也还是会觉得很好吃,但是在追求舌尖上的刺激的同时,火锅对味蕾的伤害也不可忽视。很多人说吃得辣是训练出来的,在某种程度上并没错,毕竟味蕾都被辣椒素干掉了,自然也就觉得别的菜都吃不惯或者吃不来了。

経験値上昇中☆