某国产“自主”操作系统专属 Electron 应用“移植”
某国产“自主”操作系统专属 Electron 应用“移植”
2020-12-30_16-53.png
最近在 Linux 相关群组内看到某个国产软件给某个国产系统提供了专版应用,这个专版应用在别的系统上都不可以正常运行,但是有老哥发现这个 xxxx
程序读取了 lsb-release, libyyosdevicea.so 和 os-release,在替换这三个文件成 yy 系统的文件之后,就可以直接登陆了...所以我就进行了分析和学习。
自主规避模式,将某操作系统的名字换成了 yy,而某国产软件的名字换成了 xxxx。请不要无端联想。
分析
首先先解压 deb 包,看到的是一个 Electron 程序的正常架构。
~/d/r/u/v2 > tree.├── control├── control.tar.gz├── data.tar.xz├── debian-binary├── md5sums├── opt│ └── apps│ └── com.xxxx│ ├── entries│ │ ├── applications│ │ │ └── com.xxxx.desktop│ │ ├── doc│ │ │ └── xxxx│ │ │ └── copyright│ │ ├── icons│ │ │ └── hicolor│ │ │ ├── 128x128│ │ │ │ └── apps│ │ │ │ └── xxxx.png│ │ │ ├── 16x16│ │ │ │ └── apps│ │ │ │ └── xxxx.png│ │ │ ├── 256x256│ │ │ │ └── apps│ │ │ │ └── xxxx.png│ │ │ ├── 48x48│ │ │ │ └── apps│ │ │ │ └── xxxx.png│ │ │ └── 64x64│ │ │ └── apps│ │ │ └── xxxx.png│ │ ├── lintian│ │ │ └── overrides│ │ │ └── xxxx│ │ └── pixmaps│ │ └── xxxx.png│ ├── files│ │ ├── blink_image_resources_200_percent.pak│ │ ├── content_resources_200_percent.pak│ │ ├── content_shell.pak│ │ ├── icudtl.dat│ │ ├── libffmpeg.so│ │ ├── libnode.so│ │ ├── LICENSES.chromium.html│ │ ├── locales│ │ │ ├── zh-CN.pak│ │ │ └── zh-TW.pak│ │ ├── natives_blob.bin│ │ ├── pdf_viewer_resources.pak│ │ ├── resources│ │ │ ├── app.asar│ │ │ ├── electron.asar│ │ │ ├── sae.dat│ │ │ └── wcs.node│ │ ├── snapshot_blob.bin│ │ ├── ui_resources_200_percent.pak│ │ ├── version│ │ ├── views_resources_200_percent.pak│ │ └── xxxx│ └── info├── postinst├── postrm├── sign└── usr ├── lib │ └── license │ └── libyyosdevicea.so └── share └── doc └── com.xxxx ├── changelog.Debian.gz └── copyright32 directories, 106 files
这里我们直入正题,看下 opt/apps/com.xxxx/files/
的 xxxx 文件,发现这个文件有点大,IDA 分析不动...所以就先照着别的老哥说的,看下 opt/apps/com.xxxx/files/resources
下的 app.asar。这个文件直接用 asar e app.asar $解压到的目录
就解压开了。比较关键的是下面的函数,应该是通过 node.js 的 module 进行生成 token,然后将这个 token 塞入 http 请求的头部,然后服务器进行特殊校验就可以判断是否允许通过了。
function getToken() { let pathname = path.dirname(__dirname); let wcs = require(path.join(pathname, './wcs.node')); let kp = path.join(pathname, 'sae.dat'); let buf = wcs.get_cc_data(1, kp); return buf.toString('ascii');}function bindToken(session) { session.webRequest.onBeforeSendHeaders( { urls: urlFilters }, (details, callback) => { if (details.url.indexOf('/cgi-bin/mmwebxxxx-bin/webxxxxnewloginpage') > -1) { details.requestHeaders['extspam'] = getToken(); details.requestHeaders['client-version'] = app.getVersion(); } } );}
那么现在就去分析下 wcs.node 了。看了下 wcs.node 的 strings
结果,发现没有什么关键的字符串,并且在 lld
的结果中没有发现 libyyosdevicea.so,猜测用了 dlopen
进行动态加载,所以查了下 dlopen
的交叉引用
Direction Type Address TextDown p sub_7B180+31 call _dlopenDown p sub_800D0+C5 call _dlopen