Decoding Dashcam GPS Data

Started by Neal Krawetz, May 20, 2024, 06:37:52 PM

Previous topic - Next topic

Neal Krawetz

A friend asked me if I could decode his dashcam GPS data.
It's an MP4 video with a "gps " atom.
The gps atom contains:
  Two digit version: 01 01 = 1.1
  4 byte number of records
  Then a set of 8 bytes per record: file offset for data and data size.

Each data record begins with "LIGOGPSINFO" and is followed by encoded bytes.
E.g.:
LIGOGPSINFO
####;
4FDF1/D9/E8 D=LGJL98 :L11.1=1JD8 ALEDD.GFDF=D FF.1? km/h xLD.E yL-D.D zLD.E
It looks like Phil tried to look at this encoding earlier and gave up. (https://exiftool.org/forum/index.php?topic=15387.0)

I think I've made progress on decoding it. But it's not perfect...
00068960   DA FB BA 8C  B1 66 FB B1  00 00 40 00  66 72 65 65  .....f....@.free
00068970   47 50 53 20  98 00 00 00  4C 49 47 4F  47 50 53 49  GPS ....LIGOGPSI
00068980   4E 46 4F 00  00 00 00 0D  0A 00 00 00  23 23 23 23  NFO.........####
00068990   3B 00 A0 34  46 44 46 31  2F 44 39 2F  45 38 20 44  ;..4FDF1/D9/E8 D
000689A0   3D 4C 47 4A  4C 39 38 20  3A 4C 31 31  2E 31 3D 31  =LGJL98 :L11.1=1
000689B0   4A 44 38 20  41 4C 45 44  44 2E 47 46  44 46 3D 44  JD8 ALEDD.GFDF=D
000689C0   20 46 46 2E  31 3F 20 6B  6D 2F 68 20  78 4C 44 2E   FF.1? km/h xLD.
000689D0   45 20 79 4C  2D 44 2E 44  20 7A 4C 44  2E 45 00 00  E yL-D.D zLD.E..
00004000 = block size
 "freeGPS " + 4 more bytes (unknown)
 "LIGOGPSINFO" + null
  00000d = length of header
    Header is the "####;" and ends and the "4".

Then comes the text string: "FDF1/D9/E8 D=LGJL98 :L11.1=1JD8 ALEDD.GFDF=D FF.1? km/h xLD.E yL-D.D zLD.E"
The "FDF1 is the giveaway. In the video, the dashboard time is "2024/05/19". This looks like a simple caesar cipher:
// vc is the character I want to print
        if (vc < ' ') { break; } // binary
        // substitution cipher!
        switch(vc)
          {
          case 'L': vc=':'; break;
          case '8': vc='9'; break;
          case '=': vc='8'; break;
          case 'J': vc='7'; break;
          case '?': vc='6'; break;
          case '9': vc='5'; break;
          case '1': vc='4'; break;
          case 'G': vc='3'; break;
          case 'F': vc='2'; break;
          case 'E': vc='1'; break;
          case 'D': vc='0'; break;
          case 'A': vc='-'; break;
          case ':': vc='+'; break;
          case '/': break;
          case '.': break;
          case '-': break;
          case ' ': break;
          default:  break;
          }
This decodes the string as "2024/05/19 08:37:59 +:44.484709 -:100.320280 22.46 km/h x:0.1 y:-0.0 z:0.1"
The date and time matches the video.

The weird things:
  • The GPS location appears to be off by +4,-6.5 (for my sample video, it should be around 40.48,-106.82; downtown Steamboat Springs, Colorado). The 4 degrees offset for latitude seems perfect, but the longitude is a fraction more; using -6.5 places it within 0.3 miles of the location.
  • The speed in the video says 25.8 mph. That should be 41.5 km/h, but the data encoded as 22.46 km/h. Either it's lying about encoding as km/h, or it's off by 19 km/h, or they changed the decoding.
I suspect that they are using hard-coded math offsets for obfuscation.

What I don't know:
  • Does the caesar cipher remain consistent with all videos, or is it per-video?
  • Are the math adjustments hard-coded or embedded in some of the bytes that I skipped as unknown?

Now for the really bad news: I can't share the video I'm looking at, and I don't have any others for comparison.

Does Phil have any examples he can check?

Phil Harvey

I've been collecting these videos with obfuscated coordinates and plan to have another whack at decoding these when I get a chance.  Thanks for the hint about the caesar cipher -- this will help.  Unfortunately I'm pretty busy now so it could be a while before I can work on this.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).