等额本息的战争

安全界老大哥@yuange1975最近揭露微博借钱的套路贷导致微博账号被删。套路贷问题本身还是很有意思的,很像是那种偷换概念的陷阱趣味题。

问题来了,如果借了20000块钱,一年还完,每个月要求还款2266.67,那么究竟这笔贷款的年利率该怎么算呢。

一个错误的示范是,年利率P = (2266.67 * 12 – 20000)/20000 = 0.36。也就是说一年才36%而已,好像很符合国家规定的上限。

很久不实际推算点什么东西了,这里的陷阱还真一下没反应过来。题干简单的背后,是故意模糊的概念。首先什么是年利率,一般来说它是一个等价概念,粗略说就是一笔钱过一年后增加的数目/初始钱数。如果一年到期后,一次性还2266.67 * 12 = 27200的话,那年利率计算结果就是36%。

但现在提前还了钱,先不论每个月的钱里有多少是本金,多少是利息,显然对于借钱的你是要亏一些的,而对于债主来说,它能提前拿到钱是很赚的,最次最次他拿到钱以后存到余额宝也有利息啊。所以直观感受是,这种还款年利率应该是比一年以后一起要高的,但究竟怎么量化这种感觉呢。

在此期间我看到有公众号也在讨论这个问题,其解决方法是经济学里的IRR公式。本来应该主动去分析的问题,现在都成了被动的朋友圈推送文章,久而久之现在处理问题好像更加被动了。另外公众号的文章从来都是短小精干(浅尝辄止)。即便后来找到了IRR公式“原理”,依然不甚过瘾。记得大学时候替学生会的一个部长喊到,上过一节经济学原理的课程,依稀记得课上的一道题目我是用等比数列极限求解,而老师给出的是经验公式,且没有推导过程。所以至今我仍冒昧且莽撞的认为经济学里的很多理论,由于很多人不去深究其背后数学根基,讲出来的话也就特别缺少逻辑的严谨性,仅用于计算倒是没有问题。不过这样的分析文字总让人坐立不安,一个享受证明题那种逐层推倒过程的人特别不能接受。

所以这个利率问题,感觉一定要用自己知识范式里的逻辑推导出结果才能真正“过瘾”。我们不去造什么现钱未来升值的概念,也不去假设每个月还的钱里面到底本金是不是相等。现在只是求一个等效的月利率q出来,然后用它刻画我们的直观感受。下面试试在q不变的情况下,是否能求解这个问题。

对于拿到20000块钱后第一个月末,要还2266.67,这时欠人家的本金一直是20000,而这2266.67中包含还掉的本金部分用a表示。于是有:

20000 * q + a = 2266.67

即这个月还款的2266.67是还掉的一部分本金和利息的和。由于欠的本金一直是20000,所以利息就是20000 * q,而a是还掉的本金。

现在来到了第二个月末,仍然还款2266.67,其中还掉的本金用b表示。第二个月开始,我们欠人家的钱已经不是20000,而是20000 – a了,所以这个月的利息应该是(20000 – a) * q,这样就有:

(20000 – a) * q + b = 2266.67

对于第三个月来说,还掉的本金用c表示,依据之前的推导应该有:

(20000 – a – b) * q + c = 2266.67

依次类推,到第十二个月初,我们已经还了十一笔款,每次还的本金依次是a, b, c, d, e, f, g, h, i, j, k,所以现在欠的本金应该是(20000 – a – b – c – d – e – f – g – h – i – j – k),那对于最后一个月来说有

(20000 – a – b – c – d – e – f – g – h – i – j – k) * q + l = 2266.67

最后第十三个等式是,a + b + c + d + e + f + g + h + i + j + k + l = 20000,就是每个月还掉的本金和为最初的欠的20000。

现在一共有十三个方程,十三个未知数,我们只要求出来方程里的q a b c d e f g h i j k l的正实数解即可。这个方程应该可以手动化简,不过偷懒的方法是用现成的工具,如Matlab或者 Wolfram。以Matlab为例,以下命令可以解开方程:

syms q a b c d e f g h i j k l
[q_, a_, b_, c_, d_, e_, f_, g_, h_, i_, j_, k_, l_] =  vpasolve((20000)*q + a == 2266.67,(20000 - a)*q + b == 2266.67,(20000 - a - b)*q + c == 2266.67,(20000 - a - b - c)*q + d == 2266.67,(20000 - a - b - c - d)*q + e == 2266.67,(20000 - a - b - c - d - e)*q + f == 2266.67,(20000 - a - b - c - d - e - f)*q + g == 2266.67,(20000 - a - b - c - d - e - f - g)*q + h == 2266.67,(20000 - a - b - c - d - e - f - g - h)*q + i == 2266.67,(20000 - a - b - c - d - e - f - g - h - i)*q + j == 2266.67,(20000 - a - b - c - d - e - f - g - h - i - j)*q + k == 2266.67,(20000 - a - b - c - d - e - f - g - h - i - j - k)*q + l == 2266.67,a + b + c + d + e + f + g + h + i + j + k + l == 20000,q,a,b,c,d,e,f,g,h,i,j,k,l)

解出来的正实数解为:

q_ = 0.050797584803673053315458232134993
a_ = 1250.7183039265390064504114991344 
b_ = 1314.2517730357534996140256951894 
c_ = 1381.0125889299148582748617671113 
d_ = 1451.1646930310222824133176198543 
e_ = 1524.880354589361811121911194386
f_ = 1602.3405937170699537423596414655 
g_ = 1683.7356259107806443553650286218 
h_ = 1769.2653291549490520943120595088  
i_ = 1859.139734752896094790930379943 
j_ = 1953.5795430908845605782957674657
k_ = 2052.8166656017646249690438355595
l_ = 2157.0947942590636115951655117603

所以这里抽象出来的等效月利率q = 0.050797,则年利率P = 12 * q 或者(1+q)^12 – 1。之所以P是这两种情况,是因为很多金融机构对年利率的定义不同,通常的P = 12 * q 给出的年利率数值会小一些,在贷款时使用更具有迷惑性,让借钱的人直观上觉得划算。但实际计算时用的P应该是(1+q)^12 -1,这是考虑了复利,相当于每个月末把本金取出来,又一起存进去。我认为关于这个q和P的关系比较容易理解,所以就不赘述了。

这样其实等效的P应该是(1+q)^12 – 1 = 0.81,即年利率为81%,比一开始的36%要高很多。这里的81%也是一个概念值,给你这个数值并没有办法直接用于计算比如到底还了多少钱之类的问题。它只是量化了我们最开始的直觉,即每个月还钱比到期一起还时的情况,其利率要更高,而且高很多。

推导到这里,基本上算是完事了。但是这个问题与实际世界是如何建立联系的呢。直到这时,我才了解,其实上述每个月还固定钱的问题就是所谓的等额本息还款。另一种偿还贷款的方法叫等额本金。等额本息看起来舒服,因为每个月数额整装,可背后原理复杂;等额本金看起来数额零散,不过背后计算简单。

既然对应到了现实世界的问题,那就有现实的工具可用。比如同样是这个问题,我们可以打开招商银行的计算工具,在等额本息工具下,输入本金20000,分12个月,年利率部分输入P = 12 * q,即60.96%,点击计算,你就发现其计算结果是每个月还款2266.67。这里银行用的P并没有填写我们刚刚的(1+q) ^ 12 – 1,原因就是银行贷款为了让你心里预期低一些,选择P = 12 * q。其实这两种P如前所述都没法直接用于计算,只是给你一种直观感受。真正计算用到的是q。

关于这个问题至此已经可以说讨论完整了。

最后想从纯数学的角度再看一下刚刚的方程,我们唯一的假设是q它作为一个月等效利率是不变的。如果月利率q可变,而假设每个月还款中本金是固定的呢,即用a b c d e f g h i j k l表示每个月的利率,而还的本金是q,仍然用Matlab解开这个方程就变成了:

syms q a b c d e f g h i j k l
[q_, a_, b_, c_, d_, e_, f_, g_, h_, i_, j_, k_, l_] =  vpasolve((20000 - 0 * q)*a + q == 2266.67,(20000 - 1 * q)*b + q == 2266.67,(20000 - 2 * q)*c + q == 2266.67,(20000 - 3 * q)*d + q == 2266.67,(20000 - 4 * q)*e + q == 2266.67,(20000 - 5 * q)*f + q == 2266.67,(20000 - 6 * q)*g + q == 2266.67,(20000 - 7 * q)*h + q == 2266.67,(20000 - 8 * q)*i + q == 2266.67,(20000 - 9 * q)*j + q == 2266.67,(20000 - 10 * q)*k + q == 2266.67,(20000 - 11 * q)*l + q == 2266.67,12 * q == 20000,q,a,b,c,d,e,f,g,h,i,j,k,l)

结果为

q_ = 1666.6666666666666666666666666667
a_ = 0.03000016666666667030464547375838
b_ = 0.032727454545454549423249607736414
c_ = 0.036000200000000004365574568510056
d_ = 0.040000222222222227072860631677839
e_ = 0.045000250000000005456968210637569
f_ = 0.051428857142857149093677955014365
g_ = 0.060000333333333340609290947516759
h_ = 0.072000400000000008731149137020111
i_ = 0.090000500000000010913936421275139
j_ = 0.12000066666666668121858189503352
k_ = 0.18000100000000002182787284255028
l_ = 0.36000200000000004365574568510056

注意,这里的q已经是每个月要还的本金了,而变化的a到l是每个月的月利率。但现在不过是纯粹的数学计算了,我们并不是在解等额本金问题。通过a到l没办法抽象出一个所谓的等价月利率或者年利率。

题目为什么叫战争呢,因为我和媳妇周末讨论怎么计算时,尽管两个人都一知半解但却几次三番激烈异常,时不时面红耳赤,更有甚者唇枪舌剑。当然,问题最后还是在健康平静恩爱的气氛中解诀了。

小迁徙

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

2019大计

专业方面

[-] 完成两个内核利用的编写 (wz)

[-] 完成一到两个浏览器利用的编写 (1793)

[-] 跟进已有研究的进展,形成一到两次会议议题 (infiltrate, mosec)

[-] 每周看至少两次微博或者twitter,关注业内的最新进展

[-] 阅读10篇左右学术论文,跟进学术界的研究进展 (arm nail gun)

[-] 阅读至少一本专业书籍 (TEE)

[-] 每个月至少进行一次书面总结


生活方面

[-] 阅读5本书,《地球往事》,《局外人》, 《沙丘》

[-] 出游三次 《迈阿密/密西根,bannf&jasper&Ottawa,Munich,花鸟岛》

[-] 每周去健身房两到三次

[-] 跆拳道30次以上

[-] 每个月至少一篇博客

[-] 每个月至少一部电影

[-] 不再消磨于游戏视频

[-] 每个月至少冥想一次

[-] 高考题两次,考研数学题一次

[-] 每周弹琴两次以上

外星人起死回生指南

故事发生在爱丁堡一个阳光明媚的早晨,男主将一杯苏格兰现磨咖啡放在工位桌上,伸了个懒腰,准备开始一天的科(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,原因也是因为目标算法比较老。

拯救rm误删的文件

即便采用了定时备份,云盘同步,甚至GIT,却还总是不及随手的一个rm来的杀伤力大。

今天又又又遇到了这个问题,rm随手把刚刚写好的一个cpp文件给删了,一瞬间脚都软了,上周写了一周的ROP,劳民伤财且洋洋洒洒几百行。

Linux下有很多文件恢复类的软件,前序操作一般是umount磁盘,再备份磁盘,最后用这些软件扫描分区,找到误删文件。

只不过现在遇到的情况有点特别,ext4格式的磁盘位于虚拟机当中,整个分区差不多200G,编译Android代码用的。光找个空闲磁盘存放这么大的分区就足够苦恼了,如果还要对这么大的磁盘进行磁盘恢复,时间肯定久到不敢想。

毕竟这个cpp我还是定期备份的,相比之前备份的版本,只是增加了几百行代码而已,现在只要能找到增加的这几行,哪怕有些错乱,理论上再调整下格式就可以了,并不需要传统的文件恢复工具重磅来访。

首先,在分区中搜索新增文字片段中的关键字,关键字要稍微长一点避免重复,比如我的例子中:

通过上面的搜索,可以很快(十分钟以内)找到目标字符串所属偏移(好几组)。

接下来只要从目标分区取回文件内容片段:

到此,基本上text.save里存着的就是你的文件内容了,毕竟fgrep时输出的偏移好几组,dd时倒是可以换几个试试,看哪个输出的结果最好。

下载编译AOSP

下载


Android的源码下载编译可以算是一个持久性老大难问题了,如果是在国内弄,更是涉及政治,经济,历史,文化的方方面面:-)

除了安装Google文档里的依赖库,源码本身的下载编译才是重头戏,我目前比较试过行之有效的方法如下:

首先,从清华开源站下载最新的源码tar包,解压后,修改.repo/manifests.git/config文件

然后,repo init -b xxx到你要的分支,再repo sync就可以了

选择两个站是因为,清华有tar包,可以显著提升下载速度,但至少按照他们的文档来看,仅支持http方式的git同步。相比ssh的git在repo sync阶段要慢且非常容易中断,所以下载好的.repo要修改url指向科大的源。

再来就是repo sync总是提示中断,下载错误,无论你的网络有多好,同步半个小时左右就会出现这个问题。对于这一点也确实试了所有灵丹妙药,最后发现无非就是限制线程数量,然后反复同步,为此专门写了一个脚本自动反复单线程repo sync,想要停止的话,touch stopme即可

 

编译


至于编译一般来说问题不大,无非就是Java版本可能出些问题,或者堆大小要调高之类的,编译开始前就先设置一下堆的大小:

 

刷机


由于编译好的rom并不完整,仅包含boot.img,system.img等基本信息,可能和手机内的其他模块如modem,radio,bootloader等冲突,最好先用同版本或接近版本的factory image刷一次,然后再到编译好的rom目录执行

如果刷机以后系统无法启动,可能是bootloader版本不匹配导致的,从官网下载同版本rom后,先./flash-all一下就好了。