May, 11th 2010

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
	app_14   206   33    98672 12644 ffffffff afe0d3e4 S
	app_35   227   33    93704 11892 ffffffff afe0d3e4 S
	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


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

	[Android send] :AT
	[Android recv] :0
	[Android send] :AT+CMGS=43
	[Android recv] :> 
	[Android send] :07915141991321F301000981F0CFEFFFFF000048453C9CFD96A7DD6716515E0EB7D3EE3328EC268390E1F13AED3E8342A11
	[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)

Learn more

As usual I will recommend some really really great books that helped me a lot:

Linkers and LoadersMac OS X Internals: A Systems ApproachAdvanced Unix Programming

Back to first page



Fabien Sanglard @2010