1. どうやって利用するか考えてみた
制御対象とする車輪型ロボットはBluetooth通信によってAndroid端末から専用アプリを利用してリモート・コントロールを行うことができることがわかっていたので今回は専用アプリから出力されるBluetoothメッセージを解析することで車輪型ロボットを使えるようにする方法を考えていくことにしました。
2. どうやって解析するか考えてみた
解析する方法にはいくつかあると思いますが、今回私は専用アプリをソースコードまでリバース・エンジニアリングすることでBluetoothメッセージの解析を行なっていくことにしました。
※ソフトウエアにおけるリバース・エンジニアリングは法律的に非常に微妙な立場にあるものであると考えられます。利用は自己責任でお願いします。また、本文章は知的財産権の侵害を推奨するものではありません。
3. ソース解析の手法
Androidアプリは通常apkという拡張子で配布されています。これをAppSender等を用いてPC上に移動します。これでapkの拡張子をzipに変更することで展開できるようになるため、apkの中身を見ることができます。apkのなかにはいろいろなものが入っていますが、今回使用するのはdexファイルのみです。
次に、http://code.google.com/p/dex2jar/ からdex2jarというソフトウエアを入手します。これを用いてdexファイルをjarファイルにまで戻します。dex2jar本体が入っているディレクトリにdexファイルを移動してコマンドプロンプト上でdex2jar ****.dexというコマンドを入力するだけです。
jarファイルが得られたら、後はこれをJavaのデコンパイラに通すだけで完了です。私が使用したのはjd-guiというものでした。入手は http://java.decompiler.free.fr/?q=jdgui からできます。
4. ソース解析
あとは好きなだけソースを眺めてBluetoothメッセージを解析するだけでした。幸い難読化が行われていなかったために短時間で走行制御メッセージを解析することができました。
5. 走行制御プログラム作成
今回はおなじみのProcessingを用いて車輪型ロボットとのBluetooth通信を行いました。プログラムの作成には建築発明工作ゼミさまの記事を参考にさせて頂きました。そして完成したProcessingの走行制御プログラムとArduinoのJoystickコントローラを統合した際の動作デモがこちらになります。
このプログラムのソースコードは以下のようになっています。
import processing.serial.*; int joy1,joy2; String str1,str2,move_state; int duty; Serial Robot,Echo; void setup(){ size(640,480); background(0); duty = 30; Robot = new Serial(this,"/dev/tty.BTCOM-SPPB-DevB",9600); Echo = new Serial(this,"/dev/tty.FireFly-AD1C-SPP",115200); Robot.clear(); Echo.clear(); Echo.bufferUntil(10); } void draw(){ background(0); determinSendValue(); delay(70); controller(); controlWithJoystick(joy1/16,joy2/16); move_state = "Stop"; text("Duty = " + duty,30,30); text("str1 = " + str1,30,50); text("str2 = " + str2,30,70); text("move state =" + move_state,30,90); } void determinSendValue(){ str1 = str(duty/10); str2 = str(duty/17); } void controlWithJoystick(int resist1,int resist2){ if(resist1 < 10){ //forward Robot.write("0100"+str1+str1+str1+"0\r"); move_state = "Forword"; }else if(resist1 > 54){ //back Robot.write("1000"+str1+str1+str1+"0\r"); move_state = "Back"; }else if(resist2 < 10){ //left Robot.write("1100"+str2+str2+str1+"0\r"); move_state = "Left"; }else if(resist2 > 54){ //right Robot.write("0010"+str2+str2+str1+"0\r"); move_state = "Right"; } } void serialEvent(Serial p){ String stringData=Echo.readStringUntil(10); println(stringData); if(stringData != null){ stringData = trim(stringData); int data[] = int(split(stringData,',')); if(data.length == 2){ joy1 = data[0]; joy2 = data[1]; Echo.write(65); } } } void controller(){ Robot.clear(); if (keyPressed){ switch(key){ case 'w'://Forward Robot.write("0100"+str1+str1+str1+"0\r"); move_state = "Forward"; break; case 'a'://Left Robot.write("1100"+str2+str2+str1+"0\r"); move_state = "Left"; break; case 'd'://Right Robot.write("0010"+str2+str2+str1+"0\r"); move_state = "Right"; break; case 's'://Back Robot.write("1000"+str1+str1+str1+"0\r"); move_state = "Back"; break; case 'q'://Forward-Left Robot.write("0102"+str1+str1+str1+"0\r"); move_state = "Forward-Left"; break; case 'e'://Forward-Right Robot.write("0012"+str1+str1+str1+"0\r"); move_state = "Forward-Right"; break; case 'z'://Back-Left Robot.write("1003"+str1+str1+str1+"0\r"); move_state = "Back-Left"; break; case 'c'://Back-Right Robot.write("0013"+str1+str1+str1+"0\r"); move_state = "Back-Right"; break; case '1'://Turn-Left Robot.write("1111"+str1+str1+str1+"0\r"); move_state = "Turn-Left"; break; case '3'://Turn-Right Robot.write("0000"+str1+str1+str1+"0\r"); move_state = "Turn-Right"; break; case 'h'://increase Duty duty++; if(duty >=99) duty =99; delay(70); break; case 'l'://decrease Duty duty--; if(duty <=0) duty = 0; delay(70); break; default://Stop move_state = "Stop"; break; } } }
感想など
簡単にAndroidアプリのコピーやら解析やらができてしまったのが恐ろしいと思います。しっかりした有料アプリ等は難読化がかけられているのだと思うのですが、個人でアプリ開発をしている人は念入りにやらないとコピー(そのままの意味でも、アルゴリズム等のアイディアという意味でも)されてしまうので気を付けなければならないと感じます。
0 件のコメント:
コメントを投稿