RT5350で中国のルーターを探索する

かつて、 lolipopaliexpressルーターを購入しました。 はい、シンプルなルーターではありませんが、2つのイーサネットポート、USB、さらに2000年代初期にロシア連邦でmp3プレーヤーを販売した会社Nexx WT1520Hを備えた非常にコンパクトで安価です。

画像

ほとんどの場合、標準ファームウェアは不足していたので、もちろん、より健全なものに置き換えたかったのです。 しかし、ここに問題があります-ルーター用の代替ファームウェアはありません。それをフラッシュする方法は明確ではありません。 Webインターフェースを介して他のファームウェアは受け入れられませんでした。以前にファームウェアのタイトルが表示されず、binwalkはその中に何も見つけられなかったため、暗号化されています。

00000000 32 33 35 30 6b d9 39 00 00 00 0e 02 00 00 00 00 |2350k.9.........| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 3e 19 53 c5 |............>.S.| 00000020 63 f5 51 9f 82 74 2d 03 2e 2f 1f 32 9c 4a 93 96 |cQ.t-../.2.J..| 00000030 15 82 23 d0 b2 7e d7 1b 13 c3 1b 1f 06 fa f8 e0 |..#..~..........| 00000040 bb 43 9b c6 ee fc 4b 7a e6 50 71 2b f4 f3 95 c3 |.C....Kz.Pq+....| 00000050 63 d0 a3 9c 92 2e 16 c6 19 1c 4a 93 cb 95 c3 63 |c.........J....c| 00000060 d2 9b 1a f5 2e 16 c6 19 1c 4a 93 f9 68 3c 9c 73 |.........J..h<.s| 00000070 14 63 d5 10 5e d3 6b 25 2b c2 2e 07 eb 85 73 25 |.c..^.k%+.....s%| 00000080 9b 6b c0 f2 d8 9b cf 65 56 ac a9 c2 28 61 dd 55 |.k.....eV...(aU| 00000090 18 a4 5b e9 ba 11 93 ec 30 76 4f 40 c1 f0 7c cb |..[.....0vO@..|.| 000000a0 36 d3 b3 93 fe 3d 6b 10 66 fa 43 39 f2 f6 c0 91 |6....=kfC9....|
      
      





lolipopはフラッシュドライブからプログラマーを介してデータをマージし、それを選択し始めました。



ファームウェアの研究



機器の初期化とプログラムの起動のプロセス全体が、独自のinit-/ sbin / rcに責任を負います。 これは、ルーターのほぼすべてのロジックを含む、このようなクールボックスbusyboxです。

非表示のテキスト
 .text:0040E758 .globl start_services .text:0040E758 start_services: # CODE XREF: main+14C8p .text:0040E758 # DATA XREF: main+14C0o ... .text:0040E758 .text:0040E758 var_10 = -0x10 .text:0040E758 var_8 = -8 .text:0040E758 .text:0040E758 li $gp, 0x7EBF8 .text:0040E760 addu $gp, $t9 .text:0040E764 addiu $sp, -0x20 .text:0040E768 sw $ra, 0x20+var_8($sp) .text:0040E76C sw $gp, 0x20+var_10($sp) .text:0040E770 la $t9, start_syslog .text:0040E774 nop .text:0040E778 jalr $t9 ; start_syslog .text:0040E77C nop .text:0040E780 lw $gp, 0x20+var_10($sp) .text:0040E784 nop .text:0040E788 la $t9, start_proftpd .text:0040E78C nop .text:0040E790 jalr $t9 ; start_proftpd .text:0040E794 nop .text:0040E798 lw $gp, 0x20+var_10($sp) .text:0040E79C nop .text:0040E7A0 la $t9, start_telnetd .text:0040E7A4 nop .text:0040E7A8 jalr $t9 ; start_telnetd .text:0040E7AC nop .text:0040E7B0 lw $gp, 0x20+var_10($sp) .text:0040E7B4 nop .text:0040E7B8 la $t9, load_smb_driver .text:0040E7BC nop .text:0040E7C0 jalr $t9 ; load_smb_driver .text:0040E7C4 nop .text:0040E7C8 lw $gp, 0x20+var_10($sp) .text:0040E7CC nop .text:0040E7D0 la $t9, sys_led_init .text:0040E7D4 nop .text:0040E7D8 jalr $t9 ; sys_led_init .text:0040E7DC li $a0, 2 .text:0040E7E0 lw $gp, 0x20+var_10($sp) .text:0040E7E4 nop .text:0040E7E8 la $t9, start_upnp .text:0040E7EC nop .text:0040E7F0 jalr $t9 ; start_upnp .text:0040E7F4 nop .text:0040E7F8 lw $gp, 0x20+var_10($sp) .text:0040E7FC nop .text:0040E800 la $t9, start_dhcpd .text:0040E804 nop .text:0040E808 jalr $t9 ; start_dhcpd .text:0040E80C nop .text:0040E810 lw $gp, 0x20+var_10($sp) .text:0040E814 nop .text:0040E818 la $t9, start_ntpc .text:0040E81C nop .text:0040E820 jalr $t9 ; start_ntpc .text:0040E824 nop .text:0040E828 lw $gp, 0x20+var_10($sp) .text:0040E82C nop .text:0040E830 la $t9, start_dns .text:0040E834 nop .text:0040E838 jalr $t9 ; start_dns .text:0040E83C nop .text:0040E840 lw $gp, 0x20+var_10($sp) .text:0040E844 nop .text:0040E848 la $t9, start_ddns .text:0040E84C nop .text:0040E850 jalr $t9 ; start_ddns .text:0040E854 nop .text:0040E858 lw $gp, 0x20+var_10($sp) .text:0040E85C nop .text:0040E860 la $t9, start_igmp_proxy .text:0040E864 nop .text:0040E868 jalr $t9 ; start_igmp_proxy .text:0040E86C nop .text:0040E870 lw $gp, 0x20+var_10($sp) .text:0040E874 nop .text:0040E878 la $t9, start_ipmac_bind .text:0040E87C nop .text:0040E880 jalr $t9 ; start_ipmac_bind .text:0040E884 nop .text:0040E888 lw $gp, 0x20+var_10($sp) .text:0040E88C nop .text:0040E890 la $t9, start_block_ipmac .text:0040E894 nop .text:0040E898 jalr $t9 ; start_block_ipmac .text:0040E89C nop .text:0040E8A0 lw $gp, 0x20+var_10($sp) .text:0040E8A4 nop .text:0040E8A8 la $t9, start_block_port .text:0040E8AC nop .text:0040E8B0 jalr $t9 ; start_block_port .text:0040E8B4 nop .text:0040E8B8 lw $gp, 0x20+var_10($sp) .text:0040E8BC nop .text:0040E8C0 la $t9, start_ddos .text:0040E8C4 nop .text:0040E8C8 jalr $t9 ; start_ddos .text:0040E8CC nop .text:0040E8D0 lw $gp, 0x20+var_10($sp) .text:0040E8D4 nop .text:0040E8D8 la $t9, start_monitor_rate .text:0040E8DC nop .text:0040E8E0 jalr $t9 ; start_monitor_rate .text:0040E8E4 nop .text:0040E8E8 lw $gp, 0x20+var_10($sp) .text:0040E8EC nop .text:0040E8F0 la $t9, start_upgraded .text:0040E8F4 nop .text:0040E8F8 jalr $t9 ; start_upgraded .text:0040E8FC nop .text:0040E900 lw $gp, 0x20+var_10($sp) .text:0040E904 nop .text:0040E908 la $t9, start_conntrack_limit .text:0040E90C nop .text:0040E910 jalr $t9 ; start_conntrack_limit .text:0040E914 nop .text:0040E918 lw $gp, 0x20+var_10($sp) .text:0040E91C nop .text:0040E920 la $t9, start_macfilter .text:0040E924 nop .text:0040E928 jalr $t9 ; start_macfilter .text:0040E92C nop .text:0040E930 lw $gp, 0x20+var_10($sp) .text:0040E934 nop .text:0040E938 la $t9, start_black_management .text:0040E93C nop .text:0040E940 jalr $t9 ; start_black_management .text:0040E944 nop .text:0040E948 lw $gp, 0x20+var_10($sp) .text:0040E94C nop .text:0040E950 la $t9, start_wlan_wps .text:0040E954 nop .text:0040E958 jalr $t9 ; start_wlan_wps .text:0040E95C nop .text:0040E960 lw $gp, 0x20+var_10($sp) .text:0040E964 nop .text:0040E968 la $t9, start_trakerurl .text:0040E96C nop .text:0040E970 jalr $t9 ; start_trakerurl .text:0040E974 nop .text:0040E978 lw $gp, 0x20+var_10($sp) .text:0040E97C lw $ra, 0x20+var_8($sp) .text:0040E980 move $v0, $zero .text:0040E984 jr $ra .text:0040E988 addiu $sp, 0x20 .text:0040E988 # End of function start_services
      
      





推論とnmapを使用して、telnetdがルーターで起動され、WANインターフェイスを介してアクセスできることがわかりました。 これだ! ただし、rootユーザーまたはadminユーザーのいずれかでログインに失敗しました。

Busyboxはtelnetdとして機能します。 それを見てみましょう(login_main関数):



画像



さて、今ではパスワードを入力する前に起動しますが、標準パスワード「admin」は受け入れられません。 面白い。 さらに調査します。



画像



行くぞ! WAN経由でアクセスして、nexxadmin、パスワードy1n2inc.com0755にログインします。

ファームウェアにはmtd_writeがあるため、現在、フラッシュにOpenWRTをアップロードすることを妨げるものはありません。これはlolipopによって行われましたが、暗号化アルゴリズムを逆にすることは依然として興味深いものでした。 残念ながら、私の頭の中の私のMIPSアセンブリスキルは明らかに十分ではなく、このコードをすべて見て初めて大きな不快感を覚えたので、同じルーターを自分用に注文しました。



研究を続けます



画像

RXのみが接続されており、USB電源を介したラップトップでは接地が一般的です。



ルーターは、Webインターフェイスとtftp(これもWANをリッスンします!)の両方で更新できます。 (rcからアップグレードされた)tftpデーモンが壊れているようです。 それを介して更新しても、エラーはありませんでしたが、ルーターのファームウェアは更新されませんでした。 tftpでファームウェアを更新するには、Webインターフェースと同じパスワードによる認証が必要であるため、バックドアと呼ぶのは難しく、単に設定が間違っているサービスであることに注意してください。



ファームウェアの更新をtftpで正確に調査することにしました。

標準のtftpクライアントを使用した簡単なアップグレードにより、アップグレードから「アップグレードできません:パスワードが正しくありません」が発生しました。 それを見てみましょう:



画像



通常のクライアントはtftpオプションを送信できないようです。そこで、 tftpy pythonライブラリをダウンロードし、クライアントのサンプルファイルの1行を変更しましたが、動作しました。

 --- tftpy_client.py 2014-09-30 21:48:57.375550027 +0400 +++ tftpy_client.py_ 2014-09-30 21:48:50.355520342 +0400 @@ -83,7 +83,7 @@ progresshook = Progress(tftpy.log.info).progresshook - tftp_options = {} + tftp_options = {'admin': ''} if options.blksize: tftp_options['blksize'] = int(options.blksize) if options.tsize:
      
      





いいね! 現在、ファームウェアの暗号化に対処するために残っています。 rcには復号化関数があり、次のようになります。



画像



静的変数にキーが見つからなかったため、デバッグを開始しました。 デバイスで何かをデバッグするには、もちろん、最初にデバッガーをアセンブルする必要があります。 IDA Proはlinux_serverをMIPSでコンパイルしません(そしてルーターはこのアーキテクチャ上に構築されます)ので、何らかの方法でルーターの下にgdbserverを構築する必要がありました。 ルーターは、uClibc 0.9.28の古い古いカーネル2.6.21を使用します。 まず第一に、uClibcとgdbserverの両方を使用してツールチェーンを静的にビルドするように、buildrootを使用することにしました。 さて、すべてが組み立てられたようですが、IDA Proを介してデバッグすると、サーバーが絶えずクラッシュし、奇妙なエラーptraceが生成されます。 .k。 uClibcはバイナリ互換性を約束していません。 インターネットで、正しいカーネルバージョンとuClibcを備えたRalink SDKを見つけました。 このツールチェーンによってコンパイルされたGDBServerは、古いものと同様に1対1で動作しました。 残念ながら、IDA Proにはgdbserverとの非互換性があり、gdbserverはMIPS上で実行されます。 幸いなことに、gdbserverはmips(./configure --target mipsel-linux)でコンパイルされた通常のgdbでうまく機能します。

私はめったにgdbで何かをデバッグすることはめったになく、便利なアドオンとスクリプトはx86とARMでのみ動作します。 幸いなことに、 MIPS用の.gdbinitを持つリポジトリが見つかりました。デバッグの利便性が著しく向上しました。 すべては何とかこのように起こりました:



画像



最終的に、キーは上記の数行で見つかりましたが、これは予想されることです。



画像



ファームウェアを復号化するスクリプトを作成した後、 lolipopは同様のヘッダーを持つ別のルーターを別のルーターから送信しました。 彼女が持っていた最初の4文字(魔法)はR3G2でした。 Googleでこの行を検索したところ、2013年の初めからすでにすべてがすでに行われていました:(

復号化されたファームウェアには、Linuxカーネルイメージの行があり、常に同じオフセットにあります。 この行はXORキーより長いため、異なるメーカーのrcから取得する必要はありませんが、この行から「見つける」ことができます。



ただし、ファームウェアを解凍するだけでは不十分です。また、ウェブインターフェースを介して更新できるように、それをパックする必要もあります。 判明したように、更新機能にはファームウェアのチェックサム計算があります。



画像



Cでは次のようになります。

  for (i=0; i<f.len-1; i+=2) { checksum += (data[i+1] << 8 ) | data[i]; } if (i < f.len) { checksum += data[i]; printf("Got odd byte: 0x%02X\n", data[i]); i+=1; } checksum = checksum + (checksum >> 16) + 0xffff; checksum = ~(checksum + (checksum >> 16)) & 0xffff; printf("Checksum = 0x%04X\n", checksum); data[i] = checksum & 0xFF; data[i+1] = (checksum >> 8) & 0xFF;
      
      





これで、Webインターフェース経由でファームウェアをアップロードするために必要なすべてが揃いました。



参照資料

解読

暗号化



おわりに

この方法は、SoC RT5350上の多くのデバイスに適しています。 これはおそらく、SDKからファームウェアを更新するための通常の方法です。

バックドアを備えたファームウェアとそのような低品質により、消費者はデバイスで正常に動作するソフトウェアを探す必要があります。 lolipopはOpenWRTでこのデバイスのサポートを追加し、まもなくTrunkに追加されます。 また、昨日、OpenWRT Barrier Breakerのリリースがついにリリースされました! (サイトにはまだ発表がありません)。

だから私たちは生きています。



All Articles