8

[原创]GSM Sniffing入门(硬件篇1-2楼,软件篇6楼)

木桩 2013-12-14 21:22 117878
2014-01-11 补充软件篇,请移步6楼查看 (误点"设置最佳答案"不知道怎么取消,大家忽略吧)

3个月前,听朋友介绍得知OsmocomBB项目。此前一直以为GSM Sniffing需要价格昂贵的专用设备,但osmocomBB的上手成本:一个25元左右的手机,外加一根USB转TTL的串口线,着实让我吃了一惊(我自己前后买了3台手机和2种串口线以测试稳定性,总共花了100元不到)


OsmocomBB教程想必很多人都看过了。写这篇文章的目的,一则是把我所遇到的问题列出来,避免以后或者其他人像我一样,被“2.5mm耳机没插到位”这种低级问题纠缠大半个月
另外,如果大家还在用GSM的2G网络,还是找机会换了吧,SMS协议在国内是明文传输的
第二部分(软件篇)重点介绍如何利用50元左右的设备,抓包并还原SMS短信内容:


ps:研究GSM Sniffing纯属个人兴趣,能抓SMS报文只是捡了个明文传输的漏子,切勿用于非法用途。就像sylvain说的,osmocomBB并不是为抓包而实现的,如果没有足够的GSM相关知识,想实现还原语音通话内容根本就无从下手。

---------------------------------------------------------------------------------------------------

【第一部分-硬件篇:osmocomBB环境准备与刷机】

一、硬件准备

工欲善其事,必先利其器。在开始编译osmocomBB前,需要了解运行osmocomBB需要些什么东西:

1. Moto C118
   osmocomBB支持很多型号的手机,具体可以在官网查到:http://bb.osmocom.org/trac/wiki/Hardware/Phones
   我们的目标C118,也就是官网首推的E88系列:MotorolaC123/C121/C118 (E88) -- our primary target
   你问C118有啥优势?出了官方说的支持最好,这玩意另一个优势是便宜。机器没什么讲究,直接淘宝选最便宜的买就行了;国产系统为中文,测试一样可以正常刷机。我买的机器+电池+线充(或者直接用万能充)一起30元。另外如果只有1台不建议买裸机,这个的电池完全配不到,当时我是找人30做了块才点亮机器的...

2. USB转串口模块
   推荐带TX/RX LED的 FT232模块,虽然价格略贵(淘宝上最便宜的大概28),但有指示灯可以清楚看到是否有数据传输,方便定位问题。

FT232模块


   CP2102模块 也可以,使用前需要参考这里调整波特率
sudo ./cp210x-program -p -F eeprom.hex -w --set-baudrate 812500:FFE2,FFF4,1 --set-baudrate 406250:FFC5,FFE9,1 --set-baudrate 203125:FF8A,FFD3,1

   用cp210x-program工具看到输出里有 800000 Baud, 406780 Baud, 203390 Baud, 115385 Baud 这几个波特率就可以使用了

CP2102模块,只有电源指示


3. C118数据线 (2.5mm耳机头 转 杜邦线)
   注意一头是2.5mm耳机孔的,另一边是杜邦线连接串口模块。手边有2.5mm耳机插头的可以自己做一个。淘宝只有一家卖这个线的(10¥),如果你买的是这个,请拆下电池盖观察耳机插孔是否插到位,建议买回来第一件事就是拿小刀把插头的外框狠狠的削掉一圈:


二、ArchLinux下编译osmocomBB
(网上其他linux编译的教程很多,如果不是用的Arch可以跳过这个部分,参考其他教程完成osmocomBB编译)

0. 首先将texinfo替换成4.13a,源里面texinfo5会导致gcc的文档无法编译
cd ~
svn checkout --depth=empty svn://svn.archlinux.org/packages arch_packages
cd arch_packages
svn update texinfo -r176043
cd texinfo/repos/core-i686
makepkg


安装编译好的texinfo-4.13a:
sudo pacman -U texinfo-4.13a-7-i686.pkg.tar.xz


1. 安装libosmocore:http://bb.osmocom.org/trac/wiki/libosmocore
cd ~
git clone git://git.osmocom.org/libosmocore.git
cd libosmocore/
# autoreconf -i [COLOR="Red"](not working)[/COLOR]


Arch下autoreconf怎么都过不了,直接无视之继续编译,后面再修复libosmocore.so.4找不到的问题

./configure
make
sudo make install


修复安装路径的问题,因为autoreconf失败,默认安装到了/usr/local/lib/下。需要把库手动复制到/usr/lib/里,不然运行osmocon会提示 libosmocore.so.4 找不到
sudo ldconfig
sudo cp -Rf /usr/local/lib/* /usr/lib/


2. 编译arm-toolchain:http://bb.osmocom.org/trac/wiki/GnuArmToolchain
cd ~
mkdir arm_toolchain
cd arm_toolchain
wget http://bb.osmocom.org/trac/raw-attachment/wiki/GnuArmToolchain/gnu-arm-build.2.sh
chmod +x gnu-arm-build.2.sh
mkdir build install src


这是官方推荐的gcc版本,速度太慢可以用迅雷拖下来放到src目录里:
cd src/
wget http://ftp.gnu.org/gnu/gcc/gcc-4.5.2/gcc-4.5.2.tar.bz2
wget http://ftp.gnu.org/gnu/binutils/binutils-2.21.1a.tar.bz2
wget ftp://sources.redhat.com/pub/newlib/newlib-1.19.0.tar.gz


开始编译arm的交叉编译工具:
cd ..
[B]./gnu-arm-build.2.sh[/B]
I will build an arm-elf cross-compiler:

  [B]Prefix: /root/arm_toolchain/install[/B]
  Sources: /root/arm_toolchain/src
  Build files: /root/arm_toolchain/build

Press ^C now if you do NOT want to do this.


按回车继续,时间比较长可以先去喝杯咖啡

Build complete! Add /root/arm_toolchain/install/bin to your PATH to make arm-elf-gcc and friends
accessible directly.


编译完成,按照提示导出安装目录:
export PATH=$PATH:/root/arm_toolchain/install/bin


3. 编译osmocom-bb
git clone git://git.osmocom.org/osmocom-bb.git
cd osmocom-bb
git pull --rebase
[COLOR="red"]git checkout -b gsmmap remotes/origin/luca/gsmmap[/COLOR]


不建议用 remotes/origin/sylvain/testing 分支,这个分支不太稳定,刷机几次才能搜到1次信号

如果想插上SIM卡用mobile发短信,记得打开layer1的TX发送功能:
vi src/target/firmware/Makefile
# Uncomment this line if you want to enable Tx (Transmit) Support.
CFLAGS +=-DCONFIG_TX_ENABLE



最后编译osmocomBB:
cd src
make



编译成功后,参考osmocon的教程,就可以开始对C118进行软刷机了:
http://bb.osmocom.org/trac/wiki/osmocon

0. 准备配置文件目录
$ sudo mkdir /etc/osmocom/
$ sudo touch /etc/osmocom/osmocom.cfg

1. Connect your phone
2. Choose firmware (../../target/firmware/board/compal_e88/layer1.compalram.bin)
3. Load firmware
$ cd host/osmocon/
$ ./osmocon -p /dev/ttyUSB0 -m c123xor ../../target/firmware/board/compal_e88/layer1.compalram.bin

4. 运行mobile,开启新的终端
$ cd layer23/src/mobile
$ ./mobile -i 127.0.0.1

5. 用wireshark抓包
$ sudo wireshark -k -i lo -f 'port 4729'


mobile完成的是普通电话的交互操作;相对的,在host/layer23的misc文件夹里,还有cell_log,ccch_scan等工具可以帮助抓取GSMTAP。

注意:使用cell_log和ccch_scan时,有个 GSM ARFCN 参数,这个是用于选择小区中频道的。如果选错了频道,会提示 result = 255(这个按mail list的说法是频道中没有收到控制响应)
用bcch_scan可以得到当前位置信号较强的几个频道编号,当然也可以通过mobile的输出确定最强的ARFCN,然后使用 -a 参数传递给ccch_scan来捕捉其上的GSMTAP。
上传的附件:
最新回复 (105)
8
木桩 2013-12-14 21:24
3
三、osmocomBB刷机及常见故障排除

为杜绝一切连接引起的疑难杂症,刷机前先确认USB转TTL模块没有问题。

用一根杜邦线,把模块的TX/RX两个pin脚短接。

把模块插到USB口上,此时模块的电源LED亮起,输入 lsusb 查看模块的连接情况:
[root@ArchDev ~]# lsusb
Bus 001 Device 004: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC


说明FT232模块已经被正确识别。dmesg也能看到类似的输出
[ 3939.433684] usb 1-1: Detected FT232RL
[ 3939.433691] usb 1-1: Number of endpoints 2
[ 3939.433697] usb 1-1: Endpoint 1 MaxPacketSize 64
[ 3939.433703] usb 1-1: Endpoint 2 MaxPacketSize 64
[ 3939.433708] usb 1-1: Setting MaxPacketSize 64
[ 3939.442346] usb 1-1: FTDI USB Serial Device converter now attached to [B]ttyUSB0[/B]


CP2102模块的话,输出稍有不同:
# lsusb
Bus 001 Device 003: ID 10c4:ea60 Cygnal Integrated Products, Inc. CP210x UART Bridge / myAVR mySmartUSB light

# dmesg
[ 3421.303602] cp210x 1-1:1.0: cp210x converter detected
[ 3421.554407] usb 1-1: reset full-speed USB device number 3 using uhci_hcd
[ 3421.703370] usb 1-1: cp210x converter now attached to ttyUSB0


此时使用终端工具以115385波特率连接ttyUSB0设备(有些机器是ttyUSB1,可以通过上面dmesg输出确定)。连接后,任何键入字符,应该能正确显示在终端上。

下面以minicom为例:
sudo pacman -S minicom  (或者apt-get install minicom)
sudo minicom -D /dev/ttyUSB0 -b 115385 -s

在对话框中选择"Serial port setup",按F键关闭"Hardware Flow Control",最终配置如图所示:


按回车并选"Exit"进入minicom主界面(当然也可以保存下配置),键盘随便敲些字符。能够成功显示键入字符,说明模块的TX/RX均正常,可以连接机器了。按Ctrl-A接着按Z,按X退出minicom

拔下模块接上刷机线,黑线接GND,红色和白色分别接TXD和RXD。TX/RX经常会弄反,这里LED指示灯就能派上用场了
sudo minicom -D /dev/ttyUSB0 -b 115385 -s

像刚才一样关掉"Hardware Flow Control"进入,将C118关机并短按电源键,连接正常的话会显示下面的内容先显示ftmtool,接着大约1秒后输出error,看到这个说明连接无误。


已经成功了一半,下面祈祷C118的硬件没有故障。

参考osmocon的使用教程http://bb.osmocom.org/trac/wiki/osmocon

先为osmocom创建配置文件
sudo mkdir /etc/osmocom/
sudo touch /etc/osmocom/osmocom.cfg


接着确认机器型号,C118是compal_e88的固件,使用osmocon需要刷入layer1,位于
src/target/firmware/board/compal_e88/layer1.compalram.bin

cd ~/osmocom-bb/src/
cd host/osmocon/		[COLOR="DarkSlateGray"]# 一些在电脑上运行的工具都在host目录下[/COLOR]


使用下面命令启动osmocon等待刷机:
sudo ./osmocon -p /dev/ttyUSB0 -m c123xor ../../target/firmware/board/compal_e88/layer1.compalram.bin


此时确保C118在关机状态,将刷机线插到底后,短按电源键:
got 1 bytes from modem, data looks like: 04  .
got 1 bytes from modem, data looks like: 81  .
got 4 bytes from modem, data looks like: 1b f6 02 00  ....
got 1 bytes from modem, data looks like: 41  A
got 1 bytes from modem, data looks like: 01  .
got 1 bytes from modem, data looks like: 40  @
Received PROMPT1 from phone, responding with CMD
read_file(../../target/firmware/board/compal_e88/layer1.compalram.bin): file_size=55940, hdr_len=4, dnload_len=55947
got 1 bytes from modem, data looks like: 1b  .
got 1 bytes from modem, data looks like: f6  .
got 1 bytes from modem, data looks like: 02  .
got 1 bytes from modem, data looks like: 00  .
got 1 bytes from modem, data looks like: 41  A
got 1 bytes from modem, data looks like: 02  .
got 1 bytes from modem, data looks like: 43  C
Received PROMPT2 from phone, starting download
handle_write(): 4096 bytes (4096/55947)
handle_write(): 4096 bytes (8192/55947)
handle_write(): 4096 bytes (12288/55947)
handle_write(): 4096 bytes (16384/55947)
handle_write(): 4096 bytes (20480/55947)
handle_write(): 4096 bytes (24576/55947)
handle_write(): 4096 bytes (28672/55947)
handle_write(): 4096 bytes (32768/55947)
handle_write(): 4096 bytes (36864/55947)
handle_write(): 4096 bytes (40960/55947)
handle_write(): 4096 bytes (45056/55947)
handle_write(): 4096 bytes (49152/55947)
handle_write(): 4096 bytes (53248/55947)
handle_write(): 2699 bytes (55947/55947)
handle_write(): finished



上面步骤一切正常的情况下,会看到DOWNLOAD ACK和OSMOCOM Layer 1的提示,此时C118屏幕上已经显示出layer1的界面了:

got 1 bytes from modem, data looks like: 1b  .
got 1 bytes from modem, data looks like: f6  .
got 1 bytes from modem, data looks like: 02  .
got 1 bytes from modem, data looks like: 00  .
got 1 bytes from modem, data looks like: 41  A
got 1 bytes from modem, data looks like: 03  .
got 1 bytes from modem, data looks like: 42  B
Received DOWNLOAD ACK from phone, your code is running now!
battery_compal_e88_init: starting up


OSMOCOM Layer 1 (revision osmocon_v0.0.0-1351-g074c78a-modified)



因为是软刷,按电源键大约2秒会关机。关机后需要重新执行上面操作刷入layer1
如果想把固件烧入手机中,可以参考这里:http://bb.osmocom.org/trac/wiki/flashing_new
也许是版本问题,在我的机器上总是提示crc错误。想想刷完这个还不能用直充充电,还是每次用之前软刷好了。

----------------------------------------------------------------------------------------

然而,不是事事都那么顺利。我有幸买到一台有问题的C118,断电后第一次刷机,总是无法收到DOWNLOAD ACK,直接卡死在handle_write(): finished这里。此时屏幕不亮短按电源键也没有任何反应:


虽然不是Android系统,一样可以祭出Android三宝绝招——拔电池。重新插上电池后,短按电源重新刷入,正常看到OSMOCOM Layer 1的提示(建议遇到各种非线缆相关的疑难杂症,都先尝试下拔电池重刷,这个好像是osmocom不稳定导致的)

另外,这里说下我之前犯的一个低级错误:模块和连接都确认没问题,但按电源键确输出一堆乱码。


这个网上Google了好久都没有结果,甚至mail list里还有哥们说是手机的接收模块烧了。结果最后卖家发来张图片:(抱歉旺信丢消息了,图片找不到了 大致就是红圈这里,没有插到位)


打开电池后盖才发现,如果不用小刀狠狠削掉一圈,这个数据线根本没法插到底。(微博上也看到2个同学遇到相同的问题,看来数据线都是同一家买的-_-b)

另外一种情况是只收到PROMPT1后,就出现ftmtool error了。网上有种说法是主机的时钟频率太慢(比如在虚拟机里跑osmocon),导致没有发完就超时了。但我专门用VMWARE测试,并没有遇到这样的问题。
个人理解是osmocomBB的刷机不稳定,遇到这种情况请先检查是否用了burst_ind分支(也就是sylvain/testing),我之前就因为用的这份老代码,导致刷一下午只有1-2次能成功。另外还可以把-m c123xor换成-m c123试试,有时候去掉xor方式后可以正常刷进去。
更新libosmocore并换成luca/gsmmap分支后,就再也没有遇到这个情况了。

我并非通信专业出身,GSM网络的各种概念在此之前一无所知,如果文章中有错误欢迎指正:)
上传的附件:
2
Tee8088 2013-12-14 21:29
4
前排插入,果断顶,保存网页ing.........

上面看完了,大意是买个MOTO的手机,买TTL线,下载osmocom来在linux下配置好后编译,然后用TTL线对MOTO的手机进行刷进,刷入osmocom系统,,,非常详细,很好很好,这个非常有兴趣,楼主继续啊,越详细越好。
yingyue 2013-12-14 21:36
5
等续编。。。
猫子 2013-12-14 21:39
6
前排支持。。。
8
木桩 2013-12-14 22:30
7
之前介绍了OsmocomBB的硬件与刷机,这里重点介绍下其附带软件的使用。

参考官方wiki可以知道osmocomBB的代码可以分为两种:一种是在手机基带芯片上跑的layer1(物理传输层);另一种是在PC上跑的与layer1通信,提供上层服务的程序:
[root@ArchDev ~]# cd osmocom-bb/src/
[root@ArchDev src]# ls
Makefile  README.building  README.development  host  shared  target  target_dsp  wireshark


target下就是针对各手机的固件,bin位于target/firmware/board/compal_e88下。Baseband firmware一节介绍了不同固件的功能和对应程序,*.compalram是软刷用的,断电后需要重新刷机。*.e88flash/*.e88loader是配合loader使用的,刷入前需要参考 http://bb.osmocom.org/trac/wiki/flashing_new 把loader写到手机中,然后在手机上用loader运行。

后面cell_log和ccch_scan都是对应layer1的,因为直接写入有一定危险性,本文只演示软刷(layer1.compalram)的使用方法。

回到src目录下,接着看PC侧的工具:
[root@ArchDev ~]# cd ~/osmocom-bb/src/
[root@ArchDev host]# ls
calypso_pll  fb_tools  gsmmap  layer23	osmocon  rita_pll


osmocon是刷入固件,并与固件通信的程序,使用方法(注意C118选compal_e88/layer1.compalram.bin这个固件):
$ cd host/osmocon/
$ ./osmocon -p /dev/ttyUSB0 -m c123xor ../../target/firmware/board/compal_e88/layer1.compalram.bin


将C118关机后,短按电源键就开始运行了。刷机过程和常见问题硬件篇都已经提过,这里不再详述。

layer23下,有实现不同功能的数据链路层/网络层程序,比如模拟手机功能的mobile(接入网络需要SIM卡),以及抓取相关信息的杂项程序。直接进入misc目录:
cd layer23/src/misc/


cell_log是一个扫描有效运营商频率,并收集BCCH上基本信息的工具,我们先用它来获取运营商的ARFCN、MNC和MCC等信息。这里不需要gprs数据,直接使用这个参数:
-O --only-scan	Do a scan and show available ARFCNs, no data logging

[B]./cell_log --only-scan[/B]
...
<000e> cell_log.c:248 Cell: [COLOR="red"]ARFCN=56[/COLOR] PWR=-67dB [COLOR="Blue"]MCC=460 MNC=00[/COLOR] (China, China Mobile)



例如这里选取信号最强的ARFCN=56 (China Mobile),有了这个就可以开始抓取Common Control Channel (CCCH)了:
./ccch_scan [B]-a 56[/B] -i 127.0.0.1


看到ccch_scan开始输出burst内容后,就可以
sudo wireshark -k -i lo -f 'port 4729'


打开Wireshark来抓GSMTAP,设置 gsm_sms 过滤器即可看到SMS报文内容:


-------------------------------------------------------------------------

为了加深对SMS传输的理解,我写了个Python脚本来重组短信的PDU。
下面部分需要些GSM网络相关的知识,推荐 GSM network and services 2G1723 2006


从协议图中得知,移动设备(MS)和基站(BTS)间使用Um接口,最底层就是刷入手机的layer1物理传输层,之上分别是layer2数据链路层layer3网络层

位于图中layer2的LAPDm,是一种保证数据传输不会出错的协议。一个LAPDm帧共有23个字节(184个比特),提供分片管理控制等功能:


layer3的协议则可以分为RR/MM/CM三种,这里只列出嗅探相关的功能:
[B]RR(Radio Resource Management)[/B]:channel, cell控制等信息,可以忽略
[B]MM(Mobility Management)[/B]:Location updating(如果需要接收方号码,需要关注这个动作)
[B]CM(Connection Management)[/B]:Call Control(语音通话时的控制信息,可以知道何时开始捕获TCH), SMS(这里的重点)


参考GSM的文档 TS 04.06 得知 LAPDm 的Address field字段中,定义了 3.3.3 Service access point identifier (SAPI)

SAPI value	Related entity 
0	Call control signalling, mobility management signalling and radio resource management signalling
3	Short message service


SAPI=3就是我们要的Short message service,如图:


3gpp的GSM文档看得比较晕,这里直接对照Wireshark里的gsm_sms报文分析,发现SMS帧实际是重组LAPDm的payload得到的。也就说如果想自己处理SMS帧,就必须也和Wireshark一样重组LAPDm的payload,并解析其中的SMS PDU。



这是一个SAPI=3的LAPDm报文头部。GSMTAP是一种伪头部http://bb.osmocom.org/trac/wiki/GSMTAP,记录了burst的一些基本信息(如ChannelType,ARFCN,上行还是下行等)。因为是用ccch_scan捕获的流量,编码时只用关注 Channel Type: SDCCH/8 的LADPm协议。

为了方便访问,定义GSMTAP类如下,传入udp payload部分,解析GSMTAP并提供其后的数据:
class GSMTAP:
	def __init__(self, gsmtap):
		self.gsmtap = gsmtap

		setattr(self, "version", ord(gsmtap[0]))
		setattr(self, "hdr_len", ord(gsmtap[1]) << 2)
		setattr(self, "payload_type", ord(gsmtap[2]))

		setattr(self, "time_slot", ord(gsmtap[3]))
		ARFCN = (ord(gsmtap[4])&0x3F)*0x100 + ord(gsmtap[5])
		UPLINK = ord(gsmtap[4]) >> 6
		setattr(self, "arfcn", ARFCN)
		setattr(self, "link", UPLINK)

		setattr(self, "signal_noise", ord(gsmtap[6]))
		setattr(self, "signal_level", ord(gsmtap[7]))
		# GSM Frame Number
		setattr(self, "channel_type", ord(gsmtap[12]))
		setattr(self, "antenna_number", ord(gsmtap[13]))
		setattr(self, "sub_slot", ord(gsmtap[14]))

	def get_payload(self):
		return self.gsmtap[self.hdr_len:]


GSMTAP Header之后是 Link Access Procedure, Channel Dm,即LAPDm。参考TS 04.06有3个关键字段: Address Field,Control Field,Length Field

Address Field除了上面说的SAPI外都可以不关注。
Control Field比较关键,里面记录了该LAPDm的分片信息。Frame type: Information frame说明当前是I帧(I frame),其余bit为N(S)和N(R)。Send sequence number N(S)标记该分片的顺序,从0开始递增。看Wireshark源码说实际有些N(S)可能不是从0开始的,这里组包就不判断N(S)是否为0直接按顺序附加。N(R)是Receive sequence number,看文档上I帧传输时N(R)的状态没看明白,直接默认同时间只有1个下行短信了,这样收到的N(R)基本是一样的(事实上大部分时候都是如此)
Length Field除了长度信息,还有 More segments 标记,直到这个位为0才表示接收完一个完整的SMS报文

class LAPDm:
	def __init__(self, lapdm):
		setattr(self, "lapdm", lapdm)

		setattr(self, "addr_field", ord(lapdm[0]))
		setattr(self, "lpd", (ord(lapdm[0])>>5)&0x3)
		setattr(self, "sapi", (ord(lapdm[0])>>2)&0x7)

		setattr(self, "ctrl_field", ord(lapdm[1]))
		setattr(self, "n_r", ord(lapdm[1])>>5)
		setattr(self, "n_s", (ord(lapdm[1])>>1)&0x7)

		setattr(self, "len_field", ord(lapdm[2]))
		setattr(self, "has_more", (ord(lapdm[2])>>1)&0x1)
		setattr(self, "length", ord(lapdm[2])>>2)

	def get_data(self):
		return self.lapdm[3:]


之后就可以这样,获得LAPDm的相关信息了:
gsmtap = GSMTAP(gsm_payload)
lapdm = LAPDm(gsmtap.get_payload())

if (gsmtap.channel_type == 8) and (lapdm.sapi == 3):	# TS 04.06, 3.3.3, SAPI: 3 - Short message service
	debug_printf("LINK[%d] ARFCN=%d TIME_SLOT=%d CHANNEL=%d, N(R)=%d N(S)=%d, segment more[%d], payload len=%d\n" % \
		(gsmtap.link, gsmtap.arfcn, gsmtap.time_slot, gsmtap.channel_type, lapdm.n_r, lapdm.n_s, lapdm.has_more, lapdm.length))

	last_sms_payload += lapdm.get_data()		# 附加本次收到的数据
	if (lapdm.has_more == 0):			# 最后一个分片,解析整个 SMS payload
		hexdump(last_sms_payload)
		last_sms_payload = ""


接着看wireshark中重组的payload,确认得到的last_sms_payload和wireshark中解析的一致。

在wireshark中展开一个重组后的SMS报文


可以看到,在 GSM SMS TPDU (GSM 03.40) SMS-DELIVER 之前,还有CP-DATA/RP-DATA头,RP-DATA中有短信中心的信息,但没什么作用直接跳过。我们只需要知道后面SMS TPDU的长度即可:
class SMS:
	def __init__(self, payload):
		self.payload = payload

		iOff = 0
		# CP-DATA
		setattr(self, "protocol", ord(payload[iOff])&0xF); iOff+=1
		iOff += 2

		# RP-DATA (Network to MS)
		iOff += 2
		setattr(self, "RP_origin_len", ord(payload[iOff])); iOff+=1
		setattr(self, "RP_origin_ext", ord(payload[iOff]));
		setattr(self, "RP_origin", bcdDigits(payload[iOff+1:iOff+self.RP_origin_len]))
		iOff += self.RP_origin_len

		setattr(self, "RP_dest_len", ord(payload[iOff])); iOff+=1
		iOff += self.RP_dest_len

		setattr(self, "length", ord(payload[iOff])); iOff+=1
		setattr(self, "tpdu_off", iOff);

	def get_tpdu(self):
		return self.payload[self.tpdu_off:self.tpdu_off+self.length]


调用 get_tpdu() 就会返回TPDU内容,里面TP-Originating-Address就是发送者的号码,TP-User-Data就是我们要的短信内容。

class TPDU:
	def __init__(self, tpdu):
		setattr(self, "tpdu", tpdu)
		
		iOff = 0
		# SMS-DELIVER
		iOff += 1
		setattr(self, "TP_origin_num", ord(tpdu[iOff])); iOff+=1
		setattr(self, "TP_origin_len", (self.TP_origin_num>>1)+(self.TP_origin_num%2))
		setattr(self, "TP_origin_ext", ord(tpdu[iOff])); iOff+=1
		setattr(self, "TP_origin", bcdDigits(tpdu[iOff:iOff+self.TP_origin_len]))
		iOff += self.TP_origin_len

		iOff += 2
		iOff += 7	# TimeStamp

		setattr(self, "tpu_len", ord(tpdu[iOff])); iOff+=1
		setattr(self, "data", tpdu[iOff:iOff+self.tpu_len])

	def get_data(self):
		return self.data.decode("utf-16be").encode("utf-8")


中文在SMS中是UCS2编码的,get_data() 是用python的utf-16be解码原始数据,并转成UTF-8输出。

好了,加上process_sms_tpdu()函数,最终代码就是这样:
def process_sms_tpdu(sms_payload):
	hexdump(sms_payload)

	sms = SMS(sms_payload)
	tpdu = TPDU(sms.get_tpdu())
	debug_printf("[SMS from %s] %s" % (tpdu.TP_origin, tpdu.get_data()))

def handle_tcpdump_buffer(title, buffer):
	raw_struct = str2rawbuf(buffer)
	udp_packet = UDP(raw_struct)
	gsm_payload = udp_packet.get_payload()
	#hexdump(gsm_payload)

	gsmtap = GSMTAP(gsm_payload)
	lapdm = LAPDm(gsmtap.get_payload())

	if (gsmtap.channel_type == 8) and (lapdm.sapi == 3):		# TS 04.06, 3.3.3, SAPI: 3 - Short message service
		debug_printf("LINK[%d] ARFCN=%d TIME_SLOT=%d CHANNEL=%d, N(R)=%d N(S)=%d, segment more[%d], payload len=%d\n" % \
			(gsmtap.link, gsmtap.arfcn, gsmtap.time_slot, gsmtap.channel_type, lapdm.n_r, lapdm.n_s, lapdm.has_more, lapdm.length))

		global last_sms_payload
		last_sms_payload += lapdm.get_data()
		if (lapdm.has_more == 0):
			process_sms_tpdu(last_sms_payload)
			last_sms_payload = ""


注:文末的 gsmtap_sms_decode_src.7z 里有完整的解析脚本 使用 ./ccch_scan -a ARFCN -i 127.0.0.1 将GSMTAP转发到本机的4729端口后,可以用这个脚本来重组SMS报文:
tcpdump -l -ilo -nXs0 udp and port 4729 | python2 -u show_gsmtap_sms.py

运行截图:


-----------------------------------------------------------------------------------------

上面脚本只是为了熟悉lapdm的重组,并未处理N(S)非零,以及并发时下行短信的重组 建议有一定编码能力的同学,可以参考wireshark源码进行数据还原:

static void
[B]dissect_lapdm[/B](tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
            ... ...
            /* Rely on caller to provide a way to group fragments */
            fragment_id = (pinfo->circuit_id << 4) | (sapi << 1) | pinfo->p2p_dir;

            /* This doesn't seem the best way of doing it as doesn't
               take N(S) into account, but N(S) isn't always 0 for
               the first fragment!
             */
            fd_m = [B]fragment_add_seq_next[/B] (&lapdm_reassembly_table, payload, 0,
                                pinfo,
                                fragment_id, /* guint32 ID for fragments belonging together */
                                NULL,
                                /*n_s guint32 fragment sequence number */
                                len, /* guint32 fragment length */
                                m); /* More fragments? */
            ... ...
}


另外细心的各位可能会奇怪,下行短信里怎么没有短信接受者的号码,这里有篇关于SMS传输的基本原理说明:
http://robinlea.com/pub/Amphol/Security_Research_Labs.html

简单来讲,短信接受者的号码、IMEI等数据,只有在"Location Update"时才会在网络中出现,并且是以加密形式传输的。当接收短信时,基站根据之前位置更新时注册的信息,判断接收者的位置。所以,想要拿到接受者的号码,需要破解A5/1算法并还原出"Location Update"时的原文

Airprobe项目里有介绍如何破解A5/1算法找到Kc:https://srlabs.de/airprobe-how-to/ 只不过需要价格昂贵的USRP2...
另外还看到个RTL-SDR的文章(就是以前传说中可以跟踪飞机的电视棒),也支持Airprobe:
http://www.rtl-sdr.com/rtl-sdr-tutorial-analyzing-gsm-with-airprobe-and-wireshark/

到此,GSM Sniffering入门算是告一段落了,感谢各位的回帖与支持,以及zmworm版主的催稿,不然软件篇估计我要拖到年后
最近可能没有精力继续折腾GSM网络(年底事情多完全是借口,其实主要还是因为懒...),写这篇文章权当抛砖引玉了,希望能在看雪上看到A5/1破解和语音的还原,到时再来拜读各位的大作!
上传的附件:
奮鬥 2013-12-14 22:52
8
楼主技术太好了,膜拜中
6
Claud 2013-12-14 23:02
9
前排支持楼主~
crackhell 2013-12-14 23:35
10
前排支持。感谢分享好文章
34
安于此生 2013-12-14 23:39
11
我是来看楼主的手机滴...
40
riusksk 2013-12-14 23:57
12
楼主搞搞上行短信或语音嗅探吧,然后分享分享
8
木桩 2013-12-15 00:35
13
Uplink sniffing 以前是有实现的,只不过后来嗅探相关的代码被移除了(在这里最后有人提到,貌似target_dsp中还有些)

感谢33楼stinby提醒,抓上行流量是我看代码有点想当然了。看到这里有篇讨论:
http://baseband-devel.722152.n3.nabble.com/uplink-sniffing-td3531044.html
以及http://wulujia.com/2013/11/10/OsmocomBB-Guide/的文末也有图片
里面都提到,除了代码里增加ARFCN的上行偏移,还需要移除C118上的一个RX过滤器。这里是官方的一个指引:
http://bb.osmocom.org/trac/wiki/Hardware/FilterReplacement

语音除了需要抓TCH外(sniff_tch_sched_set也还有定义),还需要算出Kc才能解码。这篇论文附录里有提到如何操作,他是在USRP2上实现的(A5/1 rainbow-table攻击)。
osmocomBB上好像做不到实时,不过mail list中倒是有些资料。TCH部分目前还是一头雾水,如果有什么比较好的思路可以探讨一二
1
AioliaSky 2013-12-15 03:33
14
玩硬件的不容易啊
lxmls 2013-12-15 06:01
15
mark!
4
我是土匪 2013-12-15 06:33
16
学习了。感谢分享。
旧信纸 2013-12-15 07:40
17
牛。围观。
ybdao 2013-12-15 09:34
18
我记得OsmocomBB 还能查出基站码!
topofall 2013-12-15 10:28
19
围观,围观,留名
ufofind 2013-12-15 20:17
20
强人,牛人。
jeffli 2013-12-15 23:52
21
好厉害!有空学习一下!
cocobear 2013-12-16 13:08
22
将sniff_xcch_dl_sched_set和sniff_xcch_ul_sched_set互换,这样就触发l1s_sniff_cmd(ul=1)了。

仅这样就可以sniffer到上行的短信了吗?你试过吗?
whnet 2013-12-16 13:17
23
膜拜, 高端大气上档次。这些步骤感觉都是容易出错的步骤,如果不是理解单纯的按步骤来操作,很容易一出错就找不到路了。
8
木桩 2013-12-16 21:37
24
感谢33楼stinby提醒,抓上行流量是我看代码有点想当然了。看到这里有篇讨论:
http://baseband-devel.722152.n3.nabble.com/uplink-sniffing-td3531044.html
以及http://wulujia.com/2013/11/10/OsmocomBB-Guide/的文末也有图片
里面都提到,除了代码里增加ARFCN的上行偏移,还需要移除C118上的一个RX过滤器。这里是官方的一个指引:
http://bb.osmocom.org/trac/wiki/Hardware/FilterReplacement

------------------------------------
没有。但从layer1的prim_sniff.c代码来看应该是这样,具体行不行不妨折腾下。这个方法最初是在 https://srlabs.de/gprs/ 的文末看到的,不知道他用的是哪份代码,有个
# open "osmocom-bb/src/target/firmware/layer1/prim_sniff.c"
# at line 288, modify #if 1 to 0

的分支,后来被移除了。


但从现在gsmmap分支的代码看,都是保留了上行偏移量的
if (ul)
    rf_arfcn |= ARFCN_UPLINK;


所以只要使 l1s_sniff_cmd()/l1s_sniff_resp()参数ul非0,就能进入到UPLINK分支。
只是探讨,如果说错了还望指正
上传的附件:
路易 2013-12-17 09:15
25
有pdf文档吗?
修莫问 2013-12-17 10:51
26
见识了  感谢分享
corefix 2013-12-17 12:45
27
太高端了!学习了!
bakurise 2013-12-17 15:39
28
我半年前买了一套,可以看出来LZ研究了很长时间呀。

查资料,测试是非常花时间的事情,不知不觉一下午就没了。

感谢LZ分享了这么细致的流程,回头我也贴出来一些。
无心问世 2013-12-18 13:33
29
膜拜中。。。。。。。。。。
1
dalao 2013-12-18 13:44
30
这玩意以前玩过,有成型的商业版软件
2
open[xgc] 2013-12-18 14:27
31
牛B,学习了!
guobing 2013-12-18 14:30
32
呵呵,最近也在搞。我的c118也快到了。。。
wodexinren 2013-12-18 18:42
33
这个碉堡了,学习下
stinby 2013-12-18 18:57
34
要抓上行信道,好像还要更换接收滤波器吧??????????
1
netknight 2013-12-18 19:12
35
啊?!啊.nnvl
8
木桩 2013-12-18 19:47
36
恩,感谢指正。确实是我直接根据代码想当然了:http://bb.osmocom.org/trac/wiki/Hardware/FilterReplacement

看来除了增加ARFCN的偏移,还需要做硬件的改动
vvLinker 2013-12-18 20:15
37
看来要换3G了。。。
osmocombb 2013-12-18 20:33
38
LZ啊,为什么我用的没改装的设备,也获取到了uplink数据呢?而且屡试不爽。我完全晕了
shiyb 2013-12-19 03:23
39
学习了。感谢楼主分享!
5
pencil 2013-12-19 08:10
40
手机还是有区别的,一些刷的中文包是不能用的。
uplink需要改Filter,网上有卖改好的。
poochi 2013-12-19 16:23
41
这里看过一篇类似的http://www.creturn.com/radiowar-%e4%b9%8bosmocombb-sms-sniffer
1
嗦迪斯咧 2013-12-19 18:07
42
请问监视抓包需要插GSM电话卡么?
8
木桩 2013-12-19 20:38
43
中文的机器我也有一台(淘宝上找最便宜买的,30带盒子还带个充电器...),软刷和信号都完全正常,相反一开始买的英文机器,第一次刷入必然卡死,刷loader则提示CRC错误。
不过还有个现象没想明白,有时很正常的机器,换了个满电的电池就不断提示ftmtool error,但放了一阵子又好了
1
嗦迪斯咧 2013-12-19 21:32
44
看着你说的这么详细,我也想试试看,但是不知道是不是需要SIM卡?不插卡可以监测么?
goobey 2013-12-19 21:49
45
两年前的技术,现在才在各种论坛上贴出来,唉。
1
嗦迪斯咧 2013-12-19 21:55
46
技术的转化需要时间,等到传到中国国内,当然就好几年之后了,除非接触第一手英文资料。
wwlai 2013-12-20 15:30
47
autoreconf通不过,是你libtool没装吧。。
LiXMX 2013-12-20 20:34
48
至少LZ在今天把他发上来分享了!!!!!!
8
木桩 2013-12-21 10:27
49
ccch_scan抓包不用。SIM卡是mobile工具用的,可以模拟手机的功能
webappsec 2013-12-21 11:38
50
不明觉厉
rainbowf 2013-12-21 12:57
51
这个厉害了,好好学习一下!
返回