Tracing the baseband: Part 2
After succesfully injecting command in the baseband on iOS, I tried the same approach on Android but
placing hooks and operating within the application was unfortunately not possible: The loader (ld
) does not support library preloading via LD_PRELOAD. I had to grow an unix beard and deal with threads/pseudo-terminals.
Android ARM Toolchain
During normal operations the Radio Layer Interface deamon (RILd) from Android communicates with the modem via a pseudo-terminal file. RILd opens /dev/smd0
( the slave end of a pseudo-terminal) and uses it as I/O to issue commands and receive responses:
The trick is to rename /dev/smd0
to /dev/smd0Real
and then create a process that will connect to /dev/smd0Real
and create a proxy /dev/smd0
. Two thread in the process then connect the ends of the two channels.
Note: I found out about this technique in a great paper by Collin Mulliner & Charlie Miller ... but they did not provide any source code. So I kept on hacking using what I could get out of their paper.
Note: Creating the pseudo terminal using openpty
was out of scope because not available in my toolchain (CodeSourcery). Instead the program opens /dev/ptmx
, grab the name of the pseudo-terminal slave end via ptsname
and then create a symbolic link from /dev/smd0
to /dev/pts/X
(try to mv throw an error about cross-device :/) .
Android ARM Toolchain
Here is the source code or the TITM (Terminal In The Middle): main.c
I used a solid IBM T43 running Linux Ubuntu with CodeSourcery's IA32 for Linux.
Compile :
cd :~/CodeSourcery/Sourcery_G++_Lite/bin ./arm-none-linux-gnueabi-gcc -lutil -pthread -static -o ~/mitm ~/main.c
Note The program is statically linked, getting Android libc's implementation bionic to work was a real pain and I gave up. Downside is 744Kb executable for 168 lines of code :/ !
Upload to Android and run:
fabiensanglard$ adb push mitm /data fabiensanglard$ adb shell // Note: At this point we jump in Android as root # cd /dev # mv smd0 smd0Real # # cd /data # ./mitm Opened /dev/smd0Real Pseudo-terminal slave name is '/dev/pts/1' Softlinking '/dev/pts/1' to '/dev/smd0' Hello, I'm Thread: 0. Hello, I'm Thread: 1.
At this point the hook is done but rild
process is still using the "real" fd. We need to restart it: Just kill it and initd will respawn it automatically.
fabiensanglard$ adb shell // Note: At this point we jump in Android as root # ps . root 1 0 280 168 c00b77a0 0000c78c S /init system 29 1 808 264 c0182688 afe0c45c S /system/bin/servicemanager app_2 173 33 98448 13204 ffffffff afe0d3e4 S com.android.calendar app_14 206 33 98672 12644 ffffffff afe0d3e4 S com.google.android.apps.maps app_35 227 33 93704 11892 ffffffff afe0d3e4 S com.android.alarmclock radio 32 1 7988 1132 ffffffff afe0cacc S /system/bin/rild . . # kill -9 32
Tips: To have strace helped tremendously to debug. Many thanks to Ben Leslie (mirror) for compiling strace
it on ARM. In order to trace rild
you can attach strace to PID=1 (init) and intruct strace to follow forking:
# strace -f -ff -o /data/strace.rild.log -p 1
Results
First thing to notice is that the baseband does not response OK but 0 to acknowledge a command, here is the initialization sequence tested on an HTC Magic:
[Android send] :AT [Android recv] :0 [Android send] :ATZE0S0=0Q0V0X3&C1&D1 [Android recv] :0 [Android send] :AT+CMEE=1 # Require error to be displayed in numeric format (1) [Android recv] :0 [Android send] :AT+CRC=1 [Android recv] :0 [Android send] :AT+CR=1 # Enabled extended format of incoming call indication [Android recv] :0 [Android send] :AT+CREG=1 # Network Registration [Android recv] :0 [Android send] :AT+FCLASS=0 [Android recv] :0 [Android send] :AT+CMGF=0 # Set Text message format to PDU (0) [Android recv] :0 [Android send] :AT+CSCS="HEX" # Set the TE (Terminal Equipment) character set [Android recv] :0 [Android send] :AT+CGREG=1 # Is GPRS supported ? [Android recv] :0 [Android send] :AT+CUSD=1 # Is 3G supported ? [Android recv] :0 [Android send] :AT+CIMI # What is the SIM Serial number ? [Android recv] :302720306663426 # 302=Canada, 720 = Rogers, rest is serial
Receiving a text message (PDU encoded) and then replying to it.
[Android recv] :+CMT: ,45 07915141991321F301000981F0CFEFFFFF000042C8721E640E8B59A03B3A4C0785E56550FE5D07D5E120FA1BF4A3D6CB20598D8E0635C379900 C16838160369DACE6A2DD40E13608756C5257B114 [Android send] :AT [Android recv] :0 [Android send] :AT+CMGS=43 [Android recv] :> [Android send] :07915141991321F301000981F0CFEFFFFF000048453C9CFD96A7DD6716515E0EB7D3EE3328EC268390E1F13AED3E8342A11 0885A2F8364353A1AD40CE74132580C0682DD74B29A8B760385DB20D4B1495DC552 [Android recv] :
Incoming call:
[Android recv] :+CRING: VOICE # Hey 'smart', someone is calling you. [Android send] :AT+CLCC # Sure, send me the phone number of this person [Android recv] :+CLIP: "+1416839XXXX",145,,,"" # Here it is +11416839XXXX [Android send] :AT+CMUT=0 # Unmute the microphone [Android recv] :0 [Android send] :ATA # Pickup the call [Android recv] :0 [Android send] :ATH # Hang up [Android recv] :0
Scanning the Operator networks around (Go Canada !!):
[Android send] :AT [Android recv] :0 [Android send] :AT+COPS=? [Android recv] :[WCDMA] Current RRC Status = 0 [Android recv] :+CREG: 1,"EA60","6225" [Android recv] :+CREG: 1,"EA60","491B" [Android recv] :+COPS: (2,"Rogers Wireless","ROGERS","302720",2), (1,"Rogers Wireless","ROGERS","302720",0),(1,"","","302880",2) , , (0,1,2,3,4), (0,1,2) 0
Learn more
As usual I will recommend some really really great books that helped me a lot:
Linkers and Loaders | Mac OS X Internals: A Systems Approach | Advanced Unix Programming |
Back to first page