更新ASUS路由器的OpenVPN证书

以前用PPTP就可以连回家里的ASUS路由器,而现在市面上无论手机还是PC出于安全考虑,基本仅支持IPSEC或者OpenVPN。考虑到灵活性且路由器的图形配置界面开启很容易,打算换用OpenVPN的方案。

按正常流程,配置结束可以导出client.ovpn配置文件,再通过手机版的OpenVPN导入这个配置文件就可以连接了。

实际尝试连接时,手机提示验证失败。路由器日志里看到XAUTH Authentication Failed的字样,再根据手机端的OpenVPN日志发现问题源是路由器OpenVPN证书仍然在使用SHA1

手机安装的新版OpenVPN觉得这样很不安全,拒绝与之通信。尽管可以在手机客户端加参数让一些违规操作以permissive放行,但实质的安全问题并没真的缓解。标准做法肯定是更新路由器里OpenVPN使用的证书,至少用SHA256作为签名的校验算法

值得庆幸的是,路由器的OpenVPN的高级配置栏可以找到[Content modification of Keys & Certification]这么个选项,里面允许更改[Certificate Authority],[Server Certificate],[Server Key],[Diffie Hellman parameters]。所以我们要做的就是自己生成强度足够的证书和密钥替换路由器默认使用的这套配置。

参考OpenVPN官方的配置文档,得知easy-rsa可以很容易生成对应的密钥文件,只不过官方文档年久失修,仍然在以停更良久的easy-rsa 2为例说明,目前换easy-rsa 3才是正解。

以Windows为例,首先从easy-rsa 3官方页面下载最新的release,解压后执行EasyRSA-Start.bat

在新的shell下面依次执行:

./easyrsa init-pki
./easyrsa build-ca
./easyrsa build-server-full server nopass
./easyrsa build-client-full client nopass
./easyrsa gen-dh

之后pki/ca.crt就是填写到[Certificate Authority]的内容;pki/issued/server.crt末尾的PEM填写到[Server Certificate]里,pki/issued/server.key的内容写到[Server Key]栏目下面;最后,pki/dh.pem填写至[Diffie Hellman parameters]

保存并再次导出client.ovpn后需要注意,新的client.ovpn里客户端的证书和私钥都是留白状态,需要手动填写。也就是说要编辑client.ovpn,<cert>栏目里填写pki/issued/client.crt末尾的PEM,<key>栏目下填写pki/issued/client.key的内容。

Arcadium游戏修改

最近手机上装了一个竖版打飞机的游戏,叫Arcadium – Space Shooter,apk的包名为:com.ihgyug.arcadium

游戏里通过收集Gems或直接花钱购买可以换购很多不同型号的飞机,每个飞机的属性有十几种。在设置界面发现有个gift code的选项,也就是输入优惠码可以直接获取Gems。最初的想法是分析下游戏代码,把优惠码都找出来。

用jadx载入apk后发现java代码并没有包含游戏逻辑,原来游戏是采用unity引擎开发的,也就说代码逻辑都是通过.net实现并打包到了libil2cpp.so,字节码的元数据包含在global-metadata.dat文件中。Il2CppInspector可以用来处理这两个文件生成IDA Pro可以识别的符号,导入后就能研究游戏的具体实现了。

看来看去,发现优惠码其实在游戏资源文件level0当中,每个优惠码的格式如下:

08 00 00 00 41 72 63 61 64 69 75 6D

11 00 00 00 48 61 76 65 20 61 20 6E 69 63 65 20 67 61 6D 65 21 00 00 00

F4 01 00 00

字串开头是长度,字符串要四字节对齐,最后一个字段0x1F4意思是优惠码会赠送250枚Gems。针对目前最新版本的游戏(1.0.66)提取出来所有的优惠码如下:

  1. Arcadium: 500
  2. SantaGift: 250
  3. HalloweenGift: 250
  4. NewYearGift: 250
  5. Cheater: 1
  6. Downloadx500: 250
  7. SummerGift: 250
  8. FullRelease: 250
  9. Downloadx1000: 250
  10. Downloadx5000: 250
  11. Downloadx10000: 250
  12. AutumnGift: 250
  13. WinterGift: 250
  14. Downloadx50000: 250
  15. Downloadx100000: 500
  16. SpringGift: 250

为了多搞点Gems,我索性直接把level0文件里Cheater对应的数值改成了99999999,这样进入游戏输入优惠码就拿到了用不完的Gems。

Uranus是我最喜欢的战斗机,也是Gems可以买到的最贵的型号。为了让游戏再省事一点,我又找到了Uranus对应的资源文件,把飞机的属性加强了一下。

飞机的属性文件为sharedassets0.assets.split15,飞机的属性值格式如下:

06 00 00 00 55 72 61 6E 75 73 00 00

05 00 00 00|00 00 80 40|00 00 80 40|00 00 80 3F

00 00 00 00|14 00 00 00|00 00 20 41|00 00 20 41

00 00 80 3F|00 00 00 40|CD CC CC 3D|00 00 00 00

00 00 00 00|00 00 00 00|00 00 00 00|01 00 00 00

00 00 00 00|10 00 00 00|00 00 C8 42|00 00 00 00

00 00 00 00|00 00 00 00|00 00 80 3F|00 00 00 00

最开始是飞机名称,接下来每个属性是4字节,有的是INT,有的是FLOAT。

我识别出来的属性有maxhp,damage,energygain,attackspeed,pickrange,droprate,glowyenemychance,bonusduration,debufduration,eneryleech,lifeleech,critchance。这里我把maxhp,damage,bonusduration和debufduration稍微修改了一下。

最后再把修改好的level0和sharedassets0.assets.split15重新塞回apk里。重新签名安装到手机上,就可以进入游戏完虐NPC了。整个修改过程仅仅是改了两个资源文件,不碰代码就省去了繁琐的指令patch,改得很惬意。

感冒随笔

周五团建边吃大闸蟹边侃大山时还对自己的身体状态沾沾自喜呢,结果过了个周末就开始干咳,再到周末时已经四肢无力,边睡边烧,那种难受想死的状态无时不提醒着我感冒已至。

每到这种不明所以的痛苦从天而降的时候,除了疑神疑鬼地揣度各种可能的原因(吃蟹没吃姜,连续睡太晚,同事的传染),也特别容易陷入对日常生活和工作学习的反思。

如果时间有限,究竟应该投入在更有价值还是更值钱的事上。比如现在,是应该接着在之前的矿坑里探索还是出来找找附近的新矿井。还是说,更有价值的事其实就是更值钱的事,或者刚好反过来。毕竟每当牵扯到钱,思想特别容易过热,放大了目标的价值。也可能多年回头看今天的决定就像今天看当年没屯币一样的心情,看它不起眼,他确是你当下能把握的最好机会。亦或者其实俩事不冲突,同时进行也是可以的。Nowadays, man knows the price of everything but the value of nothing.

差不多两周里嗓子和肺的不适,让本来闲不住的伶牙俐齿不得不停薪留职。就这样,寸土寸金挤出来的几句话,没有了调侃戏谑和有些多余的铺垫,反而饱含温情充实且平静。不禁觉得平日里的话是不是杂糅进了过多的矫情造作,少了些真诚。等后面有力气说话了,是不是还可以省着点气,别用力过猛。

随着身体状态日渐恢复,思绪又平静下来,身体开始蠢蠢欲动,意图继续之前的冲刺。希望新的平衡态是以现在为基线的情况下找到的,也希望日后不是只有倒下了才开始反思。

新家上网大作战

从2013年到现在搬了有六次家,这次终于找到了一个相对完美的上网解决方案。

这次家里是联通500M光纤入户,宽带入户后所连接的光猫位于餐厅墙内,打开墙上的塑料小门就可以尽情撸猫。光猫带有四个LAN口,一个光纤口。同样在这个墙内小隔间还有八根网线,是基建预留的,分别通向三个房间和客厅,每个房间有两个网口。

首先,我不希望辐射太猛,尽量一个路由器能搞定最好。这样的话,路由就要放在全屋的中央,也就是客厅的电视柜上。路由通过墙上预留的网口可以连接光猫的LAN1上网,当然为了挂PT,上班VPN回家等考虑,光猫要改成桥接模式。这样路由器就可以代替光猫直接PPPOE拿到公网IP,家里其他设备通过路由上网就可以了。

选了个华硕的RT-AX86U,网上看各项评价都不错,然后好像网络部署问题就over了。

实际部署好以后,发现个大问题。就是我放台式机的书房距离路由着实有点远,虽然上网流畅,但下载速度实际只有4-5M,远远低于40-50M的应有额度。显然这台PC作为家里宽带的重度使用者离热点太远了。但如果就简单地把路由拿到书房的话,电视又离路由器太远了。而电视又需要经常通过SMB看电脑里下载的电影,所以作为局域网络的重度使用者,电视也要离路由器近一点。而且路由放在中心客厅,可以充分地保障pad和手机的使用。

既然书房也有网口可以直接连接光猫,有没有办法让台式机通过这个网口上网呢?目前家里的网络环境如下图所示:

路由器WAN口和台式机LAN口通过基建预留的网口分别连接了光猫的LAN1和LAN2,并分配到192.168.1.2和192.168.1.3的IP地址。由于光猫内的桥接,路由器WAN通过PPPOE可以直达联通,还会分配到公网IP,如下图所示:

现在的问题是,台式机仍然没法上网,也不能访问路由内网的其他资源。而且上海联通也不支持PPPOE双拨,所以不能通过光猫再建立一条到Internet的通路。

经过反复尝试,目前完美解决。华硕的路由可以开启OpenVPN,这等于WAN口会侦听一个端口,允许外部认证后访问路由内网资源,也可以通过该路由访问Internet。虽然说路由VPN也可以选择更简单的PPTP/L2TP+IPSEC,但PPTP已经被OSX抛弃,IPSEC由于算法协商问题跑不通,最后就只能选择OpenVPN了。

最后的网络连接后的效果如下图所示:

台式机经由光猫的LAN2 – 路由WAN – 路由OpenVPN – 光猫LAN1 – 光猫Bridged TTL来访问Internet,当然也顺带就访问到路由器内网了。实际使用过程中,也许底层被优化(走着走着也许就直接LAN2 – TTL了也说不定),台式机下载速度基本可以跑到50M,说明这一通折腾基本没有太多流量损失在VPN上。

小迁徙

Digital Ocean的服务器用了两年多,当时10美元的配置今天已经升级了,买的早的,也不说老配置给自动降个价。虽说Google Cloud的服务器现在速度最好,但维护起来总是比较麻烦,万一哪天梯子抽风,还是挺不好办的。

所以打算还是重新买一台Digital Ocean的十美元新配置,然后把网站后台迁过去。按计划,先买新服务器,安装自带WordPress,然后从老站WordPress导出xml,新站导入,没问题就把web目录scp过去就完事了。

可实际操作起来,还是耗了几个小时。

首先Digital Ocean这种自带后台的服务器,ssh刚进去就命令行下让你配置 WordPress的域名,账号密码等信息,不配置就总弹出来,而且域名不写对了,你访问ip得到页面动不动就被跳转到奇怪的域名下。测试时比较方便的方法是改本机/etc/hosts,假装域名已经迁过去了。

WordPress的导入导出功能也很残疾,这个只适合同一个站点的备份和恢复。因为老xml导入新的站点时,用户信息没法正常导入,只有作者映射,密码没法同步,另外一些网站的名称,皮肤配置也跟不过来。

还一个问题是,因为网站目录下可能有一些自己写的东西,要拷贝web目录过来,但就很容易把某些配置文件改掉,已经配好的WordPress也会因此连不上数据库。

试了半天,发现最惬意的方法是老站点装phpmyadmin直接把wordpress数据库dump下来,然后新机同样操作,把dump的sql文件再覆盖掉原数据库。最后web目录一同步,再修改一下新机wp-config.php里的数据库密码就全好了。这样包括你皮肤里自己改动的代码也就都跟过来了。

全部折腾完,准备destroy老服务器时,确认页面居然弹出来问,是否免费自动把老服务器配置升级,very well

Infiltrate 2019

距离上次用英文讲东西已经三年了,这次的议题从春节前做完实验开始算起,幻灯片部分准备了差不多三个月。前一个月幻灯片草稿阶段投入精力比较密集,后两个月平均每天都也要花一到两个小时练习和反复修改。相比上一次,这次讲的效果似乎要好很多。

幻灯片制作时,前期偷懒省掉的animation和highlight最后又都补回来了,只有站在旁观者位置,仔细琢磨一个并不了解情况的人看你幻灯片时的感受,并且真的想人家完全听懂为动力才能把幻灯片推向自觉的极致,然后才好期待别人的认可。

练习时先用口语化的表达往复过几遍,然后把表达不理想的部分写下来,这样能慢慢调整修改,结果就是几乎每两三页就有一些文字记录在案。练习时也不必完全背诵,适当引入一些语速变化的口语化表达会显得更为自然。视频录下来看自己的表现和听录像里的声音感觉会很不一样,这有助于调整自己的语音语调以及动作表情。最后在台上时,可能是面向斜下角度的问题,表情一直不是很好,这在练习过程中确实没有发现,也可能是紧张导致的面部僵硬。

Dry Run部分会议方给的建议是Demo部分加入一个joke,这是此前讲东西从来没有尝试过的环节。最后的效果非常好,由于语言上没有Native Speaker的优势,笑点主要靠前期的P图和动画共同完成,达到一个出人意料的组合,语言上只要在这个动画出现时稍微停顿一两秒,台下已经准备好笑力的观众就会释放了。

如果说改进的话,这次会议参与度不如44con,几乎很少在会场的大厅里徘徊。另外也不是所有的议题都要去听,精力有限,听多了反而有影响。

Magisk on T1

Smartisan T1是一款老机型了,时至今日,运行的仍然是Android 4.4的系统。以前研究过它的Bootloader解锁,如今打算回头再看看怎么把最新的root方案Magisk移植进来实现持久。

不同于supersu需要twrp的支持,Magisk提供了一种十分便捷的修改镜像的方法。只要把目标设备的boot.img拖出来,放到任何一台安装有Magisk Manager的手机上,就能进行重打包,包装成一个带有root功能的镜像。接下来,无论用什么方法,只要能把boot.img刷回boot分区就可以了。

临时root

T1升到最新版本后(2018年2月份的版本),为了把boot.img拖出来,并放回去,需要取得一个临时的root权限,我利用的是CVE-2017-8890,不过这不是重点。问题是后面的Magisk重打包。

Magisk原理

Magisk的重打包,从底层看,主要就是把/init替换成了它自己的magiskinit。当boot启动时,magiskinit首先从/.backup恢复原始的init文件。然后从magiskinit中释放出来magisk.bin和Manager的APK等后续建立root需要的文件。接着它会以init权限patch sepolicy,增加一个名为magisk的上下文环境,最后启动magiskd等待su的连接。

当su命令执行时,背后实际上是向magiskd请求root,magisk则会向Magisk Manager发起问询,等待用户确认后才赋予放行,最后magiskd启动一个shell,并把它重定向到su通过unix socket发送过来的输入输出句柄上。

T1带来的麻烦

现在最大的问题是Magisk Manager编译时只能运行在5.0以上的系统,4.4没有支持。如果抛弃magisk,单靠suid之不能建立起完整root的,4.4虽然selinux弱得很(通过/proc/self/attr/current就能任意修改自身上下文),但普通的用户进程其capability已经几乎全部丢弃,即便uid和gid都为0,能做的事情也有限。还是需要一套magisk这种劫持启动流程的方案才能从一开始就拿到init。

所以打算完全抛弃Magisk Manager,通过patch magisk自身的逻辑,实现任意进程执行su时无需校验就放行。

patched_boot.img的重打包

想要patch magisk,要修改的实际上是Manager重打包后的patched_boot.img。它当中的magiskinit包含了magiskd的代码,只要修改两个关键的跳转就算通过了。不过问题是这里每个环节都很繁琐。首先magiskinit的文件结构很特殊:

$ binwalk init

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             ELF, 32-bit LSB executable, ARM, version 1 (SYSV)
262482        0x40152         Unix path: /vendor/etc/selinux/precompiled_sepolicy
262824        0x402A8         Unix path: /sys/fs/selinux/policy
262895        0x402EF         Unix path: /sys/fs/selinux/load
263576        0x40598         Unix path: /sys/fs/selinux/policy)
266224        0x40FF0         Unix path: /vendor/etc/selinux/plat_sepolicy_vers.txt
296964        0x48804         xz compressed data
301647        0x49A4F         xz compressed data
346435        0x54943         xz compressed data
376768        0x5BFC0         Unix path: /proc/device-tree/firmware/android

其中0x49A4F开始的这个区块就是magiskd也就是su_daemon。由于magiskinit要根据这些偏移解出来所需要的文件,修改的时候必须要保证文件大小精确一致。
0x49A4F 文件可以dd出来,然后unxz解开。修改二进制后,不能直接xz,xz命令和magisk用的结构稍微不太一样,需要使用python3的lzma的compress去压缩,也就是:

lzma.compress(magisk, preset=9, check=lzma.CHECK_NONE)

dd回去之后,还要进行ramdisk的重打包,这里同样有个文件大小要保持一致的问题。因为patched_boot.img已经和boot.img不一样了,末尾会增加一个xz,包含Manager的APK文件,虽然用不到,但虽已覆盖会导致初始化失败。

虽然ramdisk重打包有很多工具,但都无法和magisk的cpio保持一致,主要原因是普通的重打包都没有考虑到/.backup等隐藏目录的引入。所以更精确的做法是直接对cpio文件操作,找到init文件的位置,写入修改后的文件内容。对cpio进行gzip时同样还有问题,系统自带的gzip会加入过多的metadata导致文件比原来要大。我解决的方法是minigzip.py,去掉文件名相关的metadata,然后进行压缩,这样大小就和原来相同了,最后dd回patched_boot.img就可以了。再次开机启动就拿到了久违的su:

shell@msm8974sfo:/ # id -Z
uid=0(root) gid=0(root) context=u:r:magisk:s0

外星人起死回生指南

故事发生在爱丁堡一个阳光明媚的早晨,男主将一杯苏格兰现磨咖啡放在工位桌上,伸了个懒腰,准备开始一天的科(ban)研(zhuan)工作。

然而。。。

男主爱不释手的小外星人Alienware 13 R2却怎么也开不开机了,按下电源键没有任何反应,电源键那个外星人头也不亮了、风扇也不转了、硬盘也不响了。但是电源线上的蓝色LED灯是亮着的

昨天晚上关机时还好好的,也没有任何征兆,这才买了一年多,怎么就突然变砖了呢?

歪果的电脑维修出了名的不靠谱和昂贵,看来只能自力更生,展开自救了。经过一番问题分析、文献搜索和上手实践,本庸医竟将小外星人起死回生。以下给出整个治疗过程以供大家参考:

 

注:本方法不保证一定能拯救你的电脑,如果情况恶化,本人及本网站也谢绝负担任何责任。

据说,以下方法可以用于Alienware 13 R2 Alienware 15 R2 Alienware 17 R3这三个型号的突然开不开机的治疗

 

整个过程包括放静电和CMOS重置两个步骤:

(1)断开电源线,按住开关键10到15秒钟,以释放静电,完毕后插回电源线看看能不能开机了。如果还是不能,转到下一步。

(2)再次断开电源线,打开笔记本遮住内存条的那个后盖;

(3)将后盖内的电池供电线路的连接插销拔掉;

(4)移除内存条,此时你能看到几个金属触点(13 R2与15 R2和17 R3的触点略有不同,如下图)

          * 分支剧情1:对于Alienware 15 R2 and 17 R3,定位CLRP 1,用导体(比如全金属镊子或者曲别针)连通CLRP 1的两个触点

 

* 分支剧情2:对于Alienware 13 R2,定位CLRP 2,用导体(比如全金属镊子或者曲别针)连通CLRP 2的两个触点

 

本文男主的小外星人是13 R2型号的,导体连通CLRP 2两个触点成功会听到滴的一声巨响,其他型号的反应不确定。

 

听到滴的一声巨响后,连回电池供电线路,合上后盖,插回电源线,开机,看是不是有反应了如果有反应了,外星人头开关灯亮了但是还不能正常进入系统,请重复上述第(2)~(4)步3到5次。男主就是重复到第4次成功的。

 

 

 

 

中秋节

快一年的时间,每当想要停下来回头看看,就会望见远在家中前所未有的不安在慢条斯理地折磨着不忍心看着它的每一个家人。自骨折后,麻醉剂夺走了姥姥大半的行动时间,几个月后,消瘦的双腿再想撑起身体已经十分吃力。直到五月她的意识开始有些模糊,一天只有很少的时间可以正常思考和沟通。也是那会儿我第一次觉得无助,只能眼巴巴地看着我妈喂她吃饭喝水。甚至回家,这个我曾经只要有假期都要去做的事儿,突然也变得不忍心,试着去躲,好像不看它就没有了。

终于,中秋前我哥从南非回来了,中秋节时我也赶回家。那天飞机晚点四个小时,晚上八点多才进门,好在回来了,因为第二天下午姥姥走了。

那天下午我替我妈班,她一个上午都在试图喂姥姥吃点东西。我说话,但姥姥除了喉咙里无力的呼吸声别无回应,直到她伸手抚过我的脸和肩膀,最后握住我的手,竟然那么有力,好像生命最后的力量毫无遗憾地释放了。

呼吸从无力到停止,快一年的折磨终于离她而去。

那一天晚上开始,我和我哥在湖边走了很久,说了很多,后来两天也是。从未谈起的最后一刻到从前往事,家人关系,彼此的生活,苦恼欢笑,遗憾释然,一下长大许多。

最后的道别安静顺利,墓碑前没有外人,只有她一辈子牵肠挂肚的子女儿孙。她最后的生命换来一个真正意义的中秋节。

MacBook Air安装双系统

如果只能在linux windows osx当中选其一,兼顾了图形界面和命令行的osx当仁不让。

不过最近升级了512G的Mac,发觉得现阶段双系统才是正解,有些osx下不适合做的,就不勉强,火候一过事情就焦。

我选择的是osx + linux mint,折腾前,建议还是先准备好一个osx的安装u盘。由于涉及分区表操作,弄不好连系统的recovery都废,重装就在所难免了(我就是不小心把分区表弄坏了,只能重启进入internet版的recovery,不过提示下载失败,没能重装,最后还是在windows下制作的osx启动u盘)

安装过程主要参考的是这篇文章,用的是Macbook Air 2017。不过安装linux时,我并没有开启ext4文件系统加密,给osx留了100G,然后2G给/boot,剩下的给/

基本上安装过程不会有问题,装好以后才是麻烦的开始。

首先是键盘布局,进入linux以后:

然后选择Generic 105-key (Intl) PC,English(UK)。试了半天,唯一能让键盘布局正确的选项,否则~总是被映射为±

接下来是亮度调节,为了让mac的亮度调节快捷键工作,编辑/usr/share/X11/xorg.conf.d/20-intel.conf

还要检查一下~/.viminfo的权限是不是666,或者owner是当前用户,不然vim的配置文件会不起作用

接下来要配置L2TP的VPN,Mint默认没有提供,需要自己安装

重启后在网络管理里面就能添加vpn了,不过由于我的目标版本比较老,还需要额外配置一下

首先安装ike-scan扫描目标网络,然后把加密所用的算法填写到VPN的高级选项里,除此之外还要装一个strongswan-plugin-openssl,原因也是因为目标算法比较老。