code:
# Navicat Keygen - for Linux

[中文版README](README_FOR_LINUX.zh-CN.md)

## How to use?

> You can download [Screen recoding](image/Screen_recording.mp4) for references.

1. Switch to the path you extracted the installation package ，Run Navicat, for initialization:

    ```bash
    cd ~/navicat121_premium_en_x64 && \
    ./start_navicat
    ```

    When running for the first time, you will be prompted with the following two windows, click "Cancel" to:

    ![](image/Screenshot_2019-04-30_12-31-33.png)

    ![](image/Screenshot_2019-04-30_12-31-52.png)

    Until the `Registration` window appears, select `Trial`, close Navicat after loading is complete, and execute `Step 2`:

    ![](image/Screenshot_2019-04-30_12-32-43.png)

2. Download the latest release [from here](https://github.com/DoubleLabyrinth/navicat-keygen/releases), and extract ：

    > The 64-bit executable file is downloaded here. If you use 32-bit, please download the corresponding version.

    ```bash
    curl -O -L https://github.com/DoubleLabyrinth/navicat-keygen/releases/download/v3.1/navicat-keygen-for-x64.zip && \
    unzip navicat-keygen-for-x64.zip
    ```

3. Download `navicat-pacther.sh` and `navicat-keygen.sh`:

    ```bash
    curl -O -L https://raw.githubusercontent.com/DoubleLabyrinth/navicat-keygen/windows/bash/navicat-patcher.sh && \
    chmod +x navicat-patcher.sh && \
    curl -O -L https://raw.githubusercontent.com/DoubleLabyrinth/navicat-keygen/windows/bash/navicat-keygen.sh && \
    chmod +x navicat-keygen.sh
    ```

4. Use `navicat-patcher.exe` to replace __Navicat Activation Public Key__ that is stored in `navicat.exe` or `libcc.dll`.

   > Please turn off `Navicat` when performing this step.

   ```bash
   ./navicat-patcher.sh
   ```

   It has been tested on __Navicat Premium 12.1.12 Simplified Chinese version__. The following is an example of output.

   ```
   ***************************************************
   *       Navicat Patcher by @DoubleLabyrinth       *
   *           Release date: Jan 19 2019             *
   ***************************************************

   Press Enter to continue or Ctrl + C to abort.

   MESSAGE: PatchSolution0 will be omitted.

   MESSAGE: PatchSolution3: Keywords[0] has been found:
            Relative Machine Code Offset = +0x0000000001644a08
            Relative Machine Code RVA    = +0x0000000001645608
            Patch Offset                 = +0x00000000023d56e4
            Patch Size                   = 3 byte(s)
   ...
   ...
   ...
   MESSAGE: PatchSolution3: Keywords[110] has been found:
            Relative Machine Code Offset = +0x000000000165155e
            Relative Machine Code RVA    = +0x000000000165215e
            Patch Offset                 = +0x0000000001651561
            Patch Size                   = 1 byte(s)

   MESSAGE: PatchSolution2 will be omitted.

   MESSAGE: PatchSolution1: Keywords[0] has been found: offset = +0x021f7390.
   MESSAGE: PatchSolution1: Keywords[1] has been found: offset = +0x0074bd39.
   MESSAGE: PatchSolution1: Keywords[2] has been found: offset = +0x021f70a0.
   MESSAGE: PatchSolution1: Keywords[3] has been found: offset = +0x0074bd1f.
   MESSAGE: PatchSolution1: Keywords[4] has been found: offset = +0x021f708c.

   MESSAGE: Generating new RSA private key, it may take a long time.
   MESSAGE: New RSA private key has been saved to RegPrivateKey.pem.

   Your RSA public key:
   -----BEGIN PUBLIC KEY-----
   MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsWnV5hQxlXvDA3Ad4k5N
   ZLz4cO+iGEPegSovIDcwTo097I+0pXYKPTVl+0iKC5JtJRObb4Xx9yK9gGwqkcxo
   o6WzKq0xY1jz7X6obxwlQCNse3Os1wr0rIY0UzP1dCpkW/5MwGbFxiB6PEVqkzmJ
   CmHBzZDRu/jAuL1nyoiGnUStqwENNYhyl4k7r8AiJkBZGMOCrj6v0JfgNna25Ce6
   QCFojlY4dkYQ5/7njQ3qpLwMeLEXEysMW3aUScSB68/vsHnB4C0fIkwfEPYZ/AC5
   AqbWHVbNmveB3rjV+tZZxXcLE8ArgKh1Gs+2VtnL09gwHm6WcpyPZ42G6tMDjWyw
   1wIDAQAB
   -----END PUBLIC KEY-----

   ******************************************
   *            PatchSulution3              *
   ******************************************
   @ +023d56e4: 4D 49 49 ---> 4D 49 49
   @ +01644a63: 42 49 ---> 42 49
   @ +01644a68: 6A ---> 6A
   @ +01644ace: 41 ---> 41
   ...
   ...
   ...
   @ +023d58d4: 36 63 6A ---> 47 36 74
   @ +023d58d8: 78 6C 6A 75 75 51 61 ---> 4D 44 6A 57 79 77 31
   @ +023d58e8: 77 49 44 41 ---> 77 49 44 41
   @ +0165155c: 51 41 ---> 51 41
   @ +01651561: 42 ---> 42

   ******************************************
   *            PatchSulution1              *
   ******************************************
   @ +0x021f7390
   Previous:
   +0x00000000021F7390  44 37 35 31 32 35 42 37 30 37 36 37 42 39 34 31  D75125B70767B941
   +0x00000000021F73A0  34 35 42 34 37 43 31 43 42 33 43 30 37 35 35 45  45B47C1CB3C0755E
   +0x00000000021F73B0  37 43 43 42 38 38 32 35 43 35 44 43 45 30 43 35  7CCB8825C5DCE0C5
   ...
   ...
   ...

   @ +0x021f708c
   Previous:
   +0x00000000021F7080  31 32 32 35 4f 45 29 2e 00 00 00 00 39 32 39 33  1225OE).....9293
   +0x00000000021F7090  33 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  3...............
   After:
   +0x00000000021F7080  31 32 32 35 4f 45 29 2e 00 00 00 00 32 37 45 38  1225OE).....27E8
   +0x00000000021F7090  45 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  E...............

   MESSAGE: Patch has been done successfully.
   ```

5. Then use `navicat-keygen.exe` to generate __snKey__ and __Activation Code__

   ```
   ./navicat-keygen.sh
   ```

   You will be asked to select Navicat product, language and input major version number. After that an randomly generated __snKey__ will be given.

   ```
   Select Navicat product:
   0. DataModeler
   1. Premium
   2. MySQL
   3. PostgreSQL
   4. Oracle
   5. SQLServer
   6. SQLite
   7. MariaDB
   8. MongoDB
   9. ReportViewer

   (Input index)> 1

   Select product language:
   0. English
   1. Simplified Chinese
   2. Traditional Chinese
   3. Japanese
   4. Polish
   5. Spanish
   6. French
   7. German
   8. Korean
   9. Russian
   10. Portuguese

   (Input index)> 1

   (Input major version number, range: 0 ~ 15, default: 12)> 12

   Serial number:
   NAVO-2ORP-IN5A-GQEE

   Your name:
   ```

   You can use this __snKey__ to activate your Navicat preliminarily.

   Then you will be asked to input `Your name` and `Your organization`. Just set them whatever you want, but not too long.

   ```
   Your name: DoubleLabyrinth
   Your organization: DoubleLabyrinth
   Input request code (in Base64), input empty line to end:
   ```

   After that, you will be asked to input the request code. Now __DO NOT CLOSE KEYGEN__.

6. __Set up__ a invalid proxy. Find and click `Registration`. Fill `Registration Key` by __snKey__ that the keygen gave and click `Activate`.

7. Online activation will failed and Navicat will ask you do `Manual Activation`, just choose it.

8. Copy your request code and paste it in the keygen. Input empty line to tell the keygen that your input ends.

   ```
   Your name: DoubleLabyrinth
   Your organization: DoubleLabyrinth

   Input request code (in Base64), input empty line to end:
   t2U+0yfE2FfnbjyhCXa0lglZOHu9Ntc3qyGiPbR6xb1QoU63/9BVfdaCq0blwVycXPyT/Vqw5joIKdM5oCRR/afCPM7iRcyhQMAnvqwc+AOKCqayVV+SqKLvtR/AbREI12w++PQ6Ewfs4A8PgB8OJ9G0jKt6Q/iJRblqi2WWw9mwy+YHcYYh3UAfygTnyj/xl+MzRymbY0lkus+6LPtpDecVsFFhM7F32Ee1QPwISko7bAkHOtkt+joPfYDdn9PDGZ4HEmeLvH6UqZCXkzgaAfynB7cQZFEkId8FsW2NGkbpM7wB2Hi3fNFgOIjutTprixTdbpFKn4w6gGc28ve23A==

   Request Info:
   {"K":"NAVO2ORPIN5AGQEE", "DI":"R91j6WyMhxHznAKSxxxx", "P":"WIN"}

   Response Info:
   {"K":"NAVO2ORPIN5AGQEE","DI":"R91j6WyMhxHznAKSxxxx","N":"DoubleLabyrinth","O":"DoubleLabyrinth","T":1547826060}

   License:
   lRF18o+ZhBphyN0U5kFLHtAAGGXuvhqOcxNuvAk4dJcGeR0ISuw74mQvAfdNjv0T
   I5NZFzqIJvrzM0XeR88q+3kmZkECuxwwWHP3zzDPhPiylcTV4DoGZ1tfoViUSYQc
   LgXG0Fl7koZeP61YOKQ8GfX+Xk2ZTM64bYaF7NlhonM+GQUJCCF2JThmrP921t2p
   b/E5pV6fLOYMM13881ZQcQcltMNVDZn4lzgzKRFFxCQFaTl6fJMHZdYVmICQTHtI
   sNaym0zduc8/cv34mgJ+7NseXmsEPCdjrZ59wgfPsLhZLXqtfxi5hGWw4NMa3Sb2
   UI8dzqFzRp/hSDEM0mEqiA==
   ```

7. Finally, you will get __Activation Code__ which looks like a Base64 string. Just copy it and paste it in Navicat `Manual Activation` window, then click `Activate`. If nothing wrong, activation should be done successfully. Don't forget to close the proxy that we just set up.


code:
# Navicat Keygen - for Linux

## 如何使用这个注册机

> 可下载[录屏文件](image/Screen_recording.mp4)参考

1. 切换到解压安装包的路径，本示例解压到了`家目录`，运行Navicat，使其初始化环境：

    ```bash
    cd ~/navicat121_premium_en_x64 && \
    ./start_navicat
    ```

    首次启动时，会提示如下两个窗口，点击“Cancel”即可：

    ![](image/Screenshot_2019-04-30_12-31-33.png)

    ![](image/Screenshot_2019-04-30_12-31-52.png)

    直至出现`Registration`窗口，选择`Trial`，待加载完成后关闭Navicat，执行`步骤2`:

    ![](image/Screenshot_2019-04-30_12-32-43.png)

2. [从这里](https://github.com/DoubleLabyrinth/navicat-keygen/releases)下载最新的release，并且解压：

    > 此处下载的是64位的可执行文件，若您使用32位，请下载对应版本

    ```bash
    curl -O -L https://github.com/DoubleLabyrinth/navicat-keygen/releases/download/v3.1/navicat-keygen-for-x64.zip && \
    unzip navicat-keygen-for-x64.zip
    ```

3. 下载`navicat-pacther.sh`和`navicat-keygen.sh`：

    ```bash
    curl -O -L https://raw.githubusercontent.com/DoubleLabyrinth/navicat-keygen/windows/bash/navicat-patcher.sh && \
    chmod +x navicat-patcher.sh && \
    curl -O -L https://raw.githubusercontent.com/DoubleLabyrinth/navicat-keygen/windows/bash/navicat-keygen.sh && \
    chmod +x navicat-keygen.sh
    ```

4. 使用`navicat-patcher.exe`替换掉`navicat.exe`和`libcc.dll`里的Navicat激活公钥。

   > 执行此步骤时，请将`Navicat`关闭

   ```bash
   ./navicat-patcher.sh
   ```

   __Navicat Premium 12.1.12 简体中文版已通过测试__。下面将是一份样例输出。

   ```
   ***************************************************
   *       Navicat Patcher by @DoubleLabyrinth       *
   *           Release date: Jan 19 2019             *
   ***************************************************

   Press Enter to continue or Ctrl + C to abort.

   MESSAGE: PatchSolution0 will be omitted.

   MESSAGE: PatchSolution3: Keywords[0] has been found:
            Relative Machine Code Offset = +0x0000000001644a08
            Relative Machine Code RVA    = +0x0000000001645608
            Patch Offset                 = +0x00000000023d56e4
            Patch Size                   = 3 byte(s)
   ...
   ...
   ...
   MESSAGE: PatchSolution3: Keywords[110] has been found:
            Relative Machine Code Offset = +0x000000000165155e
            Relative Machine Code RVA    = +0x000000000165215e
            Patch Offset                 = +0x0000000001651561
            Patch Size                   = 1 byte(s)

   MESSAGE: PatchSolution2 will be omitted.

   MESSAGE: PatchSolution1: Keywords[0] has been found: offset = +0x021f7390.
   MESSAGE: PatchSolution1: Keywords[1] has been found: offset = +0x0074bd39.
   MESSAGE: PatchSolution1: Keywords[2] has been found: offset = +0x021f70a0.
   MESSAGE: PatchSolution1: Keywords[3] has been found: offset = +0x0074bd1f.
   MESSAGE: PatchSolution1: Keywords[4] has been found: offset = +0x021f708c.

   MESSAGE: Generating new RSA private key, it may take a long time.
   MESSAGE: New RSA private key has been saved to RegPrivateKey.pem.

   Your RSA public key:
   -----BEGIN PUBLIC KEY-----
   MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsWnV5hQxlXvDA3Ad4k5N
   ZLz4cO+iGEPegSovIDcwTo097I+0pXYKPTVl+0iKC5JtJRObb4Xx9yK9gGwqkcxo
   o6WzKq0xY1jz7X6obxwlQCNse3Os1wr0rIY0UzP1dCpkW/5MwGbFxiB6PEVqkzmJ
   CmHBzZDRu/jAuL1nyoiGnUStqwENNYhyl4k7r8AiJkBZGMOCrj6v0JfgNna25Ce6
   QCFojlY4dkYQ5/7njQ3qpLwMeLEXEysMW3aUScSB68/vsHnB4C0fIkwfEPYZ/AC5
   AqbWHVbNmveB3rjV+tZZxXcLE8ArgKh1Gs+2VtnL09gwHm6WcpyPZ42G6tMDjWyw
   1wIDAQAB
   -----END PUBLIC KEY-----

   ******************************************
   *            PatchSulution3              *
   ******************************************
   @ +023d56e4: 4D 49 49 ---> 4D 49 49
   @ +01644a63: 42 49 ---> 42 49
   @ +01644a68: 6A ---> 6A
   @ +01644ace: 41 ---> 41
   ...
   ...
   ...
   @ +023d58d4: 36 63 6A ---> 47 36 74
   @ +023d58d8: 78 6C 6A 75 75 51 61 ---> 4D 44 6A 57 79 77 31
   @ +023d58e8: 77 49 44 41 ---> 77 49 44 41
   @ +0165155c: 51 41 ---> 51 41
   @ +01651561: 42 ---> 42

   ******************************************
   *            PatchSulution1              *
   ******************************************
   @ +0x021f7390
   Previous:
   +0x00000000021F7390  44 37 35 31 32 35 42 37 30 37 36 37 42 39 34 31  D75125B70767B941
   +0x00000000021F73A0  34 35 42 34 37 43 31 43 42 33 43 30 37 35 35 45  45B47C1CB3C0755E
   +0x00000000021F73B0  37 43 43 42 38 38 32 35 43 35 44 43 45 30 43 35  7CCB8825C5DCE0C5
   ...
   ...
   ...

   @ +0x021f708c
   Previous:
   +0x00000000021F7080  31 32 32 35 4f 45 29 2e 00 00 00 00 39 32 39 33  1225OE).....9293
   +0x00000000021F7090  33 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  3...............
   After:
   +0x00000000021F7080  31 32 32 35 4f 45 29 2e 00 00 00 00 32 37 45 38  1225OE).....27E8
   +0x00000000021F7090  45 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  E...............

   MESSAGE: Patch has been done successfully.
   ```

5. 接下来使用`navicat-keygen.exe`来生成序列号和激活码

   ```
   ./navicat-keygen.sh
   ```

   你会被要求选择Navicat产品类别、语言以及输入主版本号。之后会随机生成一个序列号。

   ```
   Select Navicat product:
   0. DataModeler
   1. Premium
   2. MySQL
   3. PostgreSQL
   4. Oracle
   5. SQLServer
   6. SQLite
   7. MariaDB
   8. MongoDB
   9. ReportViewer

   (Input index)> 1

   Select product language:
   0. English
   1. Simplified Chinese
   2. Traditional Chinese
   3. Japanese
   4. Polish
   5. Spanish
   6. French
   7. German
   8. Korean
   9. Russian
   10. Portuguese

   (Input index)> 1

   (Input major version number, range: 0 ~ 15, default: 12)> 12

   Serial number:
   NAVO-2ORP-IN5A-GQEE

   Your name:
   ```

   你可以使用这个序列号暂时激活Navicat。

   接下来你会被要求输入`用户名`和`组织名`；请随便填写，但不要太长。

   ```
   Your name: DoubleLabyrinth
   Your organization: DoubleLabyrinth
   Input request code (in Base64), input empty line to end:
   ```

   之后你会被要求填入请求码。注意 __不要关闭命令行__.

6. 配置一个不存在的`代理`。找到`注册`窗口，并填入keygen给你的序列号。然后点击`激活`按钮。

7. 在线激活失败，这时候Navicat会询问你是否`手动激活`，直接选吧。

8. 在`手动激活`窗口你会得到一个请求码，复制它并把它粘贴到keygen里。最后别忘了连按至少两下回车结束输入。

   ```bash
   Your name: DoubleLabyrinth
   Your organization: DoubleLabyrinth

   Input request code (in Base64), input empty line to end:
   t2U+0yfE2FfnbjyhCXa0lglZOHu9Ntc3qyGiPbR6xb1QoU63/9BVfdaCq0blwVycXPyT/Vqw5joIKdM5oCRR/afCPM7iRcyhQMAnvqwc+AOKCqayVV+SqKLvtR/AbREI12w++PQ6Ewfs4A8PgB8OJ9G0jKt6Q/iJRblqi2WWw9mwy+YHcYYh3UAfygTnyj/xl+MzRymbY0lkus+6LPtpDecVsFFhM7F32Ee1QPwISko7bAkHOtkt+joPfYDdn9PDGZ4HEmeLvH6UqZCXkzgaAfynB7cQZFEkId8FsW2NGkbpM7wB2Hi3fNFgOIjutTprixTdbpFKn4w6gGc28ve23A==

   Request Info:
   {"K":"NAVO2ORPIN5AGQEE", "DI":"R91j6WyMhxHznAKSxxxx", "P":"WIN"}

   Response Info:
   {"K":"NAVO2ORPIN5AGQEE","DI":"R91j6WyMhxHznAKSxxxx","N":"DoubleLabyrinth","O":"DoubleLabyrinth","T":1547826060}

   License:
   lRF18o+ZhBphyN0U5kFLHtAAGGXuvhqOcxNuvAk4dJcGeR0ISuw74mQvAfdNjv0T
   I5NZFzqIJvrzM0XeR88q+3kmZkECuxwwWHP3zzDPhPiylcTV4DoGZ1tfoViUSYQc
   LgXG0Fl7koZeP61YOKQ8GfX+Xk2ZTM64bYaF7NlhonM+GQUJCCF2JThmrP921t2p
   b/E5pV6fLOYMM13881ZQcQcltMNVDZn4lzgzKRFFxCQFaTl6fJMHZdYVmICQTHtI
   sNaym0zduc8/cv34mgJ+7NseXmsEPCdjrZ59wgfPsLhZLXqtfxi5hGWw4NMa3Sb2
   UI8dzqFzRp/hSDEM0mEqiA==
   ```

9. 如果不出意外，你会得到一个看似用Base64编码的激活码。直接复制它，并把它粘贴到Navicat的`手动激活`窗口，最后点`激活`按钮。如果没什么意外的话应该能成功激活。别忘了关闭我们刚刚设置的不存在的代理哦。

repo_name: xianyu/navicat

license: mit


code:
# Navicat Keygen - for Windows

[中文版README](README_FOR_WINDOWS.zh-CN.md)

## How to use?

1. Download the latest release [from here](https://github.com/DoubleLabyrinth/navicat-keygen/releases).

2. Use `navicat-patcher.exe` to replace __Navicat Activation Public Key__ that is stored in `navicat.exe` or `libcc.dll`.

   ```
   navicat-patcher.exe <Navicat installation path> [RSA-2048 PEM file]
   ```

   * `<Navicat installation path>`: The full path to Navicat installation folder.

     __This parameter must be specified.__

   * `[RSA-2048 PEM file]`: The full path or relative path to a RSA-2048 private key file.

     __This parameter is optional.__ If not specified, `navicat-patcher.exe` will generate a new RSA-2048 private key file `RegPrivateKey.pem` at current directory.

   __Example: (in cmd.exe)__

   ```
   navicat-patcher.exe "C:\Program Files\PremiumSoft\Navicat Premium 12"
   ```

   It has been tested on __Navicat Premium 12.1.12 Simplified Chinese version__. The following is an example of output.

   ```
   ***************************************************
   *       Navicat Patcher by @DoubleLabyrinth       *
   *           Release date: Jan 19 2019             *
   ***************************************************

   Press Enter to continue or Ctrl + C to abort.

   MESSAGE: PatchSolution0 will be omitted.

   MESSAGE: PatchSolution3: Keywords[0] has been found:
            Relative Machine Code Offset = +0x0000000001644a08
            Relative Machine Code RVA    = +0x0000000001645608
            Patch Offset                 = +0x00000000023d56e4
            Patch Size                   = 3 byte(s)
   ...
   ...
   ...
   MESSAGE: PatchSolution3: Keywords[110] has been found:
            Relative Machine Code Offset = +0x000000000165155e
            Relative Machine Code RVA    = +0x000000000165215e
            Patch Offset                 = +0x0000000001651561
            Patch Size                   = 1 byte(s)

   MESSAGE: PatchSolution2 will be omitted.

   MESSAGE: PatchSolution1: Keywords[0] has been found: offset = +0x021f7390.
   MESSAGE: PatchSolution1: Keywords[1] has been found: offset = +0x0074bd39.
   MESSAGE: PatchSolution1: Keywords[2] has been found: offset = +0x021f70a0.
   MESSAGE: PatchSolution1: Keywords[3] has been found: offset = +0x0074bd1f.
   MESSAGE: PatchSolution1: Keywords[4] has been found: offset = +0x021f708c.

   MESSAGE: Generating new RSA private key, it may take a long time.
   MESSAGE: New RSA private key has been saved to RegPrivateKey.pem.

   Your RSA public key:
   -----BEGIN PUBLIC KEY-----
   MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsWnV5hQxlXvDA3Ad4k5N
   ZLz4cO+iGEPegSovIDcwTo097I+0pXYKPTVl+0iKC5JtJRObb4Xx9yK9gGwqkcxo
   o6WzKq0xY1jz7X6obxwlQCNse3Os1wr0rIY0UzP1dCpkW/5MwGbFxiB6PEVqkzmJ
   CmHBzZDRu/jAuL1nyoiGnUStqwENNYhyl4k7r8AiJkBZGMOCrj6v0JfgNna25Ce6
   QCFojlY4dkYQ5/7njQ3qpLwMeLEXEysMW3aUScSB68/vsHnB4C0fIkwfEPYZ/AC5
   AqbWHVbNmveB3rjV+tZZxXcLE8ArgKh1Gs+2VtnL09gwHm6WcpyPZ42G6tMDjWyw
   1wIDAQAB
   -----END PUBLIC KEY-----

   ******************************************
   *            PatchSulution3              *
   ******************************************
   @ +023d56e4: 4D 49 49 ---> 4D 49 49
   @ +01644a63: 42 49 ---> 42 49
   @ +01644a68: 6A ---> 6A
   @ +01644ace: 41 ---> 41
   ...
   ...
   ...
   @ +023d58d4: 36 63 6A ---> 47 36 74
   @ +023d58d8: 78 6C 6A 75 75 51 61 ---> 4D 44 6A 57 79 77 31
   @ +023d58e8: 77 49 44 41 ---> 77 49 44 41
   @ +0165155c: 51 41 ---> 51 41
   @ +01651561: 42 ---> 42

   ******************************************
   *            PatchSulution1              *
   ******************************************
   @ +0x021f7390
   Previous:
   +0x00000000021F7390  44 37 35 31 32 35 42 37 30 37 36 37 42 39 34 31  D75125B70767B941
   +0x00000000021F73A0  34 35 42 34 37 43 31 43 42 33 43 30 37 35 35 45  45B47C1CB3C0755E
   +0x00000000021F73B0  37 43 43 42 38 38 32 35 43 35 44 43 45 30 43 35  7CCB8825C5DCE0C5
   ...
   ...
   ...

   @ +0x021f708c
   Previous:
   +0x00000000021F7080  31 32 32 35 4f 45 29 2e 00 00 00 00 39 32 39 33  1225OE).....9293
   +0x00000000021F7090  33 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  3...............
   After:
   +0x00000000021F7080  31 32 32 35 4f 45 29 2e 00 00 00 00 32 37 45 38  1225OE).....27E8
   +0x00000000021F7090  45 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  E...............

   MESSAGE: Patch has been done successfully.
   ```

3. Then use `navicat-keygen.exe` to generate __snKey__ and __Activation Code__

   ```
   navicat-keygen.exe <-bin|-text> [-adv] <RSA-2048 PrivateKey(PEM file)>
   ```

   * `<-bin|-text>`: Must be `-bin` or `-text`.

     If `-bin` is specified, `navicat-keygen.exe` will finally generate `license_file`. It is used for Navicat old activation method only.

     If `-text` is specified, `navicat-keygen.exe` will finally generate a Base64-style string which is __Activation Code__. It is used for Navicat new activation method.

     __This parameter must be specified.__

   * `[-adv]`: Enable advanced mode.

     __This parameter is optional.__ If specified, `navicat-keygen.exe` will ask you input Navicat product ID number, language signature numbers. It is for future use generally.

   * `<RSA-2048 PrivateKey(PEM file)>`: The full path or relative path to a RSA-2048 private key file.

     __This parameter must be specified.__

   __Example: (in cmd.exe)__

   ```bash
   navicat-keygen.exe -text .\RegPrivateKey.pem
   ```

   You will be asked to select Navicat product, language and input major version number. After that an randomly generated __snKey__ will be given.

   ```
   Select Navicat product:
   0. DataModeler
   1. Premium
   2. MySQL
   3. PostgreSQL
   4. Oracle
   5. SQLServer
   6. SQLite
   7. MariaDB
   8. MongoDB
   9. ReportViewer

   (Input index)> 1

   Select product language:
   0. English
   1. Simplified Chinese
   2. Traditional Chinese
   3. Japanese
   4. Polish
   5. Spanish
   6. French
   7. German
   8. Korean
   9. Russian
   10. Portuguese

   (Input index)> 1

   (Input major version number, range: 0 ~ 15, default: 12)> 12

   Serial number:
   NAVO-2ORP-IN5A-GQEE

   Your name:
   ```

   You can use this __snKey__ to activate your Navicat preliminarily.

   Then you will be asked to input `Your name` and `Your organization`. Just set them whatever you want, but not too long.

   ```
   Your name: DoubleLabyrinth
   Your organization: DoubleLabyrinth
   Input request code (in Base64), input empty line to end:
   ```

   After that, you will be asked to input the request code. Now __DO NOT CLOSE KEYGEN__.

4. __Disconnect your network__ and open Navicat. Find and click `Registration`. Fill `Registration Key` by __snKey__ that the keygen gave and click `Activate`.

5. Generally online activation will failed and Navicat will ask you do `Manual Activation`, just choose it.

6. Copy your request code and paste it in the keygen. Input empty line to tell the keygen that your input ends.

   ```
   Your name: DoubleLabyrinth
   Your organization: DoubleLabyrinth

   Input request code (in Base64), input empty line to end:
   t2U+0yfE2FfnbjyhCXa0lglZOHu9Ntc3qyGiPbR6xb1QoU63/9BVfdaCq0blwVycXPyT/Vqw5joIKdM5oCRR/afCPM7iRcyhQMAnvqwc+AOKCqayVV+SqKLvtR/AbREI12w++PQ6Ewfs4A8PgB8OJ9G0jKt6Q/iJRblqi2WWw9mwy+YHcYYh3UAfygTnyj/xl+MzRymbY0lkus+6LPtpDecVsFFhM7F32Ee1QPwISko7bAkHOtkt+joPfYDdn9PDGZ4HEmeLvH6UqZCXkzgaAfynB7cQZFEkId8FsW2NGkbpM7wB2Hi3fNFgOIjutTprixTdbpFKn4w6gGc28ve23A==

   Request Info:
   {"K":"NAVO2ORPIN5AGQEE", "DI":"R91j6WyMhxHznAKSxxxx", "P":"WIN"}

   Response Info:
   {"K":"NAVO2ORPIN5AGQEE","DI":"R91j6WyMhxHznAKSxxxx","N":"DoubleLabyrinth","O":"DoubleLabyrinth","T":1547826060}

   License:
   lRF18o+ZhBphyN0U5kFLHtAAGGXuvhqOcxNuvAk4dJcGeR0ISuw74mQvAfdNjv0T
   I5NZFzqIJvrzM0XeR88q+3kmZkECuxwwWHP3zzDPhPiylcTV4DoGZ1tfoViUSYQc
   LgXG0Fl7koZeP61YOKQ8GfX+Xk2ZTM64bYaF7NlhonM+GQUJCCF2JThmrP921t2p
   b/E5pV6fLOYMM13881ZQcQcltMNVDZn4lzgzKRFFxCQFaTl6fJMHZdYVmICQTHtI
   sNaym0zduc8/cv34mgJ+7NseXmsEPCdjrZ59wgfPsLhZLXqtfxi5hGWw4NMa3Sb2
   UI8dzqFzRp/hSDEM0mEqiA==
   ```

7. Finally, you will get __Activation Code__ which looks like a Base64 string. Just copy it and paste it in Navicat `Manual Activation` window, then click `Activate`. If nothing wrong, activation should be done successfully.


code:
# Navicat Keygen - for Windows

## 如何使用这个注册机

1. [从这里](https://github.com/DoubleLabyrinth/navicat-keygen/releases)下载最新的release。

2. 使用`navicat-patcher.exe`替换掉`navicat.exe`和`libcc.dll`里的Navicat激活公钥。

   ```
   navicat-patcher.exe <Navicat installation path> [RSA-2048 PEM file]
   ```

   * `<Navicat installation path>`: Navicat的完整安装路径。

     __这个参数必须指定。__

   * `[RSA-2048 PEM file]`: RSA-2048私钥文件的完整路径或相对路径。

     __这个参数是可选的。__ 如果未指定，`navicat-patcher.exe`将会在当前目录生成一个新的RSA-2048私钥文件。

   __例如：(在cmd.exe中)__

   ```
   navicat-patcher.exe "C:\Program Files\PremiumSoft\Navicat Premium 12"
   ```

   __Navicat Premium 12.1.12 简体中文版已通过测试__。下面将是一份样例输出。

   ```
   ***************************************************
   *       Navicat Patcher by @DoubleLabyrinth       *
   *           Release date: Jan 19 2019             *
   ***************************************************

   Press Enter to continue or Ctrl + C to abort.

   MESSAGE: PatchSolution0 will be omitted.

   MESSAGE: PatchSolution3: Keywords[0] has been found:
            Relative Machine Code Offset = +0x0000000001644a08
            Relative Machine Code RVA    = +0x0000000001645608
            Patch Offset                 = +0x00000000023d56e4
            Patch Size                   = 3 byte(s)
   ...
   ...
   ...
   MESSAGE: PatchSolution3: Keywords[110] has been found:
            Relative Machine Code Offset = +0x000000000165155e
            Relative Machine Code RVA    = +0x000000000165215e
            Patch Offset                 = +0x0000000001651561
            Patch Size                   = 1 byte(s)

   MESSAGE: PatchSolution2 will be omitted.

   MESSAGE: PatchSolution1: Keywords[0] has been found: offset = +0x021f7390.
   MESSAGE: PatchSolution1: Keywords[1] has been found: offset = +0x0074bd39.
   MESSAGE: PatchSolution1: Keywords[2] has been found: offset = +0x021f70a0.
   MESSAGE: PatchSolution1: Keywords[3] has been found: offset = +0x0074bd1f.
   MESSAGE: PatchSolution1: Keywords[4] has been found: offset = +0x021f708c.

   MESSAGE: Generating new RSA private key, it may take a long time.
   MESSAGE: New RSA private key has been saved to RegPrivateKey.pem.

   Your RSA public key:
   -----BEGIN PUBLIC KEY-----
   MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsWnV5hQxlXvDA3Ad4k5N
   ZLz4cO+iGEPegSovIDcwTo097I+0pXYKPTVl+0iKC5JtJRObb4Xx9yK9gGwqkcxo
   o6WzKq0xY1jz7X6obxwlQCNse3Os1wr0rIY0UzP1dCpkW/5MwGbFxiB6PEVqkzmJ
   CmHBzZDRu/jAuL1nyoiGnUStqwENNYhyl4k7r8AiJkBZGMOCrj6v0JfgNna25Ce6
   QCFojlY4dkYQ5/7njQ3qpLwMeLEXEysMW3aUScSB68/vsHnB4C0fIkwfEPYZ/AC5
   AqbWHVbNmveB3rjV+tZZxXcLE8ArgKh1Gs+2VtnL09gwHm6WcpyPZ42G6tMDjWyw
   1wIDAQAB
   -----END PUBLIC KEY-----

   ******************************************
   *            PatchSulution3              *
   ******************************************
   @ +023d56e4: 4D 49 49 ---> 4D 49 49
   @ +01644a63: 42 49 ---> 42 49
   @ +01644a68: 6A ---> 6A
   @ +01644ace: 41 ---> 41
   ...
   ...
   ...
   @ +023d58d4: 36 63 6A ---> 47 36 74
   @ +023d58d8: 78 6C 6A 75 75 51 61 ---> 4D 44 6A 57 79 77 31
   @ +023d58e8: 77 49 44 41 ---> 77 49 44 41
   @ +0165155c: 51 41 ---> 51 41
   @ +01651561: 42 ---> 42

   ******************************************
   *            PatchSulution1              *
   ******************************************
   @ +0x021f7390
   Previous:
   +0x00000000021F7390  44 37 35 31 32 35 42 37 30 37 36 37 42 39 34 31  D75125B70767B941
   +0x00000000021F73A0  34 35 42 34 37 43 31 43 42 33 43 30 37 35 35 45  45B47C1CB3C0755E
   +0x00000000021F73B0  37 43 43 42 38 38 32 35 43 35 44 43 45 30 43 35  7CCB8825C5DCE0C5
   ...
   ...
   ...

   @ +0x021f708c
   Previous:
   +0x00000000021F7080  31 32 32 35 4f 45 29 2e 00 00 00 00 39 32 39 33  1225OE).....9293
   +0x00000000021F7090  33 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  3...............
   After:
   +0x00000000021F7080  31 32 32 35 4f 45 29 2e 00 00 00 00 32 37 45 38  1225OE).....27E8
   +0x00000000021F7090  45 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  E...............

   MESSAGE: Patch has been done successfully.
   ```

3. 接下来使用`navicat-keygen.exe`来生成序列号和激活码

   ```
   navicat-keygen.exe <-bin|-text> [-adv] <RSA-2048 PrivateKey(PEM file)>
   ```

   * `<-bin|-text>`: 必须是`-bin`或`-text`。

     如果指定了`-bin`，`navicat-keygen.exe`最终将生成`license_file`文件。这个选项是给Navicat旧激活方式使用的。

     如果指定了`-text`，`navicat-keygen.exe`最终将生成Base64样式的激活码。这个选项是给Navicat新激活方式使用的。

     __这个参数必须指定。__

   * `[-adv]`: 开启高级模式。

     __这个参数是可选的。__ 如果指定了这个参数，`navicat-keygen.exe`将会要求你手工填写产品ID号、语言标识号。这个选项一般是给以后用的。

   * `<RSA-2048 PrivateKey(PEM file)>`: RSA-2048私钥文件的完整路径或相对路径。

     __这个参数必须指定。__

   __例如：(在cmd.exe中)__

   ```bash
   navicat-keygen.exe -text .\RegPrivateKey.pem
   ```

   你会被要求选择Navicat产品类别、语言以及输入主版本号。之后会随机生成一个序列号。

   ```
   Select Navicat product:
   0. DataModeler
   1. Premium
   2. MySQL
   3. PostgreSQL
   4. Oracle
   5. SQLServer
   6. SQLite
   7. MariaDB
   8. MongoDB
   9. ReportViewer

   (Input index)> 1

   Select product language:
   0. English
   1. Simplified Chinese
   2. Traditional Chinese
   3. Japanese
   4. Polish
   5. Spanish
   6. French
   7. German
   8. Korean
   9. Russian
   10. Portuguese

   (Input index)> 1

   (Input major version number, range: 0 ~ 15, default: 12)> 12

   Serial number:
   NAVO-2ORP-IN5A-GQEE

   Your name:
   ```

   你可以使用这个序列号暂时激活Navicat。

   接下来你会被要求输入`用户名`和`组织名`；请随便填写，但不要太长。

   ```
   Your name: DoubleLabyrinth
   Your organization: DoubleLabyrinth
   Input request code (in Base64), input empty line to end:
   ```

   之后你会被要求填入请求码。注意 __不要关闭命令行__.

4. __断开网络__ 并打开Navicat。找到`注册`窗口，并填入keygen给你的序列号。然后点击`激活`按钮。

5. 一般来说在线激活肯定会失败，这时候Navicat会询问你是否`手动激活`，直接选吧。

6. 在`手动激活`窗口你会得到一个请求码，复制它并把它粘贴到keygen里。最后别忘了连按至少两下回车结束输入。

   ```bash
   Your name: DoubleLabyrinth
   Your organization: DoubleLabyrinth

   Input request code (in Base64), input empty line to end:
   t2U+0yfE2FfnbjyhCXa0lglZOHu9Ntc3qyGiPbR6xb1QoU63/9BVfdaCq0blwVycXPyT/Vqw5joIKdM5oCRR/afCPM7iRcyhQMAnvqwc+AOKCqayVV+SqKLvtR/AbREI12w++PQ6Ewfs4A8PgB8OJ9G0jKt6Q/iJRblqi2WWw9mwy+YHcYYh3UAfygTnyj/xl+MzRymbY0lkus+6LPtpDecVsFFhM7F32Ee1QPwISko7bAkHOtkt+joPfYDdn9PDGZ4HEmeLvH6UqZCXkzgaAfynB7cQZFEkId8FsW2NGkbpM7wB2Hi3fNFgOIjutTprixTdbpFKn4w6gGc28ve23A==

   Request Info:
   {"K":"NAVO2ORPIN5AGQEE", "DI":"R91j6WyMhxHznAKSxxxx", "P":"WIN"}

   Response Info:
   {"K":"NAVO2ORPIN5AGQEE","DI":"R91j6WyMhxHznAKSxxxx","N":"DoubleLabyrinth","O":"DoubleLabyrinth","T":1547826060}

   License:
   lRF18o+ZhBphyN0U5kFLHtAAGGXuvhqOcxNuvAk4dJcGeR0ISuw74mQvAfdNjv0T
   I5NZFzqIJvrzM0XeR88q+3kmZkECuxwwWHP3zzDPhPiylcTV4DoGZ1tfoViUSYQc
   LgXG0Fl7koZeP61YOKQ8GfX+Xk2ZTM64bYaF7NlhonM+GQUJCCF2JThmrP921t2p
   b/E5pV6fLOYMM13881ZQcQcltMNVDZn4lzgzKRFFxCQFaTl6fJMHZdYVmICQTHtI
   sNaym0zduc8/cv34mgJ+7NseXmsEPCdjrZ59wgfPsLhZLXqtfxi5hGWw4NMa3Sb2
   UI8dzqFzRp/hSDEM0mEqiA==
   ```

  4. 如果不出意外，你会得到一个看似用Base64编码的激活码。直接复制它，并把它粘贴到Navicat的`手动激活`窗口，最后点`激活`按钮。如果没什么意外的话应该能成功激活。


code:
#!/usr/bin/env bash

cd `dirname "$0"`
navicat_root=`pwd`

# Wine environment variables
WINEDIR="wine"
export LANG="en_US.UTF-8"
export PATH="$navicat_root/$WINEDIR/bin":"$navicat_root":"$navicat_root/$WINEDIR/drive_c/windows":"$PATH"
export LD_LIBRARY_PATH="$navicat_root/$WINEDIR/lib":"$navicat_root/lib":"$LD_LIBRARY_PATH"
export WINEDLLPATH="$navicat_root/$WINEDIR/lib/wine"
export WINELOADER="$navicat_root/$WINEDIR/bin/wine64"
export WINESERVER="$navicat_root/$WINEDIR/bin/wineserver"
export WINEPREFIX="$HOME/.navicat64"

exec "${WINELOADER:-wine}" "navicat-keygen.exe" "-text" "RegPrivateKey.pem"


code:
#!/usr/bin/env bash

cd `dirname "$0"`
navicat_root=`pwd`

# Wine environment variables
WINEDIR="wine"
export LANG="en_US.UTF-8"
export PATH="$navicat_root/$WINEDIR/bin":"$navicat_root":"$navicat_root/$WINEDIR/drive_c/windows":"$PATH"
export LD_LIBRARY_PATH="$navicat_root/$WINEDIR/lib":"$navicat_root/lib":"$LD_LIBRARY_PATH"
export WINEDLLPATH="$navicat_root/$WINEDIR/lib/wine"
export WINELOADER="$navicat_root/$WINEDIR/bin/wine64"
export WINESERVER="$navicat_root/$WINEDIR/bin/wineserver"
export WINEPREFIX="$HOME/.navicat64"

# 将斜线替换为反斜线
navicat_root_back_slash=${navicat_root//\//\\}
# 前缀
prefix='Z:\'
# 后缀
suffix='\Navicat'
# wine环境中的navicat路径
navicat_path="$prefix$navicat_root_back_slash$suffix"

# wine执行navicat-patcher.exe
exec "${WINELOADER:-wine}" "navicat-patcher.exe" "$navicat_path"


code:
#pragma once
#include "TString.hpp"
#include <vector>

class Exception {
private:
    static inline TString EmptyErrorStr;
    TString _File;
    size_t _Line;
    TString _Message;
    std::vector<TString> _Hints;
public:

    template<typename... __Ts>
    Exception(const TString& FileName,
              size_t LineNumber,
              const TString& CustomMsg,
              __Ts&&... SomeHints) noexcept :
        _File(FileName),
        _Line(LineNumber),
        _Message(CustomMsg),
        _Hints{ std::forward<__Ts>(SomeHints)... } {}

    const TString& File() const noexcept {
        return _File;
    }

    size_t Line() const noexcept {
        return _Line;
    }

    const TString& Message() const noexcept {
        return _Message;
    }

    std::vector<TString>& Hints() noexcept {
        return _Hints;
    }

    const std::vector<TString>& Hints() const noexcept {
        return _Hints;
    }

    virtual bool HasErrorCode() const noexcept {
        return false;
    }

    virtual uintptr_t ErrorCode() const noexcept {
        return 0;
    }

    virtual const TString& ErrorString() const noexcept {
        return EmptyErrorStr;
    }

    virtual ~Exception() = default;
};


code:
#pragma once
#include <windows.h>
#include "Exception.hpp"

class SystemException : public Exception {
private:
    DWORD _ErrorCode;
    TString _ErrorString;
public:

    template<typename... __Ts>
    SystemException(const TString& FileName,
                    size_t LineNumber,
                    DWORD Win32ErrorCode,
                    const TString& CustomMsg,
                    __Ts&&... SomeHints) noexcept :
        Exception(FileName, LineNumber, CustomMsg, std::forward<__Ts>(SomeHints)...),
        _ErrorCode(Win32ErrorCode)
    {
        PTSTR Text = NULL;
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
                      NULL,
                      Win32ErrorCode,
                      MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
                      reinterpret_cast<PTSTR>(&Text),
                      0,
                      NULL);
        _ErrorString.assign(Text);
        LocalFree(Text);
    }

    virtual bool HasErrorCode() const noexcept override {
        return true;
    }

    virtual uintptr_t ErrorCode() const noexcept override {
        return _ErrorCode;
    }

    virtual const TString& ErrorString() const noexcept override {
        return _ErrorString;
    }
};


code:
#pragma once
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/bio.h>
#include <openssl/rsa.h>
#include <memory.h>
#include "Exception.hpp"
#include "ResourceObject.hpp"

#ifdef _DEBUG
#pragma comment(lib, "libcryptoMTd.lib")
#else
#pragma comment(lib, "libcryptoMT.lib")
#endif
#pragma comment(lib, "WS2_32.lib")      // some symbol are used in OpenSSL static lib
#pragma comment(lib, "Crypt32.lib")     // some symbol are used in OpenSSL static lib

#undef __BASE_FILE__
#define __BASE_FILE__ TEXT("RSACipher.hpp")

class OpensslException : public Exception {
private:
    unsigned long _ErrorCode;
    TString _ErrorString;
public:

    OpensslException(const TString& FileName,
                     size_t LineNumber,
                     unsigned long OpensslErrorCode,
                     const TString& CustomMsg) noexcept :
        Exception(FileName, LineNumber, CustomMsg),
        _ErrorCode(OpensslErrorCode),
        _ErrorString(TStringBuilder(ERR_error_string(OpensslErrorCode, nullptr), CP_UTF8)) {}

    virtual bool HasErrorCode() const noexcept override {
        return true;
    }

    virtual uintptr_t ErrorCode() const noexcept override {
        return _ErrorCode;
    }

    virtual const TString& ErrorString() const noexcept override {
        return _ErrorString;
    }

};

struct OpensslBIOTraits {
    using HandleType = BIO*;
    static inline const HandleType InvalidValue = nullptr;
    static constexpr auto& Releasor = BIO_free;
};

struct OpensslBIOChainTraits {
    using HandleType = BIO*;
    static inline const HandleType InvalidValue = nullptr;
    static constexpr auto& Releasor = BIO_free_all;
};

struct OpensslBNTraits {
    using HandleType = BIGNUM*;
    static inline const HandleType InvalidValue = nullptr;
    static constexpr auto& Releasor = BN_free;
};

struct OpensslRSATraits {
    using HandleType = RSA*;
    static inline const HandleType InvalidValue = nullptr;
    static constexpr auto& Releasor = RSA_free;
};

enum class RSAKeyType {
    PrivateKey,
    PublicKey
};

enum class RSAKeyFormat {
    NotSpecified,
    PEM,
    PKCS1
};

class RSACipher {
private:
    ResourceObject<OpensslRSATraits> _RSAObj;

    RSACipher(RSA* pRsa) noexcept : _RSAObj(pRsa) {}

    //
    // Copy constructor is not allowed
    //
    RSACipher(const RSACipher&) = delete;

    //
    // Copy assignment is not allowed
    //
    RSACipher& operator=(const RSACipher&) = delete;

    template<RSAKeyType __Type, RSAKeyFormat __Format = RSAKeyFormat::NotSpecified>
    static void _WriteRSAToBIO(RSA* PtrToRSA, BIO* PtrToBIO) {
        if constexpr (__Type == RSAKeyType::PrivateKey) {
            if (!PEM_write_bio_RSAPrivateKey(PtrToBIO, PtrToRSA, nullptr, nullptr, 0, nullptr, nullptr))
                throw Exception(__BASE_FILE__, __LINE__,
                                TEXT("PEM_write_bio_RSAPrivateKey failed."));
        } else {
            if constexpr (__Format == RSAKeyFormat::PEM) {
                if (!PEM_write_bio_RSA_PUBKEY(PtrToBIO, PtrToRSA))
                    throw Exception(__BASE_FILE__, __LINE__,
                                    TEXT("PEM_write_bio_RSA_PUBKEY failed."));
            } else if constexpr (__Format == RSAKeyFormat::PKCS1) {
                if (!PEM_write_bio_RSAPublicKey(PtrToBIO, PtrToRSA))
                    throw Exception(__BASE_FILE__, __LINE__,
                                    TEXT("PEM_write_bio_RSAPublicKey failed."));
            } else {
                static_assert(__Format == RSAKeyFormat::PEM || __Format == RSAKeyFormat::PKCS1);
            }
        }
    }

    template<RSAKeyType __Type, RSAKeyFormat __Format = RSAKeyFormat::NotSpecified>
    static RSA* _ReadRSAFromBIO(BIO* PtrToBIO) {
        RSA* PtrToRSA;

        if constexpr (__Type == RSAKeyType::PrivateKey) {
            PtrToRSA = PEM_read_bio_RSAPrivateKey(PtrToBIO, nullptr, nullptr, nullptr);
            if (PtrToRSA == nullptr)
                throw Exception(__BASE_FILE__, __LINE__,
                                TEXT("PEM_read_bio_RSAPrivateKey failed."));
        } else {
            if constexpr (__Format == RSAKeyFormat::PEM) {
                PtrToRSA = PEM_read_bio_RSA_PUBKEY(PtrToBIO, nullptr, nullptr, nullptr);
                if (PtrToRSA == nullptr)
                    throw Exception(__BASE_FILE__, __LINE__,
                                    TEXT("PEM_read_bio_RSA_PUBKEY failed."));
            } else if constexpr (__Format == RSAKeyFormat::PKCS1) {
                PtrToRSA = PEM_read_bio_RSAPublicKey(PtrToBIO, nullptr, nullptr, nullptr);
                if (PtrToRSA == nullptr)
                    throw Exception(__BASE_FILE__, __LINE__,
                                    TEXT("PEM_read_bio_RSAPublicKey failed."));
            } else {
                static_assert(__Format == RSAKeyFormat::PEM || __Format == RSAKeyFormat::PKCS1);
            }
        }

        return PtrToRSA;
    }

public:

    RSACipher() : _RSAObj(RSA_new()) {
        if (_RSAObj.IsValid() == false)
            throw OpensslException(__BASE_FILE__, __LINE__, ERR_get_error(),
                                   TEXT("RSA_new failed."));
    }

    void GenerateKey(int bits, unsigned int e = RSA_F4) {
        ResourceObject<OpensslBNTraits> bn_e;

        bn_e.TakeOver(BN_new());
        if (bn_e.IsValid() == false)
            throw OpensslException(__BASE_FILE__, __LINE__, ERR_get_error(),
                                   TEXT("BN_new failed."));

        if (!BN_set_word(bn_e, e))
            throw Exception(__BASE_FILE__, __LINE__,
                            TEXT("BN_set_word failed."));

        if (!RSA_generate_key_ex(_RSAObj, bits, bn_e, nullptr))
            throw OpensslException(__BASE_FILE__, __LINE__, ERR_get_error(),
                                   TEXT("RSA_generate_key_ex failed."));
    }

    template<RSAKeyType __Type, RSAKeyFormat __Format = RSAKeyFormat::NotSpecified>
    void ExportKeyToFile(const std::string& FileName) {
        ResourceObject<OpensslBIOTraits> BIOKeyFile;

        BIOKeyFile.TakeOver(BIO_new_file(FileName.c_str(), "w"));
        if (BIOKeyFile.IsValid() == false)
            throw Exception(__BASE_FILE__, __LINE__,
                            TEXT("BIO_new_file failed."));

        _WriteRSAToBIO<__Type, __Format>(_RSAObj, BIOKeyFile);
    }

    template<RSAKeyType __Type, RSAKeyFormat __Format = RSAKeyFormat::NotSpecified>
    std::string ExportKeyString() {
        std::string KeyString;
        ResourceObject<OpensslBIOTraits> BIOKeyMemory;
        long s;
        const char* p = nullptr;

        BIOKeyMemory.TakeOver(BIO_new(BIO_s_mem()));
        if (BIOKeyMemory.IsValid() == false)
            throw Exception(__BASE_FILE__, __LINE__,
                            TEXT("BIO_new failed."));

        _WriteRSAToBIO<__Type, __Format>(_RSAObj, BIOKeyMemory);

        s = BIO_get_mem_data(BIOKeyMemory, &p);
        KeyString.resize(s);
        memcpy(KeyString.data(), p, s);

        return KeyString;
    }

    template<RSAKeyType __Type, RSAKeyFormat __Format = RSAKeyFormat::NotSpecified>
    void ImportKeyFromFile(const std::string& FileName) {
        ResourceObject<OpensslBIOTraits> BIOKeyFile;
        RSA* NewRSAObj;

        BIOKeyFile.TakeOver(BIO_new_file(FileName.c_str(), "r"));
        if (BIOKeyFile.IsValid() == false)
            throw Exception(__BASE_FILE__, __LINE__,
                            TEXT("BIO_new_file failed."));

        NewRSAObj = _ReadRSAFromBIO<__Type, __Format>(BIOKeyFile);
        _RSAObj.Release();
        _RSAObj.TakeOver(NewRSAObj);
    }

    template<RSAKeyType __Type, RSAKeyFormat __Format = RSAKeyFormat::NotSpecified>
    void ImportKeyString(const std::string& KeyString) {
        ResourceObject<OpensslBIOTraits> BIOKeyMemory;
        RSA* NewRSAObj;

        BIOKeyMemory = BIO_new(BIO_s_mem());
        if (BIOKeyMemory == nullptr)
            throw Exception(__BASE_FILE__, __LINE__,
                            TEXT("BIO_new failed."));

        if (BIO_puts(BIOKeyMemory, KeyString.c_str()) <= 0)
            throw Exception(__BASE_FILE__, __LINE__,
                            TEXT("BIO_puts failed."));

        NewRSAObj = _ReadRSAFromBIO<__Type, __Format>(BIOKeyMemory);
        _RSAObj.Release();
        _RSAObj.TakeOver(NewRSAObj);
    }

    template<RSAKeyType __Type = RSAKeyType::PublicKey>
    int Encrypt(const void* from, int len, void* to, int padding) {
        int WriteBytes;

        if constexpr (__Type == RSAKeyType::PrivateKey) {
            WriteBytes = RSA_private_encrypt(len,
                                             reinterpret_cast<const unsigned char*>(from),
                                             reinterpret_cast<unsigned char*>(to),
                                             _RSAObj,
                                             padding);
            if (WriteBytes == -1)
                throw OpensslException(__BASE_FILE__, __LINE__, ERR_get_error(),
                                       TEXT("RSA_private_encrypt failed."));
        } else {
            WriteBytes = RSA_public_encrypt(len,
                                            reinterpret_cast<const unsigned char*>(from),
                                            reinterpret_cast<unsigned char*>(to),
                                            _RSAObj,
                                            padding);
            if (WriteBytes == -1)
                throw OpensslException(__BASE_FILE__, __LINE__, ERR_get_error(),
                                       TEXT("RSA_public_encrypt failed."));
        }

        return WriteBytes;
    }

    template<RSAKeyType __Type = RSAKeyType::PrivateKey>
    int Decrypt(const void* from, int len, void* to, int padding) {
        int WriteBytes;

        if constexpr (__Type == RSAKeyType::PrivateKey) {
            WriteBytes = RSA_private_decrypt(len,
                                             reinterpret_cast<const unsigned char*>(from),
                                             reinterpret_cast<unsigned char*>(to),
                                             _RSAObj,
                                             padding);
            if (WriteBytes == -1)
                throw OpensslException(__BASE_FILE__, __LINE__, ERR_get_error(),
                                       TEXT("RSA_private_decrypt failed."));
        } else {
            WriteBytes = RSA_public_decrypt(len,
                                            reinterpret_cast<const unsigned char*>(from),
                                            reinterpret_cast<unsigned char*>(to),
                                            _RSAObj,
                                            padding);
            if (WriteBytes == -1)
                throw OpensslException(__BASE_FILE__, __LINE__, ERR_get_error(),
                                       TEXT("RSA_public_decrypt failed."));
        }

        return WriteBytes;
    }

};


code:
#pragma once
#include <type_traits>

template<typename __ResourceTraits>
class ResourceObject {
public:
    using HandleType = typename __ResourceTraits::HandleType;
private:
    HandleType _Handle;
public:

    ResourceObject() noexcept :
        _Handle(__ResourceTraits::InvalidValue) {}

    explicit ResourceObject(const HandleType& Handle) noexcept :
        _Handle(Handle) {}

    //
    // Copy constructor is not allowed
    //
    ResourceObject(const ResourceObject<__ResourceTraits>& Other) = delete;

    ResourceObject(ResourceObject<__ResourceTraits>&& Other) noexcept :
        _Handle(Other._Handle)
    {
        Other._Handle = __ResourceTraits::InvalidValue;
    }

    //
    // Copy assignment is not allowed
    //
    ResourceObject<__ResourceTraits>&
    operator=(const ResourceObject<__ResourceTraits>& Other) = delete;

    ResourceObject<__ResourceTraits>&
    operator=(ResourceObject<__ResourceTraits>&& Other) noexcept {
        _Handle = Other._Handle;
        Other._Handle = __ResourceTraits::InvalidValue;
        return *this;
    }

    template<typename __DummyType = int,
             typename = typename std::enable_if<std::is_pointer<HandleType>::value, __DummyType>::type>
    HandleType operator->() const noexcept {
        return _Handle;
    }

    operator HandleType() const noexcept {
        return _Handle;
    }

    // Check if handle is a valid handle
    bool IsValid() const noexcept {
        return _Handle != __ResourceTraits::InvalidValue;
    }

    HandleType Get() const noexcept {
        return _Handle;
    }

    void TakeOver(const HandleType& Handle) noexcept {
        if (_Handle != __ResourceTraits::InvalidValue) {
            __ResourceTraits::Releasor(_Handle);
            _Handle = __ResourceTraits::InvalidValue;
        } else {
            _Handle = Handle;
        }
    }

    void Abandon() noexcept {
        _Handle = __ResourceTraits::InvalidValue;
    }

    // Force release
    void Release() {
        if (_Handle != __ResourceTraits::InvalidValue) {
            __ResourceTraits::Releasor(_Handle);
            _Handle = __ResourceTraits::InvalidValue;
        }
    }

    ~ResourceObject() {
        if (_Handle != __ResourceTraits::InvalidValue) {
            __ResourceTraits::Releasor(_Handle);
            _Handle = __ResourceTraits::InvalidValue;
        }
    }
};

template<typename __ClassType>
struct CppObjectTraits {
    using HandleType = __ClassType*;
    static inline const HandleType InvalidValue = nullptr;
    static inline void Releasor(HandleType pObject) {
        delete pObject;
    }
};

template<typename __ClassType>
struct CppDynamicArrayTraits {
    using HandleType = __ClassType*;
    static inline const HandleType InvalidValue = nullptr;
    static inline void Releasor(HandleType pArray) {
        delete[] pArray;
    }
};


code:
#include "TString.hpp"
#include "ExceptionSystem.hpp"

#undef __BASE_FILE__
#define __BASE_FILE__ TEXT("TString.cpp")

TString TStringBuilder(PCSTR LpMultiByteStr, UINT CodePage) {
#ifdef _UNICODE
    TString TStr;
    int RequiredSize = MultiByteToWideChar(CodePage,
                                           NULL,
                                           LpMultiByteStr,
                                           -1,
                                           NULL,
                                           0);
    if (RequiredSize == 0)
        throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                              TEXT("MultiByteToWideChar failed."));

    TStr.resize(RequiredSize);

    if (!MultiByteToWideChar(CP_ACP,
                             NULL,
                             LpMultiByteStr,
                             -1,
                             TStr.data(),
                             RequiredSize))
        throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                              TEXT("MultiByteToWideChar failed."));

    while (TStr.back() == L'\x00')
        TStr.pop_back();

    return TStr;
#else
    if (CodePage == CP_ACP) {
        return TString(LpMultiByteStr);
    } else {
        std::wstring WideCharStr;
        TString TStr;
        int RequiredSize = MultiByteToWideChar(CodePage,
                                               NULL,
                                               LpMultiByteStr,
                                               -1,
                                               NULL,
                                               0);
        if (RequiredSize == 0)
            throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                                  TEXT("MultiByteToWideChar failed."));

        WideCharStr.resize(RequiredSize);

        if (!MultiByteToWideChar(CP_ACP,
                                 NULL,
                                 LpMultiByteStr,
                                 -1,
                                 WideCharStr.data(),
                                 RequiredSize))
            throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                                  TEXT("MultiByteToWideChar failed."));

        while (WideCharStr.back() == L'\x00')
            WideCharStr.pop_back();

        RequiredSize = WideCharToMultiByte(CP_ACP,
                                           NULL,
                                           WideCharStr.c_str(),
                                           -1,
                                           NULL,
                                           0,
                                           NULL,
                                           NULL);
        if (RequiredSize == 0)
            throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                                  TEXT("WideCharToMultiByte failed."));

        TStr.resize(RequiredSize);

        if (!WideCharToMultiByte(CP_ACP,
                                 NULL,
                                 WideCharStr.c_str(),
                                 -1,
                                 TStr.data(),
                                 RequiredSize,
                                 NULL,
                                 NULL))
            throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                                  TEXT("WideCharToMultiByte failed."));

        while (TStr.back() == '\x00')
            TStr.pop_back();

        return TStr;
    }
#endif
}

TString TStringBuilder(PCWSTR LpWideCharStr) {
#ifdef _UNICODE
    return TString(LpWideCharStr);
#else
    TString TStr;
    int RequiredSize = WideCharToMultiByte(CP_ACP,
                                           NULL,
                                           LpWideCharStr,
                                           -1,
                                           NULL,
                                           0,
                                           NULL,
                                           NULL);
    if (RequiredSize == 0)
        throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                              TEXT("WideCharToMultiByte failed."));

    TStr.resize(RequiredSize);

    if (!WideCharToMultiByte(CP_ACP,
                             NULL,
                             LpWideCharStr,
                             -1,
                             TStr.data(),
                             RequiredSize,
                             NULL,
                             NULL))
        throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                              TEXT("WideCharToMultiByte failed."));

    while (TStr.back() == '\x00')
        TStr.pop_back();

    return TStr;
#endif
}

TString TStringBuilder(const std::string& RefMultiByteStr, UINT CodePage) {
    return TStringBuilder(RefMultiByteStr.c_str(), CodePage);
}

TString TStringBuilder(const std::wstring& RefWideCharStr) {
    return TStringBuilder(RefWideCharStr.c_str());
}

std::string TStringEncode(PTSTR LpTString, UINT CodePage) {
    std::string MultiByteStr;
    int RequiredSize;
#ifdef _UNICODE
    RequiredSize = WideCharToMultiByte(CodePage,
                                       NULL,
                                       LpTString,
                                       -1,
                                       NULL,
                                       0,
                                       NULL,
                                       NULL);
    if (RequiredSize == 0)
        throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                              TEXT("WideCharToMultiByte failed."));

    MultiByteStr.resize(RequiredSize);

    if (!WideCharToMultiByte(CodePage,
                             NULL,
                             LpTString,
                             -1,
                             MultiByteStr.data(),
                             RequiredSize,
                             NULL,
                             NULL))
        throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                              TEXT("WideCharToMultiByte failed."));

    while (MultiByteStr.back() == '\x00')
        MultiByteStr.pop_back();
#else
    if (CodePage == CP_ACP)
        return RefTStr;

    std::wstring WideCharStr;
    RequiredSize = MultiByteToWideChar(CP_ACP,
                                       NULL,
                                       LpTString,
                                       -1,
                                       NULL,
                                       0);
    if (RequiredSize == 0)
        throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                              TEXT("MultiByteToWideChar failed."));

    WideCharStr.resize(RequiredSize);

    if (!MultiByteToWideChar(CP_ACP,
                             NULL,
                             LpTString,
                             -1,
                             WideCharStr.data(),
                             RequiredSize))
        throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                              TEXT("MultiByteToWideChar failed."));

    while (WideCharStr.back() == L'\x00')
        WideCharStr.pop_back();

    RequiredSize = WideCharToMultiByte(CodePage,
                                       NULL,
                                       WideCharStr.c_str(),
                                       -1,
                                       NULL,
                                       0,
                                       NULL,
                                       NULL);
    if (RequiredSize == 0)
        throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                              TEXT("WideCharToMultiByte failed."));

    MultiByteStr.resize(RequiredSize);

    if (!WideCharToMultiByte(CodePage,
                             NULL,
                             WideCharStr.c_str(),
                             -1,
                             MultiByteStr.data(),
                             RequiredSize,
                             NULL,
                             NULL))
        throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                              TEXT("WideCharToMultiByte failed."));

    while (MultiByteStr.back() == '\x00')
        MultiByteStr.pop_back();
#endif
    return MultiByteStr;
}

std::string TStringEncode(const TString& RefTStr, UINT CodePage) {
    std::string MultiByteStr;
    int RequiredSize;
#ifdef _UNICODE
    RequiredSize = WideCharToMultiByte(CodePage,
                                       NULL,
                                       RefTStr.c_str(),
                                       -1,
                                       NULL,
                                       0,
                                       NULL,
                                       NULL);
    if (RequiredSize == 0)
        throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                              TEXT("WideCharToMultiByte failed."));

    MultiByteStr.resize(RequiredSize);

    if (!WideCharToMultiByte(CodePage,
                             NULL,
                             RefTStr.c_str(),
                             -1,
                             MultiByteStr.data(),
                             RequiredSize,
                             NULL,
                             NULL))
        throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                              TEXT("WideCharToMultiByte failed."));

    while (MultiByteStr.back() == '\x00')
        MultiByteStr.pop_back();
#else
    if (CodePage == CP_ACP)
        return RefTStr;

    std::wstring WideCharStr;
    RequiredSize = MultiByteToWideChar(CP_ACP,
                                       NULL,
                                       RefTStr.c_str(),
                                       -1,
                                       NULL,
                                       0);
    if (RequiredSize == 0)
        throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                              TEXT("MultiByteToWideChar failed."));

    WideCharStr.resize(RequiredSize);

    if (!MultiByteToWideChar(CP_ACP,
                             NULL,
                             RefTStr.c_str(),
                             -1,
                             WideCharStr.data(),
                             RequiredSize))
        throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                              TEXT("MultiByteToWideChar failed."));

    while (WideCharStr.back() == L'\x00')
        WideCharStr.pop_back();

    RequiredSize = WideCharToMultiByte(CodePage,
                                       NULL,
                                       WideCharStr.c_str(),
                                       -1,
                                       NULL,
                                       0,
                                       NULL,
                                       NULL);
    if (RequiredSize == 0)
        throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                              TEXT("WideCharToMultiByte failed."));

    MultiByteStr.resize(RequiredSize);

    if (!WideCharToMultiByte(CodePage,
                             NULL,
                             WideCharStr.c_str(),
                             -1,
                             MultiByteStr.data(),
                             RequiredSize,
                             NULL,
                             NULL))
        throw SystemException(__BASE_FILE__, __LINE__, GetLastError(),
                              TEXT("WideCharToMultiByte failed."));

    while (MultiByteStr.back() == '\x00')
        MultiByteStr.pop_back();
#endif
    return MultiByteStr;
}

TString TStringDecode(PCSTR LpMultiByteStr, UINT CodePage) {
    return TStringBuilder(LpMultiByteStr, CodePage);
}

TString TStringDecode(const std::string& RefMultiByteStr, UINT CodePage) {
    return TStringBuilder(RefMultiByteStr.c_str(), CodePage);
}


code:
#pragma once
#include <tchar.h>
#include <windows.h>
#include <string>

//
// A TString can be either multiple-bytes string or wide-char string.
// When multiple-bytes string, the code page is CP_ACP.
// When wide-char string, it is UTF-16-LE encoded string.
//
#ifdef _UNICODE
using TString = std::wstring;
#else
using TString = std::string;
#endif

//
// For a multiple-bytes string, the default code-page is CP_ACP.
// Of course, you can specify code-page to override it.
//
TString TStringBuilder(PCSTR LpMultiByteStr, UINT CodePage = CP_ACP);

//
// For a wide-char string, it must be UTF-16-LE encoded.
// So `CodePage` is not needed.
//
TString TStringBuilder(PCWSTR LpWideCharStr);

//
// For a multiple-bytes string, the default code-page is CP_ACP.
// Of course, you can specify code-page to override it.
//
TString TStringBuilder(const std::string& RefMultiByteStr, UINT CodePage = CP_ACP);

//
// For a wide-char string, it must be UTF-16-LE encoded.
// So `CodePage` is not needed.
//
TString TStringBuilder(const std::wstring& RefWideCharStr);

//
// Convert a TString to a multiple-bytes string with specified code-page.
//
std::string TStringEncode(PTSTR LpTString, UINT CodePage);
std::string TStringEncode(const TString& RefTStr, UINT CodePage);

//
// Convert a multiple-bytes string to a TString with specified code-page.
//
TString TStringDecode(PCSTR LpMultiByteStr, UINT CodePage = CP_ACP);
TString TStringDecode(const std::string& RefMultiByteStr, UINT CodePage = CP_ACP);

//
// Format function for TString
//
template<typename... __Ts>
TString TStringFormat(const TString& Format, __Ts&&... Args) {
    TString s;
    s.resize(_sctprintf(Format.c_str(), std::forward<__Ts>(Args)...) + 1);
    s.resize(_sntprintf_s(s.data(), s.capacity(), _TRUNCATE, Format.c_str(), std::forward<__Ts>(Args)...));
    return s;
}


code:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Label="Globals">
    <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
    <HasSharedItems>true</HasSharedItems>
    <ItemsProjectGuid>{6aa392e2-b540-4ab5-9bfd-40ad964b209a}</ItemsProjectGuid>
  </PropertyGroup>
  <ItemDefinitionGroup>
    <ClCompile>
      <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories>
    </ClCompile>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ProjectCapability Include="SourceItemsFromImports" />
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="$(MSBuildThisFileDirectory)TString.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="$(MSBuildThisFileDirectory)Exception.hpp" />
    <ClInclude Include="$(MSBuildThisFileDirectory)ExceptionSystem.hpp" />
    <ClInclude Include="$(MSBuildThisFileDirectory)ResourceObject.hpp" />
    <ClInclude Include="$(MSBuildThisFileDirectory)RSACipher.hpp" />
    <ClInclude Include="$(MSBuildThisFileDirectory)TString.hpp" />
  </ItemGroup>
</Project>


code:
This file credits all the contributors of the Capstone engine project.

Key developers
==============
1. Nguyen Anh Quynh <aquynh -at- gmail.com>
	- Core engine
	- Bindings: Python, Ruby, OCaml, Java, C#

2. Tan Sheng Di <shengdi -at- coseinc.com>
	- Bindings: Ruby

3. Ben Nagy <ben -at- coseinc.com>
	- Bindings: Ruby, Go

4. Dang Hoang Vu <dang.hvu -at- gmail.com>
	- Bindings: Java

Beta testers (in random order)
==============================
Pancake
Van Hauser
FX of Phenoelit
The Grugq, The Grugq   <-- our hero for submitting the first ever patch!
Isaac Dawson, Veracode Inc
Patroklos Argyroudis, Census Inc. (http://census-labs.com)
Attila Suszter
Le Dinh Long
Nicolas Ruff
Gunther
Alex Ionescu, Winsider Seminars & Solutions Inc.
Snare
Daniel Godas-Lopez
Joshua J. Drake
Edgar Barbosa
Ralf-Philipp Weinmann
Hugo Fortier
Joxean Koret
Bruce Dang
Andrew Dunham

Contributors (in no particular order)
=====================================
(Please let us know if you want to have your name here)

Ole André Vadla Ravnås (author of the 100th Pull-Request in our Github repo, thanks!)
Axel "0vercl0k" Souchet (@0vercl0k) & Alex Ionescu: port to MSVC.
Daniel Pistelli: Cmake support.
Peter Hlavaty: integrate Capstone for Windows kernel drivers.
Guillaume Jeanne: Ocaml binding.
Martin Tofall, Obsidium Software: Optimize X86 performance & size + x86 encoding features.
David Martínez Moreno & Hilko Bengen: Debian package.
Félix Cloutier: Xcode project.
Benoit Lecocq: OpenBSD package.
Christophe Avoinne (Hlide): Improve memory management for better performance.
Michael Cohen & Nguyen Tan Cong: Python module installer.
Adel Gadllah, Francisco Alonso & Stefan Cornelius: RPM package.
Felix Gröbert (Google): fuzz testing harness.
Xipiter LLC: Capstone logo redesigned.
Satoshi Tanda: Support Windows kernel driver.
Tang Yuhang: cstool.
Andrew Dutcher: better Python setup.
Ruben Boonen: PowerShell binding.
David Zimmer: VB6 binding.
Philippe Antoine: Integration with oss-fuzz and various fixes.
Bui Dinh Cuong: Explicit registers accessed for Arm64.
Vincent Bénony: Explicit registers accessed for X86.
Adel Gadllah, Francisco Alonso & Stefan Cornelius: RPM package.
Felix Gröbert (Google): fuzz testing harness.
Daniel Collin & Nicolas Planel: M68K architecture.
Pranith Kumar: Explicit registers accessed for Arm64.
Xipiter LLC: Capstone logo redesigned.
Satoshi Tanda: Support Windows kernel driver.
Koutheir Attouchi: Support for Windows CE.
Fotis Loukos: TMS320C64x architecture.
Wolfgang Schwotzer: M680X architecture.
Philippe Antoine: Integration with oss-fuzz and various fixes.
Stephen Eckels (stevemk14ebr): x86 encoding features


code:
This file details the changelog of Capstone.

---------------------------------
Version 4.0.1: January 10th, 2019

[ Core ]

- Fix some issues for packaging (Debian, Gentoo).
- Better support for building with Mingw.
- cstool has new option -s to turn on skipdata mode.
- cstool -v now report build settings of the core.
- Add suite/capstone_get_setup.c so users can integrate with their own code
  to retrieve Capstone settings at build time.

[ Arm ]

- Fix 4.0 regression: the `tbh [r0, r1, lsl #1]` instruction sets the operand.shift.value back again (see #1317)
- Remove ARM_REG_PC group for BX instruction.

[ X86 ]

- Fix: endbr32 and endbr64 instructions are now properly decoded in both CS_MODE_32 and CS_MODE_64  (#1129)

[ M680X ]

- Fix some issues reported by clang-analyzer (#1329).

[ Python ]

- Fix skipdata setup.
- Add getter/setter for skipdata_mnem, skipdata_callback.

---------------------------------
Version 4.0: December 18th, 2018

[ Core ]

- New APIs: cs_regs_access()
- Add new options for cs_option(): CS_OPT_MNEMONIC & CS_OPT_UNSIGNED & CS_OPT_SYNTAX_MASM.
- Various updates & bugfixes for all architectures.
- Add 4 new architectures: EVM, M68K, M680X & TMS320C64x.
- Add new group types: CS_GRP_PRIVILEGE & CS_GRP_BRANCH_RELATIVE.
- Add new error types: CS_ERR_X86_MASM.

[ X86 ]

- Add XOP code condition type in x86_xop_cc.
- Add some info on encoding to cs_x86 in cs_x86_encoding.
- Add register flags update in cs_x86.{eflags, fpu_flags}
- Change cs_x86.disp type from int32_t to int64_t.
- Add new groups: X86_GRP_VM & X86_GRP_FPU.
- Lots of new instructions (AVX)

[ ARM64 ]

- Add instruction ARM64_INS_NEGS & ARM64_INS_NGCS.

[ Mips ]

- Add mode CS_MODE_MIPS2.

[ PPC ]

- Change cs_ppc_op.imm type from int32_t to int64_t.
- Add new groups: PPC_GRP_ICBT, PPC_GRP_P8ALTIVEC, PPC_GRP_P8VECTOR & PPC_GRP_QPX.
- Lots of new instructions (QPX among them)

[ Sparc ]

- Change cs_sparc_op.imm type from int32_t to int64_t.

[ Binding ]

- New bindings: PowerShell & VB6

---------------------------------
Version 3.0.5: July 18th, 2018

[ Core ]

- Fix the include path for Android builds when building cstool.
- Add posibility to disable universal build for Mac OS.
- cstool: Separate instruction bytes by spaces.
- Fix code path of pkg-config in Cmake.
- Update XCode project for XCode 9.1.
- Add Cortex-M support to cstool.
- Cmake forces to be build using MT with MSVC.
- Better support for Mac OS kernel.

[ X86 ]

- Fix some issues in handling EVEX & VEX3 instructions.
- Fix immediate operand for AND instruction in ATT mode.
- Fix ATT syntax when imm operand is 0.
- Better handle XACQUIRE/XRELEASE.
- Fix imm operand of RETF.

[ ARM ]

- Fix an integer overlow bug.

[ ARM64 ]

- Bug fix for incorrect operand type in certain load/store instructions.

[ Mips ]

- Mode CS_MODE_MIPS32R6 automatically sets CS_MODE_32

[ PPC ]

- Fix endian check.

[ Sparc ]

- Fix an integer overlow bug.

[ SystemZ ]

- Fix an integer overlow bug.

[ Python binding ]

- Raise error on accessing irrelevant data fields if skipdata & detail modes are enable.

---------------------------------
Version 3.0.5-rc3: July 31st, 2017

[ Core ]

- Fix compilation for MacOS kernel extension
- cstool to support armbe and arm64be modes
- Add nmake.bat for Windows build
- Fix an integer overflow for Windows kernel driver
- Support to embedded Capstone into MacOS kernel
- cstool: fix mips64 mode
- Fix a compiling error in MS Visual Studio 2015
- Install pkgconfig file with CMake build
- Fix SOVERSION property of CMake build
- Properly handle switching to Endian mode at run-time for Arm, Arm64, Mips & Sparc
- Fix MingW build
- Better handle CMake installation for Linux 64bit

[ X86 ]

- Support BND prefix of Intel MPX extension
- Correct operand size for CALL/JMP in 64bit mode with prefix 0x66
- LOCK NOP is a valid instruction
- Fix ATT syntax for instruction with zero offset segment register
- LES/LDS are invalid in 64bit mode
- Fix number of operands for some MOV instructions

[ ARM ]

- Fix POP reg to update SP register
- Update flags for UADD8 instruction

[ ARM64 ]

- Better performance with new lookup table
- Handle system registers added in ARMv8.1/2

[ Java binding ]

- Better handle input with invalid code

[ Visual Basic binding ]

- New binding

---------------------------------
Version 3.0.5-rc2: March 2nd, 2017

[ Core ]

- Fix build for Visual Studio 2012
- Fix X86_REL_ADDR macro
- Add CS_VERSION_MAJOR, CS_VERSION_MINOR, CS_VERSION_EXTRA
- Better support for embedding Capstone into Windows kernel drivers
- Support to embedded Capstone into MacOS kernel
- Support MacOS 10.11 and up
- Better support for Cygwin
- Support build packages for FreeBSD & DragonflyBSD
- Add a command-line tool "cstool"
- Properly handle switching to Endian mode at run-time for Arm, Arm64, Mips & Sparc

[ X86 ]

- Some random 16-bit code can be handled wrongly.
- Remove abundant operand type X86_OP_FP
- Fix instructions MOVQ, LOOP, LOOPE, LOOPNE, CALL/JMP rel16, REPNE LODSD, MOV *AX, MOFFS, FAR JMP/CALL
- Add X86_REG_EFLAGS for STC and STD
- Fix instruction attributes for SYSEXIT, MOVW, ROL, LGS, SLDT
- Rename registers ST0-ST7 to be consistent with asm output

[ ARM ]

- Properly handle IT instruction
- Fix LDRSB
- Fix writeback for LDR
- Fix Thumb BigEndian setup

[ ARM64 ]

- Fix arith extender
- Fix writeback for LDR
- Rename enum arm64_mrs_reg to arm64_sysreg

[ PowerPC ]

- Print 0 offset for memory operand

[ Sparc ]

- Fix POPC instruction

[ Python binding ]

- Better PyPy support
- Add __version__
- Better support for Python 3
- Fix CS_SKIPDATA_CALLBACK prototype
- Cast skipdata function inside binding to simplify the API

[ Java binding ]

- Better handle input with invalid code

[ PowerShell ]

- New binding

---------------------------------
Version 3.0.4: July 15th, 2015

[ Library ]

- Improve cross-compile for Android using Android NDK.
- Support cross-compile for AArch64 Android (with Linux GCC).
- Removed osxkernel_inttypes.h that is incompatible with BSD license.
- Make it possible to compile with CC having a space inside (like "ccache gcc").

[ X86 ]

- Fix a null pointer dereference bug on handling code with special prefixes.
- Properly handle AL/AX/EAX operand for OUT instruction in AT&T syntax.
- Print immediate operand in positive form in some algorithm instructions.
- Properly decode some SSE instructions.

[ PowerPC ]

- Fixed a memory corruption bug.
- Fixed a memory corruption bug for the engine built in DIET mode.

[ Mips ]

- Fixed instruction ID of SUBU instruction.
- Fixed a memory corruption bug.

[ Arm ]

- Fixed a memory corruption bug on IT instruction.

[ XCore ]

- Fixed a memory corruption bug when instruction has a memory operand.

[ Python ]

- Support Virtualenv.
- setup.py supports option --user if not in a virtualenv to allow for local usage.
- Properly handle the destruction of Cs object in the case the shared library
  was already unloaded.

---------------------------------
Version 3.0.3: May 08th, 2015

[ Library ]

- Support to embed into Mac OS X kernel extensions.
- Now it is possible to compile Capstone with older C compilers, such as
  GCC 4.8 on Ubuntu 12.04.
- Add "test_iter" to MSVC project.

[ X86 ]

- All shifted instructions SHL, SHR, SAL, SAR, RCL, RCR, ROL & ROR now support
  $1 as first operand in *AT&T* syntax (so we have "rcll $1, %edx" instead of
  "rcll %edx").
- CMPXCHG16B is a valid instruction with LOCK prefix.
- Fixed a segfault on the input of 0xF3.

[ Arm ]

- BLX instruction modifies PC & LR registers.

[ Sparc ]

- Improved displacement decoding for sparc banching instructions.

[ Python binding ]

- Fix for Cython so it can properly initialize.
- X86Op.avx_zero_mask now has c_bool type, but not c_uint8 type.
- Properly support compile with Cygwin & install binding (setup.py).

---------------------------------
Version 3.0.2: March 11th, 2015

[ Library ]

- On *nix, only export symbols that are part of the API (instead of all
  the internal symbols).

[ X86 ]

- Do not consider 0xF2 as REPNE prefix if it is a part of instruction encoding.
- Fix implicit registers read/written & instruction groups of some instructions.
- More flexible on the order of prefixes, so better handle some tricky
  instructions.
- REPNE prefix can go with STOS & MOVS instructions.
- Fix a compilation bug for X86_REDUCE mode.
- Fix operand size of instructions with operand PTR []

[ Arm ]

- Fix a bug where arm_op_mem.disp is wrongly calculated (in DETAIL mode).
- Fix a bug on handling the If-Then block.

[ Mips ]

- Sanity check for the input size for MIPS64 mode.

[ MSVC ]

- Compile capstone.dll with static runtime MSVCR built in.

[ Python binding ]

- Fix a compiling issue of Cython binding with gcc 4.9.

---------------------------------
Version 3.0.1: February 03rd, 2015

[ X86 ]

- Properly handle LOCK, REP, REPE & REPNE prefixes.
- Handle undocumented immediates for SSE's (V)CMPPS/PD/SS/SD instructions.
- Print LJUMP/LCALL without * as prefix for Intel syntax.
- Handle REX prefix properly for segment/MMX related instructions (x86_64).
- Instruction with length > 15 is consider invalid.
- Handle some tricky encodings for instructions MOVSXD, FXCH, FCOM, FCOMP,
  FSTP, FSTPNCE, NOP.
- Handle some tricky code for some X86_64 instructions with REX prefix.
- Add missing operands in detail mode for PUSH , POP , IN/OUT reg, reg
- MOV32ms & MOV32sm should reference word rather than dword.

[ Arm64 ]

- BL & BLR instructions do not read SP register.
- Print absolute (rather than relative) address for instructions B, BL,
  CBNZ, ADR.

[ Arm ]

- Instructions ADC & SBC do not update flags.
- BL & BLX do not read SP, but PC register.
- Alias LDR instruction with operands [sp], 4 to POP.
- Print immediate operand of MVN instruction in positive hexadecimal form.

[ PowerPC ]

- Fix some compilation bugs when DIET mode is enable.
- Populate SLWI/SRWI instruction details with SH operand.

[ Python binding ]

- Fix a Cython bug when CsInsn.bytes returns a shorten array of bytes.
- Fixed a memory leak for Cython disasm functions when we immaturely quit
  the enumeration of disassembled instructions.
- Fix a NULL memory access issue when SKIPDATA & Detail modes are enable
  at the same time.
- Fix a memory leaking bug when when we stop enumeration over the disassembled
  instructions prematurely.
- Export generic operand types & groups (CS_OP_xxx & CS_GRP_xxx).

---------------------------------
Version 3.0: November 19th, 2014

[ API ]

- New API: cs_disasm_iter & cs_malloc. See docs/README for tutorials.
- Renamed cs_disasm_ex to cs_disasm (cs_disasm_ex is still supported, but
  marked obsolete to be removed in future)
- Support SKIPDATA mode, so Capstone can jump over unknown data and keep going
  from the next legitimate instruction. See docs/README for tutorials.
- More details provided in cs_detail struct for all architectures.
- API version was bumped to 3.0.

[ Bindings ]

- Python binding supports Python3 (besides Python2).
- Support Ocaml binding.
- Java: add close() method to be used to deinitialize a Capstone object when
  no longer use it.

[ Architectures ]

- New architectures: Sparc, SystemZ & XCore.
- Important bugfixes for Arm, Arm64, Mips, PowerPC & X86.
- Support more instructions for Arm, Arm64, Mips, PowerPC & X86.
- Always expose absolute addresses rather than relative addresses (Arm, Arm64,
  Mips, PPC, Sparc, X86).
- Use common instruction operand types REG, IMM, MEM & FP across all
  architectures (to enable cross-architecture analysis).
- Use common instruction group types across all architectures (to enable
  cross-architecture analysis).

[ X86 ]

- X86 engine is mature & handles all the malware tricks (that we are aware of).
- Added a lot of new instructions (such as AVX512, 3DNow, etc).
- Add prefix symbols X86_PREFIX_REP/REPNE/LOCK/CS/DS/SS/FS/GS/ES/OPSIZE/ADDRSIZE.
- Print immediate in positive form & hexadecimal for AND/OR/XOR instructions.
- More friendly disassembly for JMP16i (in the form segment:offset)

[ Mips ]

- Engine added supports for new hardware modes: Mips32R6 (CS_MODE_MIPS32R6) &
  MipsGP64 (CS_MODE_MIPSGP64).
- Removed the ABI-only mode CS_MODE_N64.
- New modes CS_MODE_MIPS32 & CS_MODE_MIPS64 (to use instead of CS_MODE_32 &
  CS_MODE_64).

[ ARM ]

- Support new mode CS_MODE_V8 for Armv8 A32 encodings.
- Print immediate in positive form & hexadecimal for AND/ORR/EOR/BIC instructions

[ ARM64 ]

- Print immediate in hexadecimal for AND/ORR/EOR/TST instructions.

[ PowerPC ]

- Do not print a dot in front of absolute address.

[ Other features ]

- Support for Microsoft Visual Studio (so enable Windows native compilation).
- Support CMake compilation.
- Cross-compile for Android.
- Build libraries/tests using XCode project
- Much faster, while consuming less memory for all architectures.

---------------------------------
Version 2.1.2: April 3rd, 2014

This is a stable release to fix some bugs deep in the core. There is no update
to any architectures or bindings, so bindings version 2.1 can be used with this
version 2.1.2 just fine.

[ Core changes]

- Support cross-compilation for all iDevices (iPhone/iPad/iPod).
- X86: do not print memory offset in negative form.
- Fix a bug in X86 when Capstone cannot handle short instruction.
- Print negative number above -9 without prefix 0x (arm64, mips, arm).
- Correct the SONAME setup for library versioning (Linux, *BSD, Solaris).
- Set library versioning for dylib of OSX.

---------------------------------
Version 2.1.1: March 13th, 2014

This is a stable release to fix some bugs deep in the core. There is no update
to any architectures or bindings, so bindings version 2.1 can be used with this
version 2.1.1 just fine.

[ Core changes]

- Fix a buffer overflow bug in Thumb mode (ARM). Some special input can
  trigger this flaw.
- Fix a crash issue when embedding Capstone into OSX kernel. This should
  also enable Capstone to be embedded into other systems with limited stack
  memory size such as Linux kernel or some firmwares.
- Use a proper SONAME for library versioning (Linux).

---------------------------------
Version 2.1: March 5th, 2014

[ API changes ]

- API version has been bumped to 2.1.
- Change prototype of cs_close() to be able to invalidate closed handle.
  See http://capstone-engine.org/version_2.1_API.html for more information.
- Extend cs_support() to handle more query types, not only about supported
  architectures. This change is backward compatible, however, so existent code
  do not need to be modified to support this.
- New query type CS_SUPPORT_DIET for cs_support() to ask about diet status of
  the engine.
- New error code CS_ERR_DIET to report errors about newly added diet mode.
- New error code CS_ERR_VERSION to report issue of incompatible versions between
  bindings & core engine.

[ Core changes ]

- On memory usage, Capstone uses about 40% less memory, while still faster
  than version 2.0.
- All architectures are much smaller: binaries size reduce at least 30%.
  Especially, X86-only binary reduces from 1.9MB to just 720KB.
- Support "diet" mode, in which engine size is further reduced (by around 40%)
  for embedding purpose. The price to pay is that we have to sacrifice some
  non-critical data fields. See http://capstone-engine.org/diet.html for more
  details.

[ Architectures ]

- Update all 5 architectures to fix bugs.
- PowerPC:
	- New instructions: FMR & MSYNC.
- Mips:
	- New instruction: DLSA
- X86:
	- Properly handle AVX-512 instructions.
	- New instructions: PSETPM, SALC, INT1, GETSEC.
	- Fix some memory leaking issues in case of prefixed instructions such
	  as LOCK, REP, REPNE.

[ Python binding ]

- Verify the core version at initialization time. Refuse to run if its version
  is different from the core's version.
- New API disasm_lite() added to Cs class. This light API only returns tuples of
  (address, size, mnemonic, op_str), rather than list of CsInsn objects. This
  improves performance by around 30% in some benchmarks.
- New API version_bind() returns binding's version, which might differ from
  the core's API version if the binding is out-of-date.
- New API debug() returns information on Cython support, diet status & archs
  compiled in.
- Fixed some memory leaking bugs for Cython binding.
- Fix a bug crashing Cython code when accessing @regs_read/regs_write/groups.
- Support diet mode.

[ Java binding ]

- Fix some memory leaking bugs.
- New API version() returns combined version.
- Support diet mode.
- Better support for detail option.

[ Miscellaneous ]

- make.sh now can uninstall the core engine. This is done with:

	$ sudo ./make.sh uninstall

----------------------------------
Version 2.0: January 22nd, 2014

Release 2.0 deprecates verison 1.0 and brings a lot of crucial changes.

[ API changes ]

- API version has been bumped to 2.0 (see cs_version() API)
- New API cs_strerror(errno) returns a string describing error code given
  in its only argument.
- cs_version() now returns combined version encoding both major & minor versions.
- New option CS_OPT_MODE allows to change engine’s mode at run-time with
  cs_option().
- New option CS_OPT_MEM allows to specify user-defined functions for dynamically
  memory management used internally by Capstone. This is useful to embed Capstone
  into special environments such as kernel or firware.
- New API cs_support() can be used to check if this lib supports a particular
  architecture (this is necessary since we now allow to choose which architectures
  to compile in).
- The detail option is OFF by default now. To get detail information, it should be
  explicitly turned ON. The details then can be accessed using cs_insn.detail
  pointer (to newly added structure cs_detail)

[ Core changes ]

- On memory usage, Capstone uses much less memory, but a lot faster now.
- User now can choose which architectures to be supported by modifying config.mk
  before compiling/installing.

[ Architectures ]

- Arm
     - Support Big-Endian mode (besides Little-Endian mode).
     - Support friendly register, so instead of output sub "r12,r11,0x14",
	 we have "sub ip,fp,0x14".
- Arm64: support Big-Endian mode (besides Little-Endian mode).
- PowerPC: newly added.
- Mips: support friendly register, so instead of output "srl $2,$1,0x1f",
     we have "srl $v0,$at,0x1f".
- X86: bug fixes.

[ Python binding ]

- Python binding is vastly improved in performance: around 3 ~ 4 times faster
  than in 1.0.
- Cython support has been added, which can further speed up over the default
  pure Python binding (up to 30% in some cases)
- Function cs_disasm_quick() & Cs.disasm() now use generator (rather than a list)
  to return succesfully disassembled instructions. This improves the performance
  and reduces memory usage.

[ Java binding ]

- Better performance & bug fixes.

[ Miscellaneous ]

- Fixed some installation issues with Gentoo Linux.
- Capstone now can easily compile/install on all *nix, including Linux, OSX,
  {Net, Free, Open}BSD & Solaris.

----------------------------------
[Version 1.0]: December 18th, 2013

- Initial public release.


code:
==============================================================================
LLVM Release License
==============================================================================
University of Illinois/NCSA
Open Source License

Copyright (c) 2003-2013 University of Illinois at Urbana-Champaign.
All rights reserved.

Developed by:

    LLVM Team

    University of Illinois at Urbana-Champaign

    http://llvm.org

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal with
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimers.

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimers in the
      documentation and/or other materials provided with the distribution.

    * Neither the names of the LLVM Team, University of Illinois at
      Urbana-Champaign, nor the names of its contributors may be used to
      endorse or promote products derived from this Software without specific
      prior written permission.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
SOFTWARE.

==============================================================================
Copyrights and Licenses for Third Party Software Distributed with LLVM:
==============================================================================
The LLVM software contains code written by third parties.  Such software will
have its own individual LICENSE.TXT file in the directory in which it appears.
This file will describe the copyrights, license, and restrictions which apply
to that code.

The disclaimer of warranty in the University of Illinois Open Source License
applies to all code in the LLVM Distribution, and nothing in any of the
other licenses gives permission to use the names of the LLVM Team or the
University of Illinois to endorse or promote products derived from this
Software.

The following pieces of software have additional or alternate copyrights,
licenses, and/or restrictions:

Program             Directory
-------             ---------
Autoconf            llvm/autoconf
                    llvm/projects/ModuleMaker/autoconf
                    llvm/projects/sample/autoconf
Google Test         llvm/utils/unittest/googletest
OpenBSD regex       llvm/lib/Support/{reg*, COPYRIGHT.regex}
pyyaml tests        llvm/test/YAMLParser/{*.data, LICENSE.TXT}
ARM contributions   llvm/lib/Target/ARM/LICENSE.TXT
md5 contributions   llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h


code:
Capstone Engine
===============

[![Build Status](https://travis-ci.org/aquynh/capstone.svg?branch=next)](https://travis-ci.org/aquynh/capstone)
[![Build status](https://ci.appveyor.com/api/projects/status/a4wvbn89wu3pinas/branch/next?svg=true)](https://ci.appveyor.com/project/aquynh/capstone/branch/next)

Capstone is a disassembly framework with the target of becoming the ultimate
disasm engine for binary analysis and reversing in the security community.

Created by Nguyen Anh Quynh, then developed and maintained by a small community,
Capstone offers some unparalleled features:

- Support multiple hardware architectures: ARM, ARM64 (ARMv8), Ethereum VM, M68K,
  Mips, PPC, Sparc, SystemZ, TMS320C64X, M680X, XCore and X86 (including X86_64).

- Having clean/simple/lightweight/intuitive architecture-neutral API.

- Provide details on disassembled instruction (called “decomposer” by others).

- Provide semantics of the disassembled instruction, such as list of implicit
  registers read & written.

- Implemented in pure C language, with lightweight bindings for D, Clojure, F#,
  Common Lisp, Visual Basic, PHP, PowerShell, Emacs, Haskell, Perl, Python,
  Ruby, C#, NodeJS, Java, GO, C++, OCaml, Lua, Rust, Delphi, Free Pascal & Vala
  ready either in main code, or provided externally by the community).

- Native support for all popular platforms: Windows, Mac OSX, iOS, Android,
  Linux, \*BSD, Solaris, etc.

- Thread-safe by design.

- Special support for embedding into firmware or OS kernel.

- High performance & suitable for malware analysis (capable of handling various
  X86 malware tricks).

- Distributed under the open source BSD license.

Further information is available at http://www.capstone-engine.org

Compile
-------

See COMPILE.TXT file for how to compile and install Capstone.

Documentation
-------------

See docs/README for how to customize & program your own tools with Capstone.

Hack
----

See HACK.TXT file for the structure of the source code.

License
-------

This project is released under the BSD license. If you redistribute the binary
or source code of Capstone, please attach file LICENSE.TXT with your products.


code:
* Version 4.0.1 - January 10th, 2019

Release 4.0.1 was sponsored by the following companies (in no particular order).

- NowSecure: https://www.nowsecure.com
- Verichains: https://verichains.io
- Vsec: https://vsec.com.vn

-----------------------------------
* Version 4.0 - December 18th, 2018

Capstone 4.0 version marks 5 years of the project!
This release was sponsored by the following companies (in no particular order).

- Thinkst Canary: https://canary.tools
- NowSecure: https://www.nowsecure.com
- ECQ: https://e-cq.net
- Senrio: https://senr.io
- GracefulBits: https://gracefulbits.com
- Catena Cyber: https://catenacyber.fr