要学习Electron逆向,首先要有一个Electron开发的程序的发布的包,这里就以其官方的electron-quick-start作为例子来进行一下逆向的过程。

https://github.com/electron/electron-quick-start

一、Electron打包出来的程序特征识别

要逆向Electron程序,首先第一步肯定是得确定这个程序是不是Electron打包出来的了,Electron打包出来的程序特征比较明显,尝试把exe文件修改为zip文件,然后用压缩程序打开,如果能够打开,至少说明它不是一个真的ELF文件,然后再看压缩文件中是不是有一个resources目录,下面有一个app.asar文件,如果符合这两个条件,基本就是Electron开发的文件了。

将其修改为zip格式:

然后使用压缩软件打开这个压缩包,寻找resources文件夹:

然后跟进去:

看到有个app.asar,那这个程序八九不离十就是Electron开发的了。

总结一下:

  1. exe后缀修改为zip用压缩文件打开
  2. 存在resources/app.asar这个文件

在本小节的最后抖个机灵,我们当然也可以靠Electron界面所特有的浓浓的Electron风格来辨识Electron开发的程序。 :)

二、Electron打包出来的文件的结构

将electron打包出来的exe文件修改为zip后缀,并用压缩文件解压,观察解压出来的结构:
Electron程序逆向(asar归档解包)_Electron打包_05
这里的重点是resources文件夹和这个exe文件,resources文件夹下有个app.asar是项目源码的归档文件,而这个exe则是程序的启动文件。也许你会注意到,下面还有个名为LICENSE.electron.txt的文件,也许会觉得这是一个可以用来标识Electron程序的方式,是的,不仅是这个,上面还有个chrome_100_percent.pak、chrome_200_percent.pak,但是这些文件都不是必须的,在有些包里面是可能会被拿掉的,也就是根本找不到这些文件,所以只能起到一些辅助作用。
然后就是进入resources文件夹,这下面有个app.asar文件:
Electron程序逆向(asar归档解包)_Electron打包_06
这个文件就是项目源码的归档文件,asar是一种归档格式,有专门的解压工具:
https://github.com/electron/asar/
使用工具解压就可以了,先安装这个工具

npm install --engine-strict asar
然后命令行进入到asar所在的文件夹,解包它:
asar e app.asar app
然后进去app文件夹,就能看到项目所有的东西都被归档存储在这里:
Electron程序逆向(asar归档解包)_Electron打包_07
完全可以拿着这份源码继续开发或者插入一些恶意逻辑重新打包发布。 三、asar文件结构浅析

asar格式的文件就是个归档文件,这玩意儿连压缩都没有,只需要看懂它的文件结构然后根据它的方式把文件提取出来就可以得到原始文件了。
使用010 Editor打开一个app.asar文件:
Electron程序逆向(asar归档解包)_Electron打包_08
人家比较洋气,把从最开始一直到那个很长的json结束都叫做文件头,最开始的4个字节应该是魔数之类的,第2和第3个int说实话没看明白啥意思,去翻了源码也只看到是用了一个pickle,似乎是chromium的一个东西,不要再继续深究了就放弃了:
Electron程序逆向(asar归档解包)_Electron打包_09
只需要知道第4个int是紧跟着的json的长度,json结束就是所有被归档的文件的字节挨着放的,而json中存放的就是这些文件的元数据,包括文件的位置、字节大小、是否可执行等等,从010 Editor中把那个json复制出来,看一下它的长度:
Electron程序逆向(asar归档解包)_Electron打包_10
而4562的转换为16进制则是11D2:
Electron程序逆向(asar归档解包)_Electron打包_11
而之前文件里存储的长度正是11D2,只不过是小端存储的,低位在前:
Electron程序逆向(asar归档解包)_Electron打包_12
好了,将注意力回归到json上,格式化观察下元数据到底是个啥样:
Electron程序逆向(asar归档解包)_Electron打包_13
files下存储的就是文件,记录了每个文件的偏移和大小,靠这两个值就能将其从归档文件中提取出来:
Electron程序逆向(asar归档解包)_Electron打包_14
对于目录结构它还是保存了其树形结构的:
Electron程序逆向(asar归档解包)_Electron打包_15
靠这个树形结构能够知道提取出来的文件应该如何存储,至此我们对asar文件的结构和原理已经比较清楚了。
但是还有一个疑问,既然asar只是一个归档文件,为什么还要采用这种格式呢? 一种说法是为了能够加密源代码,现在我们知道这是胡扯,asar只是一个归档文件没有加密作用,另一种说法是在Windows之类的地方,对资源路径的长度是有限制的,如果路径名过长访问的时候就会报错,也许大家都遇到过这种情况,将一些比较大的开源项目的源代码下载到本地解压会发现路径过长有些路径会报错,而放在归档文件中不解压这样路径就可以很深,并且读取的时候是读取的一个文件也就不用读取小文件磁盘各种寻址了。

四、二次开发插入恶意逻辑

本节是基于第二部分解包出来的源代码二次开发,使用webstorm创建一个空项目,将上面从app.asar中逆向处理的源代码拷贝过去,但是这里涉及到了几个比较蛋疼的问题,逆向出来的package.json文件里是没有devDependencies的,而electron是开发环境依赖,所以要自己手动:

npm init
npm add electron --save-dev
然后为package.json添加一个script:
"start" : " electron . " ,
Electron程序逆向(asar归档解包)_Electron打包_16
然后npm start看下效果:
Electron程序逆向(asar归档解包)_Electron打包_17
酷!程序已经被运行起来了!
然后想一想,如何搞个恶意逻辑呢,这里只是为了演示可以做这个事情,所以就在程序启动后显示一个对话框提示一下知道我们修改逻辑成功了即可。
在renderer.js中插入一个alert框,它会在程序启动的时候运行:
Electron程序逆向(asar归档解包)_Electron打包_18
再次npm start,效果就是这样的:
Electron程序逆向(asar归档解包)_Electron打包_19

五、重新打包发布带有恶意逻辑的包

5.1 整个程序重新打包

上面已经插入了恶意逻辑,接下来就是打包发布了,这里采用electron-builder:

https://github.com/electron-userland/electron-builder

先安装此工具:

npm install electron-builder -g

打包前需要先为项目添加一些打包选项,编辑项目根目录下的package.json文件,为其添加build选项:

"build": {
  "appId": "cc11001100.electron.example-001", // 程序包名
  "copyright": "CC11001100", // 版权相关信息
  "productName": "example-001",  // 项目名字
  "dmg": {
    "background": "res/background.png",  // 背景图片的路径
    "window": {
// 启动后窗口左上角位置 
      "x": 100,
      "y": 100,
// 启动后窗口的大小
      "width": 500,
      "height": 300
  "win": {
// 打包后的文件会有个图标,这个图标的路径,不指定的话默认的不好看 
    "icon": "res/logo.png"

注意这里的图标、appId什么的要对应好,然后在项目的根路径下执行:

electron-builder

即可开始打包,最终得到了发布包:

5.2 重打包asar

但是通常情况下我们都是不知道appId之类的东西的,这个时候只重打包asar,然后把目录重新打包为exe格式的zip包。

将项目的node依赖及其他无用的东西删除掉,只保留最开始解出来的东西就可以了,不然打出来的包会很大:

在项目根目录下将整个项目打包为app.asar:

asar p . / app.asar

然后用这个app.asar狸猫换太子,把resources下的app.arsr替换掉。

TODO 怎么把文件夹打包为exe呢? 这里还没找到比较好的方案

有意思的资料,这里是一个对Electron开发的程序的源码安全性的讨论:

https://github.com/electron/electron/issues/2570



Electron程序逆向(asar归档解包)_Electron打包_23
本作品采用知识共享署名 4.0 国际许可协议进行许可。


Service调用activity的方法 android service调用service还是dao

最近公司做项目时,遇到问题,在保存场景时需要一起保存其五类属性至各自属性表中,需要决定在场景的service模块调用属性模块的service还是dao,经查询,最终调用service层方法解决。原因如下:按我的经验,service a不能调用b的dao层,只能调用b的service层实现业务。 因为b的service是对dao的CRUD封装,如果是单库的话service或许只是dao的代理,但如

shell获取python脚本的输出 shell调用python获取返回值

1.py 脚本的 sys.exit([arg])直接调用exit(),注意是个函数要加括号,无参数默认返回码0,表示脚本运行成功。参数可以是整数也可以是其他对象,若是其他对象则返回码为1,如错误信息字符串,同时字符串内容也会输出。# test.py print 'test' exit('error message') # 运行脚本 python test.py echo $? # 上个命令