Skip to content

Commit a0cf5ce

Browse files
authored
add offline license checking
1 parent 4b851f6 commit a0cf5ce

25 files changed

Lines changed: 1015 additions & 259 deletions

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Changelog - UltimateDRM
2+
- Aug 30 2025: Added offline license generation & checking (.jwt b64 encoded file), use openssl to generate a keypair + use scripts found in `License` folder
23
- Aug 11 2025: Improved anti-debugger class, added inheritance with 'violations' struct, general improvements
34
- Aug 7 2025: Added DRM violation lists, bug fixes and more testing
45
- Aug 6 2025: Added IAT hook checks for all loaded modules

License/dump_xy.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# dump_xy.py
2+
from cryptography.hazmat.primitives import serialization
3+
from cryptography.hazmat.primitives.asymmetric import ec
4+
import binascii, sys
5+
pub = serialization.load_pem_public_key(open("vendor_pub.pem","rb").read())
6+
nums = pub.public_numbers()
7+
print("X=", binascii.hexlify(nums.x.to_bytes(32,'big')).decode())
8+
print("Y=", binascii.hexlify(nums.y.to_bytes(32,'big')).decode())

License/license.jwt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
eyJhbGciOiJFUzI1NiIsImtpZCI6InYxIiwidHlwIjoiSldUIn0.eyJleHAiOjE3ODcyNzI2NDIsImZlYXR1cmVzIjpbInJ1bGVzLXNpZ25pbmciLCJncHUtZ2F0ZSIsIndlYmhvb2siXSwiaWF0IjoxNzU1NzM2NjQyLCJpc3MiOiJMaWdodGhvdXNlIiwianRpIjoiLTk5VEp3QlNXZ3FWcE5mcSIsIm9yZyI6IkNpdHkgTGlicmFyeSIsInBsYW4iOiJlZHUtZmxvYXRpbmciLCJwcm9kdWN0IjoibGlnaHRob3VzZS9hZ2VudCIsInNlYXRzIjoyNTB9.MEQCIA6jkQKQXS3gGgNd056yrwNY5KDrPBeCx3AA7MJQowpBAiBioM_rxu-Jcc6u1xQxTfN7JM9n-gld1wtK3Lxpd91s2w

License/sign.bat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
python sign_license.py --priv vendor_priv.pem --org "Your Program" --plan floating --seats 250 --days 365 > license.jwt

License/sign_license.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/usr/bin/env python3
2+
import json, argparse, base64, os, datetime as dt, hashlib
3+
from cryptography.hazmat.primitives import hashes, serialization
4+
from cryptography.hazmat.primitives.asymmetric import ec, utils
5+
6+
def b64url(data: bytes) -> str:
7+
return base64.urlsafe_b64encode(data).rstrip(b"=").decode("ascii")
8+
9+
def b64url_json(obj) -> str:
10+
return b64url(json.dumps(obj, separators=(",", ":"), sort_keys=True).encode("utf-8"))
11+
12+
def load_key(path):
13+
with open(path, "rb") as f:
14+
return serialization.load_pem_private_key(f.read(), password=None)
15+
16+
def main():
17+
ap = argparse.ArgumentParser(description="UltimateDRM license signer (ES256)")
18+
ap.add_argument("--priv", required=True, help="EC P-256 private key PEM (vendor)")
19+
ap.add_argument("--org", required=True)
20+
ap.add_argument("--plan", required=True, choices=["edu-floating","named-device","site"])
21+
ap.add_argument("--seats", type=int, default=None, help="None for site")
22+
ap.add_argument("--days", type=int, default=365, help="Validity days")
23+
ap.add_argument("--features", nargs="*", default=["rules-signing","gpu-gate","webhook"])
24+
ap.add_argument("--key-id", default="v1")
25+
args = ap.parse_args()
26+
27+
now = dt.datetime.utcnow()
28+
exp = now + dt.timedelta(days=args.days)
29+
30+
header = {"alg":"ES256","kid":args.key_id,"typ":"JWT"}
31+
payload = {
32+
"iss":"UltimateDRM",
33+
"product":"UltimateDRM/agent",
34+
"org":args.org,
35+
"plan":args.plan,
36+
"seats":args.seats,
37+
"features":args.features,
38+
"iat":int(now.timestamp()),
39+
"exp":int(exp.timestamp()),
40+
"jti": b64url(os.urandom(12)),
41+
}
42+
43+
signing_input = (b64url_json(header) + "." + b64url_json(payload)).encode("ascii")
44+
45+
key = load_key(args.priv)
46+
h = hashlib.sha256(signing_input).digest()
47+
sig = key.sign(h, ec.ECDSA(utils.Prehashed(hashes.SHA256())))
48+
token = signing_input.decode("ascii") + "." + b64url(sig)
49+
50+
print(token)
51+
52+
if __name__ == "__main__":
53+
main()

License/vendor_priv.pem

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-----BEGIN EC PRIVATE KEY-----
2+
MHcCAQEEIHGuWvP4018Ly30PuzrVJS06lz4RThoX2mpxqSYCJDh6oAoGCCqGSM49
3+
AwEHoUQDQgAEDooxHpONxRSOt5yxcNnKNTpEm7nhZaDD+8a4cyvYzcj+JPWE6w4g
4+
OdNmvnYUPNvAwZfKloNVmQ/BGFsdfZRIZw==
5+
-----END EC PRIVATE KEY-----

License/vendor_pub.pem

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-----BEGIN PUBLIC KEY-----
2+
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDooxHpONxRSOt5yxcNnKNTpEm7nh
3+
ZaDD+8a4cyvYzcj+JPWE6w4gOdNmvnYUPNvAwZfKloNVmQ/BGFsdfZRIZw==
4+
-----END PUBLIC KEY-----

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77

88
DRM Library for Windows (x64) in C++
99

10-
This project aims to take the good portions of the UltimateAnticheat project while improving aspects which were messy or implemented poorly, such as the integrity checker. An emphasis will be made on code readability, modularity, and reusability for the core aspects of this DRM. Anyone is free to contribute as long as PRs are quality and follow the same code style. The project is currently being supported for Visual Studio 17 (2022), CMake support will be added in the future.
10+
This project is an anti-tamper & anti-debugging static library for Windows. It uses the PIMPL idiom to hide implementation details so that it can be added into other projects without revealing methods. It's currently in a working state, with licensing mostly finished (just needs online checking to be added, offline checks are working). All protections/checks are runtime, and perhaps in the future we will add post-build packing /w a unpacking launcher.
11+
12+
Anyone is free to contribute as long as PRs are quality and follow the same code style. The project is currently being supported for Visual Studio 17 (2022), CMake support will be added in the future.
1113

1214
** This project was started on July 19, 2025, and might not have many files yet
1315
** There is no such thing as an 'uncrackable DRM' - any code or binaries run on a client machine can be tampered with enough effort
@@ -16,18 +18,18 @@ This project aims to take the good portions of the UltimateAnticheat project whi
1618
- Settings class which controls which types of DRM checks to occur, and resides in protected memory
1719
- Memory protections/anti-tamper
1820
- IAT hook checks on all loaded modules
19-
- Licensing (not yet finished)
21+
- Licensing (offline license checking currently working)
2022
- Periodic Integrity checks on all non-writable sections of all loaded modules
2123
- Blocks multiple client instances
2224
- Checks for and blocks threads spawning on addresses outside of any loaded module (<Windows 10 only)
2325
- Checks the parent process against a whitelist
2426
- Optionally enforces code signing via Authenticode APIs
2527
- Anti-debugging checks and hiding threads from debuggers
26-
- Extremely low CPU & RAM usage (less than 0.1% CPU)
28+
- Very low CPU & RAM usage
2729
- Supports both x86 and x64
2830

2931
## How to use:
30-
The project is a static library (.lib) which you can include in your C++ project, along with the `DRM.hpp` header file. You can then create a `DRM` class object and call the `Protect` function. Please see `DRMTest/DRMTest.cpp` for an example of how to implement this into your own project.
32+
The project is a static library (.lib) which you can include in your C++ project, along with the `UltimateDRM.hpp` header file. You can then create a `UltimateDRM` class object and call the `Protect` function. Please see `DRMTest/DRMTest.cpp` for an example of how to implement this into your own project.
3133

3234
## Testing
3335
The `DRMTest` folder contains a project which links to `UltimateDRM.lib` and tests different features of it. A failed test returns non-zero from its `main` function, while a successful test returns 0.

UltimateDRM.vcxproj

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
<ClInclude Include="include\curl\urlapi.h" />
4949
<ClInclude Include="include\curl\websockets.h" />
5050
<ClInclude Include="include\Definitions.hpp" />
51+
<ClInclude Include="include\EventLog.hpp" />
52+
<ClInclude Include="include\License.hpp" />
5153
<ClInclude Include="include\UltimateDRM.hpp" />
5254
<ClInclude Include="include\DRMException.hpp" />
5355
<ClInclude Include="include\HttpClient.hpp" />
@@ -61,7 +63,7 @@
6163
<ClInclude Include="include\Process.hpp" />
6264
<ClInclude Include="include\remap.hpp" />
6365
<ClInclude Include="include\Services.hpp" />
64-
<ClInclude Include="include\Settings.hpp" />
66+
<ClInclude Include="include\DRMSettings.hpp" />
6567
<ClInclude Include="include\Thread.hpp" />
6668
<ClInclude Include="include\Utility.hpp" />
6769
<ClInclude Include="include\XorStr.hpp" />
@@ -214,7 +216,7 @@
214216
<GenerateDebugInformation>true</GenerateDebugInformation>
215217
</Link>
216218
<Lib>
217-
<AdditionalDependencies>ntdll.lib;wintrust.lib;crypt32.lib;ws2_32.lib;lib/zlib.lib;lib/libcurl.lib;lib/brotlicommon.lib;lib/brotlidec.lib;lib/brotlienc.lib</AdditionalDependencies>
219+
<AdditionalDependencies>ntdll.lib;wintrust.lib;crypt32.lib;lib/zlib.lib;lib/libcurl.lib;lib/brotlicommon.lib;lib/brotlidec.lib;lib/brotlienc.lib</AdditionalDependencies>
218220
</Lib>
219221
</ItemDefinitionGroup>
220222
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

UltimateDRM.vcxproj.filters

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
</ClCompile>
6767
</ItemGroup>
6868
<ItemGroup>
69-
<ClInclude Include="include\Settings.hpp">
69+
<ClInclude Include="include\DRMSettings.hpp">
7070
<Filter>include</Filter>
7171
</ClInclude>
7272
<ClInclude Include="include\Logger.hpp">
@@ -162,6 +162,12 @@
162162
<ClInclude Include="include\AntiDebug\DebuggerDetections.hpp">
163163
<Filter>include\AntiDebug</Filter>
164164
</ClInclude>
165+
<ClInclude Include="include\EventLog.hpp">
166+
<Filter>include</Filter>
167+
</ClInclude>
168+
<ClInclude Include="include\License.hpp">
169+
<Filter>include</Filter>
170+
</ClInclude>
165171
</ItemGroup>
166172
<ItemGroup>
167173
<Library Include="lib\brotlicommon.lib">

0 commit comments

Comments
 (0)