當前位置:
首頁 > 最新 > Tensorflow+Android應用安全初探

Tensorflow+Android應用安全初探

1. 背景

2017年,谷歌發布了一個專門針對移動設備優化的Tensorflow版本——Tensorflow Lite,並於年末開放了開發者預覽版。

當前ML,DL系統通常軟體服務商的服務端為用戶進行服務,而此次Google希望能將一部分相關處理轉移到用戶的移動設備上,從而減輕服務端的壓力。同時,並且一些需要學習的用戶數據涉及用戶的敏感信息,並不適合通過網路連接發送給服務商,因此利用Tensorflow Lite可以使得在設備本地進行模型的train與inference。


從安全形度來看,相比於傳統的服務端集中學習,在移動設備上使用Tensorflow或是Tensorflow Lite會將訓練模型等信息集成進APK,然後對外發布。那麼所使用的訓練模型和參數等信息自然就可能被外部獲取。

本文將按照官方的例子對在APP內集成Tensorflow Lite進行分步學習,並且觀察最後的樣例APP中訓練模型相關的信息應該如何獲取與還原。

對於Tensorflow Lite的詳細開發入門,可以參考項目官方頁面。安裝Tensorflow的過程就不多說了,本文將應用開發過程大致分為兩個階段:

1 生成TFLITE文件

2 開發APP


TFLITE文件就是Tensorflow Lite保存訓練模型與參數的文件,它是由Tensorflow的訓練模型文件.pb和參數文件.ckpt合成固定後生成的.pb文件進一步優化而成的,會更小且更適合在移動設備上運行。

大致流程圖如下:

那我們就使用項目中的cifar10樣例來運行一下…咦?報錯了?!這可是官方的例子啊?眾所周知,Tensorflow現在超級火,更新也超快,所以樣例代碼中的API有許多已經被修改。根據報錯去一個個搜即可,這裡前前後後加起來可能有十幾個報錯處需要修改。

成功運行後,我們發現會在/tmp/下產生訓練相關的文件,使用項目中freeze_graph.py這個工具來對目標訓練文件進行圖參數的固化從而產生.pb文件。同樣由於版本問題,我在運行項目中的這個固化腳本時存在一些報錯,本人使用了另一個修改腳本。

有了.pb文件後,我們可以使用toco工具將其轉化為我們所需要的.tflite文件。該工具全稱為,其可以將.pb文件(包含圖與參數信息)優化並轉化為.tflite文件,從而使其可以高效地在移動設備上運行。

官方對toco的使用方式如下:

bazel run--config=opt tensorflow/contrib/lite/toco:toco --

--input_file=(pwd)/mobilenet_v1_1.0_224/frozen_graph.pb

--input_format=TENSORFLOW_GRAPHDEF --output_format=TFLITE

--output_file=/tmp/mobilenet_v1_1.0_224.lite --inference_type=FLOAT

--input_type=FLOAT --input_arrays=input

--output_arrays=MobilenetV1/Predictions/Reshape_1 --input_shapes=1,224,224,3

為了方便使用該toco工具,可以直接用bazel先編譯成elf文件(64位直接點我),然後方便複製到/usr/bin下使其成為系統工具來使用。使用該工具時需要在眾多參數中仔細輸入正確的輸入輸出信息,然後就能成功製作出優化後的.tflite文件了。


此處我們直接使用位於tensorflow/tensorflow/contrib/lite/java/demo中的例子。該樣例編譯後的APP執行效果為識別攝像頭拍攝到的畫面中的物品,效果如圖:

該項目主要有四個java代碼文件:

1.AutoFitTextureView.java

2.CameraActivity.java

3.Camera2BasicFragment.java

4.ImageClassifier.java

前兩個很簡單,CameraActivity.java是一個activity類,其中包含了一個Carama2BasicFragment。AutoFitTextureView則是提供了一個自動適應屏幕的攝像頭預覽View。

Camera2BasicFrgment.java則是整個APP的主體,其實現了UI界面,並且使用classifyFrame()方法周期性地進行圖像識別。

privateRunnable periodicClassify =

newRunnable() {

@Override

publicvoidrun(){

synchronized(lock) {

if(runClassifier) {

classifyFrame();

}

}

backgroundHandler.post(periodicClassify);

}

};

classifyFrame()的代碼中可以看出它是從AutoFitTextureView中提取圖片信息,保存為bitmap,並將其通過classifyFrame(bitmap)方法傳遞給ImageClassifier進行內容識別,然後返回識別的結果。

privatevoidclassifyFrame(){

if(classifier ==null|| getActivity() ==null|| cameraDevice ==null) {

showToast("Uninitialized Classifier or invalid context.");

return;

}

Bitmap bitmap =

textureView.getBitmap(ImageClassifier.DIM_IMG_SIZE_X, ImageClassifier.DIM_IMG_SIZE_Y);

String textToShow = classifier.classifyFrame(bitmap);

bitmap.recycle();

showToast(textToShow);

}

ImageClassifier(Activity activity)throwsIOException {

tflite =newInterpreter(loadModelFile(activity));

labelList = loadLabelList(activity);

imgData =

ByteBuffer.allocateDirect(

DIM_BATCH_SIZE * DIM_IMG_SIZE_X * DIM_IMG_SIZE_Y * DIM_PIXEL_SIZE);

imgData.order(ByteOrder.nativeOrder());

labelProbArray =newbyte[1][labelList.size()];

Log.d(TAG,"Created a Tensorflow Lite Image Classifier.");

}

StringclassifyFrame(Bitmap bitmap){

if(tflite ==null) {

Log.e(TAG,"Image classifier has not been initialized; Skipped.");

return"Uninitialized Classifier.";

}

convertBitmapToByteBuffer(bitmap);

// Here"s where the magic happens!!!

longstartTime = SystemClock.uptimeMillis();

tflite.run(imgData, labelProbArray);

longendTime = SystemClock.uptimeMillis();

Log.d(TAG,"Timecost to run model inference: "+ Long.toString(endTime - startTime));

String textToShow = printTopKLabels();

textToShow = Long.toString(endTime - startTime) +"ms"+ textToShow;

returntextToShow;

}


我們將這個官方樣例APP的APK解包,然後在assets目錄下找到了該.tflite文件。

由於toco工具並不是單向轉化的,它還可以將.tflite文件轉化為.pb文件。因此,我們可以再次利用toco工具獲得包含圖信息與參數信息的.pb文件。運行如下命令:

./toco --input_file=./target_in_your_app.tflite --output_file=test2.pb --input_format=TFLITE --output_format=TENSORFLOW_GRAPHDEF --input_shape=[1,224,224,3] --input_array=conv1 --output_array=softmax_linear

需要注意的是,這些參數對於APP的逆向分析者來說並不是現成的,需要仔細查看反編譯的代碼,從中找到這些信息。否則toco運行將失敗。

將該APK放入JADX等工具中反編譯後,在如下部分找到了所需轉換的信息。

那麼該如何從.pb文件中獲取能被我們輕易理解的訓練模型信息呢?使用tensorboard即可做到。首先利用如下腳本可以將.pb中的信息提取並保存到指定目錄下:

importtensorflowastf

fromtensorflow.python.platformimportgfile

withtf.Session()assess:

withtf.gfile.FastGFile("/path/to/the/file.pb","rb")asf:

graph_def = tf.GraphDef()

graph_def.ParseFromString(f.read())

tf.import_graph_def(graph_def, name="")

writer = tf.summary.FileWriter("/path/you/want", sess.graph)

writer.close()

然後輸入命令:

輸出中包括一個url,在瀏覽器中訪問這個地址,便可以在相關項目頁面中看到該模型的詳細信息了。下圖便是tensorboard最後顯示的模型。


在/tensorflow/tensorflow/examples/android目錄下還有一個樣例APP,它沒有使用Tensorflow Lite,而是通常Tensorflow。該APP的功能源碼此處不再展開分析,直接來看一下其關鍵部分的代碼。

從AndroidManifest.xml中可以看出,該APP安裝後會出現四個圖標,各自對應四個不同的Activity:

android:screenOrientation="portrait"

android:label="@string/activity_name_classification">

android:screenOrientation="portrait"

android:label="@string/activity_name_detection">

android:screenOrientation="portrait"

android:label="@string/activity_name_stylize">

android:screenOrientation="portrait"

android:label="@string/activity_name_speech">

進一步分析源碼,發現這個APP中的模型文件直接使用了固化參數後的.pb文件。如Stylize功能中使用TensorFlowInferenceInterface來獲取stylize_quantized.pb文件中的模型信息進行圖像處理。

privatestaticfinalString MODEL_FILE ="file:///android_asset/stylize_quantized.pb";

......

inferenceInterface =newTensorFlowInferenceInterface(getAssets(), MODEL_FILE);

......

inferenceInterface.feed(

INPUT_NODE, floatValues,1, bitmap.getWidth(), bitmap.getHeight(),3);

inferenceInterface.feed(STYLE_NODE, styleVals, NUM_STYLES);

inferenceInterface.run(newString[] , isDebug());

inferenceInterface.fetch(OUTPUT_NODE, floatValues);

......

在DetectorActivity中更是有三種物體檢測模型讓我們選擇:

privatestaticfinalString MB_MODEL_FILE ="file:///android_asset/multibox_model.pb";

......

privatestaticfinalString TF_OD_API_MODEL_FILE =

"file:///android_asset/ssd_mobilenet_v1_android_export.pb";

......

privatestaticfinalString YOLO_MODEL_FILE ="file:///android_asset/graph-tiny-yolo-voc.pb";

......

DetectorActivity的效果如下:

由此可知,要想獲取這類APP,需要提取其資源文件中的.pb文件。相比於Tensorflow Lite少了一個使用toco工具將.tflite轉化回.pb的步驟。有了.pb文件後,便和上文中使用tensorboard的方式一樣,對其內部內容進行可視化分析。


從上文中可以看出Tensorflow Lite會將訓練模型的圖信息與參數信息幾乎完全加入到APK中,我們可以從其APK中提取並理解該人工智慧模型的實現細節。因此,對於一些涉及敏感商業機密的人工智慧模型,廠商在使用Tensorflow+Anroid的開發方案前需要謹慎衡量一下其所可能泄露的技術與帶來的風險。

對於希望保護自身知識產權的組織,也可以從上文看出一些可以用來防禦的點。第一是通過一些資源保護的手段來使得分析人員無法獲取.tflite或.pb文件。第二是當使用Tensorflow Lite時,可以通過一些代碼保護技術來使得他人難以獲得正確的toco所需參數。

因此,個人認為可以對圖參數文件進行加密,或是選用一些不僅僅是保護dex,而且對資源文件也有較高保護技術的加固產品。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 銀河安全實驗室 的精彩文章:

TAG:銀河安全實驗室 |