├── GRC └── jammer_gen.grc ├── README.md ├── __init__.py ├── imgs └── jamming_session.png ├── jammer_gen.py ├── smartjam_rpcclient.py └── utils ├── __init__.py └── eu_arfcn_calc.py /GRC/jammer_gen.grc: -------------------------------------------------------------------------------- 1 | options: 2 | parameters: 3 | author: '' 4 | catch_exceptions: 'True' 5 | category: Custom 6 | cmake_opt: '' 7 | comment: '' 8 | copyright: '' 9 | description: '' 10 | gen_cmake: 'On' 11 | gen_linking: dynamic 12 | generate_options: qt_gui 13 | hier_block_src_path: '.:' 14 | id: jammer_gen 15 | max_nouts: '0' 16 | output_language: python 17 | placement: (0,0) 18 | qt_qss_theme: '' 19 | realtime_scheduling: '' 20 | run: 'True' 21 | run_command: '{python} -u {filename}' 22 | run_options: prompt 23 | sizing_mode: fixed 24 | thread_safe_setters: '' 25 | title: '' 26 | window_size: '' 27 | states: 28 | bus_sink: false 29 | bus_source: false 30 | bus_structure: null 31 | coordinate: [8, 12] 32 | rotation: 0 33 | state: enabled 34 | 35 | blocks: 36 | - name: bandwidth 37 | id: variable_qtgui_range 38 | parameters: 39 | comment: '' 40 | gui_hint: '' 41 | label: Bandwidth 42 | min_len: '200' 43 | orient: QtCore.Qt.Horizontal 44 | rangeType: float 45 | start: 2e6 46 | step: '10' 47 | stop: 50e6 48 | value: var_bandwidth 49 | widget: counter_slider 50 | states: 51 | bus_sink: false 52 | bus_source: false 53 | bus_structure: null 54 | coordinate: [736, 20.0] 55 | rotation: 0 56 | state: true 57 | - name: bb_gain 58 | id: variable_qtgui_range 59 | parameters: 60 | comment: '' 61 | gui_hint: '' 62 | label: BB gain 63 | min_len: '200' 64 | orient: QtCore.Qt.Horizontal 65 | rangeType: float 66 | start: '10' 67 | step: '10' 68 | stop: '60' 69 | value: var_bb_gain 70 | widget: counter_slider 71 | states: 72 | bus_sink: false 73 | bus_source: false 74 | bus_structure: null 75 | coordinate: [607, 18] 76 | rotation: 0 77 | state: true 78 | - name: cent_freq 79 | id: variable_qtgui_range 80 | parameters: 81 | comment: '' 82 | gui_hint: '' 83 | label: Freq 84 | min_len: '200' 85 | orient: QtCore.Qt.Horizontal 86 | rangeType: float 87 | start: 900e6 88 | step: '500' 89 | stop: 2200e6 90 | value: var_cent_freq 91 | widget: counter_slider 92 | states: 93 | bus_sink: false 94 | bus_source: false 95 | bus_structure: null 96 | coordinate: [320, 17] 97 | rotation: 0 98 | state: true 99 | - name: if_gain 100 | id: variable_qtgui_range 101 | parameters: 102 | comment: '' 103 | gui_hint: '' 104 | label: IF gain 105 | min_len: '200' 106 | orient: QtCore.Qt.Horizontal 107 | rangeType: float 108 | start: '10' 109 | step: '10' 110 | stop: '60' 111 | value: var_if_gain 112 | widget: counter_slider 113 | states: 114 | bus_sink: false 115 | bus_source: false 116 | bus_structure: null 117 | coordinate: [188, 15] 118 | rotation: 0 119 | state: true 120 | - name: rf_gain 121 | id: variable_qtgui_range 122 | parameters: 123 | comment: '' 124 | gui_hint: '' 125 | label: RF gain 126 | min_len: '200' 127 | orient: QtCore.Qt.Horizontal 128 | rangeType: float 129 | start: '10' 130 | step: '10' 131 | stop: '60' 132 | value: var_rf_gain 133 | widget: counter_slider 134 | states: 135 | bus_sink: false 136 | bus_source: false 137 | bus_structure: null 138 | coordinate: [475, 17] 139 | rotation: 0 140 | state: true 141 | - name: samp_rate 142 | id: variable 143 | parameters: 144 | comment: '' 145 | value: 5e6 146 | states: 147 | bus_sink: false 148 | bus_source: false 149 | bus_structure: null 150 | coordinate: [8, 68] 151 | rotation: 0 152 | state: enabled 153 | - name: var_bandwidth 154 | id: variable 155 | parameters: 156 | comment: '' 157 | value: 10e6 158 | states: 159 | bus_sink: false 160 | bus_source: false 161 | bus_structure: null 162 | coordinate: [8, 396] 163 | rotation: 0 164 | state: enabled 165 | - name: var_bb_gain 166 | id: variable 167 | parameters: 168 | comment: '' 169 | value: '10' 170 | states: 171 | bus_sink: false 172 | bus_source: false 173 | bus_structure: null 174 | coordinate: [8, 324] 175 | rotation: 0 176 | state: enabled 177 | - name: var_cent_freq 178 | id: variable 179 | parameters: 180 | comment: '' 181 | value: '1874200000' 182 | states: 183 | bus_sink: false 184 | bus_source: false 185 | bus_structure: null 186 | coordinate: [8, 196] 187 | rotation: 0 188 | state: enabled 189 | - name: var_if_gain 190 | id: variable 191 | parameters: 192 | comment: '' 193 | value: '10' 194 | states: 195 | bus_sink: false 196 | bus_source: false 197 | bus_structure: null 198 | coordinate: [8, 132] 199 | rotation: 0 200 | state: enabled 201 | - name: var_rf_gain 202 | id: variable 203 | parameters: 204 | comment: '' 205 | value: '10' 206 | states: 207 | bus_sink: false 208 | bus_source: false 209 | bus_structure: null 210 | coordinate: [8, 260] 211 | rotation: 0 212 | state: enabled 213 | - name: analog_noise_source_x_0 214 | id: analog_noise_source_x 215 | parameters: 216 | affinity: '' 217 | alias: '' 218 | amp: '50' 219 | comment: '' 220 | maxoutbuf: '0' 221 | minoutbuf: '0' 222 | noise_type: analog.GR_GAUSSIAN 223 | seed: '0' 224 | type: complex 225 | states: 226 | bus_sink: false 227 | bus_source: false 228 | bus_structure: null 229 | coordinate: [195, 269] 230 | rotation: 0 231 | state: enabled 232 | - name: osmosdr_sink_0 233 | id: osmosdr_sink 234 | parameters: 235 | affinity: '' 236 | alias: '' 237 | ant0: '' 238 | ant1: '' 239 | ant10: '' 240 | ant11: '' 241 | ant12: '' 242 | ant13: '' 243 | ant14: '' 244 | ant15: '' 245 | ant16: '' 246 | ant17: '' 247 | ant18: '' 248 | ant19: '' 249 | ant2: '' 250 | ant20: '' 251 | ant21: '' 252 | ant22: '' 253 | ant23: '' 254 | ant24: '' 255 | ant25: '' 256 | ant26: '' 257 | ant27: '' 258 | ant28: '' 259 | ant29: '' 260 | ant3: '' 261 | ant30: '' 262 | ant31: '' 263 | ant4: '' 264 | ant5: '' 265 | ant6: '' 266 | ant7: '' 267 | ant8: '' 268 | ant9: '' 269 | args: bladerf=0 270 | bb_gain0: bb_gain 271 | bb_gain1: '20' 272 | bb_gain10: '20' 273 | bb_gain11: '20' 274 | bb_gain12: '20' 275 | bb_gain13: '20' 276 | bb_gain14: '20' 277 | bb_gain15: '20' 278 | bb_gain16: '20' 279 | bb_gain17: '20' 280 | bb_gain18: '20' 281 | bb_gain19: '20' 282 | bb_gain2: '20' 283 | bb_gain20: '20' 284 | bb_gain21: '20' 285 | bb_gain22: '20' 286 | bb_gain23: '20' 287 | bb_gain24: '20' 288 | bb_gain25: '20' 289 | bb_gain26: '20' 290 | bb_gain27: '20' 291 | bb_gain28: '20' 292 | bb_gain29: '20' 293 | bb_gain3: '20' 294 | bb_gain30: '20' 295 | bb_gain31: '20' 296 | bb_gain4: '20' 297 | bb_gain5: '20' 298 | bb_gain6: '20' 299 | bb_gain7: '20' 300 | bb_gain8: '20' 301 | bb_gain9: '20' 302 | bw0: bandwidth 303 | bw1: '0' 304 | bw10: '0' 305 | bw11: '0' 306 | bw12: '0' 307 | bw13: '0' 308 | bw14: '0' 309 | bw15: '0' 310 | bw16: '0' 311 | bw17: '0' 312 | bw18: '0' 313 | bw19: '0' 314 | bw2: '0' 315 | bw20: '0' 316 | bw21: '0' 317 | bw22: '0' 318 | bw23: '0' 319 | bw24: '0' 320 | bw25: '0' 321 | bw26: '0' 322 | bw27: '0' 323 | bw28: '0' 324 | bw29: '0' 325 | bw3: '0' 326 | bw30: '0' 327 | bw31: '0' 328 | bw4: '0' 329 | bw5: '0' 330 | bw6: '0' 331 | bw7: '0' 332 | bw8: '0' 333 | bw9: '0' 334 | clock_source0: '' 335 | clock_source1: '' 336 | clock_source2: '' 337 | clock_source3: '' 338 | clock_source4: '' 339 | clock_source5: '' 340 | clock_source6: '' 341 | clock_source7: '' 342 | comment: '' 343 | corr0: '0' 344 | corr1: '0' 345 | corr10: '0' 346 | corr11: '0' 347 | corr12: '0' 348 | corr13: '0' 349 | corr14: '0' 350 | corr15: '0' 351 | corr16: '0' 352 | corr17: '0' 353 | corr18: '0' 354 | corr19: '0' 355 | corr2: '0' 356 | corr20: '0' 357 | corr21: '0' 358 | corr22: '0' 359 | corr23: '0' 360 | corr24: '0' 361 | corr25: '0' 362 | corr26: '0' 363 | corr27: '0' 364 | corr28: '0' 365 | corr29: '0' 366 | corr3: '0' 367 | corr30: '0' 368 | corr31: '0' 369 | corr4: '0' 370 | corr5: '0' 371 | corr6: '0' 372 | corr7: '0' 373 | corr8: '0' 374 | corr9: '0' 375 | freq0: cent_freq 376 | freq1: 100e6 377 | freq10: 100e6 378 | freq11: 100e6 379 | freq12: 100e6 380 | freq13: 100e6 381 | freq14: 100e6 382 | freq15: 100e6 383 | freq16: 100e6 384 | freq17: 100e6 385 | freq18: 100e6 386 | freq19: 100e6 387 | freq2: 100e6 388 | freq20: 100e6 389 | freq21: 100e6 390 | freq22: 100e6 391 | freq23: 100e6 392 | freq24: 100e6 393 | freq25: 100e6 394 | freq26: 100e6 395 | freq27: 100e6 396 | freq28: 100e6 397 | freq29: 100e6 398 | freq3: 100e6 399 | freq30: 100e6 400 | freq31: 100e6 401 | freq4: 100e6 402 | freq5: 100e6 403 | freq6: 100e6 404 | freq7: 100e6 405 | freq8: 100e6 406 | freq9: 100e6 407 | gain0: rf_gain 408 | gain1: '10' 409 | gain10: '10' 410 | gain11: '10' 411 | gain12: '10' 412 | gain13: '10' 413 | gain14: '10' 414 | gain15: '10' 415 | gain16: '10' 416 | gain17: '10' 417 | gain18: '10' 418 | gain19: '10' 419 | gain2: '10' 420 | gain20: '10' 421 | gain21: '10' 422 | gain22: '10' 423 | gain23: '10' 424 | gain24: '10' 425 | gain25: '10' 426 | gain26: '10' 427 | gain27: '10' 428 | gain28: '10' 429 | gain29: '10' 430 | gain3: '10' 431 | gain30: '10' 432 | gain31: '10' 433 | gain4: '10' 434 | gain5: '10' 435 | gain6: '10' 436 | gain7: '10' 437 | gain8: '10' 438 | gain9: '10' 439 | if_gain0: if_gain 440 | if_gain1: '20' 441 | if_gain10: '20' 442 | if_gain11: '20' 443 | if_gain12: '20' 444 | if_gain13: '20' 445 | if_gain14: '20' 446 | if_gain15: '20' 447 | if_gain16: '20' 448 | if_gain17: '20' 449 | if_gain18: '20' 450 | if_gain19: '20' 451 | if_gain2: '20' 452 | if_gain20: '20' 453 | if_gain21: '20' 454 | if_gain22: '20' 455 | if_gain23: '20' 456 | if_gain24: '20' 457 | if_gain25: '20' 458 | if_gain26: '20' 459 | if_gain27: '20' 460 | if_gain28: '20' 461 | if_gain29: '20' 462 | if_gain3: '20' 463 | if_gain30: '20' 464 | if_gain31: '20' 465 | if_gain4: '20' 466 | if_gain5: '20' 467 | if_gain6: '20' 468 | if_gain7: '20' 469 | if_gain8: '20' 470 | if_gain9: '20' 471 | maxoutbuf: '0' 472 | minoutbuf: '0' 473 | nchan: '1' 474 | num_mboards: '1' 475 | sample_rate: bandwidth+bandwidth/80 476 | sync: sync 477 | time_source0: '' 478 | time_source1: '' 479 | time_source2: '' 480 | time_source3: '' 481 | time_source4: '' 482 | time_source5: '' 483 | time_source6: '' 484 | time_source7: '' 485 | type: fc32 486 | states: 487 | bus_sink: false 488 | bus_source: false 489 | bus_structure: null 490 | coordinate: [481, 197] 491 | rotation: 0 492 | state: enabled 493 | - name: xmlrpc_server_0 494 | id: xmlrpc_server 495 | parameters: 496 | addr: localhost 497 | alias: '' 498 | comment: '' 499 | port: '8888' 500 | states: 501 | bus_sink: false 502 | bus_source: false 503 | bus_structure: null 504 | coordinate: [304, 420.0] 505 | rotation: 0 506 | state: enabled 507 | 508 | connections: 509 | - [analog_noise_source_x_0, '0', osmosdr_sink_0, '0'] 510 | 511 | metadata: 512 | file_format: 1 513 | grc_version: 3.10.5.1 514 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Modmobjam 2 | 3 | A smart jamming proof of concept for mobile equipments that could be powered with [Modmobmap](https://github.com/PentHertz/Modmobmap) 4 | 5 | For more information, this little tool has been presented during SSTIC rump 2018: 6 | 7 | - english slides: https://penthertz.com/resources/sstic_rump_2018_modmobjam.pdf 8 | - french presentation: https://static.sstic.org/rumps2018/SSTIC_2018-06-14_P10_RUMPS_22.mp4 9 | 10 | ## Warning 11 | 12 | You should be warned that Jamming is illegal and you're responsible for any damages when using it on your own. 13 | 14 | ## Prerequisites 15 | 16 | - a radio devices that is enabled to transmit signal (HackRF, USRP, bladeRF, and so on.) 17 | - GNU Radio installed 18 | - Modmobmap to perform automatic smartjamming: https://github.com/PentHertz/Modmobmap 19 | 20 | ## Usage 21 | 22 | ### Manual jamming 23 | 24 | If you have a HackRF or any device compatible with osmocom drivers, you can directly run the code provided in ``GRC/jammer_gen.py`` as follows: 25 | 26 | ```sh 27 | $ python GRC/jammer_gen.py 28 | ``` 29 | 30 | Note that compatible devices with `gr-osmosdr` are the following: 31 | 32 | * FunCube Dongle through libgnuradio-fcd 33 | * FUNcube Dongle Pro+ through gr-fcdproplus 34 | * sysmocom OsmoSDR Devices through libosmosdr 35 | * Nuand LLC bladeRF through libbladeRF library 36 | * Great Scott Gadgets HackRF through libhackrf 37 | * Ettus USRP Devices through Ettus UHD library 38 | * Fairwaves UmTRX through Fairwaves' fork of Ettus' UHD library 39 | * RFSPACE SDR-IQ, SDR-IP, NetSDR (incl. X2 option) 40 | * RTL2832U based DVB-T dongles through librtlsdr 41 | * RTL-TCP spectrum server (see librtlsdr project) 42 | * MSi2500 based DVB-T dongles through libmirisdr 43 | * SDRplay RSP through SDRplay API library 44 | * AirSpy R820t dongles through libairspy 45 | 46 | For those who want to use another device, edit the GNU Radio block schema ``GRC/jammer_gen.grc``: 47 | 48 | ```sh 49 | $ gnuradio-companion GRC/jammer_gen.grc 50 | ``` 51 | 52 | Then you can configure the central frequency with the QT GUI to target a frequency. But this tool has also a feature to do it automatically. 53 | 54 | ### Automatic smartjamming 55 | 56 | To automate jamming, you can first get a list of we the [Modmobmap](https://github.com/PentHertz/Modmobmap) that saves a JSON file after monitoring surrounding cells in a precise location. This JSON file looks as follows: 57 | 58 | ```sh 59 | $ cat cells_.json 60 | { 61 | "****-***50": { 62 | "PCI": "****", 63 | "PLMN": "208-01", 64 | "TAC": "50****", 65 | "band": 3, 66 | "bandwidth": "20MHz", 67 | "eARFCN": 1850, 68 | "type": "4G" 69 | }, 70 | "7-***": { 71 | "PLMN": "208-20", 72 | "arfcn": 1018, 73 | "cid": "***", 74 | "type": "2G" 75 | }, 76 | "****:-****12": { 77 | "PLMN": "208-1", 78 | "RX": 10712, 79 | "TX": 9762, 80 | "band": 1, 81 | "type": "3G" 82 | }, 83 | [...] 84 | } 85 | ``` 86 | 87 | After generating this file containing cells to jam, you can launch the RPC client that communicate with ``GRC/jammer_gen.py`` as follows: 88 | 89 | ```sh 90 | $ python smartjam_rpcclient.py -f cells_.json 91 | ``` 92 | 93 | Then leverage the gain for transmission and you should observe that a lot of noise is overflowing the targeted cells with gaussian noise. 94 | 95 | ![Jamming session](https://raw.githubusercontent.com/PentHertz/Modmobjam/master/imgs/jamming_session.png) 96 | 97 | Please note that the delay between each targeted cell can be set with a provided arguments '-d' (see arguments helper). 98 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PentHertz/Modmobjam/996c67c027a27573e9298b491854cdfbed5d7bd3/__init__.py -------------------------------------------------------------------------------- /imgs/jamming_session.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PentHertz/Modmobjam/996c67c027a27573e9298b491854cdfbed5d7bd3/imgs/jamming_session.png -------------------------------------------------------------------------------- /jammer_gen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | # 5 | # SPDX-License-Identifier: GPL-3.0 6 | # 7 | # GNU Radio Python Flow Graph 8 | # Title: Jammer Gen 9 | # GNU Radio version: 3.10.5.1 10 | 11 | from packaging.version import Version as StrictVersion 12 | 13 | if __name__ == '__main__': 14 | import ctypes 15 | import sys 16 | if sys.platform.startswith('linux'): 17 | try: 18 | x11 = ctypes.cdll.LoadLibrary('libX11.so') 19 | x11.XInitThreads() 20 | except: 21 | print("Warning: failed to XInitThreads()") 22 | 23 | from gnuradio import analog 24 | from gnuradio import gr 25 | from gnuradio.filter import firdes 26 | from gnuradio.fft import window 27 | import sys 28 | import signal 29 | from PyQt5 import Qt 30 | from argparse import ArgumentParser 31 | from gnuradio.eng_arg import eng_float, intx 32 | from gnuradio import eng_notation 33 | from gnuradio.qtgui import Range, RangeWidget 34 | from PyQt5 import QtCore 35 | from xmlrpc.server import SimpleXMLRPCServer 36 | import threading 37 | import osmosdr 38 | import time 39 | 40 | 41 | 42 | from gnuradio import qtgui 43 | 44 | class jammer_gen(gr.top_block, Qt.QWidget): 45 | 46 | def __init__(self): 47 | gr.top_block.__init__(self, "Jammer Gen", catch_exceptions=True) 48 | Qt.QWidget.__init__(self) 49 | self.setWindowTitle("Jammer Gen") 50 | qtgui.util.check_set_qss() 51 | try: 52 | self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) 53 | except: 54 | pass 55 | self.top_scroll_layout = Qt.QVBoxLayout() 56 | self.setLayout(self.top_scroll_layout) 57 | self.top_scroll = Qt.QScrollArea() 58 | self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) 59 | self.top_scroll_layout.addWidget(self.top_scroll) 60 | self.top_scroll.setWidgetResizable(True) 61 | self.top_widget = Qt.QWidget() 62 | self.top_scroll.setWidget(self.top_widget) 63 | self.top_layout = Qt.QVBoxLayout(self.top_widget) 64 | self.top_grid_layout = Qt.QGridLayout() 65 | self.top_layout.addLayout(self.top_grid_layout) 66 | 67 | self.settings = Qt.QSettings("GNU Radio", "jammer_gen") 68 | 69 | try: 70 | if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"): 71 | self.restoreGeometry(self.settings.value("geometry").toByteArray()) 72 | else: 73 | self.restoreGeometry(self.settings.value("geometry")) 74 | except: 75 | pass 76 | 77 | ################################################## 78 | # Variables 79 | ################################################## 80 | self.var_rf_gain = var_rf_gain = 10 81 | self.var_if_gain = var_if_gain = 10 82 | self.var_cent_freq = var_cent_freq = 1874200000 83 | self.var_bb_gain = var_bb_gain = 10 84 | self.var_bandwidth = var_bandwidth = 10e6 85 | self.samp_rate = samp_rate = 5e6 86 | self.rf_gain = rf_gain = var_rf_gain 87 | self.if_gain = if_gain = var_if_gain 88 | self.cent_freq = cent_freq = var_cent_freq 89 | self.bb_gain = bb_gain = var_bb_gain 90 | self.bandwidth = bandwidth = var_bandwidth 91 | 92 | ################################################## 93 | # Blocks 94 | ################################################## 95 | 96 | self._rf_gain_range = Range(10, 60, 10, var_rf_gain, 200) 97 | self._rf_gain_win = RangeWidget(self._rf_gain_range, self.set_rf_gain, "RF gain", "counter_slider", float, QtCore.Qt.Horizontal) 98 | self.top_layout.addWidget(self._rf_gain_win) 99 | self._if_gain_range = Range(10, 60, 10, var_if_gain, 200) 100 | self._if_gain_win = RangeWidget(self._if_gain_range, self.set_if_gain, "IF gain", "counter_slider", float, QtCore.Qt.Horizontal) 101 | self.top_layout.addWidget(self._if_gain_win) 102 | self._cent_freq_range = Range(900e6, 2200e6, 500, var_cent_freq, 200) 103 | self._cent_freq_win = RangeWidget(self._cent_freq_range, self.set_cent_freq, "Freq", "counter_slider", float, QtCore.Qt.Horizontal) 104 | self.top_layout.addWidget(self._cent_freq_win) 105 | self._bb_gain_range = Range(10, 60, 10, var_bb_gain, 200) 106 | self._bb_gain_win = RangeWidget(self._bb_gain_range, self.set_bb_gain, "BB gain", "counter_slider", float, QtCore.Qt.Horizontal) 107 | self.top_layout.addWidget(self._bb_gain_win) 108 | self._bandwidth_range = Range(2e6, 50e6, 10, var_bandwidth, 200) 109 | self._bandwidth_win = RangeWidget(self._bandwidth_range, self.set_bandwidth, "Bandwidth", "counter_slider", float, QtCore.Qt.Horizontal) 110 | self.top_layout.addWidget(self._bandwidth_win) 111 | self.xmlrpc_server_0 = SimpleXMLRPCServer(('localhost', 8888), allow_none=True) 112 | self.xmlrpc_server_0.register_instance(self) 113 | self.xmlrpc_server_0_thread = threading.Thread(target=self.xmlrpc_server_0.serve_forever) 114 | self.xmlrpc_server_0_thread.daemon = True 115 | self.xmlrpc_server_0_thread.start() 116 | self.osmosdr_sink_0 = osmosdr.sink( 117 | args="numchan=" + str(1) + " " + 'bladerf=0' 118 | ) 119 | self.osmosdr_sink_0.set_time_unknown_pps(osmosdr.time_spec_t()) 120 | self.osmosdr_sink_0.set_sample_rate((bandwidth+bandwidth/80)) 121 | self.osmosdr_sink_0.set_center_freq(cent_freq, 0) 122 | self.osmosdr_sink_0.set_freq_corr(0, 0) 123 | self.osmosdr_sink_0.set_gain(rf_gain, 0) 124 | self.osmosdr_sink_0.set_if_gain(if_gain, 0) 125 | self.osmosdr_sink_0.set_bb_gain(bb_gain, 0) 126 | self.osmosdr_sink_0.set_antenna('', 0) 127 | self.osmosdr_sink_0.set_bandwidth(bandwidth, 0) 128 | self.analog_noise_source_x_0 = analog.noise_source_c(analog.GR_GAUSSIAN, 50, 0) 129 | 130 | 131 | ################################################## 132 | # Connections 133 | ################################################## 134 | self.connect((self.analog_noise_source_x_0, 0), (self.osmosdr_sink_0, 0)) 135 | 136 | 137 | def closeEvent(self, event): 138 | self.settings = Qt.QSettings("GNU Radio", "jammer_gen") 139 | self.settings.setValue("geometry", self.saveGeometry()) 140 | self.stop() 141 | self.wait() 142 | 143 | event.accept() 144 | 145 | def get_var_rf_gain(self): 146 | return self.var_rf_gain 147 | 148 | def set_var_rf_gain(self, var_rf_gain): 149 | self.var_rf_gain = var_rf_gain 150 | self.set_rf_gain(self.var_rf_gain) 151 | 152 | def get_var_if_gain(self): 153 | return self.var_if_gain 154 | 155 | def set_var_if_gain(self, var_if_gain): 156 | self.var_if_gain = var_if_gain 157 | self.set_if_gain(self.var_if_gain) 158 | 159 | def get_var_cent_freq(self): 160 | return self.var_cent_freq 161 | 162 | def set_var_cent_freq(self, var_cent_freq): 163 | self.var_cent_freq = var_cent_freq 164 | self.set_cent_freq(self.var_cent_freq) 165 | 166 | def get_var_bb_gain(self): 167 | return self.var_bb_gain 168 | 169 | def set_var_bb_gain(self, var_bb_gain): 170 | self.var_bb_gain = var_bb_gain 171 | self.set_bb_gain(self.var_bb_gain) 172 | 173 | def get_var_bandwidth(self): 174 | return self.var_bandwidth 175 | 176 | def set_var_bandwidth(self, var_bandwidth): 177 | self.var_bandwidth = var_bandwidth 178 | self.set_bandwidth(self.var_bandwidth) 179 | 180 | def get_samp_rate(self): 181 | return self.samp_rate 182 | 183 | def set_samp_rate(self, samp_rate): 184 | self.samp_rate = samp_rate 185 | 186 | def get_rf_gain(self): 187 | return self.rf_gain 188 | 189 | def set_rf_gain(self, rf_gain): 190 | self.rf_gain = rf_gain 191 | self.osmosdr_sink_0.set_gain(self.rf_gain, 0) 192 | 193 | def get_if_gain(self): 194 | return self.if_gain 195 | 196 | def set_if_gain(self, if_gain): 197 | self.if_gain = if_gain 198 | self.osmosdr_sink_0.set_if_gain(self.if_gain, 0) 199 | 200 | def get_cent_freq(self): 201 | return self.cent_freq 202 | 203 | def set_cent_freq(self, cent_freq): 204 | self.cent_freq = cent_freq 205 | self.osmosdr_sink_0.set_center_freq(self.cent_freq, 0) 206 | 207 | def get_bb_gain(self): 208 | return self.bb_gain 209 | 210 | def set_bb_gain(self, bb_gain): 211 | self.bb_gain = bb_gain 212 | self.osmosdr_sink_0.set_bb_gain(self.bb_gain, 0) 213 | 214 | def get_bandwidth(self): 215 | return self.bandwidth 216 | 217 | def set_bandwidth(self, bandwidth): 218 | self.bandwidth = bandwidth 219 | self.osmosdr_sink_0.set_sample_rate((self.bandwidth+self.bandwidth/80)) 220 | self.osmosdr_sink_0.set_bandwidth(self.bandwidth, 0) 221 | 222 | 223 | 224 | 225 | def main(top_block_cls=jammer_gen, options=None): 226 | 227 | if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"): 228 | style = gr.prefs().get_string('qtgui', 'style', 'raster') 229 | Qt.QApplication.setGraphicsSystem(style) 230 | qapp = Qt.QApplication(sys.argv) 231 | 232 | tb = top_block_cls() 233 | 234 | tb.start() 235 | 236 | tb.show() 237 | 238 | def sig_handler(sig=None, frame=None): 239 | tb.stop() 240 | tb.wait() 241 | 242 | Qt.QApplication.quit() 243 | 244 | signal.signal(signal.SIGINT, sig_handler) 245 | signal.signal(signal.SIGTERM, sig_handler) 246 | 247 | timer = Qt.QTimer() 248 | timer.start(500) 249 | timer.timeout.connect(lambda: None) 250 | 251 | qapp.exec_() 252 | 253 | if __name__ == '__main__': 254 | main() 255 | -------------------------------------------------------------------------------- /smartjam_rpcclient.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # ---------------------------------------------------------------------------- 5 | # "THE BEER-WARE LICENSE" (Revision 42): 6 | # )penthertz.com> wrote this file. As long as you retain this notice you 7 | # can do whatever you want with this stuff. If we meet some day, and you think 8 | # this stuff is worth it, you can buy me a beer in return FlUxIuS ;) 9 | # 10 | # We would like to thank our contributors for maintening this code: 11 | # - @h0rac Grzegorz Wypych from PWNsec.pl 12 | # ---------------------------------------------------------------------------- 13 | 14 | from __future__ import print_function 15 | 16 | import time 17 | import json 18 | import random 19 | import xmlrpc.client 20 | import argparse 21 | from utils.eu_arfcn_calc import * 22 | 23 | def superprintofdeath(message): 24 | print('\r'+message, end='\r\r\r\r\r\r\r', flush=True) 25 | 26 | 27 | if __name__ == "__main__": 28 | parser = argparse.ArgumentParser(description='Modmodjam - Software-Defined Radio Jammer') 29 | parser.add_argument('-s', '--host', dest='host', default='localhost', 30 | help='hostname to send RPC commands (default: "localhost")') 31 | parser.add_argument('-p', '--port', dest='port', default=8888, 32 | help='RPC server port (e.g: 8888 by default)') 33 | parser.add_argument('-f', '--file', dest='filepath', required=True, 34 | help='Modmobmap json file') 35 | parser.add_argument('-d', '--delay', dest='delay', default=2, 36 | help='Delay between each frequency to jam in sec (default: 2)') 37 | parser.add_argument('-b', '--bandwidth', dest='bandwidth', default=None, 38 | help='Define a static bandwidth. Will also influence the sample rate. By default it will use the bandwidth of the JSON file') 39 | parser.add_argument('-l', '--linkjam', dest='linkjam', default=0, 40 | help='Link to jam: "0" for downlink and "1" for uplink (default: "0")') 41 | parser.add_argument('-w', '--filterplm', dest='filterplmn', default=None, 42 | help='PLMN to filter. Example: 2082-1 (separated with commas)') 43 | 44 | t_freqs = {} 45 | args = parser.parse_args() 46 | host = args.host 47 | port = int(args.port) 48 | linkjam = int(args.linkjam) 49 | filepath = args.filepath 50 | delay = int(args.delay) 51 | filterplmn = args.filterplmn 52 | bandwidth = args.bandwidth 53 | 54 | s = xmlrpc.client.ServerProxy("http://%s:%s" % (host, port)) 55 | 56 | with open(filepath) as f: 57 | modmobdata = json.load(f) 58 | 59 | plmns = [] 60 | if filterplmn is not None: 61 | plmns = args.filterplmn.split(',') 62 | 63 | for key, val in modmobdata.items(): 64 | plmn = val['PLMN'] 65 | if plmn in plmns or filterplmn is None: 66 | band = None 67 | ctype = None 68 | findex = None 69 | downlink = None 70 | uplink = None 71 | cbandwidth = 10 # MHz 72 | if 'RX' in val: 73 | findex = val['RX'] 74 | elif 'eARFCN' in val: 75 | findex = val['eARFCN'] 76 | if 'band' in val: 77 | band = val['band'] 78 | if 'type' in val: 79 | ctype = val['type'] 80 | if bandwidth is not None: 81 | cbandwidth = bandwidth 82 | else: 83 | if 'bandwidth' in val: 84 | cbandwidth = int(val['bandwidth'].replace('MHz','')) 85 | try: 86 | if ctype == '3G': 87 | if band is None: 88 | band = findband(table_uarfcn, findex) 89 | downlink, uplink = uarfcn2freq(int(band), findex, None) 90 | elif ctype == '4G': 91 | if band is None: 92 | band = findband(table_earfcn, findex) 93 | downlink, uplink = earfcn2freq(int(band), findex, None) 94 | elif ctype == '2G': 95 | pass 96 | # not implemented for our purposes 97 | if downlink is not None and uplink is not None: 98 | cent_freq = downlink 99 | if linkjam == 1: 100 | cent_freq = uplink 101 | t_freqs[key] = { 'freq' : round(cent_freq), 102 | 'bandwidth' : cbandwidth } 103 | except Exception as e: 104 | print (e) 105 | while True: 106 | try: 107 | for key, val in t_freqs.items(): 108 | message="[+] Jamming cell {cell} central frequency at {freq} MHz with {bandwidth} MHz bandwidth".format(cell=key, freq=val['freq'], bandwidth=val['bandwidth']) 109 | superprintofdeath(message) 110 | s.set_var_cent_freq(val['freq']*1e6) 111 | s.set_var_bandwidth(val['bandwidth']*1e6) 112 | time.sleep(delay) 113 | except Exception as e: 114 | print('Stopping jammer...') 115 | state = False 116 | #print(e) 117 | break 118 | 119 | -------------------------------------------------------------------------------- /utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PentHertz/Modmobjam/996c67c027a27573e9298b491854cdfbed5d7bd3/utils/__init__.py -------------------------------------------------------------------------------- /utils/eu_arfcn_calc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # ---------------------------------------------------------------------------- 5 | # "THE BEER-WARE LICENSE" (Revision 42): 6 | # )synacktiv.com> wrote this file. As long as you retain this notice you 7 | # can do whatever you want with this stuff. If we meet some day, and you think 8 | # this stuff is worth it, you can buy me a beer in return FlUxIuS ;) 9 | # ---------------------------------------------------------------------------- 10 | 11 | from __future__ import print_function 12 | 13 | ##################################### 14 | # UARFCN and EARFCN Calculator 15 | ##################################### 16 | 17 | ## 18 | # Tables 19 | # 20 | table_earfcn = { 21 | 1 : { 'FDL_Low' : 2110, 22 | 'NDL_Offset' : 0, 23 | 'DL_range' : (0,599), 24 | 'FUL_Low' : 1920, 25 | 'NUL_Offset' : 18000, 26 | 'UP_range' : (1800,18599), 27 | }, 28 | 2 : { 'FDL_Low' : 1930, 29 | 'NDL_Offset' : 600, 30 | 'DL_range' : (600,1199), 31 | 'FUL_Low' : 1850, 32 | 'NUL_Offset' : 18600, 33 | 'UP_range' : (18600,19199), 34 | }, 35 | 3 : { 'FDL_Low' : 1805, 36 | 'NDL_Offset' : 1200, 37 | 'DL_range' : (1200,1949), 38 | 'FUL_Low' : 1710, 39 | 'NUL_Offset' : 19200, 40 | 'UP_range' : (19200,19949), 41 | }, 42 | 4 : { 'FDL_Low' : 2110, 43 | 'NDL_Offset' : 1950, 44 | 'DL_range' : (1950,2399), 45 | 'FUL_Low' : 1710, 46 | 'NUL_Offset' : 19950, 47 | 'UP_range' : (19950,20399), 48 | }, 49 | 5 : { 'FDL_Low' : 869, 50 | 'NDL_Offset' : 2400, 51 | 'DL_range' : (2400,2649), 52 | 'FUL_Low' : 824, 53 | 'NUL_Offset' : 20400, 54 | 'UP_range' : (20400,20649), 55 | }, 56 | 6 : { 'FDL_Low' : 875, 57 | 'NDL_Offset' : 2650, 58 | 'DL_range' : (2650,2749), 59 | 'FUL_Low' : 830, 60 | 'NUL_Offset' : 20650, 61 | 'UP_range' : (20650,20749), 62 | }, 63 | 7 : { 'FDL_Low' : 2620, 64 | 'NDL_Offset' : 2750, 65 | 'DL_range' : (2750,3449), 66 | 'FUL_Low' : 2500, 67 | 'NUL_Offset' : 20750, 68 | 'UP_range' : (20750,21449), 69 | }, 70 | 8 : { 'FDL_Low' : 925, 71 | 'NDL_Offset' : 3450, 72 | 'DL_range' : (3450,3799), 73 | 'FUL_Low' : 880, 74 | 'NUL_Offset' : 21450, 75 | 'UP_range' : (21450,21799), 76 | }, 77 | 9 : { 'FDL_Low' : 1844.9, 78 | 'NDL_Offset' : 3800, 79 | 'DL_range' : (3800,4149), 80 | 'FUL_Low' : 1749.9, 81 | 'NUL_Offset' : 21800, 82 | 'UP_range' : (21800,22149), 83 | }, 84 | 10 : { 'FDL_Low' : 2110, 85 | 'NDL_Offset' : 4150, 86 | 'DL_range' : (4150,4749), 87 | 'FUL_Low' : 1710, 88 | 'NUL_Offset' : 22150, 89 | 'UP_range' : (22150,22749), 90 | }, 91 | 11 : { 'FDL_Low' : 1475.9, 92 | 'NDL_Offset' : 4750, 93 | 'DL_range' : (4750,4949), 94 | 'FUL_Low' : 1427.9, 95 | 'NUL_Offset' : 22750, 96 | 'UP_range' : (22750,22949), 97 | }, 98 | 12 : { 'FDL_Low' : 729, 99 | 'NDL_Offset' : 5010, 100 | 'DL_range' : (5010,5179), 101 | 'FUL_Low' : 699, 102 | 'NUL_Offset' : 23010, 103 | 'UP_range' : (23010,23179), 104 | }, 105 | 13 : { 'FDL_Low' : 746, 106 | 'NDL_Offset' : 5180, 107 | 'DL_range' : (5180,5279), 108 | 'FUL_Low' : 777, 109 | 'NUL_Offset' : 23180, 110 | 'UP_range' : (23180,23279), 111 | }, 112 | 14 : { 'FDL_Low' : 758, 113 | 'NDL_Offset' : 5280, 114 | 'DL_range' : (5280,5379), 115 | 'FUL_Low' : 788, 116 | 'NUL_Offset' : 23280, 117 | 'UP_range' : (23280,23379), 118 | }, 119 | 17 : { 'FDL_Low' : 734, 120 | 'NDL_Offset' : 5730, 121 | 'DL_range' : (5730,5849), 122 | 'FUL_Low' : 704, 123 | 'NUL_Offset' : 23730, 124 | 'UP_range' : (23730,23849), 125 | }, 126 | 18 : { 'FDL_Low' : 860, 127 | 'NDL_Offset' : 5850, 128 | 'DL_range' : (5850,5999), 129 | 'FUL_Low' : 815, 130 | 'NUL_Offset' : 23850, 131 | 'UP_range' : (23850,23999), 132 | }, 133 | 19 : { 'FDL_Low' : 875, 134 | 'NDL_Offset' : 6000, 135 | 'DL_range' : (6000,6149), 136 | 'FUL_Low' : 830, 137 | 'NUL_Offset' : 24000, 138 | 'UP_range' : (24000,24149), 139 | }, 140 | 20 : { 'FDL_Low' : 791, 141 | 'NDL_Offset' : 6150, 142 | 'DL_range' : (6150,6449), 143 | 'FUL_Low' : 832, 144 | 'NUL_Offset' : 24150, 145 | 'UP_range' : (24150,24449), 146 | }, 147 | 21 : { 'FDL_Low' : 1495.9, 148 | 'NDL_Offset' : 6450, 149 | 'DL_range' : (6450,6599), 150 | 'FUL_Low' : 1447.9, 151 | 'NUL_Offset' : 24450, 152 | 'UP_range' : (24450,24599), 153 | }, 154 | 22 : { 'FDL_Low' : 3510, 155 | 'NDL_Offset' : 6600, 156 | 'DL_range' : (6600,7399), 157 | 'FUL_Low' : 3410, 158 | 'NUL_Offset' : 24600, 159 | 'UP_range' : (24600,25399), 160 | }, 161 | 23 : { 'FDL_Low' : 2180, 162 | 'NDL_Offset' : 7500, 163 | 'DL_range' : (7500,7699), 164 | 'FUL_Low' : 2000, 165 | 'NUL_Offset' : 25500, 166 | 'UP_range' : (25500,25699), 167 | }, 168 | 24 : { 'FDL_Low' : 1525, 169 | 'NDL_Offset' : 7700, 170 | 'DL_range' : (7700,8039), 171 | 'FUL_Low' : 1626.5, 172 | 'NUL_Offset' : 25700, 173 | 'UP_range' : (25700,26039), 174 | }, 175 | 25 : { 'FDL_Low' : 1930, 176 | 'NDL_Offset' : 8040, 177 | 'DL_range' : (8040,8689), 178 | 'FUL_Low' : 1850, 179 | 'NUL_Offset' : 26040, 180 | 'UP_range' : (26040,26689), 181 | }, 182 | 26 : { 'FDL_Low' : 859, 183 | 'NDL_Offset' : 8690, 184 | 'DL_range' : (8690,9039), 185 | 'FUL_Low' : 814, 186 | 'NUL_Offset' : 26690, 187 | 'UP_range' : (26690,27039), 188 | }, 189 | 27 : { 'FDL_Low' : 852, 190 | 'NDL_Offset' : 9040, 191 | 'DL_range' : (9040,9209), 192 | 'FUL_Low' : 807, 193 | 'NUL_Offset' : 27040, 194 | 'UP_range' : (27040,27209), 195 | }, 196 | 28 : { 'FDL_Low' : 758, 197 | 'NDL_Offset' : 9210, 198 | 'DL_range' : (9210,9659), 199 | 'FUL_Low' : 703, 200 | 'NUL_Offset' : 27210, 201 | 'UP_range' : (27210,27659), 202 | }, 203 | 30 : { 'FDL_Low' : 2350, 204 | 'NDL_Offset' : 9770, 205 | 'DL_range' : (9770,9869), 206 | 'FUL_Low' : 2305, 207 | 'NUL_Offset' : 27660, 208 | 'UP_range' : (27660,27759), 209 | }, 210 | 31 : { 'FDL_Low' : 462.5, 211 | 'NDL_Offset' : 9870, 212 | 'DL_range' : (9870,9919), 213 | 'FUL_Low' : 452.5, 214 | 'NUL_Offset' : 27760, 215 | 'UP_range' : (27760,27809), 216 | }, 217 | 65 : { 'FDL_Low' : 2110, 218 | 'NDL_Offset' : 65536, 219 | 'DL_range' : (65536,66435), 220 | 'FUL_Low' : 1920, 221 | 'NUL_Offset' : 131072, 222 | 'UP_range' : (131072,131971), 223 | }, 224 | 66 : { 'FDL_Low' : 2110, 225 | 'NDL_Offset' : 66436, 226 | 'DL_range' : (66436,67335), 227 | 'FUL_Low' : 1710, 228 | 'NUL_Offset' : 131972, 229 | 'UP_range' : (131972,132671), 230 | }, 231 | 68 : { 'FDL_Low' : 753, 232 | 'NDL_Offset' : 67536, 233 | 'DL_range' : (67536,67835), 234 | 'FUL_Low' : 698, 235 | 'NUL_Offset' : 132672, 236 | 'UP_range' : (132672,132971), 237 | }, 238 | 70 : { 'FDL_Low' : 1995, 239 | 'NDL_Offset' : 68336, 240 | 'DL_range' : (68336,68585), 241 | 'FUL_Low' : 1695, 242 | 'NUL_Offset' : 132972, 243 | 'UP_range' : (132972,133121), 244 | }, 245 | 71 : { 'FDL_Low' : 617, 246 | 'NDL_Offset' : 68586, 247 | 'DL_range' : (68586,68935), 248 | 'FUL_Low' : 663, 249 | 'NUL_Offset' : 133122, 250 | 'UP_range' : (133122,133471), 251 | }, 252 | 72 : { 'FDL_Low' : 461, 253 | 'NDL_Offset' : 68936, 254 | 'DL_range' : (68936,68985), 255 | 'FUL_Low' : 451, 256 | 'NUL_Offset' : 133472, 257 | 'UP_range' : (133472,133521), 258 | }, 259 | 73 : { 'FDL_Low' : 460, 260 | 'NDL_Offset' : 68986, 261 | 'DL_range' : (68986,69465), 262 | 'FUL_Low' : 450, 263 | 'NUL_Offset' : 133522, 264 | 'UP_range' : (133522,133571), 265 | }, 266 | 74 : { 'FDL_Low' : 1475, 267 | 'NDL_Offset' : 69036, 268 | 'DL_range' : (69036,69035), 269 | 'FUL_Low' : 1427, 270 | 'NUL_Offset' : 133572, 271 | 'UP_range' : (133572,134001), 272 | }, 273 | 85 : { 'FDL_Low' : 728, 274 | 'NDL_Offset' : 70366, 275 | 'DL_range' : (70366,70545), 276 | 'FUL_Low' : 698, 277 | 'NUL_Offset' : 134002, 278 | 'UP_range' : (134002,134181), 279 | }, 280 | } 281 | 282 | table_uarfcn = { 283 | 1 : { 'FDL_Offset' : 0, 284 | 'FDL_Low' : 2112.4, 285 | 'DL_range' : (10562,10838), 286 | 'FUL_Low' : 1922.4, 287 | 'NUL_Offset' : 0, 288 | 'UP_range' : (9612,9888), 289 | }, 290 | 2 : { 'FDL_Offset' : 0, 291 | 'FDL_Low' : 1932.4, 292 | 'DL_range' : (9662,9938), 293 | 'FUL_Low' : 1852.4, 294 | 'NUL_Offset' : 0, 295 | 'UP_range' : (9262,9538), 296 | }, 297 | 3 : { 'FDL_Offset' : 1525, 298 | 'FDL_Low' : 1712.4, 299 | 'DL_range' : (937,1288), 300 | 'FUL_Low' : 1807.4, 301 | 'NUL_Offset' : 1575, 302 | 'UP_range' : (1162,1513), 303 | }, 304 | 4 : { 'FDL_Offset' : 1805, 305 | 'FDL_Low' : 2112.4, 306 | 'DL_range' : (1537,1738), 307 | 'FUL_Low' : 1712.4, 308 | 'NUL_Offset' : 1450, 309 | 'UP_range' : (1312,1513), 310 | }, 311 | 5 : { 'FDL_Offset' : 0, 312 | 'FDL_Low' : 871.4, 313 | 'DL_range' : (4357,4458), 314 | 'FUL_Low' : 826.4, 315 | 'NUL_Offset' : 0, 316 | 'UP_range' : (4132,4233), 317 | }, 318 | 6 : { 'FDL_Offset' : 0, 319 | 'FDL_Low' : 877.4, 320 | 'DL_range' : (4387,4413), 321 | 'FUL_Low' : 832.4, 322 | 'NUL_Offset' : 0, 323 | 'UP_range' : (4162,4188), 324 | }, 325 | 7 : { 'FDL_Offset' : 2175, 326 | 'FDL_Low' : 2622.4, 327 | 'DL_range' : (2237,2563), 328 | 'FUL_Low' : 2502.4, 329 | 'NUL_Offset' : 2100, 330 | 'UP_range' : (2012,2338), 331 | }, 332 | 8 : { 'FDL_Offset' : 340, 333 | 'FDL_Low' : 927.4, 334 | 'DL_range' : (2937,3088), 335 | 'FUL_Low' : 882.4, 336 | 'NUL_Offset' : 340, 337 | 'UP_range' : (2712,2863), 338 | }, 339 | 9 : { 'FDL_Offset' : 0, 340 | 'FDL_Low' : 1847.4, 341 | 'DL_range' : (9237,93878), 342 | 'FUL_Low' : 1752.4, 343 | 'NUL_Offset' : 0, 344 | 'UP_range' : (8762,8912), 345 | }, 346 | 10 : { 'FDL_Offset' : 1490, 347 | 'FDL_Low' : 2112.4, 348 | 'DL_range' : (3112,3388), 349 | 'FUL_Low' : 1712.4, 350 | 'NUL_Offset' : 1135, 351 | 'UP_range' : (2887,3163), 352 | }, 353 | 11 : { 'FDL_Offset' : 736, 354 | 'FDL_Low' : 1478.4, 355 | 'DL_range' : (3712,3812), 356 | 'FUL_Low' : 1430.4, 357 | 'NUL_Offset' : 733, 358 | 'UP_range' : (3487,3587), 359 | }, 360 | 12 : { 'FDL_Offset' : -37, 361 | 'FDL_Low' : 730.4, 362 | 'DL_range' : (3837,3903), 363 | 'FUL_Low' : 700.4, 364 | 'NUL_Offset' : -22, 365 | 'UP_range' : (3612,3678), 366 | }, 367 | 13 : { 'FDL_Offset' : -55, 368 | 'FDL_Low' : 748.4, 369 | 'DL_range' : (4017,4043), 370 | 'FUL_Low' : 779.4, 371 | 'NUL_Offset' : 21, 372 | 'UP_range' : (3792,3818), 373 | }, 374 | 14 : { 'FDL_Offset' : -63, 375 | 'FDL_Low' : 760.4, 376 | 'DL_range' : (4117,4143), 377 | 'FUL_Low' : 790.4, 378 | 'NUL_Offset' : 12, 379 | 'UP_range' : (3892,3918), 380 | }, 381 | 19 : { 'FDL_Offset' : 735, 382 | 'FDL_Low' : 877.4, 383 | 'DL_range' : (712,763), 384 | 'FUL_Low' : 832.4, 385 | 'NUL_Offset' : 770, 386 | 'UP_range' : (312,363), 387 | }, 388 | 20 : { 'FDL_Offset' : -109, 389 | 'FDL_Low' : 793.4, 390 | 'DL_range' : (4512,4638), 391 | 'FUL_Low' : 834.4, 392 | 'NUL_Offset' : -23, 393 | 'UP_range' : (4287,4413), 394 | }, 395 | 21 : { 'FDL_Offset' : 1326, 396 | 'FDL_Low' : 1498.4, 397 | 'DL_range' : (862,912), 398 | 'FUL_Low' : 1450.4, 399 | 'NUL_Offset' : 1358, 400 | 'UP_range' : (462,512), 401 | }, 402 | 22 : { 'FDL_Offset' : 2580, 403 | 'FDL_Low' : 3512.4, 404 | 'DL_range' : (4662,5038), 405 | 'FUL_Low' : 3412.4, 406 | 'NUL_Offset' : 2525, 407 | 'UP_range' : (4437,4813), 408 | }, 409 | 25 : { 'FDL_Offset' : 910, 410 | 'FDL_Low' : 1932.4, 411 | 'DL_range' : (5112,5413), 412 | 'FUL_Low' : 1852.4, 413 | 'NUL_Offset' : 875, 414 | 'UP_range' : (4887,5188), 415 | }, 416 | 26 : { 'FDL_Offset' : -291, 417 | 'FDL_Low' : 1932.4, 418 | 'DL_range' : (5762,5913), 419 | 'FUL_Low' : 1852.4, 420 | 'NUL_Offset' : -291, 421 | 'UP_range' : (5537,5688), 422 | }, 423 | } 424 | 425 | ## 426 | # Functions 427 | # 428 | 429 | 430 | def findband(indextable, dl_frequency): 431 | for i,j in indextable.items(): 432 | if dl_frequency <= j['DL_range'][1] and dl_frequency >= j['DL_range'][0]: 433 | return i 434 | 435 | def uarfcn2freq(band, dl_uarfcn=None, ul_uarfcn=None): 436 | ''' 437 | in(1): int band index, 438 | in(2): int Downling UARFCN index, 439 | in(3): int Uplink UARFCN index, 440 | out: tuple (float downlink_freq, float uplink_freq) 441 | ''' 442 | duplex_spacing = abs(table_uarfcn[band]['FDL_Low']-table_uarfcn[band]['FUL_Low']) 443 | FDL_Offset = table_uarfcn[band]['FDL_Offset'] 444 | FUL_Offset = table_uarfcn[band]['NUL_Offset'] 445 | downlink_freq = uplink_freq = None 446 | if dl_uarfcn is not None: 447 | downlink_freq = FDL_Offset + 0.2 * dl_uarfcn 448 | if ul_uarfcn is not None: 449 | uplink_freq = FUL_Offset + 0.2 * ul_uarfcn 450 | if downlink_freq is not None and uplink_freq is None: 451 | uplink_freq = downlink_freq - duplex_spacing 452 | elif downlink_freq is None and uplink_freq is not None: 453 | downlink_freq = downlink_freq + duplex_spacing 454 | return (downlink_freq, uplink_freq) 455 | 456 | def earfcn2freq(band, dl_earfcn=None, ul_earfcn=None): 457 | ''' 458 | in(1): int band index, 459 | in(2): int Downling EARFCN index, 460 | in(3): int Uplink EARFCN index, 461 | out: tuple (float downlink_freq, float uplink_freq) 462 | ''' 463 | NDL_Offset = table_earfcn[band]['NDL_Offset'] 464 | NUL_Offset = table_earfcn[band]['NUL_Offset'] 465 | duplex_spacing = abs(table_earfcn[band]['FDL_Low']-table_earfcn[band]['FUL_Low']) 466 | FDL_Low = table_earfcn[band]['FDL_Low'] 467 | FUL_Low = table_earfcn[band]['FUL_Low'] 468 | downlink_freq = uplink_freq = None 469 | if dl_earfcn is not None: 470 | downlink_freq = FDL_Low + 0.1 * (dl_earfcn-NDL_Offset) 471 | if ul_earfcn is not None: 472 | uplink_freq = FUL_Low + 0.1 * (ul_earfcn-NUL_Offset) 473 | if downlink_freq is not None and uplink_freq is None: 474 | uplink_freq = downlink_freq - duplex_spacing 475 | elif downlink_freq is None and uplink_freq is not None: 476 | downlink_freq = downlink_freq + duplex_spacing 477 | return (downlink_freq, uplink_freq) 478 | 479 | if __name__ == "__main__": 480 | import argparse 481 | parser = argparse.ArgumentParser() 482 | parser.add_argument("nettype", type=int, help="select network type: 1 for 3G, and 2 for 4G") 483 | parser.add_argument("band", type=int, help="Band index") 484 | parser.add_argument("downlink", type=int, help="Downlink U/E-ARFCN") 485 | parser.add_argument("--uplink", type=int, help="Uplink U/E-ARFCN") 486 | args = parser.parse_args() 487 | if args.nettype == 1: 488 | ret = uarfcn2freq(args.band, args.downlink, args.uplink) 489 | elif args.nettype == 2: 490 | ret = earfcn2freq(args.band, args.downlink, args.uplink) 491 | print ("[+] Selected Downlink ARFCN %i (band %i)" % (args.downlink, args.band)) 492 | print ("Downlink: %f MHz and Uplink: %f MHz" % (ret[0],ret[1])) 493 | --------------------------------------------------------------------------------