Open-source applications are open by nature, indented and encouraged for tweaking, hacking and further development. For a commercial, business critical, application or a device there often is a desire to make it closed and prevent modifications. Protecting against reverse engineering and tampering is important especially when the application or device processes valuable content, licenses, IPR or monetary transactions. Because of the dual licensing, Qt offers a commercial license option that is well suited for making closed applications and devices allowing many ways of protection. Everything can be hacked, but it is possible to make hacking your Qt based application or device difficult.
For the purposes of this blog post, I have divided the ways to protect your application into three categories: securing the application, external protection and legal aspects of protecting against hacking. I have blogged about this topic three years ago, but as the topic is still very relevant, I decided to re-visit it.
In this post, I concentrate on a few easily achievable and simple ways that everyone can do to make the reverse engineering of a Qt based application more difficult. If there are specific reverse engineering or tampering related risks in your system, for example related to processing licenses, valuable content or media, proprietary algorithms or financial transactions, then you may want to consider additional security controls for tamper resistance. Some of these more advanced anti-hacking techniques are discussed in the upcoming part 2 or this blog post series (planned for February).
Securing the application
A commercial Qt license makes it legal to prevent modifications and reverse engineering, therefore it is also possible to take actions to prevent these. Static linking is one of the easiest ways of protection as it prevents simple swapping the Qt binaries used by the application and thus makes reverse engineering harder. With static linking the application and Qt libraries are combined into a single binary. A possible hacker needs to take much more demanding and time-consuming ways to modify the behavior of the system compared to dynamically linked application.
When using static linking a good further measure to protect against reverse engineering is to strip symbol names away from the binary. Depending upon the compiler you use this is either automatically done for release builds, or can be done as an extra step for the statically linked binary. For example, MSVC automatically removes symbol names from a statically linked Windows release binary. On Linux and Mac this can be done with strip command. After the symbol table is removed from the statically linked binary, it is quite well protected against casual reverse engineering. These steps are easily done and do not require modifying your Qt application source code, thus static linking and removing the symbols can be regarded as the easiest way to make reverse engineering a lot harder.
If use of dynamic linking is needed, some protection against simply changing the dynamically linked Qt library to a new version can be gained via using libinfix to change the library names (e.g. change libQt5Core to stgElse). Another approach is to change the used namespace with configure option –qtnamespace. Namespacing Qt puts all classes inside a defined namespace resulting, for example, QString being called someNewName::QString. The protection gained by using these means to a dynamically linked library is much weaker than using static linking, and should not be used if it is possible the link statically.
It is also possible to use a generic C++ obfuscator for Qt applications. These programs can both make reverse engineering harder and provide tamper protection by preventing a modified binary from operating properly. Unlike static linking, obfuscation and tamper protection cause some overhead, requiring additional CPU cycles to run the application (typically the more the code is protected, the higher is the additional load). When considering the right level of obfuscation, it should be noted that no matter how much the code is obfuscated, it is still eventually possible to reverse engineer.
For Qt Quick applications it is beneficial to use Qt Quick Compiler if it is desired to protect the QML parts of the application. Or use QML caching, which offers similar protection (both are available with Qt 5.9 LTS). While the application logic, and thus typically the most critical parts to protect, is usually done with C++ and therefore always compiled to binary, it is a good further measure to also make it harder to reverse engineer the QML parts of the application. The Qt Quick Compiler compiles QML to binary and protects against reading the QML parts of the application. An additional benefit of the Qt Quick Compiler is improved performance of the application, especially at startup.
As the Qt application is just like any other binary running in your target operating system and hardware, you can use all generic means available for protection in your environment. Operating system may offer means to digitally sign the applications, as is typically the case with the applications distributed via application stores. There are also many different products available to provide security for application binary, and these typically work for Qt applications as well.
For embedded devices, the nature of the environment provides some protection, as it is often difficult to get access to and modify software embedded into a physical device. Securing the boot sequence and protecting the integrity of any software updates will make the work of an attacker harder. The most efficient protection is to have hardware containing functionality to prevent a modified binary from running (either in the device hardware, or an external one, such as a USB dongle). In some cases, it is also possible to leverage another system via a network connection to provide tamper protection. Optimally, the system should deploy multiple overlapping security controls according to the defense in depth design principle, starting from static linking and obfuscating the binary to make reverse engineering difficult.
Legal aspects of protection
Whereas the applications and devices using the open-source licensed Qt should be open for hacking and playing around, it is possible to prevent such when using a commercial license of Qt. One of the most important legal protection means provided by the commercial license of Qt is to forbid modifications and reverse engineering – and allowing the use of various technical countermeasures.
Commercial license of Qt makes it possible to forbid reverse engineering, which is very often desired in the end user license agreement of an application or device. However, for an application or a device created with the open-source licensed Qt it is not allowed to prevent reverse engineering or modifications, neither in the end user license agreement nor by making it difficult.
It should be noted that also leveraging external protection typically requires a commercial Qt license, similarly as the other means of preventing user from changing or modifying Qt libraries. In the LGPLv3 license it is clearly stated in the license that in addition to being allowed to modify the open-source library the user must be able to run the modified library as part of the system, and that the needed tools to achieve this must to be provided.
If there is a need to create a closed application or a device, the commercial license of Qt is the right choice. With the commercial license, it is possible to utilize various means for making it difficult to modify functionality of the application or device built with Qt:
- Making reverse engineering forbidden in end user license agreement and taking actions to prevent reverse engineering is allowed when Qt is used with a commercial license.
- An easy way to protect against modifications and reverse engineering is to use static linking instead of dynamic linking and build Qt into same binary with your application to prevent changing the Qt libraries.
- When using static linking it is important to use release builds and when needed to manually strip out the symbols before distributing the binary.
- If dynamic linking is needed, some protection against reverse engineering can be gained by building Qt with different names for libraries using libinfix and changing the used namespace. This mainly protects against user being easily able to change the dynamically linked Qt libraries – the protection against reverse engineering provided by static linking is much better.
- Using Qt Quick Compiler that compiles QML to binary and protects against reading the Qt Quick parts of the application is an efficient way of further protecting your application.
- If desired, use 3rd party obfuscators or tamper prevention to make reverse engineering even harder – most of those work well with Qt applications protecting the C++ parts of the binary.
- Leverage the capabilities of the hardware and the operating system to prevent modifications to system software.
- If your Qt based system works in a risk environment where anti-tampering is particularly important, then stay tuned for the second part of this blog post series (planned for February).
In case you want to learn more about the ways to protect your application or a device, feel free to contact us. We can help you to implement protection for your application both via technical and licensing means. If you need advice, our consultancy services will help you find the right approach for protecting your Qt application or device.