整理一下自己的程序猿生涯

其实也不知道为什么想写这个,就是看历史的东西突然想写一个这样的记录,来看看自己都弄过什么东西


2014

  • 开始接触代码,完成了下载脚本bdown(已大体废弃),和客户端缓存转码合并脚本bili

image

(那年暑假入了b站,在家ipod4能正常用最新的b站客户端,但是学校里拿的ipod3 5.1.1只能用一个特别老的,13年的版本,由此开始写代码)

  • 11月,原Tundra开发维护的BiliPlus停止服务并开源,拿了一份挂在了一个php空间上,但再未管理过网站

(算下来搭建bp比bdown早,因为早期的需求只是客户端解码flv极卡,后来无法忍受客户端的缓存bug开始自己写下载)

2015

  • 4月,把初期bp的代码进行了一些改进,因为有写bdown的经验对主流解析都比较了解。同时遇到了几位至今也在互换情报的重要好友,包括@张一环 等等各路大佬

image

(此时已是临近高考,我却每周末回去一直在搞这东西()

【那个暑假已经忘了写过什么了,主体应该就是半自学php改bp】

(当时主力机5s已因作死移动/usr/libexec到stash而入狱。妈的这个目录以前一直是没有问题的,为什么突然就死了。也正因此才会想要去剖析出softwareVersionExternalIdentifier的用途)

2016

  • 1月,爬丝沿着当初我的乐视云api解析贴找到了我,两人相聊甚欢。当时我也是认识pass的,毕竟是不二压大佬了,letv2pass我也用过传了几个视频
  • 3月,进行了一场利用收藏夹的视频全扫(现已不可行),并把数据放置服务器作aid搜索库
  • 同月,和pass第一次面基,俩人都在沈阳,相性也不错
  • 4月,源自一次偶然的github闲逛,发现了一个b站的隐藏的,分发用api(已在兽娘之后死亡),同样开了一批采集并添加了cid信息库
  • 10月,京吹时因为独特的港台直看功能,加上某个zz在3k眼前跳,然后yk就来恶心人了一阵。

(这个事其实早期也是自己想趁此火一批,当时把默认播放器改成了带跨区功能的。因为这个之后就换成了限制了)

  • 11月,借着flv.js,开始写扩展以进行更方便的“播放”,同时结识了xqq

2017

  • 2月,改动flvjs,添加了实时码率,同月改动主站abplayer,完成了一个直播html5猴子。【半个月后官方html5上线测试】
  • 3月,改动CCL添加canvas绘制,触坑无数
  • 同月月底,本是想装逼一番,搞了b的兽娘12(每集大约下午5点上传,晚上25:30网络放送),结果因壁吧群里不知名的二五仔把忘记撤回的两张图片传遍全网。所幸仅仅只有两张不能说明什么的图片,同时传开时距离tv放送只剩20多分钟,没有造成太大影响。不过因此相当一批相关的接口就死了(细究还是对不住b站的伙计,要是那天我是下午六点去搞的话,估计就不会这么清淡了)
  • 4月,鉴于本季某苣的火热,@ipcjs 的猴子同样一举成名,于是顺手给api添加了跨域权限,并帮着改动了很多地方(直接把同步blocking大改成全异步了)
  • 5月,将臆想多时的分段mp4支持完成了并加到了flv.js中。同月,本着好不容易写出一个功能,不能荒废的原则,完成了优酷html5扩展。【一个月后官方html5上线测试】
  • 8月,与@power 合作(他提供服务器与存储账号)开始进行番剧视频转存项目,自己写出php下的多线程下载模块用于减小限速影响。项目断断续续持续到11月初才完成,期间共计存了25T的视频
  • 9月月底到10月,在B站更新app新版动态后不久,开始着手写了一个web版动态,这一次所有api转发使用全部用了lua模块,虽然说基本也就是大范围复制(自己造了ngx-lua下http请求的轮子)。【官方web版与11月中旬上线】
  • 11月,将原本计划于7月份开发却坑了的acfun播放器写完了,使用反响还算不错
  • 同月月底,将转存项目链接入口加入了biliplus,并整合加入了新番剧自动任务以及用户队列添加。不同于静态数据执行时的服务器多开,这次换用了pcntl多进程进行同时5任务

2018

  • 1月,完成首个正式越狱插件【ReplayKit Everywhere】,功能为将ReplayKit引入所有程序,便捷录屏并附带质量控制覆盖系统默认码率

To be continued…

bang dream proto相关

本文相关轮子: proto读取导出 | 定时任务本体数据库对比主数据


因为上周的一个想法,写出了redive和cgss的master数据库diff库,还造了一波bundle解压的轮子

redive第三个号被制裁了,平稳科技流也开始查了

土豆的内容星月大佬写离线的时候已经表示过master不可行,都是登录时返回部分master,所以就可以放弃了

然后就是bang了,开搞前我还又去debug了一下,结果看到密钥瞬间才想起power之前给我说过

炸梦通信是protobuf,包括master和manifest也是,所以就必须要提取原始关系才行了。我刚开始还想尝试暴力提取数据,但是内结构和字符串都是wireType 2,没法区分

在之前我已经在Prefare博客上看到过说dump属性什么的,dnspy改了之后也没搞懂怎么看。后来在评论区看到回复才找到

Perfare:邦邦用的是protobuf-net不是Google.Protobuf,不需要.proto文件,你只需要找到带ProtoContractAttrbuit的类并还原出properties上ProtoMemberAttribute的值就可以序列化了

知道入口后就开始观察了,搜索了一波然后看到master数据的类是SuiteMasterGetResponse(基本上各种proto类都叫GetResponse)

观察了下结构之后就开始写proto dumper了,以SuiteMasterGetResponse为入口,循环匹配含有 [ProtoMemberAttribute] 的成员,然后匹配子类递归。匹配中就需要特殊处理,比如xxxx[]就是一个数组,List<xxxx>也是一个数组,Dictionary2<xxx, yyy>就是键值对,观察了下数据分布这里的结构是

即key+value形式

名称和类型之类的导出做完之后,就是tag id了。tag id并不是连续数,所以就需要读取原始数据。每个成员的ProtoMember属性都带一个地址,这个地址是一个函数,每个函数看起来都是这样的:

可以明显看出是个只有5条指令的函数,而id明显就是第3条,那么就只需要读取出立即数就行了

结果这个可以说是整个读取里面最大的坑了。因为某种优化,编译器输出的立即数赋值指令有两种:

movk指令的话,很简单,匹配中间的i位就可以了

但是orr整整卡了我两个小时,在群里大佬stat带领下才逐渐搞明白读取方法

简单讲,从第二字节开始,第一位为0,第二位N表示是否64位,3-8位为immr——旋转数,第三字节1-6为imms——大小数。此处nnnnn恒为11111,表示W31寄存器,即WZR,或读0。立即数结尾imms位设置为1,然后循环右移immr位,即为所读立即数

这里本来imms还表示pattern大小,但其实也没做出来,因为都是32位的pattern。

搞定tag id读取之后就是一路爽了,稍作修改就能输出规范proto。导出代码gist

造完这么个奇怪的轮子之后又得继续造读取轮子。现有的开源实现没找到能快捷转换protobuf到php数组的,估计也是php类型太少会导致格式信息丢失吧。拿出之前读b站弹幕的轮子改了改,换了最近写的FileStream轮子读取内容(Utaha:你要记住自己的本质是一个轮子工(),读完之后再进行字典键值对处理,最后又一个自定义json输出美化的轮子

高潮来了

写完逻辑代码后跑了一遍,但是我在第二遍才加了core.filemode=false,一堆mode change,于是…

一 秒 爽 到

当场恢复了message导出代码,但是主逻辑不见了。今天早上花了一上午grep /dev/sdb1恢复(msys2竟然有这个设备映射),但是p都没找着。于是,又重新造了一遍自己刚造完的轮子(Utaha:你要记住自己的本质是一个轮子工(

这次记录的基本上就这些,还是要感谢各位前辈造好的轮子,我才能这么爽到(x

闲话x2

瞎记录

1、博客的一些更新

  • 服务器

服务器使用水萌大佬的机器也有三个月了,在刚开始的时候因为他们那边也是在不断调不断加东西,所以经常会爆炸,或者重启路由导致ddns ip改变。不过自从过年那次大爆炸之后一来,已经相当稳定运行了半个月了,可喜可贺,可喜可贺。

原始的vultr本来想着会被废置,不过我留下来当作自己的socks代理了(不是ss,纯socks5)不知道为什么好像比别人用的ss还稳,老见到他们说某某又墙了之类的,可能因为只有我一个人用吧(笑

SSL的话,本来我准备换le的野卡,结果还延期公开了。前两天稍微用 acme.sh 测试了一下可以csr同时生成两个域名的证书,爬丝的dnspod api我之前给他搞ddns ip自动更新的时候要过也可以用,到时候再帮他cron上

  • 音乐播放

两周前更改了一下逻辑,之前设置仅在首页播放,因为没有可靠的跨tab通信确保不重复播放的方法。

然后想到了一个方法,用localStorage保存一个值,不存在的时候记录为当前页并自动播放,并设置关闭时删除值;存在且不是当前页的时候不自动播放,不过生成并显示播放器,点击的时候覆盖值并在关闭时删除值

这样就完成了一个简陋的单tab播放的逻辑

  • 侧栏

并不满与现在的顶端固定实现,最理想的是先跟随滚动,到底后固定,继续向下返回时跟随向上,到顶后再固定,这种感觉

写了个跟随scroll的之后发现很难看,去爬丝站上看了看实现发现是动态切换position,虽然美观一些但还是有瑕疵。最后采用了youtube式的侧栏,即独立滚动条

2、CriWare Key Logger

那阵子倒腾redive,虽然说cri的key早都有了,但还是手痒搞了一个这玩意儿

在之前给 @CaiMiao 翻腾PlayerPrefs键名解密的时候看到C# string类的格式的时候对这些对象在内存中的分布又有了一些理解

按照Il2CppDumper导出的类结构,String类是:

然后内存中的结构是这样的:

然后观察了几个其他的结构体后,大概懂了这些对象的组成:存储一个对象存的肯定是个指针,指针指向的地方0-8是所有函数的地址,C风格函数中参数开头会有一个thisPointer,static调用的时候取0,public/private等等调用就传递对象地址。而比如取string.length的时候就是*((int*) (string+0x10) )

而理解了cs的string类的内存表示之后,我就着手写了一个CSStringReader:

而写的时候碰到的坑是我hook了CriWareDecryptionConfig的构造函数,但是永远读不到正确的key string地址。我倒腾了能有两个小时也没搞出来,然后突然想到,会不会是延后设置的?(我在ida中查看构造函数的时候认为已经设置过key的值,所以一直理解是生成的时候已经设置好了)在代码中加了个Timer触发之后果然读取到了正确的stringLength,果然够坑。

在最后为了(未来可能有的)使用简便,把代码固定函数偏移转移到了插件plist中,这样搞其他的就不需要重新编译了,美滋滋

(说起来,我好像不应该用long,key的长度是固定int64,应该用long long的……不管了,都8102了谁还用32位的ios啊(小并感))

有关redive的一些

プリンセスコネクト!Re:Dive

这一阵从土豆开始,到这次redive,逆向技能提升了不少

有了上次土豆的经验,这次一上来是准备抓网络的,结果死活进不去游戏,搞得我还以为梯子不够完备。第二天song跟我说这游戏检测root,然后我看了一眼发现他检测越狱,还是用objc检测的,笑死。flex用不了不清楚原因,随手theos编了个hook就进游戏了


进去后熟练下断点,直接下在AesManaged里,结果没触发。懵逼一阵搜到了RijndaerManaged,在这里抓到了密钥,fiddler响应一解,开了,欣喜试了个其他的,崩了

然后测试了下发现动态密钥,惊了。沿着找了一阵也没找到,于是放弃搞网络


打了一天后过不动图了,群里满是喊着”等一个科技“。然后我前几天看到过一个相关的文章,仿照着写了个hook,把atk开了个根号。出于好玩顺便试了下教程战役,结果简直笑死

hp设为5000:

hp设为1:


晚上的时候顺手dump了一波卡面,这游戏卡面真美,社保了

BaiduPCS

【3/7】记录RKE开发过程

先放上成品:esterTion/ReplayKitEverywhere BigBoss


这次搞的插件开始的时候算是很久之前了

最早的时候,在github里面找了一个实现了开始/停止的类,编译注入,然后用cycript调用。结果测试了一下质量过糟,就暂时放置了

然后就是放假后了,那一阵还在学校,因为实在是需要一个随时随地的录屏功能,所以把开始停止合并成一个函数,然后activator写了一个cycript注入调用的脚本,就这样凑活使用了

回家之后配好了theos环境,然后正式开始从一个附加类升级为hook型插件。写好了activator整合之后,就提交发布了1.0。但是因为跨进程通信抄了BigShot的objcipc,只兼容ios9。

在发布之前,我本来是研究过能不能用其他方法,但次次崩溃,后来发现原因是quicktime挂载的开发者工具disk导致的问题。次日重启手机后notify.h库正常工作了,于是将objcipc改为了notify,兼容了ios10

在找人测试的时候又一次意识到,需要一个开始录制的提示,不然过于不友好。苦恼地翻了半天flipswitch源码也不知道他用的什么方法,然后在devwiki上翻阅springboard相关类的时候看到SBBulletinBannerController,找功能全靠运气(上次找mltd的aes也是运气看到那串string,包括最早b站flash的secret也是dump内存硬翻到,真是没谁了)

1.1版本花了大概三天才更新,其中主要是等别人帮忙测试,基本上是一天联系上一次。本想让pass用他的6p测试,但他机子不知道什么毛病不能开启。

1.1提交次日,我开始着手研究能不能修改码率。查看进程的时候发现开始录制后会蹦出一个replayd,文件拖到电脑上扔进ida,一百多k的小服务代码量也不是很大,而且相比il2cpp的游戏来讲,这个daemon可全是objc啊!分析起来不要太爽。

一通观察外加文档搜索,replayd用的AVFoundation的AVAssetWriterInput进行流编码,而配置都是传给initWithMediaType:outputSettings:方法。这个相当简单了,单开一个dylib注入replayd,hook调这个方法。首先在里面观察他的参数。期间出于有趣把filter改成了com.apple.avfoundation观察所有编码程序的参数,虽然最后只观察了微信。微信小视频编码设置的是1.2m视频+64k音频。

简单尝试了一下修改参数可行,就暂时没有管这里了,有一个更关键的地方需要解决。

之前也提到过,rk音频出奇的烂,不仅仅是码率,而且有一点是他会把左声道塞到输出立体声里,然后造成一些音乐变得极其难听。在ida里找了半天,最终发现replayd从AudioToolbox提取app的声音。而对比输入参数,我发现苹果程序员不知道出于什么理由,设置提取音频的声道数为1……

AudioToolbox的AudioQueueNewInput函数是c函数而不是objc方法,不过ms注入也提供了c函数的hookf。于是一套简单的参数修改,就成功的修复了录制成品的声道问题。

声道问题得到修复可以说我是心情大好,这个问题我自从试用过rk之后一直纠缠心头,也是我不愿意用rk录视频的原因。谁会愿意用一个只能录制左声道的东西。

然后就是一个比较简单的了,加入一个PreferenceLoader入口。改变码率我计划制作的是一个选单选择输出质量,所以就需要一个新的设置页了。原本我是不计划再写一个单独的bundle的,只用纯plist,目前的功能倒是也实现了,但是rk的录制文件会存在临时文件夹里一直留着,不会主动删除,直到下一次同一程序覆盖(按照包id命名文件)。这方面我计划写一个大小统计+删除功能,所以还是逃不过bundle,这些之后再说。

我原计划的最高档码率是20m,测试的时候我注意到20m会导致设备变卡,当然可能只是因为se硬件开始过时了,但毕竟还是要自用的,于是最高档设置为了15m,相比系统默认的2m(宽高1600以上3m)已经高很多了。我自己在玩了几次15m录制之后选择了4m,对于4寸屏幕而言这个cbr码率也算是差不多了,毕竟是要录来投稿的,破b也会二压。

(制作完之后我意识到这些码率大概都不够ipad使用,那个屏幕可能得需要30m能算是顶配码率?但我手上也没有支持的pad,家里6年前的pad3还停在卡的不行的802上)

到目前为止基本上的开发笔记就这么些,而我现在备忘录上已经又有了一堆todo,包括全局麦克风开关(我从不录麦)、改进notify listener声明之类,以及设置bundle制作。所以,未完待续?


02/13追记

上面那些是到1.2版本的,1.3做完也是有一阵了才来接着写

首先是写了一个全局麦克风开关,像我这种只录屏从不录麦的,直接是全程关闭的

设置bundle稍微搜了一下就看到可以创建子项目,theos这方面足够智能,会自动打包子项目。至于主设置内容依然是plist导入,所以倒也不复杂

有了bundle之后就可以搞一个临时文件大小统计了,原本期望是外面显示总大小,进入一个列表可以单独删除。但是devwiki上的样例并不能使用,搜了几下也没有类似内容,就把这个想法阉割了,转为加了一个全部删除的按钮。在最后完成的时候,又加上了一个ifile打开链接,格式也简单,ifile:/User/Library/ReplayKit

主要想加的加完了,稳定性上就在几个主要的地方加了try catch,插件成功变stable(迫真)

iOS11目前还不清楚怎么搞,有点想法要不要给系统录屏搞一个质量控制。我手头反正也是没有设备,再说吧


03/07 v1.4追记

1.4首先是加了跳过权限提示。从shared_cache里导出了框架后跟着开始录制的函数一路寻找,权限的提示依然是在replayd里发出的。看了函数后发现这个权限提示的选项是一个同步阻塞的通知(CFNotification),这也解答了我为什么alert不会导致bang dream退房间而开始录制会。

是否提示的判断是对比一个记录,而直接根据设置把这个函数选择调用原始或返回true就可以满足需求了。

做完提示跳过后顺手做了动态监听名,自己看起来爽到就是划算(

然后是做了一个自动保存,而为了不被系统相册权限限制,找了下框架调用的保存函数。不过说实在的,共享缓存里的框架在ida里真的难看,到头来也没找到怎么保存的,只是半猜加半搜索看到了PhotoLibraryServices下的PLAssetsSaver类下的saveVideoAtPath。这个方法的回调block参数在ida里看到有一个或三个参数,我用cycript试了一阵,试出来一个参数的block是NSURL,没懂三个参数是怎么个版本,反正就这样随便用了。

因为框架实在是太难看了,有一个10.3.3回报使用一小时后持续failed to start直到重启我也没搞懂具体是什么原因。我所找到的-5803(FailedToStartError)错误只有两处,一个是开始录制的时候available为false,另一个是replayd里取 isApplicationInForegroundWithBundleIdentifier:bundleId 的时候返回了false

这几天整的一些东西

为了便捷录制,ReplayKitEverywhere简陋版搞定了

用了cycript和activator自定义命令

ReplayKitEverywhere.zip


然后是前一阵我终于解决流量下使用pac代理的问题了

搜到的只有修改preferences.plist,但没等生效,重启就重置了

后来看到这个设置不是仅在重启时加载

然后就写了开机项,插到了cydia里(懒得再写LaunchDaemon了)

于是我现在流量无缝google了,巨爽啊(

(促使我重新研究的主要原因是,l2tp疯狂被干扰,服务器443没问题,只有l2tp连不上,然后socks5虽然按理说都是明文,但就是贼稳定)

如果需要添加代理域名的情况,需要root下killall -9 CommCenter(联通每次弹的好烦啊


最后是今天搞了一整天mltd

因为搞好了流量代理,所以又想坑回这个辣鸡游戏了

结果打不开,才想起当时研究的时候就碰到过,这游戏不走代理,hosts都不认

改global-metadata.dat里的域名,进去之后突然又连不上了

然后搞一通抓包发现,title里GetVersion之后,域名竟然还原了!?

看来这个鬼地方写了服务器,要实现我的无墙土豆,只能搞密钥了

ida调试ios,整了一上午,竟然真的让我瞎翻翻到了

QQ图片20180120221640

代理request,修改game_server,一气呵成,完美无墙麻辣土豆get

(资源cdn不是google家,所以不需要搞什么操作了,速度也挺快,美滋滋)

也许是年终总结

2017混结束了

是的,我自己感觉这一年就是混过来的

这一年里做了的比较大的项目

  • flvjs mp4 播放
  • 优酷播放器
  • 视频转存
  • acfun 播放器

直播播放器都不能算大项目,说实在轮实用性比不上助手,毕竟我自己也仅仅是偶尔看直播

不过一年真的是能改变很多东西,去年这个时候,我还是选择停留在ff45,用着flash播放器;现在我则是停留在ff56,坚守legacy插件,flash则是几次重装系统之后就再也没有安装过了。明年这时候,谁知道呢,说不定我会离开火狐阵营?(苦笑)

flvjs mp4

反正就像上面说的,去年这个时候,我还并不看好,或者可以说完全不喜欢html5标准,所以起初做出来的播放扩展好像我自己都不用。

然后,随着火狐里的flash越来越难用,我终于是有一天转换了阵营,开始研究无flash。

flvjs魔改之旅,是从添加实时码率统计开始。

添加mp4的过程,模仿着现有的代码,功能完成了,也踩了不少坑,同样也获得了xqq的一些帮助,一些坑直到前不久才刚刚修复。总的而言,主体功能写了三天,难度也不算很高了。

优酷播放器

紧跟着写完flvjs mp4之后,一想到写出这个功能之后,除了自己的play helper之外,就再也没有人用了,就感到心态爆炸,boom,然后脑热就写了这个扩展。

这么个产物至今都不算完美,bug依然很多,我无力处理,也懒于处理。

我用自己扩展的唯一机会:车祸视频,最近一个月也是再没继续看日更,毕竟天天的内容都是差不多的电摩横冲直撞,王者霸气转弯,确确实实容易感到厌倦。

转存b站视频

这个项目可以说是充分体现了我的懒癌了

最早,power在5月份左右就提出了,想要转存全部番剧的想法,并且准备好了google教育账号。我当时以懒得开坑+考试,推迟到了假期。

考完试的那几天晚上,造了php多线程下载的轮子;

然后7月过去了,断断续续写代码,最后在8月初,才开始在几个无限流量服务器上开始跑任务;

由于写出来的代码是单队列,在那几个linux服务器跑起来效率很低,然后8月中旬的时候,power拿了代码,放到了一个win服务器里开始跑并发。

然后…一转眼就是10月了,期间我基本没想起过项目。一次提醒后我才去整理结果数据,然后重跑失败任务之类的。

等到初期任务跑完,已经又是一个月过去了。挂上了中转代理下载之后,我又写了写队列任务,算是正式开放了合并转存。

这个系统也是有几个坑没有填,重置任务状态,转移任务服务器(旧的要弃用,需要换)等等。

acfun 播放器

然后就是ac了

原本暑假有个写播放器的计划,但当时遇到了样式困难,写了半天就坑了。

原本想好的完美简介是“一个B站播放器,送个缺B乐的各位”。但是坑计划之后我加上了yt主题并设为了默认,也是不准确宣传了(笑

说来奇妙,我完全不用ac,也不知道写这为了啥;即使如今写好了,也仅关注了一个steam周报。

虽然完成后确实得到了一些支持,也确实有真切的希望扩展能更好更完美的人。

 

写代码的破事说完了,再说说生活吧。

回到开头,这一年是混过来的

现在处在一个重大抉择的时候,大三了,需要决定自己的方向了。

家里人希望,或者说是要求我考研。本科录取没能进计算机,被调剂到了物理,现在要考当然是希望考进计算机,但心态上始终有着很大问题。

提不起学习动力。

两年多大学,整个人越过越颓废,学业越来越吃力(不如说是没有使劲)。

自己逐渐被懒惰的动物本性拖住,不知如何才能找回高三时的那种冲劲。

也许这就是进入大学前,一直听到别人说,也一直嗤之以鼻的,缺乏目标的现象吧。一直觉得自己不会是那样的,我可是有目标的人;到头来却发现,自己并没有那么特殊。

也或许是看到认识的人都是一种,算是活得风生水起,从而对自己方向感到的一种困惑吧。

这个学期考了两个外语考试,N2和托福,N2出成绩还有一个月,考完看答案估计自己要么擦线过,要么刚好在线下;托福则是考了86,半裸考,不算低,也不算高,考出来什么用都没有的分数。专业课考试也是持续走低,补上一个又挂一个。

 

如果你看到这里了,很抱歉让你看到了一堆牢骚话。

这么个总结,写出来或许仅仅是用来发泄而已。

每一学期开始都希望自己能真正的付出足够努力,却总是在结束时发现,只是又混过了一段日子。

 

12/31 2017

esterTion ( ͡° ͜ʖ ͡°)