Spoof GPS position on SITL

Hello guys,
I’m new on this forum and I would like to ask you guys the following…

So, basically, I have a few experience on dronekit, since I flew my 3DR drone on my field for research purposes. I’m also used to test my flights on dronekit-sitl and see the drone’s mission on Mission Planner or QGroundControl before going outside.
Now… my plan is to investigate about security issues on drones, specifically, GPS spoofing. The GPS spoofing is a technique that an attacker uses in order to deceive the GPS receiver of a victim. Once such GPS receiver is locked onto the spoofed GPS, the attacker has completely freedom and he can fly the drone in any arbitrary position.

Well, before simulating a correct GPS spoofing, I still have to complete a preliminary task, that is, to send a generic fake GPS position, even so bad that the drone can immediately understand that and throw failsafe.
The question is: how to edit and inject fake GPS position.

Currently, I’m able to preload a simple static mission that comprises of two point. The drone takes off at a certain home position logically placed at 0,0 (relative Cartesian coordinates) and the second point is at 0,100. On my Python code I have set a listener so that when the drone approaches 0,20, something has to happen.
But I’m not sure how to realize my thought.
I’m trying to edit the GPS_RAW_INT variable, with no success:

msg = vehicle.message_factory.gps_raw_int_encode(…)
vehicle.send_mavlink(msg)

I also tried to edit the GPS_INPUT variable, no way…:

msg = vehicle.message_factory.gps_input_encode(…)
vehicle.send_mavlink(msg)

On QGroundControl actually there is the possibility to watch few variables on the fly and one of them is GPS_RAW_INT. The problem is that when I’m injecting the supposedly new GPS_RAW_INT value, on the frontend I’m not able to see nothing.

Please give me hints.

I repeat, I’m not asking you “how to realize and bring back at home a perfect GPS spoofing”, but I’m simply asking “how to dynamically change the GPS information in such a way to throw a simple failsafe”?

Thanks so much for the moment…

Francesco :slight_smile:

Hello,

To do this on SITL you will have to path :

  • the easiest will be tonuse gps_input mavlink message. In order to use it, you need to change GPS_TYPE parameters to the right one
  • the second way will be to use a tcp port or serial to inject your fake gps data on the gps format you wanr (nmea, ublox, etc).

Hi, thanks for your answer.
I tried to figure out how to spoof GPS following your first hint but with not success…
This is the used code:

lat = 43  # fake latitude
lon = 12  # fake longitude
alt = 10

hdop = 0
vdop = 0

vn = 0
ve = 0
vd = 0

speed_accuracy = 0
horiz_accuracy = 0
vert_accuracy = 0

ignore_flags = (mavutil.mavlink.GPS_INPUT_IGNORE_FLAG_HDOP |
            mavutil.mavlink.GPS_INPUT_IGNORE_FLAG_VDOP |
            mavutil.mavlink.GPS_INPUT_IGNORE_FLAG_VEL_HORIZ |
            mavutil.mavlink.GPS_INPUT_IGNORE_FLAG_VEL_VERT |
            mavutil.mavlink.GPS_INPUT_IGNORE_FLAG_SPEED_ACCURACY |
            mavutil.mavlink.GPS_INPUT_IGNORE_FLAG_HORIZONTAL_ACCURACY |
            mavutil.mavlink.GPS_INPUT_IGNORE_FLAG_VERTICAL_ACCURACY)

time_usec = int(datetime.datetime.now().timestamp())
gps_id = 0

fix_type = 3  # 0-1: no fix, 2: 2D fix, 3: 3D fix. 4: 3D with DGPS. 5: 3D with RTK
satellites_visible = 6
epoch = 315964782
cur = datetime.datetime.utcnow()
ts = cur - datetime.datetime(1970, 1, 1)
epoch_sec = ts.total_seconds() - epoch
time_week = epoch_sec / 604800.0
time_week_ms = (epoch_sec % 604800) * 1000.0 + ts.microseconds * 0.001

msg = vehicle.message_factory.gps_input_encode(
    time_usec,
    gps_id,
    ignore_flags,
    int(time_week_ms),
    int(time_week),
    fix_type,
    int(lat * 1e7), int(lon * 1e7), alt,
    hdop, vdop,
    vn, ve, vd,
    speed_accuracy, horiz_accuracy, vert_accuracy,
    satellites_visible
)
vehicle.send_mavlink(msg)

The problem is that the drone doesn’t consider the new injected GPS at all.
Basically, it is just an AUTO mode mission starting from the home position to a destination point which is 100 meters northern than home, and nothing else.
Maybe, rather I would say “surely”, I’m doing something wrong with my code…