简体中文 / [English]


A Method for Official unRAID to Stay Happy Without Modifications or Keymaker

 

This article is currently an experimental machine translation and may contain errors. If anything is unclear, please refer to the original Chinese version. I am continuously working to improve the translation.

Recently, I wanted to switch from a hackintosh Synology on ESXi to unRAID. However, the official unRAID license is quite expensive, and I’m hesitant to use shady cracked versions.

I found an open-source cracking method, reposted from https://www.dosk.win/2022/03/11/unraid-guan-bu-xiu-gai-bu-yong-keymaker-ke-chi-xu-happy-de-fang-fa/

Personally tested and confirmed working on the latest unRAID 6.10.0 stable release. Actually, you can just compile the code using Ubuntu—no need for Slackware at all.

Preface

  1. The discussion in this article is strictly for technical exchange purposes. If you need it, please buy the official version !!!
  2. The discussion in this article is strictly for technical exchange purposes. If you need it, please buy the official version !!
  3. The discussion in this article is strictly for technical exchange purposes. If you need it, please buy the official version !
  4. Do NOT redistribute binaries!!!

Principle

  1. emhttpd uses RSA_public_decrypt to parse the BTRS.key file, which contains your registration information.
  2. The parsed data is then written into var/state.ini, making it accessible to other components.

Approach

  1. Use LD_PRELOAD to hook the RSA_public_decrypt function and replace its behavior with custom logic.

Usage

Note: I compiled this on Slackware to avoid potential issues caused by different compilation environments.

  1. Compile the source code: gcc -fPIC -shared crack.c -o BTRS.key. Why name it BTRS.key? Well, that file is useless anyway—might as well reuse the name and reduce clutter. (P.S. If you choose another name, make sure the original BTRS.key file still exists and is large enough. So it’s better to just name the compiled output BTRS.key.)
  2. Place the compiled BTRS.key file into /boot/config/BTRS.key.
  3. Modify the startup script /boot/config/go, replacing
1
/usr/local/sbin/emhttp &

with

1
2
3
4
5
export UNRAID_GUID=your_USB_drive_GUID
export UNRAID_NAME=your_name
export UNRAID_DATE=a_UNIX_timestamp
export UNRAID_VERSION=desired_edition_like_Pro
LD_PRELOAD=/boot/config/BTRS.key /usr/local/sbin/emhttp &

Result

This code was written when version 6.9.2 was current. I casually tested it on 6.10.0-rc3 and it worked fine too—here’s a screenshot:

imgimg

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#define _GNU_SOURCE
#include <stdio.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/uio.h>
#include <netinet/in.h>

#define RSA void
// Format string for fake registration data
#define BTRS_FORMAT "regGUID=%s&regTy=%s&regTo=\"%s\"&regTm=%s&regGen=0&regDays=0"

typedef int (*RSA_PUBLIC_DECRYPT_FUNC)(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding);
RSA_PUBLIC_DECRYPT_FUNC rsa_public_decrypt;

// Get the name (or full path) of the current executable
const char* get_self_exe_name(int full) {
static char buffer[4096] = "";
readlink("/proc/self/exe", buffer, 4096);
if (full) {
return buffer;
}
char* ptr = &buffer[strlen(buffer)];
while (*ptr != '/') --ptr;
return (ptr + 1);
}

// Hook for RSA_public_decrypt
int RSA_public_decrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding) {
if (!rsa_public_decrypt) {
// Resolve the real function from the library
rsa_public_decrypt = (RSA_PUBLIC_DECRYPT_FUNC)dlsym(RTLD_NEXT, "RSA_public_decrypt");
}
// Only intercept calls from emhttpd or shfs
if (!strcmp(get_self_exe_name(0), "emhttpd") || !strcmp(get_self_exe_name(0), "shfs")) {
// Fake the decrypted registration data using environment variables
sprintf(to, BTRS_FORMAT, getenv("UNRAID_GUID"), getenv("UNRAID_VERSION"), getenv("UNRAID_NAME"), getenv("UNRAID_DATE"));
int len = strlen(to);
return len;
} else {
// For other processes, use the original function
return rsa_public_decrypt(flen, from, to, rsa, padding);
}
}

This article is licensed under the CC BY-NC-SA 4.0 license.

Author: lyc8503, Article link: https://blog.lyc8503.net/en/post/unraid-crack/
If this article was helpful or interesting to you, consider buy me a coffee¬_¬
Feel free to comment in English below o/