Android逆向技术59——Flutter with Rust会发生什么续篇(By LittleQ)

admin 2023年12月20日10:02:49评论40 views字数 5891阅读19分38秒阅读模式

Android逆向技术59——Flutter with Rust会发生什么续篇(By LittleQ)

之前,写过一期文章,在Flutter里面使用Rust, 那一种方案是将rust和flutter绑定到了一起,这种方式,总觉得不太优雅,如果能作为一个独立的库,这个体验就好了,然后翻了一下flutter_rust_bridge的那个库的文档,实际上这个是支持插件的,那么动手尝试一下吧。

实验环境

实验环境和上一篇文章保持一致。

准备工作

  • 安装melos
dart pub global activate melos
  • 新建插件项目
flutter create --template=plugin_ffi --platforms=android,ios,macos,linux,windows --org=com.littleq flutter_library_rust
  • 新建rust的项目
 cargo new rust --lib

项目结构

这里,因为我们要集成到flutter当中,因此,这里和纯dart有些区别,需要进行一些微调。

.
├── analysis_options.yaml
├── android
├── example # 示例文件
├── ffigen.yaml
├── flutter_library_rust.iml
├── ios
├── lib # dart库文件
├── linux
├── macos
├── rust # rust库文件
├── scripts
└── windows

由于调整了部分结构,因此后续需要对脚本进行微调,注意我这脚本和官方文档的有差异。

样例代码

  • rust
// api.rs
pub fn add(left: usize, right: usize) -> usize {
    left + right
}


  • dart
// src/ffi.dart
import 'dart:ffi';
import 'dart:io';

import 'package:ffi/ffi.dart';

import 'bridge_generated.dart';
import 'bridge_definitions.dart';
export 'bridge_definitions.dart';

// Re-export the bridge so it is only necessary to import this file.
export 'bridge_generated.dart';
import 'dart:io' as io;

const _base = 'rust';

// On MacOS, the dynamic library is not bundled with the binary,
// but rather directly **linked** against the binary.
final _dylib = io.Platform.isWindows ? '$_base.dll' : 'lib$_base.so';

final Rust api = RustImpl(
  io.Platform.isIOS || io.Platform.isMacOS
      ? DynamicLibrary.executable()
      : DynamicLibrary.open(_dylib),
);

  • 配置文件
rust_input:
  - rust/src/api.rs
dart_output:
  - lib/src/bridge_generated.dart
c_output:
  - ios/Runner/bridge_generated.h
extra_c_output_path:
  - macos/Runner
dart_decl_output: lib/src/bridge_definitions.dart
dart_format_line_length: 120
wasm: true

然后,我们直接构建代码就可以了

flutter_rust_bridge_codegen .flutter_rust_bridge.yml

到这里,准备工作就做完了,可以瞅一瞅,代码里面还有没有报错,有报错,说明哪里没执行好,检查一遍,没报错,就可以执行下一步了。

构建各个平台的代码

Android

这里,需要配置一下CMakeList.txt

set(LibraryVersion "library_name-v0.0.0") # generated; do not edit

# Unlike the Windows & Linux CMakeLists.txt, this Android equivalent is just here
# to download the Android binaries into src/main/jniLibs/ and does not build anything.
# The binary download/extraction is difficult to do concisely in Groovy/Gradle,
# at least across host platforms, so we are just reusing our Linux/Windows logic.

# The Flutter tooling requires that developers have CMake 3.10 or later
# installed. You should not increase this version, as doing so will cause
# the plugin to fail to compile for some customers of the plugin.
cmake_minimum_required(VERSION 3.10)

# Download the binaries if they are not already present.
set(LibRoot "${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs")
set(ArchivePath "${CMAKE_CURRENT_SOURCE_DIR}/${LibraryVersion}.tar.gz")
if (NOT EXISTS ${ArchivePath})
file(DOWNLOAD
"your download uri"
${ArchivePath}
)
endif ()

# Extract the binaries, overriding any already present.
file(REMOVE_RECURSE ${LibRoot})
file(MAKE_DIRECTORY ${LibRoot})
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar xzf ${ArchivePath}
WORKING_DIRECTORY ${LibRoot}
)

这里,其实不配置也可以,编译出来的,自己放到对应的目录下也行,但是咱作为库了,自然要做的优雅一点,当然,这个配置,也可以根据自己的需要,自己改吧改吧cmake的构建文件。

然后,我们编写下构建的脚本,当然,选择手动构建也不是不行,就是麻烦点。

#!/bin/bash

# Setup
BUILD_DIR=rust
cd $BUILD_DIR

# Create the jniLibs build directory
JNI_DIR=jniLibs
mkdir -p $JNI_DIR

# Set up cargo-ndk
cargo install cargo-ndk
rustup target add 
  aarch64-linux-android 
  armv7-linux-androideabi 
  x86_64-linux-android 
  i686-linux-android

# Build the android libraries in the jniLibs directory
cargo ndk -o $JNI_DIR 
  --manifest-path ./Cargo.toml 
  -t armeabi-v7a 
  -t arm64-v8a 
  -t x86 
  -t x86_64 
  build --release

# Archive the dynamic libs
cd $JNI_DIR
tar -czvf ../android.tar.gz *
cd -

# Cleanup
rm -rf $JNI_DIR

这里,唯一需要注意的就是Cargo.toml文件的位置,其他的和官网大差不差。

IOS

这里,同样需要微调一下构建的脚本。

#!/bin/bash

# Setup
BUILD_DIR=rust
#mkdir $BUILD_DIR
cd $BUILD_DIR

# Build static libs
for TARGET in 
  aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim 
  x86_64-apple-darwin aarch64-apple-darwin; do
  rustup target add $TARGET
  cargo build -r --target=$TARGET
done

# Create XCFramework zip
FRAMEWORK="rust.xcframework"
LIBNAME=librust.a
mkdir mac-lipo ios-sim-lipo
IOS_SIM_LIPO=ios-sim-lipo/$LIBNAME
MAC_LIPO=mac-lipo/$LIBNAME
lipo -create -output $IOS_SIM_LIPO 
  ./target/aarch64-apple-ios-sim/release/$LIBNAME 
  ./target/x86_64-apple-ios/release/$LIBNAME
lipo -create -output $MAC_LIPO 
  ./target/aarch64-apple-darwin/release/$LIBNAME 
  ./target/x86_64-apple-darwin/release/$LIBNAME
xcodebuild -create-xcframework 
  -library $IOS_SIM_LIPO 
  -library $MAC_LIPO 
  -library ./target/aarch64-apple-ios/release/$LIBNAME 
  -output $FRAMEWORK
zip -r $FRAMEWORK.zip $FRAMEWORK

# Cleanup
rm -rf ios-sim-lipo mac-lipo $FRAMEWORK

然后,需要更改一下flutter_library_rust.podspec文件,内容如下

Pod::Spec.new do |s|
s.name = 'flutter_library_rust'
s.version = '0.0.1'
s.summary = 'A new Flutter FFI plugin project.'
s.description = <<-DESC
A new Flutter FFI plugin project.
DESC
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => '[email protected]' }

# This will ensure the source files in Classes/ are included in the native
# builds of apps using this FFI plugin. Podspec does not support relative
# paths, so Classes contains a forwarder C file that relatively imports
# `../src/*` so that the C sources can be shared among all target platforms.
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.vendored_frameworks = 'Frameworks/**/*.xcframework'
s.static_framework = true # This allows us to use the static library we built.
s.dependency 'Flutter'
s.platform = :ios, '11.0'

# Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
s.swift_version = '5.0'
end

如果想要自动下载依赖库的话呢,就自行处理下下载的逻辑,这里我手动移动进去的,因此呢对,就是这么的任性,不处理了。

Android逆向技术59——Flutter with Rust会发生什么续篇(By LittleQ)

IOS运行截图

MacOS

对于MacOS,具体的方法和IOS一致,这里,只需要更改对应的macos文件夹下的内容就可以了。

Android逆向技术59——Flutter with Rust会发生什么续篇(By LittleQ)
MacOS运行截图

其他平台

对于其他平台来说,直接参考文档吧,这里不在展开描述了。

总结

目前,通过插件形式来引入rust到flutter当中,相对来说,对于主项目的入侵就变得非常低了,而且也利于不同项目进行拆分,目前来看,这是一个还不错的方案。

参考资料

  • https://cjycode.com/flutter_rust_bridge/library/dart_only.html[1]

Reference

[1]

https://cjycode.com/flutter_rust_bridge/library/dart_only.html: https://cjycode.com/flutter_rust_bridge/library/dart_only.html


Android逆向技术59——Flutter with Rust会发生什么续篇(By LittleQ)


原文始发于微信公众号(安全后厨):Android逆向技术59——Flutter with Rust会发生什么续篇(By LittleQ)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年12月20日10:02:49
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Android逆向技术59——Flutter with Rust会发生什么续篇(By LittleQ)http://cn-sec.com/archives/2318354.html

发表评论

匿名网友 填写信息