13 Commits
Author SHA1 Message Date
Double Sine f701a80b8f 4.0 -> 4.1 2019-09-28 01:57:07 +08:00
Double Sine ec41feca91 Add new library requirement 2019-09-28 00:58:14 +08:00
Double Sine c36f44dd1b Fix typo 2019-09-28 00:52:07 +08:00
Double Sine 70f49762cc Add PatchSolution4 for Navicat Modeler 3 2019-09-28 00:49:34 +08:00
Double Sine c8160cb7c5 Add NumberOfSections() for ImageInterpreter 2019-09-28 00:20:43 +08:00
Double Sine c173b0ff50 Refactor ImageInterpreter 2019-09-27 16:33:50 +08:00
Double Sine 028c90b794 size_t -> cs_opt_value 2019-09-26 17:55:39 +08:00
Double SineandGitHub aac8ffd367 Merge pull request #337 from Deltafox79/windows
Modeler 3 Support
2019-09-25 22:06:26 +08:00
Paolo 953da17799 Modeler 3 Support
Support for Modeler 3 Serial Generator
2019-09-25 14:46:18 +02:00
Double Sine 33d75ddb12 fix typo 2019-09-06 23:35:31 +08:00
Double Sine 0f9e750a31 Split to multiple commands 2019-09-06 23:33:41 +08:00
Double Sine a7d282d608 Use 'latest' tag in download link 2019-09-06 23:21:22 +08:00
Double Sine e83a73b3c9 Upload code for v4.0 2019-09-06 22:35:29 +08:00
429 changed files with 8928 additions and 121069 deletions
+3 -288
View File
@@ -1,289 +1,4 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Typescript v1 declaration files
typings/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
MailDataReciever/Renci.SshNet.dll
.vscode/
bin/
obj/
+18 -371
View File
@@ -1,389 +1,36 @@
# Navicat Keygen
[中文版README](README.zh-CN.md)
[中文版README](README.zh-CN.md)
This repository will tell you how Navicat offline activation works.
This repository will tell you how Navicat offline activation works.
## 1. Keyword Explanation.
Previous code is archived in [`windows-archived`](https://github.com/DoubleLabyrinth/navicat-keygen/tree/windows-archived) branch for the reason that previous code contains 3rd binary libraries and it gets quite big :-(
* __Navicat Activation Public Key__
When you git-clone this repo, please add `--single-branch` flag so that archived branch won't be cloned to your computer, which saves your time and disk.
It is a __RSA-2048__ public key that Navicat used to encrypt or decrypt offline activation information.
```console
$ git clone -b windows --single-branch https://github.com/DoubleLabyrinth/navicat-keygen.git
```
It is stored in __navicat.exe__ as a kind of resource called __RCData__. The resource name is `"ActivationPubKey"`. You can see it by a kind of software [___Resource Hacker___](http://www.angusj.com/resourcehacker/). The concrete content is:
## 1. How does it work?
> -----BEGIN PUBLIC KEY-----
> MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw1dqF3SkCaAAmMzs889I
> qdW9M2dIdh3jG9yPcmLnmJiGpBF4E9VHSMGe8oPAy2kJDmdNt4BcEygvssEfginv
> a5t5jm352UAoDosUJkTXGQhpAWMF4fBmBpO3EedG62rOsqMBgmSdAyxCSPBRJIOF
> R0QgZFbRnU0frj34fiVmgYiLuZSAmIbs8ZxiHPdp1oD4tUpvsFci4QJtYNjNnGU2
> WPH6rvChGl1IRKrxMtqLielsvajUjyrgOC6NmymYMvZNER3htFEtL1eQbCyTfDmt
> YyQ1Wt4Ot12lxf0wVIR5mcGN7XCXJRHOFHSf1gzXWabRSvmt1nrl7sW6cjxljuuQ
> awIDAQAB
> -----END PUBLIC KEY-----
see [here](doc/how-does-it-work.md)
If you have the corresponding private key, please tell me. I would be very appreciated for your generous.
## 2. How to build?
__NOTICE:__
see [here](doc/how-to-build.md).
Start from __Navicat Premium 12.0.25__, Navicat do not load this public key from resource in `navicat.exe`. Actually the public key is stored in `libcc.dll` and encrypted. And to avoid being replaced easily, the public key is split into 5 parts:
## 3. How to use?
The content below is discovered from `libcc.dll` of Navicat Premium x64 12.0.25 Simplified Chinese version. SHA256 value is `607e0a84c75966b00f3d12fa833e91d159e4f51ac51b6ba66f98d0c3cbefdce0`. I do not guaranteed that __offset__ value is absolutely correct in other versions. But __char string__ and __immediate values__ is highly possible to be found.
For Windows users, see [here](doc/how-to-use.windows.md).
1. At file offset `+ 0x1A12090` in `libcc.dll`, stored as __char string__:
For Linux users, see [here](doc/how-to-use.linux.md).
> "D75125B70767B94145B47C1CB3C0755E
> 7CCB8825C5DCE0C58ACF944E08280140
> 9A02472FAFFD1CD77864BB821AE36766
> FEEDE6A24F12662954168BFA314BD950
> 32B9D82445355ED7BC0B880887D650F5"
## 4. Contributor
2. At file offset `+ 0x59D799` in `libcc.dll`, stored as __immediate value__ in a instruction:
* Deltafox79
> 0xFE 0xEA 0xBC 0x01
* dragonflylee
In decimal: `29158142`
* zenuo
3. At file offset `+ 0x1A11DA0` in `libcc.dll`, stored as __char string__:
> "E1CED09B9C2186BF71A70C0FE2F1E0AE
> F3BD6B75277AAB20DFAF3D110F75912B
> FB63AC50EC4C48689D1502715243A79F
> 39FF2DE2BF15CE438FF885745ED54573
> 850E8A9F40EE2FF505EB7476F95ADB78
> 3B28CA374FAC4632892AB82FB3BF4715
> FCFE6E82D03731FC3762B6AAC3DF1C3B
> C646FE9CD3C62663A97EE72DB932A301
> 312B4A7633100C8CC357262C39A2B3A6
> 4B224F5276D5EDBDF0804DC3AC4B8351
> 62BB1969EAEBADC43D2511D6E0239287
> 81B167A48273B953378D3D2080CC0677
> 7E8A2364F0234B81064C5C739A8DA28D
> C5889072BF37685CBC94C2D31D0179AD
> 86D8E3AA8090D4F0B281BE37E0143746
> E6049CCC06899401264FA471C016A96C
> 79815B55BBC26B43052609D9D175FBCD
> E455392F10E51EC162F51CF732E6BB39
> 1F56BBFD8D957DF3D4C55B71CEFD54B1
> 9C16D458757373E698D7E693A8FC3981
> 5A8BF03BA05EA8C8778D38F9873D62B4
> 460F41ACF997C30E7C3AF025FA171B5F
> 5AD4D6B15E95C27F6B35AD61875E5505
> 449B4E"
4. At file offset `+ 0x59D77F` in `libcc.dll`, stored as __immediate value__ in a instruction:
> 0x59 0x08 0x01 0x00 (in decimal )
In decimal: `67673`
5. At file offset `+ 0x1A11D8C` in `libcc.dll`, stored as __char string__:
> "92933"
Then output encrypted public key with format `"%s%d%s%d%s"`, the order is the same as it list:
> D75125B70767B94145B47C1CB3C0755E7CCB8825C5DCE0C58ACF944E082801409A02472FAFFD1CD77864BB821AE36766FEEDE6A24F12662954168BFA314BD95032B9D82445355ED7BC0B880887D650F529158142E1CED09B9C2186BF71A70C0FE2F1E0AEF3BD6B75277AAB20DFAF3D110F75912BFB63AC50EC4C48689D1502715243A79F39FF2DE2BF15CE438FF885745ED54573850E8A9F40EE2FF505EB7476F95ADB783B28CA374FAC4632892AB82FB3BF4715FCFE6E82D03731FC3762B6AAC3DF1C3BC646FE9CD3C62663A97EE72DB932A301312B4A7633100C8CC357262C39A2B3A64B224F5276D5EDBDF0804DC3AC4B835162BB1969EAEBADC43D2511D6E023928781B167A48273B953378D3D2080CC06777E8A2364F0234B81064C5C739A8DA28DC5889072BF37685CBC94C2D31D0179AD86D8E3AA8090D4F0B281BE37E0143746E6049CCC06899401264FA471C016A96C79815B55BBC26B43052609D9D175FBCDE455392F10E51EC162F51CF732E6BB391F56BBFD8D957DF3D4C55B71CEFD54B19C16D458757373E698D7E693A8FC39815A8BF03BA05EA8C8778D38F9873D62B4460F41ACF997C30E7C3AF025FA171B5F5AD4D6B15E95C27F6B35AD61875E5505449B4E6767392933
This encrypted public key can be decrypted by my another repo: [how-does-navicat-encrypt-password](https://github.com/DoubleLabyrinth/how-does-navicat-encrypt-password), while the key used is `b'23970790'`
Example:
```cmd
E:\GitHub>git clone https://github.com/DoubleLabyrinth/how-does-navicat-encrypt-password.git
...
E:\GitHub>cd how-does-navicat-encrypt-password\python3
E:\GitHub\how-does-navicat-encrypt-password\python3>python
Python 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from NavicatCrypto import *
>>> cipher = Navicat11Crypto(b'23970790')
>>> print(cipher.DecryptString('D75125B70767B94145B47C1CB3C0755E7CCB8825C5DCE0C58ACF944E082801409A02472FAFFD1CD77864BB821AE36766FEEDE6A24F12662954168BFA314BD95032B9D82445355ED7BC0B880887D650F529158142E1CED09B9C2186BF71A70C0FE2F1E0AEF3BD6B75277AAB20DFAF3D110F75912BFB63AC50EC4C48689D1502715243A79F39FF2DE2BF15CE438FF885745ED54573850E8A9F40EE2FF505EB7476F95ADB783B28CA374FAC4632892AB82FB3BF4715FCFE6E82D03731FC3762B6AAC3DF1C3BC646FE9CD3C62663A97EE72DB932A301312B4A7633100C8CC357262C39A2B3A64B224F5276D5EDBDF0804DC3AC4B835162BB1969EAEBADC43D2511D6E023928781B167A48273B953378D3D2080CC06777E8A2364F0234B81064C5C739A8DA28DC5889072BF37685CBC94C2D31D0179AD86D8E3AA8090D4F0B281BE37E0143746E6049CCC06899401264FA471C016A96C79815B55BBC26B43052609D9D175FBCDE455392F10E51EC162F51CF732E6BB391F56BBFD8D957DF3D4C55B71CEFD54B19C16D458757373E698D7E693A8FC39815A8BF03BA05EA8C8778D38F9873D62B4460F41ACF997C30E7C3AF025FA171B5F5AD4D6B15E95C27F6B35AD61875E5505449B4E6767392933'))
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw1dqF3SkCaAAmMzs889I
qdW9M2dIdh3jG9yPcmLnmJiGpBF4E9VHSMGe8oPAy2kJDmdNt4BcEygvssEfginv
a5t5jm352UAoDosUJkTXGQhpAWMF4fBmBpO3EedG62rOsqMBgmSdAyxCSPBRJIOF
R0QgZFbRnU0frj34fiVmgYiLuZSAmIbs8ZxiHPdp1oD4tUpvsFci4QJtYNjNnGU2
WPH6rvChGl1IRKrxMtqLielsvajUjyrgOC6NmymYMvZNER3htFEtL1eQbCyTfDmt
YyQ1Wt4Ot12lxf0wVIR5mcGN7XCXJRHOFHSf1gzXWabRSvmt1nrl7sW6cjxljuuQ
awIDAQAB
-----END PUBLIC KEY-----
```
* __Request Code__
It is a Base64 string that represents 256-bytes-long data, while the 256-bytes-long data is the cipher text of the __offline activation information__ encrypted by __Navicat Activation Public Key__.
* __Offline Activation Request Information__
It is just a JSON-style ASCII string which contains 3 items. Respectively they are `"K"`, `"DI"` and `"P"`, which represent __snKey__, __DeviceIdentifier__ (related with your machine), __Platform__ (Appropriately speaking, it should be OS Type).
Like:
> {"K": "xxxxxxxxxxxxxxxx", "DI": "yyyyyyyyyyyyy", "P": "WIN8"}
* __Activation Code__
It is a Base64 string that represents 256-bytes-long data, while the 256-bytes-long data is the cipher text of the __offline activation response information__ encrypted by __Navicat Activation Private Key__ (so far, we don't know official activation private key).
* __Offline Activation Response Information__
Just like __Offline Activation Request Information__, it is also a JSON-style ASCII string. But it contains 5 items. Respectively they are `"K"`, `"N"`, `"O"`, `"T"`, '`DI`'.
`"K"` and `"DI"` has the same meaning mentioned in __Offline Activation Request Information__ and must be same with the corresponding items in __Offline Activation Request Information__.
`"N"`, `"O"`, `"T"` represent __Name__, __Organization__, __Time__ respectively. __Name__ and __Organization__ are string and the type of __Time__ can be string or integer (Thanks for discoveries from @Wizr, issue #10).
`"T"` can be omitted.
* __snKey__
It is a 4-block-long string, while every block is 4-chars-long.
__snKey__ is generated by 10-bytes-long data. In order to explain it easily, I use __uint8_t data[10]__ to represent the 10-bytes-long data.
1. __data[0]__ and __data[1]__ must be `0x68` and `0x2A` respectively.
These two bytes are Naivcat signature number.
2. __data[2]__, __data[3]__ and __data[4]__ can be any byte. Just set them whatever you want.
3. __data[5]__ and __data[6]__ are related with your Navicat product language.
| Language | data[5] | data[6] | Discoverer |
|------------|-----------|-----------|-----------------|
| English | 0xAC | 0x88 | |
| 简体中文 | 0xCE | 0x32 | |
| 繁體中文 | 0xAA | 0x99 | |
| 日本語 | 0xAD | 0x82 | @dragonflylee |
| Polski | 0xBB | 0x55 | @dragonflylee |
| Español | 0xAE | 0x10 | @dragonflylee |
| Français | 0xFA | 0x20 | @Deltafox79 |
| Deutsch | 0xB1 | 0x60 | @dragonflylee |
| 한국어 | 0xB5 | 0x60 | @dragonflylee |
| Русский | 0xEE | 0x16 | @dragonflylee |
| Português | 0xCD | 0x49 | @dragonflylee |
According to symbol information in __Navicat 12 for Mac x64__, these two bytes are product language signature.
4. __data[7]__ represents Navicat product ID. (Thanks @dragonflylee and @Deltafox79)
|Product Name |Enterprise|Standard|Educational|Essentials|
|---------------------|:--------:|:------:|:---------:|:--------:|
|Navicat Report Viewer|0x0B | | | |
|Navicat Data Modeler | |0x47 |0x4A | |
|Navicat Premium |0x65 | |0x66 |0x67 |
|Navicat MySQL |0x68 |0x69 |0x6A |0x6B |
|Navicat PostgreSQL |0x6C |0x6D |0x6E |0x6F |
|Navicat Oracle |0x70 |0x71 |0x72 |0x73 |
|Navicat SQL Server |0x74 |0x75 |0x76 |0x77 |
|Navicat SQLite |0x78 |0x79 |0x7A |0x7B |
|Navicat MariaDB |0x7C |0x7D |0x7E |0x7F |
|Navicat MongoDB |0x80 | | | |
5. High 4 bits of __data[8]__ represents __major version number__. Low 4 bits is unknown, but we can use it to delay activation deadline. Possible value is `0000` or `0001`.
__Example:__
For __Navicat 12 x64__: High 4 bits must be `1100`, which is the binary of number `12`.
For __Navicat 11 x64__: High 4 bits must be `1011`, which is the binary of number `11`.
6. __data[9]__ is unknown, but you can set it `0xFD` or `0xFC` or `0xFB` if you want to use __not-for-resale license__.
According to symbol information in __Navicat 12 for Mac x64__ version:
* `0xFB` is __Not-For-Resale-30-days__ license.
* `0xFC` is __Not-For-Resale-90-days__ license.
* `0xFD` is __Not-For-Resale-365-days__ license.
* `0xFE` is __Not-For-Resale__ license.
* `0xFF` is __Site__ license.
-----------------
After that. Navicat use __DES__ with __ECB mode__ to encrypt the last 8 bytes which are from __data[2]__ to __data[9]__.
The DES key is:
```cpp
unsigned char DESKey = { 0x64, 0xAD, 0xF3, 0x2F, 0xAE, 0xF2, 0x1A, 0x27 };
```
Then encode the 10-bytes-long data: __(Use Base32 encode if you just want a conclusion.)__
1. Regard __uint8_t data[10]__ as a 80-bits-long data.
If __uint8_t data[10]__ starts with `0x68` and `0x2A`, so the 80-bits-long data is `01011000 00101010......`
2. Divide the 80-bits-long data as 16 5-bits-long blocks.
If __uint8_t data[10]__ starts with `0x68` and `0x2A`, so the 80-bits-long data is `01011`, `00000`, `10101`, `0....`, ...
3. The values in every block are less than 32. Map them by a encode-table:
```cpp
char EncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
```
Then you will get a 16-char-long string.
If __uint8_t data[10]__ starts with `0x68` and `0x2A`, after encoded, it should starts with `"N"`, `"A"`, `"V"`.
4. Divide the 16-char-long string to four 4-chars-long blocks, then you get __snKey__.
## 3. Activation Process
1. Check whether __snKey__ that user inputs is legal.
2. After user clicks `Activate`, Navicat will start online activation first. If fails, users can choose offline activation.
3. Navicat will use the __snKey__ that user inputs and some information collected from user's machine to generate __Offline Activation Request Information__, then encrypt it by __Navicat Activation Public Key__ and return Base64-encoded string as __Request Code__.
4. In legal way, the __Request Code__ should be sent to Navicat official activation server by a Internet-accessible computer. And Navicat official activation server will return a legal __Activation Code__.
But now, we use keygen to play the official activation server's role.
1. According to the __Request Code__, Get `"DI"` value and `"K"` value.
2. Fill __Offline Activation Response Information__ with `"K"` value, name, organization name and `"DI"` value.
3. Encrypt __Offline Activation Response Information__ by __Navicat Activation Private Key__ and you will get 256-byte-long data.
4. Encode 256-byte-long data by Base64. The result is __Activation Code__.
5. Input __Activation Code__, then offline activation is done.
## 4. How to use
1. Download the latest release.
2. Replace __Navicat Activation Public Key__ in `navicat.exe` or `libcc.dll`.
Example:
```bash
C:\Users\DoubleSine\Github\navicat-keygen\x64\Release>navicat-patcher.exe "C:\Program Files\PremiumSoft\Navicat Premium 12" RegPrivateKey.pem
Target has been found: navicat.exe
Solution0 has been done successfully.
Keyword0 has been found: offset = +0x02048200.
Keyword1 has been found: offset = +0x006C4E29.
Keyword2 has been found: offset = +0x02047F10.
Keyword3 has been found: offset = +0x006C4E0F.
Keyword4 has been found: offset = +0x02047F04.
@Offset +0x02048200, write string:
"D75125B70767B94145B47C1CB3C0755E7CCB8825C5DCE0C58ACF944E082801409A02472FAFFD1CD77864BB821AE36766FEEDE6A24F12662954168BFA314BD95032B9D82445355ED7784ADAC1C58775D2"
@Offset +0x006C4E29, write uint32_t:
0x0520738A
@Offset +0x02047F10, write string:
"20EEA059669FE4E949F414710A6C11CF68B5318B445D2D0CA85471E9DC382F271E974315F2F3645C2613BF60669584CF0A7531B1E5D2D281097E32A6B17286E8A9BDD06A17A036BC8949C9069CA3A166C251D325A7EAF81DB272CF4E277CC487D6BACB83C1059BBC0D45F49CBB6EA2C0E8033039CA575A939C8FF705FFA1FCA9DD53FD10447EE8D2F48128298E5DAB483F7A1500C455AFE33BB7FB280C39686CC45C7EC8C024EBF1089040D6636FF02E0E2A61092168A5CB105DBF3F5C6EB5C10D7392A46254B6E34DD4365F778ED199A52C6AB931416453CB8A677C90A6674BA5D546B25CDEC9C2E0B067729A6067FB1106B3BF7BBD56B888B5321484779570040B2095CD410D3B33F77BCFC9C24CA5A60003E342F110D35AA4714BFC8B3D9840BB3C8C286C5E353D5DEC4351A27E6E403AED2A21BBD0EA4194FB65B37F301A2E86BF9E9F8BBBFAA2400410ABC7833B3CCAAC66F27F873990E2D97BB36A70A5C9E4E3647C3AD0FAA716820A0BDC15CA8D7392"
@Offset +0x006C4E0F, write uint32_t:
0x00004708
@Offset +0x02047F04, write string:
"64308"
Solution1 has been done successfully.
```
3. Then in console:
```bash
C:\Users\DoubleSine\Github\navicat-keygen\x64\Release>navicat-keygen.exe RegPrivateKey.pem
```
You will be asked to select Navicat product, language and input major version number. After that an randomly generated __snKey__ will be generated.
__Example:__
```bash
C:\Users\DoubleSine\Github\navicat-keygen\x64\Release>navicat-keygen.exe RegPrivateKey.pem
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)> 0
(input major version number)> 12
Serial number:
NAVI-2ORL-MJQC-7WFO
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.
__Example:__
```bash
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 network and open Navicat. Find and click `Registration`. Fill `Registration Key` by __snKey__ that keygen gave. Then 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 keygen. Input empty line to tell keygen that your input ends.
__Example:__
```bash
Your name: DoubleLabyrinth
Your organization: DoubleLabyrinth
Input request code (in Base64), input empty line to end:
J517hWX/29aQMITp5UfS/FarX6q8pFKmW1Cl7Nt2UpvmVxhZDn5YBdPw/htDsBbXacNpLtorxfZM
Jxv/SZMqHsr7/JqexaaAEfzn5mo6zpatcSRArFoQh2h9IcnjRqziZ8yihkMUesKgsWXvVXMEYk7u
D1rc/GhzTf6/2kn0gTKRAlJGsxt+e1p6SOhPuMyzt3AyNvJ2s0o607Nub7vC37FOJF69jN1nOvej
uy3bmr2HSPFsh10WqUUYi6F1lzzYIq6nDjQ5CeKrCT2jPfrhoFtRbwJyYDxQOxU/adrm1bg8VjrK
XNGeKS67R1nrbBM03IKzPP3pxEGFut4gZdskRw==
Request Info:
{"K":"NAVI2ORLMJQC7WFO", "DI":"Y2eJk9vrvfGudPG7Mbdn", "P":"WIN 8"}
Response Info:
{"K":"NAVI2ORLMJQC7WFO","DI":"Y2eJk9vrvfGudPG7Mbdn","N":"DoubleLabyrinth","O":"DoubleLabyrinth","T":1534251096}
License:
iFvqOkwsVq/Wutw/hELC5dyweDahl2v8R3bMWcNXS/V49CjpaDEJIHtRLddu/ldg
WVGdwdh3aHVJ5k8I6RkUicDvZJH2vLn3o5O9Q/A5ThED0AoYnwu0DLa1gEUlRO68
4+uXwo1nZ+xtjLOSxrVh+fLkcvKtd5RDgHS5957qUwjoYBiuePGomtt9mF4NtfaF
E7pnfP/OGp8xtWdUfGZ1fESWttKcVXcmOpyF4uTWtluUhFHRk+ZueST/ETyaSx33
Kv/zSLBbK8KaVqS2sh5WBs8xVaYxDV08EC8uCCp1euTFOPG5nlrcf7iyILsh6I67
xfGRliXvM67jvsxqD200fg==
```
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.
+17 -274
View File
@@ -1,291 +1,34 @@
# Navicat Keygen
这份repo将会告诉你Navicat是怎么完成离线激活的。
这份repo将会告诉你Navicat是怎么完成离线激活的。
## 1. 关键词解释.
由于历史代码包含第三方二进制库,且大小较大,故决定将该项目的历史代码归档到 [`windows-archived`](https://github.com/DoubleLabyrinth/navicat-keygen/tree/windows-archived) 分支。
* __Navicat激活公钥__
当你clone该仓库的时候,请使用 `--single-branch` 选项,以此避免clone到 `windows-archived` 分支,并且还可以节省你的时间和磁盘空间。
这是一个2048位的RSA公钥,Navicat使用这个公钥来完成相关激活信息的加密和解密。
```console
$ git clone -b windows --single-branch https://github.com/DoubleLabyrinth/navicat-keygen.git
```
这个公钥被作为 __RCData__ 类型的资源储存在 __navicat.exe__ 当中。资源名为`"ActivationPubKey"`。你可以使用一个叫[Resource Hacker](http://www.angusj.com/resourcehacker/)的软件来查看它。这个公钥的具体内容为:
## 1. 注册机是怎么工作的?
> -----BEGIN PUBLIC KEY-----
> MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw1dqF3SkCaAAmMzs889I
> qdW9M2dIdh3jG9yPcmLnmJiGpBF4E9VHSMGe8oPAy2kJDmdNt4BcEygvssEfginv
> a5t5jm352UAoDosUJkTXGQhpAWMF4fBmBpO3EedG62rOsqMBgmSdAyxCSPBRJIOF
> R0QgZFbRnU0frj34fiVmgYiLuZSAmIbs8ZxiHPdp1oD4tUpvsFci4QJtYNjNnGU2
> WPH6rvChGl1IRKrxMtqLielsvajUjyrgOC6NmymYMvZNER3htFEtL1eQbCyTfDmt
> YyQ1Wt4Ot12lxf0wVIR5mcGN7XCXJRHOFHSf1gzXWabRSvmt1nrl7sW6cjxljuuQ
> awIDAQAB
> -----END PUBLIC KEY-----
见[这里](doc/how-does-it-work.zh-CN.md)。
如果您有相应的私钥并乐意公开的话欢迎联系我,我将非常感谢您的慷慨。
## 2. 如何编译?
__注意:__
见[这里](doc/how-to-build.zh-CN.md)。
__Navicat Premium 12.0.25__ 开始,Navicat不再从`navicat.exe`的资源中加载私钥。事实上,公钥转为从`libcc.dll`中加载,并且已经被加密。与此同时,为了防止被轻松地替换,加密的公钥被分到5个地方储存:
## 3. 如何使用这个注册机?
以下内容是从 __Navicat Premium x64 12.0.25 简体中文版__`libcc.dll`中发现的,`libcc.dll`的SHA256值为`607e0a84c75966b00f3d12fa833e91d159e4f51ac51b6ba66f98d0c3cbefdce0`。我不保证在Navicat的其他版本中相关偏移量和下述的相同,但相关的 __字符串__ 以及 __立即数__ 是很可能找得到的
针对 Windows 用户,请见[这里](doc/how-to-use.windows.zh-CN.md)
1.`libcc.dll`中,文件偏移量`+0x1A12090`的地方,储存了加密公钥的第一部分,以 __字符串__ 的形式储存:
针对 Linux 用户,请见[这里](doc/how-to-use.linux.zh-CN.md)。
> "D75125B70767B94145B47C1CB3C0755E
> 7CCB8825C5DCE0C58ACF944E08280140
> 9A02472FAFFD1CD77864BB821AE36766
> FEEDE6A24F12662954168BFA314BD950
> 32B9D82445355ED7BC0B880887D650F5"
## 4. 贡献者
2.`libcc.dll`中,文件偏移量`+0x59D799`的地方,储存了加密公钥的第二部分,以 __立即数__ 的形式储存在一条指令中:
* Deltafox79
> 0xFE 0xEA 0xBC 0x01
* dragonflylee
相应十进制为: `29158142`
* zenuo
3.`libcc.dll`中,文件偏移量`+0x1A11DA0`的地方,储存了加密公钥的第三部分,以 __字符串__ 的形式储存:
> "E1CED09B9C2186BF71A70C0FE2F1E0AE
> F3BD6B75277AAB20DFAF3D110F75912B
> FB63AC50EC4C48689D1502715243A79F
> 39FF2DE2BF15CE438FF885745ED54573
> 850E8A9F40EE2FF505EB7476F95ADB78
> 3B28CA374FAC4632892AB82FB3BF4715
> FCFE6E82D03731FC3762B6AAC3DF1C3B
> C646FE9CD3C62663A97EE72DB932A301
> 312B4A7633100C8CC357262C39A2B3A6
> 4B224F5276D5EDBDF0804DC3AC4B8351
> 62BB1969EAEBADC43D2511D6E0239287
> 81B167A48273B953378D3D2080CC0677
> 7E8A2364F0234B81064C5C739A8DA28D
> C5889072BF37685CBC94C2D31D0179AD
> 86D8E3AA8090D4F0B281BE37E0143746
> E6049CCC06899401264FA471C016A96C
> 79815B55BBC26B43052609D9D175FBCD
> E455392F10E51EC162F51CF732E6BB39
> 1F56BBFD8D957DF3D4C55B71CEFD54B1
> 9C16D458757373E698D7E693A8FC3981
> 5A8BF03BA05EA8C8778D38F9873D62B4
> 460F41ACF997C30E7C3AF025FA171B5F
> 5AD4D6B15E95C27F6B35AD61875E5505
> 449B4E"
4.`libcc.dll`中,文件偏移量`+0x59D77F`的地方,储存了加密公钥的第四部分,以 __立即数__ 的形式储存在一条指令中:
> 0x59 0x08 0x01 0x00
相应十进制为: `67673`
5.`libcc.dll`中,文件偏移量`+0x1A11D8C`的地方,储存了加密公钥的第五部分,以 __字符串__ 的形式储存:
> "92933"
这五部分按照`"%s%d%s%d%s"`的形式输出则为加密的公钥,顺序和上述的顺序相同,具体的输出为:
> D75125B70767B94145B47C1CB3C0755E7CCB8825C5DCE0C58ACF944E082801409A02472FAFFD1CD77864BB821AE36766FEEDE6A24F12662954168BFA314BD95032B9D82445355ED7BC0B880887D650F529158142E1CED09B9C2186BF71A70C0FE2F1E0AEF3BD6B75277AAB20DFAF3D110F75912BFB63AC50EC4C48689D1502715243A79F39FF2DE2BF15CE438FF885745ED54573850E8A9F40EE2FF505EB7476F95ADB783B28CA374FAC4632892AB82FB3BF4715FCFE6E82D03731FC3762B6AAC3DF1C3BC646FE9CD3C62663A97EE72DB932A301312B4A7633100C8CC357262C39A2B3A64B224F5276D5EDBDF0804DC3AC4B835162BB1969EAEBADC43D2511D6E023928781B167A48273B953378D3D2080CC06777E8A2364F0234B81064C5C739A8DA28DC5889072BF37685CBC94C2D31D0179AD86D8E3AA8090D4F0B281BE37E0143746E6049CCC06899401264FA471C016A96C79815B55BBC26B43052609D9D175FBCDE455392F10E51EC162F51CF732E6BB391F56BBFD8D957DF3D4C55B71CEFD54B19C16D458757373E698D7E693A8FC39815A8BF03BA05EA8C8778D38F9873D62B4460F41ACF997C30E7C3AF025FA171B5F5AD4D6B15E95C27F6B35AD61875E5505449B4E6767392933
这个加密的公钥可以用我的另外一个repo([how-does-navicat-encrypt-password](https://github.com/DoubleLabyrinth/how-does-navicat-encrypt-password))解密,其中密钥为`b'23970790'`
例如:
```cmd
E:\GitHub>git clone https://github.com/DoubleLabyrinth/how-does-navicat-encrypt-password.git
...
E:\GitHub>cd how-does-navicat-encrypt-password\python3
E:\GitHub\how-does-navicat-encrypt-password\python3>python
Python 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from NavicatCrypto import *
>>> cipher = Navicat11Crypto(b'23970790')
>>> print(cipher.DecryptString('D75125B70767B94145B47C1CB3C0755E7CCB8825C5DCE0C58ACF944E082801409A02472FAFFD1CD77864BB821AE36766FEEDE6A24F12662954168BFA314BD95032B9D82445355ED7BC0B880887D650F529158142E1CED09B9C2186BF71A70C0FE2F1E0AEF3BD6B75277AAB20DFAF3D110F75912BFB63AC50EC4C48689D1502715243A79F39FF2DE2BF15CE438FF885745ED54573850E8A9F40EE2FF505EB7476F95ADB783B28CA374FAC4632892AB82FB3BF4715FCFE6E82D03731FC3762B6AAC3DF1C3BC646FE9CD3C62663A97EE72DB932A301312B4A7633100C8CC357262C39A2B3A64B224F5276D5EDBDF0804DC3AC4B835162BB1969EAEBADC43D2511D6E023928781B167A48273B953378D3D2080CC06777E8A2364F0234B81064C5C739A8DA28DC5889072BF37685CBC94C2D31D0179AD86D8E3AA8090D4F0B281BE37E0143746E6049CCC06899401264FA471C016A96C79815B55BBC26B43052609D9D175FBCDE455392F10E51EC162F51CF732E6BB391F56BBFD8D957DF3D4C55B71CEFD54B19C16D458757373E698D7E693A8FC39815A8BF03BA05EA8C8778D38F9873D62B4460F41ACF997C30E7C3AF025FA171B5F5AD4D6B15E95C27F6B35AD61875E5505449B4E6767392933'))
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw1dqF3SkCaAAmMzs889I
qdW9M2dIdh3jG9yPcmLnmJiGpBF4E9VHSMGe8oPAy2kJDmdNt4BcEygvssEfginv
a5t5jm352UAoDosUJkTXGQhpAWMF4fBmBpO3EedG62rOsqMBgmSdAyxCSPBRJIOF
R0QgZFbRnU0frj34fiVmgYiLuZSAmIbs8ZxiHPdp1oD4tUpvsFci4QJtYNjNnGU2
WPH6rvChGl1IRKrxMtqLielsvajUjyrgOC6NmymYMvZNER3htFEtL1eQbCyTfDmt
YyQ1Wt4Ot12lxf0wVIR5mcGN7XCXJRHOFHSf1gzXWabRSvmt1nrl7sW6cjxljuuQ
awIDAQAB
-----END PUBLIC KEY-----
```
* __请求码__
这是一个Base64编码的字符串,代表的是长度为256字节的数据。这256字节的数据是 __离线激活信息__ 用 __Navicat激活公钥__ 加密的密文。
* __离线激活请求信息__
这是一个JSON风格的字符串。它包含了3个Key:`"K"`、`"DI"`和`"P"`,分别代表 __序列号__、__设备识别码__(与你的电脑硬件信息相关)和 __平台__ (其实就是操作系统类型)。
例如:
> {"K": "xxxxxxxxxxxxxxxx", "DI": "yyyyyyyyyyyyy", "P": "WIN8"}
* __激活码__
这是一个Base64编码的字符串,代表的是长度为256字节的数据。这256字节的数据是 __离线激活回复信息__ 用 __Navicat激活私钥__ 加密的密文,目前我们不知道官方的 __Navicat激活私钥__。
* __离线激活回复信息__
和 __离线激活请求信息__ 一样,它也是一个JSON风格的字符串。但是它包含5个Key,分别为`"K"`、`"N"`、`"O"`、`"T"`和`"DI"`.
`"K"` 和 `"DI"` 的意义与 __离线激活请求信息__ 中的相同,且Value必须与 __离线激活请求信息__ 中的相同。
`"N"`、`"O"`、`"T"` 分别代表 __注册名__、__组织__、__授权时间__。__注册名__ 和 __组织__ 的值类型为字符串,__授权时间__ 的值类型可以为字符串或整数(感谢@Wizr在issue #10的报告)。
`"T"` 可以被省略。
* __序列号__
这是一个被分为了4个部分的字符串,其中每个部分都是4个字符长。
__序列号__ 是通过10个字节的数据来生成的。为了表达方便,我用 __data[10]__ 来表示这10个字节。
1. __data[0]__ 和 __data[1]__ 必须分别为 `0x68` 和 `0x2A`。
_`Navicat产品类型变化时,这两个值可能会变。目前暂未确认。`_
2. __data[2]__、__data[3]__ 和 __data[4]__ 可以是任意字节,你想设成什么都行。
3. __data[5]__ 和 __data[6]__ 与你Navicat的语言有关,值如下:
| 语言类型 | data[5] | data[6] | 发现者 |
|------------|-----------|-----------|-----------------|
| English | 0xAC | 0x88 | |
| 简体中文 | 0xCE | 0x32 | |
| 繁體中文 | 0xAA | 0x99 | |
| 日本語 | 0xAD | 0x82 | @dragonflylee |
| Polski | 0xBB | 0x55 | @dragonflylee |
| Español | 0xAE | 0x10 | @dragonflylee |
| Français | 0xFA | 0x20 | @Deltafox79 |
| Deutsch | 0xB1 | 0x60 | @dragonflylee |
| 한국어 | 0xB5 | 0x60 | @dragonflylee |
| Русский | 0xEE | 0x16 | @dragonflylee |
| Português | 0xCD | 0x49 | @dragonflylee |
根据 __Navicat 12 for Mac x64__ 版本残留的符号信息可知这两个字节为 __Product Signature__。
4. __data[7]__ 指示这是 __commercial license__ 还是 __non-commercial license__。
对于 __Navicat 12__: `0x65`是 __commercial license__`0x66`是 __non-commercial license__。
对于 __Navicat 11__: `0x15`是 __commercial license__`0x16`是 __non-commercial license__。
_`Navicat产品类型变化时,这两个值可能会变。目前暂未确认。`_
根据 __Navicat 12 for Mac x64__ 版本残留的符号信息可知:__commercial license__ 是 __Enterprise License__ __non-commercial license__ 是 __Educational License__。
5. __data[8]__ 的高4位代表 __版本号__。低四位未知,但可以用来延长激活期限,可取的值有`0000`和`0001`。
对于 __Navicat 12__: 高4位必须是`1100`,为`12`的二进制形式。
对于 __Navicat 11__: 高4位必须是`1011`,为`11`的二进制形式。
6. __data[9]__ 目前暂未知,但如果你想要 __not-for-resale license__ 的话可以设成`0xFD`、`0xFC`或`0xFB`。
根据 __Navicat 12 for Mac x64__ 版本残留的符号信息可知:
* `0xFB`是 __Not-For-Resale-30-days__ license.
* `0xFC`是 __Not-For-Resale-90-days__ license.
* `0xFD`是 __Not-For-Resale-365-days__ license.
* `0xFE`是 __Not-For-Resale__ license.
* `0xFF`是 __Site__ license.
-----------------
之后Navicat使用 __ECB__ 模式的 __DES__ 算法来加密 __data[10]__ 的后8字节,也就是 __data[2]__ 到 __data[9]__ 的部分。
相应的DES密钥为:
```cpp
unsigned char DESKey = { 0x64, 0xAD, 0xF3, 0x2F, 0xAE, 0xF2, 0x1A, 0x27 };
```
之后编码 __data[10]__ __(使用Base32编码)__
1. 将 __data[10]__ 视作为一个80位长的数据。
如果 __data[10]__ 以`0x68`和`0x2A`开始的话,80位长的数据应该为`01011000 00101010......`
2. 将80位长的数据分为16个5位长的块。
如果 __data[10]__ 以`0x68`和`0x2A`开始的话,16个5位长的块应为`01011`、 `00000`、`10101`、`0....`
3. 这样每一块的值就会小于32。将它们通过下表编码:
```cpp
char EncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
```
你就会得到一个16字节的字符串。
如果 __data[10]__ 以`0x68`和`0x2A`开始的话,编码之后应该以`"N"`、`"A"`、`"V"`打头。
4. 将16字节的字符串分成4个4字节的小块,然后用`"-"`连接就可以得到 __序列号__。
## 3. 激活过程
1. 检查用户输入的 __序列号__ 是否合法。
2. 在用户点击了`激活`按钮之后,Navicat会先尝试在线激活。如果失败,用户可以选择离线激活。
3. Navicat会使用用户输入的 __序列号__ 以及从用户电脑收集来的信息生成 __离线激活请求信息__,然后用 __Navicat激活公钥__ 加密,并将密文用Base64编码,最后得到 __请求码__。
4. 正常流程下,__请求码__ 应该通过可访问Internet的电脑发送给Navicat的官方激活服务器。之后Navicat的官方激活服务器会返回一个合法的 __激活码__。
但现在我们使用注册机来扮演官方激活服务器的角色,只是Navicat软件里的激活公钥得换成自己的公钥:
1. 根据 __请求码__, 获得`"DI"`值和`"K"`值。
2. 用`"K"`值、用户名、组织名和`"DI"`值填写 __离线激活回复信息__。
3. 用自己的2048位RSA私钥加密 __离线激活回复信息__,你将会得到256字节的密文。
4. 用Base64编码这256字节的密文,就可以得到 __激活码__。
5. 在Navicat软件中填入 __激活码__ 即可完成离线激活。
## 4. 如何使用这个Keygen
1. 用Release模式编译好patcher以及keygen,或者从本repo的release里下载最新的release。
2. 替换掉`navicat.exe`或`libcc.dll`里的 __Navicat激活公钥__。
例如:
* 对于 Navicat Premium 版本 < 12.0.25的:
```bash
E:\GitHub\navicat-keygen\x64\Release>navicat-patcher.exe "D:\Program Files\PremiumSoft\Navicat Premium 12"
D:\Program Files\PremiumSoft\Navicat Premium 12\navicat.exe has been backed up.
Public key has been replaced.
Success!
```
* 对于 Navicat Premium 版本 >= 12.0.25的:
```bash
E:\GitHub\navicat-keygen\x64\Release>navicat-patcher.exe "D:\Program Files\PremiumSoft\Navicat Premium 12"
D:\Program Files\PremiumSoft\Navicat Premium 12\libcc.dll has been backed up.
Public key has been replaced.
Success!
```
你可能会需要等个几秒钟或者更久,因为patcher正在搜寻合适的RSA密钥。最后你会在console的当前目录得到`RegPrivateKey.pem`文件。
如果你不想搜寻,那么使用最新release里预留的`RegPrivateKey.pem`,然后:
```bash
E:\GitHub\navicat-keygen\x64\Release>navicat-patcher.exe "D:\Program Files\PremiumSoft\Navicat Premium 12" RegPrivateKey.pem
D:\Program Files\PremiumSoft\Navicat Premium 12\libcc.dll has been backed up.
Public key has been replaced.
Success!
```
3. 接下来,还是在console中:
```bash
E:\GitHub\navicat-keygen\x64\Release>navicat-keygen.exe RegPrivateKey.pem
```
你会得到一个 __序列号__,同时keygen会要求你输入用户名和组织名。
直接填写,之后你会被要求填写你得到的 __请求码__。注意 __不要关闭console__.
4. 断开网络并打开 Navicat Premium。找到`注册`窗口,并填入keygen给你的 __序列号__。然后点击`激活`按钮。
5. 一般来说在线激活肯定会失败,这时候Navicat会询问你是否`手动激活`,直接选吧。
6. 在`手动激活`窗口你会得到一个请求码,复制它并把它粘贴到keygen里。最后别忘了连按至少两下回车结束输入。
7. 如果不出意外,你会得到一个看似用Base64编码的 __激活码__。直接复制它,并把它粘贴到Navicat的`手动激活`窗口,最后点`激活`按钮。如果没什么意外的话应该能成功激活。
-27
View File
@@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAtOZGsX7UoDPuxCfEuw4iyWDASpwaN19GaPNrTlWz6K7MKXGr
AQpYD5gNZ8nGdfRgp52TErTHSNoRjgfpxGqKApPUISsIanGMcyf/H2b8pGuz1oF1
9kVKSyZTPaVLbE+1Cw7FULbI04bc64XnWSHoaQAXrYKGpC7oDomRGMtx28figu3A
HAk1UQrcCvE3+0ITTA7X8xaRwz6+gb+uLgCdiXyRYDodG8i+kk1YIt3f2mt7jH+u
EHqBYjIfvvo6g5MZz4KNz7Ewc6+sDyO8bmlXeFnHo6YAgCcaHVvVtGNCxCd1O5wW
HvUN985HHQYnFr7qzJaL9cPb735pP2hb0IXeywIDAQABAoIBAA5W7qWlQx+L3lJo
QJz/Styhsbx4UU+wWrl5CjmEa6V3LbHfU8naUw6xY+alRPkWrQ68W+swr1dkCd4z
XGF4fIYlx7v1WE5vv81lD0Ei/cXez7uiOYKTDYeVeyW405i7XMOKoTN7ucGiwCJf
U+5p1K12F2pmnVuoaDa2yuynO9hLBqf3SeQ8qd2dQvKLqL8JVLE+a1txl3YuV5Ap
PzUyLtGOmo5pIyKeeQ2dgR+AhnsUPDj5t0F1see6ysQVsNDk7i8Zcyfn2uWy4DPy
NcWu/zLilelKDiYqI2UH+Fm0RzkG7ce2UmNbrG4ESEPNfwMyzy8IUGv3sBxL8p9a
Xvtg7YkCgYEA7x9+cJNjs1DVxhTCatQrqWUwtwDiXZniz/WRUK7mQgX3mdFRhBhH
GjZCvWOz1muYYvkwPSDMzwjwuV3ItPSUp7sI9FWhkrYqG+lMLpKXrYLSj1Grc9pn
CZLQwmL9UegBUihBonm6bp+xJxbQeF/HStUWXP3xnWyRHBwUyAQC5v8CgYEAwarK
08U7NbRcrYBgzegn0n2z3iG16JR/3kLQt/MJAsbQAxavW98b8rUb3V7XvkECiTcD
74XuFdIAeeZeqlcsnYq2Gbr1tKCbTLHewztuFBwsQzeEmu1i81w0LeUaZqtB8HwQ
evRRQGaEZfIdsXCn+PiPb/O5zGJNTJTD3aE/9DUCgYAdYutw/kwEX2zGGQsDgeuT
t8HS26L2CdFb6TvghH37oywYlSbFaw5h5EUzbStOsI5bq3AIMx24W8rpnOLrihsy
ucOR82wV0Zk/MN6R4qYNRsSFpG3DoRWEkaxiFzQ2eqKe7B+UzgzhR3LH8P/Rq0Oc
qK9E4lhtFkiHAdRz+Do7FQKBgH8thkZtJcXNrHKvdGKjSstaiuybXJbgNdwiKmgx
7D/riRwOIJgHOpY2wparuqeQj3bGLwpy+/dOUcu7MX1RA9ZtCcp50PKN6Y4C3FN+
ynngSlzVr3oB29IOQaHF6oFzgzjGcBgeKuFMsTM1PLSSU2wW5jLRbbi+8R4SL1Fy
m8nlAoGBAJsq8E6qkAErFkjHt7u1Pmp7iGdgoP8hDQ0NXH6BxU432j3cIT+g2W3y
K28wXuHGamDqA9PLq3lb55wEkHqR62mTBqt9nJAW6CmAsl1Appvtf7ynep5SSNZg
jLUllIz/D76Kb4AXehqfkLmU+X3a1dNofpDSqCr4AdEizZHbX8Zp
-----END RSA PRIVATE KEY-----
+16
View File
@@ -0,0 +1,16 @@
#!/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"
+26
View File
@@ -0,0 +1,26 @@
#!/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"
+66
View File
@@ -0,0 +1,66 @@
#pragma once
#include <windows.h>
#include "xstring.hpp"
#include <vector>
namespace nkg {
class Exception {
private:
PCTSTR _SourceFile;
SIZE_T _SourceLine;
PCTSTR _Message;
std::vector<std::xstring> _Hints;
public:
Exception(PCTSTR SourceFile, SIZE_T SourceLine, PCTSTR CustomMessage) noexcept :
_SourceFile(SourceFile),
_SourceLine(SourceLine),
_Message(CustomMessage) {}
[[nodiscard]]
auto File() const noexcept {
return _SourceFile;
}
[[nodiscard]]
auto Line() const noexcept {
return _SourceLine;
}
[[nodiscard]]
auto Message() const noexcept {
return _Message;
}
auto& AddHint(const std::xstring& Hint) {
_Hints.emplace_back(Hint);
return *this;
}
[[nodiscard]]
const auto& Hints() const noexcept {
return _Hints;
}
[[nodiscard]]
virtual bool HasErrorCode() const noexcept {
return false;
}
[[nodiscard]]
virtual ULONG_PTR ErrorCode() const noexcept {
return 0;
}
[[nodiscard]]
virtual PCTSTR ErrorString() const noexcept {
return nullptr;
}
virtual ~Exception() = default;
};
}
+44
View File
@@ -0,0 +1,44 @@
#pragma once
#include "Exception.hpp"
#include <openssl/err.h>
namespace nkg {
class OpensslError final : public Exception {
private:
unsigned long _ErrorCode;
std::xstring _ErrorString;
public:
OpensslError(PCTSTR SourceFile, SIZE_T SourceLine, unsigned long OpensslErrorCode, PCTSTR CustomMessage) noexcept :
Exception(SourceFile, SourceLine, CustomMessage),
_ErrorCode(OpensslErrorCode)
{
static bool CryptoStringsLoaded = false;
if (CryptoStringsLoaded == false) {
ERR_load_crypto_strings();
CryptoStringsLoaded = true;
}
_ErrorString = std::xstring(std::xstring_extension{}, ERR_reason_error_string(_ErrorCode), CP_UTF8);
}
[[nodiscard]]
virtual bool HasErrorCode() const noexcept override {
return true;
}
[[nodiscard]]
virtual ULONG_PTR ErrorCode() const noexcept override {
return _ErrorCode;
}
[[nodiscard]]
virtual PCTSTR ErrorString() const noexcept override {
return _ErrorString.c_str();
}
};
}
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include "Exception.hpp"
namespace nkg {
class UserAbortionError final : public Exception {
public:
UserAbortionError(PCTSTR SourceFile, SIZE_T SourceLine, PCTSTR CustomMessage) noexcept :
Exception(SourceFile, SourceLine, CustomMessage) {}
[[nodiscard]]
virtual bool HasErrorCode() const noexcept override {
return false;
}
[[nodiscard]]
virtual ULONG_PTR ErrorCode() const noexcept override {
return 0;
}
[[nodiscard]]
virtual PCTSTR ErrorString() const noexcept override {
return nullptr;
}
};
}
+49
View File
@@ -0,0 +1,49 @@
#pragma once
#include "Exception.hpp"
namespace nkg {
class Win32Error final : public Exception {
private:
DWORD _ErrorCode;
std::xstring _ErrorString;
public:
Win32Error(PCTSTR SourceFile, SIZE_T SourceLine, DWORD Win32ErrorCode, PCTSTR CustomMessage) noexcept :
Exception(SourceFile, SourceLine, CustomMessage),
_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
);
if (Text) {
_ErrorString = Text;
LocalFree(Text);
}
}
[[nodiscard]]
virtual bool HasErrorCode() const noexcept override {
return true;
}
[[nodiscard]]
virtual ULONG_PTR ErrorCode() const noexcept override {
return _ErrorCode;
}
[[nodiscard]]
virtual PCTSTR ErrorString() const noexcept override {
return _ErrorString.c_str();
}
};
}
+261
View File
@@ -0,0 +1,261 @@
#pragma once
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/bio.h>
#include <openssl/rsa.h>
#include "Exception.hpp"
#include "ExceptionOpenssl.hpp"
#include "ResourceOwned.hpp"
#include "ResourceTraitsOpenssl.hpp"
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\common\\RSACipher.hpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
enum class RSAKeyType {
PrivateKey,
PublicKey
};
enum class RSAKeyFormat {
PEM,
PKCS1
};
class RSACipher final : private ResourceOwned<OpensslRSATraits> {
private:
template<RSAKeyType __Type, RSAKeyFormat __Format>
static void _WriteRSAToBIO(RSA* lpRSA, BIO* lpBIO) {
if constexpr (__Type == RSAKeyType::PrivateKey) {
if (PEM_write_bio_RSAPrivateKey(lpBIO, lpRSA, nullptr, nullptr, 0, nullptr, nullptr) == 0) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("PEM_write_bio_RSAPrivateKey failed."));
}
}
if constexpr (__Type == RSAKeyType::PublicKey) {
if constexpr (__Format == RSAKeyFormat::PEM) {
if (PEM_write_bio_RSA_PUBKEY(lpBIO, lpRSA) == 0) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("PEM_write_bio_RSA_PUBKEY failed."));
}
}
if constexpr (__Format == RSAKeyFormat::PKCS1) {
if (PEM_write_bio_RSAPublicKey(lpBIO, lpRSA) == 0) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("PEM_write_bio_RSAPublicKey failed."));
}
}
static_assert(__Format == RSAKeyFormat::PEM || __Format == RSAKeyFormat::PKCS1);
}
static_assert(__Type == RSAKeyType::PrivateKey || __Type == RSAKeyType::PublicKey);
}
template<RSAKeyType __Type, RSAKeyFormat __Format>
[[nodiscard]]
static RSA* _ReadRSAFromBIO(BIO* lpBIO) {
RSA* lpRSA;
if constexpr (__Type == RSAKeyType::PrivateKey) {
lpRSA = PEM_read_bio_RSAPrivateKey(lpBIO, nullptr, nullptr, nullptr);
if (lpRSA == nullptr) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("PEM_read_bio_RSAPrivateKey failed."))
.AddHint(TEXT("Are you sure that you DO provide a valid RSA private key file?"));
}
}
if constexpr (__Type == RSAKeyType::PublicKey) {
if constexpr (__Format == RSAKeyFormat::PEM) {
lpRSA = PEM_read_bio_RSA_PUBKEY(lpBIO, nullptr, nullptr, nullptr);
if (lpRSA == nullptr) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("PEM_read_bio_RSA_PUBKEY failed."))
.AddHint(TEXT("Are you sure that you DO provide a valid RSA public key file with PEM format?"));
}
}
if constexpr (__Format == RSAKeyFormat::PKCS1) {
lpRSA = PEM_read_bio_RSAPublicKey(lpBIO, nullptr, nullptr, nullptr);
if (lpRSA == nullptr) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("PEM_read_bio_RSAPublicKey failed."))
.AddHint(TEXT("Are you sure that you DO provide a valid RSA public key file with PKCS1 format?"));
}
}
static_assert(__Format == RSAKeyFormat::PEM || __Format == RSAKeyFormat::PKCS1);
}
static_assert(__Type == RSAKeyType::PrivateKey || __Type == RSAKeyType::PublicKey);
return lpRSA;
}
public:
RSACipher() : ResourceOwned<OpensslRSATraits>(RSA_new()) {
if (IsValid() == false) {
throw OpensslError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), ERR_get_error(), TEXT("RSA_new failed."));
}
}
[[nodiscard]]
size_t Bits() const {
if (Get()->n == nullptr) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("RSA modulus has not been set."));
} else {
return BN_num_bits(Get()->n);
}
}
void GenerateKey(int bits, unsigned int e = RSA_F4) {
ResourceOwned<OpensslBNTraits> bn_e(BN_new());
if (bn_e.IsValid() == false) {
throw OpensslError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), ERR_get_error(), TEXT("BN_new failed."));
}
if (!BN_set_word(bn_e, e)) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("BN_set_word failed."));
}
if (!RSA_generate_key_ex(Get(), bits, bn_e, nullptr)) {
throw OpensslError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), ERR_get_error(), TEXT("RSA_generate_key_ex failed."));
}
}
template<RSAKeyType __Type, RSAKeyFormat __Format>
void ExportKeyToFile(const std::xstring& FileName) const {
ResourceOwned<OpensslBIOTraits> BioFile(BIO_new_file(FileName.explicit_string(CP_UTF8).c_str(), "w"));
if (BioFile.IsValid() == false) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("BIO_new_file failed."));
}
_WriteRSAToBIO<__Type, __Format>(Get(), BioFile);
}
template<RSAKeyType __Type, RSAKeyFormat __Format>
[[nodiscard]]
std::string ExportKeyString() const {
ResourceOwned<OpensslBIOTraits> BioMemory(BIO_new(BIO_s_mem()));
long StringLength;
const char* StringChars = nullptr;
if (BioMemory.IsValid() == false) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("BIO_new failed."));
}
_WriteRSAToBIO<__Type, __Format>(Get(), BioMemory);
StringLength = BIO_get_mem_data(BioMemory.Get(), &StringChars);
return std::string(StringChars, StringLength);
}
template<RSAKeyType __Type, RSAKeyFormat __Format>
void ImportKeyFromFile(const std::xstring& FileName) {
ResourceOwned<OpensslBIOTraits> BioFile(BIO_new_file(FileName.explicit_string(CP_UTF8).c_str(), "r"));
if (BioFile.IsValid() == false) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("BIO_new_file failed."));
}
TakeOver(_ReadRSAFromBIO<__Type, __Format>(BioFile));
}
template<RSAKeyType __Type, RSAKeyFormat __Format>
void ImportKeyString(const std::string& KeyString) {
ResourceOwned<OpensslBIOTraits> BioMemory(BIO_new(BIO_s_mem()));
if (BioMemory.IsValid() == false) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("BIO_new failed."));
}
if (BIO_puts(BioMemory.Get(), KeyString.c_str()) <= 0) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("BIO_puts failed."));
}
TakeOver(_ReadRSAFromBIO<__Type, __Format>(BioMemory));
}
template<RSAKeyType __Type = RSAKeyType::PublicKey>
size_t Encrypt(const void* lpFrom, size_t cbFrom, void* lpTo, int Padding) const {
int BytesWritten;
if (cbFrom > INT_MAX) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Length overflowed."));
}
if constexpr (__Type == RSAKeyType::PrivateKey) {
BytesWritten = RSA_private_encrypt(
static_cast<int>(cbFrom),
reinterpret_cast<const unsigned char*>(lpFrom),
reinterpret_cast<unsigned char*>(lpTo),
Get(),
Padding
);
if (BytesWritten == -1) {
throw OpensslError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), ERR_get_error(), TEXT("RSA_private_encrypt failed."));
}
} else {
BytesWritten = RSA_public_encrypt(
static_cast<int>(cbFrom),
reinterpret_cast<const unsigned char*>(lpFrom),
reinterpret_cast<unsigned char*>(lpTo),
Get(),
Padding
);
if (BytesWritten == -1) {
throw OpensslError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), ERR_get_error(), TEXT("RSA_public_encrypt failed."));
}
}
return BytesWritten;
}
template<RSAKeyType __Type = RSAKeyType::PrivateKey>
size_t Decrypt(const void* lpFrom, size_t cbFrom, void* lpTo, int Padding) const {
int BytesWritten;
if (cbFrom > INT_MAX) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Length overflowed."));
}
if constexpr (__Type == RSAKeyType::PrivateKey) {
BytesWritten = RSA_private_decrypt(
static_cast<int>(cbFrom),
reinterpret_cast<const unsigned char*>(lpFrom),
reinterpret_cast<unsigned char*>(lpTo),
Get(),
Padding
);
if (BytesWritten == -1) {
throw OpensslError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), ERR_get_error(), TEXT("RSA_private_decrypt failed."))
.AddHint(TEXT("Are your sure you DO provide a correct private key?"));
}
} else {
BytesWritten = RSA_public_decrypt(
static_cast<int>(cbFrom),
reinterpret_cast<const unsigned char*>(lpFrom),
reinterpret_cast<unsigned char*>(lpTo),
Get(),
Padding
);
if (BytesWritten == -1) {
throw OpensslError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), ERR_get_error(), TEXT("RSA_public_decrypt failed."))
.AddHint(TEXT("Are your sure you DO provide a correct public key?"));
}
}
return BytesWritten;
}
};
}
+313
View File
@@ -0,0 +1,313 @@
#pragma once
#include <type_traits>
#include <utility>
template<typename __ResourceTraits, typename __LambdaReleasor = void>
class ResourceOwned {
private:
using __HandleType = typename __ResourceTraits::HandleType;
static_assert(std::is_pod_v<__HandleType>);
__HandleType _Handle;
__LambdaReleasor _Releasor;
public:
ResourceOwned(__LambdaReleasor&& Releasor) noexcept :
_Handle(__ResourceTraits::InvalidValue),
_Releasor(std::forward<__LambdaReleasor>(Releasor)) {}
ResourceOwned(const __HandleType& Handle, __LambdaReleasor&& Releasor) noexcept :
_Handle(Handle),
_Releasor(std::forward<__LambdaReleasor>(Releasor)) {}
//
// Construct from custom releasor.
// `_Handle` will be set to an invalid value.
//
ResourceOwned(__ResourceTraits, __LambdaReleasor&& Releasor) noexcept :
_Handle(__ResourceTraits::InvalidValue),
_Releasor(std::forward<__LambdaReleasor>(Releasor)) {}
//
// Construct from handle given and custom releasor.
//
ResourceOwned(__ResourceTraits, const __HandleType& Handle, __LambdaReleasor&& Releasor) noexcept :
_Handle(Handle),
_Releasor(std::forward<__LambdaReleasor>(Releasor)) {}
//
// ResourceOwned doesn't allow to copy.
// Because it takes `_Handle` exclusively.
//
ResourceOwned(const ResourceOwned<__ResourceTraits, __LambdaReleasor>& Other) = delete;
//
// ResourceOwned allows to move.
//
ResourceOwned(ResourceOwned<__ResourceTraits, __LambdaReleasor>&& Other) noexcept :
_Handle(Other._Handle),
_Releasor(std::move(Other._Releasor))
{
Other._Handle = __ResourceTraits::InvalidValue;
}
//
// ResourceOwned doesn't allow to copy.
// Because it takes `_Handle` exclusively.
//
ResourceOwned<__ResourceTraits, __LambdaReleasor>& operator=(const ResourceOwned<__ResourceTraits, __LambdaReleasor>& Other) = delete;
//
// ResourceOwned allows to move.
//
ResourceOwned<__ResourceTraits, __LambdaReleasor>& operator=(ResourceOwned<__ResourceTraits, __LambdaReleasor>&& Other) noexcept {
_Handle = Other._Handle;
_Releasor = std::move(Other._Releasor);
Other._Handle = __ResourceTraits::InvalidValue;
return *this;
}
[[nodiscard]]
operator const __HandleType&() const noexcept { // NOLINT: Allow implicit conversion.
return _Handle;
}
template<typename __AsType, bool __IsPointer = std::is_pointer_v<__HandleType>, typename = std::enable_if_t<__IsPointer>>
[[nodiscard]]
__AsType As() const noexcept {
return reinterpret_cast<__AsType>(_Handle);
}
template<bool __IsPointer = std::is_pointer_v<__HandleType>, typename = typename std::enable_if_t<__IsPointer>>
[[nodiscard]]
__HandleType operator->() const noexcept {
return _Handle;
}
[[nodiscard]]
bool IsValid() const noexcept {
return __ResourceTraits::IsValid(_Handle);
}
[[nodiscard]]
const __HandleType& Get() const noexcept {
return _Handle;
}
template<typename __ReturnType = __HandleType*>
[[nodiscard]]
__ReturnType GetAddressOf() noexcept {
return reinterpret_cast<__ReturnType>(&_Handle);
}
void TakeOver(const __HandleType& Handle) {
if (__ResourceTraits::IsValid(_Handle) == true) {
_Releasor(_Handle);
}
_Handle = Handle;
}
void Discard() noexcept {
_Handle = __ResourceTraits::InvalidValue;
}
[[nodiscard]]
__HandleType Transfer() noexcept {
__HandleType t = _Handle;
_Handle = __ResourceTraits::InvalidValue;
return t;
}
void Release() {
if (__ResourceTraits::IsValid(_Handle)) {
_Releasor(_Handle);
_Handle = __ResourceTraits::InvalidValue;
}
}
~ResourceOwned() {
if (__ResourceTraits::IsValid(_Handle)) {
_Releasor(_Handle);
_Handle = __ResourceTraits::InvalidValue;
}
}
};
template<typename __ResourceTraits>
class ResourceOwned<__ResourceTraits, void> {
private:
using __HandleType = typename __ResourceTraits::HandleType;
static_assert(std::is_pod_v<__HandleType>);
__HandleType _Handle;
public:
ResourceOwned() noexcept :
_Handle(__ResourceTraits::InvalidValue) {}
ResourceOwned(const __HandleType& Handle) noexcept :
_Handle(Handle) {}
//
// Construct from custom releasor.
// `_Handle` will be set to an invalid value.
//
explicit ResourceOwned(__ResourceTraits) noexcept :
_Handle(__ResourceTraits::InvalidValue) {}
//
// Construct from handle given and custom releasor.
//
ResourceOwned(__ResourceTraits, const __HandleType& Handle) noexcept :
_Handle(Handle) {}
//
// ResourceOwned doesn't allow to copy.
// Because it takes `_Handle` exclusively.
//
ResourceOwned(const ResourceOwned<__ResourceTraits, void>& Other) = delete;
//
// ResourceOwned allows to move.
//
ResourceOwned(ResourceOwned<__ResourceTraits, void>&& Other) noexcept :
_Handle(Other._Handle) {
Other._Handle = __ResourceTraits::InvalidValue;
}
//
// ResourceOwned doesn't allow to copy.
// Because it takes `_Handle` exclusively.
//
ResourceOwned<__ResourceTraits, void>& operator=(const ResourceOwned<__ResourceTraits, void>& Other) = delete;
//
// ResourceOwned allows to move.
//
ResourceOwned<__ResourceTraits, void>& operator=(ResourceOwned<__ResourceTraits, void>&& Other) noexcept {
_Handle = Other._Handle;
Other._Handle = __ResourceTraits::InvalidValue;
return *this;
}
[[nodiscard]]
operator const __HandleType&() const noexcept { // NOLINT: Allow implicit conversion.
return _Handle;
}
template<typename __AsType, bool __IsPointer = std::is_pointer_v<__HandleType>, typename = typename std::enable_if_t<__IsPointer>>
[[nodiscard]]
__AsType As() const noexcept {
return reinterpret_cast<__AsType>(_Handle);
}
template<bool __IsPointer = std::is_pointer_v<__HandleType>, typename = typename std::enable_if_t<__IsPointer>>
[[nodiscard]]
__HandleType operator->() const noexcept {
return _Handle;
}
[[nodiscard]]
bool IsValid() const noexcept {
return __ResourceTraits::IsValid(_Handle);
}
[[nodiscard]]
const __HandleType& Get() const noexcept {
return _Handle;
}
template<typename __ReturnType = __HandleType*>
[[nodiscard]]
__ReturnType GetAddressOf() noexcept {
return reinterpret_cast<__ReturnType>(&_Handle);
}
void TakeOver(const __HandleType& Handle) {
if (__ResourceTraits::IsValid(_Handle) == true) {
__ResourceTraits::Releasor(_Handle);
}
_Handle = Handle;
}
void Discard() noexcept {
_Handle = __ResourceTraits::InvalidValue;
}
[[nodiscard]]
__HandleType Transfer() noexcept {
__HandleType t = _Handle;
_Handle = __ResourceTraits::InvalidValue;
return t;
}
void Release() {
if (__ResourceTraits::IsValid(_Handle)) {
__ResourceTraits::Releasor(_Handle);
_Handle = __ResourceTraits::InvalidValue;
}
}
~ResourceOwned() {
if (__ResourceTraits::IsValid(_Handle)) {
__ResourceTraits::Releasor(_Handle);
_Handle = __ResourceTraits::InvalidValue;
}
}
};
template<typename __ResourceTraits>
ResourceOwned(__ResourceTraits) ->
ResourceOwned<__ResourceTraits, void>;
template<typename __ResourceTraits, typename __ArgType>
ResourceOwned(__ResourceTraits, __ArgType&&) ->
ResourceOwned<
__ResourceTraits,
std::conditional_t<
std::is_same_v<std::remove_cv_t<std::remove_reference_t<__ArgType>>, typename __ResourceTraits::HandleType> == false,
std::remove_reference_t<__ArgType>,
void
>
>;
template<typename __ResourceTraits, typename __LambdaReleasor>
ResourceOwned(__ResourceTraits, const typename __ResourceTraits::HandleType&, __LambdaReleasor&&) ->
ResourceOwned<__ResourceTraits, std::remove_reference_t<__LambdaReleasor>>;
template<typename __ClassType>
struct CppObjectTraits {
using HandleType = __ClassType*;
static inline const HandleType InvalidValue = nullptr;
[[nodiscard]]
static bool IsValid(const HandleType& Handle) noexcept {
return Handle != InvalidValue;
}
static void Releasor(const HandleType& Handle) {
delete Handle;
}
};
template<typename __ClassType>
struct CppDynamicArrayTraits {
using HandleType = __ClassType*;
static inline const HandleType InvalidValue = nullptr;
[[nodiscard]]
static bool IsValid(const HandleType& Handle) noexcept {
return Handle != InvalidValue;
}
static void Releasor(const HandleType& Handle) {
delete[] Handle;
}
};
+64
View File
@@ -0,0 +1,64 @@
#pragma once
#include <openssl/bio.h>
#include <openssl/rsa.h>
struct OpensslBIOTraits {
using HandleType = BIO*;
static inline const HandleType InvalidValue = nullptr;
[[nodiscard]]
static bool IsValid(const HandleType& Handle) noexcept {
return Handle != InvalidValue;
}
static void Releasor(const HandleType& Handle) noexcept {
BIO_free(Handle);
}
};
struct OpensslBIOChainTraits {
using HandleType = BIO*;
static inline const HandleType InvalidValue = nullptr;
[[nodiscard]]
static bool IsValid(const HandleType& Handle) noexcept {
return Handle != InvalidValue;
}
static void Releasor(const HandleType& Handle) noexcept {
BIO_free_all(Handle);
}
};
struct OpensslBNTraits {
using HandleType = BIGNUM*;
static inline const HandleType InvalidValue = nullptr;
[[nodiscard]]
static bool IsValid(const HandleType& Handle) noexcept {
return Handle != InvalidValue;
}
static void Releasor(const HandleType& Handle) noexcept {
BN_free(Handle);
}
};
struct OpensslRSATraits {
using HandleType = RSA*;
static inline const HandleType InvalidValue = nullptr;
[[nodiscard]]
static bool IsValid(const HandleType& Handle) noexcept {
return Handle != InvalidValue;
}
static void Releasor(const HandleType& Handle) noexcept {
RSA_free(Handle);
}
};
+47
View File
@@ -0,0 +1,47 @@
#pragma once
#include <windows.h>
struct GenericHandleTraits {
using HandleType = HANDLE;
static inline const HandleType InvalidValue = NULL;
[[nodiscard]]
static bool IsValid(const HandleType& Handle) noexcept {
return Handle != InvalidValue;
}
static void Releasor(const HandleType& Handle) noexcept {
CloseHandle(Handle);
}
};
struct FileHandleTraits {
using HandleType = HANDLE;
static inline const HandleType InvalidValue = INVALID_HANDLE_VALUE;
[[nodiscard]]
static bool IsValid(const HandleType& Handle) noexcept {
return Handle != InvalidValue;
}
static void Releasor(const HandleType& Handle) noexcept {
CloseHandle(Handle);
}
};
struct MapViewHandleTraits {
using HandleType = PVOID;
static inline const HandleType InvalidValue = NULL;
[[nodiscard]]
static bool IsValid(const HandleType& Handle) noexcept {
return Handle != InvalidValue;
}
static void Releasor(const HandleType& Handle) noexcept {
UnmapViewOfFile(Handle);
}
};
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include <stdint.h>
#include <vector>
namespace std {
using bytearray = vector<uint8_t>;
}
+28
View File
@@ -0,0 +1,28 @@
<?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>{290c5d5e-52d2-4fef-909f-27fd95ae0af9}</ItemsProjectGuid>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectCapability Include="SourceItemsFromImports" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(MSBuildThisFileDirectory)bytearray.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)Exception.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)ExceptionOpenssl.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)ExceptionUser.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)ExceptionWin32.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)ResourceOwned.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)ResourceTraitsOpenssl.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)ResourceTraitsWin32.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)RSACipher.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)xstring.hpp" />
</ItemGroup>
</Project>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ShowAllFiles>true</ShowAllFiles>
</PropertyGroup>
</Project>
+288
View File
@@ -0,0 +1,288 @@
#pragma once
#include <tchar.h>
#include <stdio.h>
#include <windows.h>
#include <string>
#include <utility>
#include <stdexcept>
#include <system_error>
namespace std {
struct xstring_extension {};
#if defined(_UNICODE) || defined(UNICODE)
class xstring final : public wstring {
public:
using wstring::wstring;
using wstring::operator=;
xstring(const wstring& wstr) : wstring(wstr) {}
xstring(wstring&& wstr) : wstring(std::move(wstr)) {}
xstring(xstring_extension, const string& str, DWORD CodePage = CP_ACP) {
auto len = MultiByteToWideChar(CodePage, 0, str.c_str(), -1, NULL, 0);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
resize(static_cast<size_t>(len) - 1);
len = MultiByteToWideChar(CodePage, 0, str.c_str(), -1, data(), len);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
}
xstring(xstring_extension, const char* lpstr, DWORD CodePage = CP_ACP) {
auto len = MultiByteToWideChar(CodePage, 0, lpstr, -1, NULL, 0);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
resize(static_cast<size_t>(len) - 1);
len = MultiByteToWideChar(CodePage, 0, lpstr, -1, data(), len);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
}
#else
class xstring final : public string {
public:
using string::string;
using string::operator=;
xstring(const string& str) : string(str) {}
xstring(string&& str) : string(std::move(str)) {}
xstring(xstring_extension, const string& str, DWORD CodePage = CP_ACP) {
if (CodePage == CP_ACP || CodePage == GetACP()) {
assign(str);
} else {
std::wstring wstr;
auto len = MultiByteToWideChar(CodePage, 0, str.c_str(), -1, NULL, 0);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
wstr.resize(len - 1);
len = MultiByteToWideChar(CodePage, 0, str.c_str(), -1, wstr.data(), len);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
resize(len - 1);
len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, data(), len, NULL, NULL);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
}
}
xstring(xstring_extension, const char* lpstr, DWORD CodePage = CP_ACP) {
if (CodePage == CP_ACP || CodePage == GetACP()) {
assign(lpstr);
} else {
std::wstring wstr;
auto len = MultiByteToWideChar(CodePage, 0, lpstr, -1, NULL, 0);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
wstr.resize(len - 1);
len = MultiByteToWideChar(CodePage, 0, lpstr, -1, wstr.data(), len);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
resize(len - 1);
len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, data(), len, NULL, NULL);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
}
}
xstring(xstring_extension, const wstring& wstr) {
auto len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
resize(len - 1);
len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, data(), len, NULL, NULL);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
}
xstring(xstring_extension, const wchar_t* lpwstr) {
auto len = WideCharToMultiByte(CP_ACP, 0, lpwstr, -1, NULL, 0, NULL, NULL);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
resize(len - 1);
len = WideCharToMultiByte(CP_ACP, 0, lpwstr, -1, data(), len, NULL, NULL);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
}
#endif
std::string explicit_string(DWORD CodePage = CP_ACP) const {
#if defined(_UNICODE) || defined(UNICODE)
std::string str;
auto len = WideCharToMultiByte(CodePage, 0, c_str(), -1, NULL, 0, NULL, NULL);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
str.resize(static_cast<size_t>(len) - 1);
len = WideCharToMultiByte(CodePage, 0, c_str(), -1, str.data(), len, NULL, NULL);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
return str;
#else
if (CodePage == CP_ACP || CodePage == GetACP()) {
return *this;
} else {
std::string str;
std::wstring wstr;
auto len = MultiByteToWideChar(CP_ACP, 0, c_str(), -1, NULL, 0);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
wstr.resize(len - 1);
len = MultiByteToWideChar(CP_ACP, 0, c_str(), -1, wstr.data(), len);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
len = WideCharToMultiByte(CodePage, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
str.resize(len - 1);
len = WideCharToMultiByte(CodePage, 0, wstr.c_str(), -1, str.data(), len, NULL, NULL);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
return str;
}
#endif
}
std::wstring explicit_wstring() const {
#if defined(_UNICODE) || defined(UNICODE)
return *this;
#else
std::wstring wstr;
auto len = MultiByteToWideChar(CP_ACP, 0, c_str(), -1, NULL, 0);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
wstr.resize(len - 1);
len = MultiByteToWideChar(CP_ACP, 0, c_str(), -1, wstr.data(), len);
if (len == 0) {
auto err = GetLastError();
throw std::system_error(err, std::system_category());
}
return wstr;
#endif
}
template<typename... __Ts>
static xstring format(const xstring& Format, __Ts&&... Args) {
xstring s;
auto len = _sctprintf(Format.c_str(), std::forward<__Ts>(Args)...);
if (len == -1) {
throw std::invalid_argument("_sctprintf failed.");
}
s.resize(len);
_sntprintf_s(s.data(), s.length() + 1, _TRUNCATE, Format.c_str(), std::forward<__Ts>(Args)...);
return s;
}
template<typename... __Ts>
static xstring format(PCTSTR lpszFormat, __Ts&& ... Args) {
xstring s;
auto len = _sctprintf(lpszFormat, std::forward<__Ts>(Args)...);
if (len == -1) {
throw std::invalid_argument("_sctprintf failed.");
}
s.resize(len);
_sntprintf_s(s.data(), s.length() + 1, _TRUNCATE, lpszFormat, std::forward<__Ts>(Args)...);
return s;
}
};
}
+284
View File
@@ -0,0 +1,284 @@
# Navicat Keygen - How does it work?
[中文版](how-does-it-work.zh-CN.md)
## 1. Keyword Explanation.
* __Navicat Activation Public Key__
It is a __RSA-2048__ public key that Navicat used to encrypt or decrypt offline activation information.
It is stored in __navicat.exe__ as a kind of resource called __RCData__. The resource name is `"ACTIVATIONPUBKEY"`. You can see it by a software called [___Resource Hacker___](http://www.angusj.com/resourcehacker/). The public key is
```
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw1dqF3SkCaAAmMzs889I
qdW9M2dIdh3jG9yPcmLnmJiGpBF4E9VHSMGe8oPAy2kJDmdNt4BcEygvssEfginv
a5t5jm352UAoDosUJkTXGQhpAWMF4fBmBpO3EedG62rOsqMBgmSdAyxCSPBRJIOF
R0QgZFbRnU0frj34fiVmgYiLuZSAmIbs8ZxiHPdp1oD4tUpvsFci4QJtYNjNnGU2
WPH6rvChGl1IRKrxMtqLielsvajUjyrgOC6NmymYMvZNER3htFEtL1eQbCyTfDmt
YyQ1Wt4Ot12lxf0wVIR5mcGN7XCXJRHOFHSf1gzXWabRSvmt1nrl7sW6cjxljuuQ
awIDAQAB
-----END PUBLIC KEY-----
```
If you have the corresponding private key, you can tell me. I would be very appreciated for your generous.
__NOTICE:__
Start from __Navicat Premium 12.0.25__, Navicat do not load this public key from resource in `navicat.exe`. Instead, the public key is stored in `libcc.dll` and has been encrypted. To avoid being replaced easily, the public key is split into 5 parts:
The following content is discovered from `libcc.dll` of __Navicat Premium x64 12.0.25 Simplified Chinese version__. The SHA256 value of `libcc.dll` is `607e0a84c75966b00f3d12fa833e91d159e4f51ac51b6ba66f98d0c3cbefdce0`.
I __DO NOT__ guarantee that offset values are absolutely correct in other versions. But __char strings__ and __immediate values__ are highly possible to be found.
1. At file offset `+0x01A12090` in `libcc.dll`, stored as __char string__:
```
"D75125B70767B94145B47C1CB3C0755E
7CCB8825C5DCE0C58ACF944E08280140
9A02472FAFFD1CD77864BB821AE36766
FEEDE6A24F12662954168BFA314BD950
32B9D82445355ED7BC0B880887D650F5"
```
2. At file offset `+0x0059D799` in `libcc.dll`, stored as __immediate value__ in a instruction:
```
0xFE 0xEA 0xBC 0x01
```
In decimal: `29158142`
3. At file offset `+0x01A11DA0` in `libcc.dll`, stored as __char string__:
```
"E1CED09B9C2186BF71A70C0FE2F1E0AE
F3BD6B75277AAB20DFAF3D110F75912B
FB63AC50EC4C48689D1502715243A79F
39FF2DE2BF15CE438FF885745ED54573
850E8A9F40EE2FF505EB7476F95ADB78
3B28CA374FAC4632892AB82FB3BF4715
FCFE6E82D03731FC3762B6AAC3DF1C3B
C646FE9CD3C62663A97EE72DB932A301
312B4A7633100C8CC357262C39A2B3A6
4B224F5276D5EDBDF0804DC3AC4B8351
62BB1969EAEBADC43D2511D6E0239287
81B167A48273B953378D3D2080CC0677
7E8A2364F0234B81064C5C739A8DA28D
C5889072BF37685CBC94C2D31D0179AD
86D8E3AA8090D4F0B281BE37E0143746
E6049CCC06899401264FA471C016A96C
79815B55BBC26B43052609D9D175FBCD
E455392F10E51EC162F51CF732E6BB39
1F56BBFD8D957DF3D4C55B71CEFD54B1
9C16D458757373E698D7E693A8FC3981
5A8BF03BA05EA8C8778D38F9873D62B4
460F41ACF997C30E7C3AF025FA171B5F
5AD4D6B15E95C27F6B35AD61875E5505
449B4E"
```
4. At file offset `+0x0059D77F` in `libcc.dll`, stored as __immediate value__ in a instruction:
```
0x59 0x08 0x01 0x00
```
In decimal: `67673`
5. At file offset `+ 0x1A11D8C` in `libcc.dll`, stored as __char string__:
```
"92933"
```
Then output encrypted public key with format `"%s%d%s%d%s"`. The order is the same as it lists:
```
D75125B70767B94145B47C1CB3C0755E7CCB8825C5DCE0C58ACF944E082801409A02472FAFFD1CD77864BB821AE36766FEEDE6A24F12662954168BFA314BD95032B9D82445355ED7BC0B880887D650F529158142E1CED09B9C2186BF71A70C0FE2F1E0AEF3BD6B75277AAB20DFAF3D110F75912BFB63AC50EC4C48689D1502715243A79F39FF2DE2BF15CE438FF885745ED54573850E8A9F40EE2FF505EB7476F95ADB783B28CA374FAC4632892AB82FB3BF4715FCFE6E82D03731FC3762B6AAC3DF1C3BC646FE9CD3C62663A97EE72DB932A301312B4A7633100C8CC357262C39A2B3A64B224F5276D5EDBDF0804DC3AC4B835162BB1969EAEBADC43D2511D6E023928781B167A48273B953378D3D2080CC06777E8A2364F0234B81064C5C739A8DA28DC5889072BF37685CBC94C2D31D0179AD86D8E3AA8090D4F0B281BE37E0143746E6049CCC06899401264FA471C016A96C79815B55BBC26B43052609D9D175FBCDE455392F10E51EC162F51CF732E6BB391F56BBFD8D957DF3D4C55B71CEFD54B19C16D458757373E698D7E693A8FC39815A8BF03BA05EA8C8778D38F9873D62B4460F41ACF997C30E7C3AF025FA171B5F5AD4D6B15E95C27F6B35AD61875E5505449B4E6767392933
```
This encrypted public key can be decrypted by my another repo: [how-does-navicat-encrypt-password](https://github.com/DoubleLabyrinth/how-does-navicat-encrypt-password), while the key used is `b'23970790'`.
Example:
```cmd
E:\GitHub>git clone https://github.com/DoubleLabyrinth/how-does-navicat-encrypt-password.git
...
E:\GitHub>cd how-does-navicat-encrypt-password\python3
E:\GitHub\how-does-navicat-encrypt-password\python3>python
Python 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from NavicatCrypto import *
>>> cipher = Navicat11Crypto(b'23970790')
>>> print(cipher.DecryptString('D75125B70767B94145B47C1CB3C0755E7CCB8825C5DCE0C58ACF944E082801409A02472FAFFD1CD77864BB821AE36766FEEDE6A24F12662954168BFA314BD95032B9D82445355ED7BC0B880887D650F529158142E1CED09B9C2186BF71A70C0FE2F1E0AEF3BD6B75277AAB20DFAF3D110F75912BFB63AC50EC4C48689D1502715243A79F39FF2DE2BF15CE438FF885745ED54573850E8A9F40EE2FF505EB7476F95ADB783B28CA374FAC4632892AB82FB3BF4715FCFE6E82D03731FC3762B6AAC3DF1C3BC646FE9CD3C62663A97EE72DB932A301312B4A7633100C8CC357262C39A2B3A64B224F5276D5EDBDF0804DC3AC4B835162BB1969EAEBADC43D2511D6E023928781B167A48273B953378D3D2080CC06777E8A2364F0234B81064C5C739A8DA28DC5889072BF37685CBC94C2D31D0179AD86D8E3AA8090D4F0B281BE37E0143746E6049CCC06899401264FA471C016A96C79815B55BBC26B43052609D9D175FBCDE455392F10E51EC162F51CF732E6BB391F56BBFD8D957DF3D4C55B71CEFD54B19C16D458757373E698D7E693A8FC39815A8BF03BA05EA8C8778D38F9873D62B4460F41ACF997C30E7C3AF025FA171B5F5AD4D6B15E95C27F6B35AD61875E5505449B4E6767392933'))
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw1dqF3SkCaAAmMzs889I
qdW9M2dIdh3jG9yPcmLnmJiGpBF4E9VHSMGe8oPAy2kJDmdNt4BcEygvssEfginv
a5t5jm352UAoDosUJkTXGQhpAWMF4fBmBpO3EedG62rOsqMBgmSdAyxCSPBRJIOF
R0QgZFbRnU0frj34fiVmgYiLuZSAmIbs8ZxiHPdp1oD4tUpvsFci4QJtYNjNnGU2
WPH6rvChGl1IRKrxMtqLielsvajUjyrgOC6NmymYMvZNER3htFEtL1eQbCyTfDmt
YyQ1Wt4Ot12lxf0wVIR5mcGN7XCXJRHOFHSf1gzXWabRSvmt1nrl7sW6cjxljuuQ
awIDAQAB
-----END PUBLIC KEY-----
```
__NOTICE:__
Start from __Navicat Premium 12.1.11__, Navicat do not load the public key through the method I talked before. Of course, the public key is still stored in `libcc.dll`. When Navicat starts, it encrypts the public key by an 8-bytes-long XOR key and stores the ciphertext in static area. When verifing __Activation Code__, Navicat will regenerate the 8-bytes-long XOR key and decrypts the ciphertext in static area to get the public key.
In `libcc.dll`, x64 version, you can find some instructions that looks like:
```asm
xor eax, 'M'
mov byte_xxxxxx, al
...
xor eax, 'I'
mov byte_xxxxxx, al
...
xor eax, 'I'
mov byte_xxxxxx, al
...
xor eax, 'B'
mov byte_xxxxxx, al
...
xor eax, 'I'
mov byte_xxxxxx, al
...
xor eax, 'j'
mov byte_xxxxxx, al
...
...
```
* __Request Code__
It is a Base64 string that represents 256-bytes-long data, while the 256-bytes-long data is the cipher text of __Offline Activation Request Information__ encrypted by __Navicat Activation Public Key__.
* __Offline Activation Request Information__
It is just a JSON-style ASCII string which contains 3 items. They are `"K"`, `"DI"` and `"P"` respectively, which represent __snKey__, __DeviceIdentifier__ (related with your machine), __Platform__ (OS Type).
Like
```
{"K": "xxxxxxxxxxxxxxxx", "DI": "yyyyyyyyyyyyy", "P": "WIN8"}
```
* __Activation Code__
It is a Base64 string that represents 256-bytes-long data, while the 256-bytes-long data is the cipher text of the __Offline Activation Response Information__ encrypted by __Navicat Activation Private Key__. So far, we don't know the official activation private key and we have to replace it in `navicat.exe` and `libcc.dll`.
* __Offline Activation Response Information__
Just like __Offline Activation Request Information__, it is also a JSON-style ASCII string. But it contains 5 items. They are `"K"`, `"N"`, `"O"`, `"T"` and `"DI"` respectively.
`"K"` and `"DI"` has the same meaning that is mentioned in __Offline Activation Request Information__ and must be the same with the corresponding items in __Offline Activation Request Information__.
`"N"`, `"O"`, `"T"` represent __Name__, __Organization__, __Timestamp__ respectively. __Name__ and __Organization__ are UTF-8 strings and the type of __Timestamp__ can be string or integer. (Thanks for discoveries from @Wizr, issue #10)
`"T"` can be omitted.
* __snKey__
It is a 4-block-long string, while every block is 4-chars-long.
__snKey__ is generated by 10-bytes-long data. In order to explain it easily, I use __uint8_t data[10]__ to represent the 10-bytes-long data.
1. __data[0]__ and __data[1]__ must be `0x68` and `0x2A` respectively.
These two bytes are Naivcat signature number.
2. __data[2]__, __data[3]__ and __data[4]__ can be any byte. Just set them whatever you want.
3. __data[5]__ and __data[6]__ are product language signatures.
| Language | data[5] | data[6] | Discoverer |
|------------|:---------:|:---------:|-----------------|
| English | 0xAC | 0x88 | |
| 简体中文 | 0xCE | 0x32 | |
| 繁體中文 | 0xAA | 0x99 | |
| 日本語 | 0xAD | 0x82 | @dragonflylee |
| Polski | 0xBB | 0x55 | @dragonflylee |
| Español | 0xAE | 0x10 | @dragonflylee |
| Français | 0xFA | 0x20 | @Deltafox79 |
| Deutsch | 0xB1 | 0x60 | @dragonflylee |
| 한국어 | 0xB5 | 0x60 | @dragonflylee |
| Русский | 0xEE | 0x16 | @dragonflylee |
| Português | 0xCD | 0x49 | @dragonflylee |
4. __data[7]__ is Navicat product ID. (Thanks @dragonflylee and @Deltafox79)
|Product Name |Enterprise|Standard|Educational|Essentials|
|----------------------|:--------:|:------:|:---------:|:--------:|
|Navicat Report Viewer |0x0B | | | |
|Navicat Data Modeler 3| |0x84 |0x85 | |
|Navicat Premium |0x65 | |0x66 |0x67 |
|Navicat MySQL |0x68 |0x69 |0x6A |0x6B |
|Navicat PostgreSQL |0x6C |0x6D |0x6E |0x6F |
|Navicat Oracle |0x70 |0x71 |0x72 |0x73 |
|Navicat SQL Server |0x74 |0x75 |0x76 |0x77 |
|Navicat SQLite |0x78 |0x79 |0x7A |0x7B |
|Navicat MariaDB |0x7C |0x7D |0x7E |0x7F |
|Navicat MongoDB |0x80 |0x81 |0x82 | |
5. High 4 bits of __data[8]__ represents __major version number__.
Low 4 bits is unknown, but we can use it to delay activation deadline. Possible values are `0000` or `0001`.
__Example:__
For __Navicat 12 x64__: High 4 bits must be `1100`, which is the binary of number `12`.
For __Navicat 11 x64__: High 4 bits must be `1011`, which is the binary of number `11`.
6. __data[9]__ is unknown, but you can set it by `0xFD`, `0xFC` or `0xFB` if you want to use __not-for-resale license__.
According to symbol information in __Navicat 12 for Mac x64__ version:
* `0xFB` is __Not-For-Resale-30-days__ license.
* `0xFC` is __Not-For-Resale-90-days__ license.
* `0xFD` is __Not-For-Resale-365-days__ license.
* `0xFE` is __Not-For-Resale__ license.
* `0xFF` is __Site__ license.
After `uint8_t data[10]` is ready, Navicat uses __DES__ with __ECB mode__ to encrypt the last 8 bytes of `uint8_t data[10]` which are from __data[2]__ to __data[9]__.
The DES key is:
```cpp
unsigned char DESKey = { 0x64, 0xAD, 0xF3, 0x2F, 0xAE, 0xF2, 0x1A, 0x27 };
```
Then use Base32 to encode `uint8_t data[10]` whose encode table is
```cpp
char EncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
```
After encoding, you will get a 16-char-long string starting with `"NAV"`.
Finally, divide the 16-char-long string to four 4-chars-long blocks and join them with `"-"` then you will get __snKey__.
## 2. Activation Process
1. Check whether __snKey__ that user inputs is valid.
2. After user clicks `Activate`, Navicat will start online activation first. If fails, user can choose offline activation.
3. Navicat will use the __snKey__ that user inputs and some information collected from user's machine to generate __Offline Activation Request Information__. Then Navicat will encrypt it by __Navicat Activation Public Key__ and return a Base64-encoded string as __Request Code__.
4. In legal way, the __Request Code__ should be sent to Navicat official activation server by a Internet-accessible computer. And Navicat official activation server will return a legal __Activation Code__.
But now, we use keygen to play the official activation server's role.
1. According to the __Request Code__, get `"DI"` value and `"K"` value.
2. Fill __Offline Activation Response Information__ with `"K"` value, name, organization name, `"DI"` value and, if need, `"T"` value.
3. Encrypt __Offline Activation Response Information__ by __Navicat Activation Private Key__ and you will get 256-byte-long data.
4. Encode the 256-byte-long data by Base64. The result is __Activation Code__.
5. After user input __Activation Code__, offline activation is done successfully.
+282
View File
@@ -0,0 +1,282 @@
# Navicat Keygen - 注册机是怎么工作的?
## 1. 关键词解释.
* __Navicat激活公钥__
这是一个2048位的RSA公钥,Navicat使用这个公钥来完成相关激活信息的加密和解密。
这个公钥被作为 __RCData__ 类型的资源储存在 __navicat.exe__ 当中。资源名为`"ACTIVATIONPUBKEY"`。你可以使用一个叫[Resource Hacker](http://www.angusj.com/resourcehacker/)的软件来查看它。这个公钥的具体内容为:
```
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw1dqF3SkCaAAmMzs889I
qdW9M2dIdh3jG9yPcmLnmJiGpBF4E9VHSMGe8oPAy2kJDmdNt4BcEygvssEfginv
a5t5jm352UAoDosUJkTXGQhpAWMF4fBmBpO3EedG62rOsqMBgmSdAyxCSPBRJIOF
R0QgZFbRnU0frj34fiVmgYiLuZSAmIbs8ZxiHPdp1oD4tUpvsFci4QJtYNjNnGU2
WPH6rvChGl1IRKrxMtqLielsvajUjyrgOC6NmymYMvZNER3htFEtL1eQbCyTfDmt
YyQ1Wt4Ot12lxf0wVIR5mcGN7XCXJRHOFHSf1gzXWabRSvmt1nrl7sW6cjxljuuQ
awIDAQAB
-----END PUBLIC KEY-----
```
如果您有相应的私钥并乐意公开的话欢迎联系我,我将非常感谢您的慷慨。
__注意:__
从 __Navicat Premium 12.0.25__ 开始,Navicat不再从`navicat.exe`的资源中加载私钥。事实上,公钥转为从`libcc.dll`中加载,并且已经被加密。与此同时,为了防止被轻松地替换,加密的公钥被分到5个地方储存:
以下内容是从 __Navicat Premium x64 12.0.25 简体中文版__ 的`libcc.dll`中发现的,`libcc.dll`的SHA256值为`607e0a84c75966b00f3d12fa833e91d159e4f51ac51b6ba66f98d0c3cbefdce0`。我不保证在Navicat的其他版本中相关偏移量和下述的相同,但相关的 __字符串__ 以及 __立即数__ 是很可能找得到的。
1. 在`libcc.dll`中,文件偏移量`+0x01A12090`的地方,储存了加密公钥的第一部分,以 __字符串__ 的形式储存:
```
"D75125B70767B94145B47C1CB3C0755E
7CCB8825C5DCE0C58ACF944E08280140
9A02472FAFFD1CD77864BB821AE36766
FEEDE6A24F12662954168BFA314BD950
32B9D82445355ED7BC0B880887D650F5"
```
2. 在`libcc.dll`中,文件偏移量`+0x0059D799`的地方,储存了加密公钥的第二部分,以 __立即数__ 的形式储存在一条指令中:
```
0xFE 0xEA 0xBC 0x01
```
相应的十进制值为: `29158142`
3. 在`libcc.dll`中,文件偏移量`+0x01A11DA0`的地方,储存了加密公钥的第三部分,以 __字符串__ 的形式储存:
```
"E1CED09B9C2186BF71A70C0FE2F1E0AE
F3BD6B75277AAB20DFAF3D110F75912B
FB63AC50EC4C48689D1502715243A79F
39FF2DE2BF15CE438FF885745ED54573
850E8A9F40EE2FF505EB7476F95ADB78
3B28CA374FAC4632892AB82FB3BF4715
FCFE6E82D03731FC3762B6AAC3DF1C3B
C646FE9CD3C62663A97EE72DB932A301
312B4A7633100C8CC357262C39A2B3A6
4B224F5276D5EDBDF0804DC3AC4B8351
62BB1969EAEBADC43D2511D6E0239287
81B167A48273B953378D3D2080CC0677
7E8A2364F0234B81064C5C739A8DA28D
C5889072BF37685CBC94C2D31D0179AD
86D8E3AA8090D4F0B281BE37E0143746
E6049CCC06899401264FA471C016A96C
79815B55BBC26B43052609D9D175FBCD
E455392F10E51EC162F51CF732E6BB39
1F56BBFD8D957DF3D4C55B71CEFD54B1
9C16D458757373E698D7E693A8FC3981
5A8BF03BA05EA8C8778D38F9873D62B4
460F41ACF997C30E7C3AF025FA171B5F
5AD4D6B15E95C27F6B35AD61875E5505
449B4E"
```
4. 在`libcc.dll`中,文件偏移量`+0x0059D77F`的地方,储存了加密公钥的第四部分,以 __立即数__ 的形式储存在一条指令中:
```
0x59 0x08 0x01 0x00
```
相应的十进制值为: `67673`
5. 在`libcc.dll`中,文件偏移量`+0x01A11D8C`的地方,储存了加密公钥的第五部分,以 __字符串__ 的形式储存:
```
"92933"
```
这五部分按照`"%s%d%s%d%s"`的形式输出则为加密的公钥,顺序和上述的顺序相同,具体的输出为:
```
D75125B70767B94145B47C1CB3C0755E7CCB8825C5DCE0C58ACF944E082801409A02472FAFFD1CD77864BB821AE36766FEEDE6A24F12662954168BFA314BD95032B9D82445355ED7BC0B880887D650F529158142E1CED09B9C2186BF71A70C0FE2F1E0AEF3BD6B75277AAB20DFAF3D110F75912BFB63AC50EC4C48689D1502715243A79F39FF2DE2BF15CE438FF885745ED54573850E8A9F40EE2FF505EB7476F95ADB783B28CA374FAC4632892AB82FB3BF4715FCFE6E82D03731FC3762B6AAC3DF1C3BC646FE9CD3C62663A97EE72DB932A301312B4A7633100C8CC357262C39A2B3A64B224F5276D5EDBDF0804DC3AC4B835162BB1969EAEBADC43D2511D6E023928781B167A48273B953378D3D2080CC06777E8A2364F0234B81064C5C739A8DA28DC5889072BF37685CBC94C2D31D0179AD86D8E3AA8090D4F0B281BE37E0143746E6049CCC06899401264FA471C016A96C79815B55BBC26B43052609D9D175FBCDE455392F10E51EC162F51CF732E6BB391F56BBFD8D957DF3D4C55B71CEFD54B19C16D458757373E698D7E693A8FC39815A8BF03BA05EA8C8778D38F9873D62B4460F41ACF997C30E7C3AF025FA171B5F5AD4D6B15E95C27F6B35AD61875E5505449B4E6767392933
```
这个加密的公钥可以用我的另外一个repo[how-does-navicat-encrypt-password](https://github.com/DoubleLabyrinth/how-does-navicat-encrypt-password))解密,其中密钥为`b'23970790'`。
例如:
```cmd
E:\GitHub>git clone https://github.com/DoubleLabyrinth/how-does-navicat-encrypt-password.git
...
E:\GitHub>cd how-does-navicat-encrypt-password\python3
E:\GitHub\how-does-navicat-encrypt-password\python3>python
Python 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from NavicatCrypto import *
>>> cipher = Navicat11Crypto(b'23970790')
>>> print(cipher.DecryptString('D75125B70767B94145B47C1CB3C0755E7CCB8825C5DCE0C58ACF944E082801409A02472FAFFD1CD77864BB821AE36766FEEDE6A24F12662954168BFA314BD95032B9D82445355ED7BC0B880887D650F529158142E1CED09B9C2186BF71A70C0FE2F1E0AEF3BD6B75277AAB20DFAF3D110F75912BFB63AC50EC4C48689D1502715243A79F39FF2DE2BF15CE438FF885745ED54573850E8A9F40EE2FF505EB7476F95ADB783B28CA374FAC4632892AB82FB3BF4715FCFE6E82D03731FC3762B6AAC3DF1C3BC646FE9CD3C62663A97EE72DB932A301312B4A7633100C8CC357262C39A2B3A64B224F5276D5EDBDF0804DC3AC4B835162BB1969EAEBADC43D2511D6E023928781B167A48273B953378D3D2080CC06777E8A2364F0234B81064C5C739A8DA28DC5889072BF37685CBC94C2D31D0179AD86D8E3AA8090D4F0B281BE37E0143746E6049CCC06899401264FA471C016A96C79815B55BBC26B43052609D9D175FBCDE455392F10E51EC162F51CF732E6BB391F56BBFD8D957DF3D4C55B71CEFD54B19C16D458757373E698D7E693A8FC39815A8BF03BA05EA8C8778D38F9873D62B4460F41ACF997C30E7C3AF025FA171B5F5AD4D6B15E95C27F6B35AD61875E5505449B4E6767392933'))
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw1dqF3SkCaAAmMzs889I
qdW9M2dIdh3jG9yPcmLnmJiGpBF4E9VHSMGe8oPAy2kJDmdNt4BcEygvssEfginv
a5t5jm352UAoDosUJkTXGQhpAWMF4fBmBpO3EedG62rOsqMBgmSdAyxCSPBRJIOF
R0QgZFbRnU0frj34fiVmgYiLuZSAmIbs8ZxiHPdp1oD4tUpvsFci4QJtYNjNnGU2
WPH6rvChGl1IRKrxMtqLielsvajUjyrgOC6NmymYMvZNER3htFEtL1eQbCyTfDmt
YyQ1Wt4Ot12lxf0wVIR5mcGN7XCXJRHOFHSf1gzXWabRSvmt1nrl7sW6cjxljuuQ
awIDAQAB
-----END PUBLIC KEY-----
```
__注意:__
从 __Navicat Premium 12.1.11__ 开始,Navicat不再用上面说的方法加载密钥。当然密钥还是储存在`libcc.dll`文件中。当Navicat启动时,它会用8字节长的XOR密钥来加密公钥,并储存到一个静态数据区中。当验证 __激活码__ 时,Navicat会重新生成一样的8字节XOR密钥,并解密在静态储存区中的密文,从而获取公钥。
在`libcc.dll`,x64版本中,你会看到如下的几条指令:
```asm
xor eax, 'M'
mov byte_xxxxxx, al
...
xor eax, 'I'
mov byte_xxxxxx, al
...
xor eax, 'I'
mov byte_xxxxxx, al
...
xor eax, 'B'
mov byte_xxxxxx, al
...
xor eax, 'I'
mov byte_xxxxxx, al
...
xor eax, 'j'
mov byte_xxxxxx, al
...
...
```
* __请求码__
这是一个Base64编码的字符串,代表的是长度为256字节的数据。这256字节的数据是 __离线激活信息__ 用 __Navicat激活公钥__ 加密的密文。
* __离线激活请求信息__
这是一个JSON风格的字符串。它包含了3个Key:`"K"`、`"DI"`和`"P"`,分别代表 __序列号__、__设备识别码__(与你的电脑硬件信息相关)和 __平台__ (其实就是操作系统类型)。
例如:
```
{"K": "xxxxxxxxxxxxxxxx", "DI": "yyyyyyyyyyyyy", "P": "WIN8"}
```
* __激活码__
这是一个Base64编码的字符串,代表的是长度为256字节的数据。这256字节的数据是 __离线激活回复信息__ 用 __Navicat激活私钥__ 加密的密文。目前我们不知道官方的 __Navicat激活私钥__,所以我们得替换掉软件里的公钥。
* __离线激活回复信息__
和 __离线激活请求信息__ 一样,它也是一个JSON风格的字符串。但是它包含5个Key,分别为`"K"`、`"N"`、`"O"`、`"T"` 和 `"DI"`.
`"K"` 和 `"DI"` 的意义与 __离线激活请求信息__ 中的相同,且Value必须与 __离线激活请求信息__ 中的相同。
`"N"`、`"O"`、`"T"` 分别代表 __注册名__、__组织__、__授权时间__。
__注册名__ 和 __组织__ 的值类型为UTF-8编码的字符串。__授权时间__ 的值类型可以为字符串或整数(感谢@Wizr在issue #10中的报告)。
`"T"` 可以被省略。
* __序列号__
这是一个被分为了4个部分的字符串,其中每个部分都是4个字符长。
__序列号__ 是通过10个字节的数据来生成的。为了表达方便,我用 __uint8_t data[10]__ 来表示这10个字节。
1. __data[0]__ 和 __data[1]__ 必须分别为 `0x68` 和 `0x2A`。
这两个字节为Navicat的标志数。
2. __data[2]__、__data[3]__ 和 __data[4]__ 可以是任意字节,你想设成什么都行。
3. __data[5]__ 和 __data[6]__ 是Navicat的语言标志,值如下:
| 语言类型 | data[5] | data[6] | 发现者 |
|------------|:---------:|:---------:|-----------------|
| English | 0xAC | 0x88 | |
| 简体中文 | 0xCE | 0x32 | |
| 繁體中文 | 0xAA | 0x99 | |
| 日本語 | 0xAD | 0x82 | @dragonflylee |
| Polski | 0xBB | 0x55 | @dragonflylee |
| Español | 0xAE | 0x10 | @dragonflylee |
| Français | 0xFA | 0x20 | @Deltafox79 |
| Deutsch | 0xB1 | 0x60 | @dragonflylee |
| 한국어 | 0xB5 | 0x60 | @dragonflylee |
| Русский | 0xEE | 0x16 | @dragonflylee |
| Português | 0xCD | 0x49 | @dragonflylee |
4. __data[7]__ 是Navicat产品ID。(感谢 @dragonflylee 和 @Deltafox79提供的数据)
|产品名 |Enterprise|Standard|Educational|Essentials|
|----------------------|:--------:|:------:|:---------:|:--------:|
|Navicat Report Viewer |0x0B | | | |
|Navicat Data Modeler 3| |0x84 |0x85 | |
|Navicat Premium |0x65 | |0x66 |0x67 |
|Navicat MySQL |0x68 |0x69 |0x6A |0x6B |
|Navicat PostgreSQL |0x6C |0x6D |0x6E |0x6F |
|Navicat Oracle |0x70 |0x71 |0x72 |0x73 |
|Navicat SQL Server |0x74 |0x75 |0x76 |0x77 |
|Navicat SQLite |0x78 |0x79 |0x7A |0x7B |
|Navicat MariaDB |0x7C |0x7D |0x7E |0x7F |
|Navicat MongoDB |0x80 |0x81 |0x82 | |
5. __data[8]__ 的高4位代表 __版本号__。低4位未知,但可以用来延长激活期限,可取的值有`0000`和`0001`。
例如:
对于 __Navicat 12__: 高4位必须是`1100`,为`12`的二进制形式。
对于 __Navicat 11__: 高4位必须是`1011`,为`11`的二进制形式。
6. __data[9]__ 目前暂未知,但如果你想要 __not-for-resale license__ 的话可以设成`0xFD`、`0xFC`或`0xFB`。
根据 __Navicat 12 for Mac x64__ 版本残留的符号信息可知:
* `0xFB`是 __Not-For-Resale-30-days__ license.
* `0xFC`是 __Not-For-Resale-90-days__ license.
* `0xFD`是 __Not-For-Resale-365-days__ license.
* `0xFE`是 __Not-For-Resale__ license.
* `0xFF`是 __Site__ license.
之后Navicat使用 __ECB__ 模式的 __DES__ 算法来加密 __data[10]__ 的后8字节,也就是 __data[2]__ 到 __data[9]__ 的部分。
相应的DES密钥为:
```cpp
unsigned char DESKey = { 0x64, 0xAD, 0xF3, 0x2F, 0xAE, 0xF2, 0x1A, 0x27 };
```
之后使用Base32编码 __data[10]__,其中编码表改为:
```cpp
char EncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
```
编码之后你应该会得到一个16字节长的字符串,并且以"NAV"打头。
将16字节的字符串分成4个4字节的小块,然后用`"-"`连接就可以得到 __序列号__。
## 2. 激活过程
1. 检查用户输入的 __序列号__ 是否合法。
2. 在用户点击了`激活`按钮之后,Navicat会先尝试在线激活。如果失败,用户可以选择离线激活。
3. Navicat会使用用户输入的 __序列号__ 以及从用户电脑收集来的信息生成 __离线激活请求信息__,然后用 __Navicat激活公钥__ 加密,并将密文用Base64编码,最后得到 __请求码__。
4. 正常流程下,__请求码__ 应该通过可联网的电脑发送给Navicat的官方激活服务器。之后Navicat的官方激活服务器会返回一个合法的 __激活码__。
但现在我们使用注册机来扮演官方激活服务器的角色,只是Navicat软件里的激活公钥得换成自己的公钥:
1. 根据 __请求码__, 获得`"DI"`值和`"K"`值。
2. 用`"K"`值、用户名、组织名和`"DI"`值填写 __离线激活回复信息__
3. 用自己的2048位RSA私钥加密 __离线激活回复信息__,你将会得到256字节的密文。
4. 用Base64编码这256字节的密文,就可以得到 __激活码__
5. 在Navicat软件中填入 __激活码__ 即可完成离线激活。
+56
View File
@@ -0,0 +1,56 @@
# Navicat Keygen - How to build?
[中文版](how-to-build.zh-CN.md)
## 1. Prerequisites
1. Please make sure that you have __Visual Studio 2019__ or the higher. Because this is a VS2019 project.
2. Please make sure you have installed `vcpkg` and the following libraries:
* `capstone[x86]:x64-windows-static`
* `capstone[x86]:x86-windows-static`
* `keystone:x64-windows-static`
* `keystone:x86-windows-static`
* `openssl-windows:x64-windows-static`
* `openssl-windows:x86-windows-static`
* `rapidjson:x64-windows-static`
* `rapidjson:x86-windows-static`
is installed.
You can install them by:
```console
$ vcpkg install capstone[x86]:x64-windows-static
$ vcpkg install capstone[x86]:x86-windows-static
$ vcpkg install keystone:x64-windows-static
$ vcpkg install keystone:x86-windows-static
$ vcpkg install openssl-windows:x64-windows-static
$ vcpkg install openssl-windows:x86-windows-static
$ vcpkg install rapidjson:x64-windows-static
$ vcpkg install rapidjson:x86-windows-static
```
3. Your `vcpkg` has been integrated into your __Visual Studio__, which means you have run
```console
$ vcpkg integrate install
```
successfully.
## 2. Build
1. Open this project in __Visual Studio__.
2. Select `Release` configuration.
3. Select `Win32` to build keygen/patcher for 32-bits Navicat.
Or select `x64` to build keygen/patcher for 64-bits Navicat.
4. Select __Build > Build Solution__.
You will see executable files in `bin/` directory.
+50
View File
@@ -0,0 +1,50 @@
# Navicat Keygen - 如何编译?
## 1. 前提条件
1. 请确保你有 __Visual Studio 2019__ 或者更高版本。因为这是一个VS2019项目。
2. 请确保你安装了 `vcpkg` 以及下面几个库:
* `capstone[x86]:x64-windows-static`
* `capstone[x86]:x86-windows-static`
* `keystone:x64-windows-static`
* `keystone:x86-windows-static`
* `openssl-windows:x64-windows-static`
* `openssl-windows:x86-windows-static`
* `rapidjson:x64-windows-static`
* `rapidjson:x86-windows-static`
你可以通过下面的命令来安装它们:
```console
$ vcpkg install capstone[x86]:x64-windows-static
$ vcpkg install capstone[x86]:x86-windows-static
$ vcpkg install keystone:x64-windows-static
$ vcpkg install keystone:x86-windows-static
$ vcpkg install openssl-windows:x64-windows-static
$ vcpkg install openssl-windows:x86-windows-static
$ vcpkg install rapidjson:x64-windows-static
$ vcpkg install rapidjson:x86-windows-static
```
3. 你的 `vcpkg` 已经和你的 __Visual Studio__ 集成了,即你曾成功运行了:
```console
$ vcpkg integrate install
```
## 2. 编译
1. 在 __Visual Studio__ 打开这个项目。
2. 选择 `Release` 配置。
3. 选择 `Win32` 来生成供32位Navicat使用的keygen/patcher。
或者选择 `x64` 来生成供64位Navicat使用的keygen/patcher。
4. 选择 __生成 > 生成解决方案__。
生成完成后,你会在 `bin/` 文件夹下看到编译后的keygen/patcher。
+257
View File
@@ -0,0 +1,257 @@
# Navicat Keygen - How to use? (Linux)
[中文版](how-to-use.linux.zh-CN.md)
* Maintainer(s): zenuo, DoubleLabyrinth
---
> 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:
```console
$ 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.
```console
$ curl -O -L https://github.com/DoubleLabyrinth/navicat-keygen/releases/latest/download/navicat-keygen-for-x64.zip
$ unzip navicat-keygen-for-x64.zip
```
3. Download `navicat-pacther.sh` and `navicat-keygen.sh`:
```console
$ 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.
```console
$ ./navicat-patcher.sh
```
It has been tested on __Navicat Premium 12.1.22 Simplified Chinese version__. The following is an example of output:
```
***************************************************
* Navicat Patcher by @DoubleLabyrinth *
* Version: 4.0 *
***************************************************
Press Enter to continue or Ctrl + C to abort.
[+] Try to open Navicat.exe ... Ok!
[+] Try to open libcc.dll ... Ok!
[+] PatchSolution0 ...... Ready to apply
[*] Patch offset = +0x029bccd8
[+] PatchSolution1 ...... Ready to apply
[*] [0] Patch offset = +0x02206c00
[*] [1] Patch offset = +0x0074c489
[*] [2] Patch offset = +0x02206910
[*] [3] Patch offset = +0x0074c46f
[*] [4] Patch offset = +0x02206904
[-] PatchSolution2 ...... Omitted
[+] PatchSolution3 ...... Ready to apply
[*] [ 0] Instruction RVA = 0x016539c8, Patch Offset = +0x023e64d4
[*] [ 1] Instruction RVA = 0x01653a1f, Patch Offset = +0x01652e23
[*] [ 2] Instruction RVA = 0x01653a25, Patch Offset = +0x01652e28
[*] [ 3] Instruction RVA = 0x01653a8c, Patch Offset = +0x01652e8e
...
...
...
[*] [108] Instruction RVA = 0x016604e1, Patch Offset = +0x023e66d8
[*] [109] Instruction RVA = 0x01660518, Patch Offset = +0x0165f91c
[*] [110] Instruction RVA = 0x0166051e, Patch Offset = +0x0165f921
[*] PatchSolution0 is suppressed in order to keep digital signature valid.
[*] Generating new RSA private key, it may take a long time...
[*] Your RSA public key:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1hV66HgU4LrKXWW6O7bK
AN6ZTr5W+Mq8ClTQ+Pc+BdhLu6rww55kVq7OXKGpvx0G4eTafYMGrrBETgDSTaMq
Bx+8bZbGBWh2LtNfqU+xUrpHHBSz0ByBc3iTEzzthJl+Fzf8suDX2lWYIc/Ym/eW
YtxdJ7xOzLb68z4N0zVmA0jFX2FOm75DRYgKqy4SGixapfucL9dVaWVLTUdbrVdj
4LX78t4t5ykbYoThrat4yuLvj/BxLaQ6ivKD+ScfHdtCoY+NA5jmBoUfBq3Q1SXB
iNaoXctbi0/H3MiPu0cRojryAocooF89yFm5/mNnzWGAYPr6DvBI8CDTZmjaQ4oC
aQIDAQAB
-----END PUBLIC KEY-----
*******************************************************
* PatchSolution1 *
*******************************************************
[*] Previous:
+0x0000000002206c00 44 37 35 31 32 35 42 37 30 37 36 37 42 39 34 31 D75125B70767B941
+0x0000000002206c10 34 35 42 34 37 43 31 43 42 33 43 30 37 35 35 45 45B47C1CB3C0755E
+0x0000000002206c20 37 43 43 42 38 38 32 35 43 35 44 43 45 30 43 35 7CCB8825C5DCE0C5
...
...
[*] After:
+0x0000000002206c00 33 43 32 39 30 39 35 38 33 34 38 41 42 43 35 39 3C290958348ABC59
+0x0000000002206c10 36 44 39 30 43 45 45 38 31 36 42 36 39 38 34 44 6D90CEE816B6984D
+0x0000000002206c20 35 32 35 34 37 45 30 32 34 31 42 36 42 43 31 41 52547E0241B6BC1A
...
...
[*] Previous:
+0x000000000074c480 fe ea bc 01 ....
[*] After:
+0x000000000074c480 08 00 00 00 ....
[*] Previous:
+0x0000000002206910 45 31 43 45 44 30 39 42 39 43 32 31 38 36 42 46 E1CED09B9C2186BF
+0x0000000002206920 37 31 41 37 30 43 30 46 45 32 46 31 45 30 41 45 71A70C0FE2F1E0AE
+0x0000000002206930 46 33 42 44 36 42 37 35 32 37 37 41 41 42 32 30 F3BD6B75277AAB20
...
...
[*] After:
+0x0000000002206910 41 33 39 42 41 36 43 34 31 36 33 32 35 30 46 45 A39BA6C4163250FE
+0x0000000002206920 42 32 41 39 31 41 34 32 46 44 42 46 30 41 32 31 B2A91A42FDBF0A21
+0x0000000002206930 33 34 46 34 36 44 43 45 34 30 42 46 41 42 33 35 34F46DCE40BFAB35
...
...
[*] Previous:
+0x000000000074c460 59 Y
+0x000000000074c470 08 01 00 ...
[*] After:
+0x000000000074c460 06 .
+0x000000000074c470 00 00 00 ...
[*] Previous:
+0x0000000002206900 39 32 39 33 33 92933
[*] After:
+0x0000000002206900 42 34 34 33 38 B4438
*******************************************************
* PatchSolution3 *
*******************************************************
[*] +023e64d4: 4d 49 49 ---> 4d 49 49
[*] +01652e23: 42 49 ---> 42 49
[*] +01652e28: 6a ---> 6a
...
...
...
[*] +023e66d8: 77 49 44 41 ---> 51 49 44 41
[*] +0165f91c: 51 41 ---> 51 41
[*] +0165f921: 42 ---> 42
[*] New RSA-2048 private key has been saved to
C:\Users\DoubleSine\github.com\navicat-keygen\bin\x64-Release\RegPrivateKey.pem
*******************************************************
* PATCH HAS BEEN DONE SUCCESSFULLY! *
* HAVE FUN AND ENJOY~ *
*******************************************************
```
5. Then use `navicat-keygen.exe` to generate __snKey__ and __Activation Code__
```console
$ ./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==
```
9. 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.
+255
View File
@@ -0,0 +1,255 @@
# Navicat Keygen - 如何使用这个注册机? (Linux)
* 维护者:zenuo, DoubleLabyrinth
---
> 可下载[录屏文件](image/Screen_recording.mp4)参考
1. 切换到解压安装包的路径,本示例解压到了 `家目录`,运行Navicat,使其初始化环境:
```console
$ 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位,请下载对应版本
```console
$ curl -O -L https://github.com/DoubleLabyrinth/navicat-keygen/releases/latest/download/navicat-keygen-for-x64.zip
$ unzip navicat-keygen-for-x64.zip
```
3. 下载 `navicat-pacther.sh` 和 `navicat-keygen.sh`
```console
$ 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关闭
```console
$ ./navicat-patcher.sh
```
__Navicat Premium 12.1.22 简体中文版已通过测试__。下面将是一份样例输出:
```
***************************************************
* Navicat Patcher by @DoubleLabyrinth *
* Version: 4.0 *
***************************************************
Press Enter to continue or Ctrl + C to abort.
[+] Try to open Navicat.exe ... Ok!
[+] Try to open libcc.dll ... Ok!
[+] PatchSolution0 ...... Ready to apply
[*] Patch offset = +0x029bccd8
[+] PatchSolution1 ...... Ready to apply
[*] [0] Patch offset = +0x02206c00
[*] [1] Patch offset = +0x0074c489
[*] [2] Patch offset = +0x02206910
[*] [3] Patch offset = +0x0074c46f
[*] [4] Patch offset = +0x02206904
[-] PatchSolution2 ...... Omitted
[+] PatchSolution3 ...... Ready to apply
[*] [ 0] Instruction RVA = 0x016539c8, Patch Offset = +0x023e64d4
[*] [ 1] Instruction RVA = 0x01653a1f, Patch Offset = +0x01652e23
[*] [ 2] Instruction RVA = 0x01653a25, Patch Offset = +0x01652e28
[*] [ 3] Instruction RVA = 0x01653a8c, Patch Offset = +0x01652e8e
...
...
...
[*] [108] Instruction RVA = 0x016604e1, Patch Offset = +0x023e66d8
[*] [109] Instruction RVA = 0x01660518, Patch Offset = +0x0165f91c
[*] [110] Instruction RVA = 0x0166051e, Patch Offset = +0x0165f921
[*] PatchSolution0 is suppressed in order to keep digital signature valid.
[*] Generating new RSA private key, it may take a long time...
[*] Your RSA public key:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1hV66HgU4LrKXWW6O7bK
AN6ZTr5W+Mq8ClTQ+Pc+BdhLu6rww55kVq7OXKGpvx0G4eTafYMGrrBETgDSTaMq
Bx+8bZbGBWh2LtNfqU+xUrpHHBSz0ByBc3iTEzzthJl+Fzf8suDX2lWYIc/Ym/eW
YtxdJ7xOzLb68z4N0zVmA0jFX2FOm75DRYgKqy4SGixapfucL9dVaWVLTUdbrVdj
4LX78t4t5ykbYoThrat4yuLvj/BxLaQ6ivKD+ScfHdtCoY+NA5jmBoUfBq3Q1SXB
iNaoXctbi0/H3MiPu0cRojryAocooF89yFm5/mNnzWGAYPr6DvBI8CDTZmjaQ4oC
aQIDAQAB
-----END PUBLIC KEY-----
*******************************************************
* PatchSolution1 *
*******************************************************
[*] Previous:
+0x0000000002206c00 44 37 35 31 32 35 42 37 30 37 36 37 42 39 34 31 D75125B70767B941
+0x0000000002206c10 34 35 42 34 37 43 31 43 42 33 43 30 37 35 35 45 45B47C1CB3C0755E
+0x0000000002206c20 37 43 43 42 38 38 32 35 43 35 44 43 45 30 43 35 7CCB8825C5DCE0C5
...
...
[*] After:
+0x0000000002206c00 33 43 32 39 30 39 35 38 33 34 38 41 42 43 35 39 3C290958348ABC59
+0x0000000002206c10 36 44 39 30 43 45 45 38 31 36 42 36 39 38 34 44 6D90CEE816B6984D
+0x0000000002206c20 35 32 35 34 37 45 30 32 34 31 42 36 42 43 31 41 52547E0241B6BC1A
...
...
[*] Previous:
+0x000000000074c480 fe ea bc 01 ....
[*] After:
+0x000000000074c480 08 00 00 00 ....
[*] Previous:
+0x0000000002206910 45 31 43 45 44 30 39 42 39 43 32 31 38 36 42 46 E1CED09B9C2186BF
+0x0000000002206920 37 31 41 37 30 43 30 46 45 32 46 31 45 30 41 45 71A70C0FE2F1E0AE
+0x0000000002206930 46 33 42 44 36 42 37 35 32 37 37 41 41 42 32 30 F3BD6B75277AAB20
...
...
[*] After:
+0x0000000002206910 41 33 39 42 41 36 43 34 31 36 33 32 35 30 46 45 A39BA6C4163250FE
+0x0000000002206920 42 32 41 39 31 41 34 32 46 44 42 46 30 41 32 31 B2A91A42FDBF0A21
+0x0000000002206930 33 34 46 34 36 44 43 45 34 30 42 46 41 42 33 35 34F46DCE40BFAB35
...
...
[*] Previous:
+0x000000000074c460 59 Y
+0x000000000074c470 08 01 00 ...
[*] After:
+0x000000000074c460 06 .
+0x000000000074c470 00 00 00 ...
[*] Previous:
+0x0000000002206900 39 32 39 33 33 92933
[*] After:
+0x0000000002206900 42 34 34 33 38 B4438
*******************************************************
* PatchSolution3 *
*******************************************************
[*] +023e64d4: 4d 49 49 ---> 4d 49 49
[*] +01652e23: 42 49 ---> 42 49
[*] +01652e28: 6a ---> 6a
...
...
...
[*] +023e66d8: 77 49 44 41 ---> 51 49 44 41
[*] +0165f91c: 51 41 ---> 51 41
[*] +0165f921: 42 ---> 42
[*] New RSA-2048 private key has been saved to
C:\Users\DoubleSine\github.com\navicat-keygen\bin\x64-Release\RegPrivateKey.pem
*******************************************************
* PATCH HAS BEEN DONE SUCCESSFULLY! *
* HAVE FUN AND ENJOY~ *
*******************************************************
```
5. 接下来使用`navicat-keygen.exe`来生成序列号和激活码
```console
$ ./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里。最后别忘了连按至少两下回车结束输入。
```
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的`手动激活`窗口,最后点`激活`按钮。如果没什么意外的话应该能成功激活。别忘了关闭我们刚刚设置的不存在的代理哦。
+256
View File
@@ -0,0 +1,256 @@
# Navicat Keygen - How to use? (Windows)
[中文版](how-to-use.windows.zh-CN.md)
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 [-dry-run] <Navicat Installation Path> [RSA-2048 PEM File Path]
```
* `[-dry-run]` Run patcher without applying any patches.
__This parameter is optional.__
* `<Navicat Installation Path>`: The full path to Navicat installation folder.
__This parameter must be specified.__
* `[RSA-2048 PEM File Path]`: 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.22 Simplified Chinese version__. The following is an example of output.
```
***************************************************
* Navicat Patcher by @DoubleLabyrinth *
* Version: 4.0 *
***************************************************
Press Enter to continue or Ctrl + C to abort.
[+] Try to open Navicat.exe ... Ok!
[+] Try to open libcc.dll ... Ok!
[+] PatchSolution0 ...... Ready to apply
[*] Patch offset = +0x029bccd8
[+] PatchSolution1 ...... Ready to apply
[*] [0] Patch offset = +0x02206c00
[*] [1] Patch offset = +0x0074c489
[*] [2] Patch offset = +0x02206910
[*] [3] Patch offset = +0x0074c46f
[*] [4] Patch offset = +0x02206904
[-] PatchSolution2 ...... Omitted
[+] PatchSolution3 ...... Ready to apply
[*] [ 0] Instruction RVA = 0x016539c8, Patch Offset = +0x023e64d4
[*] [ 1] Instruction RVA = 0x01653a1f, Patch Offset = +0x01652e23
[*] [ 2] Instruction RVA = 0x01653a25, Patch Offset = +0x01652e28
[*] [ 3] Instruction RVA = 0x01653a8c, Patch Offset = +0x01652e8e
...
...
...
[*] [108] Instruction RVA = 0x016604e1, Patch Offset = +0x023e66d8
[*] [109] Instruction RVA = 0x01660518, Patch Offset = +0x0165f91c
[*] [110] Instruction RVA = 0x0166051e, Patch Offset = +0x0165f921
[*] PatchSolution0 is suppressed in order to keep digital signature valid.
[*] Generating new RSA private key, it may take a long time...
[*] Your RSA public key:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1hV66HgU4LrKXWW6O7bK
AN6ZTr5W+Mq8ClTQ+Pc+BdhLu6rww55kVq7OXKGpvx0G4eTafYMGrrBETgDSTaMq
Bx+8bZbGBWh2LtNfqU+xUrpHHBSz0ByBc3iTEzzthJl+Fzf8suDX2lWYIc/Ym/eW
YtxdJ7xOzLb68z4N0zVmA0jFX2FOm75DRYgKqy4SGixapfucL9dVaWVLTUdbrVdj
4LX78t4t5ykbYoThrat4yuLvj/BxLaQ6ivKD+ScfHdtCoY+NA5jmBoUfBq3Q1SXB
iNaoXctbi0/H3MiPu0cRojryAocooF89yFm5/mNnzWGAYPr6DvBI8CDTZmjaQ4oC
aQIDAQAB
-----END PUBLIC KEY-----
*******************************************************
* PatchSolution1 *
*******************************************************
[*] Previous:
+0x0000000002206c00 44 37 35 31 32 35 42 37 30 37 36 37 42 39 34 31 D75125B70767B941
+0x0000000002206c10 34 35 42 34 37 43 31 43 42 33 43 30 37 35 35 45 45B47C1CB3C0755E
+0x0000000002206c20 37 43 43 42 38 38 32 35 43 35 44 43 45 30 43 35 7CCB8825C5DCE0C5
...
...
[*] After:
+0x0000000002206c00 33 43 32 39 30 39 35 38 33 34 38 41 42 43 35 39 3C290958348ABC59
+0x0000000002206c10 36 44 39 30 43 45 45 38 31 36 42 36 39 38 34 44 6D90CEE816B6984D
+0x0000000002206c20 35 32 35 34 37 45 30 32 34 31 42 36 42 43 31 41 52547E0241B6BC1A
...
...
[*] Previous:
+0x000000000074c480 fe ea bc 01 ....
[*] After:
+0x000000000074c480 08 00 00 00 ....
[*] Previous:
+0x0000000002206910 45 31 43 45 44 30 39 42 39 43 32 31 38 36 42 46 E1CED09B9C2186BF
+0x0000000002206920 37 31 41 37 30 43 30 46 45 32 46 31 45 30 41 45 71A70C0FE2F1E0AE
+0x0000000002206930 46 33 42 44 36 42 37 35 32 37 37 41 41 42 32 30 F3BD6B75277AAB20
...
...
[*] After:
+0x0000000002206910 41 33 39 42 41 36 43 34 31 36 33 32 35 30 46 45 A39BA6C4163250FE
+0x0000000002206920 42 32 41 39 31 41 34 32 46 44 42 46 30 41 32 31 B2A91A42FDBF0A21
+0x0000000002206930 33 34 46 34 36 44 43 45 34 30 42 46 41 42 33 35 34F46DCE40BFAB35
...
...
[*] Previous:
+0x000000000074c460 59 Y
+0x000000000074c470 08 01 00 ...
[*] After:
+0x000000000074c460 06 .
+0x000000000074c470 00 00 00 ...
[*] Previous:
+0x0000000002206900 39 32 39 33 33 92933
[*] After:
+0x0000000002206900 42 34 34 33 38 B4438
*******************************************************
* PatchSolution3 *
*******************************************************
[*] +023e64d4: 4d 49 49 ---> 4d 49 49
[*] +01652e23: 42 49 ---> 42 49
[*] +01652e28: 6a ---> 6a
...
...
...
[*] +023e66d8: 77 49 44 41 ---> 51 49 44 41
[*] +0165f91c: 51 41 ---> 51 41
[*] +0165f921: 42 ---> 42
[*] New RSA-2048 private key has been saved to
C:\Users\DoubleSine\github.com\navicat-keygen\bin\x64-Release\RegPrivateKey.pem
*******************************************************
* PATCH HAS BEEN DONE SUCCESSFULLY! *
* HAVE FUN AND ENJOY~ *
*******************************************************
```
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)__
```console
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.
+254
View File
@@ -0,0 +1,254 @@
# Navicat Keygen - 如何使用这个注册机? (Windows)
1. [从这里](https://github.com/DoubleLabyrinth/navicat-keygen/releases)下载最新的release。
2. 使用`navicat-patcher.exe`替换掉`navicat.exe``libcc.dll`里的Navicat激活公钥。
```
navicat-patcher.exe [-dry-run] <Navicat Installation Path> [RSA-2048 PEM File Path]
```
* `[-dry-run]`: 运行patcher但不对Navicat程序做任何修改。
__这个参数是可选的。__
* `<Navicat Installation Path>`: Navicat的完整安装路径。
__这个参数必须指定。__
* `[RSA-2048 PEM File Path]`: RSA-2048私钥文件的完整路径或相对路径。
__这个参数是可选的。__ 如果未指定,`navicat-patcher.exe`将会在当前目录生成一个新的RSA-2048私钥文件。
__例如:(在cmd.exe中)__
```
navicat-patcher.exe "C:\Program Files\PremiumSoft\Navicat Premium 12"
```
__Navicat Premium 12.1.22 简体中文版已通过测试__。下面将是一份样例输出:
```
***************************************************
* Navicat Patcher by @DoubleLabyrinth *
* Version: 4.0 *
***************************************************
Press Enter to continue or Ctrl + C to abort.
[+] Try to open Navicat.exe ... Ok!
[+] Try to open libcc.dll ... Ok!
[+] PatchSolution0 ...... Ready to apply
[*] Patch offset = +0x029bccd8
[+] PatchSolution1 ...... Ready to apply
[*] [0] Patch offset = +0x02206c00
[*] [1] Patch offset = +0x0074c489
[*] [2] Patch offset = +0x02206910
[*] [3] Patch offset = +0x0074c46f
[*] [4] Patch offset = +0x02206904
[-] PatchSolution2 ...... Omitted
[+] PatchSolution3 ...... Ready to apply
[*] [ 0] Instruction RVA = 0x016539c8, Patch Offset = +0x023e64d4
[*] [ 1] Instruction RVA = 0x01653a1f, Patch Offset = +0x01652e23
[*] [ 2] Instruction RVA = 0x01653a25, Patch Offset = +0x01652e28
[*] [ 3] Instruction RVA = 0x01653a8c, Patch Offset = +0x01652e8e
...
...
...
[*] [108] Instruction RVA = 0x016604e1, Patch Offset = +0x023e66d8
[*] [109] Instruction RVA = 0x01660518, Patch Offset = +0x0165f91c
[*] [110] Instruction RVA = 0x0166051e, Patch Offset = +0x0165f921
[*] PatchSolution0 is suppressed in order to keep digital signature valid.
[*] Generating new RSA private key, it may take a long time...
[*] Your RSA public key:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1hV66HgU4LrKXWW6O7bK
AN6ZTr5W+Mq8ClTQ+Pc+BdhLu6rww55kVq7OXKGpvx0G4eTafYMGrrBETgDSTaMq
Bx+8bZbGBWh2LtNfqU+xUrpHHBSz0ByBc3iTEzzthJl+Fzf8suDX2lWYIc/Ym/eW
YtxdJ7xOzLb68z4N0zVmA0jFX2FOm75DRYgKqy4SGixapfucL9dVaWVLTUdbrVdj
4LX78t4t5ykbYoThrat4yuLvj/BxLaQ6ivKD+ScfHdtCoY+NA5jmBoUfBq3Q1SXB
iNaoXctbi0/H3MiPu0cRojryAocooF89yFm5/mNnzWGAYPr6DvBI8CDTZmjaQ4oC
aQIDAQAB
-----END PUBLIC KEY-----
*******************************************************
* PatchSolution1 *
*******************************************************
[*] Previous:
+0x0000000002206c00 44 37 35 31 32 35 42 37 30 37 36 37 42 39 34 31 D75125B70767B941
+0x0000000002206c10 34 35 42 34 37 43 31 43 42 33 43 30 37 35 35 45 45B47C1CB3C0755E
+0x0000000002206c20 37 43 43 42 38 38 32 35 43 35 44 43 45 30 43 35 7CCB8825C5DCE0C5
...
...
[*] After:
+0x0000000002206c00 33 43 32 39 30 39 35 38 33 34 38 41 42 43 35 39 3C290958348ABC59
+0x0000000002206c10 36 44 39 30 43 45 45 38 31 36 42 36 39 38 34 44 6D90CEE816B6984D
+0x0000000002206c20 35 32 35 34 37 45 30 32 34 31 42 36 42 43 31 41 52547E0241B6BC1A
...
...
[*] Previous:
+0x000000000074c480 fe ea bc 01 ....
[*] After:
+0x000000000074c480 08 00 00 00 ....
[*] Previous:
+0x0000000002206910 45 31 43 45 44 30 39 42 39 43 32 31 38 36 42 46 E1CED09B9C2186BF
+0x0000000002206920 37 31 41 37 30 43 30 46 45 32 46 31 45 30 41 45 71A70C0FE2F1E0AE
+0x0000000002206930 46 33 42 44 36 42 37 35 32 37 37 41 41 42 32 30 F3BD6B75277AAB20
...
...
[*] After:
+0x0000000002206910 41 33 39 42 41 36 43 34 31 36 33 32 35 30 46 45 A39BA6C4163250FE
+0x0000000002206920 42 32 41 39 31 41 34 32 46 44 42 46 30 41 32 31 B2A91A42FDBF0A21
+0x0000000002206930 33 34 46 34 36 44 43 45 34 30 42 46 41 42 33 35 34F46DCE40BFAB35
...
...
[*] Previous:
+0x000000000074c460 59 Y
+0x000000000074c470 08 01 00 ...
[*] After:
+0x000000000074c460 06 .
+0x000000000074c470 00 00 00 ...
[*] Previous:
+0x0000000002206900 39 32 39 33 33 92933
[*] After:
+0x0000000002206900 42 34 34 33 38 B4438
*******************************************************
* PatchSolution3 *
*******************************************************
[*] +023e64d4: 4d 49 49 ---> 4d 49 49
[*] +01652e23: 42 49 ---> 42 49
[*] +01652e28: 6a ---> 6a
...
...
...
[*] +023e66d8: 77 49 44 41 ---> 51 49 44 41
[*] +0165f91c: 51 41 ---> 51 41
[*] +0165f921: 42 ---> 42
[*] New RSA-2048 private key has been saved to
C:\Users\DoubleSine\github.com\navicat-keygen\bin\x64-Release\RegPrivateKey.pem
*******************************************************
* PATCH HAS BEEN DONE SUCCESSFULLY! *
* HAVE FUN AND ENJOY~ *
*******************************************************
```
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中)__
```console
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里。最后别忘了连按至少两下回车结束输入。
```
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的`手动激活`窗口,最后点`激活`按钮。如果没什么意外的话应该能成功激活。
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

+30 -20
View File
@@ -1,13 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
# Visual Studio Version 16
VisualStudioVersion = 16.0.29215.179
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "navicat-keygen", "navicat-keygen\navicat-keygen.vcxproj", "{CB49F054-83AB-4C16-B73B-33D7DF696E16}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "navicat-keygen", "navicat-keygen\navicat-keygen.vcxproj", "{BA201764-EECF-4DA8-BCAD-7CFBA301FC9C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "navicat-patcher", "navicat-patcher\navicat-patcher.vcxproj", "{30BE8CAB-6137-4441-9F64-599D0A6EEA0C}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "navicat-patcher", "navicat-patcher\navicat-patcher.vcxproj", "{7EE03EF3-D58D-4B53-913D-4A4DC8A29E34}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "common\common.vcxitems", "{290C5D5E-52D2-4FEF-909F-27FD95AE0AF9}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
common\common.vcxitems*{290c5d5e-52d2-4fef-909f-27fd95ae0af9}*SharedItemsImports = 9
common\common.vcxitems*{7ee03ef3-d58d-4b53-913d-4a4dc8a29e34}*SharedItemsImports = 4
common\common.vcxitems*{ba201764-eecf-4da8-bcad-7cfba301fc9c}*SharedItemsImports = 4
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
@@ -15,24 +22,27 @@ Global
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CB49F054-83AB-4C16-B73B-33D7DF696E16}.Debug|x64.ActiveCfg = Debug|x64
{CB49F054-83AB-4C16-B73B-33D7DF696E16}.Debug|x64.Build.0 = Debug|x64
{CB49F054-83AB-4C16-B73B-33D7DF696E16}.Debug|x86.ActiveCfg = Debug|Win32
{CB49F054-83AB-4C16-B73B-33D7DF696E16}.Debug|x86.Build.0 = Debug|Win32
{CB49F054-83AB-4C16-B73B-33D7DF696E16}.Release|x64.ActiveCfg = Release|x64
{CB49F054-83AB-4C16-B73B-33D7DF696E16}.Release|x64.Build.0 = Release|x64
{CB49F054-83AB-4C16-B73B-33D7DF696E16}.Release|x86.ActiveCfg = Release|Win32
{CB49F054-83AB-4C16-B73B-33D7DF696E16}.Release|x86.Build.0 = Release|Win32
{30BE8CAB-6137-4441-9F64-599D0A6EEA0C}.Debug|x64.ActiveCfg = Debug|x64
{30BE8CAB-6137-4441-9F64-599D0A6EEA0C}.Debug|x64.Build.0 = Debug|x64
{30BE8CAB-6137-4441-9F64-599D0A6EEA0C}.Debug|x86.ActiveCfg = Debug|Win32
{30BE8CAB-6137-4441-9F64-599D0A6EEA0C}.Debug|x86.Build.0 = Debug|Win32
{30BE8CAB-6137-4441-9F64-599D0A6EEA0C}.Release|x64.ActiveCfg = Release|x64
{30BE8CAB-6137-4441-9F64-599D0A6EEA0C}.Release|x64.Build.0 = Release|x64
{30BE8CAB-6137-4441-9F64-599D0A6EEA0C}.Release|x86.ActiveCfg = Release|Win32
{30BE8CAB-6137-4441-9F64-599D0A6EEA0C}.Release|x86.Build.0 = Release|Win32
{BA201764-EECF-4DA8-BCAD-7CFBA301FC9C}.Debug|x64.ActiveCfg = Debug|x64
{BA201764-EECF-4DA8-BCAD-7CFBA301FC9C}.Debug|x64.Build.0 = Debug|x64
{BA201764-EECF-4DA8-BCAD-7CFBA301FC9C}.Debug|x86.ActiveCfg = Debug|Win32
{BA201764-EECF-4DA8-BCAD-7CFBA301FC9C}.Debug|x86.Build.0 = Debug|Win32
{BA201764-EECF-4DA8-BCAD-7CFBA301FC9C}.Release|x64.ActiveCfg = Release|x64
{BA201764-EECF-4DA8-BCAD-7CFBA301FC9C}.Release|x64.Build.0 = Release|x64
{BA201764-EECF-4DA8-BCAD-7CFBA301FC9C}.Release|x86.ActiveCfg = Release|Win32
{BA201764-EECF-4DA8-BCAD-7CFBA301FC9C}.Release|x86.Build.0 = Release|Win32
{7EE03EF3-D58D-4B53-913D-4A4DC8A29E34}.Debug|x64.ActiveCfg = Debug|x64
{7EE03EF3-D58D-4B53-913D-4A4DC8A29E34}.Debug|x64.Build.0 = Debug|x64
{7EE03EF3-D58D-4B53-913D-4A4DC8A29E34}.Debug|x86.ActiveCfg = Debug|Win32
{7EE03EF3-D58D-4B53-913D-4A4DC8A29E34}.Debug|x86.Build.0 = Debug|Win32
{7EE03EF3-D58D-4B53-913D-4A4DC8A29E34}.Release|x64.ActiveCfg = Release|x64
{7EE03EF3-D58D-4B53-913D-4A4DC8A29E34}.Release|x64.Build.0 = Release|x64
{7EE03EF3-D58D-4B53-913D-4A4DC8A29E34}.Release|x86.ActiveCfg = Release|Win32
{7EE03EF3-D58D-4B53-913D-4A4DC8A29E34}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CB1D6B65-6AEA-44E4-8698-0AEBDBC63CD2}
EndGlobalSection
EndGlobal
+92
View File
@@ -0,0 +1,92 @@
#pragma once
#include <Exception.hpp>
#include <ExceptionWin32.hpp>
#include <xstring.hpp>
#include <bytearray.hpp>
#include <wincrypt.h>
#pragma comment(lib, "Crypt32")
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-keygen\\Base64.hpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
std::xstring Base64Encode(const std::bytearray& Bytes) {
if (Bytes.empty()) {
return std::xstring();
} else {
DWORD cchBase64String = 0;
std::xstring Base64String;
auto bResult = CryptBinaryToString(
Bytes.data(),
static_cast<DWORD>(Bytes.size()),
CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF,
NULL,
&cchBase64String
);
if (bResult == FALSE) {
throw Win32Error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), TEXT("CryptBinaryToString failed."));
}
Base64String.resize(cchBase64String - 1);
bResult = CryptBinaryToString(
Bytes.data(),
static_cast<DWORD>(Bytes.size()),
CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF,
Base64String.data(),
&cchBase64String
);
if (bResult == FALSE) {
throw Win32Error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), TEXT("CryptBinaryToString failed."));
}
return Base64String;
}
}
std::bytearray Base64Decode(const std::xstring& Base64String) {
if (Base64String.empty()) {
return std::bytearray();
} else {
DWORD cbBytes = 0;
std::bytearray Bytes;
auto bResult = CryptStringToBinary(
Base64String.c_str(),
NULL,
CRYPT_STRING_BASE64,
NULL,
&cbBytes,
NULL,
NULL
);
if (bResult == FALSE) {
throw Win32Error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), TEXT("CryptStringToBinary failed."))
.AddHint(TEXT("Are you sure it is a Base64 string?"));
}
Bytes.resize(cbBytes);
bResult = CryptStringToBinary(
Base64String.c_str(),
NULL,
CRYPT_STRING_BASE64,
Bytes.data(),
&cbBytes,
NULL,
NULL
);
if (bResult == FALSE) {
throw Win32Error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), TEXT("CryptStringToBinary failed."));
}
return Bytes;
}
}
}
+152
View File
@@ -0,0 +1,152 @@
#include "SerialNumberGenerator.hpp"
#include <ExceptionUser.hpp>
#include <iostream>
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-keygen\\CollectInformation.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace std {
#if defined(_UNICODE) || defined(UNICODE)
static auto& xcin = wcin;
static auto& xcout = wcout;
static auto& xcerr = wcerr;
#else
static auto& xcin = cin;
static auto& xcout = cout;
static auto& xcerr = cerr;
#endif
}
namespace nkg {
[[nodiscard]]
static int ReadInt(int MinVal, int MaxVal, PCTSTR lpszPrompt, PCTSTR lpszErrorMessage) {
int val;
std::xstring s;
while (true) {
std::xcout << lpszPrompt;
if (!std::getline(std::xcin, s)) {
throw UserAbortionError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Abort."));
}
if (s.empty())
continue;
try {
val = std::stoi(s, nullptr, 0);
if (MinVal <= val && val <= MaxVal) {
return val;
} else {
throw std::invalid_argument("");
}
} catch (std::invalid_argument&) {
std::xcout << lpszErrorMessage << std::endl;
}
}
}
[[nodiscard]]
static int ReadInt(int MinVal, int MaxVal, int DefaultVal, PCTSTR lpszPrompt, PCTSTR lpszErrorMessage) {
int val;
std::xstring s;
while (true) {
std::xcout << lpszPrompt;
if (!std::getline(std::xcin, s)) {
throw UserAbortionError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Abort."));
}
if (s.empty()) {
return DefaultVal;
}
try {
val = std::stoi(s, nullptr, 0);
if (MinVal <= val && val <= MaxVal) {
return val;
} else {
throw std::invalid_argument("");
}
} catch (std::invalid_argument&) {
std::xcout << lpszErrorMessage << std::endl;
}
}
}
[[nodiscard]]
SerialNumberGenerator CollectInformationNormal() {
SerialNumberGenerator Generator;
std::xcout << TEXT("[*] Select Navicat product:") << std::endl;
std::xcout << TEXT(" 0. DataModeler") << std::endl;
std::xcout << TEXT(" 1. Premium") << std::endl;
std::xcout << TEXT(" 2. MySQL") << std::endl;
std::xcout << TEXT(" 3. PostgreSQL") << std::endl;
std::xcout << TEXT(" 4. Oracle") << std::endl;
std::xcout << TEXT(" 5. SQLServer") << std::endl;
std::xcout << TEXT(" 6. SQLite") << std::endl;
std::xcout << TEXT(" 7. MariaDB") << std::endl;
std::xcout << TEXT(" 8. MongoDB") << std::endl;
std::xcout << TEXT(" 9. ReportViewer") << std::endl;
std::xcout << std::endl;
Generator.SetProductSignature(
static_cast<NavicatProductType>(ReadInt(0, 9, TEXT("(Input index)> "), TEXT("Invalid index.")))
);
std::xcout << std::endl;
std::xcout << TEXT("[*] Select product language:") << std::endl;
std::xcout << TEXT(" 0. English") << std::endl;
std::xcout << TEXT(" 1. Simplified Chinese") << std::endl;
std::xcout << TEXT(" 2. Traditional Chinese") << std::endl;
std::xcout << TEXT(" 3. Japanese") << std::endl;
std::xcout << TEXT(" 4. Polish") << std::endl;
std::xcout << TEXT(" 5. Spanish") << std::endl;
std::xcout << TEXT(" 6. French") << std::endl;
std::xcout << TEXT(" 7. German") << std::endl;
std::xcout << TEXT(" 8. Korean") << std::endl;
std::xcout << TEXT(" 9. Russian") << std::endl;
std::xcout << TEXT(" 10. Portuguese") << std::endl;
std::xcout << std::endl;
Generator.SetLanguageSignature(
static_cast<NavicatLanguage>(ReadInt(0, 10, TEXT("(Input index)> "), TEXT("Invalid index.")))
);
std::xcout << std::endl;
std::xcout << TEXT("[*] Input major version number:") << std::endl;
Generator.SetVersion(
static_cast<BYTE>(ReadInt(0, 15, 12, TEXT("(range: 0 ~ 15, default: 12)> "), TEXT("Invalid number.")))
);
std::xcout << std::endl;
return Generator;
}
[[nodiscard]]
SerialNumberGenerator CollectInformationAdvanced() {
SerialNumberGenerator Generator;
std::xcout << TEXT("[*] Navicat Product Signature:") << std::endl;
Generator.SetProductSignature(
static_cast<BYTE>(ReadInt(0x00, 0xff, TEXT("(range: 0x00 ~ 0xFF)> "), TEXT("Invalid number.")))
);
std::xcout << std::endl;
std::xcout << TEXT("[*] Navicat Language Signature 0:") << std::endl;
auto s1 = static_cast<BYTE>(ReadInt(0x00, 0xff, TEXT("(range: 0x00 ~ 0xFF)> "), TEXT("Invalid number.")));
std::xcout << std::endl;
std::xcout << TEXT("[*] Navicat Language Signature 1:") << std::endl;
auto s2 = static_cast<BYTE>(ReadInt(0x00, 0xff, TEXT("(range: 0x00 ~ 0xFF)> "), TEXT("Invalid number.")));
Generator.SetLanguageSignature(s1, s2);
std::xcout << std::endl;
std::xcout << TEXT("[*] Input major version number:") << std::endl;
Generator.SetVersion(
static_cast<BYTE>(ReadInt(0, 15, 12, TEXT("(range: 0 ~ 15, default: 12)> "), TEXT("Invalid number.")))
);
std::xcout << std::endl;
return Generator;
}
}
+241
View File
@@ -0,0 +1,241 @@
#include <ExceptionUser.hpp>
#include <ResourceOwned.hpp>
#include <ResourceTraitsWin32.hpp>
#include <xstring.hpp>
#include <bytearray.hpp>
#include <RSACipher.hpp>
#include "Base64.hpp"
#include "SerialNumberGenerator.hpp"
#include <iostream>
#include <ctime>
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-keygen\\GenerateLicense.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace std {
#if defined(_UNICODE) || defined(UNICODE)
static auto & xcin = wcin;
static auto& xcout = wcout;
static auto& xcerr = wcerr;
#else
static auto& xcin = cin;
static auto& xcout = cout;
static auto& xcerr = cerr;
#endif
}
namespace nkg {
void GenerateLicenseText(const RSACipher& Cipher, const SerialNumberGenerator& Generator) {
std::xstring username;
std::xstring organization;
std::string utf8username;
std::string utf8organization;
std::xstring b64RequestCode;
std::bytearray RequestCode;
std::string utf8RequestInfo;
std::string utf8ResponseInfo;
std::bytearray ResponseCode;
std::xstring b64ResponseCode;
std::xcout << TEXT("[*] Your name: ");
if (!std::getline(std::xcin, username)) {
throw UserAbortionError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Abort."));
} else {
utf8username = username.explicit_string(CP_UTF8);
}
std::xcout << TEXT("[*] Your organization: ");
if (!std::getline(std::xcin, organization)) {
throw UserAbortionError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Abort."));
} else {
utf8organization = organization.explicit_string(CP_UTF8);
}
std::xcout << TEXT("[*] Input request code in Base64: (Input empty line to end)") << std::endl;
while (true) {
std::xstring temp;
if (!std::getline(std::xcin, temp)) {
throw UserAbortionError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Abort."));
}
if (temp.empty()) {
break;
}
b64RequestCode.append(temp);
}
RequestCode = Base64Decode(b64RequestCode);
utf8RequestInfo.resize((Cipher.Bits() + 7) / 8);
Cipher.Decrypt(RequestCode.data(), RequestCode.size(), utf8RequestInfo.data(), RSA_PKCS1_PADDING);
while (utf8RequestInfo.back() == '\x00') {
utf8RequestInfo.pop_back();
}
std::xcout << TEXT("[*] Request Info:") << std::endl;
std::xcout << std::xstring(std::xstring_extension{}, utf8RequestInfo, CP_UTF8) << std::endl;
std::xcout << std::endl;
rapidjson::Document json;
rapidjson::Value N_Key;
rapidjson::Value N_Value;
rapidjson::Value O_Key;
rapidjson::Value O_Value;
rapidjson::Value T_Key;
rapidjson::Value T_Value;
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
//
// Begin to parse
//
json.Parse(utf8RequestInfo.c_str());
//
// Remove "Platform" info
//
json.RemoveMember("P");
//
// Set "Name" info
//
N_Key.SetString("N", 1);
N_Value.SetString(utf8username.c_str(), static_cast<rapidjson::SizeType>(utf8username.length()));
//
// Set "Organization" info
//
O_Key.SetString("O", 1);
O_Value.SetString(utf8organization.c_str(), static_cast<rapidjson::SizeType>(utf8organization.length()));
//
// Set "Time" info
//
T_Key.SetString("T", 1);
T_Value.SetUint(static_cast<unsigned int>(std::time(nullptr)));
//
// Add "Name", "Organization" and "Time"
//
json.AddMember(N_Key, N_Value, json.GetAllocator());
json.AddMember(O_Key, O_Value, json.GetAllocator());
json.AddMember(T_Key, T_Value, json.GetAllocator());
json.Accept(writer);
if (buffer.GetSize() > 240) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Response info is too long."));
}
utf8ResponseInfo.assign(buffer.GetString(), buffer.GetSize());
std::xcout << TEXT("[*] Response Info:") << std::endl;
std::xcout << std::xstring(std::xstring_extension{}, utf8ResponseInfo, CP_UTF8) << std::endl;
std::xcout << std::endl;
ResponseCode.resize((Cipher.Bits() + 7) / 8);
Cipher.Encrypt<RSAKeyType::PrivateKey>(utf8ResponseInfo.data(), utf8ResponseInfo.size(), ResponseCode.data(), RSA_PKCS1_PADDING);
b64ResponseCode = Base64Encode(ResponseCode);
std::xcout << TEXT("[*] Activation Code:") << std::endl;
std::xcout << b64ResponseCode << std::endl;
std::xcout << std::endl;
}
void GenerateLicenseBinary(const RSACipher& Cipher, const SerialNumberGenerator& Generator) {
ResourceOwned hLicenseFile(FileHandleTraits{});
std::string utf8SerialNumber = Generator.GetSerialNumberShort().explicit_string(CP_UTF8);
std::xstring username;
std::xstring organization;
std::string utf8username;
std::string utf8organization;
std::string utf8ResponseInfo;
std::bytearray ResponseCode;
std::xcout << TEXT("[*] Your name: ");
if (!std::getline(std::xcin, username)) {
throw UserAbortionError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Abort."));
} else {
utf8username = username.explicit_string(CP_UTF8);
}
std::xcout << TEXT("[*] Your organization: ");
if (!std::getline(std::xcin, organization)) {
throw UserAbortionError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Abort."));
} else {
utf8organization = organization.explicit_string(CP_UTF8);
}
rapidjson::Document json;
rapidjson::Value N_Key;
rapidjson::Value N_Value;
rapidjson::Value O_Key;
rapidjson::Value O_Value;
rapidjson::Value T_Key;
rapidjson::Value T_Value;
rapidjson::Value K_Key;
rapidjson::Value K_Value;
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
json.Parse("{}");
K_Key.SetString("K", 1);
K_Value.SetString(utf8SerialNumber.c_str(), static_cast<rapidjson::SizeType>(utf8SerialNumber.length()));
N_Key.SetString("N", 1);
N_Value.SetString(utf8username.c_str(), static_cast<rapidjson::SizeType>(utf8username.length()));
O_Key.SetString("O", 1);
O_Value.SetString(utf8organization.c_str(), static_cast<rapidjson::SizeType>(utf8organization.length()));
T_Key.SetString("T", 1);
T_Value.SetUint(static_cast<unsigned int>(std::time(nullptr)));
json.AddMember(K_Key, K_Value, json.GetAllocator());
json.AddMember(N_Key, N_Value, json.GetAllocator());
json.AddMember(O_Key, O_Value, json.GetAllocator());
json.AddMember(T_Key, T_Value, json.GetAllocator());
json.Accept(writer);
if (buffer.GetSize() > 240) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Response info is too long."));
}
utf8ResponseInfo.assign(buffer.GetString(), buffer.GetSize());
std::xcout << TEXT("[*] Response Info:") << std::endl;
std::xcout << std::xstring(std::xstring_extension{}, utf8ResponseInfo, CP_UTF8) << std::endl;
std::xcout << std::endl;
ResponseCode.resize((Cipher.Bits() + 7) / 8);
Cipher.Encrypt<RSAKeyType::PrivateKey>(utf8ResponseInfo.data(), utf8ResponseInfo.size(), ResponseCode.data(), RSA_PKCS1_PADDING);
hLicenseFile.TakeOver(
CreateFile(
TEXT("license_file"),
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
)
);
if (hLicenseFile.IsValid() == false) {
throw Win32Error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), TEXT("CreateFile failed."));
}
DWORD NumberOfBytesWritten;
if (!WriteFile(hLicenseFile, ResponseCode.data(), static_cast<DWORD>(ResponseCode.size()), &NumberOfBytesWritten, NULL)) {
throw Win32Error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), TEXT("WriteFile failed."));
}
std::xcout << TEXT("[+] license_file has been generated.") << std::endl;
}
}
-200
View File
@@ -1,200 +0,0 @@
#pragma once
#include "RSACipher.hpp"
#include <openssl/des.h>
#include <string>
#include <random>
class NavicatKeygen {
public:
enum class Language {
English,
SimplifiedChinese,
TraditionalChinese,
Japanese,
Polish,
Spanish,
French,
German,
Korean,
Russian,
Portuguese
};
enum class Product {
DataModeler,
Premium,
MySQL,
PostgreSQL,
Oracle,
SQLServer,
SQLite,
MariaDB,
MongoDB,
ReportViewer
};
private:
std::random_device rand_dev;
std::default_random_engine rand_eng;
std::uniform_int_distribution<int> rand;
uint8_t data[10];
void SetLanguageSigature(Language _language) {
switch (_language) {
case Language::English:
data[5] = 0xAC; // Must be 0xAC for English version.
data[6] = 0x88; // Must be 0x88 for English version.
break;
case Language::SimplifiedChinese:
data[5] = 0xCE; // Must be 0xCE for Simplified Chinese version.
data[6] = 0x32; // Must be 0x32 for Simplified Chinese version.
break;
case Language::TraditionalChinese:
data[5] = 0xAA; // Must be 0xAA for Traditional Chinese version.
data[6] = 0x99; // Must be 0x99 for Traditional Chinese version.
break;
case Language::Japanese:
data[5] = 0xAD; // Must be 0xAD for Japanese version. Discoverer: @dragonflylee
data[6] = 0x82; // Must be 0x82 for Japanese version. Discoverer: @dragonflylee
break;
case Language::Polish:
data[5] = 0xBB; // Must be 0xBB for Polish version. Discoverer: @dragonflylee
data[6] = 0x55; // Must be 0x55 for Polish version. Discoverer: @dragonflylee
break;
case Language::Spanish:
data[5] = 0xAE; // Must be 0xAE for Spanish version. Discoverer: @dragonflylee
data[6] = 0x10; // Must be 0x10 for Spanish version. Discoverer: @dragonflylee
break;
case Language::French:
data[5] = 0xFA; // Must be 0xFA for French version. Discoverer: @Deltafox79
data[6] = 0x20; // Must be 0x20 for French version. Discoverer: @Deltafox79
break;
case Language::German:
data[5] = 0xB1; // Must be 0xB1 for German version. Discoverer: @dragonflylee
data[6] = 0x60; // Must be 0x60 for German version. Discoverer: @dragonflylee
break;
case Language::Korean:
data[5] = 0xB5; // Must be 0xB5 for Korean version. Discoverer: @dragonflylee
data[6] = 0x60; // Must be 0x60 for Korean version. Discoverer: @dragonflylee
break;
case Language::Russian:
data[5] = 0xEE; // Must be 0xB5 for Russian version. Discoverer: @dragonflylee
data[6] = 0x16; // Must be 0x60 for Russian version. Discoverer: @dragonflylee
break;
case Language::Portuguese:
data[5] = 0xCD; // Must be 0xCD for Portuguese version. Discoverer: @dragonflylee
data[6] = 0x49; // Must be 0x49 for Portuguese version. Discoverer: @dragonflylee
break;
default:
break;
}
}
void SetProductSignature(Product _product) {
switch (_product) {
case Product::DataModeler:
data[7] = 0x47;
break;
case Product::Premium:
data[7] = 0x65;
break;
case Product::MySQL:
data[7] = 0x68;
break;
case Product::PostgreSQL:
data[7] = 0x6C;
break;
case Product::Oracle:
data[7] = 0x70;
break;
case Product::SQLServer:
data[7] = 0x74;
break;
case Product::SQLite:
data[7] = 0x78;
break;
case Product::MariaDB:
data[7] = 0x7C;
break;
case Product::MongoDB:
data[7] = 0x80;
break;
case Product::ReportViewer:
data[7] = 0xb;
default:
break;
}
}
void DoEncrypt() {
const_DES_cblock DESKey = { 0x64, 0xAD, 0xF3, 0x2F, 0xAE, 0xF2, 0x1A, 0x27 };
DES_key_schedule schedule;
DES_cblock enc_data;
DES_set_key_unchecked(&DESKey, &schedule);
DES_ecb_encrypt(reinterpret_cast<const_DES_cblock*>(data + 2),
&enc_data,
&schedule,
DES_ENCRYPT);
memcpy(data + 2, enc_data, sizeof(enc_data));
}
public:
NavicatKeygen() : rand_eng(rand_dev()), rand(0, UINT8_MAX), data() {
data[0] = 0x68;
data[1] = 0x2A;
}
void Generate(uint8_t version, Language language, Product product) {
data[2] = rand(rand_eng);
data[3] = rand(rand_eng);
data[4] = rand(rand_eng);
SetLanguageSigature(language);
SetProductSignature(product);
data[8] = version << 4;
data[9] = 0x32;
DoEncrypt();
}
std::string GetKey() const {
std::string Key;
const char EncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
Key.resize(16 + 1);
Key[0] = EncodeTable[data[0] >> 3];
Key[1] = EncodeTable[(data[0] & 0x07) << 2 | data[1] >> 6];
Key[2] = EncodeTable[data[1] >> 1 & 0x1F];
Key[3] = EncodeTable[(data[1] & 0x1) << 4 | data[2] >> 4];
Key[4] = EncodeTable[(data[2] & 0xF) << 1 | data[3] >> 7];
Key[5] = EncodeTable[data[3] >> 2 & 0x1F];
Key[6] = EncodeTable[data[3] << 3 & 0x1F | data[4] >> 5];
Key[7] = EncodeTable[data[4] & 0x1F];
Key[8] = EncodeTable[data[5] >> 3];
Key[9] = EncodeTable[(data[5] & 0x07) << 2 | data[6] >> 6];
Key[10] = EncodeTable[data[6] >> 1 & 0x1F];
Key[11] = EncodeTable[(data[6] & 0x1) << 4 | data[7] >> 4];
Key[12] = EncodeTable[(data[7] & 0xF) << 1 | data[8] >> 7];
Key[13] = EncodeTable[data[8] >> 2 & 0x1F];
Key[14] = EncodeTable[data[8] << 3 & 0x1F | data[9] >> 5];
Key[15] = EncodeTable[data[9] & 0x1F];
Key[16] = 0;
return Key;
}
std::string GetFormatedKey() const {
std::string Key = GetKey();
auto ptr = Key.begin() + 4;
Key.insert(ptr++, '-');
ptr += 4;
Key.insert(ptr++, '-');
ptr += 4;
Key.insert(ptr++, '-');
return Key;
}
};
-266
View File
@@ -1,266 +0,0 @@
#pragma once
#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <string>
#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
class RSACipher {
private:
RSA * _RsaObj;
RSACipher() : _RsaObj(nullptr) {}
RSACipher(RSA* lpRsa) : _RsaObj(lpRsa) {}
RSACipher(const RSACipher&) = delete;
RSACipher(RSACipher&&) = delete;
RSACipher& operator=(const RSACipher&) = delete;
RSACipher& operator=(RSACipher&&) = delete;
public:
enum class KeyType {
PrivateKey,
PublicKey
};
enum class KeyFormat {
NotSpecified,
PEM,
PKCS1
};
~RSACipher() {
if (_RsaObj)
RSA_free(_RsaObj);
_RsaObj = nullptr;
}
static RSACipher* Create() {
RSACipher* aCipher = new RSACipher(RSA_new());
if (aCipher->_RsaObj == nullptr) {
delete aCipher;
aCipher = nullptr;
}
return aCipher;
}
bool GenerateKey(int bits, unsigned long long e = RSA_F4) {
bool bSuccess = false;
BIGNUM* bn_e = nullptr;
bn_e = BN_new();
if (bn_e == nullptr)
goto ON_RSACipher_GenerateKey0_ERROR;
if (!BN_set_word(bn_e, e))
goto ON_RSACipher_GenerateKey0_ERROR;
if (!RSA_generate_key_ex(_RsaObj, bits, bn_e, nullptr))
goto ON_RSACipher_GenerateKey0_ERROR;
bSuccess = true;
ON_RSACipher_GenerateKey0_ERROR:
if (bn_e)
BN_free(bn_e);
return bSuccess;
}
template<KeyType _Type, KeyFormat _Format = KeyFormat::NotSpecified>
bool ExportKeyToFile(const std::string& filename) {
static_assert(
_Type == KeyType::PrivateKey || (_Format == KeyFormat::PEM || _Format == KeyFormat::PKCS1),
"Not supported format."
);
bool bSuccess = false;
BIO* bio_file = nullptr;
bio_file = BIO_new_file(filename.c_str(), "w");
if (bio_file == nullptr)
goto ON_RSACipher_ExportKeyToFile_0_ERROR;
if (_Type == KeyType::PrivateKey) {
bSuccess = PEM_write_bio_RSAPrivateKey(bio_file, _RsaObj, nullptr, nullptr, 0, nullptr, nullptr) ? true : false;
} else {
if (_Format == KeyFormat::PEM)
bSuccess = PEM_write_bio_RSA_PUBKEY(bio_file, _RsaObj) ? true : false;
else if (_Format == KeyFormat::PKCS1)
bSuccess = PEM_write_bio_RSAPublicKey(bio_file, _RsaObj) ? true : false;
}
ON_RSACipher_ExportKeyToFile_0_ERROR:
return bSuccess;
}
template<KeyType _Type, KeyFormat _Format = KeyFormat::NotSpecified>
std::string ExportKeyString() {
static_assert(
_Type == KeyType::PrivateKey || (_Format == KeyFormat::PEM || _Format == KeyFormat::PKCS1),
"Not supported format."
);
std::string KeyString;
BIO* bio_mem = nullptr;
int len = 0;
const char* lpdata = nullptr;
bio_mem = BIO_new(BIO_s_mem());
if (bio_mem == nullptr)
goto ON_RSACipher_ExportKeyString_0_ERROR;
if (_Type == KeyType::PrivateKey) {
if (!PEM_write_bio_RSAPrivateKey(bio_mem, _RsaObj, nullptr, nullptr, 0, nullptr, nullptr))
goto ON_RSACipher_ExportKeyString_0_ERROR;
} else {
if (_Format == KeyFormat::PEM) {
if (!PEM_write_bio_RSA_PUBKEY(bio_mem, _RsaObj))
goto ON_RSACipher_ExportKeyString_0_ERROR;
} else if (_Format == KeyFormat::PKCS1) {
if (!PEM_write_bio_RSAPublicKey(bio_mem, _RsaObj))
goto ON_RSACipher_ExportKeyString_0_ERROR;
}
}
len = BIO_get_mem_data(bio_mem, &lpdata);
KeyString.resize(len);
memcpy(KeyString.data(), lpdata, len);
ON_RSACipher_ExportKeyString_0_ERROR:
if (bio_mem)
BIO_free_all(bio_mem);
return KeyString;
}
template<KeyType _Type, KeyFormat _Format = KeyFormat::NotSpecified>
bool ImportKeyFromFile(const std::string& filename) {
static_assert(
_Type == KeyType::PrivateKey || (_Format == KeyFormat::PEM || _Format == KeyFormat::PKCS1),
"Not supported format."
);
bool bSuccess = false;
BIO* bio_file = nullptr;
RSA* _newRsaObj = nullptr;
bio_file = BIO_new_file(filename.c_str(), "r");
if (bio_file == nullptr)
goto ON_RSACipher_ImportKeyFromFile_0_ERROR;
if (_Type == KeyType::PrivateKey) {
_newRsaObj = PEM_read_bio_RSAPrivateKey(bio_file, nullptr, nullptr, nullptr);
} else {
if (_Format == KeyFormat::PEM)
_newRsaObj = PEM_read_bio_RSA_PUBKEY(bio_file, nullptr, nullptr, nullptr);
else if (_Format == KeyFormat::PKCS1)
_newRsaObj = PEM_read_bio_RSAPublicKey(bio_file, nullptr, nullptr, nullptr);
}
if (_newRsaObj) {
RSA_free(_RsaObj);
_RsaObj = _newRsaObj;
bSuccess = true;
}
ON_RSACipher_ImportKeyFromFile_0_ERROR:
if (bio_file)
BIO_free_all(bio_file);
return bSuccess;
}
template<KeyType _Type, KeyFormat _Format = KeyFormat::NotSpecified>
bool ImportKeyString(const std::string& KeyString) {
static_assert(
_Type == KeyType::PrivateKey || (_Format == KeyFormat::PEM || _Format == KeyFormat::PKCS1),
"Not supported format."
);
bool bSuccess = false;
BIO* bio_mem = nullptr;
RSA* _newRsaObj = nullptr;
bio_mem = BIO_new(BIO_s_mem());
if (bio_mem == nullptr)
goto ON_RSACipher_ImportKeyString_0_ERROR;
BIO_puts(bio_mem, KeyString.c_str());
if (_Type == KeyType::PrivateKey) {
_newRsaObj = PEM_read_bio_RSAPrivateKey(bio_mem, nullptr, nullptr, nullptr);
} else {
if (_Format == KeyFormat::PEM)
_newRsaObj = PEM_read_bio_RSA_PUBKEY(bio_mem, nullptr, nullptr, nullptr);
else if (_Format == KeyFormat::PKCS1)
_newRsaObj = PEM_read_bio_RSAPublicKey(bio_mem, nullptr, nullptr, nullptr);
}
if (_newRsaObj) {
RSA_free(_RsaObj);
_RsaObj = _newRsaObj;
bSuccess = true;
}
ON_RSACipher_ImportKeyString_0_ERROR:
if (bio_mem)
BIO_free_all(bio_mem);
return bSuccess;
}
template<KeyType _Type = KeyType::PublicKey>
int Encrypt(const void* from, int len, void* to, int padding) {
int write_bytes = 0;
if (_Type == KeyType::PrivateKey) {
write_bytes = RSA_private_encrypt(len,
reinterpret_cast<const unsigned char*>(from),
reinterpret_cast<unsigned char*>(to),
_RsaObj,
padding);
} else {
write_bytes = RSA_public_encrypt(len,
reinterpret_cast<const unsigned char*>(from),
reinterpret_cast<unsigned char*>(to),
_RsaObj,
padding);
}
if (write_bytes == -1)
write_bytes = 0;
return write_bytes;
}
template<KeyType _Type = KeyType::PrivateKey>
int Decrypt(const void* from, int len, void* to, int padding) {
int write_bytes = 0;
if (_Type == KeyType::PrivateKey) {
write_bytes = RSA_private_decrypt(len,
reinterpret_cast<const unsigned char*>(from),
reinterpret_cast<unsigned char*>(to),
_RsaObj,
padding);
} else {
write_bytes = RSA_public_decrypt(len,
reinterpret_cast<const unsigned char*>(from),
reinterpret_cast<unsigned char*>(to),
_RsaObj,
padding);
}
if (write_bytes == -1)
write_bytes = 0;
return write_bytes;
}
};
+195
View File
@@ -0,0 +1,195 @@
#include "SerialNumberGenerator.hpp"
#include <Exception.hpp>
#include <openssl/des.h>
#include <NTSecAPI.h>
#include <iostream>
#pragma comment(lib, "Advapi32")
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-keygen\\NavicatKeygen.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace std {
#if defined(_UNICODE) || defined(UNICODE)
static auto & xcin = wcin;
static auto& xcout = wcout;
static auto& xcerr = wcerr;
#else
static auto& xcin = cin;
static auto& xcout = cout;
static auto& xcerr = cerr;
#endif
}
namespace nkg {
SerialNumberGenerator::SerialNumberGenerator() noexcept :
_Data{ 0x68 , 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32 } {}
void SerialNumberGenerator::SetLanguageSignature(NavicatLanguage Language) noexcept {
switch (Language) {
case NavicatLanguage::English:
_Data[5] = 0xAC; // Must be 0xAC for English version.
_Data[6] = 0x88; // Must be 0x88 for English version.
break;
case NavicatLanguage::SimplifiedChinese:
_Data[5] = 0xCE; // Must be 0xCE for Simplified Chinese version.
_Data[6] = 0x32; // Must be 0x32 for Simplified Chinese version.
break;
case NavicatLanguage::TraditionalChinese:
_Data[5] = 0xAA; // Must be 0xAA for Traditional Chinese version.
_Data[6] = 0x99; // Must be 0x99 for Traditional Chinese version.
break;
case NavicatLanguage::Japanese:
_Data[5] = 0xAD; // Must be 0xAD for Japanese version. Discoverer: @dragonflylee
_Data[6] = 0x82; // Must be 0x82 for Japanese version. Discoverer: @dragonflylee
break;
case NavicatLanguage::Polish:
_Data[5] = 0xBB; // Must be 0xBB for Polish version. Discoverer: @dragonflylee
_Data[6] = 0x55; // Must be 0x55 for Polish version. Discoverer: @dragonflylee
break;
case NavicatLanguage::Spanish:
_Data[5] = 0xAE; // Must be 0xAE for Spanish version. Discoverer: @dragonflylee
_Data[6] = 0x10; // Must be 0x10 for Spanish version. Discoverer: @dragonflylee
break;
case NavicatLanguage::French:
_Data[5] = 0xFA; // Must be 0xFA for French version. Discoverer: @Deltafox79
_Data[6] = 0x20; // Must be 0x20 for French version. Discoverer: @Deltafox79
break;
case NavicatLanguage::German:
_Data[5] = 0xB1; // Must be 0xB1 for German version. Discoverer: @dragonflylee
_Data[6] = 0x60; // Must be 0x60 for German version. Discoverer: @dragonflylee
break;
case NavicatLanguage::Korean:
_Data[5] = 0xB5; // Must be 0xB5 for Korean version. Discoverer: @dragonflylee
_Data[6] = 0x60; // Must be 0x60 for Korean version. Discoverer: @dragonflylee
break;
case NavicatLanguage::Russian:
_Data[5] = 0xEE; // Must be 0xB5 for Russian version. Discoverer: @dragonflylee
_Data[6] = 0x16; // Must be 0x60 for Russian version. Discoverer: @dragonflylee
break;
case NavicatLanguage::Portuguese:
_Data[5] = 0xCD; // Must be 0xCD for Portuguese version. Discoverer: @dragonflylee
_Data[6] = 0x49; // Must be 0x49 for Portuguese version. Discoverer: @dragonflylee
break;
default:
break;
}
}
void SerialNumberGenerator::SetLanguageSignature(BYTE LanguageSignature0, BYTE LanguageSignature1) noexcept {
_Data[5] = LanguageSignature0;
_Data[6] = LanguageSignature1;
}
void SerialNumberGenerator::SetProductSignature(NavicatProductType ProductType) noexcept {
switch (ProductType) {
case NavicatProductType::DataModeler:
_Data[7] = 0x84;
break;
case NavicatProductType::Premium:
_Data[7] = 0x65;
break;
case NavicatProductType::MySQL:
_Data[7] = 0x68;
break;
case NavicatProductType::PostgreSQL:
_Data[7] = 0x6C;
break;
case NavicatProductType::Oracle:
_Data[7] = 0x70;
break;
case NavicatProductType::SQLServer:
_Data[7] = 0x74;
break;
case NavicatProductType::SQLite:
_Data[7] = 0x78;
break;
case NavicatProductType::MariaDB:
_Data[7] = 0x7C;
break;
case NavicatProductType::MongoDB:
_Data[7] = 0x80;
break;
case NavicatProductType::ReportViewer:
_Data[7] = 0xb;
default:
break;
}
}
void SerialNumberGenerator::SetProductSignature(BYTE ProductSignature) noexcept {
_Data[7] = ProductSignature;
}
void SerialNumberGenerator::SetVersion(BYTE Version) {
if (Version < 0x10) {
_Data[8] = static_cast<BYTE>(Version << 4);
} else {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Invalid version for Navicat."));
}
}
void SerialNumberGenerator::Generate() {
static const TCHAR EncodeTable[] = TEXT("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567");
RtlGenRandom(_Data + 2, 3);
const_DES_cblock key = { 0x64, 0xAD, 0xF3, 0x2F, 0xAE, 0xF2, 0x1A, 0x27 };
DES_key_schedule schedule;
DES_set_key_unchecked(&key, &schedule);
DES_ecb_encrypt(
reinterpret_cast<const_DES_cblock*>(_Data + 2),
reinterpret_cast<const_DES_cblock*>(_Data + 2),
&schedule,
DES_ENCRYPT
);
_SerialNumberShort.resize(16);
_SerialNumberShort[0] = EncodeTable[_Data[0] >> 3];
_SerialNumberShort[1] = EncodeTable[(_Data[0] & 0x07) << 2 | _Data[1] >> 6];
_SerialNumberShort[2] = EncodeTable[_Data[1] >> 1 & 0x1F];
_SerialNumberShort[3] = EncodeTable[(_Data[1] & 0x1) << 4 | _Data[2] >> 4];
_SerialNumberShort[4] = EncodeTable[(_Data[2] & 0xF) << 1 | _Data[3] >> 7];
_SerialNumberShort[5] = EncodeTable[_Data[3] >> 2 & 0x1F];
_SerialNumberShort[6] = EncodeTable[_Data[3] << 3 & 0x1F | _Data[4] >> 5];
_SerialNumberShort[7] = EncodeTable[_Data[4] & 0x1F];
_SerialNumberShort[8] = EncodeTable[_Data[5] >> 3];
_SerialNumberShort[9] = EncodeTable[(_Data[5] & 0x07) << 2 | _Data[6] >> 6];
_SerialNumberShort[10] = EncodeTable[_Data[6] >> 1 & 0x1F];
_SerialNumberShort[11] = EncodeTable[(_Data[6] & 0x1) << 4 | _Data[7] >> 4];
_SerialNumberShort[12] = EncodeTable[(_Data[7] & 0xF) << 1 | _Data[8] >> 7];
_SerialNumberShort[13] = EncodeTable[_Data[8] >> 2 & 0x1F];
_SerialNumberShort[14] = EncodeTable[_Data[8] << 3 & 0x1F | _Data[9] >> 5];
_SerialNumberShort[15] = EncodeTable[_Data[9] & 0x1F];
_SerialNumberLong = std::xstring::format(
TEXT("%.4s-%.4s-%.4s-%.4s"),
_SerialNumberShort.c_str() + 0,
_SerialNumberShort.c_str() + 4,
_SerialNumberShort.c_str() + 8,
_SerialNumberShort.c_str() + 12
);
}
[[nodiscard]]
const std::xstring& SerialNumberGenerator::GetSerialNumberShort() const noexcept {
return _SerialNumberShort;
}
[[nodiscard]]
const std::xstring& SerialNumberGenerator::GetSerialNumberLong() const noexcept {
return _SerialNumberLong;
}
void SerialNumberGenerator::ShowInConsole() const {
std::xcout << TEXT("[*] Serial number:") << std::endl;
std::xcout << _SerialNumberLong << std::endl;
std::xcout << std::endl;
}
}
+64
View File
@@ -0,0 +1,64 @@
#pragma once
#include <windows.h>
#include <xstring.hpp>
namespace nkg {
enum class NavicatLanguage {
English,
SimplifiedChinese,
TraditionalChinese,
Japanese,
Polish,
Spanish,
French,
German,
Korean,
Russian,
Portuguese
};
enum class NavicatProductType {
DataModeler,
Premium,
MySQL,
PostgreSQL,
Oracle,
SQLServer,
SQLite,
MariaDB,
MongoDB,
ReportViewer
};
class SerialNumberGenerator {
private:
BYTE _Data[10];
std::xstring _SerialNumberShort;
std::xstring _SerialNumberLong;
public:
SerialNumberGenerator() noexcept;
void SetLanguageSignature(NavicatLanguage Language) noexcept;
void SetLanguageSignature(BYTE LanguageSignature0, BYTE LanguageSignature1) noexcept;
void SetProductSignature(NavicatProductType ProductType) noexcept;
void SetProductSignature(BYTE ProductSignature) noexcept;
void SetVersion(BYTE Version);
void Generate();
[[nodiscard]]
const std::xstring& GetSerialNumberShort() const noexcept;
[[nodiscard]]
const std::xstring& GetSerialNumberLong() const noexcept;
void ShowInConsole() const;
};
}
+94 -437
View File
@@ -1,460 +1,117 @@
#include <iostream>
#include <ctime>
#include <tchar.h>
#include <stdio.h>
#include <windows.h>
#include <Exception.hpp>
#include <ExceptionUser.hpp>
#include <RSACipher.hpp>
#include "SerialNumberGenerator.hpp"
#include "NavicatKeygen.hpp"
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-keygen\\_tmain.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
namespace nkg {
using fnCollectInformation = SerialNumberGenerator();
using fnGenerateLicense = void(const RSACipher& Cipher, const SerialNumberGenerator& Generator);
bool ConvertToUTF8(LPCSTR from, std::string& to) {
bool bSuccess = false;
int len = 0;
LPWSTR lpUnicodeString = nullptr;
len = MultiByteToWideChar(CP_ACP, NULL, from, -1, NULL, 0);
if (len == 0)
goto ON_ConvertToUTF8_0_ERROR;
lpUnicodeString = reinterpret_cast<LPWSTR>(HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
len * sizeof(WCHAR)));
if (lpUnicodeString == nullptr)
goto ON_ConvertToUTF8_0_ERROR;
if (!MultiByteToWideChar(CP_ACP, NULL, from, -1, lpUnicodeString, len))
goto ON_ConvertToUTF8_0_ERROR;
len = WideCharToMultiByte(CP_UTF8, NULL, lpUnicodeString, -1, NULL, 0, NULL, NULL);
if (len == 0)
goto ON_ConvertToUTF8_0_ERROR;
to.resize(len);
if (!WideCharToMultiByte(CP_UTF8, NULL, lpUnicodeString, -1, to.data(), len, NULL, NULL))
goto ON_ConvertToUTF8_0_ERROR;
while (to.back() == 0)
to.pop_back();
bSuccess = true;
ON_ConvertToUTF8_0_ERROR:
if (lpUnicodeString)
HeapFree(GetProcessHeap(), NULL, lpUnicodeString);
return bSuccess;
SerialNumberGenerator CollectInformationNormal();
SerialNumberGenerator CollectInformationAdvanced();
void GenerateLicenseText(const RSACipher& Cipher, const SerialNumberGenerator& Generator);
void GenerateLicenseBinary(const RSACipher& Cipher, const SerialNumberGenerator& Generator);
}
bool ConvertToUTF8(LPCWSTR from, std::string& to) {
bool bSuccess = false;
int len = 0;
len = WideCharToMultiByte(CP_UTF8, NULL, from, -1, NULL, 0, NULL, NULL);
if (len == 0)
goto ON_ConvertToUTF8_1_ERROR;
to.resize(len);
if (!WideCharToMultiByte(CP_UTF8, NULL, from, -1, to.data(), len, NULL, NULL))
goto ON_ConvertToUTF8_1_ERROR;
while (to.back() == 0)
to.pop_back();
bSuccess = true;
ON_ConvertToUTF8_1_ERROR:
return bSuccess;
static void Welcome() {
_putts(TEXT("***************************************************"));
_putts(TEXT("* Navicat Keygen by @DoubleLabyrinth *"));
_putts(TEXT("* Version: 4.0 *"));
_putts(TEXT("***************************************************"));
_putts(TEXT(""));
}
bool ConvertToUTF8(std::string& str) {
bool bSuccess = false;
std::string temp;
bSuccess = ConvertToUTF8(str.c_str(), temp);
if (!bSuccess)
return false;
str = temp;
return true;
static void Help() {
_putts(TEXT("Usage:"));
_putts(TEXT(" navicat-keygen.exe <-bin|-text> [-adv] <RSA-2048 Private Key File>"));
_putts(TEXT(""));
_putts(TEXT(" <-bin|-text> Specify \"-bin\" to generate \"license_file\" used by Navicat 11."));
_putts(TEXT(" Specify \"-text\" to generate base64-encoded activation code."));
_putts(TEXT(" This parameter must be specified."));
_putts(TEXT(""));
_putts(TEXT(" [-adv] Enable advance mode."));
_putts(TEXT(" This parameter is optional."));
_putts(TEXT(""));
_putts(TEXT(" <RSA-2048 Private Key File> A path to an RSA-2048 private key file."));
_putts(TEXT(" This parameter must be specified."));
_putts(TEXT(""));
_putts(TEXT("Example:"));
_putts(TEXT(" navicat-keygen.exe -text .\\RegPrivateKey.pem"));
}
std::string Base64Encode(const std::vector<uint8_t>& bytes) {
std::string Result;
DWORD pcchString = 0;
int _tmain(int argc, PTSTR argv[]) {
Welcome();
if (bytes.empty())
return Result;
if (argc == 3 || argc == 4) {
nkg::fnCollectInformation* lpfnCollectInformation = nullptr;
nkg::fnGenerateLicense* lpfnGenerateLicense = nullptr;
CryptBinaryToStringA(bytes.data(),
bytes.size(),
CRYPT_STRING_BASE64,
NULL,
&pcchString);
if (pcchString == 0)
return Result;
Result.resize(pcchString + 1);
if (!CryptBinaryToStringA(bytes.data(),
bytes.size(),
CRYPT_STRING_BASE64,
Result.data(),
&pcchString))
Result.clear();
return Result;
}
std::vector<uint8_t> Base64Decode(std::string& str) {
std::vector<uint8_t> Result;
DWORD pcbBinary = 0;
if (str.empty())
return Result;
CryptStringToBinaryA(str.c_str(),
NULL,
CRYPT_STRING_BASE64,
NULL,
&pcbBinary,
NULL,
NULL);
if (pcbBinary == 0)
return Result;
Result.resize(pcbBinary);
if (!CryptStringToBinaryA(str.c_str(),
NULL,
CRYPT_STRING_BASE64,
Result.data(),
&pcbBinary,
NULL,
NULL))
Result.clear();
return Result;
}
void help() {
std::cout << "Usage:" << std::endl;
std::cout << " navicat-keygen.exe <RSA-2048 PrivateKey(PEM file)>" << std::endl;
}
bool GatherInformation(NavicatKeygen::Product& product,
NavicatKeygen::Language& language,
uint8_t& version) {
int index = -1;
std::string temp;
std::cout << "Select Navicat product:" << std::endl
<< "0. DataModeler" << std::endl
<< "1. Premium" << std::endl
<< "2. MySQL" << std::endl
<< "3. PostgreSQL" << std::endl
<< "4. Oracle" << std::endl
<< "5. SQLServer" << std::endl
<< "6. SQLite" << std::endl
<< "7. MariaDB" << std::endl
<< "8. MongoDB" << std::endl
<< "9. ReportViewer" << std::endl
<< std::endl;
while (true) {
std::cout << "(input index)> ";
if (!std::getline(std::cin, temp)) {
return false;
if (_tcsicmp(argv[1], TEXT("-bin")) == 0) {
lpfnGenerateLicense = nkg::GenerateLicenseBinary;
} else if (_tcsicmp(argv[1], TEXT("-text")) == 0) {
lpfnGenerateLicense = nkg::GenerateLicenseText;
} else {
Help();
return -1;
}
try {
index = std::stoi(temp);
switch (index) {
case 0:
product = NavicatKeygen::Product::DataModeler;
break;
case 1:
product = NavicatKeygen::Product::Premium;
break;
case 2:
product = NavicatKeygen::Product::MySQL;
break;
case 3:
product = NavicatKeygen::Product::PostgreSQL;
break;
case 4:
product = NavicatKeygen::Product::Oracle;
break;
case 5:
product = NavicatKeygen::Product::SQLServer;
break;
case 6:
product = NavicatKeygen::Product::SQLite;
break;
case 7:
product = NavicatKeygen::Product::MariaDB;
break;
case 8:
product = NavicatKeygen::Product::MongoDB;
break;
case 9:
product = NavicatKeygen::Product::ReportViewer;
break;
default:
throw std::invalid_argument("Invalid index");
if (argc == 4) {
if (_tcsicmp(argv[2], TEXT("-adv")) == 0) {
lpfnCollectInformation = nkg::CollectInformationAdvanced;
} else {
Help();
return -1;
}
break;
} catch (...) {
std::cout << "Invalid index." << std::endl;
continue;
}
}
std::cout << std::endl;
std::cout << "Select product language:" << std::endl
<< "0. English" << std::endl
<< "1. Simplified Chinese" << std::endl
<< "2. Traditional Chinese" << std::endl
<< "3. Japanese" << std::endl
<< "4. Polish" << std::endl
<< "5. Spanish" << std::endl
<< "6. French" << std::endl
<< "7. German" << std::endl
<< "8. Korean" << std::endl
<< "9. Russian" << std::endl
<< "10. Portuguese" << std::endl
<< std::endl;
while (true) {
std::cout << "(input index)> ";
if (!std::getline(std::cin, temp)) {
return false;
} else {
lpfnCollectInformation = nkg::CollectInformationNormal;
}
try {
index = std::stoi(temp);
switch (index) {
case 0:
language = NavicatKeygen::Language::English;
break;
case 1:
language = NavicatKeygen::Language::SimplifiedChinese;
break;
case 2:
language = NavicatKeygen::Language::TraditionalChinese;
break;
case 3:
language = NavicatKeygen::Language::Japanese;
break;
case 4:
language = NavicatKeygen::Language::Polish;
break;
case 5:
language = NavicatKeygen::Language::Spanish;
break;
case 6:
language = NavicatKeygen::Language::French;
break;
case 7:
language = NavicatKeygen::Language::German;
break;
case 8:
language = NavicatKeygen::Language::Korean;
break;
case 9:
language = NavicatKeygen::Language::Russian;
break;
case 10:
language = NavicatKeygen::Language::Portuguese;
break;
default:
throw std::invalid_argument("Invalid index");
nkg::RSACipher Cipher;
Cipher.ImportKeyFromFile<nkg::RSAKeyType::PrivateKey, nkg::RSAKeyFormat::PEM>(argv[argc - 1]);
if (Cipher.Bits() != 2048) {
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("RSA key length mismatches."))
.AddHint(TEXT("You must provide an RSA key whose modulus length is 2048 bits."));
}
break;
} catch (...) {
std::cout << "Invalid index." << std::endl;
continue;
auto Generator = lpfnCollectInformation();
Generator.Generate();
Generator.ShowInConsole();
lpfnGenerateLicense(Cipher, Generator);
return 0;
} catch (nkg::UserAbortionError&) {
return -1;
} catch (nkg::Exception& e) {
_tprintf_s(TEXT("[-] %s:%zu ->\n"), e.File(), e.Line());
_tprintf_s(TEXT(" %s\n"), e.Message());
if (e.HasErrorCode()) {
_tprintf_s(TEXT(" %s (0x%zx)\n"), e.ErrorString(), e.ErrorCode());
}
for (auto& Hint : e.Hints()) {
_tprintf_s(TEXT(" Hints: %s\n"), Hint.c_str());
}
return -1;
} catch (std::exception& e) {
_tprintf_s(TEXT("[-] %hs\n"), e.what());
return -1;
}
} else {
Help();
return -1;
}
std::cout << std::endl;
while (true) {
std::cout << "(input major version number)> ";
if (!std::getline(std::cin, temp)) {
return false;
}
try {
version = std::stoi(temp);
break;
} catch (...) {
std::cout << "Invalid index." << std::endl;
continue;
}
}
std::cout << std::endl;
}
int _tmain(int argc, LPTSTR argv[]) {
if (argc != 2) {
help();
return 0;
}
std::string RSAPrivateKeyPath;
RSACipher* cipher = nullptr;
std::string RequestCode_b64;
std::string ResponseCode_b64;
std::vector<uint8_t> RequestCode;
std::vector<uint8_t> ResponseCode;
char RequestInfo[256] = {};
char ResponseInfo[256] = {};
rapidjson::Document json;
NavicatKeygen keygen;
NavicatKeygen::Product product;
NavicatKeygen::Language language;
uint8_t version = 0;
std::string username;
std::string organization;
cipher = RSACipher::Create();
if (cipher == nullptr) {
std::cout << "@Function: " << __FUNCSIG__ << " LINE: " << __LINE__ << std::endl;
std::cout << "Failed to create RSACipher." << std::endl;
goto ON_tmain_ERROR;
}
if (!ConvertToUTF8(argv[1], RSAPrivateKeyPath)) {
std::cout << "@Function: " << __FUNCSIG__ << " LINE: " << __LINE__ << std::endl;
std::cout << "ConvertToUTF8 fails." << std::endl;
goto ON_tmain_ERROR;
}
if (!cipher->ImportKeyFromFile<RSACipher::KeyType::PrivateKey>(RSAPrivateKeyPath)) {
std::cout << "@Function: " << __FUNCSIG__ << " LINE: " << __LINE__ << std::endl;
std::cout << "ImportKeyFromFile fails." << std::endl;
goto ON_tmain_ERROR;
}
GatherInformation(product, language, version);
keygen.Generate(version, language, product);
std::cout << "Serial number:" << std::endl;
std::cout << keygen.GetFormatedKey() << std::endl;
std::cout << std::endl;
std::cout << "Your name: ";
if (!std::getline(std::cin, username))
goto ON_tmain_ERROR;
if (!ConvertToUTF8(username)) {
std::cout << "@Function: " << __FUNCSIG__ << " LINE: " << __LINE__ << std::endl;
std::cout << "ConvertToUTF8 fails." << std::endl;
goto ON_tmain_ERROR;
}
std::cout << "Your organization: ";
if (!std::getline(std::cin, organization))
goto ON_tmain_ERROR;
if (!ConvertToUTF8(organization)) {
std::cout << "@Function: " << __FUNCSIG__ << " LINE: " << __LINE__ << std::endl;
std::cout << "ConvertToUTF8 fails." << std::endl;
goto ON_tmain_ERROR;
}
std::cout << "Input request code (in Base64), input empty line to end:" << std::endl;
while (true) {
std::string temp;
if (!std::getline(std::cin, temp))
goto ON_tmain_ERROR;
if (temp.empty())
break;
RequestCode_b64 += temp;
}
RequestCode = Base64Decode(RequestCode_b64);
if (RequestCode.empty()) {
std::cout << "@Function: " << __FUNCSIG__ << " LINE: " << __LINE__ << std::endl;
std::cout << "Base64Decode fails." << std::endl;
goto ON_tmain_ERROR;
}
if (!cipher->Decrypt(RequestCode.data(),
RequestCode.size(),
RequestInfo,
RSA_PKCS1_PADDING)) {
std::cout << "@Function: " << __FUNCSIG__ << " LINE: " << __LINE__ << std::endl;
std::cout << "Decrypt<RSACipher::KeyType::PrivateKey> fails." << std::endl;
goto ON_tmain_ERROR;
}
std::cout << "Request Info:" << std::endl;
std::cout << RequestInfo << std::endl << std::endl;
json.Parse(RequestInfo);
json.RemoveMember("P");
{
rapidjson::Value N_Key;
rapidjson::Value N_Value;
rapidjson::Value O_Key;
rapidjson::Value O_Value;
rapidjson::Value T_Key;
rapidjson::Value T_Value;
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
N_Key.SetString("N", 1);
N_Value.SetString(username.c_str(), username.length());
O_Key.SetString("O", 1);
O_Value.SetString(organization.c_str(), organization.length());
T_Key.SetString("T", 1);
T_Value.SetUint(std::time(nullptr));
json.AddMember(N_Key, N_Value, json.GetAllocator());
json.AddMember(O_Key, O_Value, json.GetAllocator());
json.AddMember(T_Key, T_Value, json.GetAllocator());
json.Accept(writer);
if (buffer.GetSize() > 240) {
std::cout << "Response info too long." << std::endl;
goto ON_tmain_ERROR;
}
memcpy(ResponseInfo, buffer.GetString(), buffer.GetSize());
}
std::cout << "Response Info:" << std::endl;
std::cout << ResponseInfo << std::endl << std::endl;
ResponseCode.resize(256);
if (!cipher->Encrypt<RSACipher::KeyType::PrivateKey>(ResponseInfo,
strlen(ResponseInfo),
ResponseCode.data(),
RSA_PKCS1_PADDING)) {
std::cout << "@Function: " << __FUNCSIG__ << " LINE: " << __LINE__ << std::endl;
std::cout << "Encrypt<RSACipher::KeyType::PrivateKey> fails." << std::endl;
goto ON_tmain_ERROR;
}
ResponseCode_b64 = Base64Encode(ResponseCode);
if (ResponseCode_b64.empty()) {
std::cout << "@Function: " << __FUNCSIG__ << " LINE: " << __LINE__ << std::endl;
std::cout << "Base64Encode fails." << std::endl;
goto ON_tmain_ERROR;
}
std::cout << "License:" << std::endl;
std::cout << ResponseCode_b64 << std::endl;
ON_tmain_ERROR:
if (cipher)
delete cipher;
return 0;
}
+45 -42
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -19,42 +19,50 @@
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{CB49F054-83AB-4C16-B73B-33D7DF696E16}</ProjectGuid>
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{BA201764-EECF-4DA8-BCAD-7CFBA301FC9C}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>navicatkeygen</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<VcpkgTriplet Condition="'$(Platform)'=='Win32'">x86-windows-static</VcpkgTriplet>
<VcpkgTriplet Condition="'$(Platform)'=='x64'">x64-windows-static</VcpkgTriplet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
<Import Project="..\common\common.vcxitems" Label="Shared" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
@@ -71,38 +79,33 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)rapidjson-lib\include;$(SolutionDir)openssl-lib\include;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)openssl-lib\lib;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
<OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)rapidjson-lib\include;$(SolutionDir)openssl-lib\include64;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)openssl-lib\lib64;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)rapidjson-lib\include;$(SolutionDir)openssl-lib\include;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)openssl-lib\lib;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
<OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)rapidjson-lib\include;$(SolutionDir)openssl-lib\include64;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)openssl-lib\lib64;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalOptions>/std:c++latest</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -111,14 +114,13 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalOptions>/std:c++latest</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -128,15 +130,14 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalOptions>/std:c++latest</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -148,15 +149,14 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalOptions>/std:c++latest</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -166,11 +166,14 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="CollectInformation.cpp" />
<ClCompile Include="GenerateLicense.cpp" />
<ClCompile Include="SerialNumberGenerator.cpp" />
<ClCompile Include="_tmain.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="NavicatKeygen.hpp" />
<ClInclude Include="RSACipher.hpp" />
<ClInclude Include="Base64.hpp" />
<ClInclude Include="SerialNumberGenerator.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
+12 -3
View File
@@ -7,7 +7,7 @@
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
@@ -18,12 +18,21 @@
<ClCompile Include="_tmain.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="SerialNumberGenerator.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="CollectInformation.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="GenerateLicense.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="RSACipher.hpp">
<ClInclude Include="Base64.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="NavicatKeygen.hpp">
<ClInclude Include="SerialNumberGenerator.hpp">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ShowAllFiles>true</ShowAllFiles>
</PropertyGroup>
</Project>
+98
View File
@@ -0,0 +1,98 @@
#include "CapstoneDisassembler.hpp"
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\CapstoneDisassembler.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
CapstoneDisassembler::CapstoneDisassembler(const CapstoneEngine& Engine) :
ResourceOwned<CapstoneInsnTraits>(cs_malloc(Engine)),
_Engine(Engine),
_CurrentState{},
_NextState{},
_lpCurrentInsn(nullptr)
{
if (IsValid() == false) {
throw CapstoneError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), cs_errno(Engine), TEXT("cs_malloc failed."));
}
}
CapstoneDisassembler::CapstoneDisassembler(CapstoneDisassembler&& Other) noexcept :
ResourceOwned<CapstoneInsnTraits>(static_cast<ResourceOwned<CapstoneInsnTraits>&&>(Other)),
_Engine(Other._Engine),
_CurrentState(Other._CurrentState),
_NextState(Other._NextState),
_lpCurrentInsn(Other._lpCurrentInsn) {}
CapstoneDisassembler& CapstoneDisassembler::SetContext(const CapstoneContext& Ctx) noexcept {
_lpCurrentInsn = nullptr;
_CurrentState.lpMachineCode = nullptr;
_CurrentState.cbMachineCode = 0;
_CurrentState.Address = 0;
_NextState = Ctx;
return *this;
}
[[nodiscard]]
const CapstoneContext& CapstoneDisassembler::GetContext() const noexcept {
return _NextState;
}
[[nodiscard]]
bool CapstoneDisassembler::Next() noexcept {
bool bSucceed;
CapstoneContext backup = _NextState;
bSucceed = cs_disasm_iter(_Engine.Get(), reinterpret_cast<const uint8_t**>(&_NextState.lpMachineCode), &_NextState.cbMachineCode, &_NextState.Address, Get());
if (bSucceed) {
if (_lpCurrentInsn == nullptr) {
_lpCurrentInsn = Get();
}
_CurrentState = backup;
} else {
_lpCurrentInsn = nullptr;
}
return bSucceed;
}
[[nodiscard]]
const cs_insn* CapstoneDisassembler::GetInstruction() const noexcept {
return _lpCurrentInsn;
}
[[nodiscard]]
const CapstoneContext& CapstoneDisassembler::GetInstructionContext() const noexcept {
return _CurrentState;
}
CapstoneEngine::CapstoneEngine(cs_arch ArchType, cs_mode Mode) {
auto err = cs_open(ArchType, Mode, GetAddressOf());
if (err != CS_ERR_OK) {
throw CapstoneError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), err, TEXT("cs_open failed."));
}
}
void CapstoneEngine::Option(cs_opt_type Type, cs_opt_value Value) {
auto err = cs_option(Get(), Type, Value);
if (err != CS_ERR_OK) {
throw CapstoneError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), err, TEXT("cs_option failed."));
}
}
const char* CapstoneEngine::GetRegisterName(unsigned int reg_id) const noexcept {
return cs_reg_name(Get(), reg_id);
}
[[nodiscard]]
CapstoneDisassembler CapstoneEngine::CreateDisassembler() const {
return CapstoneDisassembler(*this);
}
}
+61
View File
@@ -0,0 +1,61 @@
#pragma once
#include "ExceptionCapstone.hpp"
#include <ResourceOwned.hpp>
#include "ResourceTraitsCapstone.hpp"
namespace nkg {
struct CapstoneContext {
const void* lpMachineCode;
size_t cbMachineCode;
uint64_t Address;
};
class CapstoneEngine;
class CapstoneDisassembler : private ResourceOwned<CapstoneInsnTraits> {
friend class CapstoneEngine;
private:
const CapstoneEngine& _Engine;
CapstoneContext _CurrentState;
CapstoneContext _NextState;
cs_insn* _lpCurrentInsn;
CapstoneDisassembler(const CapstoneEngine& Engine);
public:
CapstoneDisassembler(CapstoneDisassembler&& Other) noexcept;
CapstoneDisassembler& SetContext(const CapstoneContext& Ctx) noexcept;
[[nodiscard]]
const CapstoneContext& GetContext() const noexcept;
[[nodiscard]]
bool Next() noexcept;
[[nodiscard]]
const cs_insn* GetInstruction() const noexcept;
[[nodiscard]]
const CapstoneContext& GetInstructionContext() const noexcept;
};
class CapstoneEngine : private ResourceOwned<CapstoneHandleTraits> {
friend class CapstoneDisassembler;
public:
CapstoneEngine(cs_arch ArchType, cs_mode Mode);
void Option(cs_opt_type Type, cs_opt_value Value);
const char* GetRegisterName(unsigned int reg_id) const noexcept;
[[nodiscard]]
CapstoneDisassembler CreateDisassembler() const;
};
}
-13
View File
@@ -1,13 +0,0 @@
// to avoid "AES_KEY" definaition conflict
#include "NavicatCrypto/NavicatCrypto.hpp"
namespace patcher {
static Navicat11Crypto cipher("23970790", 8);
std::string EncryptPublicKey(const char* public_key, size_t len) {
auto&& temp = cipher.EncryptString(public_key, len);
return std::string(temp.begin(), temp.end());
}
}
+36
View File
@@ -0,0 +1,36 @@
#pragma once
#include <Exception.hpp>
#include <capstone/capstone.h>
namespace nkg {
class CapstoneError final : public Exception {
private:
cs_err _ErrorCode;
std::xstring _ErrorString;
public:
CapstoneError(PCTSTR SourceFile, SIZE_T SourceLine, cs_err CapstoneErrorCode, PCTSTR CustomMessage) noexcept :
Exception(SourceFile, SourceLine, CustomMessage),
_ErrorCode(CapstoneErrorCode),
_ErrorString(std::xstring_extension{}, cs_strerror(CapstoneErrorCode), CP_UTF8) {}
[[nodiscard]]
virtual bool HasErrorCode() const noexcept override {
return true;
}
[[nodiscard]]
virtual ULONG_PTR ErrorCode() const noexcept override {
return _ErrorCode;
}
[[nodiscard]]
virtual PCTSTR ErrorString() const noexcept override {
return _ErrorString.c_str();
}
};
}
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#include <Exception.hpp>
#include <keystone/keystone.h>
namespace nkg {
class KeystoneError final : public Exception {
private:
ks_err _ErrorCode;
std::xstring _ErrorString;
public:
KeystoneError(PCTSTR SourceFile, SIZE_T SourceLine, ks_err KeystoneErrorCode, PCTSTR CustomMessage) noexcept :
Exception(SourceFile, SourceLine, CustomMessage),
_ErrorCode(KeystoneErrorCode),
_ErrorString(std::xstring_extension{}, ks_strerror(KeystoneErrorCode), CP_UTF8) {}
[[nodiscard]]
virtual bool HasErrorCode() const noexcept override {
return true;
}
[[nodiscard]]
virtual ULONG_PTR ErrorCode() const noexcept override {
return _ErrorCode;
}
[[nodiscard]]
virtual PCTSTR ErrorString() const noexcept override {
return _ErrorString.c_str();
}
};
}
+342
View File
@@ -0,0 +1,342 @@
#include "ImageInterpreter.hpp"
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\ImageInterpreter.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
ImageInterpreter::ImageInterpreter() :
_DosHeader(nullptr),
_NtHeaders(nullptr),
_SectionHeaderTable(nullptr),
_VsFixedFileInfo(nullptr) {}
[[nodiscard]]
ImageInterpreter ImageInterpreter::ParseImage(PVOID ImageBase, bool DisableRelocationParsing) {
ImageInterpreter NewImage;
NewImage._DosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(ImageBase);
if (NewImage._DosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Invalid Image. (DOS signature check failure)"))
.AddHint(TEXT("Are you sure you DO provide a valid WinPE file?"));
}
NewImage._NtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(
reinterpret_cast<uint8_t*>(ImageBase) + NewImage._DosHeader->e_lfanew
);
if (NewImage._NtHeaders->Signature != IMAGE_NT_SIGNATURE) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Invalid Image. (NT signature check failure)"))
.AddHint(TEXT("Are you sure you DO provide a valid WinPE file?"));
}
#if defined(_M_AMD64)
if (NewImage._NtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Invalid Image. (Optional header magic check failure)"))
.AddHint(TEXT("Are you sure you DO provide a valid 64-bits WinPE file?"));
}
if (NewImage._NtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Invalid Image. (Machine check failure)"))
.AddHint(TEXT("Are you sure you DO provide a valid 64-bits WinPE file?"));
}
#elif defined(_M_IX86)
if (NewImage._NtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Invalid Image. (Optional header magic check failure)"))
.AddHint(TEXT("Are you sure you DO provide a valid 32-bits WinPE file?"));
}
if (NewImage._NtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Invalid Image. (Machine check failure)"))
.AddHint(TEXT("Are you sure you DO provide a valid 32-bits WinPE file?"));
}
#else
#error "Unsupported architecture."
#endif
NewImage._SectionHeaderTable = reinterpret_cast<PIMAGE_SECTION_HEADER>(
reinterpret_cast<char*>(&NewImage._NtHeaders->OptionalHeader) + NewImage._NtHeaders->FileHeader.SizeOfOptionalHeader
);
for (WORD i = 0; i < NewImage._NtHeaders->FileHeader.NumberOfSections; ++i) {
uint64_t SectionName = *reinterpret_cast<uint64_t*>(NewImage._SectionHeaderTable[i].Name);
if (NewImage._SectionNameTable.find(SectionName) == NewImage._SectionNameTable.end()) {
NewImage._SectionNameTable[SectionName] = i;
}
NewImage._SectionRvaTable[NewImage._SectionHeaderTable[i].VirtualAddress] = i;
NewImage._SectionFileOffsetTable[NewImage._SectionHeaderTable[i].PointerToRawData] = i;
}
if (!DisableRelocationParsing && NewImage._NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0) {
auto RelocTableRva = NewImage._NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
auto RelocTable = NewImage.RvaToPointer<PIMAGE_BASE_RELOCATION>(RelocTableRva);
while (RelocTable->VirtualAddress != 0) {
uintptr_t Rva = RelocTable->VirtualAddress;
PWORD RelocItems = reinterpret_cast<PWORD>(RelocTable + 1);
DWORD RelocItemsCount = (RelocTable->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
for (DWORD i = 0; i < RelocItemsCount; ++i) {
auto RelocType = RelocItems[i] >> 12;
switch (RelocType) {
case IMAGE_REL_BASED_ABSOLUTE:
break;
case IMAGE_REL_BASED_HIGH:
case IMAGE_REL_BASED_LOW:
case IMAGE_REL_BASED_HIGHADJ:
NewImage._RelocationRvaTable[Rva + (RelocItems[i] & 0x0fff)] = 2;
break;
case IMAGE_REL_BASED_HIGHLOW:
NewImage._RelocationRvaTable[Rva + (RelocItems[i] & 0x0fff)] = 4;
break;
#if defined(IMAGE_REL_BASED_DIR64)
case IMAGE_REL_BASED_DIR64:
NewImage._RelocationRvaTable[Rva + (RelocItems[i] & 0x0fff)] = 8;
break;
#endif
default:
break;
}
}
RelocTable = reinterpret_cast<PIMAGE_BASE_RELOCATION>(&RelocItems[RelocItemsCount]);
}
}
if (NewImage._NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress) {
uintptr_t ResourceRva = NewImage._NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
auto ResourceTypeTable =
NewImage.RvaToPointer<PIMAGE_RESOURCE_DIRECTORY>(ResourceRva);
auto ResourceTypeNameEntries =
reinterpret_cast<PIMAGE_RESOURCE_DIRECTORY_ENTRY>(ResourceTypeTable + 1);
auto ResourceTypeIdEntries =
ResourceTypeNameEntries + ResourceTypeTable->NumberOfNamedEntries;
bool VS_FII_Ok = false;
for (WORD i = 0; i < ResourceTypeTable->NumberOfIdEntries && !VS_FII_Ok; ++i) {
if (ResourceTypeIdEntries[i].Id == reinterpret_cast<uintptr_t>(RT_VERSION) && ResourceTypeIdEntries[i].DataIsDirectory) {
auto ResourceNameTable =
NewImage.RvaToPointer<PIMAGE_RESOURCE_DIRECTORY>(ResourceRva + ResourceTypeIdEntries[i].OffsetToDirectory);
auto ResourceNameNameEntries =
reinterpret_cast<PIMAGE_RESOURCE_DIRECTORY_ENTRY>(ResourceNameTable + 1);
auto ResourceNameIdEntries =
ResourceNameNameEntries + ResourceNameTable->NumberOfNamedEntries;
for (WORD j = 0; j < ResourceNameTable->NumberOfIdEntries && !VS_FII_Ok; ++j) {
if (ResourceNameIdEntries[j].Id == VS_VERSION_INFO && ResourceNameIdEntries[j].DataIsDirectory) {
auto ResourceLangTable =
NewImage.RvaToPointer<PIMAGE_RESOURCE_DIRECTORY>(ResourceRva + ResourceNameIdEntries[j].OffsetToDirectory);
auto ResourceLangNameEntries =
reinterpret_cast<PIMAGE_RESOURCE_DIRECTORY_ENTRY>(ResourceLangTable + 1);
auto ResourceLangIdEntries =
ResourceLangNameEntries + ResourceLangTable->NumberOfNamedEntries;
for (WORD k = 0; k < ResourceLangTable->NumberOfIdEntries && !VS_FII_Ok; ++k) {
if (ResourceLangIdEntries[k].Id == MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) && !ResourceLangIdEntries[k].DataIsDirectory) {
auto ResourceDataEntry =
NewImage.RvaToPointer<PIMAGE_RESOURCE_DATA_ENTRY>(ResourceRva + ResourceLangIdEntries[k].OffsetToData);
auto VsVersionInfo = NewImage.RvaToPointer<PBYTE>(ResourceDataEntry->OffsetToData);
auto VsVersionInfoszKey = reinterpret_cast<PWSTR>(VsVersionInfo + 6);
if (_wcsicmp(VsVersionInfoszKey, L"VS_VERSION_INFO") == 0) {
auto p = reinterpret_cast<PBYTE>(VsVersionInfoszKey + _countof(L"VS_VERSION_INFO"));
while (NewImage.PointerToRva(p) % sizeof(DWORD)) {
++p;
}
if (reinterpret_cast<VS_FIXEDFILEINFO*>(p)->dwSignature == VS_FFI_SIGNATURE) {
NewImage._VsFixedFileInfo = reinterpret_cast<VS_FIXEDFILEINFO*>(p);
VS_FII_Ok = true;
}
}
}
}
}
}
}
}
}
return NewImage;
}
[[nodiscard]]
PIMAGE_DOS_HEADER ImageInterpreter::ImageDosHeader() const noexcept {
return _DosHeader;
}
[[nodiscard]]
PIMAGE_NT_HEADERS ImageInterpreter::ImageNtHeaders() const noexcept {
return _NtHeaders;
}
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageInterpreter::ImageSectionTable() const noexcept {
return _SectionHeaderTable;
}
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageInterpreter::ImageSectionHeader(size_t Idx) const {
if (Idx < _NtHeaders->FileHeader.NumberOfSections) {
return _SectionHeaderTable + Idx;
} else {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Idx is out of range."));
}
}
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageInterpreter::ImageSectionHeaderByName(PCSTR lpszSectionName) const {
uint64_t NameValue = 0;
for (int i = 0; i < sizeof(NameValue) && lpszSectionName[i]; ++i)
reinterpret_cast<PSTR>(&NameValue)[i] = lpszSectionName[i];
auto it = _SectionNameTable.find(NameValue);
if (it == _SectionNameTable.end()) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Target section header is not found."))
.AddHint(std::xstring::format(TEXT("lpszSectionName = %s"), lpszSectionName));
}
return &_SectionHeaderTable[it->second];
}
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageInterpreter::ImageSectionHeaderByRva(uintptr_t Rva) const {
auto it = _SectionRvaTable.upper_bound(Rva);
if (it != _SectionRvaTable.begin()) {
--it;
}
auto SectionHeader = &_SectionHeaderTable[it->second];
uintptr_t SectionRvaBegin = SectionHeader->VirtualAddress;
uintptr_t SectionRvaEnd = SectionRvaBegin + SectionHeader->Misc.VirtualSize;
if (SectionRvaBegin <= Rva && Rva < SectionRvaEnd) {
return SectionHeader;
} else {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Target section header is not found."))
.AddHint(std::xstring::format(TEXT("Rva = 0x%zx"), Rva));
}
}
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageInterpreter::ImageSectionHeaderByVa(uintptr_t Va) const {
return ImageSectionHeaderByRva(Va - _NtHeaders->OptionalHeader.ImageBase);
}
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageInterpreter::ImageSectionHeaderByFileOffset(uintptr_t FileOffset) const {
auto it = _SectionFileOffsetTable.upper_bound(FileOffset);
if (it != _SectionFileOffsetTable.begin()) {
--it;
}
auto SectionHeader = &_SectionHeaderTable[it->second];
uintptr_t SectionFileOffsetBegin = SectionHeader->PointerToRawData;
uintptr_t SectionFileOffsetEnd = SectionFileOffsetBegin + SectionHeader->SizeOfRawData;
if (SectionFileOffsetBegin <= FileOffset && FileOffset < SectionFileOffsetEnd) {
return SectionHeader;
} else {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Target section header is not found."))
.AddHint(std::xstring::format(TEXT("FileOffset = 0x%zx"), FileOffset));
}
}
[[nodiscard]]
uintptr_t ImageInterpreter::RvaToVa(uintptr_t Rva) const noexcept {
return Rva + _NtHeaders->OptionalHeader.ImageBase;
}
[[nodiscard]]
uintptr_t ImageInterpreter::RvaToFileOffset(uintptr_t Rva) const {
auto SectionHeader = ImageSectionHeaderByRva(Rva);
return SectionHeader->PointerToRawData + (Rva - static_cast<uintptr_t>(SectionHeader->VirtualAddress));
}
[[nodiscard]]
uintptr_t ImageInterpreter::FileOffsetToRva(uintptr_t FileOffset) const {
auto SectionHeader = ImageSectionHeaderByFileOffset(FileOffset);
return SectionHeader->VirtualAddress + (FileOffset - SectionHeader->PointerToRawData);
}
[[nodiscard]]
uintptr_t ImageInterpreter::FileOffsetToVa(uintptr_t FileOffset) const {
return FileOffsetToRva(FileOffset) + _NtHeaders->OptionalHeader.ImageBase;
}
[[nodiscard]]
uintptr_t ImageInterpreter::VaToRva(uintptr_t Va) const noexcept {
return Va - _NtHeaders->OptionalHeader.ImageBase;
}
[[nodiscard]]
uintptr_t ImageInterpreter::VaToFileOffset(uintptr_t Va) const {
return ImageSectionHeaderByVa(Va)->PointerToRawData;
}
[[nodiscard]]
bool ImageInterpreter::IsRvaRangeInRelocTable(uintptr_t Rva, size_t Size) const {
auto it = _RelocationRvaTable.upper_bound(Rva);
if (it != _RelocationRvaTable.begin()) {
--it;
}
return it->first <= Rva && Rva < it->first + it->second;
}
[[nodiscard]]
bool ImageInterpreter::IsVaRangeInRelocTable(uintptr_t Va, size_t Size) const {
return IsRvaRangeInRelocTable(VaToRva(Va), Size);
}
[[nodiscard]]
bool ImageInterpreter::IsFileOffsetRangeInRelocTable(uintptr_t FileOffset, size_t Size) const {
return IsRvaRangeInRelocTable(FileOffsetToRva(FileOffset), Size);
}
[[nodiscard]]
DWORD ImageInterpreter::ImageFileMajorVersion() const {
if (_VsFixedFileInfo) {
return _VsFixedFileInfo->dwFileVersionMS;
} else {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Image does not have version info."));
}
}
[[nodiscard]]
DWORD ImageInterpreter::ImageFileMinorVersion() const {
if (_VsFixedFileInfo) {
return _VsFixedFileInfo->dwFileVersionLS;
} else {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Image does not have version info."));
}
}
[[nodiscard]]
DWORD ImageInterpreter::ImageProductMajorVersion() const {
if (_VsFixedFileInfo) {
return _VsFixedFileInfo->dwProductVersionMS;
} else {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Image does not have version info."));
}
}
[[nodiscard]]
DWORD ImageInterpreter::ImageProductMinorVersion() const {
if (_VsFixedFileInfo) {
return _VsFixedFileInfo->dwProductVersionLS;
} else {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Image does not have version info."));
}
}
[[nodiscard]]
size_t ImageInterpreter::NumberOfSections() const noexcept {
return _NtHeaders->FileHeader.NumberOfSections;
}
}
+238
View File
@@ -0,0 +1,238 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <Exception.hpp>
#include <windows.h>
#include <map>
#include <utility>
#include <type_traits>
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\ImageInterpreter.hpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
class ImageInterpreter {
private:
PIMAGE_DOS_HEADER _DosHeader;
PIMAGE_NT_HEADERS _NtHeaders;
PIMAGE_SECTION_HEADER _SectionHeaderTable;
std::map<uint64_t, size_t> _SectionNameTable;
std::map<uintptr_t, size_t> _SectionRvaTable;
std::map<uintptr_t, size_t> _SectionFileOffsetTable;
std::map<uintptr_t, size_t> _RelocationRvaTable;
VS_FIXEDFILEINFO* _VsFixedFileInfo;
ImageInterpreter();
public:
[[nodiscard]]
static ImageInterpreter ParseImage(PVOID PtrToImageBase, bool DisableRelocationParsing = false);
template<typename __PtrType = PVOID>
[[nodiscard]]
__PtrType ImageBase() const noexcept {
static_assert(std::is_pointer_v<__PtrType>);
return reinterpret_cast<__PtrType>(_DosHeader);
}
template<typename __PtrType = PVOID>
[[nodiscard]]
__PtrType ImageOffset(size_t Offset) const noexcept {
static_assert(std::is_pointer_v<__PtrType>);
return reinterpret_cast<__PtrType>(reinterpret_cast<char*>(_DosHeader) + Offset);
}
[[nodiscard]]
PIMAGE_DOS_HEADER ImageDosHeader() const noexcept;
[[nodiscard]]
PIMAGE_NT_HEADERS ImageNtHeaders() const noexcept;
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageSectionTable() const noexcept;
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageSectionHeader(size_t Idx) const;
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageSectionHeaderByName(PCSTR lpszSectionName) const;
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageSectionHeaderByRva(uintptr_t Rva) const;
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageSectionHeaderByVa(uintptr_t Va) const;
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageSectionHeaderByFileOffset(uintptr_t FileOffset) const;
template<typename __PtrType = PVOID>
[[nodiscard]]
__PtrType ImageSectionView(PIMAGE_SECTION_HEADER SectionHeader, size_t Offset = 0) const noexcept {
return ImageOffset<__PtrType>(SectionHeader->PointerToRawData + Offset);
}
template<typename __PtrType = PVOID>
[[nodiscard]]
__PtrType ImageSectionViewByName(PCSTR lpszSectionName, size_t Offset = 0) const {
return ImageOffset<__PtrType>(ImageSectionHeaderByName(lpszSectionName)->PointerToRawData + Offset);
}
template<typename __PtrType = PVOID>
[[nodiscard]]
__PtrType ImageSectionViewByRva(uintptr_t Rva, size_t Offset = 0) const {
return ImageOffset<__PtrType>(ImageSectionHeaderByRva(Rva)->PointerToRawData + Offset);
}
template<typename __PtrType = PVOID>
[[nodiscard]]
__PtrType ImageSectionViewByVa(uintptr_t Va, size_t Offset = 0) const {
return ImageOffset<__PtrType>(ImageSectionHeaderByVa(Va)->PointerToRawData + Offset);
}
template<typename __PtrType = PVOID>
[[nodiscard]]
__PtrType ImageSectionViewByFileOffset(uintptr_t FileOffset, size_t Offset = 0) const {
return ImageOffset<__PtrType>(ImageSectionHeaderByFileOffset(FileOffset)->PointerToRawData + Offset);
}
template<typename __ReturnType, typename __Hint>
[[nodiscard]]
__ReturnType SearchSection(PIMAGE_SECTION_HEADER SectionHeader, __Hint&& Hint) const {
static_assert(std::is_pointer_v<__ReturnType>);
auto begin = ImageSectionView<const uint8_t*>(SectionHeader);
auto end = begin + SectionHeader->Misc.VirtualSize;
for (; begin < end; ++begin) {
if (Hint(begin) == true) {
return reinterpret_cast<__ReturnType>(const_cast<uint8_t*>(begin));
}
}
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Data is not found."));
}
template<typename __ReturnType, typename __Hint>
[[nodiscard]]
__ReturnType SearchSection(PIMAGE_SECTION_HEADER SectionHeader, size_t Offset, __Hint&& Hint) const {
static_assert(std::is_pointer_v<__ReturnType>);
auto begin = ImageSectionView<const uint8_t*>(SectionHeader) + Offset;
auto end = begin + SectionHeader->Misc.VirtualSize;
for (; begin < end; ++begin) {
if (Hint(begin) == true) {
return reinterpret_cast<__ReturnType>(const_cast<uint8_t*>(begin));
}
}
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Data is not found."));
}
template<typename __ReturnType, typename __Hint>
[[nodiscard]]
__ReturnType SearchSection(PCSTR lpszSectionName, __Hint&& Hint) const {
return SearchSection<__ReturnType>(ImageSectionHeaderByName(lpszSectionName), std::forward<__Hint>(Hint));
}
template<typename __ReturnType, typename __Hint>
[[nodiscard]]
__ReturnType SearchSection(PCSTR lpszSectionName, size_t Offset, __Hint&& Hint) const {
return SearchSection<__ReturnType>(ImageSectionHeaderByName(lpszSectionName), Offset, std::forward<__Hint>(Hint));
}
[[nodiscard]]
uintptr_t RvaToVa(uintptr_t Rva) const noexcept;
[[nodiscard]]
uintptr_t RvaToFileOffset(uintptr_t Rva) const;
template<typename __PtrType = PVOID>
[[nodiscard]]
__PtrType RvaToPointer(uintptr_t Rva) const {
static_assert(std::is_pointer_v<__PtrType>);
return ImageOffset<__PtrType>(RvaToFileOffset(Rva));
}
[[nodiscard]]
uintptr_t FileOffsetToRva(uintptr_t FileOffset) const;
[[nodiscard]]
uintptr_t FileOffsetToVa(uintptr_t FileOffset) const;
template<typename __PtrType>
[[nodiscard]]
__PtrType FileOffsetToPointer(uintptr_t FileOffset) const noexcept {
return ImageOffset<__PtrType>(FileOffset);
}
[[nodiscard]]
uintptr_t VaToRva(uintptr_t Va) const noexcept;
[[nodiscard]]
uintptr_t VaToFileOffset(uintptr_t Va) const;
template<typename __PtrType>
[[nodiscard]]
__PtrType VaToPointer(uintptr_t Va) const noexcept {
return RvaToPointer<__PtrType>(VaToRva(Va));
}
template<typename __PtrType>
[[nodiscard]]
uintptr_t PointerToFileOffset(__PtrType Ptr) const noexcept {
static_assert(std::is_pointer_v<__PtrType>);
return reinterpret_cast<const volatile char*>(Ptr) - reinterpret_cast<const volatile char*>(_DosHeader);
}
template<typename __PtrType>
[[nodiscard]]
uintptr_t PointerToRva(__PtrType Ptr) const {
return FileOffsetToRva(PointerToFileOffset(Ptr));
}
template<typename __PtrType>
[[nodiscard]]
uintptr_t PointerToVa(__PtrType Ptr) const {
return FileOffsetToVa(PointerToFileOffset(Ptr));
}
[[nodiscard]]
bool IsRvaRangeInRelocTable(uintptr_t Rva, size_t Size) const;
[[nodiscard]]
bool IsVaRangeInRelocTable(uintptr_t Va, size_t Size) const;
[[nodiscard]]
bool IsFileOffsetRangeInRelocTable(uintptr_t FileOffset, size_t Size) const;
template<typename __PtrType>
[[nodiscard]]
bool IsFileOffsetRangeInRelocTable(__PtrType Ptr, size_t Size) const {
return IsRvaRangeInRelocTable(PointerToRva(Ptr), Size);
}
[[nodiscard]]
DWORD ImageFileMajorVersion() const;
[[nodiscard]]
DWORD ImageFileMinorVersion() const;
[[nodiscard]]
DWORD ImageProductMajorVersion() const;
[[nodiscard]]
DWORD ImageProductMinorVersion() const;
[[nodiscard]]
size_t NumberOfSections() const noexcept;
};
}
+44
View File
@@ -0,0 +1,44 @@
#include "KeystoneAssembler.hpp"
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\KeystoneAssembler.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
KeystoneAssembler::KeystoneAssembler(const KeystoneEngine& Engine) noexcept :
_Engine(Engine) {}
[[nodiscard]]
std::vector<uint8_t> KeystoneAssembler::GenerateMachineCode(const char* AssemblyCode, uint64_t Address) const {
ResourceOwned pbMachineCode(KeystoneMallocTraits{});
size_t cbMachineCode = 0;
size_t InstructionsProcessed = 0;
if (ks_asm(_Engine, AssemblyCode, Address, pbMachineCode.GetAddressOf(), &cbMachineCode, &InstructionsProcessed) != 0) {
throw KeystoneError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), ks_errno(_Engine), TEXT("ks_asm failed."));
}
return std::vector<uint8_t>(pbMachineCode.Get(), pbMachineCode.Get() + cbMachineCode);
}
KeystoneEngine::KeystoneEngine(ks_arch ArchType, ks_mode Mode) {
auto err = ks_open(ArchType, Mode, GetAddressOf());
if (err != KS_ERR_OK) {
throw KeystoneError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), err, TEXT("ks_open failed."));
}
}
void KeystoneEngine::Option(ks_opt_type Type, ks_opt_value Value) {
auto err = ks_option(Get(), Type, Value);
if (err != KS_ERR_OK) {
throw KeystoneError(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), err, TEXT("ks_option failed."));
}
}
KeystoneAssembler KeystoneEngine::CreateAssembler() const {
return KeystoneAssembler(*this);
}
}
+39
View File
@@ -0,0 +1,39 @@
#pragma once
#include "ExceptionKeystone.hpp"
#include <ResourceOwned.hpp>
#include "ResourceTraitsKeystone.hpp"
#include <vector>
namespace nkg {
class KeystoneEngine;
class KeystoneAssembler {
friend class KeystoneEngine;
private:
const KeystoneEngine& _Engine;
KeystoneAssembler(const KeystoneEngine& Engine) noexcept;
public:
[[nodiscard]]
std::vector<uint8_t> GenerateMachineCode(const char* AssemblyCode, uint64_t Address = 0) const;
};
class KeystoneEngine : private ResourceOwned<KeystoneHandleTraits> {
friend class KeystoneAssembler;
public:
KeystoneEngine(ks_arch ArchType, ks_mode Mode);
void Option(ks_opt_type Type, ks_opt_value Value);
[[nodiscard]]
KeystoneAssembler CreateAssembler() const;
};
}
+176
View File
@@ -0,0 +1,176 @@
#include <stddef.h>
#include <stdint.h>
#include <tchar.h>
#include <windows.h>
#include <ExceptionWin32.hpp>
#include <xstring.hpp>
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\Misc.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
template<typename __Type>
static inline bool ProbeForRead(const void* p, void* out) {
__try {
*reinterpret_cast<__Type*>(out) = *reinterpret_cast<const __Type*>(p);
return true;
} __except (EXCEPTION_EXECUTE_HANDLER) {
return false;
}
}
//
// Print memory data in [lpMemBegin, lpMemEnd)
// If `base` is not nullptr, print address as offset. Otherwise, as absolute address.
// NOTICE:
// `base` must >= `from`
//
void PrintMemory(const void* lpMemBegin, const void* lpMemEnd, const void* lpBase) noexcept {
auto pbBegin = reinterpret_cast<const uint8_t*>(lpMemBegin);
auto pbEnd = reinterpret_cast<const uint8_t*>(lpMemEnd);
auto pbBase = reinterpret_cast<const uint8_t*>(lpBase);
if (pbBegin >= pbEnd)
return;
while (reinterpret_cast<uintptr_t>(pbBegin) % 16)
pbBegin--;
while (reinterpret_cast<uintptr_t>(pbEnd) % 16)
pbEnd++;
while (pbBegin < pbEnd) {
uint16_t Values[16] = {};
if (pbBase) {
uintptr_t d = pbBegin >= lpBase ? pbBegin - pbBase : pbBase - pbBegin;
if (pbBegin >= lpBase) {
_tprintf_s(TEXT("+0x%.*zx "), static_cast<int>(2 * sizeof(void*)), d);
} else {
_tprintf_s(TEXT("-0x%.*zx "), static_cast<int>(2 * sizeof(void*)), d);
}
} else {
_tprintf_s(TEXT("0x%.*zx "), static_cast<int>(2 * sizeof(void*)), reinterpret_cast<uintptr_t>(pbBegin));
}
for (int i = 0; i < 16; ++i) {
if (pbBegin + i < lpMemBegin || pbBegin + i >= lpMemEnd) {
_tprintf_s(TEXT(" "));
Values[i] = 0xfffe;
} else if (ProbeForRead<uint8_t>(pbBegin + i, Values + i)) {
_tprintf_s(TEXT("%02x "), Values[i]);
} else {
_tprintf_s(TEXT("?? "));
Values[i] = 0xffff;
}
}
_tprintf_s(TEXT(" "));
for (int i = 0; i < 16; ++i) { // NOLINT
if (0x20 <= Values[i] && Values[i] < 0x7f) {
_tprintf_s(TEXT("%c"), Values[i]);
} else if (Values[i] == 0xfffe) {
_tprintf_s(TEXT(" "));
} else {
_tprintf_s(TEXT("."));
}
}
_tprintf_s(TEXT("\n"));
pbBegin += 0x10;
}
}
//
// Print memory data in [lpMem, lpMem + cbMem)
// If `base` is not nullptr, print address as offset. Otherwise, as absolute address.
// NOTICE:
// `base` must >= `from`
//
void PrintMemory(const void* lpMem, size_t cbMem, const void* lpBase) noexcept {
PrintMemory(lpMem, reinterpret_cast<const uint8_t*>(lpMem) + cbMem, lpBase);
}
void PrintBytes(const void* lpMemBegin, const void* lpMemEnd) noexcept {
auto pbMemBegin = reinterpret_cast<const uint8_t*>(lpMemBegin);
auto pbMemEnd = reinterpret_cast<const uint8_t*>(lpMemEnd);
if (pbMemBegin < pbMemEnd) {
uint8_t v;
if (ProbeForRead<uint8_t>(pbMemBegin, &v)) {
_tprintf_s(TEXT("%.2x"), v);
} else {
_tprintf_s(TEXT("??"));
}
++pbMemBegin;
}
while (pbMemBegin < pbMemEnd) {
uint8_t v;
if (ProbeForRead<uint8_t>(pbMemBegin, &v)) {
_tprintf_s(TEXT(" %.2x"), v);
} else {
_tprintf_s(TEXT(" ??"));
}
++pbMemBegin;
}
}
void PrintBytes(const void* lpMem, size_t cbMem) noexcept {
PrintBytes(lpMem, reinterpret_cast<const char*>(lpMem) + cbMem);
}
[[nodiscard]]
bool IsValidDirectoryPath(PCTSTR lpszDirectoryPath) noexcept {
DWORD Attribute = GetFileAttributes(lpszDirectoryPath);
return Attribute != INVALID_FILE_ATTRIBUTES && (Attribute & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
[[nodiscard]]
bool IsValidFilePath(PCTSTR lpszFilePath) noexcept {
DWORD Attribute = GetFileAttributes(lpszFilePath);
return Attribute != INVALID_FILE_ATTRIBUTES && (Attribute & FILE_ATTRIBUTE_DIRECTORY) == 0;
}
[[nodiscard]]
bool IsWineEnvironment() noexcept {
static bool Checked = false;
static bool IsWineEnv = false;
if (Checked == false) {
auto hNtdll = GetModuleHandle(TEXT("ntdll.dll"));
IsWineEnv = hNtdll && GetProcAddress(hNtdll, "wine_get_version") != nullptr;
Checked = true;
}
return IsWineEnv;
}
std::xstring GetCurrentWorkingDirectory() {
std::xstring CurrentDirectory;
auto s = ::GetCurrentDirectory(0, NULL);
if (s == 0) {
throw Win32Error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), TEXT("GetCurrentDirectory failed"));
}
CurrentDirectory.resize(static_cast<size_t>(s) - 1);
s = ::GetCurrentDirectory(s, CurrentDirectory.data());
if (s == 0) {
throw Win32Error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), TEXT("GetCurrentDirectory failed"));
}
return CurrentDirectory;
}
}
+74
View File
@@ -0,0 +1,74 @@
#pragma once
#include <stddef.h>
#include <tchar.h>
#include <windows.h>
#include <type_traits>
#include <xstring.hpp>
#define LOG_SUCCESS(tab, fmt, ...) tab ? _tprintf_s(TEXT("%*c[+] " fmt "\n"), tab, ' ', __VA_ARGS__) : _tprintf_s(TEXT("[+] " fmt "\n"), __VA_ARGS__)
#define LOG_FAILURE(tab, fmt, ...) tab ? _tprintf_s(TEXT("%*c[-] " fmt "\n"), tab, ' ', __VA_ARGS__) : _tprintf_s(TEXT("[-] " fmt "\n"), __VA_ARGS__)
#define LOG_HINT(tab, fmt, ...) tab ? _tprintf_s(TEXT("%*c[*] " fmt "\n"), tab, ' ', __VA_ARGS__) : _tprintf_s(TEXT("[*] " fmt "\n"), __VA_ARGS__)
#define LOG_SELECT(tab, fmt, ...) tab ? _tprintf_s(TEXT("%*c[?] " fmt " "), tab, ' ', __VA_ARGS__) : _tprintf_s(TEXT("[?] " fmt " "), __VA_ARGS__)
namespace nkg {
template<size_t __Len>
constexpr size_t literal_length(const char (&)[__Len]) noexcept {
return __Len - 1;
}
template<typename __PtrType1, typename __PtrType2>
constexpr auto address_delta(__PtrType1 p1, __PtrType2 p2) noexcept {
static_assert(std::is_pointer_v<__PtrType1>);
static_assert(std::is_pointer_v<__PtrType2>);
return reinterpret_cast<const volatile char*>(p1) - reinterpret_cast<const volatile char*>(p2);
}
template<typename __PtrType>
constexpr __PtrType address_offset(__PtrType p, decltype(static_cast<char*>(nullptr) - static_cast<char*>(nullptr)) offset) noexcept {
static_assert(std::is_pointer_v<__PtrType>);
return reinterpret_cast<__PtrType>(
const_cast<char*>(reinterpret_cast<const volatile char*>(p)) + offset
);
}
template<typename __ReturnType, typename __PtrType>
constexpr __ReturnType address_offset_cast(__PtrType p, decltype(static_cast<char*>(nullptr) - static_cast<char*>(nullptr)) offset) noexcept {
static_assert(std::is_pointer_v<__ReturnType>);
static_assert(std::is_pointer_v<__PtrType>);
return reinterpret_cast<__ReturnType>(
const_cast<char*>(reinterpret_cast<const volatile char*>(p)) + offset
);
}
//
// Print memory data in [lpMemBegin, lpMemEnd)
// If `base` is not nullptr, print address as offset. Otherwise, as absolute address.
// NOTICE:
// `base` must >= `from`
//
void PrintMemory(const void* lpMemBegin, const void* lpMemEnd, const void* lpBase) noexcept;
//
// Print memory data in [lpMem, lpMem + cbMem)
// If `base` is not nullptr, print address as offset. Otherwise, as absolute address.
// NOTICE:
// `base` must >= `from`
//
void PrintMemory(const void* lpMem, size_t cbMem, const void* lpBase) noexcept;
void PrintBytes(const void* lpMemBegin, const void* lpMemEnd) noexcept;
void PrintBytes(const void* lpMem, size_t cbMem) noexcept;
[[nodiscard]]
bool IsValidDirectoryPath(PCTSTR lpszDirectoryPath) noexcept;
[[nodiscard]]
bool IsValidFilePath(PCTSTR lpszFilePath) noexcept;
[[nodiscard]]
bool IsWineEnvironment() noexcept;
std::xstring GetCurrentWorkingDirectory();
}
+217
View File
@@ -0,0 +1,217 @@
#pragma once
#include <openssl/crypto.h>
#include <openssl/blowfish.h>
#include <openssl/sha.h>
#include <string>
#include <stdexcept>
class Navicat11Crypto {
protected:
using BlockType = uint8_t[BF_BLOCK];
BF_KEY _BlowfishKey;
template<bool __UpperCase = true>
static void _BytesToHex(const void* src, size_t len, char* dst) noexcept {
auto pb_src = reinterpret_cast<const uint8_t*>(src);
for (size_t i = 0; i < len; ++i) {
char h = pb_src[i] >> 4;
char l = pb_src[i] & 0x0F;
if constexpr (__UpperCase) {
h += h >= 10 ? 'A' - 10 : '0';
l += l >= 10 ? 'A' - 10 : '0';
} else {
h += h >= 10 ? 'a' - 10 : '0';
l += l >= 10 ? 'a' - 10 : '0';
}
dst[2 * i] = h;
dst[2 * i + 1] = l;
}
}
static void _HexToBytes(const char* src, size_t len, void* dst) {
auto pb_dst = reinterpret_cast<uint8_t*>(dst);
for (size_t i = 0; i < len; i += 2) {
uint8_t h = src[i];
uint8_t l = src[i + 1];
if ('0' <= h && h <= '9') {
h -= '0';
} else if ('A' <= h && h <= 'F') {
h -= 'A';
} else if ('a' <= h && h <= 'f') {
h -= 'a';
} else {
throw std::invalid_argument("Non-hex character detected.");
}
if ('0' <= l && l <= '9') {
l -= '0';
} else if ('A' <= l && l <= 'F') {
l -= 'A';
} else if ('a' <= l && l <= 'f') {
l -= 'a';
} else {
throw std::invalid_argument("Non-hex character detected.");
}
pb_dst[i / 2] = (h << 4) ^ l;
}
}
static void _XorBlock(BlockType& a, const BlockType& b) noexcept {
reinterpret_cast<uint64_t&>(a) ^= reinterpret_cast<const uint64_t&>(b);
}
[[nodiscard]]
std::string _EncryptString(const void* lpPlaintext, size_t cbPlaintext) const {
std::string Ciphertext;
if (cbPlaintext) {
Ciphertext.resize(2 * cbPlaintext);
alignas(sizeof(BlockType)) BlockType CV = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
alignas(sizeof(BlockType)) BlockType Block;
auto lpPlaintextBlock = reinterpret_cast<const uint8_t*>(lpPlaintext);
auto lpCiphertextHexBlock = Ciphertext.data();
auto BlockCount = cbPlaintext / BF_BLOCK;
BF_ecb_encrypt(CV, CV, &_BlowfishKey, BF_ENCRYPT);
for (size_t i = 0; i < BlockCount; ++i, lpPlaintextBlock += sizeof(BlockType), lpCiphertextHexBlock += 2 * sizeof(BlockType)) {
memcpy(Block, lpPlaintextBlock, sizeof(BlockType));
_XorBlock(Block, CV);
BF_ecb_encrypt(Block, Block, &_BlowfishKey, BF_ENCRYPT);
_XorBlock(CV, Block);
_BytesToHex(Block, sizeof(Block), lpCiphertextHexBlock);
}
auto LeftByteCount = cbPlaintext % sizeof(BlockType);
if (LeftByteCount) {
BF_ecb_encrypt(CV, CV, &_BlowfishKey, BF_ENCRYPT);
for (size_t i = 0; i < LeftByteCount; ++i) {
CV[i] ^= lpPlaintextBlock[i];
}
_BytesToHex(CV, LeftByteCount, lpCiphertextHexBlock);
}
}
return Ciphertext;
}
[[nodiscard]]
std::string _DecryptString(const char* lpCiphertext, size_t cbCiphertext) const {
std::string Plaintext;
if (cbCiphertext) {
if (cbCiphertext % 2) {
throw std::invalid_argument("Ciphertext is not a hex string.");
}
Plaintext.resize(cbCiphertext / 2);
alignas(sizeof(BlockType)) BlockType CV = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
alignas(sizeof(BlockType)) BlockType Block;
auto lpPlaintextBlock = Plaintext.data();
auto lpCiphertextHexBlock = lpCiphertext;
auto BlockCount = cbCiphertext / (2 * sizeof(BlockType));
BF_ecb_encrypt(CV, CV, &_BlowfishKey, BF_ENCRYPT);
for (size_t i = 0; i < BlockCount; ++i, lpPlaintextBlock += sizeof(BlockType), lpCiphertextHexBlock += 2 * sizeof(BlockType)) {
alignas(sizeof(BlockType)) BlockType CiphertextBlock;
_HexToBytes(lpCiphertextHexBlock, 2 * sizeof(BlockType), CiphertextBlock);
memcpy(Block, CiphertextBlock, sizeof(BlockType));
BF_ecb_encrypt(Block, Block, &_BlowfishKey, BF_DECRYPT);
_XorBlock(Block, CV);
_XorBlock(CV, CiphertextBlock);
memcpy(lpPlaintextBlock, Block, sizeof(BlockType));
}
auto LeftHexCount = cbCiphertext % (2 * sizeof(BlockType));
if (LeftHexCount) {
_HexToBytes(lpCiphertextHexBlock, LeftHexCount, Block);
BF_ecb_encrypt(CV, CV, &_BlowfishKey, BF_ENCRYPT);
for (size_t i = 0; i < LeftHexCount / 2; ++i) {
lpPlaintextBlock[i] = Block[i] ^ CV[i];
}
}
}
return Plaintext;
}
public:
Navicat11Crypto() noexcept {
static const uint8_t PresetKey[SHA_DIGEST_LENGTH] = {
0x42, 0xCE, 0xB2, 0x71, 0xA5, 0xE4, 0x58, 0xB7,
0x4A, 0xEA, 0x93, 0x94, 0x79, 0x22, 0x35, 0x43,
0x91, 0x87, 0x33, 0x40
};
BF_set_key(&_BlowfishKey, sizeof(PresetKey), PresetKey);
}
Navicat11Crypto(const void* lpUserKey, size_t cbUserKey) noexcept {
SetKey(lpUserKey, cbUserKey);
}
Navicat11Crypto(const std::initializer_list<uint8_t>& UserKey) noexcept {
SetKey(UserKey);
}
void SetKey(const void* lpUserKey, size_t cbUserKey) noexcept {
uint8_t MessageDigest[SHA_DIGEST_LENGTH];
BF_set_key(
&_BlowfishKey,
sizeof(MessageDigest),
SHA1(reinterpret_cast<const uint8_t*>(lpUserKey), cbUserKey, MessageDigest)
);
OPENSSL_cleanse(MessageDigest, SHA_DIGEST_LENGTH);
}
void SetKey(const std::initializer_list<uint8_t>& UserKey) noexcept {
uint8_t MessageDigest[SHA_DIGEST_LENGTH];
BF_set_key(
&_BlowfishKey,
sizeof(MessageDigest),
SHA1(UserKey.begin(), UserKey.size(), MessageDigest)
);
OPENSSL_cleanse(MessageDigest, SHA_DIGEST_LENGTH);
}
[[nodiscard]]
std::string EncryptString(const std::string& Plaintext) const {
return _EncryptString(Plaintext.c_str(), Plaintext.length());
}
[[nodiscard]]
std::string DecryptString(const std::string& Ciphertext) const {
return _DecryptString(Ciphertext.c_str(), Ciphertext.length());
}
void Clear() noexcept {
OPENSSL_cleanse(&_BlowfishKey, sizeof(_BlowfishKey));
}
~Navicat11Crypto() noexcept {
Clear();
}
};
@@ -1,291 +0,0 @@
#pragma once
#include "aes.h"
#include "blowfish.h"
#include "SHA1.h"
#include <vector>
class Navicat11Crypto {
protected:
BLOWFISH_KEY BlowfishKey;
void BytesToHex(const void* src, size_t len, char* dst) {
for (size_t i = 0; i < len; ++i) {
char h = reinterpret_cast<const uint8_t*>(src)[i] >> 4;
char l = reinterpret_cast<const uint8_t*>(src)[i] & 0x0F;
h += h >= 10 ? 'A' - 10 : '0';
l += l >= 10 ? 'A' - 10 : '0';
dst[2 * i] = h;
dst[2 * i + 1] = l;
}
}
bool CheckHex(const char* src, size_t len) {
if (len % 2 != 0)
return false;
for (size_t i = 0; i < len; i += 2) {
char h = src[i];
char l = src[i + 1];
if (src[i] < '0' || src[i] > 'F')
return false;
if (src[i] < 'A' && src[i] > '9')
return false;
if (src[i + 1] < '0' || src[i + 1] > 'F')
return false;
if (src[i + 1] < 'A' && src[i + 1] > '9')
return false;
}
return true;
}
void HexToBytes(const char* src, size_t len, void* dst) {
for (size_t i = 0; i < len; i += 2) {
uint8_t h = src[i];
uint8_t l = src[i + 1];
h -= h > '9' ? 'A' - 10 : '0';
l -= l > '9' ? 'A' - 10 : '0';
reinterpret_cast<uint8_t*>(dst)[i / 2] = (h << 4 )^ l;
}
}
public:
Navicat11Crypto() {
const uint8_t DefaultKey[8] = {
'3', 'D', 'C', '5', 'C', 'A', '3', '9'
};
SHA1_DIGEST KeyHash;
accelc_SHA1(DefaultKey, sizeof(DefaultKey), &KeyHash);
accelc_Blowfish_set_key(KeyHash.byte, sizeof(KeyHash), &BlowfishKey);
}
Navicat11Crypto(const void* srcBytes, size_t srclen) {
if (srclen == 0)
srclen = BLOWFISH_MIN_KEY_LENGTH;
if (srclen > BLOWFISH_MAX_KEY_LENGTH)
srclen = BLOWFISH_MAX_KEY_LENGTH;
SHA1_DIGEST KeyHash;
accelc_SHA1(srcBytes, srclen, &KeyHash);
accelc_Blowfish_set_key(KeyHash.byte, sizeof(KeyHash), &BlowfishKey);
}
std::vector<char> EncryptString(const void* srcBytes, size_t srclen) {
std::vector<char> ret;
if (srclen == 0)
return ret;
ret.resize(srclen * 2 + 1);
ret[srclen * 2] = 0;
uint8_t CV[BLOWFISH_BLOCK_SIZE] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
accelc_Blowfish_encrypt(CV, &BlowfishKey, BLOWFISH_BIG_ENDIAN);
const uint64_t* blocks = reinterpret_cast<const uint64_t*>(srcBytes);
size_t blocks_len = srclen / BLOWFISH_BLOCK_SIZE;
for (size_t i = 0; i < blocks_len; ++i) {
union {
uint8_t byte[8];
uint64_t qword;
} temp;
temp.qword = blocks[i];
temp.qword ^= *reinterpret_cast<uint64_t*>(CV);
accelc_Blowfish_encrypt(temp.byte, &BlowfishKey, BLOWFISH_BIG_ENDIAN);
*reinterpret_cast<uint64_t*>(CV) ^= temp.qword;
BytesToHex(temp.byte, 8, ret.data() + 16 * i);
}
if (srclen % BLOWFISH_BLOCK_SIZE) {
accelc_Blowfish_encrypt(CV, &BlowfishKey, BLOWFISH_BIG_ENDIAN);
for (size_t i = 0; i < srclen % BLOWFISH_BLOCK_SIZE; ++i)
CV[i] ^= reinterpret_cast<const uint8_t*>(blocks + blocks_len)[i];
BytesToHex(CV, srclen % BLOWFISH_BLOCK_SIZE, ret.data() + 16 * blocks_len);
}
return ret;
}
std::vector<uint8_t> DecryptString(const char* srchex, size_t srclen) {
std::vector<uint8_t> ret;
if (CheckHex(srchex, srclen) == false)
return ret;
ret.resize(srclen / 2);
uint8_t CV[BLOWFISH_BLOCK_SIZE] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
accelc_Blowfish_encrypt(CV, &BlowfishKey, BLOWFISH_BIG_ENDIAN);
const char (*blocks)[16] = reinterpret_cast<const char (*)[16]>(srchex);
size_t blocks_len = srclen / 16;
for (size_t i = 0; i < blocks_len; ++i) {
union {
uint8_t byte[8];
uint64_t qword;
} temp, temp2;
HexToBytes(blocks[i], 16, temp.byte);
std::memcpy(temp2.byte, temp.byte, 8);
accelc_Blowfish_decrypt(temp.byte, &BlowfishKey, BLOWFISH_BIG_ENDIAN);
temp.qword ^= *reinterpret_cast<uint64_t*>(CV);
*reinterpret_cast<uint64_t*>(ret.data() + 8 * i) = temp.qword;
*reinterpret_cast<uint64_t*>(CV) ^= temp2.qword;
}
if (srclen % 16) {
union {
uint8_t byte[8];
uint64_t qword;
} temp = { };
HexToBytes(blocks[blocks_len], srclen % 16, temp.byte);
accelc_Blowfish_encrypt(CV, &BlowfishKey, BLOWFISH_BIG_ENDIAN);
for (size_t i = 0; i < (srclen % 16) / 2; ++i)
ret[blocks_len * 8 + i] = temp.byte[i] ^ CV[i];
}
return ret;
}
};
class Navicat12Crypto : public Navicat11Crypto {
protected:
AES_KEY AES128Key;
public:
Navicat12Crypto() : Navicat11Crypto() {
uint8_t DefaultKey[16] = {
'l', 'i', 'b', 'c', 'c', 'k', 'e', 'y',
'l', 'i', 'b', 'c', 'c', 'k', 'e', 'y'
};
accelc_AES128_set_key(DefaultKey, &AES128Key);
}
Navicat12Crypto(const void* srcBytes, size_t srclen) :
Navicat11Crypto(srcBytes, srclen) {
uint8_t DefaultKey[16] = {
'l', 'i', 'b', 'c', 'c', 'k', 'e', 'y',
'l', 'i', 'b', 'c', 'c', 'k', 'e', 'y'
};
accelc_AES128_set_key(DefaultKey, &AES128Key);
}
std::vector<char> EncryptString(const void* srcBytes, size_t srclen) {
std::vector<char> ret;
if (srclen == 0)
return ret;
ret.resize((srclen / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE * 2);
union {
uint8_t byte[AES_BLOCK_SIZE];
uint64_t qword[2];
} CV = {
'l', 'i', 'b', 'c', 'c', 'i', 'v', ' ',
'l', 'i', 'b', 'c', 'c', 'i', 'v', ' '
};
const uint8_t (*blocks)[AES_BLOCK_SIZE] = reinterpret_cast<const uint8_t (*)[AES_BLOCK_SIZE]>(srcBytes);
size_t blocks_len = srclen / AES_BLOCK_SIZE;
for (size_t i = 0; i < blocks_len; ++i) {
union {
uint8_t byte[AES_BLOCK_SIZE];
uint64_t qword[2];
} temp;
std::memcpy(temp.byte, blocks[i], AES_BLOCK_SIZE);
temp.qword[0] ^= CV.qword[0];
temp.qword[1] ^= CV.qword[1];
accelc_AES128_encrypt(temp.byte, &AES128Key);
BytesToHex(temp.byte, AES_BLOCK_SIZE, ret.data() + 2 * AES_BLOCK_SIZE * i);
CV.qword[0] = temp.qword[0];
CV.qword[1] = temp.qword[1];
}
uint8_t padding = AES_BLOCK_SIZE - srclen % AES_BLOCK_SIZE;
union {
uint8_t byte[AES_BLOCK_SIZE];
uint64_t qword[2];
} temp;
std::memcpy(temp.byte, blocks[blocks_len], srclen % AES_BLOCK_SIZE);
for (size_t i = srclen % AES_BLOCK_SIZE; i < AES_BLOCK_SIZE; ++i)
temp.byte[i] = padding;
temp.qword[0] ^= CV.qword[0];
temp.qword[1] ^= CV.qword[1];
accelc_AES128_encrypt(temp.byte, &AES128Key);
BytesToHex(temp.byte, AES_BLOCK_SIZE, ret.data() + 2 * AES_BLOCK_SIZE * blocks_len);
return ret;
}
std::vector<uint8_t> DecryptString(const char* srchex, size_t srclen) {
std::vector<uint8_t> ret;
if (srclen % (2 * AES_BLOCK_SIZE) != 0 || CheckHex(srchex, srclen) == false)
return ret;
ret.reserve(srclen / 2);
ret.resize(srclen / 2 - AES_BLOCK_SIZE);
union {
uint8_t byte[AES_BLOCK_SIZE];
uint64_t qword[2];
} CV = {
'l', 'i', 'b', 'c', 'c', 'i', 'v', ' ',
'l', 'i', 'b', 'c', 'c', 'i', 'v', ' '
};
const char (*blocks)[2 * AES_BLOCK_SIZE] = reinterpret_cast<const char(*)[2 * AES_BLOCK_SIZE]>(srchex);
size_t blocks_len = srclen / (2 * AES_BLOCK_SIZE);
for (size_t i = 0; i < blocks_len; ++i) {
union {
uint8_t byte[AES_BLOCK_SIZE];
uint64_t qword[2];
} temp, NextVector;
HexToBytes(blocks[i], 2 * AES_BLOCK_SIZE, temp.byte);
std::memcpy(NextVector.byte, temp.byte, AES_BLOCK_SIZE);
accelc_AES128_decrypt(temp.byte, &AES128Key);
temp.qword[0] ^= CV.qword[0];
temp.qword[1] ^= CV.qword[1];
std::memcpy(ret.data() + AES_BLOCK_SIZE * i, temp.byte, AES_BLOCK_SIZE);
std::memcpy(CV.byte, NextVector.byte, AES_BLOCK_SIZE);
}
union {
uint8_t byte[AES_BLOCK_SIZE];
uint64_t qword[2];
} temp;
HexToBytes(blocks[blocks_len], 2 * AES_BLOCK_SIZE, temp.byte);
accelc_AES128_decrypt(temp.byte, &AES128Key);
temp.qword[0] ^= CV.qword[0];
temp.qword[1] ^= CV.qword[1];
if (temp.byte[AES_BLOCK_SIZE - 1] > AES_BLOCK_SIZE) {
ret.clear();
return ret;
} else {
uint8_t padding = temp.byte[AES_BLOCK_SIZE - 1];
for (int i = AES_BLOCK_SIZE - padding; i < AES_BLOCK_SIZE; ++i)
if (temp.byte[i] != padding) {
ret.clear();
return ret;
}
for (int i = 0; i < (AES_BLOCK_SIZE - padding); ++i)
ret.emplace_back(temp.byte[i]);
}
return ret;
}
};
-438
View File
@@ -1,438 +0,0 @@
#include "aes.h"
#if defined(_MSC_VER)
#include <intrin.h>
#else
#include <x86intrin.h>
#endif
extern const uint32_t accelc_aes_rcon[11];
extern const uint8_t accelc_aes_SBox[256];
extern const uint8_t accelc_aes_InverseSBox[256];
extern const uint8_t accelc_aes_GF2p8_Mul_0x02[256];
extern const uint8_t accelc_aes_GF2p8_Mul_0x03[256];
extern const uint8_t accelc_aes_GF2p8_Mul_0x09[256];
extern const uint8_t accelc_aes_GF2p8_Mul_0x0B[256];
extern const uint8_t accelc_aes_GF2p8_Mul_0x0D[256];
extern const uint8_t accelc_aes_GF2p8_Mul_0x0E[256];
#define Swap(X, Y, Temp) \
Temp = X; \
X = Y; \
Y = Temp;
void accelc_AES128_encrypt(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcKey) {
((uint64_t*)srcBytes)[0] ^= srcKey->qword[0];
((uint64_t*)srcBytes)[1] ^= srcKey->qword[1];
uint8_t ShiftTemp = 0;
for (int i = 1; i < 10; ++i) {
for (int j = 0; j < 16; ++j)
srcBytes[j] = accelc_aes_SBox[srcBytes[j]];
//Shift rows starts;
//Shift the second row;
Swap(srcBytes[1], srcBytes[5], ShiftTemp)
Swap(srcBytes[5], srcBytes[9], ShiftTemp)
Swap(srcBytes[9], srcBytes[13], ShiftTemp)
//Shift the third row;
Swap(srcBytes[2], srcBytes[10], ShiftTemp)
Swap(srcBytes[6], srcBytes[14], ShiftTemp)
//Shift the fourth row;
Swap(srcBytes[3], srcBytes[15], ShiftTemp)
Swap(srcBytes[15], srcBytes[11], ShiftTemp)
Swap(srcBytes[11], srcBytes[7], ShiftTemp)
//Shift rows ends;
for (int j = 0; j < 16; j += 4) {
uint8_t temp[4];
*(uint32_t*)temp = ((uint32_t*)srcBytes)[j / 4];
srcBytes[j] = (uint8_t)(accelc_aes_GF2p8_Mul_0x02[temp[0]] ^ accelc_aes_GF2p8_Mul_0x03[temp[1]] ^ temp[2] ^ temp[3]);
srcBytes[j + 1] = (uint8_t)(temp[0] ^ accelc_aes_GF2p8_Mul_0x02[temp[1]] ^ accelc_aes_GF2p8_Mul_0x03[temp[2]] ^ temp[3]);
srcBytes[j + 2] = (uint8_t)(temp[0] ^ temp[1] ^ accelc_aes_GF2p8_Mul_0x02[temp[2]] ^ accelc_aes_GF2p8_Mul_0x03[temp[3]]);
srcBytes[j + 3] = (uint8_t)(accelc_aes_GF2p8_Mul_0x03[temp[0]] ^ temp[1] ^ temp[2] ^ accelc_aes_GF2p8_Mul_0x02[temp[3]]);
}
((uint64_t*)(srcBytes))[0] ^= srcKey->qword[i * 2];
((uint64_t*)(srcBytes))[1] ^= srcKey->qword[i * 2 + 1];
}
for (int j = 0; j < 16; ++j)
srcBytes[j] = accelc_aes_SBox[srcBytes[j]];
//Shift rows starts;
//Shift the second row;
Swap(srcBytes[1], srcBytes[5], ShiftTemp)
Swap(srcBytes[5], srcBytes[9], ShiftTemp)
Swap(srcBytes[9], srcBytes[13], ShiftTemp)
//Shift the third row;
Swap(srcBytes[2], srcBytes[10], ShiftTemp)
Swap(srcBytes[6], srcBytes[14], ShiftTemp)
//Shift the fourth row;
Swap(srcBytes[3], srcBytes[15], ShiftTemp)
Swap(srcBytes[15], srcBytes[11], ShiftTemp)
Swap(srcBytes[11], srcBytes[7], ShiftTemp)
//Shift rows ends;
((uint64_t*)srcBytes)[0] ^= srcKey->qword[20];
((uint64_t*)srcBytes)[1] ^= srcKey->qword[21];
}
void accelc_AES128_decrypt(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcKey) {
((uint64_t*)srcBytes)[0] ^= srcKey->qword[20];
((uint64_t*)srcBytes)[1] ^= srcKey->qword[21];
uint8_t ShiftTemp = 0;
for (int i = 9; i > 0; --i) {
//Inverse Shift rows starts;
//Inverse shift the second row;
Swap(srcBytes[13], srcBytes[9], ShiftTemp)
Swap(srcBytes[9], srcBytes[5], ShiftTemp)
Swap(srcBytes[5], srcBytes[1], ShiftTemp)
//Inverse shift the third row;
Swap(srcBytes[14], srcBytes[6], ShiftTemp)
Swap(srcBytes[10], srcBytes[2], ShiftTemp)
//Inverse shift the fourth row;
Swap(srcBytes[3], srcBytes[7], ShiftTemp)
Swap(srcBytes[7], srcBytes[11], ShiftTemp)
Swap(srcBytes[11], srcBytes[15], ShiftTemp)
for (int j = 0; j < 16; ++j)
srcBytes[j] = accelc_aes_InverseSBox[srcBytes[j]];
((uint64_t*)srcBytes)[0] ^= srcKey->qword[i * 2];
((uint64_t*)srcBytes)[1] ^= srcKey->qword[i * 2 + 1];
for (int j = 0; j < 16; j += 4) {
uint8_t temp[4];
*(uint32_t*)temp = ((uint32_t*)srcBytes)[j / 4];
srcBytes[j] = (uint8_t)(accelc_aes_GF2p8_Mul_0x0E[temp[0]] ^ accelc_aes_GF2p8_Mul_0x0B[temp[1]] ^ accelc_aes_GF2p8_Mul_0x0D[temp[2]] ^ accelc_aes_GF2p8_Mul_0x09[temp[3]]);
srcBytes[j + 1] = (uint8_t)(accelc_aes_GF2p8_Mul_0x09[temp[0]] ^ accelc_aes_GF2p8_Mul_0x0E[temp[1]] ^ accelc_aes_GF2p8_Mul_0x0B[temp[2]] ^ accelc_aes_GF2p8_Mul_0x0D[temp[3]]);
srcBytes[j + 2] = (uint8_t)(accelc_aes_GF2p8_Mul_0x0D[temp[0]] ^ accelc_aes_GF2p8_Mul_0x09[temp[1]] ^ accelc_aes_GF2p8_Mul_0x0E[temp[2]] ^ accelc_aes_GF2p8_Mul_0x0B[temp[3]]);
srcBytes[j + 3] = (uint8_t)(accelc_aes_GF2p8_Mul_0x0B[temp[0]] ^ accelc_aes_GF2p8_Mul_0x0D[temp[1]] ^ accelc_aes_GF2p8_Mul_0x09[temp[2]] ^ accelc_aes_GF2p8_Mul_0x0E[temp[3]]);
}
}
//Inverse Shift rows starts;
//Inverse shift the second row;
Swap(srcBytes[13], srcBytes[9], ShiftTemp)
Swap(srcBytes[9], srcBytes[5], ShiftTemp)
Swap(srcBytes[5], srcBytes[1], ShiftTemp)
//Inverse shift the third row;
Swap(srcBytes[14], srcBytes[6], ShiftTemp)
Swap(srcBytes[10], srcBytes[2], ShiftTemp)
//Inverse shift the fourth row;
Swap(srcBytes[3], srcBytes[7], ShiftTemp)
Swap(srcBytes[7], srcBytes[11], ShiftTemp)
Swap(srcBytes[11], srcBytes[15], ShiftTemp)
for (int j = 0; j < 16; ++j)
srcBytes[j] = accelc_aes_InverseSBox[srcBytes[j]];
((uint64_t*)srcBytes)[0] ^= srcKey->qword[0];
((uint64_t*)srcBytes)[1] ^= srcKey->qword[1];
}
void accelc_AES128_set_key(const uint8_t srcUserKey[16], AES_KEY* dstKey) {
dstKey->qword[0] = ((const uint64_t*)srcUserKey)[0];
dstKey->qword[1] = ((const uint64_t*)srcUserKey)[1];
for (int i = 4; i < 44; ++i) {
uint32_t temp = dstKey->dword[i - 1];
if (i % 4 == 0) {
temp = _rotr(temp, 8);
((uint8_t*)&temp)[0] = accelc_aes_SBox[((uint8_t*)&temp)[0]];
((uint8_t*)&temp)[1] = accelc_aes_SBox[((uint8_t*)&temp)[1]];
((uint8_t*)&temp)[2] = accelc_aes_SBox[((uint8_t*)&temp)[2]];
((uint8_t*)&temp)[3] = accelc_aes_SBox[((uint8_t*)&temp)[3]];
temp ^= accelc_aes_rcon[i / 4];
}
dstKey->dword[i] = dstKey->dword[i - 4] ^ temp;
}
}
void accelc_AES192_encrypt(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcKey) {
((uint64_t*)srcBytes)[0] ^= srcKey->qword[0];
((uint64_t*)srcBytes)[1] ^= srcKey->qword[1];
uint8_t ShiftTemp = 0;
for (int i = 1; i < 12; ++i) {
for (int j = 0; j < 16; ++j)
srcBytes[j] = accelc_aes_SBox[srcBytes[j]];
//Shift rows starts;
//Shift the second row;
Swap(srcBytes[1], srcBytes[5], ShiftTemp)
Swap(srcBytes[5], srcBytes[9], ShiftTemp)
Swap(srcBytes[9], srcBytes[13], ShiftTemp)
//Shift the third row;
Swap(srcBytes[2], srcBytes[10], ShiftTemp)
Swap(srcBytes[6], srcBytes[14], ShiftTemp)
//Shift the fourth row;
Swap(srcBytes[3], srcBytes[15], ShiftTemp)
Swap(srcBytes[15], srcBytes[11], ShiftTemp)
Swap(srcBytes[11], srcBytes[7], ShiftTemp)
//Shift rows ends;
for (int j = 0; j < 16; j += 4) {
uint8_t temp[4];
*(uint32_t*)temp = ((uint32_t*)srcBytes)[j / 4];
srcBytes[j] = (uint8_t)(accelc_aes_GF2p8_Mul_0x02[temp[0]] ^ accelc_aes_GF2p8_Mul_0x03[temp[1]] ^ temp[2] ^ temp[3]);
srcBytes[j + 1] = (uint8_t)(temp[0] ^ accelc_aes_GF2p8_Mul_0x02[temp[1]] ^ accelc_aes_GF2p8_Mul_0x03[temp[2]] ^ temp[3]);
srcBytes[j + 2] = (uint8_t)(temp[0] ^ temp[1] ^ accelc_aes_GF2p8_Mul_0x02[temp[2]] ^ accelc_aes_GF2p8_Mul_0x03[temp[3]]);
srcBytes[j + 3] = (uint8_t)(accelc_aes_GF2p8_Mul_0x03[temp[0]] ^ temp[1] ^ temp[2] ^ accelc_aes_GF2p8_Mul_0x02[temp[3]]);
}
((uint64_t*)srcBytes)[0] ^= srcKey->qword[i * 2];
((uint64_t*)srcBytes)[1] ^= srcKey->qword[i * 2 + 1];
}
for (int j = 0; j < 16; ++j)
srcBytes[j] = accelc_aes_SBox[srcBytes[j]];
//Shift rows starts;
//Shift the second row;
Swap(srcBytes[1], srcBytes[5], ShiftTemp) //Swap is a MACRO, no need to add ';'.
Swap(srcBytes[5], srcBytes[9], ShiftTemp)
Swap(srcBytes[9], srcBytes[13], ShiftTemp)
//Shift the third row;
Swap(srcBytes[2], srcBytes[10], ShiftTemp)
Swap(srcBytes[6], srcBytes[14], ShiftTemp)
//Shift the fourth row;
Swap(srcBytes[3], srcBytes[15], ShiftTemp)
Swap(srcBytes[15], srcBytes[11], ShiftTemp)
Swap(srcBytes[11], srcBytes[7], ShiftTemp)
//Shift rows ends;
((uint64_t*)srcBytes)[0] ^= srcKey->qword[24];
((uint64_t*)srcBytes)[1] ^= srcKey->qword[25];
}
void accelc_AES192_decrypt(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcKey) {
((uint64_t*)srcBytes)[0] ^= srcKey->qword[24];
((uint64_t*)srcBytes)[1] ^= srcKey->qword[25];
uint8_t ShiftTemp = 0;
for (int i = 11; i > 0; --i) {
//Inverse Shift rows starts;
//Inverse shift the second row;
Swap(srcBytes[13], srcBytes[9], ShiftTemp)
Swap(srcBytes[9], srcBytes[5], ShiftTemp)
Swap(srcBytes[5], srcBytes[1], ShiftTemp)
//Inverse shift the third row;
Swap(srcBytes[14], srcBytes[6], ShiftTemp)
Swap(srcBytes[10], srcBytes[2], ShiftTemp)
//Inverse shift the fourth row;
Swap(srcBytes[3], srcBytes[7], ShiftTemp)
Swap(srcBytes[7], srcBytes[11], ShiftTemp)
Swap(srcBytes[11], srcBytes[15], ShiftTemp)
for (int j = 0; j < 16; ++j)
srcBytes[j] = accelc_aes_InverseSBox[srcBytes[j]];
((uint64_t*)srcBytes)[0] ^= srcKey->qword[i * 2];
((uint64_t*)srcBytes)[1] ^= srcKey->qword[i * 2 + 1];
for (int j = 0; j < 16; j += 4) {
uint8_t temp[4];
*(uint32_t*)temp = ((uint32_t*)srcBytes)[j / 4];
srcBytes[j] = (uint8_t)(accelc_aes_GF2p8_Mul_0x0E[temp[0]] ^ accelc_aes_GF2p8_Mul_0x0B[temp[1]] ^ accelc_aes_GF2p8_Mul_0x0D[temp[2]] ^ accelc_aes_GF2p8_Mul_0x09[temp[3]]);
srcBytes[j + 1] = (uint8_t)(accelc_aes_GF2p8_Mul_0x09[temp[0]] ^ accelc_aes_GF2p8_Mul_0x0E[temp[1]] ^ accelc_aes_GF2p8_Mul_0x0B[temp[2]] ^ accelc_aes_GF2p8_Mul_0x0D[temp[3]]);
srcBytes[j + 2] = (uint8_t)(accelc_aes_GF2p8_Mul_0x0D[temp[0]] ^ accelc_aes_GF2p8_Mul_0x09[temp[1]] ^ accelc_aes_GF2p8_Mul_0x0E[temp[2]] ^ accelc_aes_GF2p8_Mul_0x0B[temp[3]]);
srcBytes[j + 3] = (uint8_t)(accelc_aes_GF2p8_Mul_0x0B[temp[0]] ^ accelc_aes_GF2p8_Mul_0x0D[temp[1]] ^ accelc_aes_GF2p8_Mul_0x09[temp[2]] ^ accelc_aes_GF2p8_Mul_0x0E[temp[3]]);
}
}
//Inverse Shift rows starts;
//Inverse shift the second row;
Swap(srcBytes[13], srcBytes[9], ShiftTemp)
Swap(srcBytes[9], srcBytes[5], ShiftTemp)
Swap(srcBytes[5], srcBytes[1], ShiftTemp)
//Inverse shift the third row;
Swap(srcBytes[14], srcBytes[6], ShiftTemp)
Swap(srcBytes[10], srcBytes[2], ShiftTemp)
//Inverse shift the fourth row;
Swap(srcBytes[3], srcBytes[7], ShiftTemp)
Swap(srcBytes[7], srcBytes[11], ShiftTemp)
Swap(srcBytes[11], srcBytes[15], ShiftTemp)
for (uint8_t j = 0; j < 16; ++j)
srcBytes[j] = accelc_aes_InverseSBox[srcBytes[j]];
((uint64_t*)srcBytes)[0] ^= srcKey->qword[0];
((uint64_t*)srcBytes)[1] ^= srcKey->qword[1];
}
void accelc_AES192_set_key(const uint8_t srcUserKey[24], AES_KEY* dstKey) {
dstKey->qword[0] = ((const uint64_t*)srcUserKey)[0];
dstKey->qword[1] = ((const uint64_t*)srcUserKey)[1];
dstKey->qword[2] = ((const uint64_t*)srcUserKey)[2];
for (int i = 6; i < 52; ++i) {
uint32_t temp = dstKey->dword[i - 1];
if (i % 6 == 0) {
temp = _rotr(temp, 8);
((uint8_t*)&temp)[0] = accelc_aes_SBox[((uint8_t*)&temp)[0]];
((uint8_t*)&temp)[1] = accelc_aes_SBox[((uint8_t*)&temp)[1]];
((uint8_t*)&temp)[2] = accelc_aes_SBox[((uint8_t*)&temp)[2]];
((uint8_t*)&temp)[3] = accelc_aes_SBox[((uint8_t*)&temp)[3]];
temp ^= accelc_aes_rcon[i / 6];
}
dstKey->dword[i] = dstKey->dword[i - 6] ^ temp;
}
}
void accelc_AES256_encrypt(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcKey) {
((uint64_t*)srcBytes)[0] ^= srcKey->qword[0];
((uint64_t*)srcBytes)[1] ^= srcKey->qword[1];
uint8_t ShiftTemp = 0;
for (int i = 1; i < 14; ++i) {
for (int j = 0; j < 16; ++j)
srcBytes[j] = accelc_aes_SBox[srcBytes[j]];
//Shift rows starts;
//Shift the second row;
Swap(srcBytes[1], srcBytes[5], ShiftTemp)
Swap(srcBytes[5], srcBytes[9], ShiftTemp)
Swap(srcBytes[9], srcBytes[13], ShiftTemp)
//Shift the third row;
Swap(srcBytes[2], srcBytes[10], ShiftTemp)
Swap(srcBytes[6], srcBytes[14], ShiftTemp)
//Shift the fourth row;
Swap(srcBytes[3], srcBytes[15], ShiftTemp)
Swap(srcBytes[15], srcBytes[11], ShiftTemp)
Swap(srcBytes[11], srcBytes[7], ShiftTemp)
//Shift rows ends;
for (int j = 0; j < 16; j += 4) {
uint8_t temp[4];
*(uint32_t*)temp = ((uint32_t*)srcBytes)[j / 4];
srcBytes[j] = (uint8_t)(accelc_aes_GF2p8_Mul_0x02[temp[0]] ^ accelc_aes_GF2p8_Mul_0x03[temp[1]] ^ temp[2] ^ temp[3]);
srcBytes[j + 1] = (uint8_t)(temp[0] ^ accelc_aes_GF2p8_Mul_0x02[temp[1]] ^ accelc_aes_GF2p8_Mul_0x03[temp[2]] ^ temp[3]);
srcBytes[j + 2] = (uint8_t)(temp[0] ^ temp[1] ^ accelc_aes_GF2p8_Mul_0x02[temp[2]] ^ accelc_aes_GF2p8_Mul_0x03[temp[3]]);
srcBytes[j + 3] = (uint8_t)(accelc_aes_GF2p8_Mul_0x03[temp[0]] ^ temp[1] ^ temp[2] ^ accelc_aes_GF2p8_Mul_0x02[temp[3]]);
}
((uint64_t*)srcBytes)[0] ^= srcKey->qword[i * 2];
((uint64_t*)srcBytes)[1] ^= srcKey->qword[i * 2 + 1];
}
for (int j = 0; j < 16; ++j)
srcBytes[j] = accelc_aes_SBox[srcBytes[j]];
//Shift rows starts;
//Shift the second row;
Swap(srcBytes[1], srcBytes[5], ShiftTemp)
Swap(srcBytes[5], srcBytes[9], ShiftTemp)
Swap(srcBytes[9], srcBytes[13], ShiftTemp)
//Shift the third row;
Swap(srcBytes[2], srcBytes[10], ShiftTemp)
Swap(srcBytes[6], srcBytes[14], ShiftTemp)
//Shift the fourth row;
Swap(srcBytes[3], srcBytes[15], ShiftTemp)
Swap(srcBytes[15], srcBytes[11], ShiftTemp)
Swap(srcBytes[11], srcBytes[7], ShiftTemp)
//Shift rows ends;
((uint64_t*)srcBytes)[0] ^= srcKey->qword[28];
((uint64_t*)srcBytes)[1] ^= srcKey->qword[29];
}
void accelc_AES256_decrypt(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcKey) {
((uint64_t*)srcBytes)[0] ^= srcKey->qword[28];
((uint64_t*)srcBytes)[1] ^= srcKey->qword[29];
uint8_t ShiftTemp = 0;
for (int i = 13; i > 0; --i) {
//Inverse Shift rows starts;
//Inverse shift the second row;
Swap(srcBytes[13], srcBytes[9], ShiftTemp)
Swap(srcBytes[9], srcBytes[5], ShiftTemp)
Swap(srcBytes[5], srcBytes[1], ShiftTemp)
//Inverse shift the third row;
Swap(srcBytes[14], srcBytes[6], ShiftTemp)
Swap(srcBytes[10], srcBytes[2], ShiftTemp)
//Inverse shift the fourth row;
Swap(srcBytes[3], srcBytes[7], ShiftTemp)
Swap(srcBytes[7], srcBytes[11], ShiftTemp)
Swap(srcBytes[11], srcBytes[15], ShiftTemp)
for (int j = 0; j < 16; ++j)
srcBytes[j] = accelc_aes_InverseSBox[srcBytes[j]];
((uint64_t*)srcBytes)[0] ^= srcKey->qword[i * 2];
((uint64_t*)srcBytes)[1] ^= srcKey->qword[i * 2 + 1];
for (int j = 0; j < 16; j += 4) {
uint8_t temp[4];
*(uint32_t*)temp = ((uint32_t*)srcBytes)[j / 4];
srcBytes[j] = (uint8_t)(accelc_aes_GF2p8_Mul_0x0E[temp[0]] ^ accelc_aes_GF2p8_Mul_0x0B[temp[1]] ^ accelc_aes_GF2p8_Mul_0x0D[temp[2]] ^ accelc_aes_GF2p8_Mul_0x09[temp[3]]);
srcBytes[j + 1] = (uint8_t)(accelc_aes_GF2p8_Mul_0x09[temp[0]] ^ accelc_aes_GF2p8_Mul_0x0E[temp[1]] ^ accelc_aes_GF2p8_Mul_0x0B[temp[2]] ^ accelc_aes_GF2p8_Mul_0x0D[temp[3]]);
srcBytes[j + 2] = (uint8_t)(accelc_aes_GF2p8_Mul_0x0D[temp[0]] ^ accelc_aes_GF2p8_Mul_0x09[temp[1]] ^ accelc_aes_GF2p8_Mul_0x0E[temp[2]] ^ accelc_aes_GF2p8_Mul_0x0B[temp[3]]);
srcBytes[j + 3] = (uint8_t)(accelc_aes_GF2p8_Mul_0x0B[temp[0]] ^ accelc_aes_GF2p8_Mul_0x0D[temp[1]] ^ accelc_aes_GF2p8_Mul_0x09[temp[2]] ^ accelc_aes_GF2p8_Mul_0x0E[temp[3]]);
}
}
//Inverse Shift rows starts;
//Inverse shift the second row;
Swap(srcBytes[13], srcBytes[9], ShiftTemp)
Swap(srcBytes[9], srcBytes[5], ShiftTemp)
Swap(srcBytes[5], srcBytes[1], ShiftTemp)
//Inverse shift the third row;
Swap(srcBytes[14], srcBytes[6], ShiftTemp)
Swap(srcBytes[10], srcBytes[2], ShiftTemp)
//Inverse shift the fourth row;
Swap(srcBytes[3], srcBytes[7], ShiftTemp)
Swap(srcBytes[7], srcBytes[11], ShiftTemp)
Swap(srcBytes[11], srcBytes[15], ShiftTemp)
for (int j = 0; j < 16; ++j)
srcBytes[j] = accelc_aes_InverseSBox[srcBytes[j]];
((uint64_t*)srcBytes)[0] ^= srcKey->qword[0];
((uint64_t*)srcBytes)[1] ^= srcKey->qword[1];
}
void accelc_AES256_set_key(const uint8_t srcUserKey[32], AES_KEY* dstKey) {
dstKey->qword[0] = ((const uint64_t*)srcUserKey)[0];
dstKey->qword[1] = ((const uint64_t*)srcUserKey)[1];
dstKey->qword[2] = ((const uint64_t*)srcUserKey)[2];
dstKey->qword[3] = ((const uint64_t*)srcUserKey)[3];
for (int i = 8; i < 60; ++i) {
uint32_t temp = dstKey->dword[i - 1];
if (i % 8 == 0) {
temp = _rotr(temp, 8);
((uint8_t*)&temp)[0] = accelc_aes_SBox[((uint8_t*)&temp)[0]];
((uint8_t*)&temp)[1] = accelc_aes_SBox[((uint8_t*)&temp)[1]];
((uint8_t*)&temp)[2] = accelc_aes_SBox[((uint8_t*)&temp)[2]];
((uint8_t*)&temp)[3] = accelc_aes_SBox[((uint8_t*)&temp)[3]];
temp ^= accelc_aes_rcon[i / 8];
}
if (i % 8 == 4) {
((uint8_t*)&temp)[0] = accelc_aes_SBox[((uint8_t*)&temp)[0]];
((uint8_t*)&temp)[1] = accelc_aes_SBox[((uint8_t*)&temp)[1]];
((uint8_t*)&temp)[2] = accelc_aes_SBox[((uint8_t*)&temp)[2]];
((uint8_t*)&temp)[3] = accelc_aes_SBox[((uint8_t*)&temp)[3]];
}
dstKey->dword[i] = dstKey->dword[i - 8] ^ temp;
}
}
-82
View File
@@ -1,82 +0,0 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#if defined(__cplusplus)
extern "C" {
#endif
#define AES_BLOCK_SIZE 16
#define AES128_USERKEY_LENGTH 16
#define AES192_USERKEY_LENGTH 24
#define AES256_USERKEY_LENGTH 32
typedef struct _AES_KEY {
union {
uint8_t byte[240];
uint16_t word[120];
uint32_t dword[60];
uint64_t qword[30];
};
} AES_KEY;
//
// encrypt
//
void accelc_AES128_encrypt(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcKey);
void accelc_AES192_encrypt(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcKey);
void accelc_AES256_encrypt(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcKey);
//
// dncrypt
//
void accelc_AES128_decrypt(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcKey);
void accelc_AES192_decrypt(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcKey);
void accelc_AES256_decrypt(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcKey);
//
// set_key
//
void accelc_AES128_set_key(const uint8_t srcUserKey[AES128_USERKEY_LENGTH], AES_KEY* dstKey);
void accelc_AES192_set_key(const uint8_t srcUserKey[AES192_USERKEY_LENGTH], AES_KEY* dstKey);
void accelc_AES256_set_key(const uint8_t srcUserKey[AES256_USERKEY_LENGTH], AES_KEY* dstKey);
//
// encrypt_aesni
//
void accelc_AES128_encrypt_aesni(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcKey);
void accelc_AES192_encrypt_aesni(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcKey);
void accelc_AES256_encrypt_aesni(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcKey);
//
// decrypt_aesni
//
void accelc_AES128_decrypt_aesni(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcKey);
void accelc_AES192_decrypt_aesni(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcKey);
void accelc_AES256_decrypt_aesni(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcKey);
//
// decrypt_aesni_fast
//
void accelc_AES128_decrypt_aesni_fast(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcInverseKey);
void accelc_AES192_decrypt_aesni_fast(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcInverseKey);
void accelc_AES256_decrypt_aesni_fast(uint8_t srcBytes[AES_BLOCK_SIZE], const AES_KEY* srcInverseKey);
//
// set_key_aesni
//
void accelc_AES128_set_key_aesni(const uint8_t srcUserKey[AES128_USERKEY_LENGTH], AES_KEY* dstKey);
void accelc_AES192_set_key_aesni(const uint8_t srcUserKey[AES128_USERKEY_LENGTH], AES_KEY* dstKey);
void accelc_AES256_set_key_aesni(const uint8_t srcUserKey[AES256_USERKEY_LENGTH], AES_KEY* dstKey);
//
// set_invkey_aesni
//
void accelc_AES128_set_invkey_aesni(const AES_KEY* __restrict srcKey, AES_KEY* __restrict dstInverseKey);
void accelc_AES192_set_invkey_aesni(const AES_KEY* __restrict srcKey, AES_KEY* __restrict dstInverseKey);
void accelc_AES256_set_invkey_aesni(const AES_KEY* __restrict srcKey, AES_KEY* __restrict dstInverseKey);
#if defined(__cplusplus)
}
#endif
@@ -1,157 +0,0 @@
#include <stdint.h>
const uint8_t accelc_aes_SBox[256] = {
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
};
const uint32_t accelc_aes_rcon[11] = {
0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
};
const uint8_t accelc_aes_GF2p8_Mul_0x02[256] = {
0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E,
0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3E,
0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5A, 0x5C, 0x5E,
0x60, 0x62, 0x64, 0x66, 0x68, 0x6A, 0x6C, 0x6E, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7A, 0x7C, 0x7E,
0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8E, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9A, 0x9C, 0x9E,
0xA0, 0xA2, 0xA4, 0xA6, 0xA8, 0xAA, 0xAC, 0xAE, 0xB0, 0xB2, 0xB4, 0xB6, 0xB8, 0xBA, 0xBC, 0xBE,
0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE, 0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE, 0xF0, 0xF2, 0xF4, 0xF6, 0xF8, 0xFA, 0xFC, 0xFE,
0x1B, 0x19, 0x1F, 0x1D, 0x13, 0x11, 0x17, 0x15, 0x0B, 0x09, 0x0F, 0x0D, 0x03, 0x01, 0x07, 0x05,
0x3B, 0x39, 0x3F, 0x3D, 0x33, 0x31, 0x37, 0x35, 0x2B, 0x29, 0x2F, 0x2D, 0x23, 0x21, 0x27, 0x25,
0x5B, 0x59, 0x5F, 0x5D, 0x53, 0x51, 0x57, 0x55, 0x4B, 0x49, 0x4F, 0x4D, 0x43, 0x41, 0x47, 0x45,
0x7B, 0x79, 0x7F, 0x7D, 0x73, 0x71, 0x77, 0x75, 0x6B, 0x69, 0x6F, 0x6D, 0x63, 0x61, 0x67, 0x65,
0x9B, 0x99, 0x9F, 0x9D, 0x93, 0x91, 0x97, 0x95, 0x8B, 0x89, 0x8F, 0x8D, 0x83, 0x81, 0x87, 0x85,
0xBB, 0xB9, 0xBF, 0xBD, 0xB3, 0xB1, 0xB7, 0xB5, 0xAB, 0xA9, 0xAF, 0xAD, 0xA3, 0xA1, 0xA7, 0xA5,
0xDB, 0xD9, 0xDF, 0xDD, 0xD3, 0xD1, 0xD7, 0xD5, 0xCB, 0xC9, 0xCF, 0xCD, 0xC3, 0xC1, 0xC7, 0xC5,
0xFB, 0xF9, 0xFF, 0xFD, 0xF3, 0xF1, 0xF7, 0xF5, 0xEB, 0xE9, 0xEF, 0xED, 0xE3, 0xE1, 0xE7, 0xE5
};
const uint8_t accelc_aes_GF2p8_Mul_0x03[256] = {
0x00, 0x03, 0x06, 0x05, 0x0C, 0x0F, 0x0A, 0x09, 0x18, 0x1B, 0x1E, 0x1D, 0x14, 0x17, 0x12, 0x11,
0x30, 0x33, 0x36, 0x35, 0x3C, 0x3F, 0x3A, 0x39, 0x28, 0x2B, 0x2E, 0x2D, 0x24, 0x27, 0x22, 0x21,
0x60, 0x63, 0x66, 0x65, 0x6C, 0x6F, 0x6A, 0x69, 0x78, 0x7B, 0x7E, 0x7D, 0x74, 0x77, 0x72, 0x71,
0x50, 0x53, 0x56, 0x55, 0x5C, 0x5F, 0x5A, 0x59, 0x48, 0x4B, 0x4E, 0x4D, 0x44, 0x47, 0x42, 0x41,
0xC0, 0xC3, 0xC6, 0xC5, 0xCC, 0xCF, 0xCA, 0xC9, 0xD8, 0xDB, 0xDE, 0xDD, 0xD4, 0xD7, 0xD2, 0xD1,
0xF0, 0xF3, 0xF6, 0xF5, 0xFC, 0xFF, 0xFA, 0xF9, 0xE8, 0xEB, 0xEE, 0xED, 0xE4, 0xE7, 0xE2, 0xE1,
0xA0, 0xA3, 0xA6, 0xA5, 0xAC, 0xAF, 0xAA, 0xA9, 0xB8, 0xBB, 0xBE, 0xBD, 0xB4, 0xB7, 0xB2, 0xB1,
0x90, 0x93, 0x96, 0x95, 0x9C, 0x9F, 0x9A, 0x99, 0x88, 0x8B, 0x8E, 0x8D, 0x84, 0x87, 0x82, 0x81,
0x9B, 0x98, 0x9D, 0x9E, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8F, 0x8C, 0x89, 0x8A,
0xAB, 0xA8, 0xAD, 0xAE, 0xA7, 0xA4, 0xA1, 0xA2, 0xB3, 0xB0, 0xB5, 0xB6, 0xBF, 0xBC, 0xB9, 0xBA,
0xFB, 0xF8, 0xFD, 0xFE, 0xF7, 0xF4, 0xF1, 0xF2, 0xE3, 0xE0, 0xE5, 0xE6, 0xEF, 0xEC, 0xE9, 0xEA,
0xCB, 0xC8, 0xCD, 0xCE, 0xC7, 0xC4, 0xC1, 0xC2, 0xD3, 0xD0, 0xD5, 0xD6, 0xDF, 0xDC, 0xD9, 0xDA,
0x5B, 0x58, 0x5D, 0x5E, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4F, 0x4C, 0x49, 0x4A,
0x6B, 0x68, 0x6D, 0x6E, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7F, 0x7C, 0x79, 0x7A,
0x3B, 0x38, 0x3D, 0x3E, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2F, 0x2C, 0x29, 0x2A,
0x0B, 0x08, 0x0D, 0x0E, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1F, 0x1C, 0x19, 0x1A
};
const uint8_t accelc_aes_InverseSBox[256] = {
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
};
const uint8_t accelc_aes_GF2p8_Mul_0x09[256] = {
0x00, 0x09, 0x12, 0x1B, 0x24, 0x2D, 0x36, 0x3F, 0x48, 0x41, 0x5A, 0x53, 0x6C, 0x65, 0x7E, 0x77,
0x90, 0x99, 0x82, 0x8B, 0xB4, 0xBD, 0xA6, 0xAF, 0xD8, 0xD1, 0xCA, 0xC3, 0xFC, 0xF5, 0xEE, 0xE7,
0x3B, 0x32, 0x29, 0x20, 0x1F, 0x16, 0x0D, 0x04, 0x73, 0x7A, 0x61, 0x68, 0x57, 0x5E, 0x45, 0x4C,
0xAB, 0xA2, 0xB9, 0xB0, 0x8F, 0x86, 0x9D, 0x94, 0xE3, 0xEA, 0xF1, 0xF8, 0xC7, 0xCE, 0xD5, 0xDC,
0x76, 0x7F, 0x64, 0x6D, 0x52, 0x5B, 0x40, 0x49, 0x3E, 0x37, 0x2C, 0x25, 0x1A, 0x13, 0x08, 0x01,
0xE6, 0xEF, 0xF4, 0xFD, 0xC2, 0xCB, 0xD0, 0xD9, 0xAE, 0xA7, 0xBC, 0xB5, 0x8A, 0x83, 0x98, 0x91,
0x4D, 0x44, 0x5F, 0x56, 0x69, 0x60, 0x7B, 0x72, 0x05, 0x0C, 0x17, 0x1E, 0x21, 0x28, 0x33, 0x3A,
0xDD, 0xD4, 0xCF, 0xC6, 0xF9, 0xF0, 0xEB, 0xE2, 0x95, 0x9C, 0x87, 0x8E, 0xB1, 0xB8, 0xA3, 0xAA,
0xEC, 0xE5, 0xFE, 0xF7, 0xC8, 0xC1, 0xDA, 0xD3, 0xA4, 0xAD, 0xB6, 0xBF, 0x80, 0x89, 0x92, 0x9B,
0x7C, 0x75, 0x6E, 0x67, 0x58, 0x51, 0x4A, 0x43, 0x34, 0x3D, 0x26, 0x2F, 0x10, 0x19, 0x02, 0x0B,
0xD7, 0xDE, 0xC5, 0xCC, 0xF3, 0xFA, 0xE1, 0xE8, 0x9F, 0x96, 0x8D, 0x84, 0xBB, 0xB2, 0xA9, 0xA0,
0x47, 0x4E, 0x55, 0x5C, 0x63, 0x6A, 0x71, 0x78, 0x0F, 0x06, 0x1D, 0x14, 0x2B, 0x22, 0x39, 0x30,
0x9A, 0x93, 0x88, 0x81, 0xBE, 0xB7, 0xAC, 0xA5, 0xD2, 0xDB, 0xC0, 0xC9, 0xF6, 0xFF, 0xE4, 0xED,
0x0A, 0x03, 0x18, 0x11, 0x2E, 0x27, 0x3C, 0x35, 0x42, 0x4B, 0x50, 0x59, 0x66, 0x6F, 0x74, 0x7D,
0xA1, 0xA8, 0xB3, 0xBA, 0x85, 0x8C, 0x97, 0x9E, 0xE9, 0xE0, 0xFB, 0xF2, 0xCD, 0xC4, 0xDF, 0xD6,
0x31, 0x38, 0x23, 0x2A, 0x15, 0x1C, 0x07, 0x0E, 0x79, 0x70, 0x6B, 0x62, 0x5D, 0x54, 0x4F, 0x46
};
const uint8_t accelc_aes_GF2p8_Mul_0x0B[256] = {
0x00, 0x0B, 0x16, 0x1D, 0x2C, 0x27, 0x3A, 0x31, 0x58, 0x53, 0x4E, 0x45, 0x74, 0x7F, 0x62, 0x69,
0xB0, 0xBB, 0xA6, 0xAD, 0x9C, 0x97, 0x8A, 0x81, 0xE8, 0xE3, 0xFE, 0xF5, 0xC4, 0xCF, 0xD2, 0xD9,
0x7B, 0x70, 0x6D, 0x66, 0x57, 0x5C, 0x41, 0x4A, 0x23, 0x28, 0x35, 0x3E, 0x0F, 0x04, 0x19, 0x12,
0xCB, 0xC0, 0xDD, 0xD6, 0xE7, 0xEC, 0xF1, 0xFA, 0x93, 0x98, 0x85, 0x8E, 0xBF, 0xB4, 0xA9, 0xA2,
0xF6, 0xFD, 0xE0, 0xEB, 0xDA, 0xD1, 0xCC, 0xC7, 0xAE, 0xA5, 0xB8, 0xB3, 0x82, 0x89, 0x94, 0x9F,
0x46, 0x4D, 0x50, 0x5B, 0x6A, 0x61, 0x7C, 0x77, 0x1E, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2F,
0x8D, 0x86, 0x9B, 0x90, 0xA1, 0xAA, 0xB7, 0xBC, 0xD5, 0xDE, 0xC3, 0xC8, 0xF9, 0xF2, 0xEF, 0xE4,
0x3D, 0x36, 0x2B, 0x20, 0x11, 0x1A, 0x07, 0x0C, 0x65, 0x6E, 0x73, 0x78, 0x49, 0x42, 0x5F, 0x54,
0xF7, 0xFC, 0xE1, 0xEA, 0xDB, 0xD0, 0xCD, 0xC6, 0xAF, 0xA4, 0xB9, 0xB2, 0x83, 0x88, 0x95, 0x9E,
0x47, 0x4C, 0x51, 0x5A, 0x6B, 0x60, 0x7D, 0x76, 0x1F, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2E,
0x8C, 0x87, 0x9A, 0x91, 0xA0, 0xAB, 0xB6, 0xBD, 0xD4, 0xDF, 0xC2, 0xC9, 0xF8, 0xF3, 0xEE, 0xE5,
0x3C, 0x37, 0x2A, 0x21, 0x10, 0x1B, 0x06, 0x0D, 0x64, 0x6F, 0x72, 0x79, 0x48, 0x43, 0x5E, 0x55,
0x01, 0x0A, 0x17, 0x1C, 0x2D, 0x26, 0x3B, 0x30, 0x59, 0x52, 0x4F, 0x44, 0x75, 0x7E, 0x63, 0x68,
0xB1, 0xBA, 0xA7, 0xAC, 0x9D, 0x96, 0x8B, 0x80, 0xE9, 0xE2, 0xFF, 0xF4, 0xC5, 0xCE, 0xD3, 0xD8,
0x7A, 0x71, 0x6C, 0x67, 0x56, 0x5D, 0x40, 0x4B, 0x22, 0x29, 0x34, 0x3F, 0x0E, 0x05, 0x18, 0x13,
0xCA, 0xC1, 0xDC, 0xD7, 0xE6, 0xED, 0xF0, 0xFB, 0x92, 0x99, 0x84, 0x8F, 0xBE, 0xB5, 0xA8, 0xA3
};
const uint8_t accelc_aes_GF2p8_Mul_0x0D[256] = {
0x00, 0x0D, 0x1A, 0x17, 0x34, 0x39, 0x2E, 0x23, 0x68, 0x65, 0x72, 0x7F, 0x5C, 0x51, 0x46, 0x4B,
0xD0, 0xDD, 0xCA, 0xC7, 0xE4, 0xE9, 0xFE, 0xF3, 0xB8, 0xB5, 0xA2, 0xAF, 0x8C, 0x81, 0x96, 0x9B,
0xBB, 0xB6, 0xA1, 0xAC, 0x8F, 0x82, 0x95, 0x98, 0xD3, 0xDE, 0xC9, 0xC4, 0xE7, 0xEA, 0xFD, 0xF0,
0x6B, 0x66, 0x71, 0x7C, 0x5F, 0x52, 0x45, 0x48, 0x03, 0x0E, 0x19, 0x14, 0x37, 0x3A, 0x2D, 0x20,
0x6D, 0x60, 0x77, 0x7A, 0x59, 0x54, 0x43, 0x4E, 0x05, 0x08, 0x1F, 0x12, 0x31, 0x3C, 0x2B, 0x26,
0xBD, 0xB0, 0xA7, 0xAA, 0x89, 0x84, 0x93, 0x9E, 0xD5, 0xD8, 0xCF, 0xC2, 0xE1, 0xEC, 0xFB, 0xF6,
0xD6, 0xDB, 0xCC, 0xC1, 0xE2, 0xEF, 0xF8, 0xF5, 0xBE, 0xB3, 0xA4, 0xA9, 0x8A, 0x87, 0x90, 0x9D,
0x06, 0x0B, 0x1C, 0x11, 0x32, 0x3F, 0x28, 0x25, 0x6E, 0x63, 0x74, 0x79, 0x5A, 0x57, 0x40, 0x4D,
0xDA, 0xD7, 0xC0, 0xCD, 0xEE, 0xE3, 0xF4, 0xF9, 0xB2, 0xBF, 0xA8, 0xA5, 0x86, 0x8B, 0x9C, 0x91,
0x0A, 0x07, 0x10, 0x1D, 0x3E, 0x33, 0x24, 0x29, 0x62, 0x6F, 0x78, 0x75, 0x56, 0x5B, 0x4C, 0x41,
0x61, 0x6C, 0x7B, 0x76, 0x55, 0x58, 0x4F, 0x42, 0x09, 0x04, 0x13, 0x1E, 0x3D, 0x30, 0x27, 0x2A,
0xB1, 0xBC, 0xAB, 0xA6, 0x85, 0x88, 0x9F, 0x92, 0xD9, 0xD4, 0xC3, 0xCE, 0xED, 0xE0, 0xF7, 0xFA,
0xB7, 0xBA, 0xAD, 0xA0, 0x83, 0x8E, 0x99, 0x94, 0xDF, 0xD2, 0xC5, 0xC8, 0xEB, 0xE6, 0xF1, 0xFC,
0x67, 0x6A, 0x7D, 0x70, 0x53, 0x5E, 0x49, 0x44, 0x0F, 0x02, 0x15, 0x18, 0x3B, 0x36, 0x21, 0x2C,
0x0C, 0x01, 0x16, 0x1B, 0x38, 0x35, 0x22, 0x2F, 0x64, 0x69, 0x7E, 0x73, 0x50, 0x5D, 0x4A, 0x47,
0xDC, 0xD1, 0xC6, 0xCB, 0xE8, 0xE5, 0xF2, 0xFF, 0xB4, 0xB9, 0xAE, 0xA3, 0x80, 0x8D, 0x9A, 0x97
};
const uint8_t accelc_aes_GF2p8_Mul_0x0E[256] = {
0x00, 0x0E, 0x1C, 0x12, 0x38, 0x36, 0x24, 0x2A, 0x70, 0x7E, 0x6C, 0x62, 0x48, 0x46, 0x54, 0x5A,
0xE0, 0xEE, 0xFC, 0xF2, 0xD8, 0xD6, 0xC4, 0xCA, 0x90, 0x9E, 0x8C, 0x82, 0xA8, 0xA6, 0xB4, 0xBA,
0xDB, 0xD5, 0xC7, 0xC9, 0xE3, 0xED, 0xFF, 0xF1, 0xAB, 0xA5, 0xB7, 0xB9, 0x93, 0x9D, 0x8F, 0x81,
0x3B, 0x35, 0x27, 0x29, 0x03, 0x0D, 0x1F, 0x11, 0x4B, 0x45, 0x57, 0x59, 0x73, 0x7D, 0x6F, 0x61,
0xAD, 0xA3, 0xB1, 0xBF, 0x95, 0x9B, 0x89, 0x87, 0xDD, 0xD3, 0xC1, 0xCF, 0xE5, 0xEB, 0xF9, 0xF7,
0x4D, 0x43, 0x51, 0x5F, 0x75, 0x7B, 0x69, 0x67, 0x3D, 0x33, 0x21, 0x2F, 0x05, 0x0B, 0x19, 0x17,
0x76, 0x78, 0x6A, 0x64, 0x4E, 0x40, 0x52, 0x5C, 0x06, 0x08, 0x1A, 0x14, 0x3E, 0x30, 0x22, 0x2C,
0x96, 0x98, 0x8A, 0x84, 0xAE, 0xA0, 0xB2, 0xBC, 0xE6, 0xE8, 0xFA, 0xF4, 0xDE, 0xD0, 0xC2, 0xCC,
0x41, 0x4F, 0x5D, 0x53, 0x79, 0x77, 0x65, 0x6B, 0x31, 0x3F, 0x2D, 0x23, 0x09, 0x07, 0x15, 0x1B,
0xA1, 0xAF, 0xBD, 0xB3, 0x99, 0x97, 0x85, 0x8B, 0xD1, 0xDF, 0xCD, 0xC3, 0xE9, 0xE7, 0xF5, 0xFB,
0x9A, 0x94, 0x86, 0x88, 0xA2, 0xAC, 0xBE, 0xB0, 0xEA, 0xE4, 0xF6, 0xF8, 0xD2, 0xDC, 0xCE, 0xC0,
0x7A, 0x74, 0x66, 0x68, 0x42, 0x4C, 0x5E, 0x50, 0x0A, 0x04, 0x16, 0x18, 0x32, 0x3C, 0x2E, 0x20,
0xEC, 0xE2, 0xF0, 0xFE, 0xD4, 0xDA, 0xC8, 0xC6, 0x9C, 0x92, 0x80, 0x8E, 0xA4, 0xAA, 0xB8, 0xB6,
0x0C, 0x02, 0x10, 0x1E, 0x34, 0x3A, 0x28, 0x26, 0x7C, 0x72, 0x60, 0x6E, 0x44, 0x4A, 0x58, 0x56,
0x37, 0x39, 0x2B, 0x25, 0x0F, 0x01, 0x13, 0x1D, 0x47, 0x49, 0x5B, 0x55, 0x7F, 0x71, 0x63, 0x6D,
0xD7, 0xD9, 0xCB, 0xC5, 0xEF, 0xE1, 0xF3, 0xFD, 0xA7, 0xA9, 0xBB, 0xB5, 0x9F, 0x91, 0x83, 0x8D
};
-281
View File
@@ -1,281 +0,0 @@
#include "blowfish.h"
#include <memory.h>
#if defined(_MSC_VER)
#include <intrin.h>
#define _bswap _byteswap_ulong
#elif defined(__GNUC__)
#include <x86intrin.h>
#endif
const uint32_t accelc_Blowfish_Original_PBox[18] = {
0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, 0xA4093822, 0x299F31D0,
0x082EFA98, 0xEC4E6C89, 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, 0x9216D5D9, 0x8979FB1B
};
const uint32_t accelc_Blowfish_Original_SBox[4][256] = {
{
0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16, 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E,
0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE, 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF, 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E,
0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A,
0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677, 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032,
0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239, 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0,
0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3, 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88, 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE,
0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6, 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7,
0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463, 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, 0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09,
0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB, 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573,
0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0, 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790, 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8,
0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4, 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C,
0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1, 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9,
0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF, 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF,
0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA, 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41, 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915,
0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400, 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664, 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A
},
{
0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1, 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E,
0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6, 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1,
0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD,
0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7, 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331,
0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87,
0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16, 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD,
0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B, 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3,
0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A, 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960,
0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28, 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E,
0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50, 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8, 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281,
0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73,
0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0, 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250,
0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061,
0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB, 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735, 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC,
0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9, 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7
},
{
0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF, 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840,
0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45, 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A, 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB,
0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE, 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B,
0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB, 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B,
0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C, 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC,
0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17, 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B, 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115,
0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922, 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0, 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E,
0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B,
0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB, 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE,
0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D, 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F, 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61,
0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2, 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C,
0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633, 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169,
0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027, 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62,
0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634, 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24, 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC,
0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4, 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837, 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0
},
{
0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4,
0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8, 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304, 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22,
0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4, 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59,
0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51, 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C,
0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28, 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD,
0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A, 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB, 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F,
0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991, 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680, 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166,
0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47,
0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D, 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7,
0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38, 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C, 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525,
0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E,
0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D, 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299,
0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A,
0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0, 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060,
0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E, 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6
}
};
#define f_transform(_x, _S) ((((_S)[0][(_x)[3]] + (_S)[1][(_x)[2]]) ^ (_S)[2][(_x)[1]]) + (_S)[3][(_x)[0]])
void accelc_Blowfish_encrypt(uint8_t srcBytes[8],
const BLOWFISH_KEY* srcKey,
int Endian) {
uint32_t* const L = (uint32_t*)srcBytes;
uint32_t* const R = (uint32_t*)(srcBytes + 4);
if (Endian == BLOWFISH_BIG_ENDIAN) {
*L = _bswap(*L);
*R = _bswap(*R);
}
*L ^= srcKey->SubKey[0];
*R ^= f_transform(srcBytes, srcKey->SBox);
*R ^= srcKey->SubKey[1];
*L ^= f_transform(srcBytes + 4, srcKey->SBox);
*L ^= srcKey->SubKey[2];
*R ^= f_transform(srcBytes, srcKey->SBox);
*R ^= srcKey->SubKey[3];
*L ^= f_transform(srcBytes + 4, srcKey->SBox);
*L ^= srcKey->SubKey[4];
*R ^= f_transform(srcBytes, srcKey->SBox);
*R ^= srcKey->SubKey[5];
*L ^= f_transform(srcBytes + 4, srcKey->SBox);
*L ^= srcKey->SubKey[6];
*R ^= f_transform(srcBytes, srcKey->SBox);
*R ^= srcKey->SubKey[7];
*L ^= f_transform(srcBytes + 4, srcKey->SBox);
*L ^= srcKey->SubKey[8];
*R ^= f_transform(srcBytes, srcKey->SBox);
*R ^= srcKey->SubKey[9];
*L ^= f_transform(srcBytes + 4, srcKey->SBox);
*L ^= srcKey->SubKey[10];
*R ^= f_transform(srcBytes, srcKey->SBox);
*R ^= srcKey->SubKey[11];
*L ^= f_transform(srcBytes + 4, srcKey->SBox);
*L ^= srcKey->SubKey[12];
*R ^= f_transform(srcBytes, srcKey->SBox);
*R ^= srcKey->SubKey[13];
*L ^= f_transform(srcBytes + 4, srcKey->SBox);
*L ^= srcKey->SubKey[14];
*R ^= f_transform(srcBytes, srcKey->SBox);
*R ^= srcKey->SubKey[15];
*L ^= f_transform(srcBytes + 4, srcKey->SBox);
*L ^= srcKey->SubKey[16];
*R ^= srcKey->SubKey[17];
uint32_t temp = *R;
*R = *L;
*L = temp;
if (Endian == BLOWFISH_BIG_ENDIAN) {
*L = _bswap(*L);
*R = _bswap(*R);
}
}
void accelc_Blowfish_decrypt(uint8_t srcBytes[8],
const BLOWFISH_KEY* srcKey,
int Endian) {
uint32_t* const L = (uint32_t*)srcBytes;
uint32_t* const R = (uint32_t*)(srcBytes + 4);
if (Endian == BLOWFISH_BIG_ENDIAN) {
*L = _bswap(*L);
*R = _bswap(*R);
}
uint32_t temp = *R;
*R = *L;
*L = temp;
*L ^= srcKey->SubKey[16];
*R ^= srcKey->SubKey[17];
*L ^= f_transform(srcBytes + 4, srcKey->SBox);
*R ^= srcKey->SubKey[15];
*R ^= f_transform(srcBytes, srcKey->SBox);
*L ^= srcKey->SubKey[14];
*L ^= f_transform(srcBytes + 4, srcKey->SBox);
*R ^= srcKey->SubKey[13];
*R ^= f_transform(srcBytes, srcKey->SBox);
*L ^= srcKey->SubKey[12];
*L ^= f_transform(srcBytes + 4, srcKey->SBox);
*R ^= srcKey->SubKey[11];
*R ^= f_transform(srcBytes, srcKey->SBox);
*L ^= srcKey->SubKey[10];
*L ^= f_transform(srcBytes + 4, srcKey->SBox);
*R ^= srcKey->SubKey[9];
*R ^= f_transform(srcBytes, srcKey->SBox);
*L ^= srcKey->SubKey[8];
*L ^= f_transform(srcBytes + 4, srcKey->SBox);
*R ^= srcKey->SubKey[7];
*R ^= f_transform(srcBytes, srcKey->SBox);
*L ^= srcKey->SubKey[6];
*L ^= f_transform(srcBytes + 4, srcKey->SBox);
*R ^= srcKey->SubKey[5];
*R ^= f_transform(srcBytes, srcKey->SBox);
*L ^= srcKey->SubKey[4];
*L ^= f_transform(srcBytes + 4, srcKey->SBox);
*R ^= srcKey->SubKey[3];
*R ^= f_transform(srcBytes, srcKey->SBox);
*L ^= srcKey->SubKey[2];
*L ^= f_transform(srcBytes + 4, srcKey->SBox);
*R ^= srcKey->SubKey[1];
*R ^= f_transform(srcBytes, srcKey->SBox);
*L ^= srcKey->SubKey[0];
if (Endian == BLOWFISH_BIG_ENDIAN) {
*L = _bswap(*L);
*R = _bswap(*R);
}
}
int accelc_Blowfish_set_key(const uint8_t srcUserKey[], uint8_t UserKeyLength,
BLOWFISH_KEY* dstKey) {
if (UserKeyLength == 0)
return STATUS_BLOWFISH_INVALID_KEY_LENGTH;
if (UserKeyLength > BLOWFISH_MAX_KEY_LENGTH)
return STATUS_BLOWFISH_KEY_TOO_LONG;
memcpy(dstKey->SubKey, accelc_Blowfish_Original_PBox, sizeof(accelc_Blowfish_Original_PBox));
memcpy(dstKey->SBox, accelc_Blowfish_Original_SBox, sizeof(accelc_Blowfish_Original_SBox));
for (int i = 0; i < 18; ++i) {
uint32_t temp = 0;
temp <<= 8;
temp |= srcUserKey[(i * 4) % UserKeyLength];
temp <<= 8;
temp |= srcUserKey[(i * 4 + 1) % UserKeyLength];
temp <<= 8;
temp |= srcUserKey[(i * 4 + 2) % UserKeyLength];
temp <<= 8;
temp |= srcUserKey[(i * 4 + 3) % UserKeyLength];
dstKey->SubKey[i] ^= temp;
}
uint8_t temp[8] = { 0 };
for (int i = 0; i < 9; ++i) {
accelc_Blowfish_encrypt(temp, dstKey, BLOWFISH_LITTLE_ENDIAN);
((uint64_t*)dstKey->SubKey)[i] = *(uint64_t*)temp;
}
for (int i = 0; i < 512; ++i) {
accelc_Blowfish_encrypt(temp, dstKey, BLOWFISH_LITTLE_ENDIAN);
((uint64_t*)dstKey->SBox)[i] = *(uint64_t*)temp;
}
return STATUS_BLOWFISH_SUCCESS;
}
-39
View File
@@ -1,39 +0,0 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#define STATUS_BLOWFISH_SUCCESS 0
#define STATUS_BLOWFISH_INVALID_KEY_LENGTH (-1)
#define STATUS_BLOWFISH_KEY_TOO_LONG (-2)
#define BLOWFISH_LITTLE_ENDIAN 0
#define BLOWFISH_BIG_ENDIAN 1
#define BLOWFISH_MIN_KEY_LENGTH 1
#define BLOWFISH_MAX_KEY_LENGTH 56
#define BLOWFISH_BLOCK_SIZE 8
#if defined(__cplusplus)
extern "C" {
#endif
typedef struct _BLOWFISH_KEY {
uint32_t SubKey[18];
uint32_t SBox[4][256];
} BLOWFISH_KEY;
void accelc_Blowfish_encrypt(uint8_t srcBytes[8],
const BLOWFISH_KEY* srcKey,
int Endian);
void accelc_Blowfish_decrypt(uint8_t srcBytes[8],
const BLOWFISH_KEY* srcKey,
int Endian);
int accelc_Blowfish_set_key(const uint8_t srcUserKey[], uint8_t UserKeyLength,
BLOWFISH_KEY* dstKey);
#if defined(__cplusplus)
}
#endif
-120
View File
@@ -1,120 +0,0 @@
#include "sha1.h"
#include <memory.h>
#if defined(_MSC_VER)
#include <intrin.h>
#define _bswap _byteswap_ulong
#define _bswap64 _byteswap_uint64
#elif defined(__GNUC__)
#include <x86intrin.h>
#endif
#define SHA1_BLOCKSIZE 64
void accelc_SHA1_init(SHA1_BUFFER* HashBuffer) {
HashBuffer->dword[0] = 0x67452301;
HashBuffer->dword[1] = 0xEFCDAB89;
HashBuffer->dword[2] = 0x98BADCFE;
HashBuffer->dword[3] = 0x10325476;
HashBuffer->dword[4] = 0xC3D2E1F0;
}
void accelc_SHA1_update(const void* __restrict srcBytes, size_t srcBytesLength,
SHA1_BUFFER* __restrict HashBuffer) {
uint32_t Buffer[80] = { 0 };
uint32_t a, b, c, d, e;
const uint32_t (*MessageBlock)[16] = srcBytes;
size_t RoundsOfMainCycle = srcBytesLength / SHA1_BLOCKSIZE;
for (size_t i = 0; i < RoundsOfMainCycle; ++i) {
for (int j = 0; j < 16; ++j)
Buffer[j] = _bswap(MessageBlock[i][j]);
for (int j = 16; j < 80; ++j) {
uint32_t temp = Buffer[j - 3] ^ Buffer[j - 8] ^ Buffer[j - 14] ^ Buffer[j - 16];
Buffer[j] = _rotl(temp, 1);
}
a = HashBuffer->dword[0];
b = HashBuffer->dword[1];
c = HashBuffer->dword[2];
d = HashBuffer->dword[3];
e = HashBuffer->dword[4];
for (int j = 0; j < 20; ++j) {
uint32_t T = _rotl(a, 5);
T += ((b & c) ^ (~b & d)) + e + 0x5A827999 + Buffer[j];
e = d;
d = c;
c = _rotl(b, 30);
b = a;
a = T;
}
for (int j = 20; j < 40; ++j) {
uint32_t T = _rotl(a, 5);
T += (b ^ c ^ d) + e + 0x6ED9EBA1 + Buffer[j];
e = d;
d = c;
c = _rotl(b, 30);
b = a;
a = T;
}
for (int j = 40; j < 60; ++j) {
uint32_t T = _rotl(a, 5);
T += ((b & c) ^ (b & d) ^ (c & d)) + e + 0x8F1BBCDC + Buffer[j];
e = d;
d = c;
c = _rotl(b, 30);
b = a;
a = T;
}
for (int j = 60; j < 80; ++j) {
uint32_t T = _rotl(a, 5);
T += (b ^ c ^ d) + e + 0xCA62C1D6 + Buffer[j];
e = d;
d = c;
c = _rotl(b, 30);
b = a;
a = T;
}
HashBuffer->dword[0] += a;
HashBuffer->dword[1] += b;
HashBuffer->dword[2] += c;
HashBuffer->dword[3] += d;
HashBuffer->dword[4] += e;
}
}
void accelc_SHA1_final(const void* __restrict LeftBytes, size_t LeftBytesLength, uint64_t TotalBytesLength,
const SHA1_BUFFER* HashBuffer, SHA1_DIGEST* Hash) {
if (HashBuffer != Hash)
memcpy(Hash, HashBuffer, sizeof(SHA1_BUFFER));
if (LeftBytesLength >= SHA1_BLOCKSIZE) {
accelc_SHA1_update(LeftBytes, LeftBytesLength, Hash);
LeftBytes = (const uint8_t*)LeftBytes + (LeftBytesLength / SHA1_BLOCKSIZE) * SHA1_BLOCKSIZE;
LeftBytesLength %= SHA1_BLOCKSIZE;
}
uint8_t Extra[128] = { 0 };
for (size_t i = 0; i < LeftBytesLength; ++i)
Extra[i] = ((const uint8_t*)LeftBytes)[i];
Extra[LeftBytesLength] = 0x80;
*(uint64_t*)(Extra + (LeftBytesLength >= 64 - 8 ? 128 - 8 : 64 - 8)) = _bswap64(TotalBytesLength * 8);
accelc_SHA1_update(Extra, LeftBytesLength >= 56 ? 128 : 64, Hash);
Hash->dword[0] = _bswap(Hash->dword[0]);
Hash->dword[1] = _bswap(Hash->dword[1]);
Hash->dword[2] = _bswap(Hash->dword[2]);
Hash->dword[3] = _bswap(Hash->dword[3]);
Hash->dword[4] = _bswap(Hash->dword[4]);
}
void accelc_SHA1(const void* __restrict srcBytes, size_t srclen,
SHA1_DIGEST* __restrict Hash) {
accelc_SHA1_init(Hash);
accelc_SHA1_update(srcBytes, srclen, Hash);
accelc_SHA1_final((uint8_t*)srcBytes + (srclen / SHA1_BLOCKSIZE) * SHA1_BLOCKSIZE, srclen % SHA1_BLOCKSIZE, srclen, Hash, Hash);
}
-29
View File
@@ -1,29 +0,0 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#if defined(__cplusplus)
extern "C" {
#endif
typedef struct _SHA1_DIGEST {
union {
uint8_t byte[20];
uint32_t dword[5];
};
} SHA1_DIGEST, SHA1_BUFFER;
void accelc_SHA1_init(SHA1_BUFFER* HashBuffer);
void accelc_SHA1_update(const void* __restrict srcBytes, size_t srcBytesLength,
SHA1_BUFFER* __restrict HashBuffer);
void accelc_SHA1_final(const void* __restrict LeftBytes, size_t LeftBytesLength, uint64_t TotalBytesLength,
const SHA1_BUFFER* HashBuffer, SHA1_DIGEST* Hash);
void accelc_SHA1(const void* __restrict srcBytes, size_t srclen,
SHA1_DIGEST* __restrict Hash);
#if defined(__cplusplus)
}
#endif
+82
View File
@@ -0,0 +1,82 @@
#include "PatchSolutions.hpp"
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\PatchSolution0.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
const char PatchSolution0::Keyword[461] =
"-----BEGIN PUBLIC KEY-----\r\n"
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw1dqF3SkCaAAmMzs889I\r\n"
"qdW9M2dIdh3jG9yPcmLnmJiGpBF4E9VHSMGe8oPAy2kJDmdNt4BcEygvssEfginv\r\n"
"a5t5jm352UAoDosUJkTXGQhpAWMF4fBmBpO3EedG62rOsqMBgmSdAyxCSPBRJIOF\r\n"
"R0QgZFbRnU0frj34fiVmgYiLuZSAmIbs8ZxiHPdp1oD4tUpvsFci4QJtYNjNnGU2\r\n"
"WPH6rvChGl1IRKrxMtqLielsvajUjyrgOC6NmymYMvZNER3htFEtL1eQbCyTfDmt\r\n"
"YyQ1Wt4Ot12lxf0wVIR5mcGN7XCXJRHOFHSf1gzXWabRSvmt1nrl7sW6cjxljuuQ\r\n"
"awIDAQAB\r\n"
"-----END PUBLIC KEY-----\r\n";
[[nodiscard]]
bool PatchSolution0::FindPatchOffset() noexcept {
try {
_PatchOffset = _Image.PointerToFileOffset(
_Image.SearchSection<uint8_t*>(".rsrc", [](const uint8_t* p) {
__try {
return memcmp(p, Keyword, literal_length(Keyword)) == 0;
} __except (EXCEPTION_EXECUTE_HANDLER) {
return false;
}
})
);
LOG_SUCCESS(0, "PatchSolution0 ...... Ready to apply");
LOG_HINT(4, "Patch offset = +0x%.8zx", _PatchOffset);
return true;
} catch (nkg::Exception&) {
_PatchOffset = InvalidOffset;
LOG_FAILURE(0, "PatchSolution0 ...... Omitted");
return false;
}
}
[[nodiscard]]
bool PatchSolution0::CheckKey(const RSACipher& Cipher) const noexcept {
auto szPublicKey = Cipher.ExportKeyString<RSAKeyType::PublicKey, RSAKeyFormat::PEM>();
for (auto i = szPublicKey.find("\n"); i != std::string::npos; i = szPublicKey.find("\n", i + 2)) {
szPublicKey.replace(i, 1, "\r\n");
}
return szPublicKey.length() == literal_length(Keyword);
}
void PatchSolution0::MakePatch(const RSACipher& Cipher) const {
if (_PatchOffset == InvalidOffset) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("PatchSolution0 has not been ready yet."));
}
auto szPublicKey = Cipher.ExportKeyString<RSAKeyType::PublicKey, RSAKeyFormat::PEM>();
for (auto i = szPublicKey.find("\n"); i != std::string::npos; i = szPublicKey.find("\n", i + 2)) {
szPublicKey.replace(i, 1, "\r\n");
}
_putts(TEXT("*******************************************************"));
_putts(TEXT("* PatchSolution0 *"));
_putts(TEXT("*******************************************************"));
LOG_HINT(0, "Previous:");
PrintMemory(_Image.ImageOffset(_PatchOffset), literal_length(Keyword), _Image.ImageBase());
memcpy(_Image.ImageOffset(_PatchOffset), szPublicKey.c_str(), literal_length(Keyword));
LOG_HINT(0, "After:");
PrintMemory(_Image.ImageOffset(_PatchOffset), literal_length(Keyword), _Image.ImageBase());
_putts(TEXT(""));
}
}
+308
View File
@@ -0,0 +1,308 @@
#include "PatchSolutions.hpp"
#include "NavicatCrypto.hpp"
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\PatchSolution1.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
static Navicat11Crypto g_NavicatCipher = Navicat11Crypto("23970790", 8);
const char PatchSolution1::Keyword0[160 + 1] =
"D75125B70767B94145B47C1CB3C0755E"
"7CCB8825C5DCE0C58ACF944E08280140"
"9A02472FAFFD1CD77864BB821AE36766"
"FEEDE6A24F12662954168BFA314BD950"
"32B9D82445355ED7BC0B880887D650F5";
const char PatchSolution1::Keyword1[4 + 1] =
"\xfe\xea\xbc\x01";
const char PatchSolution1::Keyword2[742 + 1] =
"E1CED09B9C2186BF71A70C0FE2F1E0AE"
"F3BD6B75277AAB20DFAF3D110F75912B"
"FB63AC50EC4C48689D1502715243A79F"
"39FF2DE2BF15CE438FF885745ED54573"
"850E8A9F40EE2FF505EB7476F95ADB78"
"3B28CA374FAC4632892AB82FB3BF4715"
"FCFE6E82D03731FC3762B6AAC3DF1C3B"
"C646FE9CD3C62663A97EE72DB932A301"
"312B4A7633100C8CC357262C39A2B3A6"
"4B224F5276D5EDBDF0804DC3AC4B8351"
"62BB1969EAEBADC43D2511D6E0239287"
"81B167A48273B953378D3D2080CC0677"
"7E8A2364F0234B81064C5C739A8DA28D"
"C5889072BF37685CBC94C2D31D0179AD"
"86D8E3AA8090D4F0B281BE37E0143746"
"E6049CCC06899401264FA471C016A96C"
"79815B55BBC26B43052609D9D175FBCD"
"E455392F10E51EC162F51CF732E6BB39"
"1F56BBFD8D957DF3D4C55B71CEFD54B1"
"9C16D458757373E698D7E693A8FC3981"
"5A8BF03BA05EA8C8778D38F9873D62B4"
"460F41ACF997C30E7C3AF025FA171B5F"
"5AD4D6B15E95C27F6B35AD61875E5505"
"449B4E";
const char PatchSolution1::Keyword3[4 + 1] =
"\x59\x08\x01\x00";
const char PatchSolution1::Keyword4[5 + 1] =
"92933";
[[nodiscard]]
bool PatchSolution1::FindPatchOffset() noexcept {
try {
PIMAGE_SECTION_HEADER SectionHeader_text = _Image.ImageSectionHeaderByName(".text");
PIMAGE_SECTION_HEADER SectionHeader_rdata = _Image.ImageSectionHeaderByName(".rdata");
const uint8_t* pbPatch[_countof(_PatchOffset)] = {};
pbPatch[0] = _Image.SearchSection<const uint8_t*>(SectionHeader_rdata, [](const uint8_t* p) {
__try {
return memcmp(p, Keyword0, sizeof(Keyword0)) == 0;
} __except (EXCEPTION_EXECUTE_HANDLER) {
return false;
}
});
pbPatch[2] = _Image.SearchSection<const uint8_t*>(SectionHeader_rdata, [](const uint8_t* p) {
__try {
return memcmp(p, Keyword2, sizeof(Keyword2)) == 0;
} __except (EXCEPTION_EXECUTE_HANDLER) {
return false;
}
});
pbPatch[4] = _Image.SearchSection<const uint8_t*>(SectionHeader_rdata, [](const uint8_t* p) {
__try {
return memcmp(p, Keyword4, sizeof(Keyword4)) == 0;
} __except (EXCEPTION_EXECUTE_HANDLER) {
return false;
}
});
pbPatch[1] = _Image.SearchSection<const uint8_t*>(SectionHeader_text, [&pbPatch](const uint8_t* p) {
__try {
if (memcmp(p, Keyword1, literal_length(Keyword1)) == 0) {
// Keyword3 must be close to Keyword1
for (auto j = p - 64; j < p + 64; ++j) {
if (memcmp(j, Keyword3, literal_length(Keyword3)) == 0) {
pbPatch[3] = j;
return true;
}
}
}
return false;
} __except (EXCEPTION_EXECUTE_HANDLER) {
return false;
}
});
for (size_t i = 0; i < _countof(_PatchOffset); ++i) {
_PatchOffset[i] = _Image.PointerToFileOffset(pbPatch[i]);
}
_PatchSize[0] = literal_length(Keyword0);
while (pbPatch[0][_PatchSize[0] + 1] == 0 && _PatchSize[0] < literal_length(Keyword0) + literal_length("29158142") - 1) {
++_PatchSize[0];
}
_PatchSize[1] = sizeof(uint32_t);
_PatchSize[2] = literal_length(Keyword2);
while (pbPatch[2][_PatchSize[2] + 1] == 0 && _PatchSize[2] < literal_length(Keyword2) + literal_length("67673") - 1) {
++_PatchSize[2];
}
_PatchSize[3] = sizeof(uint32_t);
_PatchSize[4] = literal_length(Keyword4);
LOG_SUCCESS(0, "PatchSolution1 ...... Ready to apply");
LOG_HINT(4, "[0] Patch offset = +0x%.8zx", _PatchOffset[0]);
LOG_HINT(4, "[1] Patch offset = +0x%.8zx", _PatchOffset[1]);
LOG_HINT(4, "[2] Patch offset = +0x%.8zx", _PatchOffset[2]);
LOG_HINT(4, "[3] Patch offset = +0x%.8zx", _PatchOffset[3]);
LOG_HINT(4, "[4] Patch offset = +0x%.8zx", _PatchOffset[4]);
return true;
} catch (nkg::Exception&) {
for (size_t i = 0; i < _countof(_PatchOffset); ++i) {
_PatchOffset[i] = InvalidOffset;
_PatchSize[i] = 0;
}
LOG_FAILURE(0, "PatchSolution1 ...... Omitted");
return false;
}
}
[[nodiscard]]
bool PatchSolution1::CheckKey(const RSACipher& Cipher) const noexcept {
if (_PatchSize[0] && _PatchSize[1] && _PatchSize[2] && _PatchSize[3] && _PatchSize[4]) {
auto szPublicKey = Cipher.ExportKeyString<RSAKeyType::PublicKey, RSAKeyFormat::PEM>();
for (auto i = szPublicKey.find("\n"); i != std::string::npos; i = szPublicKey.find("\n", i + 2)) {
szPublicKey.replace(i, 1, "\r\n");
}
auto szPublicKeyEncrypted = g_NavicatCipher.EncryptString(szPublicKey);
if (szPublicKeyEncrypted.length() != 920) {
return false;
}
// we require the chars in [p1, p2) of szPublicKeyEncrypted must be number chars
size_t p1, p2;
p1 = _PatchSize[0];
p2 = literal_length(Keyword0) + literal_length("29158142");
if (('1' <= szPublicKeyEncrypted[p1] && szPublicKeyEncrypted[p1] <= '9') == false) {
return false;
}
for (size_t i = p1 + 1; i < p2; ++i) {
if (('0' <= szPublicKeyEncrypted[i] && szPublicKeyEncrypted[i] <= '9') == false) {
return false;
}
}
// we require the chars in [p1, p2) of szPublicKeyEncrypted must be number chars
p1 = literal_length(Keyword0) + literal_length("29158142") + _PatchSize[2];
p2 = literal_length(Keyword0) + literal_length("29158142") + literal_length(Keyword2) + literal_length("67673");
if (('1' <= szPublicKeyEncrypted[p1] && szPublicKeyEncrypted[p1] <= '9') == false) {
return false;
}
for (size_t i = p1 + 1; i < p2; ++i) {
if (('0' <= szPublicKeyEncrypted[i] && szPublicKeyEncrypted[i] <= '9') == false) {
return false;
}
}
return true;
} else {
return false;
}
}
void PatchSolution1::MakePatch(const RSACipher& Cipher) const {
if (_PatchSize[0] && _PatchSize[1] && _PatchSize[2] && _PatchSize[3] && _PatchSize[4]) {
auto szPublicKey = Cipher.ExportKeyString<RSAKeyType::PublicKey, RSAKeyFormat::PEM>();
for (auto i = szPublicKey.find("\n"); i != std::string::npos; i = szPublicKey.find("\n", i + 2)) {
szPublicKey.replace(i, 1, "\r\n");
}
auto szPublicKeyEncrypted = g_NavicatCipher.EncryptString(szPublicKey);
//
// p0 p1 p2 p3 p4 p5
// Original encrypted public key layout: |160 chars|8 chars|742 chars|5 chars|5 chars|
// | |
// V V
// ImmValue1 ImmValue3
size_t p0, p1, p2, p3, p4, p5;
p0 = 0;
p1 = _PatchSize[0];
p2 = literal_length(Keyword0) + literal_length("29158142");
p3 = literal_length(Keyword0) + literal_length("29158142") + _PatchSize[2];
p4 = literal_length(Keyword0) + literal_length("29158142") + literal_length(Keyword2) + literal_length("67673");
p5 = literal_length(Keyword0) + literal_length("29158142") + literal_length(Keyword2) + literal_length("67673") + literal_length(Keyword4);
if (szPublicKeyEncrypted.length() != 920) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("szPublicKeyEncrypted.length() != 920"));
}
std::string EncryptedPEM0(szPublicKeyEncrypted.begin() + p0, szPublicKeyEncrypted.begin() + p1);
std::string EncryptedPEM1(szPublicKeyEncrypted.begin() + p1, szPublicKeyEncrypted.begin() + p2);
std::string EncryptedPEM2(szPublicKeyEncrypted.begin() + p2, szPublicKeyEncrypted.begin() + p3);
std::string EncryptedPEM3(szPublicKeyEncrypted.begin() + p3, szPublicKeyEncrypted.begin() + p4);
std::string EncryptedPEM4(szPublicKeyEncrypted.begin() + p4, szPublicKeyEncrypted.begin() + p5);
uint32_t ImmValue1 = std::stoul(EncryptedPEM1.c_str());
uint32_t ImmValue3 = std::stoul(EncryptedPEM3.c_str());
uint8_t* pbPatch[_countof(_PatchOffset)] = {};
for (size_t i = 0; i < _countof(_PatchOffset); ++i) {
pbPatch[i] = _Image.FileOffsetToPointer<uint8_t*>(_PatchOffset[i]);
}
_putts(TEXT("*******************************************************"));
_putts(TEXT("* PatchSolution1 *"));
_putts(TEXT("*******************************************************"));
// ----------------------------------
// process PatchOffsets[0]
// ----------------------------------
LOG_HINT(0, "Previous:");
PrintMemory(pbPatch[0], _PatchSize[0], _Image.ImageBase());
memcpy(pbPatch[0], EncryptedPEM0.data(), _PatchSize[0]);
LOG_HINT(0, "After:");
PrintMemory(pbPatch[0], _PatchSize[0], _Image.ImageBase());
_putts(TEXT(""));
// ----------------------------------
// process PatchOffsets[1]
// ----------------------------------
LOG_HINT(0, "Previous:");
PrintMemory(pbPatch[1], _PatchSize[1], _Image.ImageBase());
memcpy(pbPatch[1], &ImmValue1, _PatchSize[1]);
LOG_HINT(0, "After:");
PrintMemory(pbPatch[1], _PatchSize[1], _Image.ImageBase());
_putts(TEXT(""));
// ----------------------------------
// process PatchOffsets[2]
// ----------------------------------
LOG_HINT(0, "Previous:");
PrintMemory(pbPatch[2], _PatchSize[2], _Image.ImageBase());
memcpy(pbPatch[2], EncryptedPEM2.data(), _PatchSize[2]);
LOG_HINT(0, "After:");
PrintMemory(pbPatch[2], _PatchSize[2], _Image.ImageBase());
_putts(TEXT(""));
// ----------------------------------
// process PatchOffsets[3]
// ----------------------------------
LOG_HINT(0, "Previous:");
PrintMemory(pbPatch[3], _PatchSize[3], _Image.ImageBase());
memcpy(pbPatch[3], &ImmValue3, _PatchSize[3]);
LOG_HINT(0, "After:");
PrintMemory(pbPatch[3], _PatchSize[3], _Image.ImageBase());
_putts(TEXT(""));
// ----------------------------------
// process PatchOffsets[4]
// ----------------------------------
LOG_HINT(0, "Previous:");
PrintMemory(pbPatch[4], _PatchSize[4], _Image.ImageBase());
memcpy(pbPatch[4], EncryptedPEM4.data(), _PatchSize[4]);
LOG_HINT(0, "After:");
PrintMemory(pbPatch[4], _PatchSize[4], _Image.ImageBase());
_putts(TEXT(""));
} else {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("PatchSolution1 has not been ready yet."));
}
}
}
+511
View File
@@ -0,0 +1,511 @@
#include "PatchSolutions.hpp"
#include <vector>
#include <algorithm>
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\PatchSolution2-amd64.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
/*
Keyword[0x188][5] is generated by the following python script:
-----Begin Python3 Script-----
meta = \
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw1dqF3SkCaAAmMzs889I" \
"qdW9M2dIdh3jG9yPcmLnmJiGpBF4E9VHSMGe8oPAy2kJDmdNt4BcEygvssEfginv" \
"a5t5jm352UAoDosUJkTXGQhpAWMF4fBmBpO3EedG62rOsqMBgmSdAyxCSPBRJIOF" \
"R0QgZFbRnU0frj34fiVmgYiLuZSAmIbs8ZxiHPdp1oD4tUpvsFci4QJtYNjNnGU2" \
"WPH6rvChGl1IRKrxMtqLielsvajUjyrgOC6NmymYMvZNER3htFEtL1eQbCyTfDmt" \
"YyQ1Wt4Ot12lxf0wVIR5mcGN7XCXJRHOFHSf1gzXWabRSvmt1nrl7sW6cjxljuuQ" \
"awIDAQAB"
print('const uint8_t PatchSolution2::Keyword[0x188][5] = {')
for i in range(0, len(meta)):
i1 = '0x83, 0xf0, 0x%.2x' % ord(meta[i]) # asm('xor eax, meta[i]')
i2 = '0x88, 0x05' # asm_prefix('mov byte ptr ds:xxxxxxxxxxxxxxxx, al')
print(' { %s, %s }' % (i1, i2), end = ',\n' if i != len(meta) - 1 else '\n')
print('};')
-----End Python3 Script-----
*/
const uint8_t PatchSolution2::Keyword[0x188][5] = {
{ 0x83, 0xf0, 0x4d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x49, 0x88, 0x05 },
{ 0x83, 0xf0, 0x49, 0x88, 0x05 },
{ 0x83, 0xf0, 0x42, 0x88, 0x05 },
{ 0x83, 0xf0, 0x49, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x41, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4e, 0x88, 0x05 },
{ 0x83, 0xf0, 0x42, 0x88, 0x05 },
{ 0x83, 0xf0, 0x67, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6b, 0x88, 0x05 },
{ 0x83, 0xf0, 0x71, 0x88, 0x05 },
{ 0x83, 0xf0, 0x68, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6b, 0x88, 0x05 },
{ 0x83, 0xf0, 0x69, 0x88, 0x05 },
{ 0x83, 0xf0, 0x47, 0x88, 0x05 },
{ 0x83, 0xf0, 0x39, 0x88, 0x05 },
{ 0x83, 0xf0, 0x77, 0x88, 0x05 },
{ 0x83, 0xf0, 0x30, 0x88, 0x05 },
{ 0x83, 0xf0, 0x42, 0x88, 0x05 },
{ 0x83, 0xf0, 0x41, 0x88, 0x05 },
{ 0x83, 0xf0, 0x51, 0x88, 0x05 },
{ 0x83, 0xf0, 0x45, 0x88, 0x05 },
{ 0x83, 0xf0, 0x46, 0x88, 0x05 },
{ 0x83, 0xf0, 0x41, 0x88, 0x05 },
{ 0x83, 0xf0, 0x41, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4f, 0x88, 0x05 },
{ 0x83, 0xf0, 0x43, 0x88, 0x05 },
{ 0x83, 0xf0, 0x41, 0x88, 0x05 },
{ 0x83, 0xf0, 0x51, 0x88, 0x05 },
{ 0x83, 0xf0, 0x38, 0x88, 0x05 },
{ 0x83, 0xf0, 0x41, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x49, 0x88, 0x05 },
{ 0x83, 0xf0, 0x49, 0x88, 0x05 },
{ 0x83, 0xf0, 0x42, 0x88, 0x05 },
{ 0x83, 0xf0, 0x43, 0x88, 0x05 },
{ 0x83, 0xf0, 0x67, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4b, 0x88, 0x05 },
{ 0x83, 0xf0, 0x43, 0x88, 0x05 },
{ 0x83, 0xf0, 0x41, 0x88, 0x05 },
{ 0x83, 0xf0, 0x51, 0x88, 0x05 },
{ 0x83, 0xf0, 0x45, 0x88, 0x05 },
{ 0x83, 0xf0, 0x41, 0x88, 0x05 },
{ 0x83, 0xf0, 0x77, 0x88, 0x05 },
{ 0x83, 0xf0, 0x31, 0x88, 0x05 },
{ 0x83, 0xf0, 0x64, 0x88, 0x05 },
{ 0x83, 0xf0, 0x71, 0x88, 0x05 },
{ 0x83, 0xf0, 0x46, 0x88, 0x05 },
{ 0x83, 0xf0, 0x33, 0x88, 0x05 },
{ 0x83, 0xf0, 0x53, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6b, 0x88, 0x05 },
{ 0x83, 0xf0, 0x43, 0x88, 0x05 },
{ 0x83, 0xf0, 0x61, 0x88, 0x05 },
{ 0x83, 0xf0, 0x41, 0x88, 0x05 },
{ 0x83, 0xf0, 0x41, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x7a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x73, 0x88, 0x05 },
{ 0x83, 0xf0, 0x38, 0x88, 0x05 },
{ 0x83, 0xf0, 0x38, 0x88, 0x05 },
{ 0x83, 0xf0, 0x39, 0x88, 0x05 },
{ 0x83, 0xf0, 0x49, 0x88, 0x05 },
{ 0x83, 0xf0, 0x71, 0x88, 0x05 },
{ 0x83, 0xf0, 0x64, 0x88, 0x05 },
{ 0x83, 0xf0, 0x57, 0x88, 0x05 },
{ 0x83, 0xf0, 0x39, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x32, 0x88, 0x05 },
{ 0x83, 0xf0, 0x64, 0x88, 0x05 },
{ 0x83, 0xf0, 0x49, 0x88, 0x05 },
{ 0x83, 0xf0, 0x64, 0x88, 0x05 },
{ 0x83, 0xf0, 0x68, 0x88, 0x05 },
{ 0x83, 0xf0, 0x33, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x47, 0x88, 0x05 },
{ 0x83, 0xf0, 0x39, 0x88, 0x05 },
{ 0x83, 0xf0, 0x79, 0x88, 0x05 },
{ 0x83, 0xf0, 0x50, 0x88, 0x05 },
{ 0x83, 0xf0, 0x63, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4c, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6e, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x69, 0x88, 0x05 },
{ 0x83, 0xf0, 0x47, 0x88, 0x05 },
{ 0x83, 0xf0, 0x70, 0x88, 0x05 },
{ 0x83, 0xf0, 0x42, 0x88, 0x05 },
{ 0x83, 0xf0, 0x46, 0x88, 0x05 },
{ 0x83, 0xf0, 0x34, 0x88, 0x05 },
{ 0x83, 0xf0, 0x45, 0x88, 0x05 },
{ 0x83, 0xf0, 0x39, 0x88, 0x05 },
{ 0x83, 0xf0, 0x56, 0x88, 0x05 },
{ 0x83, 0xf0, 0x48, 0x88, 0x05 },
{ 0x83, 0xf0, 0x53, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x47, 0x88, 0x05 },
{ 0x83, 0xf0, 0x65, 0x88, 0x05 },
{ 0x83, 0xf0, 0x38, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6f, 0x88, 0x05 },
{ 0x83, 0xf0, 0x50, 0x88, 0x05 },
{ 0x83, 0xf0, 0x41, 0x88, 0x05 },
{ 0x83, 0xf0, 0x79, 0x88, 0x05 },
{ 0x83, 0xf0, 0x32, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6b, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x44, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x64, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4e, 0x88, 0x05 },
{ 0x83, 0xf0, 0x74, 0x88, 0x05 },
{ 0x83, 0xf0, 0x34, 0x88, 0x05 },
{ 0x83, 0xf0, 0x42, 0x88, 0x05 },
{ 0x83, 0xf0, 0x63, 0x88, 0x05 },
{ 0x83, 0xf0, 0x45, 0x88, 0x05 },
{ 0x83, 0xf0, 0x79, 0x88, 0x05 },
{ 0x83, 0xf0, 0x67, 0x88, 0x05 },
{ 0x83, 0xf0, 0x76, 0x88, 0x05 },
{ 0x83, 0xf0, 0x73, 0x88, 0x05 },
{ 0x83, 0xf0, 0x73, 0x88, 0x05 },
{ 0x83, 0xf0, 0x45, 0x88, 0x05 },
{ 0x83, 0xf0, 0x66, 0x88, 0x05 },
{ 0x83, 0xf0, 0x67, 0x88, 0x05 },
{ 0x83, 0xf0, 0x69, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6e, 0x88, 0x05 },
{ 0x83, 0xf0, 0x76, 0x88, 0x05 },
{ 0x83, 0xf0, 0x61, 0x88, 0x05 },
{ 0x83, 0xf0, 0x35, 0x88, 0x05 },
{ 0x83, 0xf0, 0x74, 0x88, 0x05 },
{ 0x83, 0xf0, 0x35, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x33, 0x88, 0x05 },
{ 0x83, 0xf0, 0x35, 0x88, 0x05 },
{ 0x83, 0xf0, 0x32, 0x88, 0x05 },
{ 0x83, 0xf0, 0x55, 0x88, 0x05 },
{ 0x83, 0xf0, 0x41, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6f, 0x88, 0x05 },
{ 0x83, 0xf0, 0x44, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6f, 0x88, 0x05 },
{ 0x83, 0xf0, 0x73, 0x88, 0x05 },
{ 0x83, 0xf0, 0x55, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6b, 0x88, 0x05 },
{ 0x83, 0xf0, 0x54, 0x88, 0x05 },
{ 0x83, 0xf0, 0x58, 0x88, 0x05 },
{ 0x83, 0xf0, 0x47, 0x88, 0x05 },
{ 0x83, 0xf0, 0x51, 0x88, 0x05 },
{ 0x83, 0xf0, 0x68, 0x88, 0x05 },
{ 0x83, 0xf0, 0x70, 0x88, 0x05 },
{ 0x83, 0xf0, 0x41, 0x88, 0x05 },
{ 0x83, 0xf0, 0x57, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x46, 0x88, 0x05 },
{ 0x83, 0xf0, 0x34, 0x88, 0x05 },
{ 0x83, 0xf0, 0x66, 0x88, 0x05 },
{ 0x83, 0xf0, 0x42, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x42, 0x88, 0x05 },
{ 0x83, 0xf0, 0x70, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4f, 0x88, 0x05 },
{ 0x83, 0xf0, 0x33, 0x88, 0x05 },
{ 0x83, 0xf0, 0x45, 0x88, 0x05 },
{ 0x83, 0xf0, 0x65, 0x88, 0x05 },
{ 0x83, 0xf0, 0x64, 0x88, 0x05 },
{ 0x83, 0xf0, 0x47, 0x88, 0x05 },
{ 0x83, 0xf0, 0x36, 0x88, 0x05 },
{ 0x83, 0xf0, 0x32, 0x88, 0x05 },
{ 0x83, 0xf0, 0x72, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4f, 0x88, 0x05 },
{ 0x83, 0xf0, 0x73, 0x88, 0x05 },
{ 0x83, 0xf0, 0x71, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x42, 0x88, 0x05 },
{ 0x83, 0xf0, 0x67, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x53, 0x88, 0x05 },
{ 0x83, 0xf0, 0x64, 0x88, 0x05 },
{ 0x83, 0xf0, 0x41, 0x88, 0x05 },
{ 0x83, 0xf0, 0x79, 0x88, 0x05 },
{ 0x83, 0xf0, 0x78, 0x88, 0x05 },
{ 0x83, 0xf0, 0x43, 0x88, 0x05 },
{ 0x83, 0xf0, 0x53, 0x88, 0x05 },
{ 0x83, 0xf0, 0x50, 0x88, 0x05 },
{ 0x83, 0xf0, 0x42, 0x88, 0x05 },
{ 0x83, 0xf0, 0x52, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x49, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4f, 0x88, 0x05 },
{ 0x83, 0xf0, 0x46, 0x88, 0x05 },
{ 0x83, 0xf0, 0x52, 0x88, 0x05 },
{ 0x83, 0xf0, 0x30, 0x88, 0x05 },
{ 0x83, 0xf0, 0x51, 0x88, 0x05 },
{ 0x83, 0xf0, 0x67, 0x88, 0x05 },
{ 0x83, 0xf0, 0x5a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x46, 0x88, 0x05 },
{ 0x83, 0xf0, 0x62, 0x88, 0x05 },
{ 0x83, 0xf0, 0x52, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6e, 0x88, 0x05 },
{ 0x83, 0xf0, 0x55, 0x88, 0x05 },
{ 0x83, 0xf0, 0x30, 0x88, 0x05 },
{ 0x83, 0xf0, 0x66, 0x88, 0x05 },
{ 0x83, 0xf0, 0x72, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x33, 0x88, 0x05 },
{ 0x83, 0xf0, 0x34, 0x88, 0x05 },
{ 0x83, 0xf0, 0x66, 0x88, 0x05 },
{ 0x83, 0xf0, 0x69, 0x88, 0x05 },
{ 0x83, 0xf0, 0x56, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x67, 0x88, 0x05 },
{ 0x83, 0xf0, 0x59, 0x88, 0x05 },
{ 0x83, 0xf0, 0x69, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4c, 0x88, 0x05 },
{ 0x83, 0xf0, 0x75, 0x88, 0x05 },
{ 0x83, 0xf0, 0x5a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x53, 0x88, 0x05 },
{ 0x83, 0xf0, 0x41, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x49, 0x88, 0x05 },
{ 0x83, 0xf0, 0x62, 0x88, 0x05 },
{ 0x83, 0xf0, 0x73, 0x88, 0x05 },
{ 0x83, 0xf0, 0x38, 0x88, 0x05 },
{ 0x83, 0xf0, 0x5a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x78, 0x88, 0x05 },
{ 0x83, 0xf0, 0x69, 0x88, 0x05 },
{ 0x83, 0xf0, 0x48, 0x88, 0x05 },
{ 0x83, 0xf0, 0x50, 0x88, 0x05 },
{ 0x83, 0xf0, 0x64, 0x88, 0x05 },
{ 0x83, 0xf0, 0x70, 0x88, 0x05 },
{ 0x83, 0xf0, 0x31, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6f, 0x88, 0x05 },
{ 0x83, 0xf0, 0x44, 0x88, 0x05 },
{ 0x83, 0xf0, 0x34, 0x88, 0x05 },
{ 0x83, 0xf0, 0x74, 0x88, 0x05 },
{ 0x83, 0xf0, 0x55, 0x88, 0x05 },
{ 0x83, 0xf0, 0x70, 0x88, 0x05 },
{ 0x83, 0xf0, 0x76, 0x88, 0x05 },
{ 0x83, 0xf0, 0x73, 0x88, 0x05 },
{ 0x83, 0xf0, 0x46, 0x88, 0x05 },
{ 0x83, 0xf0, 0x63, 0x88, 0x05 },
{ 0x83, 0xf0, 0x69, 0x88, 0x05 },
{ 0x83, 0xf0, 0x34, 0x88, 0x05 },
{ 0x83, 0xf0, 0x51, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x74, 0x88, 0x05 },
{ 0x83, 0xf0, 0x59, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4e, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4e, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6e, 0x88, 0x05 },
{ 0x83, 0xf0, 0x47, 0x88, 0x05 },
{ 0x83, 0xf0, 0x55, 0x88, 0x05 },
{ 0x83, 0xf0, 0x32, 0x88, 0x05 },
{ 0x83, 0xf0, 0x57, 0x88, 0x05 },
{ 0x83, 0xf0, 0x50, 0x88, 0x05 },
{ 0x83, 0xf0, 0x48, 0x88, 0x05 },
{ 0x83, 0xf0, 0x36, 0x88, 0x05 },
{ 0x83, 0xf0, 0x72, 0x88, 0x05 },
{ 0x83, 0xf0, 0x76, 0x88, 0x05 },
{ 0x83, 0xf0, 0x43, 0x88, 0x05 },
{ 0x83, 0xf0, 0x68, 0x88, 0x05 },
{ 0x83, 0xf0, 0x47, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6c, 0x88, 0x05 },
{ 0x83, 0xf0, 0x31, 0x88, 0x05 },
{ 0x83, 0xf0, 0x49, 0x88, 0x05 },
{ 0x83, 0xf0, 0x52, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4b, 0x88, 0x05 },
{ 0x83, 0xf0, 0x72, 0x88, 0x05 },
{ 0x83, 0xf0, 0x78, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x74, 0x88, 0x05 },
{ 0x83, 0xf0, 0x71, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4c, 0x88, 0x05 },
{ 0x83, 0xf0, 0x69, 0x88, 0x05 },
{ 0x83, 0xf0, 0x65, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6c, 0x88, 0x05 },
{ 0x83, 0xf0, 0x73, 0x88, 0x05 },
{ 0x83, 0xf0, 0x76, 0x88, 0x05 },
{ 0x83, 0xf0, 0x61, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x55, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x79, 0x88, 0x05 },
{ 0x83, 0xf0, 0x72, 0x88, 0x05 },
{ 0x83, 0xf0, 0x67, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4f, 0x88, 0x05 },
{ 0x83, 0xf0, 0x43, 0x88, 0x05 },
{ 0x83, 0xf0, 0x36, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4e, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x79, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x59, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x76, 0x88, 0x05 },
{ 0x83, 0xf0, 0x5a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4e, 0x88, 0x05 },
{ 0x83, 0xf0, 0x45, 0x88, 0x05 },
{ 0x83, 0xf0, 0x52, 0x88, 0x05 },
{ 0x83, 0xf0, 0x33, 0x88, 0x05 },
{ 0x83, 0xf0, 0x68, 0x88, 0x05 },
{ 0x83, 0xf0, 0x74, 0x88, 0x05 },
{ 0x83, 0xf0, 0x46, 0x88, 0x05 },
{ 0x83, 0xf0, 0x45, 0x88, 0x05 },
{ 0x83, 0xf0, 0x74, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4c, 0x88, 0x05 },
{ 0x83, 0xf0, 0x31, 0x88, 0x05 },
{ 0x83, 0xf0, 0x65, 0x88, 0x05 },
{ 0x83, 0xf0, 0x51, 0x88, 0x05 },
{ 0x83, 0xf0, 0x62, 0x88, 0x05 },
{ 0x83, 0xf0, 0x43, 0x88, 0x05 },
{ 0x83, 0xf0, 0x79, 0x88, 0x05 },
{ 0x83, 0xf0, 0x54, 0x88, 0x05 },
{ 0x83, 0xf0, 0x66, 0x88, 0x05 },
{ 0x83, 0xf0, 0x44, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x74, 0x88, 0x05 },
{ 0x83, 0xf0, 0x59, 0x88, 0x05 },
{ 0x83, 0xf0, 0x79, 0x88, 0x05 },
{ 0x83, 0xf0, 0x51, 0x88, 0x05 },
{ 0x83, 0xf0, 0x31, 0x88, 0x05 },
{ 0x83, 0xf0, 0x57, 0x88, 0x05 },
{ 0x83, 0xf0, 0x74, 0x88, 0x05 },
{ 0x83, 0xf0, 0x34, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4f, 0x88, 0x05 },
{ 0x83, 0xf0, 0x74, 0x88, 0x05 },
{ 0x83, 0xf0, 0x31, 0x88, 0x05 },
{ 0x83, 0xf0, 0x32, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6c, 0x88, 0x05 },
{ 0x83, 0xf0, 0x78, 0x88, 0x05 },
{ 0x83, 0xf0, 0x66, 0x88, 0x05 },
{ 0x83, 0xf0, 0x30, 0x88, 0x05 },
{ 0x83, 0xf0, 0x77, 0x88, 0x05 },
{ 0x83, 0xf0, 0x56, 0x88, 0x05 },
{ 0x83, 0xf0, 0x49, 0x88, 0x05 },
{ 0x83, 0xf0, 0x52, 0x88, 0x05 },
{ 0x83, 0xf0, 0x35, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x63, 0x88, 0x05 },
{ 0x83, 0xf0, 0x47, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4e, 0x88, 0x05 },
{ 0x83, 0xf0, 0x37, 0x88, 0x05 },
{ 0x83, 0xf0, 0x58, 0x88, 0x05 },
{ 0x83, 0xf0, 0x43, 0x88, 0x05 },
{ 0x83, 0xf0, 0x58, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x52, 0x88, 0x05 },
{ 0x83, 0xf0, 0x48, 0x88, 0x05 },
{ 0x83, 0xf0, 0x4f, 0x88, 0x05 },
{ 0x83, 0xf0, 0x46, 0x88, 0x05 },
{ 0x83, 0xf0, 0x48, 0x88, 0x05 },
{ 0x83, 0xf0, 0x53, 0x88, 0x05 },
{ 0x83, 0xf0, 0x66, 0x88, 0x05 },
{ 0x83, 0xf0, 0x31, 0x88, 0x05 },
{ 0x83, 0xf0, 0x67, 0x88, 0x05 },
{ 0x83, 0xf0, 0x7a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x58, 0x88, 0x05 },
{ 0x83, 0xf0, 0x57, 0x88, 0x05 },
{ 0x83, 0xf0, 0x61, 0x88, 0x05 },
{ 0x83, 0xf0, 0x62, 0x88, 0x05 },
{ 0x83, 0xf0, 0x52, 0x88, 0x05 },
{ 0x83, 0xf0, 0x53, 0x88, 0x05 },
{ 0x83, 0xf0, 0x76, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6d, 0x88, 0x05 },
{ 0x83, 0xf0, 0x74, 0x88, 0x05 },
{ 0x83, 0xf0, 0x31, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6e, 0x88, 0x05 },
{ 0x83, 0xf0, 0x72, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6c, 0x88, 0x05 },
{ 0x83, 0xf0, 0x37, 0x88, 0x05 },
{ 0x83, 0xf0, 0x73, 0x88, 0x05 },
{ 0x83, 0xf0, 0x57, 0x88, 0x05 },
{ 0x83, 0xf0, 0x36, 0x88, 0x05 },
{ 0x83, 0xf0, 0x63, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x78, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6c, 0x88, 0x05 },
{ 0x83, 0xf0, 0x6a, 0x88, 0x05 },
{ 0x83, 0xf0, 0x75, 0x88, 0x05 },
{ 0x83, 0xf0, 0x75, 0x88, 0x05 },
{ 0x83, 0xf0, 0x51, 0x88, 0x05 },
{ 0x83, 0xf0, 0x61, 0x88, 0x05 },
{ 0x83, 0xf0, 0x77, 0x88, 0x05 },
{ 0x83, 0xf0, 0x49, 0x88, 0x05 },
{ 0x83, 0xf0, 0x44, 0x88, 0x05 },
{ 0x83, 0xf0, 0x41, 0x88, 0x05 },
{ 0x83, 0xf0, 0x51, 0x88, 0x05 },
{ 0x83, 0xf0, 0x41, 0x88, 0x05 },
{ 0x83, 0xf0, 0x42, 0x88, 0x05 }
};
[[nodiscard]]
bool PatchSolution2::FindPatchOffset() noexcept {
try {
auto SectionHeader_text = _Image.ImageSectionHeaderByName(".text");
auto SectionView_text = _Image.ImageSectionView<const uint8_t*>(SectionHeader_text);
const uint8_t* lpPatch[_countof(_PatchOffset)] = {};
std::vector<size_t> Hints;
DWORD PossibleRangeStart = 0xffffffff;
DWORD PossibleRangeEnd;
for (DWORD i = 0; i < SectionHeader_text->SizeOfRawData; ++i) {
if (memcmp(SectionView_text + i, Keyword[0], sizeof(Keyword[0])) == 0) {
size_t RRip = i + sizeof(Keyword[0]) + sizeof(uint32_t);
size_t RRipOffset = *reinterpret_cast<const uint32_t*>(SectionView_text + i + sizeof(Keyword[0]));
Hints.emplace_back(RRip + RRipOffset);
if (i < PossibleRangeStart) {
PossibleRangeStart = i;
}
}
}
PossibleRangeStart -= 0x1000;
PossibleRangeEnd = PossibleRangeStart + 0x100000;
// Keywords[0] should occur 9 times.
// Because there's only 9 'M' chars in `KeywordMeta`.
if (Hints.size() != 9) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Hints.size() != 9"));
}
std::sort(Hints.begin(), Hints.end());
// assert
// if not satisfied, refuse to patch
if (Hints.back() - Hints.front() != 0x18360F8F8 - 0x18360F7D0) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Hints.back() - Hints.front() != 0x18360F8F8 - 0x18360F7D0"));
}
for (size_t i = 0; i < _countof(_PatchOffset); ++i) {
for (DWORD j = PossibleRangeStart; j < PossibleRangeEnd; ++j) {
if (memcmp(SectionView_text + j, Keyword[i], sizeof(Keyword[i])) == 0) {
size_t RRip = j + sizeof(Keyword[i]) + sizeof(uint32_t);
size_t RRipOffset = *reinterpret_cast<const uint32_t*>(SectionView_text + j + sizeof(Keyword[i]));
size_t Index = RRip + RRipOffset - Hints.front();
if (Index == i) {
lpPatch[i] = SectionView_text + j;
}
}
}
// if not found, refuse to patch
if (lpPatch[i] == nullptr) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("A patch point is missing."));
}
}
for (size_t i = 0; i < _countof(_PatchOffset); ++i) {
_PatchOffset[i] = _Image.PointerToFileOffset(lpPatch[i]);
}
LOG_SUCCESS(0, "PatchSolution2 ...... Ready to apply");
for (size_t i = 0; i < _countof(_PatchOffset); i += 4) {
static_assert(sizeof(_countof(_PatchOffset)) % 4 == 0);
LOG_HINT(4, "Patch offset[%zu ... %zu] = 0x%.8zx, 0x%.8zx, 0x%.8zx, 0x%.8zx", i, i + 3, _PatchOffset[i], _PatchOffset[i + 1], _PatchOffset[i + 2], _PatchOffset[i + 3]);
}
return true;
} catch (nkg::Exception&) {
for (size_t i = 0; i < _countof(_PatchOffset); ++i) {
_PatchOffset[i] = InvalidOffset;
}
LOG_FAILURE(0, "PatchSolution2 ...... Omitted");
return false;
}
}
}
@@ -0,0 +1,92 @@
#include "PatchSolutions.hpp"
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\PatchSolution2-generic.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
const char PatchSolution2::KeywordMeta[0x188 + 1] =
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw1dqF3SkCaAAmMzs889I"
"qdW9M2dIdh3jG9yPcmLnmJiGpBF4E9VHSMGe8oPAy2kJDmdNt4BcEygvssEfginv"
"a5t5jm352UAoDosUJkTXGQhpAWMF4fBmBpO3EedG62rOsqMBgmSdAyxCSPBRJIOF"
"R0QgZFbRnU0frj34fiVmgYiLuZSAmIbs8ZxiHPdp1oD4tUpvsFci4QJtYNjNnGU2"
"WPH6rvChGl1IRKrxMtqLielsvajUjyrgOC6NmymYMvZNER3htFEtL1eQbCyTfDmt"
"YyQ1Wt4Ot12lxf0wVIR5mcGN7XCXJRHOFHSf1gzXWabRSvmt1nrl7sW6cjxljuuQ"
"awIDAQAB";
[[nodiscard]]
bool PatchSolution2::CheckKey(const RSACipher& Cipher) const noexcept {
auto szPublicKey = Cipher.ExportKeyString<RSAKeyType::PublicKey, RSAKeyFormat::PEM>();
for (auto pos = szPublicKey.find("-----BEGIN PUBLIC KEY-----"); pos != std::string::npos; pos = szPublicKey.find("-----BEGIN PUBLIC KEY-----", pos)) {
szPublicKey.erase(pos, literal_length("-----BEGIN PUBLIC KEY-----"));
}
for (auto pos = szPublicKey.find("-----END PUBLIC KEY-----"); pos != std::string::npos; pos = szPublicKey.find("-----END PUBLIC KEY-----", pos)) {
szPublicKey.erase(pos, literal_length("-----END PUBLIC KEY-----"));
}
for (auto pos = szPublicKey.find("\n"); pos != std::string::npos; pos = szPublicKey.find("\n", pos)) {
szPublicKey.erase(pos, literal_length("\n"));
}
return szPublicKey.length() == literal_length(KeywordMeta);
}
void PatchSolution2::MakePatch(const RSACipher& Cipher) const {
for (size_t i = 0; i < _countof(_PatchOffset); ++i) {
if (_PatchOffset[i] == InvalidOffset) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("PatchSolution2 has not been ready yet."));
}
}
auto pbImage = _Image.ImageBase<uint8_t*>();
auto szPublicKey = Cipher.ExportKeyString<RSAKeyType::PublicKey, RSAKeyFormat::PEM>();
for (auto pos = szPublicKey.find("-----BEGIN PUBLIC KEY-----"); pos != std::string::npos; pos = szPublicKey.find("-----BEGIN PUBLIC KEY-----", pos)) {
szPublicKey.erase(pos, literal_length("-----BEGIN PUBLIC KEY-----"));
}
for (auto pos = szPublicKey.find("-----END PUBLIC KEY-----"); pos != std::string::npos; pos = szPublicKey.find("-----END PUBLIC KEY-----", pos)) {
szPublicKey.erase(pos, literal_length("-----END PUBLIC KEY-----"));
}
for (auto pos = szPublicKey.find("\n"); pos != std::string::npos; pos = szPublicKey.find("\n", pos)) {
szPublicKey.erase(pos, literal_length("\n"));
}
if (szPublicKey.length() != literal_length(KeywordMeta)) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("szPublicKey.length() != literal_length(KeywordMeta)"));
}
_putts(TEXT("*******************************************************"));
_putts(TEXT("* PatchSolution2 *"));
_putts(TEXT("*******************************************************"));
for (size_t i = 0; i < _countof(_PatchOffset); i += 2) {
static_assert(_countof(_PatchOffset) % 2 == 0);
LOG_HINT(0, "+0x%.8zx: %.2x %.2x %.2x -> %.2x %.2x %.2x | +0x%.8zx: %.2x %.2x %.2x -> %.2x %.2x %.2x",
_PatchOffset[i],
pbImage[_PatchOffset[i]],
pbImage[_PatchOffset[i] + 1],
pbImage[_PatchOffset[i] + 2],
pbImage[_PatchOffset[i]],
pbImage[_PatchOffset[i] + 1],
szPublicKey[i],
_PatchOffset[i + 1],
pbImage[_PatchOffset[i + 1]],
pbImage[_PatchOffset[i + 1] + 1],
pbImage[_PatchOffset[i + 1] + 2],
pbImage[_PatchOffset[i + 1]],
pbImage[_PatchOffset[i + 1] + 1],
szPublicKey[i + 1]
);
pbImage[_PatchOffset[i] + 2] = szPublicKey[i];
pbImage[_PatchOffset[i + 1] + 2] = szPublicKey[i + 1];
}
}
}
+517
View File
@@ -0,0 +1,517 @@
#include "PatchSolutions.hpp"
#include <vector>
#include <algorithm>
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\PatchSolution2-i386.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
/*
Keyword[0x188][5] is generated by the following python script:
-----Begin Python3 Script-----
meta = \
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw1dqF3SkCaAAmMzs889I" \
"qdW9M2dIdh3jG9yPcmLnmJiGpBF4E9VHSMGe8oPAy2kJDmdNt4BcEygvssEfginv" \
"a5t5jm352UAoDosUJkTXGQhpAWMF4fBmBpO3EedG62rOsqMBgmSdAyxCSPBRJIOF" \
"R0QgZFbRnU0frj34fiVmgYiLuZSAmIbs8ZxiHPdp1oD4tUpvsFci4QJtYNjNnGU2" \
"WPH6rvChGl1IRKrxMtqLielsvajUjyrgOC6NmymYMvZNER3htFEtL1eQbCyTfDmt" \
"YyQ1Wt4Ot12lxf0wVIR5mcGN7XCXJRHOFHSf1gzXWabRSvmt1nrl7sW6cjxljuuQ" \
"awIDAQAB"
print('const uint8_t PatchSolution2::Keywords[0x188][5] = {')
for i in range(0, len(meta)):
if i % 3 == 0:
i1 = '0x83, 0xf2, 0x%.2x' % ord(meta[i]) # asm('xor edx, meta[i]')
i2 = '0x88, 0x15' # asm_prefix('mov byte ptr ds:xxxxxxxx, dl')
elif i % 3 == 1:
i1 = '0x83, 0xf0, 0x%.2x' % ord(meta[i]) # asm('xor eax, meta[i]')
i2 = '0xa2' # asm_prefix('mov byte ptr ds:xxxxxxxx, al')
else:
i1 = '0x83, 0xf1, 0x%.2x' % ord(meta[i]) # asm('xor ecx, meta[i]')
i2 = '0x88, 0x0d' # asm_prefix('mov byte ptr ds:xxxxxxxx, cl')
print(' { %s, %s }' % (i1, i2), end=',\n' if i != len(meta) - 1 else '\n')
print('};')
-----End Python3 Script-----
*/
const uint8_t PatchSolution2::Keyword[0x188][5] = {
{ 0x83, 0xf2, 0x4d, 0x88, 0x15 },
{ 0x83, 0xf0, 0x49, 0xa2 },
{ 0x83, 0xf1, 0x49, 0x88, 0x0d },
{ 0x83, 0xf2, 0x42, 0x88, 0x15 },
{ 0x83, 0xf0, 0x49, 0xa2 },
{ 0x83, 0xf1, 0x6a, 0x88, 0x0d },
{ 0x83, 0xf2, 0x41, 0x88, 0x15 },
{ 0x83, 0xf0, 0x4e, 0xa2 },
{ 0x83, 0xf1, 0x42, 0x88, 0x0d },
{ 0x83, 0xf2, 0x67, 0x88, 0x15 },
{ 0x83, 0xf0, 0x6b, 0xa2 },
{ 0x83, 0xf1, 0x71, 0x88, 0x0d },
{ 0x83, 0xf2, 0x68, 0x88, 0x15 },
{ 0x83, 0xf0, 0x6b, 0xa2 },
{ 0x83, 0xf1, 0x69, 0x88, 0x0d },
{ 0x83, 0xf2, 0x47, 0x88, 0x15 },
{ 0x83, 0xf0, 0x39, 0xa2 },
{ 0x83, 0xf1, 0x77, 0x88, 0x0d },
{ 0x83, 0xf2, 0x30, 0x88, 0x15 },
{ 0x83, 0xf0, 0x42, 0xa2 },
{ 0x83, 0xf1, 0x41, 0x88, 0x0d },
{ 0x83, 0xf2, 0x51, 0x88, 0x15 },
{ 0x83, 0xf0, 0x45, 0xa2 },
{ 0x83, 0xf1, 0x46, 0x88, 0x0d },
{ 0x83, 0xf2, 0x41, 0x88, 0x15 },
{ 0x83, 0xf0, 0x41, 0xa2 },
{ 0x83, 0xf1, 0x4f, 0x88, 0x0d },
{ 0x83, 0xf2, 0x43, 0x88, 0x15 },
{ 0x83, 0xf0, 0x41, 0xa2 },
{ 0x83, 0xf1, 0x51, 0x88, 0x0d },
{ 0x83, 0xf2, 0x38, 0x88, 0x15 },
{ 0x83, 0xf0, 0x41, 0xa2 },
{ 0x83, 0xf1, 0x4d, 0x88, 0x0d },
{ 0x83, 0xf2, 0x49, 0x88, 0x15 },
{ 0x83, 0xf0, 0x49, 0xa2 },
{ 0x83, 0xf1, 0x42, 0x88, 0x0d },
{ 0x83, 0xf2, 0x43, 0x88, 0x15 },
{ 0x83, 0xf0, 0x67, 0xa2 },
{ 0x83, 0xf1, 0x4b, 0x88, 0x0d },
{ 0x83, 0xf2, 0x43, 0x88, 0x15 },
{ 0x83, 0xf0, 0x41, 0xa2 },
{ 0x83, 0xf1, 0x51, 0x88, 0x0d },
{ 0x83, 0xf2, 0x45, 0x88, 0x15 },
{ 0x83, 0xf0, 0x41, 0xa2 },
{ 0x83, 0xf1, 0x77, 0x88, 0x0d },
{ 0x83, 0xf2, 0x31, 0x88, 0x15 },
{ 0x83, 0xf0, 0x64, 0xa2 },
{ 0x83, 0xf1, 0x71, 0x88, 0x0d },
{ 0x83, 0xf2, 0x46, 0x88, 0x15 },
{ 0x83, 0xf0, 0x33, 0xa2 },
{ 0x83, 0xf1, 0x53, 0x88, 0x0d },
{ 0x83, 0xf2, 0x6b, 0x88, 0x15 },
{ 0x83, 0xf0, 0x43, 0xa2 },
{ 0x83, 0xf1, 0x61, 0x88, 0x0d },
{ 0x83, 0xf2, 0x41, 0x88, 0x15 },
{ 0x83, 0xf0, 0x41, 0xa2 },
{ 0x83, 0xf1, 0x6d, 0x88, 0x0d },
{ 0x83, 0xf2, 0x4d, 0x88, 0x15 },
{ 0x83, 0xf0, 0x7a, 0xa2 },
{ 0x83, 0xf1, 0x73, 0x88, 0x0d },
{ 0x83, 0xf2, 0x38, 0x88, 0x15 },
{ 0x83, 0xf0, 0x38, 0xa2 },
{ 0x83, 0xf1, 0x39, 0x88, 0x0d },
{ 0x83, 0xf2, 0x49, 0x88, 0x15 },
{ 0x83, 0xf0, 0x71, 0xa2 },
{ 0x83, 0xf1, 0x64, 0x88, 0x0d },
{ 0x83, 0xf2, 0x57, 0x88, 0x15 },
{ 0x83, 0xf0, 0x39, 0xa2 },
{ 0x83, 0xf1, 0x4d, 0x88, 0x0d },
{ 0x83, 0xf2, 0x32, 0x88, 0x15 },
{ 0x83, 0xf0, 0x64, 0xa2 },
{ 0x83, 0xf1, 0x49, 0x88, 0x0d },
{ 0x83, 0xf2, 0x64, 0x88, 0x15 },
{ 0x83, 0xf0, 0x68, 0xa2 },
{ 0x83, 0xf1, 0x33, 0x88, 0x0d },
{ 0x83, 0xf2, 0x6a, 0x88, 0x15 },
{ 0x83, 0xf0, 0x47, 0xa2 },
{ 0x83, 0xf1, 0x39, 0x88, 0x0d },
{ 0x83, 0xf2, 0x79, 0x88, 0x15 },
{ 0x83, 0xf0, 0x50, 0xa2 },
{ 0x83, 0xf1, 0x63, 0x88, 0x0d },
{ 0x83, 0xf2, 0x6d, 0x88, 0x15 },
{ 0x83, 0xf0, 0x4c, 0xa2 },
{ 0x83, 0xf1, 0x6e, 0x88, 0x0d },
{ 0x83, 0xf2, 0x6d, 0x88, 0x15 },
{ 0x83, 0xf0, 0x4a, 0xa2 },
{ 0x83, 0xf1, 0x69, 0x88, 0x0d },
{ 0x83, 0xf2, 0x47, 0x88, 0x15 },
{ 0x83, 0xf0, 0x70, 0xa2 },
{ 0x83, 0xf1, 0x42, 0x88, 0x0d },
{ 0x83, 0xf2, 0x46, 0x88, 0x15 },
{ 0x83, 0xf0, 0x34, 0xa2 },
{ 0x83, 0xf1, 0x45, 0x88, 0x0d },
{ 0x83, 0xf2, 0x39, 0x88, 0x15 },
{ 0x83, 0xf0, 0x56, 0xa2 },
{ 0x83, 0xf1, 0x48, 0x88, 0x0d },
{ 0x83, 0xf2, 0x53, 0x88, 0x15 },
{ 0x83, 0xf0, 0x4d, 0xa2 },
{ 0x83, 0xf1, 0x47, 0x88, 0x0d },
{ 0x83, 0xf2, 0x65, 0x88, 0x15 },
{ 0x83, 0xf0, 0x38, 0xa2 },
{ 0x83, 0xf1, 0x6f, 0x88, 0x0d },
{ 0x83, 0xf2, 0x50, 0x88, 0x15 },
{ 0x83, 0xf0, 0x41, 0xa2 },
{ 0x83, 0xf1, 0x79, 0x88, 0x0d },
{ 0x83, 0xf2, 0x32, 0x88, 0x15 },
{ 0x83, 0xf0, 0x6b, 0xa2 },
{ 0x83, 0xf1, 0x4a, 0x88, 0x0d },
{ 0x83, 0xf2, 0x44, 0x88, 0x15 },
{ 0x83, 0xf0, 0x6d, 0xa2 },
{ 0x83, 0xf1, 0x64, 0x88, 0x0d },
{ 0x83, 0xf2, 0x4e, 0x88, 0x15 },
{ 0x83, 0xf0, 0x74, 0xa2 },
{ 0x83, 0xf1, 0x34, 0x88, 0x0d },
{ 0x83, 0xf2, 0x42, 0x88, 0x15 },
{ 0x83, 0xf0, 0x63, 0xa2 },
{ 0x83, 0xf1, 0x45, 0x88, 0x0d },
{ 0x83, 0xf2, 0x79, 0x88, 0x15 },
{ 0x83, 0xf0, 0x67, 0xa2 },
{ 0x83, 0xf1, 0x76, 0x88, 0x0d },
{ 0x83, 0xf2, 0x73, 0x88, 0x15 },
{ 0x83, 0xf0, 0x73, 0xa2 },
{ 0x83, 0xf1, 0x45, 0x88, 0x0d },
{ 0x83, 0xf2, 0x66, 0x88, 0x15 },
{ 0x83, 0xf0, 0x67, 0xa2 },
{ 0x83, 0xf1, 0x69, 0x88, 0x0d },
{ 0x83, 0xf2, 0x6e, 0x88, 0x15 },
{ 0x83, 0xf0, 0x76, 0xa2 },
{ 0x83, 0xf1, 0x61, 0x88, 0x0d },
{ 0x83, 0xf2, 0x35, 0x88, 0x15 },
{ 0x83, 0xf0, 0x74, 0xa2 },
{ 0x83, 0xf1, 0x35, 0x88, 0x0d },
{ 0x83, 0xf2, 0x6a, 0x88, 0x15 },
{ 0x83, 0xf0, 0x6d, 0xa2 },
{ 0x83, 0xf1, 0x33, 0x88, 0x0d },
{ 0x83, 0xf2, 0x35, 0x88, 0x15 },
{ 0x83, 0xf0, 0x32, 0xa2 },
{ 0x83, 0xf1, 0x55, 0x88, 0x0d },
{ 0x83, 0xf2, 0x41, 0x88, 0x15 },
{ 0x83, 0xf0, 0x6f, 0xa2 },
{ 0x83, 0xf1, 0x44, 0x88, 0x0d },
{ 0x83, 0xf2, 0x6f, 0x88, 0x15 },
{ 0x83, 0xf0, 0x73, 0xa2 },
{ 0x83, 0xf1, 0x55, 0x88, 0x0d },
{ 0x83, 0xf2, 0x4a, 0x88, 0x15 },
{ 0x83, 0xf0, 0x6b, 0xa2 },
{ 0x83, 0xf1, 0x54, 0x88, 0x0d },
{ 0x83, 0xf2, 0x58, 0x88, 0x15 },
{ 0x83, 0xf0, 0x47, 0xa2 },
{ 0x83, 0xf1, 0x51, 0x88, 0x0d },
{ 0x83, 0xf2, 0x68, 0x88, 0x15 },
{ 0x83, 0xf0, 0x70, 0xa2 },
{ 0x83, 0xf1, 0x41, 0x88, 0x0d },
{ 0x83, 0xf2, 0x57, 0x88, 0x15 },
{ 0x83, 0xf0, 0x4d, 0xa2 },
{ 0x83, 0xf1, 0x46, 0x88, 0x0d },
{ 0x83, 0xf2, 0x34, 0x88, 0x15 },
{ 0x83, 0xf0, 0x66, 0xa2 },
{ 0x83, 0xf1, 0x42, 0x88, 0x0d },
{ 0x83, 0xf2, 0x6d, 0x88, 0x15 },
{ 0x83, 0xf0, 0x42, 0xa2 },
{ 0x83, 0xf1, 0x70, 0x88, 0x0d },
{ 0x83, 0xf2, 0x4f, 0x88, 0x15 },
{ 0x83, 0xf0, 0x33, 0xa2 },
{ 0x83, 0xf1, 0x45, 0x88, 0x0d },
{ 0x83, 0xf2, 0x65, 0x88, 0x15 },
{ 0x83, 0xf0, 0x64, 0xa2 },
{ 0x83, 0xf1, 0x47, 0x88, 0x0d },
{ 0x83, 0xf2, 0x36, 0x88, 0x15 },
{ 0x83, 0xf0, 0x32, 0xa2 },
{ 0x83, 0xf1, 0x72, 0x88, 0x0d },
{ 0x83, 0xf2, 0x4f, 0x88, 0x15 },
{ 0x83, 0xf0, 0x73, 0xa2 },
{ 0x83, 0xf1, 0x71, 0x88, 0x0d },
{ 0x83, 0xf2, 0x4d, 0x88, 0x15 },
{ 0x83, 0xf0, 0x42, 0xa2 },
{ 0x83, 0xf1, 0x67, 0x88, 0x0d },
{ 0x83, 0xf2, 0x6d, 0x88, 0x15 },
{ 0x83, 0xf0, 0x53, 0xa2 },
{ 0x83, 0xf1, 0x64, 0x88, 0x0d },
{ 0x83, 0xf2, 0x41, 0x88, 0x15 },
{ 0x83, 0xf0, 0x79, 0xa2 },
{ 0x83, 0xf1, 0x78, 0x88, 0x0d },
{ 0x83, 0xf2, 0x43, 0x88, 0x15 },
{ 0x83, 0xf0, 0x53, 0xa2 },
{ 0x83, 0xf1, 0x50, 0x88, 0x0d },
{ 0x83, 0xf2, 0x42, 0x88, 0x15 },
{ 0x83, 0xf0, 0x52, 0xa2 },
{ 0x83, 0xf1, 0x4a, 0x88, 0x0d },
{ 0x83, 0xf2, 0x49, 0x88, 0x15 },
{ 0x83, 0xf0, 0x4f, 0xa2 },
{ 0x83, 0xf1, 0x46, 0x88, 0x0d },
{ 0x83, 0xf2, 0x52, 0x88, 0x15 },
{ 0x83, 0xf0, 0x30, 0xa2 },
{ 0x83, 0xf1, 0x51, 0x88, 0x0d },
{ 0x83, 0xf2, 0x67, 0x88, 0x15 },
{ 0x83, 0xf0, 0x5a, 0xa2 },
{ 0x83, 0xf1, 0x46, 0x88, 0x0d },
{ 0x83, 0xf2, 0x62, 0x88, 0x15 },
{ 0x83, 0xf0, 0x52, 0xa2 },
{ 0x83, 0xf1, 0x6e, 0x88, 0x0d },
{ 0x83, 0xf2, 0x55, 0x88, 0x15 },
{ 0x83, 0xf0, 0x30, 0xa2 },
{ 0x83, 0xf1, 0x66, 0x88, 0x0d },
{ 0x83, 0xf2, 0x72, 0x88, 0x15 },
{ 0x83, 0xf0, 0x6a, 0xa2 },
{ 0x83, 0xf1, 0x33, 0x88, 0x0d },
{ 0x83, 0xf2, 0x34, 0x88, 0x15 },
{ 0x83, 0xf0, 0x66, 0xa2 },
{ 0x83, 0xf1, 0x69, 0x88, 0x0d },
{ 0x83, 0xf2, 0x56, 0x88, 0x15 },
{ 0x83, 0xf0, 0x6d, 0xa2 },
{ 0x83, 0xf1, 0x67, 0x88, 0x0d },
{ 0x83, 0xf2, 0x59, 0x88, 0x15 },
{ 0x83, 0xf0, 0x69, 0xa2 },
{ 0x83, 0xf1, 0x4c, 0x88, 0x0d },
{ 0x83, 0xf2, 0x75, 0x88, 0x15 },
{ 0x83, 0xf0, 0x5a, 0xa2 },
{ 0x83, 0xf1, 0x53, 0x88, 0x0d },
{ 0x83, 0xf2, 0x41, 0x88, 0x15 },
{ 0x83, 0xf0, 0x6d, 0xa2 },
{ 0x83, 0xf1, 0x49, 0x88, 0x0d },
{ 0x83, 0xf2, 0x62, 0x88, 0x15 },
{ 0x83, 0xf0, 0x73, 0xa2 },
{ 0x83, 0xf1, 0x38, 0x88, 0x0d },
{ 0x83, 0xf2, 0x5a, 0x88, 0x15 },
{ 0x83, 0xf0, 0x78, 0xa2 },
{ 0x83, 0xf1, 0x69, 0x88, 0x0d },
{ 0x83, 0xf2, 0x48, 0x88, 0x15 },
{ 0x83, 0xf0, 0x50, 0xa2 },
{ 0x83, 0xf1, 0x64, 0x88, 0x0d },
{ 0x83, 0xf2, 0x70, 0x88, 0x15 },
{ 0x83, 0xf0, 0x31, 0xa2 },
{ 0x83, 0xf1, 0x6f, 0x88, 0x0d },
{ 0x83, 0xf2, 0x44, 0x88, 0x15 },
{ 0x83, 0xf0, 0x34, 0xa2 },
{ 0x83, 0xf1, 0x74, 0x88, 0x0d },
{ 0x83, 0xf2, 0x55, 0x88, 0x15 },
{ 0x83, 0xf0, 0x70, 0xa2 },
{ 0x83, 0xf1, 0x76, 0x88, 0x0d },
{ 0x83, 0xf2, 0x73, 0x88, 0x15 },
{ 0x83, 0xf0, 0x46, 0xa2 },
{ 0x83, 0xf1, 0x63, 0x88, 0x0d },
{ 0x83, 0xf2, 0x69, 0x88, 0x15 },
{ 0x83, 0xf0, 0x34, 0xa2 },
{ 0x83, 0xf1, 0x51, 0x88, 0x0d },
{ 0x83, 0xf2, 0x4a, 0x88, 0x15 },
{ 0x83, 0xf0, 0x74, 0xa2 },
{ 0x83, 0xf1, 0x59, 0x88, 0x0d },
{ 0x83, 0xf2, 0x4e, 0x88, 0x15 },
{ 0x83, 0xf0, 0x6a, 0xa2 },
{ 0x83, 0xf1, 0x4e, 0x88, 0x0d },
{ 0x83, 0xf2, 0x6e, 0x88, 0x15 },
{ 0x83, 0xf0, 0x47, 0xa2 },
{ 0x83, 0xf1, 0x55, 0x88, 0x0d },
{ 0x83, 0xf2, 0x32, 0x88, 0x15 },
{ 0x83, 0xf0, 0x57, 0xa2 },
{ 0x83, 0xf1, 0x50, 0x88, 0x0d },
{ 0x83, 0xf2, 0x48, 0x88, 0x15 },
{ 0x83, 0xf0, 0x36, 0xa2 },
{ 0x83, 0xf1, 0x72, 0x88, 0x0d },
{ 0x83, 0xf2, 0x76, 0x88, 0x15 },
{ 0x83, 0xf0, 0x43, 0xa2 },
{ 0x83, 0xf1, 0x68, 0x88, 0x0d },
{ 0x83, 0xf2, 0x47, 0x88, 0x15 },
{ 0x83, 0xf0, 0x6c, 0xa2 },
{ 0x83, 0xf1, 0x31, 0x88, 0x0d },
{ 0x83, 0xf2, 0x49, 0x88, 0x15 },
{ 0x83, 0xf0, 0x52, 0xa2 },
{ 0x83, 0xf1, 0x4b, 0x88, 0x0d },
{ 0x83, 0xf2, 0x72, 0x88, 0x15 },
{ 0x83, 0xf0, 0x78, 0xa2 },
{ 0x83, 0xf1, 0x4d, 0x88, 0x0d },
{ 0x83, 0xf2, 0x74, 0x88, 0x15 },
{ 0x83, 0xf0, 0x71, 0xa2 },
{ 0x83, 0xf1, 0x4c, 0x88, 0x0d },
{ 0x83, 0xf2, 0x69, 0x88, 0x15 },
{ 0x83, 0xf0, 0x65, 0xa2 },
{ 0x83, 0xf1, 0x6c, 0x88, 0x0d },
{ 0x83, 0xf2, 0x73, 0x88, 0x15 },
{ 0x83, 0xf0, 0x76, 0xa2 },
{ 0x83, 0xf1, 0x61, 0x88, 0x0d },
{ 0x83, 0xf2, 0x6a, 0x88, 0x15 },
{ 0x83, 0xf0, 0x55, 0xa2 },
{ 0x83, 0xf1, 0x6a, 0x88, 0x0d },
{ 0x83, 0xf2, 0x79, 0x88, 0x15 },
{ 0x83, 0xf0, 0x72, 0xa2 },
{ 0x83, 0xf1, 0x67, 0x88, 0x0d },
{ 0x83, 0xf2, 0x4f, 0x88, 0x15 },
{ 0x83, 0xf0, 0x43, 0xa2 },
{ 0x83, 0xf1, 0x36, 0x88, 0x0d },
{ 0x83, 0xf2, 0x4e, 0x88, 0x15 },
{ 0x83, 0xf0, 0x6d, 0xa2 },
{ 0x83, 0xf1, 0x79, 0x88, 0x0d },
{ 0x83, 0xf2, 0x6d, 0x88, 0x15 },
{ 0x83, 0xf0, 0x59, 0xa2 },
{ 0x83, 0xf1, 0x4d, 0x88, 0x0d },
{ 0x83, 0xf2, 0x76, 0x88, 0x15 },
{ 0x83, 0xf0, 0x5a, 0xa2 },
{ 0x83, 0xf1, 0x4e, 0x88, 0x0d },
{ 0x83, 0xf2, 0x45, 0x88, 0x15 },
{ 0x83, 0xf0, 0x52, 0xa2 },
{ 0x83, 0xf1, 0x33, 0x88, 0x0d },
{ 0x83, 0xf2, 0x68, 0x88, 0x15 },
{ 0x83, 0xf0, 0x74, 0xa2 },
{ 0x83, 0xf1, 0x46, 0x88, 0x0d },
{ 0x83, 0xf2, 0x45, 0x88, 0x15 },
{ 0x83, 0xf0, 0x74, 0xa2 },
{ 0x83, 0xf1, 0x4c, 0x88, 0x0d },
{ 0x83, 0xf2, 0x31, 0x88, 0x15 },
{ 0x83, 0xf0, 0x65, 0xa2 },
{ 0x83, 0xf1, 0x51, 0x88, 0x0d },
{ 0x83, 0xf2, 0x62, 0x88, 0x15 },
{ 0x83, 0xf0, 0x43, 0xa2 },
{ 0x83, 0xf1, 0x79, 0x88, 0x0d },
{ 0x83, 0xf2, 0x54, 0x88, 0x15 },
{ 0x83, 0xf0, 0x66, 0xa2 },
{ 0x83, 0xf1, 0x44, 0x88, 0x0d },
{ 0x83, 0xf2, 0x6d, 0x88, 0x15 },
{ 0x83, 0xf0, 0x74, 0xa2 },
{ 0x83, 0xf1, 0x59, 0x88, 0x0d },
{ 0x83, 0xf2, 0x79, 0x88, 0x15 },
{ 0x83, 0xf0, 0x51, 0xa2 },
{ 0x83, 0xf1, 0x31, 0x88, 0x0d },
{ 0x83, 0xf2, 0x57, 0x88, 0x15 },
{ 0x83, 0xf0, 0x74, 0xa2 },
{ 0x83, 0xf1, 0x34, 0x88, 0x0d },
{ 0x83, 0xf2, 0x4f, 0x88, 0x15 },
{ 0x83, 0xf0, 0x74, 0xa2 },
{ 0x83, 0xf1, 0x31, 0x88, 0x0d },
{ 0x83, 0xf2, 0x32, 0x88, 0x15 },
{ 0x83, 0xf0, 0x6c, 0xa2 },
{ 0x83, 0xf1, 0x78, 0x88, 0x0d },
{ 0x83, 0xf2, 0x66, 0x88, 0x15 },
{ 0x83, 0xf0, 0x30, 0xa2 },
{ 0x83, 0xf1, 0x77, 0x88, 0x0d },
{ 0x83, 0xf2, 0x56, 0x88, 0x15 },
{ 0x83, 0xf0, 0x49, 0xa2 },
{ 0x83, 0xf1, 0x52, 0x88, 0x0d },
{ 0x83, 0xf2, 0x35, 0x88, 0x15 },
{ 0x83, 0xf0, 0x6d, 0xa2 },
{ 0x83, 0xf1, 0x63, 0x88, 0x0d },
{ 0x83, 0xf2, 0x47, 0x88, 0x15 },
{ 0x83, 0xf0, 0x4e, 0xa2 },
{ 0x83, 0xf1, 0x37, 0x88, 0x0d },
{ 0x83, 0xf2, 0x58, 0x88, 0x15 },
{ 0x83, 0xf0, 0x43, 0xa2 },
{ 0x83, 0xf1, 0x58, 0x88, 0x0d },
{ 0x83, 0xf2, 0x4a, 0x88, 0x15 },
{ 0x83, 0xf0, 0x52, 0xa2 },
{ 0x83, 0xf1, 0x48, 0x88, 0x0d },
{ 0x83, 0xf2, 0x4f, 0x88, 0x15 },
{ 0x83, 0xf0, 0x46, 0xa2 },
{ 0x83, 0xf1, 0x48, 0x88, 0x0d },
{ 0x83, 0xf2, 0x53, 0x88, 0x15 },
{ 0x83, 0xf0, 0x66, 0xa2 },
{ 0x83, 0xf1, 0x31, 0x88, 0x0d },
{ 0x83, 0xf2, 0x67, 0x88, 0x15 },
{ 0x83, 0xf0, 0x7a, 0xa2 },
{ 0x83, 0xf1, 0x58, 0x88, 0x0d },
{ 0x83, 0xf2, 0x57, 0x88, 0x15 },
{ 0x83, 0xf0, 0x61, 0xa2 },
{ 0x83, 0xf1, 0x62, 0x88, 0x0d },
{ 0x83, 0xf2, 0x52, 0x88, 0x15 },
{ 0x83, 0xf0, 0x53, 0xa2 },
{ 0x83, 0xf1, 0x76, 0x88, 0x0d },
{ 0x83, 0xf2, 0x6d, 0x88, 0x15 },
{ 0x83, 0xf0, 0x74, 0xa2 },
{ 0x83, 0xf1, 0x31, 0x88, 0x0d },
{ 0x83, 0xf2, 0x6e, 0x88, 0x15 },
{ 0x83, 0xf0, 0x72, 0xa2 },
{ 0x83, 0xf1, 0x6c, 0x88, 0x0d },
{ 0x83, 0xf2, 0x37, 0x88, 0x15 },
{ 0x83, 0xf0, 0x73, 0xa2 },
{ 0x83, 0xf1, 0x57, 0x88, 0x0d },
{ 0x83, 0xf2, 0x36, 0x88, 0x15 },
{ 0x83, 0xf0, 0x63, 0xa2 },
{ 0x83, 0xf1, 0x6a, 0x88, 0x0d },
{ 0x83, 0xf2, 0x78, 0x88, 0x15 },
{ 0x83, 0xf0, 0x6c, 0xa2 },
{ 0x83, 0xf1, 0x6a, 0x88, 0x0d },
{ 0x83, 0xf2, 0x75, 0x88, 0x15 },
{ 0x83, 0xf0, 0x75, 0xa2 },
{ 0x83, 0xf1, 0x51, 0x88, 0x0d },
{ 0x83, 0xf2, 0x61, 0x88, 0x15 },
{ 0x83, 0xf0, 0x77, 0xa2 },
{ 0x83, 0xf1, 0x49, 0x88, 0x0d },
{ 0x83, 0xf2, 0x44, 0x88, 0x15 },
{ 0x83, 0xf0, 0x41, 0xa2 },
{ 0x83, 0xf1, 0x51, 0x88, 0x0d },
{ 0x83, 0xf2, 0x41, 0x88, 0x15 },
{ 0x83, 0xf0, 0x42, 0xa2 }
};
[[nodiscard]]
bool PatchSolution2::FindPatchOffset() noexcept {
try {
auto SectionHeader_text = _Image.ImageSectionHeaderByName(".text");
auto SectionView_text = _Image.ImageSectionView<const uint8_t*>(SectionHeader_text);
const uint8_t* lpPatch[_countof(_PatchOffset)] = {};
std::vector<size_t> Hints;
DWORD PossibleRangeStart = 0xffffffff;
DWORD PossibleRangeEnd;
for (DWORD i = 0; i < SectionHeader_text->SizeOfRawData; ++i) {
if (memcmp(SectionView_text + i, Keyword[0], sizeof(Keyword[0])) == 0) {
Hints.emplace_back(
*reinterpret_cast<const uint32_t*>(SectionView_text + i + sizeof(Keyword[0]))
);
if (i < PossibleRangeStart) {
PossibleRangeStart = i;
}
}
}
PossibleRangeStart -= 0x1000;
PossibleRangeEnd = PossibleRangeStart + 0x100000;
// Keywords[0] should occur 3 times.
if (Hints.size() != 3) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Hints.size() != 3"));
}
std::sort(Hints.begin(), Hints.end());
if (Hints.back() - Hints.front() != 0x127382BE - 0x12738210) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Hints.back() - Hints.front() != 0x127382BE - 0x12738210"));
}
for (size_t i = 0; i < _countof(_PatchOffset); ++i) {
uint8_t CurrentKeyword[9];
size_t CurrentKeywordSize = i % 3 == 1 ? 4 : 5;
memcpy(CurrentKeyword, Keyword[i], CurrentKeywordSize);
*reinterpret_cast<uint32_t*>(CurrentKeyword + CurrentKeywordSize) = Hints[0] + i;
CurrentKeywordSize += sizeof(uint32_t);
for (DWORD j = PossibleRangeStart; j < PossibleRangeEnd; ++j) {
if (memcmp(SectionView_text + j, CurrentKeyword, CurrentKeywordSize) == 0) {
lpPatch[i] = SectionView_text + j;
break;
}
}
// if not found, refuse to patch
if (lpPatch[i] == nullptr) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("A patch point is missing."));
}
}
for (size_t i = 0; i < _countof(_PatchOffset); ++i) {
_PatchOffset[i] = _Image.PointerToFileOffset(lpPatch[i]);
}
LOG_SUCCESS(0, "PatchSolution2 ...... Ready to apply");
for (size_t i = 0; i < _countof(_PatchOffset); i += 4) {
static_assert(sizeof(_countof(_PatchOffset)) % 4 == 0);
LOG_HINT(4, "Patch offset[%zu ... %zu] = 0x%.8zx, 0x%.8zx, 0x%.8zx, 0x%.8zx", i, i + 3, _PatchOffset[i], _PatchOffset[i + 1], _PatchOffset[i + 2], _PatchOffset[i + 3]);
}
return true;
} catch (nkg::Exception&) {
for (size_t i = 0; i < _countof(_PatchOffset); ++i) {
_PatchOffset[i] = InvalidOffset;
}
LOG_FAILURE(0, "PatchSolution2 ...... Omitted");
return false;
}
}
}
+231
View File
@@ -0,0 +1,231 @@
#include "PatchSolutions.hpp"
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\PatchSolution3-amd64.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
PatchSolution3::PatchSolution3(const ImageInterpreter& Image) :
_Image(Image),
_Engine(CS_ARCH_X86, CS_MODE_64),
_Patch{}
{
_Engine.Option(CS_OPT_DETAIL, CS_OPT_ON);
}
PatchSolution3::PatchSolution3(const ImageInterpreter* lpImage) :
_Image(*lpImage),
_Engine(CS_ARCH_X86, CS_MODE_64),
_Patch{}
{
_Engine.Option(CS_OPT_DETAIL, CS_OPT_ON);
}
[[nodiscard]]
bool PatchSolution3::CheckIfMatchPattern(const cs_insn* lpInsn) const noexcept {
// the instruction we're interested in has one of the following patterns:
// 1. mov PTR [MEM], IMM (IMM must consist of printable chars) // for IMM_DATA
// 2. lea REG, PTR [MEM] (MEM must point to a non-empty printable string) // for STRING_DATA
if (_stricmp(lpInsn->mnemonic, "mov") == 0) {
if (lpInsn->detail->x86.operands[1].type != X86_OP_IMM) {
return false;
}
auto pbImmValue = lpInsn->bytes + lpInsn->detail->x86.encoding.imm_offset;
auto cbImmValue = lpInsn->detail->x86.encoding.imm_size;
return IsPrintable(pbImmValue, cbImmValue);
} else if (_stricmp(lpInsn->mnemonic, "lea") == 0) {
// as far as I know, all strings are loaded by "lea REG, QWORD PTR [RIP + disp]"
// so operands[1] must look like "[RIP + disp]"
if (lpInsn->detail->x86.operands[1].mem.base != X86_REG_RIP) {
return false;
}
// scale must 1, otherwise pattern mismatches
if (lpInsn->detail->x86.operands[1].mem.scale != 1) {
return false;
}
auto StringRva = static_cast<uintptr_t>(
lpInsn->address + lpInsn->size + // Next RIP
lpInsn->detail->x86.operands[1].mem.disp
);
try {
auto StringPtr = _Image.RvaToPointer<const char*>(StringRva);
auto StringLength = strlen(StringPtr);
// StringPtr must have at least one char
// every char in StringPtr must be printable, otherwise pattern mismatches
return StringLength && IsPrintable(StringPtr, StringLength);
} catch (nkg::Exception&) {
// If not found, pattern mismatches
return false;
}
} else {
return false;
}
}
[[nodiscard]]
bool PatchSolution3::CheckIfFound(const cs_insn* lpInsn, size_t KeywordIdx) const noexcept {
// the instruction we're interested in has one of the following patterns:
// 1. mov PTR [MEM], IMM (IMM must consist of printable chars) // for IMM_DATA
// 2. lea REG, PTR [MEM] (MEM must point to a non-empty printable string) // for STRING_DATA
auto& op_count = lpInsn->detail->x86.op_count;
auto& operands = lpInsn->detail->x86.operands;
if (op_count != 2) {
return false;
}
if (Keyword[KeywordIdx].Type == IMM_DATA && operands[1].type == X86_OP_IMM) {
static_assert(sizeof(operands[1].imm) == sizeof(Keyword[KeywordIdx].Value));
return
operands[1].imm == *reinterpret_cast<const int64_t*>(Keyword[KeywordIdx].Value) &&
lpInsn->detail->x86.encoding.imm_size == Keyword[KeywordIdx].Size;
} else if (Keyword[KeywordIdx].Type == STRING_DATA && operands[1].type == X86_OP_MEM) {
auto StringRva = static_cast<uintptr_t>(
lpInsn->address + lpInsn->size + // Next RIP
operands[1].mem.disp
);
try {
auto StringPtr = _Image.RvaToPointer<const char*>(StringRva);
return
strncmp(StringPtr, reinterpret_cast<const char*>(Keyword[KeywordIdx].Value), Keyword[KeywordIdx].Size) == 0 &&
StringPtr[Keyword[KeywordIdx].Size] == '\x00';
} catch (nkg::Exception&) {
return false;
}
} else {
return false;
}
}
[[nodiscard]]
PatchSolution3::PatchInfo PatchSolution3::CreatePatchPoint(const void* lpOpcode, const cs_insn* lpInsn, size_t KeywordIdx) const noexcept {
PatchInfo NewPatch;
NewPatch.OpcodeRva = lpInsn->address;
NewPatch.lpOpcode = const_cast<void*>(lpOpcode);
if (lpInsn->detail->x86.operands[1].type == X86_OP_MEM) {
auto StringRva = static_cast<uintptr_t>(
lpInsn->address + lpInsn->size + // Next RIP
lpInsn->detail->x86.operands[1].mem.disp
);
NewPatch.lpOriginalString = _Image.RvaToPointer<char*>(StringRva);
if (Keyword[KeywordIdx].NotRecommendedToModify) {
NewPatch.lpPatch = address_offset(NewPatch.lpOpcode, lpInsn->detail->x86.encoding.disp_offset);
NewPatch.cbPatch = lpInsn->detail->x86.encoding.disp_size;
} else {
NewPatch.lpPatch = reinterpret_cast<uint8_t*>(NewPatch.lpOriginalString);
NewPatch.cbPatch = Keyword[KeywordIdx].Size;
}
} else { // X86_OP_IMM
NewPatch.lpPatch = address_offset(NewPatch.lpOpcode, lpInsn->detail->x86.encoding.imm_offset);
NewPatch.cbPatch = lpInsn->detail->x86.encoding.imm_size;
NewPatch.lpOriginalString = nullptr;
}
NewPatch.lpReplaceString = nullptr;
return NewPatch;
}
[[nodiscard]]
bool PatchSolution3::FindPatchOffset() noexcept {
try {
static const uint8_t HeaderOfTargetFunction[] = {
0x40, 0x55, // push rbp
0x48, 0x8D, 0xAC, 0x24, 0x70, 0xBC, 0xFF, 0xFF, // lea rbp, [rsp-4390h]
0xB8, 0x90, 0x44, 0x00, 0x00 // mov eax, 4490h
};
PatchInfo Patch[_countof(_Patch)] = {};
const uint8_t* lpTargetFunction = nullptr;
auto lptargetFunctionHint = _Image.SearchSection<const uint8_t*>(".text", [&lpTargetFunction](const uint8_t* p) {
__try {
if (*reinterpret_cast<const uint32_t*>(p) == 0x6b67424e) {
auto i = p - 0x250;
for (; i < p; ++i) {
if (memcmp(i, HeaderOfTargetFunction, sizeof(HeaderOfTargetFunction)) == 0) {
lpTargetFunction = i;
return true;
}
}
}
return false;
} __except (EXCEPTION_EXECUTE_HANDLER) {
return false;
}
});
size_t KeywordIndex = 0;
CapstoneDisassembler Disassembler = _Engine.CreateDisassembler();
Disassembler.SetContext(CapstoneContext{ lpTargetFunction, 0xcd03, _Image.PointerToRva(lpTargetFunction) });
while (Disassembler.Next()) {
auto lpInsn = Disassembler.GetInstruction();
if (lpInsn->mnemonic[0] == 'j' || lpInsn->mnemonic[0] == 'J') {
auto JumpedBranch = GetJumpedBranch(Disassembler.GetContext(), lpInsn);
if (_stricmp(lpInsn->mnemonic, "jmp") == 0) {
Disassembler.SetContext(JumpedBranch);
} else {
Disassembler.SetContext(SelectBranch(Disassembler.GetContext(), JumpedBranch, KeywordIndex));
}
} else if (_stricmp(lpInsn->mnemonic, "ret") == 0) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Reach end of function."));
} else {
if (CheckIfMatchPattern(lpInsn) == false) {
continue;
}
if (CheckIfFound(lpInsn, KeywordIndex) == false) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Missing a patch."));
}
Patch[KeywordIndex] = CreatePatchPoint(Disassembler.GetInstructionContext().lpMachineCode, lpInsn, KeywordIndex);
++KeywordIndex;
}
if (KeywordIndex == _countof(Patch)) {
break;
}
}
if (KeywordIndex != _countof(Patch)) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Some patches are not found."));
}
LOG_SUCCESS(0, "PatchSolution3 ...... Ready to apply");
for (size_t i = 0; i < _countof(Patch); ++i) {
_Patch[i] = Patch[i];
LOG_HINT(4, "[%3zu] Instruction RVA = 0x%.8llx, Patch Offset = +0x%.8zx", i, _Patch[i].OpcodeRva, address_delta(_Patch[i].lpPatch, _Image.ImageBase()));
}
return true;
} catch (nkg::Exception&) {
memset(_Patch, 0, sizeof(_Patch));
LOG_FAILURE(0, "PatchSolution3 ...... Omitted");
return false;
}
}
}
+424
View File
@@ -0,0 +1,424 @@
#include "PatchSolutions.hpp"
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\PatchSolution3-generic.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
const PatchSolution3::KeywordInfo PatchSolution3::Keyword[111] = {
{ { 0x4d, 0x49, 0x49 }, 3, STRING_DATA, false },
{ { 0x42, 0x49 }, 2, IMM_DATA, false },
{ { 0x6a }, 1, IMM_DATA, false },
{ { 0x41 }, 1, IMM_DATA, false },
{ { 0x4e, 0x42, 0x67, 0x6b }, 4, IMM_DATA, false },
{ { 0x71 }, 1, IMM_DATA, false },
{ { 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77 }, 6, STRING_DATA, false },
{ { 0x30 }, 1, STRING_DATA, true },
{ { 0x42 }, 1, IMM_DATA, false },
{ { 0x41 }, 1, IMM_DATA, false },
{ { 0x51, 0x45, 0x46, 0x41, 0x41, 0x4f, 0x43 }, 7, STRING_DATA, false },
{ { 0x41, 0x51, 0x38, 0x41, 0x4d, 0x49 }, 6, STRING_DATA, false },
{ { 0x49, 0x42 }, 2, STRING_DATA, false },
{ { 0x43, 0x67, 0x4b, 0x43 }, 4, IMM_DATA, false },
{ { 0x41, 0x51 }, 2, STRING_DATA, false },
{ { 0x45, 0x41, 0x77, 0x31 }, 4, IMM_DATA, false },
{ { 0x64, 0x71, 0x46, 0x33 }, 4, IMM_DATA, false },
{ { 0x53 }, 1, STRING_DATA, true },
{ { 0x6b, 0x43, 0x61, 0x41, 0x41, 0x6d }, 6, STRING_DATA, false },
{ { 0x4d, 0x7a, 0x73, 0x38 }, 4, IMM_DATA, false },
{ { 0x38, 0x39, 0x49, 0x71 }, 4, IMM_DATA, false },
{ { 0x64 }, 1, IMM_DATA, false },
{ { 0x57 }, 1, IMM_DATA, false },
{ { 0x39, 0x4d, 0x32, 0x64 }, 4, IMM_DATA, false },
{ { 0x49, 0x64, 0x68 }, 3, STRING_DATA, false },
{ { 0x33, 0x6a }, 2, IMM_DATA, false },
{ { 0x47, 0x39, 0x79, 0x50 }, 4, IMM_DATA, false },
{ { 0x63, 0x6d }, 2, IMM_DATA, false },
{ { 0x4c }, 1, IMM_DATA, false },
{ { 0x6e, 0x6d, 0x4a }, 3, STRING_DATA, false },
{ { 0x69, 0x47, 0x70, 0x42, 0x46, 0x34, 0x45 }, 7, STRING_DATA, false },
{ { 0x39, 0x56, 0x48, 0x53, 0x4d, 0x47 }, 6, STRING_DATA, false },
{ { 0x65, 0x38, 0x6f, 0x50, 0x41, 0x79, 0x32, 0x6b }, 8, STRING_DATA, false },
{ { 0x4a, 0x44 }, 2, STRING_DATA, false },
{ { 0x6d, 0x64 }, 2, IMM_DATA, false },
{ { 0x4e, 0x74, 0x34 }, 3, STRING_DATA, false },
{ { 0x42, 0x63, 0x45, 0x79, 0x67, 0x76 }, 6, STRING_DATA, false },
{ { 0x73, 0x73, 0x45, 0x66, 0x67, 0x69 }, 6, STRING_DATA, false },
{ { 0x6e, 0x76, 0x61, 0x35, 0x74 }, 5, STRING_DATA, false },
{ { 0x35, 0x6a, 0x6d, 0x33, 0x35, 0x32 }, 6, STRING_DATA, false },
{ { 0x55, 0x41 }, 2, IMM_DATA, false },
{ { 0x6f, 0x44, 0x6f, 0x73 }, 4, IMM_DATA, false },
{ { 0x55, 0x4a }, 2, IMM_DATA, false },
{ { 0x6b, 0x54, 0x58, 0x47, 0x51 }, 5, STRING_DATA, false },
{ { 0x68, 0x70, 0x41, 0x57, 0x4d, 0x46 }, 6, STRING_DATA, false },
{ { 0x34, 0x66, 0x42, 0x6d, 0x42 }, 5, STRING_DATA, false },
{ { 0x70, 0x4f, 0x33, 0x45 }, 4, IMM_DATA, false },
{ { 0x65, 0x64 }, 2, IMM_DATA, false },
{ { 0x47 }, 1, IMM_DATA, false },
{ { 0x36, 0x32, 0x72, 0x4f, 0x73, 0x71 }, 6, STRING_DATA, false },
{ { 0x4d }, 1, IMM_DATA, false },
{ { 0x42, 0x67, 0x6d, 0x53 }, 4, STRING_DATA, false },
{ { 0x64 }, 1, IMM_DATA, false },
{ { 0x41, 0x79, 0x78, 0x43, 0x53 }, 5, STRING_DATA, false },
{ { 0x50 }, 1, IMM_DATA, false },
{ { 0x42, 0x52, 0x4a, 0x49, 0x4f }, 5, STRING_DATA, false },
{ { 0x46, 0x52, 0x30, 0x51, 0x67, 0x5a, 0x46, 0x62 }, 8, STRING_DATA, false },
{ { 0x52 }, 1, IMM_DATA, false },
{ { 0x6e, 0x55, 0x30, 0x66 }, 4, STRING_DATA, false },
{ { 0x72, 0x6a, 0x33, 0x34 }, 4, IMM_DATA, false },
{ { 0x66 }, 1, STRING_DATA, true },
{ { 0x69, 0x56, 0x6d, 0x67 }, 4, IMM_DATA, false },
{ { 0x59, 0x69, 0x4c, 0x75 }, 4, STRING_DATA, false },
{ { 0x5a, 0x53, 0x41, 0x6d }, 4, IMM_DATA, false },
{ { 0x49, 0x62 }, 2, IMM_DATA, false },
{ { 0x73 }, 1, IMM_DATA, false },
{ { 0x38, 0x5a, 0x78, 0x69 }, 4, IMM_DATA, false },
{ { 0x48 }, 1, IMM_DATA, false },
{ { 0x50, 0x64, 0x70, 0x31 }, 4, IMM_DATA, false },
{ { 0x6f, 0x44 }, 2, IMM_DATA, false },
{ { 0x34 }, 1, IMM_DATA, false },
{ { 0x74, 0x55, 0x70, 0x76, 0x73, 0x46 }, 6, STRING_DATA, false },
{ { 0x63, 0x69, 0x34, 0x51, 0x4a, 0x74 }, 6, STRING_DATA, false },
{ { 0x59, 0x4e, 0x6a, 0x4e, 0x6e, 0x47, 0x55 }, 7, STRING_DATA, false },
{ { 0x32, 0x57, 0x50, 0x48 }, 4, STRING_DATA, false },
{ { 0x36, 0x72, 0x76, 0x43, 0x68, 0x47, 0x6c }, 7, STRING_DATA, false },
{ { 0x31, 0x49, 0x52, 0x4b, 0x72, 0x78, 0x4d, 0x74 }, 8, STRING_DATA, false },
{ { 0x71, 0x4c, 0x69, 0x65, 0x6c }, 5, STRING_DATA, false },
{ { 0x73, 0x76, 0x61, 0x6a, 0x55, 0x6a, 0x79, 0x72 }, 8, STRING_DATA, false },
{ { 0x67 }, 1, STRING_DATA, true },
{ { 0x4f, 0x43, 0x36, 0x4e, 0x6d, 0x79, 0x6d, 0x59 }, 8, STRING_DATA, false },
{ { 0x4d }, 1, IMM_DATA, false },
{ { 0x76, 0x5a, 0x4e }, 3, STRING_DATA, false },
{ { 0x45, 0x52, 0x33, 0x68, 0x74 }, 5, STRING_DATA, false },
{ { 0x46 }, 1, IMM_DATA, false },
{ { 0x45, 0x74, 0x4c, 0x31 }, 4, STRING_DATA, false },
{ { 0x65, 0x51, 0x62, 0x43, 0x79 }, 5, STRING_DATA, false },
{ { 0x54, 0x66, 0x44, 0x6d, 0x74, 0x59, 0x79, 0x51 }, 8, STRING_DATA, false },
{ { 0x31, 0x57, 0x74, 0x34 }, 4, STRING_DATA, false },
{ { 0x4f }, 1, IMM_DATA, false },
{ { 0x74, 0x31, 0x32, 0x6c, 0x78, 0x66 }, 6, STRING_DATA, false },
{ { 0x30 }, 1, IMM_DATA, false },
{ { 0x77, 0x56, 0x49, 0x52, 0x35 }, 5, STRING_DATA, false },
{ { 0x6d }, 1, IMM_DATA, false },
{ { 0x63, 0x47, 0x4e, 0x37 }, 4, STRING_DATA, false },
{ { 0x58, 0x43, 0x58, 0x4a }, 4, STRING_DATA, false },
{ { 0x52, 0x48, 0x4f, 0x46 }, 4, IMM_DATA, false },
{ { 0x48, 0x53 }, 2, IMM_DATA, false },
{ { 0x66 }, 1, IMM_DATA, false },
{ { 0x31, 0x67, 0x7a, 0x58, 0x57 }, 5, STRING_DATA, false },
{ { 0x61 }, 1, IMM_DATA, false },
{ { 0x62 }, 1, IMM_DATA, false },
{ { 0x52, 0x53 }, 2, STRING_DATA, false },
{ { 0x76, 0x6d, 0x74, 0x31, 0x6e }, 5, STRING_DATA, false },
{ { 0x72, 0x6c }, 2, STRING_DATA, true },
{ { 0x37, 0x73, 0x57 }, 3, STRING_DATA, false },
{ { 0x36, 0x63, 0x6a }, 3, STRING_DATA, false },
{ { 0x78, 0x6c, 0x6a, 0x75, 0x75, 0x51, 0x61 }, 7, STRING_DATA, false },
{ { 0x77, 0x49, 0x44, 0x41 }, 4, STRING_DATA, false },
{ { 0x51, 0x41 }, 2, IMM_DATA, false },
{ { 0x42 }, 1, IMM_DATA, false }
};
[[nodiscard]]
bool PatchSolution3::IsPrintable(const void* p, size_t s) noexcept {
auto pb = reinterpret_cast<const uint8_t*>(p);
for (size_t i = 0; i < s; ++i) {
if (isprint(pb[i]) == false) {
return false;
}
}
return true;
}
[[nodiscard]]
CapstoneContext PatchSolution3::GetJumpedBranch(const CapstoneContext& NotJumpedBranch, const cs_insn* lpJxxInsn) const {
CapstoneContext JumpedBranch;
JumpedBranch.lpMachineCode = _Image.RvaToPointer<const void*>(
static_cast<uintptr_t>(lpJxxInsn->detail->x86.operands[0].imm)
);
JumpedBranch.cbMachineCode = NotJumpedBranch.cbMachineCode - (
reinterpret_cast<const uint8_t*>(JumpedBranch.lpMachineCode) -
reinterpret_cast<const uint8_t*>(NotJumpedBranch.lpMachineCode)
);
JumpedBranch.Address = lpJxxInsn->detail->x86.operands[0].imm;
return JumpedBranch;
}
[[nodiscard]]
CapstoneContext PatchSolution3::SelectBranch(const CapstoneContext& NotJumpedBranch, const CapstoneContext& JumpedBranch, size_t KeywordIdx) const {
CapstoneContext A = NotJumpedBranch;
CapstoneContext B = JumpedBranch;
int WeightA = 0;
int WeightB = 0;
auto Disassembler = _Engine.CreateDisassembler();
while (true) {
int WeightAPrev = WeightA;
int WeightBPrev = WeightB;
//
// process NotJumpedBranch
//
Disassembler.SetContext(A);
while (Disassembler.Next()) {
auto lpInsn = Disassembler.GetInstruction();
//
// For all x86 mnemonics, only 'jcc' or 'jmp' starts with 'j' or 'J'.
// So it should be a new branch if we meet them.
//
if (lpInsn->mnemonic[0] == 'j' || lpInsn->mnemonic[0] == 'J') {
auto JumpedBranch = GetJumpedBranch(Disassembler.GetContext(), lpInsn);
if (_stricmp(lpInsn->mnemonic, "jmp") == 0) {
Disassembler.SetContext(JumpedBranch);
} else {
try {
Disassembler.SetContext(SelectBranch(Disassembler.GetContext(), JumpedBranch, KeywordIdx));
} catch (nkg::Exception&) {
// If exception occurs, give up NotJumpedBranch
break;
}
}
} else if (_stricmp(lpInsn->mnemonic, "ret") == 0) {
return JumpedBranch;
} else {
if (CheckIfMatchPattern(lpInsn) == false) {
continue;
}
//
// if match pattern, but keyword doesn't match,
// NotJumpedBranch must not be what we want
//
if (CheckIfFound(lpInsn, KeywordIdx) == false) {
return JumpedBranch;
}
//
// If keyword is succeeded to match
// Add WeightA and stop processing NotJumpedBranch
//
++WeightA;
break;
}
}
A = Disassembler.GetContext();
//
// process JumpedBranch
//
Disassembler.SetContext(B);
while (Disassembler.Next()) {
auto lpInsn = Disassembler.GetInstruction();
//
// For all x86 mnemonics, only 'jcc' or 'jmp' starts with 'j' or 'J'.
// So it should be a new branch if we meet them.
//
if (lpInsn->mnemonic[0] == 'j' || lpInsn->mnemonic[0] == 'J') {
auto JumpedBranch = GetJumpedBranch(Disassembler.GetContext(), lpInsn);
if (_stricmp(lpInsn->mnemonic, "jmp") == 0) {
Disassembler.SetContext(JumpedBranch);
} else {
try {
Disassembler.SetContext(SelectBranch(Disassembler.GetContext(), JumpedBranch, KeywordIdx));
} catch (nkg::Exception&) {
// If exception occurs, give up JumpedBranch
break;
}
}
} else if (_stricmp(lpInsn->mnemonic, "ret") == 0) {
return NotJumpedBranch;
} else {
if (CheckIfMatchPattern(lpInsn) == false) {
continue;
}
//
// if match pattern, but keyword doesn't match,
// JumpedBranch must not be what we want
//
if (CheckIfFound(lpInsn, KeywordIdx) == false) {
return NotJumpedBranch;
}
//
// If keyword is succeeded to match
// Add WeightB and stop processing JumpedBranch
//
++WeightB;
break;
}
}
B = Disassembler.GetContext();
//
// If this happens, it means neither of two branch is our target
if (WeightAPrev == WeightA && WeightBPrev == WeightB) {
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Branch is not selected."));
}
if (WeightA != WeightB)
return WeightA > WeightB ? NotJumpedBranch : JumpedBranch;
else
++KeywordIdx;
}
}
[[nodiscard]]
bool PatchSolution3::CheckKey(const RSACipher& Cipher) const noexcept {
//
// Brute-force search, cchString should be 1 or 2
//
auto SearchString = [](const void* lpRange, size_t cbRange, const char* lpString, size_t cchString) -> const char* {
const char* p = reinterpret_cast<const char*>(lpRange);
for (size_t i = 0; i < cbRange; ++i) {
if (p[i] == lpString[0]) {
bool match = true;
__try {
for (size_t j = 1; j < cchString; ++j) {
if (p[i + j] != lpString[j]) {
match = false;
break;
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
match = false;
}
if (match && p[i + cchString] == '\x00')
return address_offset_cast<const char*>(lpRange, i);
}
}
return nullptr;
};
auto szPublicKey = Cipher.ExportKeyString<RSAKeyType::PublicKey, RSAKeyFormat::PEM>();
for (auto pos = szPublicKey.find("-----BEGIN PUBLIC KEY-----"); pos != std::string::npos; pos = szPublicKey.find("-----BEGIN PUBLIC KEY-----", pos)) {
szPublicKey.erase(pos, literal_length("-----BEGIN PUBLIC KEY-----"));
}
for (auto pos = szPublicKey.find("-----END PUBLIC KEY-----"); pos != std::string::npos; pos = szPublicKey.find("-----END PUBLIC KEY-----", pos)) {
szPublicKey.erase(pos, literal_length("-----END PUBLIC KEY-----"));
}
for (auto pos = szPublicKey.find("\n"); pos != std::string::npos; pos = szPublicKey.find("\n", pos)) {
szPublicKey.erase(pos, literal_length("\n"));
}
if (szPublicKey.length() != 0x188) {
return false;
}
size_t PublicKeyReadCursor = 0;
auto SectionHeader_rdata = _Image.ImageSectionHeaderByName(".rdata");
auto SectionView_rdata = _Image.ImageSectionView(SectionHeader_rdata);
for (size_t i = 0; i < _countof(_Patch); PublicKeyReadCursor += Keyword[i].Size, ++i) {
if (Keyword[i].NotRecommendedToModify) {
_Patch[i].lpReplaceString = nullptr;
const char* lpReplaceString = nullptr;
const void* lpSearchRange = _Patch[i].lpOriginalString;
size_t cbSearchRange = SectionHeader_rdata->SizeOfRawData - address_delta(_Patch[i].lpOriginalString, SectionView_rdata);
for (size_t offset = 0;;) {
lpReplaceString = SearchString(
address_offset(lpSearchRange, offset),
cbSearchRange - offset,
szPublicKey.c_str() + PublicKeyReadCursor,
Keyword[i].Size
);
if (lpReplaceString == nullptr) {
return false;
}
if (_Image.IsRvaRangeInRelocTable(_Image.PointerToRva(lpReplaceString), Keyword[i].Size + 1)) {
//
// Damn it!
// ReplaceString will be modified during relocation
// We have to find another one
//
++offset;
} else {
//
// ReplaceString won't be modified during relocation
// which can be used to act as a part of public key string
//
break;
}
}
_Patch[i].lpReplaceString = const_cast<char*>(lpReplaceString);
}
}
return true;
}
void PatchSolution3::MakePatch(const RSACipher& Cipher) const {
for (size_t i = 0; i < _countof(_Patch); ++i) {
if (_Patch[i].lpPatch == nullptr) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("PatchSolution3 has not been ready yet."));
}
}
auto szPublicKey = Cipher.ExportKeyString<RSAKeyType::PublicKey, RSAKeyFormat::PEM>();
for (auto pos = szPublicKey.find("-----BEGIN PUBLIC KEY-----"); pos != std::string::npos; pos = szPublicKey.find("-----BEGIN PUBLIC KEY-----", pos)) {
szPublicKey.erase(pos, literal_length("-----BEGIN PUBLIC KEY-----"));
}
for (auto pos = szPublicKey.find("-----END PUBLIC KEY-----"); pos != std::string::npos; pos = szPublicKey.find("-----END PUBLIC KEY-----", pos)) {
szPublicKey.erase(pos, literal_length("-----END PUBLIC KEY-----"));
}
for (auto pos = szPublicKey.find("\n"); pos != std::string::npos; pos = szPublicKey.find("\n", pos)) {
szPublicKey.erase(pos, literal_length("\n"));
}
_putts(TEXT("*******************************************************"));
_putts(TEXT("* PatchSolution3 *"));
_putts(TEXT("*******************************************************"));
size_t readptr = 0;
for (size_t i = 0; i < _countof(_Patch); readptr += Keyword[i].Size, ++i) {
_tprintf_s(TEXT("[*] +%.8zx: "), address_delta(_Patch[i].lpPatch, _Image.ImageBase()));
PrintBytes(_Patch[i].lpPatch, _Patch[i].cbPatch);
_tprintf_s(TEXT(" ---> "));
if (Keyword[i].NotRecommendedToModify) {
auto offset = _Patch[i].lpReplaceString - _Patch[i].lpOriginalString;
uint64_t disp = 0;
memcpy(&disp, _Patch[i].lpPatch, _Patch[i].cbPatch);
disp += offset;
memcpy(_Patch[i].lpPatch, &disp, _Patch[i].cbPatch);
} else {
memcpy(_Patch[i].lpPatch, szPublicKey.c_str() + readptr, Keyword[i].Size);
}
PrintBytes(_Patch[i].lpPatch, _Patch[i].cbPatch);
_tprintf_s(TEXT("\n"));
}
_putts(TEXT(""));
return;
}
}
+247
View File
@@ -0,0 +1,247 @@
#include "PatchSolutions.hpp"
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\PatchSolution3-i386.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
PatchSolution3::PatchSolution3(const ImageInterpreter& Image) :
_Image(Image),
_Engine(CS_ARCH_X86, CS_MODE_32),
_Patch{}
{
_Engine.Option(CS_OPT_DETAIL, CS_OPT_ON);
}
PatchSolution3::PatchSolution3(const ImageInterpreter* lpImage) :
_Image(*lpImage),
_Engine(CS_ARCH_X86, CS_MODE_32),
_Patch{}
{
_Engine.Option(CS_OPT_DETAIL, CS_OPT_ON);
}
[[nodiscard]]
bool PatchSolution3::CheckIfMatchPattern(const cs_insn* lpInsn) const noexcept {
// the instruction we're interested in has one of the following patterns:
// 1. mov PTR [MEM], IMM (IMM must consist of printable chars) // for KeywordType::IMM_DATA
// except pattern "mov [ebp - 0x4], IMM"
// 2. push IMM (IMM must consist of printable chars) // for KeywordType::IMM_DATA
// 3. push offset MEM (MEM must point to a non-empty printable string) // for KeywordType::STRING_DATA
//
if (_stricmp(lpInsn->mnemonic, "mov") == 0) {
// filter the case "mov [ebp - 0x4], IMM"
// because IMM may consist of printable chars in that case, which will mislead us.
//
// Here I use "> -0x30" to intensify condition, instead of "== -0x4"
if (lpInsn->detail->x86.operands[0].type == X86_OP_MEM &&
lpInsn->detail->x86.operands[0].mem.base == X86_REG_EBP &&
lpInsn->detail->x86.operands[0].mem.disp > -0x30)
{
return false;
}
if (lpInsn->detail->x86.operands[1].type != X86_OP_IMM) {
return false;
}
auto pbImmValue = lpInsn->bytes + lpInsn->detail->x86.encoding.imm_offset;
auto cbImmValue = lpInsn->detail->x86.encoding.imm_size;
// each bytes of imm must be printable;
return IsPrintable(pbImmValue, cbImmValue);
} else if (_stricmp(lpInsn->mnemonic, "push") == 0) {
if (lpInsn->detail->x86.operands[0].type != X86_OP_IMM) {
return false;
}
// test if match pattern 2
auto pbImmValue = lpInsn->bytes + lpInsn->detail->x86.encoding.imm_offset;
auto cbImmValue = lpInsn->detail->x86.encoding.imm_size;
if (IsPrintable(pbImmValue, cbImmValue)) {
return true;
}
// test if match pattern 3
auto StringRva = static_cast<uintptr_t>(
lpInsn->detail->x86.operands[0].imm - _Image.ImageNtHeaders()->OptionalHeader.ImageBase
);
try {
auto StringPtr = _Image.RvaToPointer<const char*>(StringRva);
auto StringLength = strlen(StringPtr);
// StringPtr must have at least one char
// every char in StringPtr must be printable, otherwise pattern mismatches
return StringLength && IsPrintable(StringPtr, StringLength);
} catch (nkg::Exception&) {
// If not found, pattern mismatches
return false;
}
} else {
return false;
}
}
[[nodiscard]]
bool PatchSolution3::CheckIfFound(const cs_insn* lpInsn, size_t KeywordIdx) const noexcept {
// the instruction we're interested in has one of the following patterns:
// 1. mov PTR [MEM], IMM (IMM must consist of printable chars) // for KeywordType::IMM_DATA
// except pattern "mov [ebp - 0x4], IMM"
// 2. push IMM (IMM must consist of printable chars) // for KeywordType::IMM_DATA
// 3. push offset MEM (MEM must point to a non-empty printable string) // for KeywordType::STRING_DATA
//
auto& op_count = lpInsn->detail->x86.op_count;
auto& operands = lpInsn->detail->x86.operands;
if (op_count < 1 || operands[op_count - 1].type != X86_OP_IMM) {
return false;
}
if (Keyword[KeywordIdx].Type == IMM_DATA) {
static_assert(sizeof(operands[op_count - 1].imm) == sizeof(Keyword[KeywordIdx].Value));
return
operands[op_count - 1].imm == *reinterpret_cast<const int64_t*>(Keyword[KeywordIdx].Value) &&
lpInsn->detail->x86.encoding.imm_size == Keyword[KeywordIdx].Size;
} else if (Keyword[KeywordIdx].Type == STRING_DATA) {
auto StringRva = static_cast<uintptr_t>(
operands[op_count - 1].imm - _Image.ImageNtHeaders()->OptionalHeader.ImageBase
);
try {
auto StringPtr = _Image.RvaToPointer<const char*>(StringRva);
return
strncmp(StringPtr, reinterpret_cast<const char*>(Keyword[KeywordIdx].Value), Keyword[KeywordIdx].Size) == 0 &&
StringPtr[Keyword[KeywordIdx].Size] == '\x00';
} catch (nkg::Exception&) {
return false;
}
} else {
return false;
}
}
[[nodiscard]]
PatchSolution3::PatchInfo PatchSolution3::CreatePatchPoint(const void* lpOpcode, const cs_insn* lpInsn, size_t KeywordIdx) const noexcept {
PatchInfo NewPatch;
NewPatch.OpcodeRva = lpInsn->address;
NewPatch.lpOpcode = const_cast<void*>(lpOpcode);
if (Keyword[KeywordIdx].Type == IMM_DATA) {
NewPatch.lpPatch = address_offset(NewPatch.lpOpcode, lpInsn->detail->x86.encoding.imm_offset);
NewPatch.cbPatch = lpInsn->detail->x86.encoding.imm_size;
NewPatch.lpOriginalString = nullptr;
} else {
auto StringRva = static_cast<uintptr_t>(
lpInsn->detail->x86.operands[0].imm - _Image.ImageNtHeaders()->OptionalHeader.ImageBase
);
NewPatch.lpOriginalString = _Image.RvaToPointer<char*>(StringRva);
if (Keyword[KeywordIdx].NotRecommendedToModify) {
NewPatch.lpPatch = address_offset(NewPatch.lpOpcode, lpInsn->detail->x86.encoding.imm_offset);
NewPatch.cbPatch = lpInsn->detail->x86.encoding.imm_size;
} else {
NewPatch.lpPatch = reinterpret_cast<uint8_t*>(NewPatch.lpOriginalString);
NewPatch.cbPatch = Keyword[KeywordIdx].Size;
}
}
NewPatch.lpReplaceString = nullptr;
return NewPatch;
}
[[nodiscard]]
bool PatchSolution3::FindPatchOffset() noexcept {
try {
static const uint8_t HeaderOfTargetFunction[] = {
0x55, // push ebp
0x8B, 0xEC, // mov ebp, esp
0x6A, 0xFF // push 0xffffffff
};
PatchInfo Patch[_countof(_Patch)] = {};
const uint8_t* lpTargetFunction = nullptr;
auto lptargetFunctionHint = _Image.SearchSection<const uint8_t*>(".text", [&lpTargetFunction](const uint8_t* p) {
__try {
if (*reinterpret_cast<const uint32_t*>(p) == 0x6b67424e) {
auto i = p - 0x1B0;
for (; i < p; ++i) {
if (memcmp(i, HeaderOfTargetFunction, sizeof(HeaderOfTargetFunction)) == 0) {
lpTargetFunction = i;
return true;
}
}
}
return false;
} __except (EXCEPTION_EXECUTE_HANDLER) {
return false;
}
});
size_t KeywordIndex = 0;
CapstoneDisassembler Disassembler = _Engine.CreateDisassembler();
Disassembler.SetContext(CapstoneContext{ lpTargetFunction, 0x9014, _Image.PointerToRva(lpTargetFunction) });
while (Disassembler.Next()) {
auto lpInsn = Disassembler.GetInstruction();
if (lpInsn->mnemonic[0] == 'j' || lpInsn->mnemonic[0] == 'J') {
auto JumpedBranch = GetJumpedBranch(Disassembler.GetContext(), lpInsn);
if (_stricmp(lpInsn->mnemonic, "jmp") == 0) {
Disassembler.SetContext(JumpedBranch);
} else {
Disassembler.SetContext(SelectBranch(Disassembler.GetContext(), JumpedBranch, KeywordIndex));
}
} else if (_stricmp(lpInsn->mnemonic, "ret") == 0) {
return false;
} else {
if (CheckIfMatchPattern(lpInsn) == false) {
continue;
}
if (CheckIfFound(lpInsn, KeywordIndex) == false) {
return false;
}
Patch[KeywordIndex] = CreatePatchPoint(Disassembler.GetInstructionContext().lpMachineCode, lpInsn, KeywordIndex);
++KeywordIndex;
}
if (KeywordIndex == _countof(Patch)) {
break;
}
}
if (KeywordIndex != _countof(Patch)) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Some patches are not found."));
}
LOG_SUCCESS(0, "PatchSolution3 ...... Ready to apply");
for (size_t i = 0; i < _countof(Patch); ++i) {
_Patch[i] = Patch[i];
LOG_HINT(4, "[%3zu] Instruction RVA = 0x%.8llx, Patch Offset = +0x%.8zx", i, _Patch[i].OpcodeRva, address_delta(_Patch[i].lpPatch, _Image.ImageBase()));
}
return true;
} catch (nkg::Exception&) {
memset(_Patch, 0, sizeof(_Patch));
LOG_FAILURE(0, "PatchSolution3 ...... Omitted");
return false;
}
}
}
+150
View File
@@ -0,0 +1,150 @@
#include "PatchSolutions.hpp"
#include <xstring.hpp>
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\PatchSolution4-amd64.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
PatchSolution4::PatchSolution4(const ImageInterpreter& Image) :
_Image(Image),
_DisassemblyEngine(CS_ARCH_X86, CS_MODE_64),
_AssemblyEngine(KS_ARCH_X86, KS_MODE_64),
_pbPatchMachineCode(nullptr),
_pbPatchNewPublicKey(nullptr) { _DisassemblyEngine.Option(CS_OPT_DETAIL, CS_OPT_ON); }
PatchSolution4::PatchSolution4(const ImageInterpreter* Image) :
_Image(*Image),
_DisassemblyEngine(CS_ARCH_X86, CS_MODE_64),
_AssemblyEngine(KS_ARCH_X86, KS_MODE_64),
_pbPatchMachineCode(nullptr),
_pbPatchNewPublicKey(nullptr) { _DisassemblyEngine.Option(CS_OPT_DETAIL, CS_OPT_ON); }
bool PatchSolution4::FindPatchOffset() noexcept {
try {
_pbPatchMachineCode = _Image.SearchSection<uint8_t*>(".text", [](const uint8_t* p) {
__try {
return
p[0] == 0x48 && p[1] == 0x8d && // prefix of "lea rcx, [rbp+5Fh+var_38]"
p[4] == 0x48 && p[5] == 0x83 && // prefix of "cmp [rbp+5Fh+var_20], 10h"
p[9] == 0x48 && p[10] == 0x0f && p[11] == 0x43 && // prefix of "cmovnb rcx, [rbp+5Fh+var_38]"
p[14] == 0x48 && p[15] == 0x8d && // prefix of "lea rax, [rbp+5Fh+var_58]"
p[18] == 0x48 && p[19] == 0x83 && // prefix of "cmp [rbp+5Fh+var_40], 10h"
p[23] == 0x48 && p[24] == 0x0f && p[25] == 0x43 && // prefix of "cmovnb rax, [rbp+5Fh+var_58]"
p[28] == 0x44 && p[29] == 0x0f && p[30] == 0xb6 && // prefix of "movzx r8d, byte ptr [rax+rdi]"
p[33] == 0x44 && p[34] == 0x02 && // prefix of "add r8b, [rcx+rdi]"
p[37] == 0xba && // prefix of "mov edx, 1"
p[42] == 0x48 && p[43] == 0x8b && // prefix of "mov rcx, rbx"
p[45] == 0xe8; // prefix of "call sub_1806E65F0"
} __except (EXCEPTION_EXECUTE_HANDLER) {
return false;
}
});
auto RegisterIndex = X86_REG_INVALID;
auto Disassembler = _DisassemblyEngine.CreateDisassembler();
Disassembler.SetContext({ _pbPatchMachineCode, 45, _Image.PointerToVa(_pbPatchMachineCode) });
if (Disassembler.Next() && Disassembler.Next() && Disassembler.Next() && Disassembler.Next() && Disassembler.Next() && Disassembler.Next() && Disassembler.Next()) {
auto lpInsn = Disassembler.GetInstruction();
if (_stricmp(lpInsn->mnemonic, "movzx") == 0 &&
lpInsn->detail->x86.op_count == 2 &&
lpInsn->detail->x86.operands[0].type == X86_OP_REG &&
lpInsn->detail->x86.operands[1].type == X86_OP_MEM &&
lpInsn->detail->x86.operands[1].size == 1 &&
lpInsn->detail->x86.operands[1].mem.scale == 1)
{
RegisterIndex = lpInsn->detail->x86.operands[1].mem.index;
} else {
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Unexpected machine code."));
}
} else {
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Disassemble failed."));
}
if (Disassembler.Next() && Disassembler.Next() && Disassembler.Next()) {
auto lpInsn = Disassembler.GetInstruction();
//
// The previous instruction of "call sub_1806E65F0" should set RCX register.
//
if (_stricmp(lpInsn->mnemonic, "mov") != 0 ||
lpInsn->detail->x86.op_count < 1 ||
lpInsn->detail->x86.operands[0].type != X86_OP_REG ||
lpInsn->detail->x86.operands[0].reg != X86_REG_RCX)
{
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Unexpected machine code."));
}
} else {
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Disassemble failed."));
}
for (size_t i = 0; i < _Image.NumberOfSections(); ++i) {
auto lpSectionHeader = _Image.ImageSectionHeader(i);
if (lpSectionHeader->SizeOfRawData > lpSectionHeader->Misc.VirtualSize) {
auto cbReserved =
lpSectionHeader->SizeOfRawData -
lpSectionHeader->Misc.VirtualSize;
if (cbReserved >= 0x188) {
_pbPatchNewPublicKey = _Image.ImageSectionView<uint8_t*>(lpSectionHeader, lpSectionHeader->Misc.VirtualSize);
auto Assembler = _AssemblyEngine.CreateAssembler();
_NewMachineCode = Assembler.GenerateMachineCode(
std::xstring::format(
TEXT(
"lea rax, qword ptr[0x%.16llx];"
"mov r8b, byte ptr[rax + %hs];"
"mov edx, 1;"
),
_Image.PointerToVa(_pbPatchNewPublicKey),
_DisassemblyEngine.GetRegisterName(RegisterIndex)
).explicit_string().c_str(),
_Image.PointerToVa(_pbPatchMachineCode)
);
// >>>>>>>>>>>> .text:00000001819B02C0 48 8D 4D 27 lea rcx, [rbp + 5Fh + var_38]
// .text:00000001819B02C4 48 83 7D 3F 10 cmp[rbp + 5Fh + var_20], 10h
// 42 BYTES .text:00000001819B02C9 48 0F 43 4D 27 cmovnb rcx, [rbp + 5Fh + var_38]
// .text:00000001819B02CE 48 8D 45 07 lea rax, [rbp + 5Fh + var_58]
// THESE CODE .text:00000001819B02D2 48 83 7D 1F 10 cmp[rbp + 5Fh + var_40], 10h
// WILL BE .text:00000001819B02D7 48 0F 43 45 07 cmovnb rax, [rbp + 5Fh + var_58]
// REPLACED .text:00000001819B02DC 44 0F B6 04 38 movzx r8d, byte ptr[rax + rdi]
// .text:00000001819B02E1 44 02 04 39 add r8b, [rcx + rdi]
// <<<<<<<<<<<< .text:00000001819B02E5 BA 01 00 00 00 mov edx, 1
// .text:00000001819B02EA 48 8B CB mov rcx, rbx
// .text:00000001819B02ED E8 FE 62 D3 FE call sub_1806E65F0
while (_NewMachineCode.size() < 42) {
_NewMachineCode.emplace_back(0x90); // padding with "nop"
}
if (_NewMachineCode.size() != 42) {
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Something unexpected happens."));
}
LOG_SUCCESS(0, "PatchSolution4 ...... Ready to apply");
LOG_HINT(4, "Machine code patch VA = 0x%zx", _Image.PointerToVa(_pbPatchMachineCode));
LOG_HINT(4, "New public key VA = 0x%zx", _Image.PointerToVa(_pbPatchNewPublicKey));
LOG_HINT(4, "New public key offset = 0x%zx", _Image.PointerToFileOffset(_pbPatchNewPublicKey));
return true;
}
}
}
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("No space to store public key."));
} catch (nkg::Exception&) {
_pbPatchMachineCode = nullptr;
_pbPatchNewPublicKey = nullptr;
_NewMachineCode.clear();
LOG_FAILURE(0, "PatchSolution4 ...... Omitted");
return false;
}
}
}
@@ -0,0 +1,72 @@
#include "PatchSolutions.hpp"
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\PatchSolution4-generic.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
bool PatchSolution4::CheckKey(const RSACipher& Cipher) const noexcept {
auto szPublicKey = Cipher.ExportKeyString<RSAKeyType::PublicKey, RSAKeyFormat::PEM>();
for (auto pos = szPublicKey.find("-----BEGIN PUBLIC KEY-----"); pos != std::string::npos; pos = szPublicKey.find("-----BEGIN PUBLIC KEY-----", pos)) {
szPublicKey.erase(pos, literal_length("-----BEGIN PUBLIC KEY-----"));
}
for (auto pos = szPublicKey.find("-----END PUBLIC KEY-----"); pos != std::string::npos; pos = szPublicKey.find("-----END PUBLIC KEY-----", pos)) {
szPublicKey.erase(pos, literal_length("-----END PUBLIC KEY-----"));
}
for (auto pos = szPublicKey.find("\n"); pos != std::string::npos; pos = szPublicKey.find("\n", pos)) {
szPublicKey.erase(pos, literal_length("\n"));
}
return szPublicKey.length() == 0x188;
}
void PatchSolution4::MakePatch(const RSACipher& Cipher) const {
if (_pbPatchMachineCode == nullptr || _pbPatchNewPublicKey == nullptr || _NewMachineCode.empty()) {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("PatchSolution4 has not been ready yet."));
}
auto szPublicKey = Cipher.ExportKeyString<RSAKeyType::PublicKey, RSAKeyFormat::PEM>();
for (auto pos = szPublicKey.find("-----BEGIN PUBLIC KEY-----"); pos != std::string::npos; pos = szPublicKey.find("-----BEGIN PUBLIC KEY-----", pos)) {
szPublicKey.erase(pos, literal_length("-----BEGIN PUBLIC KEY-----"));
}
for (auto pos = szPublicKey.find("-----END PUBLIC KEY-----"); pos != std::string::npos; pos = szPublicKey.find("-----END PUBLIC KEY-----", pos)) {
szPublicKey.erase(pos, literal_length("-----END PUBLIC KEY-----"));
}
for (auto pos = szPublicKey.find("\n"); pos != std::string::npos; pos = szPublicKey.find("\n", pos)) {
szPublicKey.erase(pos, literal_length("\n"));
}
_putts(TEXT("*******************************************************"));
_putts(TEXT("* PatchSolution4 *"));
_putts(TEXT("*******************************************************"));
LOG_HINT(0, "Previous:");
PrintMemory(_pbPatchMachineCode, _NewMachineCode.size(), _Image.ImageBase());
memcpy(_pbPatchMachineCode, _NewMachineCode.data(), _NewMachineCode.size());
LOG_HINT(0, "After:");
PrintMemory(_pbPatchMachineCode, _NewMachineCode.size(), _Image.ImageBase());
_putts(TEXT(""));
LOG_HINT(0, "Previous:");
PrintMemory(_pbPatchNewPublicKey, szPublicKey.size(), _Image.ImageBase());
memcpy(_pbPatchNewPublicKey, szPublicKey.data(), szPublicKey.size());
LOG_HINT(0, "After:");
PrintMemory(_pbPatchNewPublicKey, szPublicKey.size(), _Image.ImageBase());
_putts(TEXT(""));
}
}
+145
View File
@@ -0,0 +1,145 @@
#include "PatchSolutions.hpp"
#include <xstring.hpp>
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\PatchSolution4-i386.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
PatchSolution4::PatchSolution4(const ImageInterpreter& Image) :
_Image(Image),
_DisassemblyEngine(CS_ARCH_X86, CS_MODE_32),
_AssemblyEngine(KS_ARCH_X86, KS_MODE_32),
_pbPatchMachineCode(nullptr),
_pbPatchNewPublicKey(nullptr) { _DisassemblyEngine.Option(CS_OPT_DETAIL, CS_OPT_ON); }
PatchSolution4::PatchSolution4(const ImageInterpreter* Image) :
_Image(*Image),
_DisassemblyEngine(CS_ARCH_X86, CS_MODE_32),
_AssemblyEngine(KS_ARCH_X86, KS_MODE_32),
_pbPatchMachineCode(nullptr),
_pbPatchNewPublicKey(nullptr) { _DisassemblyEngine.Option(CS_OPT_DETAIL, CS_OPT_ON); }
bool PatchSolution4::FindPatchOffset() noexcept {
try {
_pbPatchMachineCode = _Image.SearchSection<uint8_t*>(".text", [](const uint8_t* p) {
__try {
return
p[0] == 0x83 && // prefix of "cmp [ebp+var_30], 10h"
p[4] == 0x8d && // prefix of "lea ecx, [ebp+Dst]"
p[7] == 0x8d && // prefix of "lea eax, [ebp+Memory]"
p[10] == 0x0f && p[11] == 0x43 && // prefix of "cmovnb ecx, [ebp+Dst]"
p[14] == 0x83 && // prefix of "cmp [ebp+var_18], 10h"
p[18] == 0x0f && p[19] == 0x43 && // prefix of "cmovnb eax, [ebp+Memory]"
p[22] == 0x8a && // prefix of "mov dl, [eax+ebx]"
p[25] == 0x02; // prefix of "add dl, [ecx+ebx]"
// p[28]
} __except (EXCEPTION_EXECUTE_HANDLER) {
return false;
}
});
auto RegisterIndex = X86_REG_INVALID;
auto RegisterFinalValue = X86_REG_INVALID;
auto Disassembler = _DisassemblyEngine.CreateDisassembler();
Disassembler.SetContext({ _pbPatchMachineCode, 28, _Image.PointerToVa(_pbPatchMachineCode) });
if (Disassembler.Next() && Disassembler.Next() && Disassembler.Next() && Disassembler.Next() && Disassembler.Next() && Disassembler.Next() && Disassembler.Next()) {
auto lpInsn = Disassembler.GetInstruction();
if (_stricmp(lpInsn->mnemonic, "mov") == 0 &&
lpInsn->detail->x86.op_count == 2 &&
lpInsn->detail->x86.operands[0].type == X86_OP_REG &&
lpInsn->detail->x86.operands[1].type == X86_OP_MEM &&
lpInsn->detail->x86.operands[1].size == 1 &&
lpInsn->detail->x86.operands[1].mem.scale == 1)
{
RegisterIndex = lpInsn->detail->x86.operands[1].mem.index;
} else {
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Unexpected machine code."));
}
} else {
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Disassemble failed."));
}
if (Disassembler.Next()) {
auto lpInsn = Disassembler.GetInstruction();
if (_stricmp(lpInsn->mnemonic, "add") == 0 &&
lpInsn->detail->x86.op_count >= 1 &&
lpInsn->detail->x86.operands[0].type == X86_OP_REG &&
lpInsn->detail->x86.operands[0].size == 1)
{
RegisterFinalValue = lpInsn->detail->x86.operands[0].reg;
} else {
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Unexpected machine code."));
}
} else {
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Disassemble failed."));
}
for (size_t i = 0; i < _Image.NumberOfSections(); ++i) {
auto lpSectionHeader = _Image.ImageSectionHeader(i);
if (lpSectionHeader->SizeOfRawData > lpSectionHeader->Misc.VirtualSize) {
auto cbReserved =
lpSectionHeader->SizeOfRawData -
lpSectionHeader->Misc.VirtualSize;
if (cbReserved >= 0x188) {
_pbPatchNewPublicKey = _Image.ImageSectionView<uint8_t*>(lpSectionHeader, lpSectionHeader->Misc.VirtualSize);
auto Assembler = _AssemblyEngine.CreateAssembler();
_NewMachineCode = Assembler.GenerateMachineCode(
std::xstring::format(
TEXT(
"call +5;"
"pop eax;"
"add eax, 0x%.8x;"
"mov %hs, byte ptr [eax + %hs];"
),
_Image.PointerToVa(_pbPatchNewPublicKey) - (_Image.PointerToVa(_pbPatchMachineCode) + 5),
_DisassemblyEngine.GetRegisterName(RegisterFinalValue),
_DisassemblyEngine.GetRegisterName(RegisterIndex)
).explicit_string().c_str()
);
// >>>>>>>>>>>> .text:113FE4A0 83 7D D0 10 cmp [ebp+var_30], 10h
// 28 BYTES .text:113FE4A4 8D 4D BC lea ecx, [ebp+Dst]
// .text:113FE4A7 8D 45 D4 lea eax, [ebp+Memory]
// THESE CODE .text:113FE4AA 0F 43 4D BC cmovnb ecx, [ebp+Dst]
// WILL BE .text:113FE4AE 83 7D E8 10 cmp [ebp+var_18], 10h
// REPLACED .text:113FE4B2 0F 43 45 D4 cmovnb eax, [ebp+Memory]
// .text:113FE4B6 8A 14 18 mov dl, [eax+ebx]
// <<<<<<<<<<<< .text:113FE4B9 02 14 19 add dl, [ecx+ebx]
while (_NewMachineCode.size() < 28) {
_NewMachineCode.emplace_back(0x90); // padding with "nop"
}
if (_NewMachineCode.size() != 28) {
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Something unexpected happens."));
}
LOG_SUCCESS(0, "PatchSolution4 ...... Ready to apply");
LOG_HINT(4, "Machine code patch VA = 0x%zx", _Image.PointerToVa(_pbPatchMachineCode));
LOG_HINT(4, "New public key VA = 0x%zx", _Image.PointerToVa(_pbPatchNewPublicKey));
LOG_HINT(4, "New public key offset = 0x%zx", _Image.PointerToFileOffset(_pbPatchNewPublicKey));
return true;
}
}
}
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("No space to store public key."));
} catch (nkg::Exception&) {
_pbPatchMachineCode = nullptr;
_pbPatchNewPublicKey = nullptr;
_NewMachineCode.clear();
LOG_FAILURE(0, "PatchSolution4 ...... Omitted");
return false;
}
}
}
+234
View File
@@ -0,0 +1,234 @@
#pragma once
#include <RSACipher.hpp>
#include "ImageInterpreter.hpp"
#include "CapstoneDisassembler.hpp"
#include "KeystoneAssembler.hpp"
#include "Misc.hpp"
namespace nkg {
class PatchSolution {
protected:
static constexpr size_t InvalidOffset = -1;
public:
[[nodiscard]]
virtual bool FindPatchOffset() noexcept = 0;
[[nodiscard]]
virtual bool CheckKey(const RSACipher& Cipher) const noexcept = 0;
virtual void MakePatch(const RSACipher& Cipher) const = 0;
virtual ~PatchSolution() = default;
};
//
// PatchSolution0 will replace the RSA public key stored in navicat.exe
//
class PatchSolution0 final : public PatchSolution {
private:
static const char Keyword[461];
const ImageInterpreter& _Image;
size_t _PatchOffset;
public:
PatchSolution0(const ImageInterpreter& Image) noexcept :
_Image(Image),
_PatchOffset(InvalidOffset) {}
PatchSolution0(const ImageInterpreter* lpImage) noexcept :
_Image(*lpImage),
_PatchOffset(InvalidOffset) {}
[[nodiscard]]
virtual bool FindPatchOffset() noexcept override;
[[nodiscard]]
virtual bool CheckKey(const RSACipher& Cipher) const noexcept override;
virtual void MakePatch(const RSACipher& Cipher) const override;
};
//
// PatchSolution1 will replace the RSA public key stored in libcc.dll
//
class PatchSolution1 final : public PatchSolution {
private:
static const char Keyword0[160 + 1];
static const char Keyword1[4 + 1];
static const char Keyword2[742 + 1];
static const char Keyword3[4 + 1];
static const char Keyword4[5 + 1];
const ImageInterpreter& _Image;
size_t _PatchOffset[5];
size_t _PatchSize[5];
public:
PatchSolution1(const ImageInterpreter& Image) noexcept :
_Image(Image),
_PatchOffset{ InvalidOffset , InvalidOffset , InvalidOffset , InvalidOffset , InvalidOffset },
_PatchSize{} {}
PatchSolution1(const ImageInterpreter* lpImage) noexcept :
_Image(*lpImage),
_PatchOffset{ InvalidOffset , InvalidOffset , InvalidOffset , InvalidOffset , InvalidOffset },
_PatchSize{} {}
[[nodiscard]]
virtual bool FindPatchOffset() noexcept override;
[[nodiscard]]
virtual bool CheckKey(const RSACipher& Cipher) const noexcept override;
virtual void MakePatch(const RSACipher& Cipher) const override;
};
//
// PatchSolution2 will replace the RSA public key stored in libcc.dll
//
class PatchSolution2 final : public PatchSolution {
private:
static const char KeywordMeta[0x188 + 1];
static const uint8_t Keyword[0x188][5];
const ImageInterpreter& _Image;
size_t _PatchOffset[0x188];
public:
PatchSolution2(const ImageInterpreter& Image) noexcept :
_Image(Image),
_PatchOffset{}
{
for (size_t i = 0; i < _countof(_PatchOffset); ++i) {
_PatchOffset[i] = InvalidOffset;
}
}
PatchSolution2(const ImageInterpreter* lpImage) noexcept :
_Image(*lpImage),
_PatchOffset{}
{
for (size_t i = 0; i < _countof(_PatchOffset); ++i) {
_PatchOffset[i] = InvalidOffset;
}
}
[[nodiscard]]
virtual bool FindPatchOffset() noexcept override;
[[nodiscard]]
virtual bool CheckKey(const RSACipher& Cipher) const noexcept override;
virtual void MakePatch(const RSACipher& Cipher) const override;
};
//
// PatchSolution3 will replace the RSA public key stored in libcc.dll
//
class PatchSolution3 final : public PatchSolution {
private:
using KeywordValueType = uint8_t[8];
using KeywordSizeType = size_t;
enum KeywordTypeEnum { IMM_DATA, STRING_DATA };
struct KeywordInfo {
KeywordValueType Value;
KeywordSizeType Size;
KeywordTypeEnum Type;
bool NotRecommendedToModify;
};
struct PatchInfo {
uint64_t OpcodeRva;
void* lpOpcode;
void* lpPatch;
size_t cbPatch;
char* lpOriginalString;
char* lpReplaceString;
};
static const KeywordInfo Keyword[111];
const ImageInterpreter& _Image;
CapstoneEngine _Engine;
mutable PatchInfo _Patch[111];
[[nodiscard]]
static bool IsPrintable(const void* p, size_t s) noexcept;
[[nodiscard]]
bool CheckIfMatchPattern(const cs_insn* lpInsn) const noexcept;
[[nodiscard]]
bool CheckIfFound(const cs_insn* lpInsn, size_t KeywordIdx) const noexcept;
[[nodiscard]]
PatchInfo CreatePatchPoint(const void* lpOpcode, const cs_insn* lpInsn, size_t KeywordIdx) const noexcept;
[[nodiscard]]
CapstoneContext GetJumpedBranch(const CapstoneContext& Bifurcation, const cs_insn* lpJxxInsn) const;
[[nodiscard]]
CapstoneContext SelectBranch(const CapstoneContext& NotJumpedBranch, const CapstoneContext& JumpedBranch, size_t KeywordIdx) const;
public:
PatchSolution3(const ImageInterpreter& Image);
PatchSolution3(const ImageInterpreter* lpImage);
[[nodiscard]]
virtual bool FindPatchOffset() noexcept override;
[[nodiscard]]
virtual bool CheckKey(const RSACipher& Cipher) const noexcept override;
virtual void MakePatch(const RSACipher& Cipher) const override;
};
//
// PatchSolution3 will replace the RSA public key stored in libcc.dll
// For Navicat Data Modeler 3
//
class PatchSolution4 : public PatchSolution {
private:
static const uint8_t KeywordA[0x188];
static const uint8_t KeywordB[0x188];
const ImageInterpreter& _Image;
CapstoneEngine _DisassemblyEngine;
KeystoneEngine _AssemblyEngine;
uint8_t* _pbPatchMachineCode;
uint8_t* _pbPatchNewPublicKey;
std::vector<uint8_t> _NewMachineCode;
public:
PatchSolution4(const ImageInterpreter& Image);
PatchSolution4(const ImageInterpreter* lpImage);
[[nodiscard]]
virtual bool FindPatchOffset() noexcept override;
[[nodiscard]]
virtual bool CheckKey(const RSACipher& Cipher) const noexcept override;
virtual void MakePatch(const RSACipher& Cipher) const override;
};
}
-266
View File
@@ -1,266 +0,0 @@
#pragma once
#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <string>
#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
class RSACipher {
private:
RSA * _RsaObj;
RSACipher() : _RsaObj(nullptr) {}
RSACipher(RSA* lpRsa) : _RsaObj(lpRsa) {}
RSACipher(const RSACipher&) = delete;
RSACipher(RSACipher&&) = delete;
RSACipher& operator=(const RSACipher&) = delete;
RSACipher& operator=(RSACipher&&) = delete;
public:
enum class KeyType {
PrivateKey,
PublicKey
};
enum class KeyFormat {
NotSpecified,
PEM,
PKCS1
};
~RSACipher() {
if (_RsaObj)
RSA_free(_RsaObj);
_RsaObj = nullptr;
}
static RSACipher* Create() {
RSACipher* aCipher = new RSACipher(RSA_new());
if (aCipher->_RsaObj == nullptr) {
delete aCipher;
aCipher = nullptr;
}
return aCipher;
}
bool GenerateKey(int bits, unsigned long long e = RSA_F4) {
bool bSuccess = false;
BIGNUM* bn_e = nullptr;
bn_e = BN_new();
if (bn_e == nullptr)
goto ON_RSACipher_GenerateKey0_ERROR;
if (!BN_set_word(bn_e, e))
goto ON_RSACipher_GenerateKey0_ERROR;
if (!RSA_generate_key_ex(_RsaObj, bits, bn_e, nullptr))
goto ON_RSACipher_GenerateKey0_ERROR;
bSuccess = true;
ON_RSACipher_GenerateKey0_ERROR:
if (bn_e)
BN_free(bn_e);
return bSuccess;
}
template<KeyType _Type, KeyFormat _Format = KeyFormat::NotSpecified>
bool ExportKeyToFile(const std::string& filename) {
static_assert(
_Type == KeyType::PrivateKey || (_Format == KeyFormat::PEM || _Format == KeyFormat::PKCS1),
"Not supported format."
);
bool bSuccess = false;
BIO* bio_file = nullptr;
bio_file = BIO_new_file(filename.c_str(), "w");
if (bio_file == nullptr)
goto ON_RSACipher_ExportKeyToFile_0_ERROR;
if (_Type == KeyType::PrivateKey) {
bSuccess = PEM_write_bio_RSAPrivateKey(bio_file, _RsaObj, nullptr, nullptr, 0, nullptr, nullptr) ? true : false;
} else {
if (_Format == KeyFormat::PEM)
bSuccess = PEM_write_bio_RSA_PUBKEY(bio_file, _RsaObj) ? true : false;
else if (_Format == KeyFormat::PKCS1)
bSuccess = PEM_write_bio_RSAPublicKey(bio_file, _RsaObj) ? true : false;
}
ON_RSACipher_ExportKeyToFile_0_ERROR:
return bSuccess;
}
template<KeyType _Type, KeyFormat _Format = KeyFormat::NotSpecified>
std::string ExportKeyString() {
static_assert(
_Type == KeyType::PrivateKey || (_Format == KeyFormat::PEM || _Format == KeyFormat::PKCS1),
"Not supported format."
);
std::string KeyString;
BIO* bio_mem = nullptr;
int len = 0;
const char* lpdata = nullptr;
bio_mem = BIO_new(BIO_s_mem());
if (bio_mem == nullptr)
goto ON_RSACipher_ExportKeyString_0_ERROR;
if (_Type == KeyType::PrivateKey) {
if (!PEM_write_bio_RSAPrivateKey(bio_mem, _RsaObj, nullptr, nullptr, 0, nullptr, nullptr))
goto ON_RSACipher_ExportKeyString_0_ERROR;
} else {
if (_Format == KeyFormat::PEM) {
if (!PEM_write_bio_RSA_PUBKEY(bio_mem, _RsaObj))
goto ON_RSACipher_ExportKeyString_0_ERROR;
} else if (_Format == KeyFormat::PKCS1) {
if (!PEM_write_bio_RSAPublicKey(bio_mem, _RsaObj))
goto ON_RSACipher_ExportKeyString_0_ERROR;
}
}
len = BIO_get_mem_data(bio_mem, &lpdata);
KeyString.resize(len);
memcpy(KeyString.data(), lpdata, len);
ON_RSACipher_ExportKeyString_0_ERROR:
if (bio_mem)
BIO_free_all(bio_mem);
return KeyString;
}
template<KeyType _Type, KeyFormat _Format = KeyFormat::NotSpecified>
bool ImportKeyFromFile(const std::string& filename) {
static_assert(
_Type == KeyType::PrivateKey || (_Format == KeyFormat::PEM || _Format == KeyFormat::PKCS1),
"Not supported format."
);
bool bSuccess = false;
BIO* bio_file = nullptr;
RSA* _newRsaObj = nullptr;
bio_file = BIO_new_file(filename.c_str(), "r");
if (bio_file == nullptr)
goto ON_RSACipher_ImportKeyFromFile_0_ERROR;
if (_Type == KeyType::PrivateKey) {
_newRsaObj = PEM_read_bio_RSAPrivateKey(bio_file, nullptr, nullptr, nullptr);
} else {
if (_Format == KeyFormat::PEM)
_newRsaObj = PEM_read_bio_RSA_PUBKEY(bio_file, nullptr, nullptr, nullptr);
else if (_Format == KeyFormat::PKCS1)
_newRsaObj = PEM_read_bio_RSAPublicKey(bio_file, nullptr, nullptr, nullptr);
}
if (_newRsaObj) {
RSA_free(_RsaObj);
_RsaObj = _newRsaObj;
bSuccess = true;
}
ON_RSACipher_ImportKeyFromFile_0_ERROR:
if (bio_file)
BIO_free_all(bio_file);
return bSuccess;
}
template<KeyType _Type, KeyFormat _Format = KeyFormat::NotSpecified>
bool ImportKeyString(const std::string& KeyString) {
static_assert(
_Type == KeyType::PrivateKey || (_Format == KeyFormat::PEM || _Format == KeyFormat::PKCS1),
"Not supported format."
);
bool bSuccess = false;
BIO* bio_mem = nullptr;
RSA* _newRsaObj = nullptr;
bio_mem = BIO_new(BIO_s_mem());
if (bio_mem == nullptr)
goto ON_RSACipher_ImportKeyString_0_ERROR;
BIO_puts(bio_mem, KeyString.c_str());
if (_Type == KeyType::PrivateKey) {
_newRsaObj = PEM_read_bio_RSAPrivateKey(bio_mem, nullptr, nullptr, nullptr);
} else {
if (_Format == KeyFormat::PEM)
_newRsaObj = PEM_read_bio_RSA_PUBKEY(bio_mem, nullptr, nullptr, nullptr);
else if (_Format == KeyFormat::PKCS1)
_newRsaObj = PEM_read_bio_RSAPublicKey(bio_mem, nullptr, nullptr, nullptr);
}
if (_newRsaObj) {
RSA_free(_RsaObj);
_RsaObj = _newRsaObj;
bSuccess = true;
}
ON_RSACipher_ImportKeyString_0_ERROR:
if (bio_mem)
BIO_free_all(bio_mem);
return bSuccess;
}
template<KeyType _Type = KeyType::PublicKey>
int Encrypt(const void* from, int len, void* to, int padding) {
int write_bytes = 0;
if (_Type == KeyType::PrivateKey) {
write_bytes = RSA_private_encrypt(len,
reinterpret_cast<const unsigned char*>(from),
reinterpret_cast<unsigned char*>(to),
_RsaObj,
padding);
} else {
write_bytes = RSA_public_encrypt(len,
reinterpret_cast<const unsigned char*>(from),
reinterpret_cast<unsigned char*>(to),
_RsaObj,
padding);
}
if (write_bytes == -1)
write_bytes = 0;
return write_bytes;
}
template<KeyType _Type = KeyType::PrivateKey>
int Decrypt(const void* from, int len, void* to, int padding) {
int write_bytes = 0;
if (_Type == KeyType::PrivateKey) {
write_bytes = RSA_private_decrypt(len,
reinterpret_cast<const unsigned char*>(from),
reinterpret_cast<unsigned char*>(to),
_RsaObj,
padding);
} else {
write_bytes = RSA_public_decrypt(len,
reinterpret_cast<const unsigned char*>(from),
reinterpret_cast<unsigned char*>(to),
_RsaObj,
padding);
}
if (write_bytes == -1)
write_bytes = 0;
return write_bytes;
}
};
@@ -0,0 +1,33 @@
#pragma once
#include <capstone/capstone.h>
struct CapstoneHandleTraits {
using HandleType = csh;
static inline const HandleType InvalidValue = NULL;
[[nodiscard]]
static bool IsValid(const HandleType& Handle) noexcept {
return Handle != InvalidValue;
}
static void Releasor(HandleType& Handle) noexcept {
cs_close(&Handle);
}
};
struct CapstoneInsnTraits {
using HandleType = cs_insn*;
static inline const HandleType InvalidValue = nullptr;
[[nodiscard]]
static bool IsValid(const HandleType& Handle) noexcept {
return Handle != InvalidValue;
}
static void Releasor(const HandleType& Handle) noexcept {
cs_free(Handle, 1);
}
};
@@ -0,0 +1,33 @@
#pragma once
#include <keystone/keystone.h>
struct KeystoneHandleTraits {
using HandleType = ks_engine*;
static inline const HandleType InvalidValue = nullptr;
[[nodiscard]]
static bool IsValid(const HandleType& Handle) noexcept {
return Handle != InvalidValue;
}
static void Releasor(const HandleType& Handle) noexcept {
ks_close(Handle);
}
};
struct KeystoneMallocTraits {
using HandleType = uint8_t*;
static inline const HandleType InvalidValue = nullptr;
[[nodiscard]]
static bool IsValid(const HandleType& Handle) noexcept {
return Handle != InvalidValue;
}
static void Releasor(const HandleType& Handle) noexcept {
ks_free(Handle);
}
};
-234
View File
@@ -1,234 +0,0 @@
#include "def.hpp"
// Solution0 is for navicat premium of which the version < 12.0.25
namespace patcher::Solution0 {
static std::Tstring InstallationPath;
static const CHAR Keyword[] =
"-----BEGIN PUBLIC KEY-----\r\n"
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw1dqF3SkCaAAmMzs889I\r\n"
"qdW9M2dIdh3jG9yPcmLnmJiGpBF4E9VHSMGe8oPAy2kJDmdNt4BcEygvssEfginv\r\n"
"a5t5jm352UAoDosUJkTXGQhpAWMF4fBmBpO3EedG62rOsqMBgmSdAyxCSPBRJIOF\r\n"
"R0QgZFbRnU0frj34fiVmgYiLuZSAmIbs8ZxiHPdp1oD4tUpvsFci4QJtYNjNnGU2\r\n"
"WPH6rvChGl1IRKrxMtqLielsvajUjyrgOC6NmymYMvZNER3htFEtL1eQbCyTfDmt\r\n"
"YyQ1Wt4Ot12lxf0wVIR5mcGN7XCXJRHOFHSf1gzXWabRSvmt1nrl7sW6cjxljuuQ\r\n"
"awIDAQAB\r\n"
"-----END PUBLIC KEY-----\r\n";
static const DWORD KeywordLength = sizeof(Keyword) - 1;
static LPCTSTR PossibleName[3] = {
TEXT("navicat.exe"),
TEXT("modeler.exe"),
TEXT("rviewer.exe")
};
static LPCTSTR TargetName = NULL;
static HMODULE hTarget = NULL;
BOOL Init(const std::Tstring& Path) {
BOOL bSuccess = FALSE;
DWORD dwLastError = ERROR_SUCCESS;
DWORD attr = INVALID_FILE_ATTRIBUTES;
attr = GetFileAttributes(Path.c_str());
if (attr == INVALID_FILE_ATTRIBUTES) {
dwLastError = GetLastError();
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("Failed @ GetFileAttributes. CODE: 0x%08X\n"), dwLastError);
goto ON_Init_ERROR;
}
if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("Error: Path is not a directory.\n"));
goto ON_Init_ERROR;
}
InstallationPath = Path;
if (InstallationPath.back() != TEXT('\\') && InstallationPath.back() != TEXT('/'))
InstallationPath.push_back(TEXT('\\'));
bSuccess = TRUE;
ON_Init_ERROR:
return bSuccess;
}
BOOL CheckKey(RSACipher* cipher) {
return TRUE;
}
BOOL FindTargetFile() {
BOOL bSuccess = FALSE;
DWORD dwLastError = ERROR_SUCCESS;
for (size_t i = 0; i < _countof(PossibleName); ++i) {
std::Tstring&& PossibleFileName = InstallationPath + PossibleName[i];
hTarget = LoadLibrary(PossibleFileName.c_str());
if (hTarget == NULL && (dwLastError = GetLastError()) != ERROR_MOD_NOT_FOUND) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("Unexpected Error @ LoadLibrary. CODE: 0x%08X\n"), dwLastError);
goto ON_FindTargetFile_ERROR;
}
if (hTarget) {
_tprintf_s(TEXT("Target has been found: %s\n"), PossibleName[i]);
TargetName = PossibleName[i];
bSuccess = TRUE;
goto ON_FindTargetFile_ERROR;
}
}
ON_FindTargetFile_ERROR:
return bSuccess;
}
BOOL CheckFile() {
BOOL bFound = FALSE;
DWORD dwLastError = ERROR_SUCCESS;
HRSRC hRes = NULL;
HGLOBAL hGLobal = NULL;
PVOID lpData = NULL;
DWORD dwSize = 0;
if (hTarget == NULL) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("Error: Target has not been set yet.\n"));
goto ON_CheckFile_ERROR;
}
hRes = FindResource(hTarget, TEXT("ACTIVATIONPUBKEY"), RT_RCDATA);
if (hRes == NULL) {
dwLastError = GetLastError();
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("Failed @ FindResource. CODE: 0x%08X\n"), dwLastError);
goto ON_CheckFile_ERROR;
}
hGLobal = LoadResource(hTarget, hRes);
if (hGLobal == NULL) {
dwLastError = GetLastError();
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("Failed @ LoadResource. CODE: 0x%08X\n"), dwLastError);
goto ON_CheckFile_ERROR;
}
lpData = LockResource(hGLobal);
if (lpData == NULL) {
dwLastError = GetLastError();
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("Failed @ LockResource. CODE: 0x%08X\n"), dwLastError);
goto ON_CheckFile_ERROR;
}
dwSize = SizeofResource(hTarget, hRes);
if (dwSize == 0) {
dwLastError = GetLastError();
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("Failed @ SizeofResource. CODE: 0x%08X\n"), dwLastError);
goto ON_CheckFile_ERROR;
}
if (dwSize == KeywordLength && memcmp(lpData, Keyword, KeywordLength) == 0) {
FreeLibrary(hTarget);
hTarget = NULL;
bFound = TRUE;
} else {
FreeLibrary(hTarget);
hTarget = NULL;
TargetName = NULL;
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("ERROR: Resource doest not match.\n"));
goto ON_CheckFile_ERROR;
}
ON_CheckFile_ERROR:
return bFound;
}
BOOL BackupFile() {
BOOL bSuccess = FALSE;
DWORD dwLastError = ERROR_SUCCESS;
std::Tstring&& TargetFileName = InstallationPath + TargetName;
std::Tstring&& BackupFileName = InstallationPath + TargetName + TEXT(".backup");
if (!CopyFile(TargetFileName.c_str(), BackupFileName.c_str(), TRUE)) {
dwLastError = GetLastError();
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("Failed @ CopyFile. CODE: 0x%08X\n"), dwLastError);
goto ON_BackupFile_ERROR;
}
bSuccess = TRUE;
ON_BackupFile_ERROR:
return bSuccess;
}
BOOL Do(RSACipher* cipher) {
BOOL bSuccess = FALSE;
DWORD dwLastError = ERROR_SUCCESS;
std::string RSAPublicKeyPEM;
std::Tstring&& TargetFileName = InstallationPath + TargetName;
HANDLE hUpdater = NULL;
RSAPublicKeyPEM = cipher->ExportKeyString<RSACipher::KeyType::PublicKey, RSACipher::KeyFormat::PEM>();
if (RSAPublicKeyPEM.empty()) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("ERROR: cipher->ExportKeyString failed.\n"));
goto ON_Do_ERROR;
}
[](std::string& str, const std::string& OldSub, const std::string& NewSub) {
std::string::size_type pos = 0;
std::string::size_type srclen = OldSub.size();
std::string::size_type dstlen = NewSub.size();
while ((pos = str.find(OldSub, pos)) != std::string::npos) {
str.replace(pos, srclen, NewSub);
pos += dstlen;
}
} (RSAPublicKeyPEM, "\n", "\r\n"); // replace '\n' to '\r\n'
if (RSAPublicKeyPEM.length() != KeywordLength) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("ERROR: Public key length does not match.\n"));
goto ON_Do_ERROR;
}
hUpdater = BeginUpdateResource(TargetFileName.c_str(), FALSE);
if (hUpdater == NULL) {
dwLastError = GetLastError();
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("Failed @ BeginUpdateResource. CODE: 0x%08X\n"), dwLastError);
goto ON_Do_ERROR;
}
if (!UpdateResource(hUpdater,
RT_RCDATA,
TEXT("ACTIVATIONPUBKEY"),
MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
(LPVOID)RSAPublicKeyPEM.c_str(),
KeywordLength)) {
dwLastError = GetLastError();
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("Failed @ UpdateResource. CODE: 0x%08X\n"), dwLastError);
goto ON_Do_ERROR;
}
bSuccess = TRUE;
ON_Do_ERROR:
EndUpdateResource(hUpdater, !bSuccess);
return bSuccess;
}
VOID Finalize() {
if (hTarget) {
FreeLibrary(hTarget);
hTarget = NULL;
}
}
}
-417
View File
@@ -1,417 +0,0 @@
#include "def.hpp"
// Solution1 is for navicat premium of which the version = 12.0.25
namespace patcher::Solution1 {
static std::Tstring InstallationPath;
static const CHAR Keyword0[] =
"D75125B70767B94145B47C1CB3C0755E"
"7CCB8825C5DCE0C58ACF944E08280140"
"9A02472FAFFD1CD77864BB821AE36766"
"FEEDE6A24F12662954168BFA314BD950"
"32B9D82445355ED7BC0B880887D650F5";
static const DWORD KeywordSize0 = sizeof(Keyword0) - 1;
static const uint8_t Keyword1[] = {
0xFE, 0xEA, 0xBC, 0x01
};
static const DWORD KeywordSize1 = sizeof(Keyword1);
static const CHAR Keyword2[] =
"E1CED09B9C2186BF71A70C0FE2F1E0AE"
"F3BD6B75277AAB20DFAF3D110F75912B"
"FB63AC50EC4C48689D1502715243A79F"
"39FF2DE2BF15CE438FF885745ED54573"
"850E8A9F40EE2FF505EB7476F95ADB78"
"3B28CA374FAC4632892AB82FB3BF4715"
"FCFE6E82D03731FC3762B6AAC3DF1C3B"
"C646FE9CD3C62663A97EE72DB932A301"
"312B4A7633100C8CC357262C39A2B3A6"
"4B224F5276D5EDBDF0804DC3AC4B8351"
"62BB1969EAEBADC43D2511D6E0239287"
"81B167A48273B953378D3D2080CC0677"
"7E8A2364F0234B81064C5C739A8DA28D"
"C5889072BF37685CBC94C2D31D0179AD"
"86D8E3AA8090D4F0B281BE37E0143746"
"E6049CCC06899401264FA471C016A96C"
"79815B55BBC26B43052609D9D175FBCD"
"E455392F10E51EC162F51CF732E6BB39"
"1F56BBFD8D957DF3D4C55B71CEFD54B1"
"9C16D458757373E698D7E693A8FC3981"
"5A8BF03BA05EA8C8778D38F9873D62B4"
"460F41ACF997C30E7C3AF025FA171B5F"
"5AD4D6B15E95C27F6B35AD61875E5505"
"449B4E";
static const DWORD KeywordSize2 = sizeof(Keyword2) - 1;
static const uint8_t Keyword3[] = {
0x59, 0x08, 0x01, 0x00
};
static const DWORD KeywordSize3 = sizeof(Keyword3);
static const CHAR Keyword4[] = "92933";
static const DWORD KeywordSize4 = sizeof(Keyword4) - 1;
static DWORD KeywordOffset[5] = { -1, -1, -1, -1, -1 };
static LPCTSTR TargetName = TEXT("libcc.dll");
static HANDLE hTarget = INVALID_HANDLE_VALUE;
static HANDLE hTargetMap = NULL;
static PVOID lpFileContent = NULL;
BOOL Init(const std::Tstring& Path) {
BOOL bSuccess = FALSE;
DWORD dwLastError = ERROR_SUCCESS;
DWORD attr = INVALID_FILE_ATTRIBUTES;
attr = GetFileAttributes(Path.c_str());
if (attr == INVALID_FILE_ATTRIBUTES) {
dwLastError = GetLastError();
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("Failed @ GetFileAttributes. CODE: 0x%08X\n"), dwLastError);
goto ON_Init_ERROR;
}
if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("Error: Path is not a directory.\n"));
goto ON_Init_ERROR;
}
InstallationPath = Path;
if (InstallationPath.back() != TEXT('\\') && InstallationPath.back() != TEXT('/'))
InstallationPath.push_back(TEXT('\\'));
bSuccess = TRUE;
ON_Init_ERROR:
return bSuccess;
}
BOOL CheckKey(RSACipher* cipher) {
BOOL bOk = FALSE;
std::string RSAPublicKeyPEM;
RSAPublicKeyPEM = cipher->ExportKeyString<RSACipher::KeyType::PublicKey, RSACipher::KeyFormat::PEM>();
if (RSAPublicKeyPEM.empty()) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("ERROR: cipher->ExportKeyString failed.\n"));
return FALSE;
}
[](std::string& str, const std::string& OldSub, const std::string& NewSub) {
std::string::size_type pos = 0;
std::string::size_type srclen = OldSub.size();
std::string::size_type dstlen = NewSub.size();
while ((pos = str.find(OldSub, pos)) != std::string::npos) {
str.replace(pos, srclen, NewSub);
pos += dstlen;
}
} (RSAPublicKeyPEM, "\n", "\r\n"); // replace '\n' to '\r\n'
std::string encrypted_pem_text = EncryptPublicKey(RSAPublicKeyPEM.c_str(),
RSAPublicKeyPEM.length());
if (encrypted_pem_text[160] > '9' || encrypted_pem_text[160] < '1')
return FALSE;
for (int i = 1; i < 8; ++i)
if (encrypted_pem_text[160 + i] > '9' || encrypted_pem_text[160 + i] < '0')
return FALSE;
if (encrypted_pem_text[910] > '9' || encrypted_pem_text[910] < '1')
return FALSE;
for (int i = 1; i < 5; ++i)
if (encrypted_pem_text[910 + i] > '9' || encrypted_pem_text[910 + i] < '0')
return FALSE;
return TRUE;
}
static PIMAGE_SECTION_HEADER ImageSectionHeader(PVOID lpBase, LPCSTR lpSectionName) {
IMAGE_DOS_HEADER* pFileHeader = NULL;
IMAGE_NT_HEADERS* pNtHeader = NULL;
IMAGE_SECTION_HEADER* pSectionHeaders = NULL;
pFileHeader = (IMAGE_DOS_HEADER*)lpBase;
if (pFileHeader->e_magic != IMAGE_DOS_SIGNATURE)
return NULL;
pNtHeader = (IMAGE_NT_HEADERS*)((BYTE*)lpBase + pFileHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
return NULL;
pSectionHeaders = (IMAGE_SECTION_HEADER*)((BYTE*)pNtHeader +
offsetof(IMAGE_NT_HEADERS, OptionalHeader) +
pNtHeader->FileHeader.SizeOfOptionalHeader);
for (WORD i = 0; i < pNtHeader->FileHeader.NumberOfSections; ++i)
if (_stricmp((const char*)pSectionHeaders[i].Name, lpSectionName) == 0)
return pSectionHeaders + i;
return NULL;
}
BOOL FindTargetFile() {
DWORD dwLastError = ERROR_SUCCESS;
std::Tstring&& TargetFileName = InstallationPath + TargetName;
hTarget = CreateFile(TargetFileName.c_str(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hTarget == INVALID_HANDLE_VALUE) {
dwLastError = GetLastError();
if (dwLastError == ERROR_FILE_NOT_FOUND) {
return FALSE;
} else {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("Unexpected Error @ CreateFile. CODE: 0x%08X\n"), dwLastError);
return FALSE;
}
}
return TRUE;
}
BOOL FindOffset() {
BOOL bSuccess = FALSE;
DWORD dwLastError = ERROR_SUCCESS;
IMAGE_SECTION_HEADER* textSection = NULL;
IMAGE_SECTION_HEADER* rdataSection = NULL;
hTargetMap = CreateFileMapping(hTarget,
NULL,
PAGE_READWRITE,
0,
0,
NULL);
if (hTargetMap == NULL) {
dwLastError = GetLastError();
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("Failed @ CreateFileMapping. CODE: 0x%08X\n"), dwLastError);
goto ON_FindOffset_ERROR;
}
lpFileContent = MapViewOfFile(hTargetMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
if (lpFileContent == NULL) {
dwLastError = GetLastError();
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("Failed @ MapViewOfFile. CODE: 0x%08X\n"), dwLastError);
goto ON_FindOffset_ERROR;
}
textSection = ImageSectionHeader(lpFileContent, ".text");
if (textSection == NULL) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("ERROR: Cannot find .text section.\n"));
goto ON_FindOffset_ERROR;
}
rdataSection = ImageSectionHeader(lpFileContent, ".rdata");
if (textSection == NULL) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("ERROR: Cannot find .rdata section.\n"));
goto ON_FindOffset_ERROR;
}
// -------------------------
// try to search keyword0
// -------------------------
for (DWORD i = 0; i < rdataSection->SizeOfRawData; ++i) {
if (memcmp((uint8_t*)lpFileContent + rdataSection->PointerToRawData + i, Keyword0, KeywordSize0) == 0) {
KeywordOffset[0] = rdataSection->PointerToRawData + i;
break;
}
}
if (KeywordOffset[0] == -1) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("ERROR: Cannot find Keyword0.\n"));
goto ON_FindOffset_ERROR;
} else {
_tprintf_s(TEXT("Keyword0 has been found: offset = +0x%08X.\n"), KeywordOffset[0]);
}
// -------------------------
// try to search keyword1
// -------------------------
for (DWORD i = 0; i < textSection->SizeOfRawData; ++i) {
if (memcmp((uint8_t*)lpFileContent + textSection->PointerToRawData + i, Keyword1, KeywordSize1) == 0) {
KeywordOffset[1] = textSection->PointerToRawData + i;
break;
}
}
if (KeywordOffset[1] == -1) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("ERROR: Cannot find Keyword1.\n"));
goto ON_FindOffset_ERROR;
} else {
_tprintf_s(TEXT("Keyword1 has been found: offset = +0x%08X.\n"), KeywordOffset[1]);
}
// -------------------------
// try to search keyword2
// -------------------------
for (DWORD i = 0; i < rdataSection->SizeOfRawData; ++i) {
if (memcmp((uint8_t*)lpFileContent + rdataSection->PointerToRawData + i, Keyword2, KeywordSize2) == 0) {
KeywordOffset[2] = rdataSection->PointerToRawData + i;
break;
}
}
if (KeywordOffset[2] == -1) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("ERROR: Cannot find Keyword2.\n"));
goto ON_FindOffset_ERROR;
} else {
_tprintf_s(TEXT("Keyword2 has been found: offset = +0x%08X.\n"), KeywordOffset[2]);
}
// -------------------------
// try to search keyword3
// -------------------------
for (DWORD i = 0; i < textSection->SizeOfRawData; ++i) {
if (memcmp((uint8_t*)lpFileContent + textSection->PointerToRawData + i, Keyword3, KeywordSize3) == 0) {
KeywordOffset[3] = textSection->PointerToRawData + i;
break;
}
}
if (KeywordOffset[3] == -1) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("ERROR: Cannot find Keyword3.\n"));
goto ON_FindOffset_ERROR;
} else {
_tprintf_s(TEXT("Keyword3 has been found: offset = +0x%08X.\n"), KeywordOffset[3]);
}
// -------------------------
// try to search keyword4
// -------------------------
for (DWORD i = 0; i < rdataSection->SizeOfRawData; ++i) {
if (memcmp((uint8_t*)lpFileContent + rdataSection->PointerToRawData + i, Keyword4, KeywordSize4) == 0) {
KeywordOffset[4] = rdataSection->PointerToRawData + i;
break;
}
}
if (KeywordOffset[4] == -1) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("ERROR: Cannot find Keyword4.\n"));
goto ON_FindOffset_ERROR;
} else {
_tprintf_s(TEXT("Keyword4 has been found: offset = +0x%08X.\n"), KeywordOffset[4]);
}
bSuccess = TRUE;
ON_FindOffset_ERROR:
return bSuccess;
}
BOOL BackupFile() {
BOOL bSuccess = FALSE;
DWORD dwLastError = ERROR_SUCCESS;
std::Tstring&& TargetFileName = InstallationPath + TargetName;
std::Tstring&& BackupFileName = InstallationPath + TargetName + TEXT(".backup");
if (!CopyFile(TargetFileName.c_str(), BackupFileName.c_str(), TRUE)) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("Failed @ CopyFile. CODE: 0x%08X\n"), dwLastError);
goto ON_BackupFile_ERROR;
}
bSuccess = TRUE;
ON_BackupFile_ERROR:
return bSuccess;
}
BOOL Do(RSACipher* cipher) {
std::string RSAPublicKeyPEM;
std::string encrypted_pem_pubkey;
RSAPublicKeyPEM = cipher->ExportKeyString<RSACipher::KeyType::PublicKey, RSACipher::KeyFormat::PEM>();
if (RSAPublicKeyPEM.empty()) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("ERROR: cipher->ExportKeyString failed.\n"));
return FALSE;
}
[](std::string& str, const std::string& OldSub, const std::string& NewSub) {
std::string::size_type pos = 0;
std::string::size_type srclen = OldSub.size();
std::string::size_type dstlen = NewSub.size();
while ((pos = str.find(OldSub, pos)) != std::string::npos) {
str.replace(pos, srclen, NewSub);
pos += dstlen;
}
} (RSAPublicKeyPEM, "\n", "\r\n"); // replace '\n' to '\r\n'
encrypted_pem_pubkey = EncryptPublicKey(RSAPublicKeyPEM.c_str(), RSAPublicKeyPEM.length());
// split encrypted_pem_pubkey to 5 part: |160 chars|8 chars|742 chars|5 chars|5 chars|
// | |
// \ / \ /
// imm1 imm3
std::string encrypted_pem_pubkey0(encrypted_pem_pubkey.begin(), encrypted_pem_pubkey.begin() + 160);
std::string encrypted_pem_pubkey1(encrypted_pem_pubkey.begin() + 160, encrypted_pem_pubkey.begin() + 160 + 8);
std::string encrypted_pem_pubkey2(encrypted_pem_pubkey.begin() + 160 + 8, encrypted_pem_pubkey.begin() + 160 + 8 + 742);
std::string encrypted_pem_pubkey3(encrypted_pem_pubkey.begin() + 160 + 8 + 742, encrypted_pem_pubkey.begin() + 160 + 8 + 742 + 5);
std::string encrypted_pem_pubkey4(encrypted_pem_pubkey.begin() + 160 + 8 + 742 + 5, encrypted_pem_pubkey.end());
uint32_t imm1 = std::stoul(encrypted_pem_pubkey1.c_str());
uint32_t imm3 = std::stoul(encrypted_pem_pubkey3.c_str());
_tprintf_s(TEXT("\n"));
_tprintf_s(TEXT("@Offset +0x%08X, write string:\n"), KeywordOffset[0]);
printf_s("\"%s\"\n\n", encrypted_pem_pubkey0.c_str());
memcpy((uint8_t*)lpFileContent + KeywordOffset[0], encrypted_pem_pubkey0.c_str(), 160);
_tprintf_s(TEXT("@Offset +0x%08X, write uint32_t:\n"), KeywordOffset[1]);
printf_s("0x%08X\n\n", imm1);
memcpy((uint8_t*)lpFileContent + KeywordOffset[1], &imm1, sizeof(uint32_t));
_tprintf_s(TEXT("@Offset +0x%08X, write string:\n"), KeywordOffset[2]);
printf_s("\"%s\"\n\n", encrypted_pem_pubkey2.c_str());
memcpy((uint8_t*)lpFileContent + KeywordOffset[2], encrypted_pem_pubkey2.c_str(), 742);
_tprintf_s(TEXT("@Offset +0x%08X, write uint32_t:\n"), KeywordOffset[3]);
printf_s("0x%08X\n\n", imm3);
memcpy((uint8_t*)lpFileContent + KeywordOffset[3], &imm3, sizeof(uint32_t));
_tprintf_s(TEXT("@Offset +0x%08X, write string:\n"), KeywordOffset[4]);
printf_s("\"%s\"\n\n", encrypted_pem_pubkey4.c_str());
memcpy((uint8_t*)lpFileContent + KeywordOffset[4], encrypted_pem_pubkey4.c_str(), 5);
return TRUE;
}
VOID Finalize() {
if (lpFileContent) {
UnmapViewOfFile(lpFileContent);
lpFileContent = NULL;
}
if (hTargetMap) {
CloseHandle(hTargetMap);
hTargetMap = NULL;
}
if (hTarget) {
CloseHandle(hTarget);
hTarget = INVALID_HANDLE_VALUE;
}
}
}
+444 -151
View File
@@ -1,166 +1,459 @@
#include "def.hpp"
#include <tchar.h>
#include <stdio.h>
#include <windows.h>
bool ConvertToUTF8(LPCSTR from, std::string& to) {
bool bSuccess = false;
int len = 0;
LPWSTR lpUnicodeString = nullptr;
#include <Exception.hpp>
#include <ExceptionWin32.hpp>
#include <ResourceOwned.hpp>
#include <ResourceTraitsWin32.hpp>
#include "ImageInterpreter.hpp"
#include "PatchSolutions.hpp"
#include "Misc.hpp"
len = MultiByteToWideChar(CP_ACP, NULL, from, -1, NULL, 0);
if (len == 0)
goto ON_ConvertToUTF8_0_ERROR;
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE
#define NKG_CURRENT_SOURCE_FILE() TEXT(".\\navicat-patcher\\_tmain.cpp")
#define NKG_CURRENT_SOURCE_LINE() __LINE__
lpUnicodeString = reinterpret_cast<LPWSTR>(HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
len * sizeof(WCHAR)));
if (lpUnicodeString == nullptr)
goto ON_ConvertToUTF8_0_ERROR;
if (!MultiByteToWideChar(CP_ACP, NULL, from, -1, lpUnicodeString, len))
goto ON_ConvertToUTF8_0_ERROR;
len = WideCharToMultiByte(CP_UTF8, NULL, lpUnicodeString, -1, NULL, 0, NULL, NULL);
if (len == 0)
goto ON_ConvertToUTF8_0_ERROR;
to.resize(len);
if (!WideCharToMultiByte(CP_UTF8, NULL, lpUnicodeString, -1, to.data(), len, NULL, NULL))
goto ON_ConvertToUTF8_0_ERROR;
while (to.back() == 0)
to.pop_back();
bSuccess = true;
ON_ConvertToUTF8_0_ERROR:
if (lpUnicodeString)
HeapFree(GetProcessHeap(), NULL, lpUnicodeString);
return bSuccess;
static void Welcome() {
_putts(TEXT("***************************************************"));
_putts(TEXT("* Navicat Patcher by @DoubleLabyrinth *"));
_putts(TEXT("* Version: 4.1 *"));
_putts(TEXT("***************************************************"));
_putts(TEXT(""));
_putts(TEXT("Press Enter to continue or Ctrl + C to abort."));
auto c = _gettchar();
while (c != TEXT('\n') && _gettchar() != TEXT('\n')) {}
}
bool ConvertToUTF8(LPCWSTR from, std::string& to) {
bool bSuccess = false;
int len = 0;
len = WideCharToMultiByte(CP_UTF8, NULL, from, -1, NULL, 0, NULL, NULL);
if (len == 0)
goto ON_ConvertToUTF8_1_ERROR;
to.resize(len);
if (!WideCharToMultiByte(CP_UTF8, NULL, from, -1, to.data(), len, NULL, NULL))
goto ON_ConvertToUTF8_1_ERROR;
while (to.back() == 0)
to.pop_back();
bSuccess = true;
ON_ConvertToUTF8_1_ERROR:
return bSuccess;
static void Help() {
_putts(TEXT("***************************************************"));
_putts(TEXT("* Navicat Patcher by @DoubleLabyrinth *"));
_putts(TEXT("* Version: 4.1 *"));
_putts(TEXT("***************************************************"));
_putts(TEXT(""));
_putts(TEXT("Usage:"));
_putts(TEXT(" navicat-patcher.exe [-dry-run] <Navicat Installation Path> [RSA-2048 PEM File Path]"));
_putts(TEXT(""));
_putts(TEXT(" [-dry-run] Run patcher without applying any patches."));
_putts(TEXT(" This parameter is optional."));
_putts(TEXT(""));
_putts(TEXT(" <Navicat Installation Path> The folder path where Navicat is installed."));
_putts(TEXT(" This parameter must be specified."));
_putts(TEXT(""));
_putts(TEXT(" [RSA-2048 PEM File Path] The path to an RSA-2048 private key file."));
_putts(TEXT(" This parameter is optional."));
_putts(TEXT(" If not specified, an RSA-2048 private key file"));
_putts(TEXT(" named \"RegPrivateKey.pem\" will be generated."));
_putts(TEXT(""));
_putts(TEXT("Example:"));
_putts(TEXT(" navicat-patcher.exe \"C:\\Program Files\\PremiumSoft\\Navicat Premium 12\""));
}
bool ConvertToUTF8(std::string& str) {
bool bSuccess = false;
std::string temp;
bSuccess = ConvertToUTF8(str.c_str(), temp);
if (!bSuccess)
return false;
str = temp;
return true;
}
int _tmain(int argc, TCHAR* argv[]) {
if (argc != 2 && argc != 3) {
_tprintf_s(TEXT("Usage:\n"));
_tprintf_s(TEXT(" navicat-patcher.exe <Navicat installation path> [RSA-2048 PEM file]\n"));
return 0;
}
RSACipher* cipher = NULL;
cipher = RSACipher::Create();
if (cipher == NULL) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("RSACipher::Create failed.\n"));
goto ON_tmain_ERROR;
}
if (!patcher::Solution0::Init(argv[1]))
goto ON_tmain_ERROR;
if (!patcher::Solution1::Init(argv[1]))
goto ON_tmain_ERROR;
if (argc == 3) {
std::string PrivateKeyFileName;
if (!ConvertToUTF8(argv[2], PrivateKeyFileName)) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("ERROR: ConvertToUTF8 failed.\n"));
goto ON_tmain_ERROR;
static bool ParseCommandLine(int argc, PTSTR argv[], bool& bDryRun, std::xstring& NavInstallPath, std::xstring& RsaPrivateKeyPath) {
if (argc == 2) {
bDryRun = false;
NavInstallPath = argv[1];
RsaPrivateKeyPath.clear();
return true;
} else if (argc == 3) {
if (_tcsicmp(argv[1], TEXT("-dry-run")) == 0) {
bDryRun = true;
NavInstallPath = argv[2];
RsaPrivateKeyPath.clear();
return true;
} else {
bDryRun = false;
NavInstallPath = argv[1];
RsaPrivateKeyPath = argv[2];
return true;
}
if (!cipher->ImportKeyFromFile<RSACipher::KeyType::PrivateKey, RSACipher::KeyFormat::PEM>(PrivateKeyFileName)) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("ERROR: cipher->ImportKeyFromFile failed.\n"));
goto ON_tmain_ERROR;
}
if (patcher::Solution0::CheckKey(cipher) == FALSE || patcher::Solution1::CheckKey(cipher) == FALSE) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("ERROR: RSA private key specified cannot be used.\n"));
goto ON_tmain_ERROR;
} else if (argc == 4) {
if (_tcsicmp(argv[1], TEXT("-dry-run")) == 0) {
bDryRun = true;
NavInstallPath = argv[2];
RsaPrivateKeyPath = argv[3];
return true;
} else {
return false;
}
} else {
return false;
}
}
static void SelectPatchSolutions(
ResourceOwned<CppObjectTraits<nkg::PatchSolution>>& lpSolution0,
ResourceOwned<CppObjectTraits<nkg::PatchSolution>>& lpSolution1,
ResourceOwned<CppObjectTraits<nkg::PatchSolution>>& lpSolution2,
ResourceOwned<CppObjectTraits<nkg::PatchSolution>>& lpSolution3)
{
// if RSA public is detected in libcc.dll, don't patch main application to keep digital signature valid.
if ((lpSolution1.IsValid() || lpSolution2.IsValid() || lpSolution3.IsValid()) && lpSolution0.IsValid()) {
LOG_HINT(0, "PatchSolution0 is suppressed in order to keep digital signature valid.");
lpSolution0.Release();
}
}
static void NavicatBackupDetect(const std::xstring& FilePath) {
if (std::xstring BackupPath = FilePath + TEXT(".backup"); nkg::IsValidFilePath(BackupPath.c_str()) == true) {
while (true) {
LOG_SELECT(0, "Previous backup %s detected. Delete? (y/n)", BackupPath.c_str());
auto select = _gettchar();
while (select != TEXT('\n') && _gettchar() != TEXT('\n')) {}
if (select == TEXT('Y') || select == TEXT('y')) {
if (!DeleteFile(BackupPath.c_str())) {
throw nkg::Win32Error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), TEXT("Failed to delete backup file."));
} else {
break;
}
} else if (select == TEXT('N') || select == TEXT('n')) {
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Backup file still existed. Patch abort!"));
} else {
continue;
}
}
_putts(TEXT(""));
}
}
static void NavicatBackupMake(const std::xstring& FilePath) {
std::xstring BackupPath = FilePath + TEXT(".backup");
if (CopyFile(FilePath.c_str(), BackupPath.c_str(), TRUE) == FALSE) {
throw nkg::Win32Error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), TEXT("CopyFile failed."));
}
}
static void LoadKey(
nkg::RSACipher& Cipher, const std::xstring& KeyFilePath,
nkg::PatchSolution* pSolution0,
nkg::PatchSolution* pSolution1,
nkg::PatchSolution* pSolution2,
nkg::PatchSolution* pSolution3,
nkg::PatchSolution* pSolution4)
{
if (KeyFilePath.empty() == false) {
LOG_HINT(0, "Import RSA-2048 key from %s", KeyFilePath.c_str());
Cipher.ImportKeyFromFile<nkg::RSAKeyType::PrivateKey, nkg::RSAKeyFormat::PEM>(KeyFilePath);
if (pSolution0 && !pSolution0->CheckKey(Cipher) ||
pSolution1 && !pSolution1->CheckKey(Cipher) ||
pSolution2 && !pSolution2->CheckKey(Cipher) ||
pSolution3 && !pSolution3->CheckKey(Cipher) ||
pSolution4 && !pSolution4->CheckKey(Cipher))
{
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("The RSA private key you provide cannot be used."));
}
} else {
LOG_HINT(0, "Generating new RSA private key, it may take a long time...");
do {
cipher->GenerateKey(2048);
} while (patcher::Solution0::CheckKey(cipher) && patcher::Solution1::CheckKey(cipher));
cipher->ExportKeyToFile<RSACipher::KeyType::PrivateKey, RSACipher::KeyFormat::PEM>("RegPrivateKey.pem");
_tprintf_s(TEXT("New RSA private key has been saved to RegPrivateKey.pem.\n"));
Cipher.GenerateKey(2048);
} while (pSolution0 && !pSolution0->CheckKey(Cipher) ||
pSolution1 && !pSolution1->CheckKey(Cipher) ||
pSolution2 && !pSolution2->CheckKey(Cipher) ||
pSolution3 && !pSolution3->CheckKey(Cipher) ||
pSolution4 && !pSolution4->CheckKey(Cipher)); // re-generate RSA key if one of 'CheckKey's return false
}
// ------------------
// begin Solution0
// ------------------
if (!patcher::Solution0::FindTargetFile()) {
_tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
_tprintf_s(TEXT("ERROR: Cannot find main program. Are you sure the path you specified is correct?\n"));
goto ON_tmain_ERROR;
LOG_HINT(0, "Your RSA public key:\n%hs", Cipher.ExportKeyString<nkg::RSAKeyType::PublicKey, nkg::RSAKeyFormat::PEM>().c_str());
}
int _tmain(int argc, PTSTR argv[]) {
bool bDryRun;
std::xstring NavInstallPath;
std::xstring RsaPrivateKeyPath;
if (ParseCommandLine(argc, argv, bDryRun, NavInstallPath, RsaPrivateKeyPath) == false) {
Help();
return -1;
} else {
Welcome();
try {
if (nkg::IsValidDirectoryPath(NavInstallPath.c_str()) == false) {
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Navicat installation path doesn't point to a directory."))
.AddHint(TEXT("Are you sure the path you specified is correct?"))
.AddHint(std::xstring::format(TEXT("The path you specified: %s"), NavInstallPath.c_str()));
}
if (RsaPrivateKeyPath.empty() == false && nkg::IsValidFilePath(RsaPrivateKeyPath.c_str()) == false) {
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("RSA key file path doesn't point to a file."))
.AddHint(TEXT("Are you sure the path you specified is correct?"))
.AddHint(std::xstring::format(TEXT("The path you specified: %s"), RsaPrivateKeyPath.c_str()));
}
while (NavInstallPath.back() == TEXT('\\') || NavInstallPath.back() == TEXT('/')) {
NavInstallPath.pop_back();
}
NavInstallPath.push_back(nkg::IsWineEnvironment() ? TEXT('/') : TEXT('\\'));
nkg::RSACipher Cipher;
std::xstring MainExePath;
ResourceOwned hMainExe(FileHandleTraits{});
ResourceOwned hMainExeMapping(GenericHandleTraits{});
ResourceOwned lpMainExeMapping(MapViewHandleTraits{});
ResourceOwned lpMainExeInterpreter(CppObjectTraits<nkg::ImageInterpreter>{});
std::xstring LibccDllPath;
ResourceOwned hLibccDll(FileHandleTraits{});
ResourceOwned hLibccDllMapping(GenericHandleTraits{});
ResourceOwned lpLibccDllMapping(MapViewHandleTraits{});
ResourceOwned lpLibccDllInterpreter(CppObjectTraits<nkg::ImageInterpreter>{});
ResourceOwned lpSolution0(CppObjectTraits<nkg::PatchSolution>{});
ResourceOwned lpSolution1(CppObjectTraits<nkg::PatchSolution>{});
ResourceOwned lpSolution2(CppObjectTraits<nkg::PatchSolution>{});
ResourceOwned lpSolution3(CppObjectTraits<nkg::PatchSolution>{});
ResourceOwned lpSolution4(CppObjectTraits<nkg::PatchSolution>{});
//
// Open main application
//
do {
MainExePath = NavInstallPath + TEXT("Navicat.exe");
hMainExe.TakeOver(
CreateFile(MainExePath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)
);
if (hMainExe.IsValid()) {
LOG_SUCCESS(0, "Try to open Navicat.exe ... Ok!");
break;
} else if (GetLastError() == ERROR_FILE_NOT_FOUND) {
LOG_FAILURE(0, "Try to open Navicat.exe ... Not found!");
} else {
throw nkg::Win32Error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), TEXT("Failed to open Navicat.exe"));
}
MainExePath = NavInstallPath + TEXT("Modeler.exe");
hMainExe.TakeOver(
CreateFile(MainExePath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)
);
if (hMainExe.IsValid()) {
LOG_SUCCESS(0, "Try to open Modeler.exe ... Ok!");
break;
} else if (GetLastError() == ERROR_FILE_NOT_FOUND) {
LOG_FAILURE(0, "Try to open Modeler.exe ... Not found!");
} else {
throw nkg::Win32Error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), TEXT("Failed to open Modeler.exe"));
}
MainExePath = NavInstallPath + TEXT("Rviewer.exe");
hMainExe.TakeOver(
CreateFile(MainExePath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)
);
if (hMainExe.IsValid()) {
LOG_SUCCESS(0, "Try to open Rviewer.exe ... Ok!");
break;
} else if (GetLastError() == ERROR_FILE_NOT_FOUND) {
LOG_FAILURE(0, "Try to open Rviewer.exe ... Not found!");
} else {
throw nkg::Win32Error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), TEXT("Failed to open Rviewer.exe"));
}
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Main application is not found."))
.AddHint(TEXT("Are you sure you specified a valid Navicat installation path?"))
.AddHint(std::xstring::format(TEXT("The path you specified: %s"), NavInstallPath.c_str()));
} while (false);
//
// Open libcc.dll, if have
//
do {
LibccDllPath = NavInstallPath + TEXT("libcc.dll");
hLibccDll.TakeOver(
CreateFile(LibccDllPath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)
);
if (hLibccDll.IsValid()) {
LOG_SUCCESS(0, "Try to open libcc.dll ... Ok!");
break;
} else if (GetLastError() == ERROR_FILE_NOT_FOUND) {
LOG_FAILURE(0, "Try to open libcc.dll ... Not found!");
} else {
throw nkg::Win32Error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), TEXT("Failed to open libcc.dll"));
}
} while (false);
_putts(TEXT(""));
//
// Map main application
//
hMainExeMapping.TakeOver(CreateFileMapping(hMainExe, NULL, PAGE_READWRITE, 0, 0, NULL));
if (hMainExeMapping.IsValid() == false) {
throw nkg::Win32Error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), TEXT("CreateFileMapping failed."));
}
lpMainExeMapping.TakeOver(MapViewOfFile(hMainExeMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0));
if (hMainExeMapping.IsValid() == false) {
throw nkg::Win32Error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), TEXT("MapViewOfFile failed."));
}
lpMainExeInterpreter.TakeOver(
new nkg::ImageInterpreter(nkg::ImageInterpreter::ParseImage(lpMainExeMapping))
);
lpSolution0.TakeOver(new nkg::PatchSolution0(lpMainExeInterpreter));
//
// Map libcc.dll, if have
//
if (hLibccDll.IsValid()) {
hLibccDllMapping.TakeOver(CreateFileMapping(hLibccDll, NULL, PAGE_READWRITE, 0, 0, NULL));
if (hMainExeMapping.IsValid() == false) {
throw nkg::Win32Error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), TEXT("CreateFileMapping failed."));
}
lpLibccDllMapping.TakeOver(MapViewOfFile(hLibccDllMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0));
if (hMainExeMapping.IsValid() == false) {
throw nkg::Win32Error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), GetLastError(), TEXT("MapViewOfFile failed."));
}
lpLibccDllInterpreter.TakeOver(
new nkg::ImageInterpreter(nkg::ImageInterpreter::ParseImage(lpLibccDllMapping))
);
lpSolution1.TakeOver(new nkg::PatchSolution1(lpLibccDllInterpreter));
lpSolution2.TakeOver(new nkg::PatchSolution2(lpLibccDllInterpreter));
lpSolution3.TakeOver(new nkg::PatchSolution3(lpLibccDllInterpreter));
lpSolution4.TakeOver(new nkg::PatchSolution4(lpLibccDllInterpreter));
}
//
// Finding patch offsets
//
if (lpSolution0->FindPatchOffset() == false) {
lpSolution0.Release();
}
if (lpSolution1.IsValid() && lpSolution1->FindPatchOffset() == false) {
lpSolution1.Release();
}
if (lpSolution2.IsValid() && lpSolution2->FindPatchOffset() == false) {
lpSolution2.Release();
}
if (lpSolution3.IsValid() && lpSolution3->FindPatchOffset() == false) {
lpSolution3.Release();
}
if (lpSolution4.IsValid() && lpSolution4->FindPatchOffset() == false) {
lpSolution4.Release();
}
_putts(TEXT(""));
//
// decide which solutions will be applied
//
SelectPatchSolutions(lpSolution0, lpSolution1, lpSolution2, lpSolution3);
if (lpSolution0.IsValid() == false && lpSolution1.IsValid() == false && lpSolution2.IsValid() == false && lpSolution3.IsValid() == false && lpSolution4.IsValid() == false) {
throw nkg::Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("No patch applied. Patch abort!"))
.AddHint(TEXT("Are you sure your Navicat has not been patched/modified before?"));
}
_putts(TEXT(""));
//
// detecting backups
//
if (lpSolution0.IsValid()) {
NavicatBackupDetect(MainExePath);
}
if (lpSolution1.IsValid() || lpSolution2.IsValid() || lpSolution3.IsValid() || lpSolution4.IsValid()) {
NavicatBackupDetect(LibccDllPath);
}
//
// Loading key
//
LoadKey(Cipher, RsaPrivateKeyPath, lpSolution0, lpSolution1, lpSolution2, lpSolution3, lpSolution4);
if (bDryRun == false) {
//
// Saving private key if not given
//
if (RsaPrivateKeyPath.empty()) {
Cipher.ExportKeyToFile<nkg::RSAKeyType::PrivateKey, nkg::RSAKeyFormat::PEM>(std::xstring{ std::xstring_extension{}, "RegPrivateKey.pem" });
}
//
// Making backups
//
if (lpSolution0.IsValid()) {
NavicatBackupMake(MainExePath);
}
if (lpSolution1.IsValid() || lpSolution2.IsValid() || lpSolution3.IsValid() || lpSolution4.IsValid()) {
NavicatBackupMake(LibccDllPath);
}
//
// Making patch. No way to go back here :-)
//
if (lpSolution0.IsValid()) {
lpSolution0->MakePatch(Cipher);
}
if (lpSolution1.IsValid()) {
lpSolution1->MakePatch(Cipher);
}
if (lpSolution2.IsValid()) {
lpSolution2->MakePatch(Cipher);
}
if (lpSolution3.IsValid()) {
lpSolution3->MakePatch(Cipher);
}
if (lpSolution4.IsValid()) {
lpSolution4->MakePatch(Cipher);
}
if (RsaPrivateKeyPath.empty()) {
LOG_HINT(
0,
"New RSA-2048 private key has been saved to\n%s%cRegPrivateKey.pem",
nkg::GetCurrentWorkingDirectory().c_str(),
nkg::IsWineEnvironment() ? TEXT('/') : TEXT('\\')
);
_putts(TEXT(""));
}
_putts(TEXT("*******************************************************"));
_putts(TEXT("* PATCH HAS BEEN DONE SUCCESSFULLY! *"));
_putts(TEXT("* HAVE FUN AND ENJOY~ *"));
_putts(TEXT("*******************************************************"));
} else {
_putts(TEXT("*******************************************************"));
_putts(TEXT("* DRY-RUN MODE ENABLE! *"));
_putts(TEXT("* NO PATCH WILL BE APPLIED! *"));
_putts(TEXT("*******************************************************"));
}
return 0;
} catch (nkg::Exception& e) {
LOG_FAILURE(0, "%s:%zu ->", e.File(), e.Line());
LOG_FAILURE(4, "%s", e.Message());
if (e.HasErrorCode()) {
LOG_HINT(4, "%s (0x%zx)", e.ErrorString(), e.ErrorCode());
}
for (auto& Hint : e.Hints()) {
LOG_HINT(4, "Hint: %s", Hint.c_str());
}
return -1;
}
}
}
if (!patcher::Solution0::CheckFile())
goto ON_tmain_ERROR;
if (!patcher::Solution0::BackupFile())
goto ON_tmain_ERROR;
if (!patcher::Solution0::Do(cipher))
goto ON_tmain_ERROR;
_tprintf_s(TEXT("Solution0 has been done successfully.\n"));
_tprintf_s(TEXT("\n"));
// ------------------
// begin Solution1
// ------------------
if (!patcher::Solution1::FindTargetFile())
goto ON_tmain_ERROR;
if (!patcher::Solution1::FindOffset())
goto ON_tmain_ERROR;
if (!patcher::Solution1::BackupFile())
goto ON_tmain_ERROR;
if (!patcher::Solution1::Do(cipher))
goto ON_tmain_ERROR;
_tprintf_s(TEXT("Solution1 has been done successfully.\n"));
_tprintf_s(TEXT("\n"));
ON_tmain_ERROR:
patcher::Solution1::Finalize();
patcher::Solution0::Finalize();
delete cipher;
return 0;
}
-41
View File
@@ -1,41 +0,0 @@
#pragma once
#include <tchar.h>
#include <windows.h>
#include <string>
#include "RSACipher.hpp"
#pragma comment(lib, "version.lib") // GetFileVersionInfoSize, GetFileVersionInfo, VerQueryValue are in this lib
namespace std {
#ifdef UNICODE
typedef wstring Tstring;
#else
typedef string Tstring;
#endif // UNICODE
}
namespace patcher {
std::string EncryptPublicKey(const char* public_key, size_t len);
namespace Solution0 {
BOOL Init(const std::Tstring& Path);
BOOL CheckKey(RSACipher* cipher);
BOOL FindTargetFile();
BOOL CheckFile();
BOOL BackupFile();
BOOL Do(RSACipher* cipher);
VOID Finalize();
}
namespace Solution1 {
BOOL Init(const std::Tstring& Path);
BOOL CheckKey(RSACipher* cipher);
BOOL FindTargetFile();
BOOL FindOffset();
BOOL BackupFile();
BOOL Do(RSACipher* cipher);
VOID Finalize();
}
}
+79 -49
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -19,42 +19,50 @@
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{30BE8CAB-6137-4441-9F64-599D0A6EEA0C}</ProjectGuid>
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{7EE03EF3-D58D-4B53-913D-4A4DC8A29E34}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>navicatpatcher</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<VcpkgTriplet Condition="'$(Platform)'=='Win32'">x86-windows-static</VcpkgTriplet>
<VcpkgTriplet Condition="'$(Platform)'=='x64'">x64-windows-static</VcpkgTriplet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
<Import Project="..\common\common.vcxitems" Label="Shared" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
@@ -71,38 +79,33 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)openssl-lib\include;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)openssl-lib\lib;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
<IntDir>$(SolutionDir)obj\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir>
<OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)openssl-lib\include64;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)openssl-lib\lib64;$(LibraryPath)</LibraryPath>
<IntDir>$(SolutionDir)obj\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir>
<OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)openssl-lib\include;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)openssl-lib\lib;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
<IntDir>$(SolutionDir)obj\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir>
<OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)openssl-lib\include64;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)openssl-lib\lib64;$(LibraryPath)</LibraryPath>
<IntDir>$(SolutionDir)obj\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir>
<OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalOptions>/std:c++latest</AdditionalOptions>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -111,14 +114,13 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalOptions>/std:c++latest</AdditionalOptions>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -128,15 +130,14 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalOptions>/std:c++latest</AdditionalOptions>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -148,15 +149,14 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalOptions>/std:c++latest</AdditionalOptions>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -166,22 +166,52 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="EncryptPublicKey.cpp" />
<ClCompile Include="NavicatCrypto\aes.c" />
<ClCompile Include="NavicatCrypto\aes_constant.c" />
<ClCompile Include="NavicatCrypto\blowfish.c" />
<ClCompile Include="NavicatCrypto\sha1.c" />
<ClCompile Include="Solution0.cpp" />
<ClCompile Include="Solution1.cpp" />
<ClCompile Include="CapstoneDisassembler.cpp" />
<ClCompile Include="ImageInterpreter.cpp" />
<ClCompile Include="KeystoneAssembler.cpp" />
<ClCompile Include="Misc.cpp" />
<ClCompile Include="PatchSolution0.cpp" />
<ClCompile Include="PatchSolution1.cpp" />
<ClCompile Include="PatchSolution2-generic.cpp" />
<ClCompile Include="PatchSolution2-i386.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="PatchSolution2-amd64.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="PatchSolution3-amd64.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="PatchSolution3-generic.cpp" />
<ClCompile Include="PatchSolution3-i386.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="PatchSolution4-amd64.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="PatchSolution4-generic.cpp" />
<ClCompile Include="PatchSolution4-i386.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="_tmain.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="def.hpp" />
<ClInclude Include="NavicatCrypto\aes.h" />
<ClInclude Include="NavicatCrypto\blowfish.h" />
<ClInclude Include="NavicatCrypto\NavicatCrypto.hpp" />
<ClInclude Include="NavicatCrypto\sha1.h" />
<ClInclude Include="RSACipher.hpp" />
<ClInclude Include="CapstoneDisassembler.hpp" />
<ClInclude Include="ExceptionCapstone.hpp" />
<ClInclude Include="ExceptionKeystone.hpp" />
<ClInclude Include="ImageInterpreter.hpp" />
<ClInclude Include="KeystoneAssembler.hpp" />
<ClInclude Include="Misc.hpp" />
<ClInclude Include="NavicatCrypto.hpp" />
<ClInclude Include="PatchSolutions.hpp" />
<ClInclude Include="ResourceTraitsCapstone.hpp" />
<ClInclude Include="ResourceTraitsKeystone.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
+50 -14
View File
@@ -7,7 +7,7 @@
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
@@ -18,45 +18,81 @@
<ClCompile Include="_tmain.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="NavicatCrypto\aes.c">
<ClCompile Include="ImageInterpreter.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="NavicatCrypto\aes_constant.c">
<ClCompile Include="PatchSolution0.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="NavicatCrypto\blowfish.c">
<ClCompile Include="PatchSolution1.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="NavicatCrypto\sha1.c">
<ClCompile Include="PatchSolution2-i386.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="EncryptPublicKey.cpp">
<ClCompile Include="PatchSolution2-amd64.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Solution0.cpp">
<ClCompile Include="PatchSolution3-amd64.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Solution1.cpp">
<ClCompile Include="PatchSolution3-i386.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Misc.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="PatchSolution2-generic.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="PatchSolution3-generic.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="CapstoneDisassembler.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="PatchSolution4-generic.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="PatchSolution4-amd64.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="KeystoneAssembler.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="PatchSolution4-i386.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="NavicatCrypto\aes.h">
<ClInclude Include="NavicatCrypto.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="NavicatCrypto\blowfish.h">
<ClInclude Include="ImageInterpreter.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="NavicatCrypto\NavicatCrypto.hpp">
<ClInclude Include="CapstoneDisassembler.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="NavicatCrypto\sha1.h">
<ClInclude Include="ResourceTraitsCapstone.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="def.hpp">
<ClInclude Include="ExceptionCapstone.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="RSACipher.hpp">
<ClInclude Include="PatchSolutions.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="Misc.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="KeystoneAssembler.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="ExceptionKeystone.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="ResourceTraitsKeystone.hpp">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ShowAllFiles>true</ShowAllFiles>
</PropertyGroup>
</Project>
-2
View File
@@ -1,2 +0,0 @@
Please https://www.openssl.org/community/thanks.html for the current
acknowledgements.
-21
View File
@@ -1,21 +0,0 @@
Andy Polyakov
Ben Laurie
Bodo Möller
Emilia Käsper
Eric Young
Geoff Thorpe
Holger Reif
Kurt Roeckx
Lutz Jänicke
Mark J. Cox
Matt Caswell
Nils Larsch
Paul C. Sutton
Ralf S. Engelschall
Rich Salz
Richard Levitte
Stephen Henson
Steve Marquess
Tim Hudson
Ulf Möller
Viktor Dukhovni
File diff suppressed because it is too large Load Diff
-54
View File
@@ -1,54 +0,0 @@
HOW TO CONTRIBUTE PATCHES TO OpenSSL
------------------------------------
(Please visit https://www.openssl.org/community/getting-started.html for
other ideas about how to contribute.)
Development is coordinated on the openssl-dev mailing list (see the
above link or https://mta.openssl.org for information on subscribing).
If you are unsure as to whether a feature will be useful for the general
OpenSSL community you might want to discuss it on the openssl-dev mailing
list first. Someone may be already working on the same thing or there
may be a good reason as to why that feature isn't implemented.
To submit a patch, make a pull request on GitHub. If you think the patch
could use feedback from the community, please start a thread on openssl-dev
to discuss it.
Having addressed the following items before the PR will help make the
acceptance and review process faster:
1. Anything other than trivial contributions will require a contributor
licensing agreement, giving us permission to use your code. See
https://www.openssl.org/policies/cla.html for details.
2. All source files should start with the following text (with
appropriate comment characters at the start of each line and the
year(s) updated):
Copyright 20xx-20yy The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
https://www.openssl.org/source/license.html
3. Patches should be as current as possible; expect to have to rebase
often. We do not accept merge commits; You will be asked to remove
them before a patch is considered acceptable.
4. Patches should follow our coding style (see
https://www.openssl.org/policies/codingstyle.html) and compile without
warnings. Where gcc or clang is available you should use the
--strict-warnings Configure option. OpenSSL compiles on many varied
platforms: try to ensure you only use portable features.
Clean builds via Travis and AppVeyor are expected, and done whenever
a PR is created or updated.
5. When at all possible, patches should include tests. These can
either be added to an existing test, or completely new. Please see
test/README for information on the test framework.
6. New features or changed functionality must include
documentation. Please look at the "pod" files in doc/apps, doc/crypto
and doc/ssl for examples of our style.
-2
View File
@@ -1,2 +0,0 @@
The FAQ is now maintained on the web:
https://www.openssl.org/docs/faq.html
-125
View File
@@ -1,125 +0,0 @@
LICENSE ISSUES
==============
The OpenSSL toolkit stays under a double license, i.e. both the conditions of
the OpenSSL License and the original SSLeay license apply to the toolkit.
See below for the actual license texts.
OpenSSL License
---------------
/* ====================================================================
* Copyright (c) 1998-2017 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
Original SSLeay License
-----------------------
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
-856
View File
@@ -1,856 +0,0 @@
NEWS
====
This file gives a brief overview of the major changes between each OpenSSL
release. For more details please read the CHANGES file.
Major changes between OpenSSL 1.1.0e and OpenSSL 1.1.0f [25 May 2017]
o config now recognises 64-bit mingw and chooses mingw64 instead of mingw
Major changes between OpenSSL 1.1.0d and OpenSSL 1.1.0e [16 Feb 2017]
o Encrypt-Then-Mac renegotiation crash (CVE-2017-3733)
Major changes between OpenSSL 1.1.0c and OpenSSL 1.1.0d [26 Jan 2017]
o Truncated packet could crash via OOB read (CVE-2017-3731)
o Bad (EC)DHE parameters cause a client crash (CVE-2017-3730)
o BN_mod_exp may produce incorrect results on x86_64 (CVE-2017-3732)
Major changes between OpenSSL 1.1.0b and OpenSSL 1.1.0c [10 Nov 2016]
o ChaCha20/Poly1305 heap-buffer-overflow (CVE-2016-7054)
o CMS Null dereference (CVE-2016-7053)
o Montgomery multiplication may produce incorrect results (CVE-2016-7055)
Major changes between OpenSSL 1.1.0a and OpenSSL 1.1.0b [26 Sep 2016]
o Fix Use After Free for large message sizes (CVE-2016-6309)
Major changes between OpenSSL 1.1.0 and OpenSSL 1.1.0a [22 Sep 2016]
o OCSP Status Request extension unbounded memory growth (CVE-2016-6304)
o SSL_peek() hang on empty record (CVE-2016-6305)
o Excessive allocation of memory in tls_get_message_header()
(CVE-2016-6307)
o Excessive allocation of memory in dtls1_preprocess_fragment()
(CVE-2016-6308)
Major changes between OpenSSL 1.0.2h and OpenSSL 1.1.0 [25 Aug 2016]
o Copyright text was shrunk to a boilerplate that points to the license
o "shared" builds are now the default when possible
o Added support for "pipelining"
o Added the AFALG engine
o New threading API implemented
o Support for ChaCha20 and Poly1305 added to libcrypto and libssl
o Support for extended master secret
o CCM ciphersuites
o Reworked test suite, now based on perl, Test::Harness and Test::More
o *Most* libcrypto and libssl public structures were made opaque,
including:
BIGNUM and associated types, EC_KEY and EC_KEY_METHOD,
DH and DH_METHOD, DSA and DSA_METHOD, RSA and RSA_METHOD,
BIO and BIO_METHOD, EVP_MD_CTX, EVP_MD, EVP_CIPHER_CTX,
EVP_CIPHER, EVP_PKEY and associated types, HMAC_CTX,
X509, X509_CRL, X509_OBJECT, X509_STORE_CTX, X509_STORE,
X509_LOOKUP, X509_LOOKUP_METHOD
o libssl internal structures made opaque
o SSLv2 support removed
o Kerberos ciphersuite support removed
o RC4 removed from DEFAULT ciphersuites in libssl
o 40 and 56 bit cipher support removed from libssl
o All public header files moved to include/openssl, no more symlinking
o SSL/TLS state machine, version negotiation and record layer rewritten
o EC revision: now operations use new EC_KEY_METHOD.
o Support for OCB mode added to libcrypto
o Support for asynchronous crypto operations added to libcrypto and libssl
o Deprecated interfaces can now be disabled at build time either
relative to the latest release via the "no-deprecated" Configure
argument, or via the "--api=1.1.0|1.0.0|0.9.8" option.
o Application software can be compiled with -DOPENSSL_API_COMPAT=version
to ensure that features deprecated in that version are not exposed.
o Support for RFC6698/RFC7671 DANE TLSA peer authentication
o Change of Configure to use --prefix as the main installation
directory location rather than --openssldir. The latter becomes
the directory for certs, private key and openssl.cnf exclusively.
o Reworked BIO networking library, with full support for IPv6.
o New "unified" build system
o New security levels
o Support for scrypt algorithm
o Support for X25519
o Extended SSL_CONF support using configuration files
o KDF algorithm support. Implement TLS PRF as a KDF.
o Support for Certificate Transparency
o HKDF support.
Major changes between OpenSSL 1.0.2g and OpenSSL 1.0.2h [3 May 2016]
o Prevent padding oracle in AES-NI CBC MAC check (CVE-2016-2107)
o Fix EVP_EncodeUpdate overflow (CVE-2016-2105)
o Fix EVP_EncryptUpdate overflow (CVE-2016-2106)
o Prevent ASN.1 BIO excessive memory allocation (CVE-2016-2109)
o EBCDIC overread (CVE-2016-2176)
o Modify behavior of ALPN to invoke callback after SNI/servername
callback, such that updates to the SSL_CTX affect ALPN.
o Remove LOW from the DEFAULT cipher list. This removes singles DES from
the default.
o Only remove the SSLv2 methods with the no-ssl2-method option.
Major changes between OpenSSL 1.0.2f and OpenSSL 1.0.2g [1 Mar 2016]
o Disable weak ciphers in SSLv3 and up in default builds of OpenSSL.
o Disable SSLv2 default build, default negotiation and weak ciphers
(CVE-2016-0800)
o Fix a double-free in DSA code (CVE-2016-0705)
o Disable SRP fake user seed to address a server memory leak
(CVE-2016-0798)
o Fix BN_hex2bn/BN_dec2bn NULL pointer deref/heap corruption
(CVE-2016-0797)
o Fix memory issues in BIO_*printf functions (CVE-2016-0799)
o Fix side channel attack on modular exponentiation (CVE-2016-0702)
Major changes between OpenSSL 1.0.2e and OpenSSL 1.0.2f [28 Jan 2016]
o DH small subgroups (CVE-2016-0701)
o SSLv2 doesn't block disabled ciphers (CVE-2015-3197)
Major changes between OpenSSL 1.0.2d and OpenSSL 1.0.2e [3 Dec 2015]
o BN_mod_exp may produce incorrect results on x86_64 (CVE-2015-3193)
o Certificate verify crash with missing PSS parameter (CVE-2015-3194)
o X509_ATTRIBUTE memory leak (CVE-2015-3195)
o Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs
o In DSA_generate_parameters_ex, if the provided seed is too short,
return an error
Major changes between OpenSSL 1.0.2c and OpenSSL 1.0.2d [9 Jul 2015]
o Alternate chains certificate forgery (CVE-2015-1793)
o Race condition handling PSK identify hint (CVE-2015-3196)
Major changes between OpenSSL 1.0.2b and OpenSSL 1.0.2c [12 Jun 2015]
o Fix HMAC ABI incompatibility
Major changes between OpenSSL 1.0.2a and OpenSSL 1.0.2b [11 Jun 2015]
o Malformed ECParameters causes infinite loop (CVE-2015-1788)
o Exploitable out-of-bounds read in X509_cmp_time (CVE-2015-1789)
o PKCS7 crash with missing EnvelopedContent (CVE-2015-1790)
o CMS verify infinite loop with unknown hash function (CVE-2015-1792)
o Race condition handling NewSessionTicket (CVE-2015-1791)
Major changes between OpenSSL 1.0.2 and OpenSSL 1.0.2a [19 Mar 2015]
o OpenSSL 1.0.2 ClientHello sigalgs DoS fix (CVE-2015-0291)
o Multiblock corrupted pointer fix (CVE-2015-0290)
o Segmentation fault in DTLSv1_listen fix (CVE-2015-0207)
o Segmentation fault in ASN1_TYPE_cmp fix (CVE-2015-0286)
o Segmentation fault for invalid PSS parameters fix (CVE-2015-0208)
o ASN.1 structure reuse memory corruption fix (CVE-2015-0287)
o PKCS7 NULL pointer dereferences fix (CVE-2015-0289)
o DoS via reachable assert in SSLv2 servers fix (CVE-2015-0293)
o Empty CKE with client auth and DHE fix (CVE-2015-1787)
o Handshake with unseeded PRNG fix (CVE-2015-0285)
o Use After Free following d2i_ECPrivatekey error fix (CVE-2015-0209)
o X509_to_X509_REQ NULL pointer deref fix (CVE-2015-0288)
o Removed the export ciphers from the DEFAULT ciphers
Major changes between OpenSSL 1.0.1l and OpenSSL 1.0.2 [22 Jan 2015]:
o Suite B support for TLS 1.2 and DTLS 1.2
o Support for DTLS 1.2
o TLS automatic EC curve selection.
o API to set TLS supported signature algorithms and curves
o SSL_CONF configuration API.
o TLS Brainpool support.
o ALPN support.
o CMS support for RSA-PSS, RSA-OAEP, ECDH and X9.42 DH.
Major changes between OpenSSL 1.0.1k and OpenSSL 1.0.1l [15 Jan 2015]
o Build fixes for the Windows and OpenVMS platforms
Major changes between OpenSSL 1.0.1j and OpenSSL 1.0.1k [8 Jan 2015]
o Fix for CVE-2014-3571
o Fix for CVE-2015-0206
o Fix for CVE-2014-3569
o Fix for CVE-2014-3572
o Fix for CVE-2015-0204
o Fix for CVE-2015-0205
o Fix for CVE-2014-8275
o Fix for CVE-2014-3570
Major changes between OpenSSL 1.0.1i and OpenSSL 1.0.1j [15 Oct 2014]
o Fix for CVE-2014-3513
o Fix for CVE-2014-3567
o Mitigation for CVE-2014-3566 (SSL protocol vulnerability)
o Fix for CVE-2014-3568
Major changes between OpenSSL 1.0.1h and OpenSSL 1.0.1i [6 Aug 2014]
o Fix for CVE-2014-3512
o Fix for CVE-2014-3511
o Fix for CVE-2014-3510
o Fix for CVE-2014-3507
o Fix for CVE-2014-3506
o Fix for CVE-2014-3505
o Fix for CVE-2014-3509
o Fix for CVE-2014-5139
o Fix for CVE-2014-3508
Major changes between OpenSSL 1.0.1g and OpenSSL 1.0.1h [5 Jun 2014]
o Fix for CVE-2014-0224
o Fix for CVE-2014-0221
o Fix for CVE-2014-0198
o Fix for CVE-2014-0195
o Fix for CVE-2014-3470
o Fix for CVE-2010-5298
Major changes between OpenSSL 1.0.1f and OpenSSL 1.0.1g [7 Apr 2014]
o Fix for CVE-2014-0160
o Add TLS padding extension workaround for broken servers.
o Fix for CVE-2014-0076
Major changes between OpenSSL 1.0.1e and OpenSSL 1.0.1f [6 Jan 2014]
o Don't include gmt_unix_time in TLS server and client random values
o Fix for TLS record tampering bug CVE-2013-4353
o Fix for TLS version checking bug CVE-2013-6449
o Fix for DTLS retransmission bug CVE-2013-6450
Major changes between OpenSSL 1.0.1d and OpenSSL 1.0.1e [11 Feb 2013]:
o Corrected fix for CVE-2013-0169
Major changes between OpenSSL 1.0.1c and OpenSSL 1.0.1d [4 Feb 2013]:
o Fix renegotiation in TLS 1.1, 1.2 by using the correct TLS version.
o Include the fips configuration module.
o Fix OCSP bad key DoS attack CVE-2013-0166
o Fix for SSL/TLS/DTLS CBC plaintext recovery attack CVE-2013-0169
o Fix for TLS AESNI record handling flaw CVE-2012-2686
Major changes between OpenSSL 1.0.1b and OpenSSL 1.0.1c [10 May 2012]:
o Fix TLS/DTLS record length checking bug CVE-2012-2333
o Don't attempt to use non-FIPS composite ciphers in FIPS mode.
Major changes between OpenSSL 1.0.1a and OpenSSL 1.0.1b [26 Apr 2012]:
o Fix compilation error on non-x86 platforms.
o Make FIPS capable OpenSSL ciphers work in non-FIPS mode.
o Fix SSL_OP_NO_TLSv1_1 clash with SSL_OP_ALL in OpenSSL 1.0.0
Major changes between OpenSSL 1.0.1 and OpenSSL 1.0.1a [19 Apr 2012]:
o Fix for ASN1 overflow bug CVE-2012-2110
o Workarounds for some servers that hang on long client hellos.
o Fix SEGV in AES code.
Major changes between OpenSSL 1.0.0h and OpenSSL 1.0.1 [14 Mar 2012]:
o TLS/DTLS heartbeat support.
o SCTP support.
o RFC 5705 TLS key material exporter.
o RFC 5764 DTLS-SRTP negotiation.
o Next Protocol Negotiation.
o PSS signatures in certificates, requests and CRLs.
o Support for password based recipient info for CMS.
o Support TLS v1.2 and TLS v1.1.
o Preliminary FIPS capability for unvalidated 2.0 FIPS module.
o SRP support.
Major changes between OpenSSL 1.0.0g and OpenSSL 1.0.0h [12 Mar 2012]:
o Fix for CMS/PKCS#7 MMA CVE-2012-0884
o Corrected fix for CVE-2011-4619
o Various DTLS fixes.
Major changes between OpenSSL 1.0.0f and OpenSSL 1.0.0g [18 Jan 2012]:
o Fix for DTLS DoS issue CVE-2012-0050
Major changes between OpenSSL 1.0.0e and OpenSSL 1.0.0f [4 Jan 2012]:
o Fix for DTLS plaintext recovery attack CVE-2011-4108
o Clear block padding bytes of SSL 3.0 records CVE-2011-4576
o Only allow one SGC handshake restart for SSL/TLS CVE-2011-4619
o Check parameters are not NULL in GOST ENGINE CVE-2012-0027
o Check for malformed RFC3779 data CVE-2011-4577
Major changes between OpenSSL 1.0.0d and OpenSSL 1.0.0e [6 Sep 2011]:
o Fix for CRL vulnerability issue CVE-2011-3207
o Fix for ECDH crashes CVE-2011-3210
o Protection against EC timing attacks.
o Support ECDH ciphersuites for certificates using SHA2 algorithms.
o Various DTLS fixes.
Major changes between OpenSSL 1.0.0c and OpenSSL 1.0.0d [8 Feb 2011]:
o Fix for security issue CVE-2011-0014
Major changes between OpenSSL 1.0.0b and OpenSSL 1.0.0c [2 Dec 2010]:
o Fix for security issue CVE-2010-4180
o Fix for CVE-2010-4252
o Fix mishandling of absent EC point format extension.
o Fix various platform compilation issues.
o Corrected fix for security issue CVE-2010-3864.
Major changes between OpenSSL 1.0.0a and OpenSSL 1.0.0b [16 Nov 2010]:
o Fix for security issue CVE-2010-3864.
o Fix for CVE-2010-2939
o Fix WIN32 build system for GOST ENGINE.
Major changes between OpenSSL 1.0.0 and OpenSSL 1.0.0a [1 Jun 2010]:
o Fix for security issue CVE-2010-1633.
o GOST MAC and CFB fixes.
Major changes between OpenSSL 0.9.8n and OpenSSL 1.0.0 [29 Mar 2010]:
o RFC3280 path validation: sufficient to process PKITS tests.
o Integrated support for PVK files and keyblobs.
o Change default private key format to PKCS#8.
o CMS support: able to process all examples in RFC4134
o Streaming ASN1 encode support for PKCS#7 and CMS.
o Multiple signer and signer add support for PKCS#7 and CMS.
o ASN1 printing support.
o Whirlpool hash algorithm added.
o RFC3161 time stamp support.
o New generalised public key API supporting ENGINE based algorithms.
o New generalised public key API utilities.
o New ENGINE supporting GOST algorithms.
o SSL/TLS GOST ciphersuite support.
o PKCS#7 and CMS GOST support.
o RFC4279 PSK ciphersuite support.
o Supported points format extension for ECC ciphersuites.
o ecdsa-with-SHA224/256/384/512 signature types.
o dsa-with-SHA224 and dsa-with-SHA256 signature types.
o Opaque PRF Input TLS extension support.
o Updated time routines to avoid OS limitations.
Major changes between OpenSSL 0.9.8m and OpenSSL 0.9.8n [24 Mar 2010]:
o CFB cipher definition fixes.
o Fix security issues CVE-2010-0740 and CVE-2010-0433.
Major changes between OpenSSL 0.9.8l and OpenSSL 0.9.8m [25 Feb 2010]:
o Cipher definition fixes.
o Workaround for slow RAND_poll() on some WIN32 versions.
o Remove MD2 from algorithm tables.
o SPKAC handling fixes.
o Support for RFC5746 TLS renegotiation extension.
o Compression memory leak fixed.
o Compression session resumption fixed.
o Ticket and SNI coexistence fixes.
o Many fixes to DTLS handling.
Major changes between OpenSSL 0.9.8k and OpenSSL 0.9.8l [5 Nov 2009]:
o Temporary work around for CVE-2009-3555: disable renegotiation.
Major changes between OpenSSL 0.9.8j and OpenSSL 0.9.8k [25 Mar 2009]:
o Fix various build issues.
o Fix security issues (CVE-2009-0590, CVE-2009-0591, CVE-2009-0789)
Major changes between OpenSSL 0.9.8i and OpenSSL 0.9.8j [7 Jan 2009]:
o Fix security issue (CVE-2008-5077)
o Merge FIPS 140-2 branch code.
Major changes between OpenSSL 0.9.8g and OpenSSL 0.9.8h [28 May 2008]:
o CryptoAPI ENGINE support.
o Various precautionary measures.
o Fix for bugs affecting certificate request creation.
o Support for local machine keyset attribute in PKCS#12 files.
Major changes between OpenSSL 0.9.8f and OpenSSL 0.9.8g [19 Oct 2007]:
o Backport of CMS functionality to 0.9.8.
o Fixes for bugs introduced with 0.9.8f.
Major changes between OpenSSL 0.9.8e and OpenSSL 0.9.8f [11 Oct 2007]:
o Add gcc 4.2 support.
o Add support for AES and SSE2 assembly language optimization
for VC++ build.
o Support for RFC4507bis and server name extensions if explicitly
selected at compile time.
o DTLS improvements.
o RFC4507bis support.
o TLS Extensions support.
Major changes between OpenSSL 0.9.8d and OpenSSL 0.9.8e [23 Feb 2007]:
o Various ciphersuite selection fixes.
o RFC3779 support.
Major changes between OpenSSL 0.9.8c and OpenSSL 0.9.8d [28 Sep 2006]:
o Introduce limits to prevent malicious key DoS (CVE-2006-2940)
o Fix security issues (CVE-2006-2937, CVE-2006-3737, CVE-2006-4343)
o Changes to ciphersuite selection algorithm
Major changes between OpenSSL 0.9.8b and OpenSSL 0.9.8c [5 Sep 2006]:
o Fix Daniel Bleichenbacher forged signature attack, CVE-2006-4339
o New cipher Camellia
Major changes between OpenSSL 0.9.8a and OpenSSL 0.9.8b [4 May 2006]:
o Cipher string fixes.
o Fixes for VC++ 2005.
o Updated ECC cipher suite support.
o New functions EVP_CIPHER_CTX_new() and EVP_CIPHER_CTX_free().
o Zlib compression usage fixes.
o Built in dynamic engine compilation support on Win32.
o Fixes auto dynamic engine loading in Win32.
Major changes between OpenSSL 0.9.8 and OpenSSL 0.9.8a [11 Oct 2005]:
o Fix potential SSL 2.0 rollback, CVE-2005-2969
o Extended Windows CE support
Major changes between OpenSSL 0.9.7g and OpenSSL 0.9.8 [5 Jul 2005]:
o Major work on the BIGNUM library for higher efficiency and to
make operations more streamlined and less contradictory. This
is the result of a major audit of the BIGNUM library.
o Addition of BIGNUM functions for fields GF(2^m) and NIST
curves, to support the Elliptic Crypto functions.
o Major work on Elliptic Crypto; ECDH and ECDSA added, including
the use through EVP, X509 and ENGINE.
o New ASN.1 mini-compiler that's usable through the OpenSSL
configuration file.
o Added support for ASN.1 indefinite length constructed encoding.
o New PKCS#12 'medium level' API to manipulate PKCS#12 files.
o Complete rework of shared library construction and linking
programs with shared or static libraries, through a separate
Makefile.shared.
o Rework of the passing of parameters from one Makefile to another.
o Changed ENGINE framework to load dynamic engine modules
automatically from specifically given directories.
o New structure and ASN.1 functions for CertificatePair.
o Changed the ZLIB compression method to be stateful.
o Changed the key-generation and primality testing "progress"
mechanism to take a structure that contains the ticker
function and an argument.
o New engine module: GMP (performs private key exponentiation).
o New engine module: VIA PadLOck ACE extension in VIA C3
Nehemiah processors.
o Added support for IPv6 addresses in certificate extensions.
See RFC 1884, section 2.2.
o Added support for certificate policy mappings, policy
constraints and name constraints.
o Added support for multi-valued AVAs in the OpenSSL
configuration file.
o Added support for multiple certificates with the same subject
in the 'openssl ca' index file.
o Make it possible to create self-signed certificates using
'openssl ca -selfsign'.
o Make it possible to generate a serial number file with
'openssl ca -create_serial'.
o New binary search functions with extended functionality.
o New BUF functions.
o New STORE structure and library to provide an interface to all
sorts of data repositories. Supports storage of public and
private keys, certificates, CRLs, numbers and arbitrary blobs.
This library is unfortunately unfinished and unused within
OpenSSL.
o New control functions for the error stack.
o Changed the PKCS#7 library to support one-pass S/MIME
processing.
o Added the possibility to compile without old deprecated
functionality with the OPENSSL_NO_DEPRECATED macro or the
'no-deprecated' argument to the config and Configure scripts.
o Constification of all ASN.1 conversion functions, and other
affected functions.
o Improved platform support for PowerPC.
o New FIPS 180-2 algorithms (SHA-224, -256, -384 and -512).
o New X509_VERIFY_PARAM structure to support parametrisation
of X.509 path validation.
o Major overhaul of RC4 performance on Intel P4, IA-64 and
AMD64.
o Changed the Configure script to have some algorithms disabled
by default. Those can be explicitly enabled with the new
argument form 'enable-xxx'.
o Change the default digest in 'openssl' commands from MD5 to
SHA-1.
o Added support for DTLS.
o New BIGNUM blinding.
o Added support for the RSA-PSS encryption scheme
o Added support for the RSA X.931 padding.
o Added support for BSD sockets on NetWare.
o Added support for files larger than 2GB.
o Added initial support for Win64.
o Added alternate pkg-config files.
Major changes between OpenSSL 0.9.7l and OpenSSL 0.9.7m [23 Feb 2007]:
o FIPS 1.1.1 module linking.
o Various ciphersuite selection fixes.
Major changes between OpenSSL 0.9.7k and OpenSSL 0.9.7l [28 Sep 2006]:
o Introduce limits to prevent malicious key DoS (CVE-2006-2940)
o Fix security issues (CVE-2006-2937, CVE-2006-3737, CVE-2006-4343)
Major changes between OpenSSL 0.9.7j and OpenSSL 0.9.7k [5 Sep 2006]:
o Fix Daniel Bleichenbacher forged signature attack, CVE-2006-4339
Major changes between OpenSSL 0.9.7i and OpenSSL 0.9.7j [4 May 2006]:
o Visual C++ 2005 fixes.
o Update Windows build system for FIPS.
Major changes between OpenSSL 0.9.7h and OpenSSL 0.9.7i [14 Oct 2005]:
o Give EVP_MAX_MD_SIZE it's old value, except for a FIPS build.
Major changes between OpenSSL 0.9.7g and OpenSSL 0.9.7h [11 Oct 2005]:
o Fix SSL 2.0 Rollback, CVE-2005-2969
o Allow use of fixed-length exponent on DSA signing
o Default fixed-window RSA, DSA, DH private-key operations
Major changes between OpenSSL 0.9.7f and OpenSSL 0.9.7g [11 Apr 2005]:
o More compilation issues fixed.
o Adaptation to more modern Kerberos API.
o Enhanced or corrected configuration for Solaris64, Mingw and Cygwin.
o Enhanced x86_64 assembler BIGNUM module.
o More constification.
o Added processing of proxy certificates (RFC 3820).
Major changes between OpenSSL 0.9.7e and OpenSSL 0.9.7f [22 Mar 2005]:
o Several compilation issues fixed.
o Many memory allocation failure checks added.
o Improved comparison of X509 Name type.
o Mandatory basic checks on certificates.
o Performance improvements.
Major changes between OpenSSL 0.9.7d and OpenSSL 0.9.7e [25 Oct 2004]:
o Fix race condition in CRL checking code.
o Fixes to PKCS#7 (S/MIME) code.
Major changes between OpenSSL 0.9.7c and OpenSSL 0.9.7d [17 Mar 2004]:
o Security: Fix Kerberos ciphersuite SSL/TLS handshaking bug
o Security: Fix null-pointer assignment in do_change_cipher_spec()
o Allow multiple active certificates with same subject in CA index
o Multiple X509 verification fixes
o Speed up HMAC and other operations
Major changes between OpenSSL 0.9.7b and OpenSSL 0.9.7c [30 Sep 2003]:
o Security: fix various ASN1 parsing bugs.
o New -ignore_err option to OCSP utility.
o Various interop and bug fixes in S/MIME code.
o SSL/TLS protocol fix for unrequested client certificates.
Major changes between OpenSSL 0.9.7a and OpenSSL 0.9.7b [10 Apr 2003]:
o Security: counter the Klima-Pokorny-Rosa extension of
Bleichbacher's attack
o Security: make RSA blinding default.
o Configuration: Irix fixes, AIX fixes, better mingw support.
o Support for new platforms: linux-ia64-ecc.
o Build: shared library support fixes.
o ASN.1: treat domainComponent correctly.
o Documentation: fixes and additions.
Major changes between OpenSSL 0.9.7 and OpenSSL 0.9.7a [19 Feb 2003]:
o Security: Important security related bugfixes.
o Enhanced compatibility with MIT Kerberos.
o Can be built without the ENGINE framework.
o IA32 assembler enhancements.
o Support for new platforms: FreeBSD/IA64 and FreeBSD/Sparc64.
o Configuration: the no-err option now works properly.
o SSL/TLS: now handles manual certificate chain building.
o SSL/TLS: certain session ID malfunctions corrected.
Major changes between OpenSSL 0.9.6 and OpenSSL 0.9.7 [30 Dec 2002]:
o New library section OCSP.
o Complete rewrite of ASN1 code.
o CRL checking in verify code and openssl utility.
o Extension copying in 'ca' utility.
o Flexible display options in 'ca' utility.
o Provisional support for international characters with UTF8.
o Support for external crypto devices ('engine') is no longer
a separate distribution.
o New elliptic curve library section.
o New AES (Rijndael) library section.
o Support for new platforms: Windows CE, Tandem OSS, A/UX, AIX 64-bit,
Linux x86_64, Linux 64-bit on Sparc v9
o Extended support for some platforms: VxWorks
o Enhanced support for shared libraries.
o Now only builds PIC code when shared library support is requested.
o Support for pkg-config.
o Lots of new manuals.
o Makes symbolic links to or copies of manuals to cover all described
functions.
o Change DES API to clean up the namespace (some applications link also
against libdes providing similar functions having the same name).
Provide macros for backward compatibility (will be removed in the
future).
o Unify handling of cryptographic algorithms (software and engine)
to be available via EVP routines for asymmetric and symmetric ciphers.
o NCONF: new configuration handling routines.
o Change API to use more 'const' modifiers to improve error checking
and help optimizers.
o Finally remove references to RSAref.
o Reworked parts of the BIGNUM code.
o Support for new engines: Broadcom ubsec, Accelerated Encryption
Processing, IBM 4758.
o A few new engines added in the demos area.
o Extended and corrected OID (object identifier) table.
o PRNG: query at more locations for a random device, automatic query for
EGD style random sources at several locations.
o SSL/TLS: allow optional cipher choice according to server's preference.
o SSL/TLS: allow server to explicitly set new session ids.
o SSL/TLS: support Kerberos cipher suites (RFC2712).
Only supports MIT Kerberos for now.
o SSL/TLS: allow more precise control of renegotiations and sessions.
o SSL/TLS: add callback to retrieve SSL/TLS messages.
o SSL/TLS: support AES cipher suites (RFC3268).
Major changes between OpenSSL 0.9.6j and OpenSSL 0.9.6k [30 Sep 2003]:
o Security: fix various ASN1 parsing bugs.
o SSL/TLS protocol fix for unrequested client certificates.
Major changes between OpenSSL 0.9.6i and OpenSSL 0.9.6j [10 Apr 2003]:
o Security: counter the Klima-Pokorny-Rosa extension of
Bleichbacher's attack
o Security: make RSA blinding default.
o Build: shared library support fixes.
Major changes between OpenSSL 0.9.6h and OpenSSL 0.9.6i [19 Feb 2003]:
o Important security related bugfixes.
Major changes between OpenSSL 0.9.6g and OpenSSL 0.9.6h [5 Dec 2002]:
o New configuration targets for Tandem OSS and A/UX.
o New OIDs for Microsoft attributes.
o Better handling of SSL session caching.
o Better comparison of distinguished names.
o Better handling of shared libraries in a mixed GNU/non-GNU environment.
o Support assembler code with Borland C.
o Fixes for length problems.
o Fixes for uninitialised variables.
o Fixes for memory leaks, some unusual crashes and some race conditions.
o Fixes for smaller building problems.
o Updates of manuals, FAQ and other instructive documents.
Major changes between OpenSSL 0.9.6f and OpenSSL 0.9.6g [9 Aug 2002]:
o Important building fixes on Unix.
Major changes between OpenSSL 0.9.6e and OpenSSL 0.9.6f [8 Aug 2002]:
o Various important bugfixes.
Major changes between OpenSSL 0.9.6d and OpenSSL 0.9.6e [30 Jul 2002]:
o Important security related bugfixes.
o Various SSL/TLS library bugfixes.
Major changes between OpenSSL 0.9.6c and OpenSSL 0.9.6d [9 May 2002]:
o Various SSL/TLS library bugfixes.
o Fix DH parameter generation for 'non-standard' generators.
Major changes between OpenSSL 0.9.6b and OpenSSL 0.9.6c [21 Dec 2001]:
o Various SSL/TLS library bugfixes.
o BIGNUM library fixes.
o RSA OAEP and random number generation fixes.
o Object identifiers corrected and added.
o Add assembler BN routines for IA64.
o Add support for OS/390 Unix, UnixWare with gcc, OpenUNIX 8,
MIPS Linux; shared library support for Irix, HP-UX.
o Add crypto accelerator support for AEP, Baltimore SureWare,
Broadcom and Cryptographic Appliance's keyserver
[in 0.9.6c-engine release].
Major changes between OpenSSL 0.9.6a and OpenSSL 0.9.6b [9 Jul 2001]:
o Security fix: PRNG improvements.
o Security fix: RSA OAEP check.
o Security fix: Reinsert and fix countermeasure to Bleichbacher's
attack.
o MIPS bug fix in BIGNUM.
o Bug fix in "openssl enc".
o Bug fix in X.509 printing routine.
o Bug fix in DSA verification routine and DSA S/MIME verification.
o Bug fix to make PRNG thread-safe.
o Bug fix in RAND_file_name().
o Bug fix in compatibility mode trust settings.
o Bug fix in blowfish EVP.
o Increase default size for BIO buffering filter.
o Compatibility fixes in some scripts.
Major changes between OpenSSL 0.9.6 and OpenSSL 0.9.6a [5 Apr 2001]:
o Security fix: change behavior of OpenSSL to avoid using
environment variables when running as root.
o Security fix: check the result of RSA-CRT to reduce the
possibility of deducing the private key from an incorrectly
calculated signature.
o Security fix: prevent Bleichenbacher's DSA attack.
o Security fix: Zero the premaster secret after deriving the
master secret in DH ciphersuites.
o Reimplement SSL_peek(), which had various problems.
o Compatibility fix: the function des_encrypt() renamed to
des_encrypt1() to avoid clashes with some Unixen libc.
o Bug fixes for Win32, HP/UX and Irix.
o Bug fixes in BIGNUM, SSL, PKCS#7, PKCS#12, X.509, CONF and
memory checking routines.
o Bug fixes for RSA operations in threaded environments.
o Bug fixes in misc. openssl applications.
o Remove a few potential memory leaks.
o Add tighter checks of BIGNUM routines.
o Shared library support has been reworked for generality.
o More documentation.
o New function BN_rand_range().
o Add "-rand" option to openssl s_client and s_server.
Major changes between OpenSSL 0.9.5a and OpenSSL 0.9.6 [10 Oct 2000]:
o Some documentation for BIO and SSL libraries.
o Enhanced chain verification using key identifiers.
o New sign and verify options to 'dgst' application.
o Support for DER and PEM encoded messages in 'smime' application.
o New 'rsautl' application, low level RSA utility.
o MD4 now included.
o Bugfix for SSL rollback padding check.
o Support for external crypto devices [1].
o Enhanced EVP interface.
[1] The support for external crypto devices is currently a separate
distribution. See the file README.ENGINE.
Major changes between OpenSSL 0.9.5 and OpenSSL 0.9.5a [1 Apr 2000]:
o Bug fixes for Win32, SuSE Linux, NeXTSTEP and FreeBSD 2.2.8
o Shared library support for HPUX and Solaris-gcc
o Support of Linux/IA64
o Assembler support for Mingw32
o New 'rand' application
o New way to check for existence of algorithms from scripts
Major changes between OpenSSL 0.9.4 and OpenSSL 0.9.5 [25 May 2000]:
o S/MIME support in new 'smime' command
o Documentation for the OpenSSL command line application
o Automation of 'req' application
o Fixes to make s_client, s_server work under Windows
o Support for multiple fieldnames in SPKACs
o New SPKAC command line utilty and associated library functions
o Options to allow passwords to be obtained from various sources
o New public key PEM format and options to handle it
o Many other fixes and enhancements to command line utilities
o Usable certificate chain verification
o Certificate purpose checking
o Certificate trust settings
o Support of authority information access extension
o Extensions in certificate requests
o Simplified X509 name and attribute routines
o Initial (incomplete) support for international character sets
o New DH_METHOD, DSA_METHOD and enhanced RSA_METHOD
o Read only memory BIOs and simplified creation function
o TLS/SSL protocol bugfixes: Accept TLS 'client hello' in SSL 3.0
record; allow fragmentation and interleaving of handshake and other
data
o TLS/SSL code now "tolerates" MS SGC
o Work around for Netscape client certificate hang bug
o RSA_NULL option that removes RSA patent code but keeps other
RSA functionality
o Memory leak detection now allows applications to add extra information
via a per-thread stack
o PRNG robustness improved
o EGD support
o BIGNUM library bug fixes
o Faster DSA parameter generation
o Enhanced support for Alpha Linux
o Experimental MacOS support
Major changes between OpenSSL 0.9.3 and OpenSSL 0.9.4 [9 Aug 1999]:
o Transparent support for PKCS#8 format private keys: these are used
by several software packages and are more secure than the standard
form
o PKCS#5 v2.0 implementation
o Password callbacks have a new void * argument for application data
o Avoid various memory leaks
o New pipe-like BIO that allows using the SSL library when actual I/O
must be handled by the application (BIO pair)
Major changes between OpenSSL 0.9.2b and OpenSSL 0.9.3 [24 May 1999]:
o Lots of enhancements and cleanups to the Configuration mechanism
o RSA OEAP related fixes
o Added `openssl ca -revoke' option for revoking a certificate
o Source cleanups: const correctness, type-safe stacks and ASN.1 SETs
o Source tree cleanups: removed lots of obsolete files
o Thawte SXNet, certificate policies and CRL distribution points
extension support
o Preliminary (experimental) S/MIME support
o Support for ASN.1 UTF8String and VisibleString
o Full integration of PKCS#12 code
o Sparc assembler bignum implementation, optimized hash functions
o Option to disable selected ciphers
Major changes between OpenSSL 0.9.1c and OpenSSL 0.9.2b [22 Mar 1999]:
o Fixed a security hole related to session resumption
o Fixed RSA encryption routines for the p < q case
o "ALL" in cipher lists now means "everything except NULL ciphers"
o Support for Triple-DES CBCM cipher
o Support of Optimal Asymmetric Encryption Padding (OAEP) for RSA
o First support for new TLSv1 ciphers
o Added a few new BIOs (syslog BIO, reliable BIO)
o Extended support for DSA certificate/keys.
o Extended support for Certificate Signing Requests (CSR)
o Initial support for X.509v3 extensions
o Extended support for compression inside the SSL record layer
o Overhauled Win32 builds
o Cleanups and fixes to the Big Number (BN) library
o Support for ASN.1 GeneralizedTime
o Splitted ASN.1 SETs from SEQUENCEs
o ASN1 and PEM support for Netscape Certificate Sequences
o Overhauled Perl interface
o Lots of source tree cleanups.
o Lots of memory leak fixes.
o Lots of bug fixes.
Major changes between SSLeay 0.9.0b and OpenSSL 0.9.1c [23 Dec 1998]:
o Integration of the popular NO_RSA/NO_DSA patches
o Initial support for compression inside the SSL record layer
o Added BIO proxy and filtering functionality
o Extended Big Number (BN) library
o Added RIPE MD160 message digest
o Addeed support for RC2/64bit cipher
o Extended ASN.1 parser routines
o Adjustations of the source tree for CVS
o Support for various new platforms
-139
View File
@@ -1,139 +0,0 @@
NOTES FOR THE WINDOWS PLATFORMS
===============================
Requirement details for native (Visual C++) builds
--------------------------------------------------
In addition to the requirements and instructions listed in INSTALL,
this are required as well:
- You need Perl. We recommend ActiveState Perl, available from
https://www.activestate.com/ActivePerl. Another viable alternative
appears to be Strawberry Perl, http://strawberryperl.com.
You also need the perl module Text::Template, available on CPAN.
Please read NOTES.PERL for more information.
- You need a C compiler. OpenSSL has been tested to build with these:
* Visual C++
- Netwide Assembler, a.k.a. NASM, available from http://www.nasm.us,
is required if you intend to utilize assembler modules. Note that NASM
is the only supported assembler. The Microsoft provided assembler is NOT
supported.
Visual C++ (native Windows)
---------------------------
Installation directories
The default installation directories are derived from environment
variables.
For VC-WIN32, the following defaults are use:
PREFIX: %ProgramFiles(86)%\OpenSSL
OPENSSLDIR: %CommonProgramFiles(86)%\SSL
For VC-WIN64, the following defaults are use:
PREFIX: %ProgramW6432%\OpenSSL
OPENSSLDIR: %CommonProgramW6432%\SSL
Should those environment variables not exist (on a pure Win32
installation for examples), these fallbacks are used:
PREFIX: %ProgramFiles%\OpenSSL
OPENSSLDIR: %CommonProgramFiles%\SSL
ALSO NOTE that those directories are usually write protected, even if
your account is in the Administrators group. To work around that,
start the command prompt by right-clicking on it and choosing "Run as
Administrator" before running 'nmake install'. The other solution
is, of course, to choose a different set of directories by using
--prefix and --openssldir when configuring.
GNU C (Cygwin)
--------------
Cygwin implements a Posix/Unix runtime system (cygwin1.dll) on top of the
Windows subsystem and provides a bash shell and GNU tools environment.
Consequently, a make of OpenSSL with Cygwin is virtually identical to the
Unix procedure.
To build OpenSSL using Cygwin, you need to:
* Install Cygwin (see https://cygwin.com/)
* Install Cygwin Perl and ensure it is in the path. Recall that
as least 5.10.0 is required.
* Run the Cygwin bash shell
Apart from that, follow the Unix instructions in INSTALL.
NOTE: "make test" and normal file operations may fail in directories
mounted as text (i.e. mount -t c:\somewhere /home) due to Cygwin
stripping of carriage returns. To avoid this ensure that a binary
mount is used, e.g. mount -b c:\somewhere /home.
It is also possible to create "conventional" Windows binaries that use
the Microsoft C runtime system (msvcrt.dll or crtdll.dll) using MinGW
development add-on for Cygwin. MinGW is supported even as a standalone
setup as described in the following section. In the context you should
recognize that binaries targeting Cygwin itself are not interchangeable
with "conventional" Windows binaries you generate with/for MinGW.
GNU C (MinGW/MSYS)
------------------
* Compiler and shell environment installation:
MinGW and MSYS are available from http://www.mingw.org/, both are
required. Run the installers and do whatever magic they say it takes
to start MSYS bash shell with GNU tools and matching Perl on its PATH.
"Matching Perl" refers to chosen "shell environment", i.e. if built
under MSYS, then Perl compiled for MSYS must be used.
Alternatively, one can use MSYS2 from https://msys2.github.io/,
which includes MingW (32-bit and 64-bit).
* It is also possible to cross-compile it on Linux by configuring
with './Configure --cross-compile-prefix=i386-mingw32- mingw ...'.
Other possible cross compile prefixes include x86_64-w64-mingw32-
and i686-w64-mingw32-.
Linking your application
------------------------
This section applies to non-Cygwin builds.
If you link with static OpenSSL libraries then you're expected to
additionally link your application with WS2_32.LIB, GDI32.LIB,
ADVAPI32.LIB, CRYPT32.LIB and USER32.LIB. Those developing
non-interactive service applications might feel concerned about
linking with GDI32.LIB and USER32.LIB, as they are justly associated
with interactive desktop, which is not available to service
processes. The toolkit is designed to detect in which context it's
currently executed, GUI, console app or service, and act accordingly,
namely whether or not to actually make GUI calls. Additionally those
who wish to /DELAYLOAD:GDI32.DLL and /DELAYLOAD:USER32.DLL and
actually keep them off service process should consider implementing
and exporting from .exe image in question own _OPENSSL_isservice not
relying on USER32.DLL. E.g., on Windows Vista and later you could:
__declspec(dllexport) __cdecl BOOL _OPENSSL_isservice(void)
{ DWORD sess;
if (ProcessIdToSessionId(GetCurrentProcessId(),&sess))
return sess==0;
return FALSE;
}
If you link with OpenSSL .DLLs, then you're expected to include into
your application code small "shim" snippet, which provides glue between
OpenSSL BIO layer and your compiler run-time. See the OPENSSL_Applink
manual page for further details.
-61
View File
@@ -1,61 +0,0 @@
NOTE: The OpenSSL Software Foundation has executed a sublicense agreement
entitled "Elliptic Curve Cryptography Patent License Agreement" with the
National Security Agency/ Central Security Service Commercial Solutions
Center (NCSC) dated 2010-11-04. That agreement permits implementation and
distribution of software containing features covered by any or all of the
following patents:
1.) U.S. Pat. No. 5,761,305 entitled "Key Agreement and Transport Protocol
with Implicit Signatures" issued on June 2, 1998;
2.) Can. Pat. Appl. Ser. No. 2176972 entitled "Key Agreement and Transport
Protocol with Implicit Signature and Reduced Bandwidth" filed on May
16, 1996;
3.) U.S. Pat. No. 5,889,865 entitled "Key Agreement and Transport Protocol
with Implicit Signatures" issued on March 30, 1999;
4.) U.S. Pat. No. 5,896,455 entitled "Key Agreement and Transport Protocol
with Implicit Signatures" issued on April 20, 1999;
5.) U.S. Pat. No. 5,933,504 entitled "Strengthened Public Key Protocol"
issued on August 3, 1999;
6.) Can. Pat. Appl. Ser. No. 2176866 entitled "Strengthened Public Key
Protocol" filed on May 17, 1996;
7.) E.P. Pat. Appl. Ser. No. 96201322.3 entitled "Strengthened Public Key
Protocol" filed on May 17, 1996;
8.) U.S. Pat. No. 5,999,626 entitled "Digital Signatures on a Smartcard"
issued on December 7, 1999;
9.) Can. Pat. Appl. Ser. No. 2202566 entitled "Digital Signatures on a
Smartcard" filed on April 14, 1997;
10.) E.P. Pat. Appl. No. 97106114.8 entitled "Digital Signatures on a
Smartcard" filed on April 15, 1997;
11.) U.S Pat. No. 6,122,736 entitled "Key Agreement and Transport Protocol
with Implicit Signatures" issued on September 19, 2000;
12.) Can. Pat. Appl. Ser. No. 2174261 entitled "Key Agreement and Transport
Protocol with Implicit Signatures" filed on April 16, 1996;
13.) E.P. Pat. Appl. Ser. No. 96105920.1 entitled "Key Agreement and
Transport Protocol with Implicit Signatures" filed on April 16, 1996;
14.) U.S. Pat. No. 6,141,420 entitled "Elliptic Curve Encryption Systems"
issued on October 31, 2000;
15.) Can. Pat. Appl. Ser. No. 2155038 entitled "Elliptic Curve Encryption
Systems" filed on July 31, 1995;
16.) E.P. Pat. Appl. Ser. No. 95926348.4 entitled "Elliptic Curve Encryption
Systems" filed on July 31, 1995;
17.) U.S. Pat. No. 6,336,188 entitled "Authenticated Key Agreement" issued
on January 1, 2002;
18.) U.S. Pat. No. 6,487,661 entitled "Key Agreement and Transport Protocol"
issued on November 26, 2002;
19.) Can. Pat. Appl. Ser. No. 2174260 entitled "Key Agreement and Transport
Protocol" filed on April 16, 1996;
20.) E.P. Pat. Appl. Ser. No. 96105921.9 entitled "Key Agreement and
Transport Protocol" filed on April 21, 1996;
21.) U.S. Pat. No. 6,563,928 entitled "Strengthened Public Key Protocol"
issued on May 13, 2003;
22.) U.S. Pat. No. 6,618,483 entitled "Elliptic Curve Encryption Systems"
issued September 9, 2003;
23.) U.S. Pat. Appl. Ser. No. 09/434,247 entitled "Digital Signatures on a
Smartcard" filed on November 5, 1999;
24.) U.S. Pat. Appl. Ser. No. 09/558,256 entitled "Key Agreement and
Transport Protocol with Implicit Signatures" filed on April 25, 2000;
25.) U.S. Pat. Appl. Ser. No. 09/942,492 entitled "Digital Signatures on a
Smartcard" filed on August 29, 2001 and published on July 18, 2002; and,
26.) U.S. Pat. Appl. Ser. No. 10/185,735 entitled "Strengthened Public Key
Protocol" filed on July 1, 2000.
-94
View File
@@ -1,94 +0,0 @@
OpenSSL 1.1.0f 25 May 2017
Copyright (c) 1998-2016 The OpenSSL Project
Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson
All rights reserved.
DESCRIPTION
-----------
The OpenSSL Project is a collaborative effort to develop a robust,
commercial-grade, fully featured, and Open Source toolkit implementing the
Transport Layer Security (TLS) protocols (including SSLv3) as well as a
full-strength general purpose cryptographic library.
OpenSSL is descended from the SSLeay library developed by Eric A. Young
and Tim J. Hudson. The OpenSSL toolkit is licensed under a dual-license (the
OpenSSL license plus the SSLeay license), which means that you are free to
get and use it for commercial and non-commercial purposes as long as you
fulfill the conditions of both licenses.
OVERVIEW
--------
The OpenSSL toolkit includes:
libssl (with platform specific naming):
Provides the client and server-side implementations for SSLv3 and TLS.
libcrypto (with platform specific naming):
Provides general cryptographic and X.509 support needed by SSL/TLS but
not logically part of it.
openssl:
A command line tool that can be used for:
Creation of key parameters
Creation of X.509 certificates, CSRs and CRLs
Calculation of message digests
Encryption and decryption
SSL/TLS client and server tests
Handling of S/MIME signed or encrypted mail
And more...
INSTALLATION
------------
See the appropriate file:
INSTALL Linux, Unix, Windows, OpenVMS, ...
NOTES.* INSTALL addendums for different platforms
SUPPORT
-------
See the OpenSSL website www.openssl.org for details on how to obtain
commercial technical support. Free community support is available through the
openssl-users email list (see
https://www.openssl.org/community/mailinglists.html for further details).
If you have any problems with OpenSSL then please take the following steps
first:
- Download the latest version from the repository
to see if the problem has already been addressed
- Configure with no-asm
- Remove compiler optimisation flags
If you wish to report a bug then please include the following information
and create an issue on GitHub:
- OpenSSL version: output of 'openssl version -a'
- Any "Configure" options that you selected during compilation of the
library if applicable (see INSTALL)
- OS Name, Version, Hardware platform
- Compiler Details (name, version)
- Application Details (name, version)
- Problem Description (steps that will reproduce the problem, if known)
- Stack Traceback (if the application dumps core)
Just because something doesn't work the way you expect does not mean it
is necessarily a bug in OpenSSL. Use the openssl-users email list for this type
of query.
HOW TO CONTRIBUTE TO OpenSSL
----------------------------
See CONTRIBUTING
LEGALITIES
----------
A number of nations restrict the use or export of cryptography. If you
are potentially subject to such restrictions you should seek competent
professional legal advice before attempting to develop or distribute
cryptographic code.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,16 +0,0 @@
/*
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* This file is only used by HP C on VMS, and is included automatically
* after each header file from this directory
*/
/* restore state. Must correspond to the save in __decc_include_prologue.h */
#pragma names restore

Some files were not shown because too many files have changed in this diff Show More