- 投稿日:2020-08-12T17:27:00+09:00
RobomasterS1をハックしたい ①ルート化とファイル構成確認
概要
何をしたか
- Robomasters1をPCとのUSB接続し,adbを使ってルートにアクセスする。
- 中身のファイル構成を覗いてみた
何ができるか?
- わからない…(情弱)
- コマンドライン上でPython環境を制限なしで走らせられる(アプリ経由すると使えないライブラリがある)
何がしたいか?
- 下記参照
本記事の最終目的
- RobomasterS1へPCから司令を送ったり,画像やセンサデータを収集したい 参考:Ishikawa氏の記事
- 有志のデモのようにRobomasterの画像をPCで処理して制御信号を送るといったことに使いたい。
ボールトラッキングのデモ動画を以下に添付します。こういうのをやりたいです。
方針
RobomasterS1の後継となるEPという機種があり,そちらは今言ったようなことができます。SDKも配布されています。(Documentはこちら)
https://github.com/dji-sdk/RoboMaster-SDK/tree/master/sample_code
この件に詳しいBruno氏に寄ればこのSDKでは本来S1のサポートはしていませんが,構成が似通っているため上手くやると流用できるとのことです。
参照:
実際にやったこと
ひとまず,rootアクセスが必要そうなので
- ここのDiscussionを参考にrootアクセスを行う。
- Systemの中身を覗いてみる
Windows10 PC からadbを用いてrootアクセスする
Windows10 HomeのPCからmicroUSBコネクタを用いてRobomasters1に接続します。
ここのPDFをもとに進めていきますが,注意としてファームウェアが新しいとroot化できないなどの報告があるのでアップデートはしないことが挙げられます。
前準備
以下のものを準備します。
- PC,microUSB変換ケーブル
- Android SDK Platform Tools
Platform Toolsは解凍してフォルダの場所を記憶しておきます。PCとRobomasters1を接続します。
次の工程に行く前にPCに接続されているAndroid機器を取り外しておいてください。
PCとRobomasters1の接続
Robomasters1の電源を入れ,PC側もソフトを起動して接続します。(自分はWifi接続)
「ラボ」→「DIYプログラミング」からPythonスクリプトを書くページに行きます。
新規作成で下記のコードをコピペし,実行します。(adbを有効化するshを叩いているっぽい)
def root_me(module): __import__=rm_log.__dict__['__builtins__']['__import__'] return __import__(module,globals(),locals(),[],0) builtins=root_me('builtins') subprocess=root_me('subprocess') proc=subprocess.Popen('/system/bin/adb_en.sh',shell=True,executable='/system/bin/sh',stdout=subprocess.PIPE,stderr=subprocess.PIPE)adbを用いた接続
次に先程解凍した,Platform Toolsのフォルダ(adbが実行可能なフォルダ)に行き,Powershellを起動します。(Linuxの人はTerminal)
.\adb.exe devicesを実行した後に,
.\adb.exe shellを実行します。
上手く行けば以下のようにrootでは入れているはずです。次にやること(多分)
なんとかしてRobomasters1側のConnectionRefusedError: [WinError 10061]
を解除してSDKのサンプルプログラムを試す- どうやらRobomaster s1 にはSDKのトリガーとなるソケットのポートが開かれていないのでEPからファイルをコピーしてくる必要がある…EPも買うお金はない…
追記:ここのやり取りを見るに,Robomaster EPからファイルをコピーする必要があるようで自分の手持ちでは実現できなそう…となっています。
説明
2020年8月12日現在のSDKを見た感じでは,Robomasters1のアドレスの特定のポートに信号を送ることでSDKモードを有効にし,様々な司令を出しているようです。
例えば,SDKを有効にして各種命令をPCから実行するテストファイルではソケット通信で40923ポートに信号を投げています。
SDKサンプルコード
# -*- encoding: utf-8 -*- # 测试环境: Python 3.6 版本 import socket import sys # 直连模式下,机器人默认 IP 地址为 192.168.2.1, 控制命令端口号为 40923 host = "192.168.100.111" port = 40923 def main(): address = (host, int(port)) # 与机器人控制命令端口建立 TCP 连接 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print("Connecting...") s.connect(address) print("Connected!") while True: # 等待用户输入控制指令 msg = input(">>> please input SDK cmd: ") # 当用户输入 Q 或 q 时,退出当前程序 if msg.upper() == 'Q': break # 添加结束符 msg += ';' # 发送控制命令给机器人 s.send(msg.encode('utf-8')) try: # 等待机器人返回执行结果 buf = s.recv(1024) print(buf.decode('utf-8')) except socket.error as e: print("Error receiving :", e) sys.exit(1) if not len(buf): break # 关闭端口连接 s.shutdown(socket.SHUT_WR) s.close() if __name__ == '__main__': main()しかし,Client側からConnectする際に以下のようにエラーを出されてしまいます。
ConnectionRefusedError: [WinError 10061] 対象のコンピューターによって拒否されたため、接続できませんでした。hostsか何か編集したり,Permissionをいじるとかが必要なのでしょうか?ちょっと調べている所です。(詳しい方に教わりたい。)
追記:試した所どうやら,EPには開かれているPortが,S1では開かれていないというのが問題のようです。
根拠として下記のサーバをRobomaster s1 で立ち上げてPCから接続できることを確認したためです。
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(("192.168.100.111", 1235)) s.listen(5) timeout=60## run 60 sec s.settimeout(timeout) while True: clientsocket, address = s.accept() print(f"Connection from {address} has been established!") clientsocket.send(bytes("Welcome to the server!", 'utf-8')) clientsocket.close() print("Exit!")補足:中身を探索する
自分はLinuxもこういったHackもズブの素人なので中身を覗いて理解するのも一苦労でした。一応記録までに載せておきます。
システム情報
一応Linuxシステムではあるようです。
$ cat /proc/versionLinux version 3.10.62 (jenkins@APServer01) (gcc version 4.7 (GCC) ) #1 SMP PREEMPT Tue Jul 16 04:08:11 CST 2019
/
直下なんもわからんのでこれを見てもって感じですが一応メモしておきます。
クリックして展開
amt blackbox cache data default.prop dev etc file_contexts ftp init init.environ.rc init.lc1860.3connective.rc init.rc init.trace.rc init.usb.rc proc property_contexts root sbin sdcard seapp_contexts sepolicy sys system system.md5 tmp ueventd.rc var vendorPython環境
data/python_flies
の中にPythonのフォルダがあります。binの中身は以下の通り,
2to3 idle pydoc python python-config python3.6m pyvenv実際に実行もできます。環境は3.6のようです。
126|root@xw607_dz_ap0002_v4:/data/python_files/bin # ./python Python 3.6.6 (default, Jul 16 2018, 17:22:20) [GCC 4.8.3 20140320 (prerelease)] on linux Type "help", "copyright", "credits" or "license" for more information. >>>robomasterのアプリとの違いは,特定のパッケージが使えることです。
例えば,アプリで作成したコードではsocketなどはimportした時点でエラーとして弾かれるのに対してrootのコマンドライン実行では普通に実行できます。
viなどのエディタがあればいいのですが,
ls /system/bin
の出力を見る限りエディタはないのでファイル転送などをする必要がありそうです。アプリで作成したファイルがどこにあるかがわかればroot上である程度操作ができそうですね。
devの中身
ttyとかは省略。video0とかはありますね。
クリックして展開
alarm android_adb apple_roleswitch applecp ashmem binder block bulk_usb bus comip-snd-lowpower comip-ureg console cpu_dma_latency cuse full fuse graphics hx170dec hx280enc hx280enc_h1 i2c-0 i2c-1 i2c-3 i2c-4 input ion kmsg lcmem log loop-control mem modem mtp_usb network_latency network_throughput null on2map on2psm ptmx pts random rtc0 sdpr sdps snd socket spidev0.0 spidev1.0 spidev2.0 uio0 uio1 uio2 urandom vcs vcs1 vcsa vcsa1 video0 zero
- 投稿日:2020-08-12T17:00:23+09:00
sshfsコマンド ディレクトリの同期
- 投稿日:2020-08-12T14:50:56+09:00
ディレクトリ内のPSDファイルをPDFに一括変換
psdファイル(元データ)とpdfファイル(変換後)それぞれ用のディレクトリがある親ディレクトリで実施する前提
$ ls psd_dir/ pdf_dirImageMagickを利用
for file in `ls psd_dir`; do # 拡張子削除 base=`basename "${file}" .psd` # 変換 convert -flatten -density 300 -compress zip psd_dir/"${base}".psd pdf_dir/"${base}".pdf; done参考
- ファイル名からディレクトリや拡張子を取り除くには
- 表紙の画像ファイルを PDFファイルに変換 解像度 350dpi
- 投稿日:2020-08-12T11:12:08+09:00
port forwardingをunix domain socketにbindすると捗る
port forwardingをunix domain socketにbindすると、dockerコンテナ内にvolume mountを通じて持っていけるので便利。
以下、mysqlを例にする。コマンド
ssh -o StreamLocalBindUnlink=yes -fNL /tmp/sock/db.sock:$DB_HOST:3306 bastionbastionはもちろん、踏み台サーバー
fNオプションは不要であれば外して良い。
-o StreamLocalBindUnlink=yes
をつけると、指定したpathにunix domain socketが既に存在する場合でも上書きしてforwardingしてくれる。dockerコンテナ内での使用
--volume /tmp/sock:/tmp/sock
付きでコンテナを起動する。mysql --socket /tmp/sock/db.sock -u ...curlでも使える
https://qiita.com/toritori0318/items/193df8f749a9c4bda883
ブラウザからアクセスできないのが残念(コンテナ内でブラウザを使うわけではないが、portにbindするのとunix domain socketにbindするのを切り替えるのが面倒くさい)
- 投稿日:2020-08-12T11:12:08+09:00
port forwardingをunix socketにbindするとはかどる
port forwardingをunix socketにbindすると、dockerコンテナ内にvolume mountを通じて持っていけるので便利。
以下、mysqlを例にする。コマンド
ssh -o StreamLocalBindUnlink=yes -fNL /tmp/sock/db.sock:$DB_HOST:3306 bastionbastionはもちろん、踏み台サーバー
fNオプションは不要であれば外して良い。
-o StreamLocalBindUnlink=yes
をつけると、指定したpathにunix socketが既に存在する場合でも上書きしてforwardingしてくれる。dockerコンテナ内での使用
--volume /tmp/sock:/tmp/sock
付きでコンテナを起動する。mysql --socket /tmp/sock/db.sock -u ...curlでも使える
https://qiita.com/toritori0318/items/193df8f749a9c4bda883
ブラウザからアクセスできないのが残念(コンテナ内でブラウザを使うわけではないが、portにbindするのとunix socketにbindするのを切り替えるのが面倒くさい)
- 投稿日:2020-08-12T09:11:10+09:00
【Linux】FQDNの安全な確認方法について検証してみた(CentOS7)
はじめに
以前の記事にてこのようなご質問を頂きました。
【以前の記事】
【Linux】インフラエンジニアの僕が「hostname」コマンドを使わない理由とは?申し訳ございませんが、FQDNまで考慮しておりませんでした。(業務にてFQDNまで確認するシチュエーションがなかったため。)
せっかくなので、検証してみようと思います。
今回検証するOS等の情報
OSバージョン[root@tspdev01 ~]# cat /etc/redhat-release CentOS Linux release 7.8.2003 (Core) [root@tspdev01 ~]#※事前に
/etc/hostname
をこのようにしました。ホスト名[root@tspdev01 ~]# cat /etc/hostname tspdev01.example.com [root@tspdev01 ~]#
「そもそもrootユーザーでやらないだろ!」
そのような声もよくわかります。(既存サーバには、基本的にrootログインしません。)しかし、今回は検証用のためrootユーザーでやってみたいと思います。
そもそも、「hostname -f」の出力結果とは?
実行コマンドhostname -f実行結果[root@tspdev01 ~]# hostname -f tspdev01.example.com [root@tspdev01 ~]#実行結果を確認すると、FQDN
(tspdev01.example.com)
にて表示されております。他のコマンドで試してみる
他のコマンドでFQDNを確認してみたいと思います。
質問にあったコマンドにて実行
質問にあったコマンドを実行してみる。
実行コマンドecho `uname -n`.`dnsdomainname`実行結果は、こんな感じです。
実行結果[root@tspdev01 ~]# echo `uname -n`.`dnsdomainname` tspdev01.example.com.example.com [root@tspdev01 ~]#結果、ドメインが2回表示されています。
「uname -n」にて実行してみる
こちらのコマンドにて実行
実行コマンドuname -n実行結果はこちらになります。
実行結果[root@tspdev01 ~]# uname -n tspdev01.example.com [root@tspdev01 ~]#FQDNにて表示されました!
ホスト名を短縮名で表示してみる
通常のホスト名の短縮名表示
実行コマンドhostname -s実行結果はこちらになります。
実行結果[root@tspdev01 ~]# hostname -s tspdev01 [root@tspdev01 ~]#ホスト名の短縮系のみ表示される。
awkを使った短縮ホスト名確認方法
実行コマンドuname -n | awk -F "." '{print $1}'実行結果はこちらになります。
実行結果[root@tspdev01 ~]# uname -n | awk -F "." '{print $1}' tspdev01 [root@tspdev01 ~]#このように、短縮されたホスト名のみ表示させることができます。
※tspdev01.example.com
の.
で区切っています。ドメイン名のみ確認
通常のドメイン名確認方法
実行コマンドhostname -d実行結果は、こちらになります。
実行結果[root@tspdev01 ~]# hostname -d example.com [root@tspdev01 ~]#安全なドメイン名確認方法
実行コマンドecho `dnsdomainname`実行結果は、こちらになります。
実行結果[root@tspdev01 ~]# echo `dnsdomainname` example.com [root@tspdev01 ~]#ドメイン名のみ表示されております。
まとめ
FQDNでの表示方法
uname -n短縮ホスト名のみ表示
uname -n | awk -F "." '{print $1}'ドメイン名のみ表示
echo `dnsdomainname`
おそらく、他にも方法があると思われます。
まだまだ勉強不足なので、これからもキャッチアップしていく所存です。