Cracking the Davinci Resolve Studio 18.5 and 19.0 license check by patching a single bit

Published:
Last edit:

NOTE: This blog was written for 18.5, but it also applies for 18.6 and 19 with some minor changes. See patches for patch scripts.

So I was trying out Davinci Resolve on Linux, and no matter how hard I tried to make it work, it wouldn’t display my OBS recorded videos.

After some searching, I found out that the DNxHD codec worked, but it requires about 2 GB/min of storage, so it wouldn’t work for me.

After some more searching, I found this Reddit post and this Davinci Resolve document. Turns out H264 and H265 don’t work specifically on Linux and specifically on the free version, AAC doesn’t work on Linux at all, and all of this is due to some licensing bullshit. I was pissed.

I tried to find a Linux crack, but the best that I’ve found was for 18.1 or something, so I decided to try and crack it myself.

Note that I’m using Arch Linux and the davinci-resolve-studio AUR package, but this should work for any Linux distro, and even Windows/macOS.

Searching for the offending file

After launching Davinci Resolve Studio, I’m presented with a license activation window. Trying out a random key doesn’t work, but it gives us a couple of strings and tells us that it probably uses a server to verify the key.

Activating license The key entered does not appear to be valid

Let’s try searching for them

$ grep -R 'Activating license' /opt/resolve
grep: /opt/resolve/libs/Fusion/libfusionsystem.so: binary file matches
grep: /opt/resolve/bin/BlackmagicRawAPI: No such file or directory
grep: /opt/resolve/bin/resolve: binary file matches
$ grep -R 'The key entered does not appear to be valid' /opt/resolve
grep: /opt/resolve/libs/Fusion/libfusionsystem.so: binary file matches
grep: /opt/resolve/bin/BlackmagicRawAPI: No such file or directory
grep: /opt/resolve/bin/resolve: binary file matches

It looks like either libfusionsystem.so or resolve handle license checking. I’ll start with resolve since it’s our entry binary.

Disassembling with Ghidra

I gave Ghidra this rather large (510 MiB) file for analysis and waited for a few hours…

And waited a few more hours…

Eventually, I gave up and stopped the analysis. It seems to have disassembled the functions, and I didn’t have the patience to wait an entire day for it to complete.

Search -> For Strings..., press Search, filter for The key entered does not appear to be valid

Go to definition, change type to TerminatedCString, go to XREF, open decompile

After going through a few DAT_xxxxxxxx labels and changing their types to string, the function started to look a lot like a failure callback. I named it appropriately

Activation failed callback

The function had this string later on: Unable to connect to the server. Please check your internet connection.
This confirms that a server is used for key verification

After going through this function’s XREFs in a similar way, one function caught my eye

Activation callback

It calls our failure callback in one branch and has strings like Start DaVinci Resolve and Has been successfully activated. %1 in the other.

Patching

I decided to try and patch param_2 != 0 to param_2 == 0 to see what happens.

I went into assembly view, found this jump instruction, pressed right click, Patch Instruction, and changed JZ (jump if zero) to JNZ (jump if not zero)

Ghidra before patch Ghidra after patch

After that, I tried to export the patched binary with Ghidra, but the resulting binary was too different. So I decided to change the instruction with a hex editor.

ImHex patching

Don’t forget to subtract Ghidra’s base address from the instruction address!

Running

After saving changes from the hex editor and trying an invalid key again, to my surprise, the patch worked!

Has been successfully activated

The program launched without issues, and I was able to use my H264 videos.

The AAC codec still doesn’t work, but this is a lot better than before.

Conclusions

This patch isn’t perfect because Davinci requires the key on each launch, but it is very easy. There is probably a way to hack this with mitmproxy or something similar, but I didn’t look into it.

I haven’t looked into libfusionsystem.so at all, but everything seems to work okay. I’ll probably update this blog post if I notice something fishy.

Also, if your screen is too small, you can use hax11 to remove the minimum size requirements. This will slightly break the UI, but it will make the program a lot more usable.

Please message me on Steam if you found this useful :)

Patches

Here are small patch scripts using pattern searching and their patterns if you don’t want to bother with reverse engineering.

Linux

Versions ??? - 18.6.6+

patch-resolve18.sh
55 41 56 53 48 83 EC 20 49 89 FE 85 F6 0F 84 ?? ?? ?? ?? 81 FE 13 FC FF FF 0F 85
offset 14 (0x0E) bytes, patch with 0x85

Versions 19.0b1 - 19.0b3

Update 2024-05-19: version 19.0b1 has changed some license related functions, so it needed a new pattern.
I also get some undefined symbol issues, so now I have to launch resolve like this: LD_PRELOAD="/usr/lib/libgio-2.0.so /usr/lib/libgmodule-2.0.so /usr/lib/libglib-2.0.so /usr/lib/libc++abi.so.1.0" /opt/resolve/bin/resolve

patch-resolve19.sh
55 41 57 41 56 53 48 83 EC ?? 49 89 FE 85 F6 0F 84 ?? ?? ?? ?? 89 F5 81 FE 13 FC FF FF 0F 85
offset 16 (0x10) bytes, patch with 0x85

Versions 19.0b4 - 19.1.1+

Update 2024-07-07: version 19.0b4 changed the pattern again.
Update 2025-01-16: added NixOS package.

patch-resolve19b4.sh

NixOS / nixpkgs package by dasha.rip
  • Download davinci-resolve-paid.nix
  • To install system-wide:
    1. Put the .nix file in /etc/nixos
    2. Add the .nix file to environment.systemPackages (By default in /etc/nixos/configuration.nix):
      environment.systemPackages = [
        (pkgs.callPackage ./davinci-resolve-paid.nix  {})
      ];
      
  • To install as a shell:
    1. Put the .nix file anywhere.
    2. In the same folder as the .nix file create shell.nix file with the following contents:
      {
        pkgs ? (import <nixpkgs> { }),
      }:
      pkgs.mkShellNoCC {
        packages = [
          (pkgs.callPackage ./davinci-resolve-paid.nix  {})
        ];
      }
      
    3. Launch the shell with nix-shell .

55 41 57 41 56 53 48 83 EC ?? 49 89 FE C7 47 34 FF FF FF FF 85 F6 0F 84 ?? ?? ?? ?? 89 F5 81 FE 13 FC FF FF 0F 85
offset 23 (0x17) bytes, patch with 0x85

Windows x86

Update 2024-12-05: added patch scripts for windows resolve 18 and 19 release.

NOTE: Windows patch scripts need ~7GB of ram to patch due to powershell annoyances. You may also need to edit the Resolve.exe path in the script.

Versions ??? - 18.6.6+

Patch script Improved patch script by dmcx.dev
85 D2 74 ?? 48 8B 59 10 41 B8 01 00 00 00
offset 2 (0x02) bytes, patch with 0x75

Versions 19.0b4? - 19.1.1+

Patch script Improved patch script by dmcx.dev
E9 ?? ?? ?? ?? 85 F6 0F 84 ?? ?? ?? ?? 48 8B 59 10
offset 8 (0x08) bytes, patch with 0x85

Windows ARM64/AArch64

Update 2025-01-16: added patterns for windows ARM64/AArch64

Versions 19.0b4? - 19.1.2+ (untested)

Patch script Improved patch script by dmcx.dev
?? ?? ?? 34 22 00 80 52 74 0A 40 F9
or ?? ?? ?? 34 ?? 00 80 52 ?? ?? ?? f9 ?? 03 ?? 2a ?? ?? 00 91
offset 3 (0x03) bytes, patch with 0x35

macOS ARM64/AArch64

Update 2024-12-05: added patterns for ARM64/AArch64 resolve 18 and 19 that i had laying around since half a year ago. not sure about their corectness.

NOTE: You need to remove or disable code signatures to launch patched binaries. codesign -fs - DaVinci\ Resolve.app

To find the needed function: 3f b4 0f 31 ?1 ?? 00 54

Versions ??? - 18.6+ ?

E1 04 00 34 3F B4 0F 31
offset 3 (0x03) bytes, patch with 0x35

Versions 19.0b1 - 19.0b3 ?

01 05 00 34 F4 03 01 AA 3F B4 0F 31
offset 3 (0x03) bytes, patch with 0x35

Versions 19.0b4 - 19.1.1+

¯\_(ツ)_/¯
Send me a pattern, a patch script, a binary, or tell me that the 19.0b1 pattern works

ImHex pattern search