Flutter

flutter - blutter

0x1 #

手把手带你逆向flutter。

如今flutter的逆向光靠使用reflutter已经有些不行了,在逛github的时候发现了一个项目 worawit/blutter:Flutter移动应用程序逆向工程工具

根据作者的步骤来。

win,先把Visual Studio 2022 给安装上,配置好C/C++的开发环境。

期间因为需要访问github,所以最好使挂上代理,注意将port替换为你代理的端口

set HTTP_PROXY=http://127.0.0.1:port
set HTTPS_PROXY=http://127.0.0.1:port

克隆下来

git clone https://github.com/worawit/blutter.git
cd blutter

安装所需的库文件

python scripts\init_env_win.py

然后把flutter软件里的lib文件夹提出来,如arm64-v8a文件夹,注意两个文件都需要(libapp.so、libflutter.so)

在win的所有应用里面找到Visual Studio 2022 里面的 x64 Native Tools Command Prompt for VS 2022

在里面输入,注意在此终端仍建议挂上代理(需下载很多),一定注意代理

python blutter.py ./app/lib/arm64-v8a ./output

会有相当多的需要编译,cpu都给干烧了

C:\Users\jinchuan\Desktop\2\blutter>python blutter.py ./demo ./output
Dart version: 2.19.3, Snapshot: adb4292f3ec25074ca70abcd2d5c7251, Target: android arm64
Cloning into 'C:\Users\jinchuan\Desktop\2\blutter\dartsdk\v2.19.3'...
remote: Enumerating objects: 2361, done.
remote: Counting objects: 100% (2361/2361), done.
remote: Compressing objects: 100% (1912/1912), done.
remote: Total 2361 (delta 82), reused 1427 (delta 63), pack-reused 0
Receiving objects: 100% (2361/2361), 1.34 MiB | 197.00 KiB/s, done.
Resolving deltas: 100% (82/82), done.
remote: Enumerating objects: 23, done.
remote: Counting objects: 100% (23/23), done.
remote: Compressing objects: 100% (22/22), done.
remote: Total 23 (delta 0), reused 7 (delta 0), pack-reused 0
Receiving objects: 100% (23/23), 119.77 KiB | 257.00 KiB/s, done.
Updating files: 100% (23/23), done.
remote: Enumerating objects: 3424, done.
remote: Counting objects: 100% (3424/3424), done.
remote: Compressing objects: 100% (2343/2343), done.
remote: Total 3424 (delta 1159), reused 2165 (delta 1048), pack-reused 0
Receiving objects: 100% (3424/3424), 8.90 MiB | 4.09 MiB/s, done.
Resolving deltas: 100% (1159/1159), done.
Updating files: 100% (3886/3886), done.
-- Configuring done (4.8s)
-- Generating done (0.1s)
-- Build files have been written to: C:/Users/jinchuan/Desktop/2/blutter/build/dartvm2.19.3_android_arm64
[124/268] Building CXX object CMakeFiles\dartvm2.19.3_android_arm64.dir\runtime\vm\profiler_service.cc.obj
C:\Users\jinchuan\Desktop\2\blutter\dartsdk\v2.19.3\runtime\vm/scope_timer.h(38): warning C4566: 由通用字符名称“\u00B5”表示的字符不能在当前代码页(936)中表示出来
[133/268] Building CXX object CMakeFiles\dartvm2.19.3_android_arm64.dir\runtime\vm\regexp_assembler.cc.obj
C:\Users\jinchuan\Desktop\2\blutter\external\icu-windows\include\unicode/stringoptions.h(1): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode  格式以防止数据丢失
C:\Users\jinchuan\Desktop\2\blutter\external\icu-windows\include\unicode/uchar.h(3156): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
//省略n多
C:\Users\jinchuan\Desktop\2\blutter\dartsdk\v2.19.3\runtime\vm/timer.h(156): warning C4566: 由通用字符名称“\u00B5”表示的字符不能在当前代码页(936)中表示出来
[268/268] Linking CXX static library dartvm2.19.3_android_arm64.lib
-- Install configuration: "Release"
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/lib/dartvm2.19.3_android_arm64.lib
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3/include
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3/include/analyze_snapshot_api.h
//省略n多
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3/platform/utils_win.h
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3/vm
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3/vm/allocation.h
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3/vm/app_snapshot.h
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3/vm/base64.h
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3/vm/base_isolate.h

-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/include/dartvm2.19.3/vm/zone_text_buffer.h
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/lib/cmake/dartvm2.19.3_android_arm64/dartvmTarget.cmake
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/lib/cmake/dartvm2.19.3_android_arm64/dartvmTarget-release.cmake
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/lib/cmake/dartvm2.19.3_android_arm64/dartvm2.19.3_android_arm64Config.cmake
-- Installing: C:/Users/jinchuan/Desktop/2/blutter/dartsdk/v2.19.3/../../packages/lib/cmake/dartvm2.19.3_android_arm64/dartvm2.19.3_android_arm64ConfigVersion.cmake
-- Configuring done (1.6s)
-- Generating done (0.0s)
-- Build files have been written to: C:/Users/jinchuan/Desktop/2/blutter/build/blutter_dartvm2.19.3_android_arm64
[22/22] Linking CXX executable blutter_dartvm2.19.3_android_arm64.exe
-- Install configuration: "Release"

以上为编译成功

...

flutter 初探

安装 #

首先我们手搓一个flutter apk来

去官网下载flutter 解压,配置环境bin目录

考虑网络因素,配置国内源,环境变量清华源

export PUB_HOSTED_URL=https://mirrors.tuna.tsinghua.edu.cn/dart-pub
export FLUTTER_STORAGE_BASE_URL=https://mirrors.tuna.tsinghua.edu.cn/flutter

配置 #

使用vscode,插件安装flutter,配置flutter sdk的路径

安装dart插件。

ctrl+shift+P 输入flutter 选择 new project,选择application,会生成项目

在里面随便加点加密

在文件pubspec.yaml文件中 dependencies节点下添加依赖

crypto: ^3.0.3

随后在项目的根目录下执行

flutter packages get

main.dart文件

import 'package:crypto/crypto.dart';
import 'dart:convert';

md5加密

md5.convert(utf8.encode("hello")).toString()

先测试一下是否正常安装,随后打包release版本

打包

flutter build apk

反编译 #

使用reflutter来获取dart文件,其中包含了……,使用详见

记得将apk重新签名一遍

打开,在app 数据目录,找到dump.dart文件

当你满脸欢喜的打开,搜索md5,诶,我函数呢,妈的。

淘金社区登陆

某个淘金社区,登陆有md5加密

用blutter 解析一下,找到hash_update的地址,放到frida的脚本中,在console的下面加一句

console.log('hexdump'+hexdump(args[0]))

打印出来4个uint32List,虽然看不懂,但是我们打印了hex

多看几次知道有随机的东西,在多看几次就知道应该是时间戳末尾在控制,反复测试得到所有出现过的字符,易得脚本


import requests
import hashlib
import time
def get_data(p):

    A=['gcw7eeh5','eegc15nnccccoqh5r7','15gcnncc','h5ccccgc15nnee/i','15gcnnq4oq/ih5oqccccee','15cc/ir7oqnnq4oqh5','nncc/i','h515r7q4oqcc','oqoqnnr7q4/i','h5nn']

    B=['eeoqh5','','h5ccoqeer7','oqr7','r7','oqccgc','oqccgcoqh515r7oqq4','oqgcoqnn/i','h515oqcc','oq']

  
    C=['','','/iq4','q4','op','','','','gc','2115oqr7q4/ioqccgc']
    # 16位时间戳
    t=str(int(time.time()*1000000))
    k=int(t[-1])

    # B164D0C43EDB3BAD89D1A073EBE9691D
    # 为固定值,可能跟随app版本所迭代
    
    #一下情况特殊出现,需要对换位置
    if k==8 or k==5:

        message= 'action=sendcode&phone={}&verifytoken={}&verifycodes={}{}B164D0C43EDB3BAD89D1A073EBE9691D..{}W1W2W3W4W5W6W7W8W901020304050607..{}{}'.format(p,'{system::verifytoken}','{system::verifytoken}',A[k],B[k],C[k],t)

    else:

        message= 'action=sendcode&phone={}&verifytoken={}&verifycodes={}{}W1W2W3W4W5W6W7W8W901020304050607..{}B164D0C43EDB3BAD89D1A073EBE9691D..{}{}'.format(p,'{system::verifytoken}','{system::verifytoken}',A[k],B[k],C[k],t)

    # print(message)
    return {'action':'sendcode','phone':p,'verifytoken':hashlib.md5(message.encode()).hexdigest(),'verifycodes':t}

data=get_data('19999994444')

resp=requests.get('http://bbs.taojingdaohang.cn/index.php',params=data)

print(resp.text)

测试正常发送短信

flutter 逆向小计

某个淘金社区,登陆有md5加密

用blutter 解析一下,找到hash_update的地址,放到frida的脚本中,在console的下面加一句

console.log('hexdump'+hexdump(args[0]))

打印出来4个uint32List,虽然看不懂,但是我们打印了hex

多看几次知道有随机的东西,在多看几次就知道应该是时间戳末尾在控制,反复测试得到所有出现过的字符,易得脚本


import requests
import hashlib
import time
def get_data(p):

    A=['gcw7eeh5','eegc15nnccccoqh5r7','15gcnncc','h5ccccgc15nnee/i','15gcnnq4oq/ih5oqccccee','15cc/ir7oqnnq4oqh5','nncc/i','h515r7q4oqcc','oqoqnnr7q4/i','h5nn']

    B=['eeoqh5','','h5ccoqeer7','oqr7','r7','oqccgc','oqccgcoqh515r7oqq4','oqgcoqnn/i','h515oqcc','oq']

  
    C=['','','/iq4','q4','op','','','','gc','2115oqr7q4/ioqccgc']
    # 16位时间戳
    t=str(int(time.time()*1000000))
    k=int(t[-1])

    # B164D0C43EDB3BAD89D1A073EBE9691D
    # 为固定值,可能跟随app版本所迭代
    
    #一下情况特殊出现,需要对换位置
    if k==8 or k==5:

        message= 'action=sendcode&phone={}&verifytoken={}&verifycodes={}{}B164D0C43EDB3BAD89D1A073EBE9691D..{}W1W2W3W4W5W6W7W8W901020304050607..{}{}'.format(p,'{system::verifytoken}','{system::verifytoken}',A[k],B[k],C[k],t)

    else:

        message= 'action=sendcode&phone={}&verifytoken={}&verifycodes={}{}W1W2W3W4W5W6W7W8W901020304050607..{}B164D0C43EDB3BAD89D1A073EBE9691D..{}{}'.format(p,'{system::verifytoken}','{system::verifytoken}',A[k],B[k],C[k],t)

    # print(message)
    return {'action':'sendcode','phone':p,'verifytoken':hashlib.md5(message.encode()).hexdigest(),'verifycodes':t}

data=get_data('19999994444')

resp=requests.get('http://bbs.taojingdaohang.cn/index.php',params=data)

print(resp.text)

测试正常发送短信

flutter

起因 #

放假在家闲的皮爆,有空学习写了个(其实在很久之前就有打算了) 因为网易云音乐下载有很多但是加密的,虽然可以解密,但是也不方便管理,所以就有了这个软件,可以嵌入元数据(mp3和flac),包括歌词封面等。同步网易云歌单,可以删除本地文件

开发 #

至于学习flutter,最开始知道flutter是因为逆向系列了解到的,听说写ui很方便,之前也有用过java开发。java的语法还也不是很喜欢。 网易云的api 参考: NeteaseCloudMusicApi

学习编程语言我不是很喜欢看视频来,慢得很,需要什么直接去搜代码就行了。 先看看官方的文档,demo,自己需要什么功能直接百度 虽然可能了解不深刻,但是跟着视频写代码更烦人

使用 #

设置里面要先设置cookie,只需要cookie中的MUSIC_U的部分,以及保存路径,这个保存路径是歌单的保存路径,如果下载的话会根据歌单名为文件夹保存在下级。

元数据默认嵌入所有

先根据歌单id获取歌曲,若要下载需要收藏歌单,下载完成会检测本地歌单中多余歌曲并徐闻是否删除。

似乎就这点鸟功能