├── .gitattributes ├── LICENSE ├── README.md ├── hexlicsrv ├── CA │ └── .gitignore ├── config │ └── hexlicsrv.conf ├── data │ └── .gitignore ├── docker-compose.yml ├── image │ ├── Dockerfile │ ├── entrypoint.sh │ └── patch.py └── logs │ └── .gitignore ├── hexvault ├── CA │ └── .gitignore ├── config │ └── hexvault.conf ├── data │ └── store │ │ └── .gitignore ├── docker-compose.yml ├── image │ ├── Dockerfile │ ├── entrypoint.sh │ └── patch.py └── logs │ └── .gitignore ├── ida ├── CA │ └── .gitignore └── patch.py ├── lumina ├── CA │ └── .gitignore ├── config │ └── .gitignore ├── data │ └── .gitignore ├── db_data │ └── .gitignore ├── docker-compose.yml ├── image │ ├── Dockerfile │ ├── entrypoint.sh │ └── patch.py ├── logs │ └── .gitignore └── my.cnf ├── shell.9.1.reg └── shell.reg /.gitattributes: -------------------------------------------------------------------------------- 1 | *.reg text=auto eol=crlf charset=utf-8 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Ren 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IDATeamsDocker 2 | Docker configuration (and only docker configuration) files for hosting self-hosted Hexvault, Lumina and Hexlicsrv. The installation files should be in `./image` folders. 3 | 4 | Supported version: [IDA 9.0.240925 September 30, 2024](https://docs.hex-rays.com/release-notes/9_0) 5 | 6 | # CA (NOTE) 7 | Before you start doing anything, you need to generate your own CA certificate. This can be done like this: 8 | ```bash 9 | openssl req -x509 -newkey rsa:4096 -sha512 \ 10 | -keyout CA.key -out CA.pem -days 365 -nodes \ 11 | -subj "/C=BE/L=Liège/O=Hex-Rays SA./CN=Hex-Rays SA. Root CA" 12 | ``` 13 | Now you have two files (the key and the certificate itself), you need to place these two files in the CA folders (`./CA`). Also you need to replace the CA in IDA itself, which is done in another step below. 14 | 15 | # IDA preparing 16 | 1. Create a CA folder in the root (`C:\Program Files\IDA Professional 9.0\CA`) 17 | 2. Copy `CA.key` and `CA.pem` to the previously created folder 18 | 4. Copy the Python script (`patch.py`) to the root 19 | 5. Run script as administrator (`python3 patch.py ida-pro`) 20 | 6. Enjoy 21 | 22 | # Hexvault hosting 23 | 1. `cd ./hexvault` 24 | 2. Copy `hexvault90_x64linux.run` into `./image` 25 | 3. `chmod +x ./image/entrypoint.sh` 26 | 4. Copy `CA.key` and `CA.pem` to the CA folder (`./CA`) 27 | 5. Edit `docker-compose.yml`. (You need to edit `VAULT_HOST` for TLS) 28 | 6. `sudo docker-compose up -d` 29 | 7. Enjoy 30 | 31 | # Lumina hosting 32 | 11. `cd ./lumina` 33 | 2. Copy `lumina90_x64linux.run` into `./image` 34 | 3. `chmod +x ./image/entrypoint.sh` 35 | 4. Copy `CA.key` and `CA.pem` to the CA folder (`./CA`) 36 | 5. Edit `docker-compose.yml`. (You need to edit `LUMINA_HOST` for TLS) 37 | 6. `sudo docker-compose up -d` 38 | 7. Enjoy 39 | 40 | # Hexlicsrv hosting 41 | 1. `cd ./hexlicsrv` 42 | 2. Copy `hexlicsrv90_x64linux.run` into `./image` 43 | 3. `chmod +x ./image/entrypoint.sh` 44 | 4. Copy `CA.key` and `CA.pem` to the CA folder (`./CA`) 45 | 5. Edit `docker-compose.yml`. (You need to edit `LICENSE_HOST` for TLS) 46 | 6. `sudo docker-compose up -d` 47 | 7. Enjoy 48 | 49 | # NOTE 50 | The *_schema.lock flag file is an indicator to the container when it is time to run a schema recreate using --recreate-schema. As long as this file exists, the container will not run a schema recreate. 51 | 52 | # shell.reg 53 | This file adds support for opening IDA with the right mouse button in Windows. 54 | 55 | # shell.9.1.reg 56 | Same as `shell.reg` but for IDA 9.1 57 | -------------------------------------------------------------------------------- /hexlicsrv/CA/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /hexlicsrv/config/hexlicsrv.conf: -------------------------------------------------------------------------------- 1 | sqlite3;Data Source=/opt/hexlicsrv/data/hexlicsrv.sqlite3; 2 | -------------------------------------------------------------------------------- /hexlicsrv/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /hexlicsrv/docker-compose.yml: -------------------------------------------------------------------------------- 1 | 2 | services: 3 | hexlicsrv: 4 | container_name: hexlicsrv 5 | build: 6 | context: ./image 7 | restart: always 8 | environment: 9 | - LICENSE_HOST=reversing.example.com 10 | - LICENSE_PORT=65434 # Optional; Default: 65434 11 | volumes: 12 | - ./CA:/opt/hexlicsrv/CA 13 | - ./config:/opt/hexlicsrv/config 14 | - ./logs:/opt/hexlicsrv/logs 15 | - ./data:/opt/hexlicsrv/data 16 | ports: 17 | - "65434:65434" 18 | -------------------------------------------------------------------------------- /hexlicsrv/image/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:12 2 | 3 | EXPOSE 65434 4 | 5 | RUN apt-get update && \ 6 | apt-get install -y python3 && \ 7 | apt-get clean && \ 8 | rm -rf /var/lib/apt/lists/* 9 | 10 | COPY hexlicsrv90_x64linux.run /tmp/hexlicsrv90_x64linux.run 11 | COPY entrypoint.sh /entrypoint.sh 12 | COPY patch.py /opt/hexlicsrv/patch.py 13 | 14 | RUN chmod +x /entrypoint.sh && \ 15 | echo -e '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\ny\n\ny\n\nn\ny\n\n' | /tmp/hexlicsrv90_x64linux.run --mode text && \ 16 | rm /tmp/hexlicsrv90_x64linux.run && \ 17 | mkdir -p /opt/hexlicsrv/{CA,config,data} 18 | 19 | ENTRYPOINT ["/entrypoint.sh"] 20 | -------------------------------------------------------------------------------- /hexlicsrv/image/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Installation and configuration paths 4 | INSTALL_PATH="/opt/hexlicsrv" 5 | CA_PATH="${INSTALL_PATH}/CA" 6 | CONFIG_PATH="${INSTALL_PATH}/config" 7 | LOGS_PATH="${INSTALL_PATH}/logs" 8 | DATA_PATH="${INSTALL_PATH}/data" 9 | SCHEMA_LOCK="${CONFIG_PATH}/hexlicsrv_schema.lock" 10 | 11 | # Default Variables 12 | LICENSE_HOST="${LICENSE_HOST:-localhost}" 13 | LICENSE_PORT="${LICENSE_PORT:-65434}" 14 | 15 | # Ensure directory structure 16 | mkdir -p "$CA_PATH" "$CONFIG_PATH" "$LOGS_PATH" "$DATA_PATH" 17 | 18 | # Change to installation directory 19 | cd "$INSTALL_PATH" || { echo "Failed to change directory to $INSTALL_PATH"; exit 1; } 20 | 21 | # Create configuration file if it doesn't exist 22 | CONFIG_FILE="${CONFIG_PATH}/hexlicsrv.conf" 23 | if [[ ! -f "$CONFIG_FILE" ]]; then 24 | echo "sqlite3;Data Source=${DATA_PATH}/hexlicsrv.sqlite3;" > "$CONFIG_FILE" 25 | chmod 640 "$CONFIG_FILE" 26 | fi 27 | 28 | # Check for Certification Authority files 29 | if [[ ! -f "${CA_PATH}/CA.pem" || ! -f "${CA_PATH}/CA.key" ]]; then 30 | echo "ERROR: Certification Authority files are missing in $CA_PATH!" 31 | sleep 5 32 | exit 1 33 | fi 34 | 35 | # Apply patch and set permissions 36 | python3 "${INSTALL_PATH}/patch.py" hexlicsrv || { echo "Patch script failed"; exit 1; } 37 | chown root:root "${INSTALL_PATH}/license_server" "${INSTALL_PATH}/lsadm" 38 | chmod 755 "${INSTALL_PATH}/license_server" "${INSTALL_PATH}/lsadm" 39 | 40 | # Recreate schema if not already done 41 | if [[ ! -f "$SCHEMA_LOCK" ]]; then 42 | "${INSTALL_PATH}/license_server" -f "$CONFIG_FILE" --recreate-schema 43 | touch "$SCHEMA_LOCK" 44 | fi 45 | 46 | # Generate TLS certificate chain 47 | openssl req -newkey rsa:2048 -keyout "${CONFIG_PATH}/hexlicsrv.key" \ 48 | -out "${CONFIG_PATH}/hexlicsrv.csr" -nodes -subj "/CN=${LICENSE_HOST}" || { 49 | echo "Failed to create TLS certificate request" 50 | exit 1 51 | } 52 | 53 | openssl x509 -req -in "${CONFIG_PATH}/hexlicsrv.csr" -CA "${CA_PATH}/CA.pem" \ 54 | -CAkey "${CA_PATH}/CA.key" -CAcreateserial -out "${CONFIG_PATH}/hexlicsrv.crt" \ 55 | -days 365 -sha512 -extfile <(cat <<-EOF 56 | [req] 57 | distinguished_name=req_distinguished_name 58 | [req_distinguished_name] 59 | [v3_req] 60 | keyUsage = critical, digitalSignature, keyEncipherment 61 | extendedKeyUsage = serverAuth 62 | subjectAltName = @alt_names 63 | [alt_names] 64 | DNS.1 = "$LICENSE_HOST" 65 | EOF 66 | ) || { echo "Failed to generate TLS certificate"; exit 1; } 67 | 68 | # Clean up certificate request file 69 | rm -f "${CONFIG_PATH}/hexlicsrv.csr" 70 | 71 | # Set permissions 72 | chmod 640 "$CONFIG_FILE" "${CONFIG_PATH}/hexlicsrv.crt" "${CONFIG_PATH}/hexlicsrv.key" "${INSTALL_PATH}/license_server.hexlic" 73 | 74 | # Start the license server 75 | "${INSTALL_PATH}/license_server" -f "$CONFIG_FILE" \ 76 | -p "$LICENSE_PORT" \ 77 | -l "${LOGS_PATH}/license_server.log" \ 78 | -c "${CONFIG_PATH}/hexlicsrv.crt" \ 79 | -k "${CONFIG_PATH}/hexlicsrv.key" \ 80 | -L "${INSTALL_PATH}/license_server.hexlic" 81 | 82 | sleep 30 83 | -------------------------------------------------------------------------------- /hexlicsrv/image/patch.py: -------------------------------------------------------------------------------- 1 | 2 | # Imports 3 | 4 | import platform 5 | import sys 6 | import hashlib 7 | import json 8 | 9 | from pathlib import Path 10 | from random import randint 11 | from datetime import datetime 12 | 13 | # General 14 | 15 | CURRENT_DIRECTORY = Path(__file__).parent 16 | OS_NAME = platform.system() 17 | 18 | ORIGINAL_ROOT_CA_CERTIFICATE = bytes.fromhex('2D2D2D2D2D424547494E2043455254494649434154452D2D2D2D2D0A4D4949463054434341376D6741774942416749554C7A4B74454F50395137562F4C2F4734526E76344C3376712F6845774451594A4B6F5A496876634E4151454E0A425141775644454C4D416B474131554542684D43516B5578447A414E42674E564241634D426B78707736686E5A5445564D424D47413155454367774D534756340A4C564A6865584D67553045754D5230774777594456515144444252495A586774556D46356379425451533467556D39766443424451544165467730794D4441310A4D4451784D5441794D446861467730304D4441304D6A6B784D5441794D4468614D465178437A414A42674E5642415954416B4A464D51387744515944565151480A44415A4D61634F6F5A3255784654415442674E5642416F4D4445686C6543315359586C7A49464E424C6A45644D4273474131554541777755534756344C564A680A65584D675530457549464A766233516751304577676749694D4130474353714753496233445145424151554141344943447741776767494B416F4943415144420A727345683438564E796A4350524F53597A773576694163664475426F4441486533624952594D61476D3261366F6D5358537A54303252416970536C4F366E4A5A0A2F50674E4569706158594C6245586D727247646E5364427538756235317431374164476347597A7A506A534970495648356D5832694F624864533367794E7A700A4A4B4A515543444D3646644A61385A637A744B772B6258734E3166744B615A437A4863755542633850356C6B6952476375596662694872693543303270476F310A3379344F7A3939536F74384B5566774E6842794F4F474F77655979666E394E676D6871686B427532372B367278706D7552376D48794F68666E4C732B707351300A796A4536627A756C32696C5746724F53614C41784B6268424C4C5144574359654276586D4530497A6D5A56626F32447154552B4E575245553661766D5252427A0A36526E5A484655686C324C56624A354172343542617752333862524E726F36564E4354713839724258564665436E6B394A613676345A416F576D6A4A757048430A70585449786F65626B6F655741774943757A36336357735268317932617164675136763979564572413634476867436B704A4F383248447441395369716765330A542B7267556E6A3170636C6C474B6778414659634B686C434C6C342B626D306F686C784630574638564D68472F54424C4E48334D6C4A466A6C4D6F4277516E6C0A4150686545675A576F5153456A416B7A524C55725277376B566B2F51743847356846474C6233556A4538534B44504B5259534241554E2F75503859484B46716F0A3261727054436931444F345371583872367A717A736C565466367557546971384D4E6B5A2F2B374E5972312F4A50543235694D6C7736736136673447555070510A7A685261507931396F62476534337534766A7079736539673576715839703375394D49313478336B36514944415141426F3447614D4947584D423047413155640A4467515742425161784E6163664D37584B6A4B4975744948726336746A6945394454416642674E5648534D454744415767425161784E6163664D37584B6A4B490A75744948726336746A6945394454415042674E5648524D4241663845425441444151482F4D41344741315564447745422F77514541774942686A413042674E560A485238454C5441724D436D674A36416C68694E6F644852774F69387659334A734C6D686C6543317959586C7A4C6D4E76625339796232393058324E684C6D4E790A6244414E42676B71686B6947397730424151304641414F4341674541644B7034496E70526B357A30426A50733643634A53674B624348304D585A7162742F454D0A2F34644A50766D4136744165784A7076396539426D542F444F423834514232787A516C45694E4F42372F56346A336F44696A356D4D77527971594C32346C33670A4841617677632B644C72707A582F3534755A6D4839624B7337796A33666B2F7655336537746837323041724C322F595A6A485632577830424D63732B595669740A70687647326D7875313644547069646D733370436A3235654549534A76586665385845664B4F503146784743706D4B7878367150486C4E41534F70357A6477560A6945696D6B677555777A43736D6D5049357245574C58644C52786330436B66666D62734E6D734638535A7A333843697775526C6963684444645A754A586A69370A6A6E5A46376830344D6F32414B507436774A392B36367259714469677650397348474B70517035687231444D756B46476E656933533968354B703865446852580A593234792F434A564E4F307278596F4650556E4F77625355463346777534665833457A71356557374E304E6C37733058484578622F5039666D685078514256310A677772363635696E71355A77443848397577474556703349425439634852753869655A7251444D49315571504F792B3245574E507459344B786D6765725462630A4E3056483442754538746478544755636B67344A5462734E525562717853586D534C396A4131644C425436336C624D4C49553036644964714E627078453447560A4D674F4C777177782F42462B465A6751547474646A6D7065786D6C364E49445647444278667945434A3576647778624B4D4952666F376670306A52706A5A70500A3862773442506E783059344E704D7A4B78695753306937726539694561666468364774704E796E4B55304A46534B7249776D4965634B462B5A345A55452F314B0A2B742F464F67493D0A2D2D2D2D2D454E442043455254494649434154452D2D2D2D2D0A00') 19 | ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS = bytes.fromhex('4D4949463054434341376D6741774942416749554C7A4B74454F50395137562F4C2F4734526E76344C3376712F6845774451594A4B6F5A496876634E4151454E425141775644454C4D416B474131554542684D43516B5578447A414E42674E564241634D426B78707736686E5A5445564D424D47413155454367774D534756344C564A6865584D67553045754D5230774777594456515144444252495A586774556D46356379425451533467556D39766443424451544165467730794D4441314D4451784D5441794D446861467730304D4441304D6A6B784D5441794D4468614D465178437A414A42674E5642415954416B4A464D513877445159445651514844415A4D61634F6F5A3255784654415442674E5642416F4D4445686C6543315359586C7A49464E424C6A45644D4273474131554541777755534756344C564A6865584D675530457549464A766233516751304577676749694D4130474353714753496233445145424151554141344943447741776767494B416F494341514442727345683438564E796A4350524F53597A773576694163664475426F4441486533624952594D61476D3261366F6D5358537A54303252416970536C4F366E4A5A2F50674E4569706158594C6245586D727247646E5364427538756235317431374164476347597A7A506A534970495648356D5832694F624864533367794E7A704A4B4A515543444D3646644A61385A637A744B772B6258734E3166744B615A437A4863755542633850356C6B6952476375596662694872693543303270476F313379344F7A3939536F74384B5566774E6842794F4F474F77655979666E394E676D6871686B427532372B367278706D7552376D48794F68666E4C732B70735130796A4536627A756C32696C5746724F53614C41784B6268424C4C5144574359654276586D4530497A6D5A56626F32447154552B4E575245553661766D5252427A36526E5A484655686C324C56624A354172343542617752333862524E726F36564E4354713839724258564665436E6B394A613676345A416F576D6A4A7570484370585449786F65626B6F655741774943757A36336357735268317932617164675136763979564572413634476867436B704A4F38324844744139536971676533542B7267556E6A3170636C6C474B6778414659634B686C434C6C342B626D306F686C784630574638564D68472F54424C4E48334D6C4A466A6C4D6F4277516E6C4150686545675A576F5153456A416B7A524C55725277376B566B2F51743847356846474C6233556A4538534B44504B5259534241554E2F75503859484B46716F3261727054436931444F345371583872367A717A736C565466367557546971384D4E6B5A2F2B374E5972312F4A50543235694D6C7736736136673447555070517A685261507931396F62476534337534766A7079736539673576715839703375394D49313478336B36514944415141426F3447614D4947584D423047413155644467515742425161784E6163664D37584B6A4B4975744948726336746A6945394454416642674E5648534D454744415767425161784E6163664D37584B6A4B4975744948726336746A6945394454415042674E5648524D4241663845425441444151482F4D41344741315564447745422F77514541774942686A413042674E56485238454C5441724D436D674A36416C68694E6F644852774F69387659334A734C6D686C6543317959586C7A4C6D4E76625339796232393058324E684C6D4E796244414E42676B71686B6947397730424151304641414F4341674541644B7034496E70526B357A30426A50733643634A53674B624348304D585A7162742F454D2F34644A50766D4136744165784A7076396539426D542F444F423834514232787A516C45694E4F42372F56346A336F44696A356D4D77527971594C32346C33674841617677632B644C72707A582F3534755A6D4839624B7337796A33666B2F7655336537746837323041724C322F595A6A485632577830424D63732B5956697470687647326D7875313644547069646D733370436A3235654549534A76586665385845664B4F503146784743706D4B7878367150486C4E41534F70357A6477566945696D6B677555777A43736D6D5049357245574C58644C52786330436B66666D62734E6D734638535A7A333843697775526C6963684444645A754A586A69376A6E5A46376830344D6F32414B507436774A392B36367259714469677650397348474B70517035687231444D756B46476E656933533968354B70386544685258593234792F434A564E4F307278596F4650556E4F77625355463346777534665833457A71356557374E304E6C37733058484578622F5039666D68507851425631677772363635696E71355A77443848397577474556703349425439634852753869655A7251444D49315571504F792B3245574E507459344B786D6765725462634E3056483442754538746478544755636B67344A5462734E525562717853586D534C396A4131644C425436336C624D4C49553036644964714E627078453447564D674F4C777177782F42462B465A6751547474646A6D7065786D6C364E49445647444278667945434A3576647778624B4D4952666F376670306A52706A5A70503862773442506E783059344E704D7A4B78695753306937726539694561666468364774704E796E4B55304A46534B7249776D4965634B462B5A345A55452F314B2B742F464F67493D00') 20 | ORIGINAL_PUBLIC_MODULUS = bytes.fromhex('EDFD425CF978546E8911225884436C57140525650BCF6EBFE80EDBC5FB1DE68F4C66C29CB22EB668788AFCB0ABBB718044584B810F8970CDDF227385F75D5DDDD91D4F18937A08AA83B28C49D12DC92E7505BB38809E91BD0FBD2F2E6AB1D2E33C0C55D5BDDD478EE8BF845FCEF3C82B9D2929ECB71F4D1B3DB96E3A8E7AAF93') 21 | 22 | PRIVATE_KEY = bytes.fromhex('77C86ABBB7F3BB134436797B68FF47BEB1A5457816608DBFB72641814DD464DD640D711D5732D3017A1C4E63D835822F00A4EAB619A2C4791CF33F9F57F9C2AE4D9EED9981E79AC9B8F8A411F68F25B9F0C05D04D11E22A3A0D8D4672B56A61F1532282FF4E4E74759E832B70E98B9D102D07E9FB9BA8D15810B144970029874') 23 | NEW_PUBLIC_MODULUS = bytes.fromhex('EDFD42CBF978546E8911225884436C57140525650BCF6EBFE80EDBC5FB1DE68F4C66C29CB22EB668788AFCB0ABBB718044584B810F8970CDDF227385F75D5DDDD91D4F18937A08AA83B28C49D12DC92E7505BB38809E91BD0FBD2F2E6AB1D2E33C0C55D5BDDD478EE8BF845FCEF3C82B9D2929ECB71F4D1B3DB96E3A8E7AAF93') 24 | 25 | HAVE_NEW_ROOT_CA_CERTIFICATE = False 26 | if CURRENT_DIRECTORY.joinpath('CA').joinpath('CA.pem').exists(): 27 | NEW_ROOT_CA_CERTIFICATE = b'' 28 | with open(CURRENT_DIRECTORY.joinpath('CA').joinpath('CA.pem'), 'rb') as f: 29 | NEW_ROOT_CA_CERTIFICATE += f.read() 30 | NEW_ROOT_CA_CERTIFICATE += b'\x00' 31 | 32 | NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS = NEW_ROOT_CA_CERTIFICATE \ 33 | .replace(b'-----BEGIN CERTIFICATE-----', b'') \ 34 | .replace(b'-----END CERTIFICATE-----', b'') \ 35 | .replace(b'\r\n', b'') \ 36 | .replace(b'\r', b'') \ 37 | .replace(b'\n', b'') 38 | 39 | if len(NEW_ROOT_CA_CERTIFICATE) > len(ORIGINAL_ROOT_CA_CERTIFICATE) or \ 40 | len(NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) > len(ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS): 41 | print('New CA certificate is too big!') 42 | else: 43 | NEW_ROOT_CA_CERTIFICATE += b'\x00' * (len(ORIGINAL_ROOT_CA_CERTIFICATE) - len(NEW_ROOT_CA_CERTIFICATE)) 44 | NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS += b'\x00' * (len(ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) - len(NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS)) 45 | 46 | HAVE_NEW_ROOT_CA_CERTIFICATE = True 47 | 48 | # Crypto functions 49 | 50 | def bytes_to_bigint(data: bytes) -> int: 51 | return int.from_bytes(data, byteorder='little') 52 | 53 | def bigint_to_bytes(n: int) -> bytes: 54 | return n.to_bytes((n.bit_length() + 7) // 8, byteorder='little') 55 | 56 | def decrypt_message(message: bytes, public_key: int, exponent: int = 0x13) -> bytes: 57 | decrypted = pow(bytes_to_bigint(message), exponent, public_key) 58 | decrypted = bigint_to_bytes(decrypted) 59 | return decrypted[::-1] 60 | 61 | def encrypt_message(message: bytes, private_key: int, public_key: int) -> bytes: 62 | encrypted = pow(bytes_to_bigint(message[::-1]), private_key, public_key) 63 | encrypted = bigint_to_bytes(encrypted) 64 | return encrypted 65 | 66 | # License 67 | 68 | # IDAPRO - IDA Pro 69 | # IDAEDU - IDA Educational 70 | # IDAPC - IDA Home for Intel x64 71 | # IDAARM - IDA Home for ARM 72 | # IDAPPC - IDA Home for PowerPC 73 | # IDAMIPS - IDA Home for MIPS 74 | # IDAM68K - IDA Home for Motorola 68K 75 | # IDABASE - Hex-Rays Base 76 | # IDACORE - Hex-Rays Core 77 | # IDAULT - Hex-Rays Ultra 78 | 79 | # code 80 | # HEXX64 - x64 Decompiler 81 | # HEXX86 - x86 Decompiler 82 | # HEXARM64 - ARM64 Decompiler 83 | # HEXARM - ARM Decompiler 84 | # HEXPPC64 - PowerPC64 Decompiler 85 | # HEXPPC - PowerPC Decompiler 86 | # HEXMIPS64 - MIPS64 Decompiler 87 | # HEXMIPS - MIPS Decompiler 88 | # HEXRV64 - RISC-V64 Decompiler 89 | # HEXRV - RISC-V Decompiler 90 | # HEXARC - ARC Decompiler 91 | # HEXARC64 - ARC64 Decompiler 92 | # HEXCX64 - x64 Decompiler (cloud) 93 | # HEXCX86 - x86 Decompiler (cloud) 94 | # HEXCARM64 - ARM64 Decompiler (cloud) 95 | # HEXCARM - ARM Decompiler (cloud) 96 | # HEXCPPC64 - PowerPC64 Decompiler (cloud) 97 | # HEXCPPC - PowerPC Decompiler (cloud) 98 | # HEXCMIPS64 - MIPS64 Decompiler (cloud) 99 | # HEXCMIPS - MIPS Decompiler (cloud) 100 | # HEXCRV64 - RISC-V64 Decompiler (cloud) 101 | # HEXCRV - RISC-V Decompiler (cloud) 102 | # HEXCARC - ARC Decompiler (cloud) 103 | # HEXCARC64 - ARC64 Decompiler (cloud) 104 | # LUMINA - Lumina Server 105 | # TEAMS - Vault Server 106 | 107 | def generate_add_on(code: str, owner: str, start_date: str, end_date: str, id: str) -> dict: 108 | data = { 109 | 'code': code, 110 | 'owner': owner, 111 | 'start_date': start_date, 112 | 'end_date': end_date, 113 | 'id': id 114 | } 115 | 116 | return data 117 | 118 | # product_id 119 | # IDAPRO 120 | # IDAHOME 121 | # IDAFREE 122 | # TEAMS_SERVER 123 | # LUMINA_SERVER 124 | # LICENSE_SERVER 125 | 126 | # edition_id: 127 | # ida-pro 128 | # ida-pro-classroom 129 | # ida-home-pc 130 | # ida-home-arm 131 | # ida-home-mips 132 | # ida-home-ppc 133 | # ida-home-riscv 134 | # ida-free 135 | # teams-server 136 | # lumina-server 137 | # license-server 138 | 139 | def generate_license(license_type: str, product_id: str, edition_id: str, description: str, seats: int, start_date: str, end_date: str, issued_on: str, owner: str, add_ons: list, features: list, id: str) -> dict: 140 | data = { 141 | 'license_type': license_type, 142 | 'product_id': product_id, 143 | 'edition_id': edition_id, 144 | 'description': description, 145 | 'seats': seats, 146 | 'start_date': start_date, 147 | 'end_date': end_date, 148 | 'issued_on': issued_on, 149 | 'owner': owner, 150 | 'add_ons': add_ons, 151 | 'features': features, 152 | 'id': id 153 | } 154 | 155 | return data 156 | 157 | def generate_license_package(version: int, name: str, email: str, licenses: list) -> dict: 158 | if version == 1: 159 | data = { 160 | 'header': { 'version': version }, 161 | 'payload': { 162 | 'name': name, 163 | 'email': email, 164 | 'licenses': licenses 165 | } 166 | } 167 | 168 | return data 169 | 170 | def to_alphabetical_json(d: dict) -> str: 171 | return json.dumps(d, sort_keys=True, separators=(',', ':')) 172 | 173 | def from_alphabetical_json(s: str) -> dict: 174 | return json.loads(s) 175 | 176 | def sign_license_package(license: dict, private_key: int, public_key: int) -> str: 177 | data = { 'payload': license['payload'] } 178 | data_str = to_alphabetical_json(data) 179 | 180 | buffer = bytearray(128) 181 | 182 | # First 33 bytes are random 183 | for i in range(33): 184 | buffer[i] = 0x42 185 | 186 | # Compute sha256 of the data 187 | sha256 = hashlib.sha256() 188 | sha256.update(data_str.encode()) 189 | digest = sha256.digest() 190 | 191 | # Copy the sha256 digest to the buffer 192 | for i in range(32): 193 | buffer[33 + i] = digest[i] 194 | 195 | # Encrypt the buffer 196 | encrypted = encrypt_message(buffer, private_key, public_key) 197 | 198 | return encrypted.hex().upper() 199 | 200 | # Patch 201 | 202 | def patch_file(file_path: Path) -> bool: 203 | data = None 204 | 205 | if file_path.exists(): 206 | with open(file_path, 'rb') as f: 207 | data = f.read() 208 | 209 | backup_file_path = file_path.parent / (file_path.name + '.bak') 210 | 211 | if not backup_file_path.exists(): 212 | with open(backup_file_path, 'wb') as sf: 213 | sf.write(data) 214 | else: 215 | with open(backup_file_path, 'rb') as sf: 216 | data = sf.read() 217 | 218 | if data: 219 | if HAVE_NEW_ROOT_CA_CERTIFICATE: 220 | if data.find(NEW_PUBLIC_MODULUS[:6]) != -1 or data.find(NEW_ROOT_CA_CERTIFICATE) != -1 or data.find(NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) != -1: 221 | print(f'INFO: `{file_path.name}` already has a patch.') 222 | return False 223 | 224 | if data.find(ORIGINAL_PUBLIC_MODULUS[:6]) == -1 and data.find(ORIGINAL_ROOT_CA_CERTIFICATE) == -1 and data.find(ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) == -1: 225 | print(f'ERROR: Patch for `{file_path.name}` is not supported!') 226 | return False 227 | else: 228 | if data.find(NEW_PUBLIC_MODULUS[:6]) != -1: 229 | print(f'INFO: `{file_path.name}` already has a patch.') 230 | return False 231 | 232 | if data.find(ORIGINAL_PUBLIC_MODULUS[:6]) == -1: 233 | print(f'ERROR: Patch for `{file_path.name}` is not supported!') 234 | return False 235 | 236 | data = data.replace(ORIGINAL_PUBLIC_MODULUS[:6], NEW_PUBLIC_MODULUS[:6]) 237 | 238 | if HAVE_NEW_ROOT_CA_CERTIFICATE: 239 | data = data.replace(ORIGINAL_ROOT_CA_CERTIFICATE, NEW_ROOT_CA_CERTIFICATE) 240 | data = data.replace(ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS, NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) 241 | 242 | with open(file_path, 'wb') as f: 243 | f.write(data) 244 | 245 | print(f'INFO: `{file_path.name}` successful patched.') 246 | 247 | # Main 248 | 249 | def generate_id(ID_0: int = randint(0x00, 0xFF), ID_1: int = randint(0x00, 0xFF), 250 | ID_2: int = randint(0x00, 0xFF), ID_3: int = randint(0x00, 0xFF), 251 | ID_4: int = randint(0x00, 0xFF), ID_5: int = randint(0x00, 0xFF)) -> list: 252 | return [ID_0, ID_1, ID_2, ID_3, ID_4, ID_5] 253 | 254 | def format_id(id:list) -> str: 255 | return f'{id[0]:02X}-{id[1]:02X}{id[2]:02X}-{id[3]:02X}{id[4]:02X}-{id[5]:02X}' 256 | 257 | def main(argv: list) -> int: 258 | 259 | private_key = bytes_to_bigint(PRIVATE_KEY) 260 | public_key = bytes_to_bigint(NEW_PUBLIC_MODULUS) 261 | 262 | if 'ida-pro' in argv: 263 | if OS_NAME == 'Linux': 264 | files = [ 265 | 'hv', 266 | 'hvui', 267 | 'libida.so', 268 | 'libida32.so', 269 | 'dbgsrv/linux_server', 270 | 'dbgsrv/linux_server32', 271 | 'dbgsrv/mac_server', 272 | 'dbgsrv/mac_server32', 273 | 'dbgsrv/mac_server_arm', 274 | 'dbgsrv/mac_server_arme', 275 | 'dbgsrv/win32_remote32', 276 | 'dbgsrv/win64_remote.exe', 277 | 'plugins/armlinux_stub.so', 278 | 'plugins/arm_mac_stub.so', 279 | 'plugins/dalvik_user.so', 280 | 'plugins/gdb_user.so', 281 | 'plugins/ios_user.so', 282 | 'plugins/linux_stub.so', 283 | 'plugins/mac_stub.so', 284 | 'plugins/pin_user.so', 285 | 'plugins/win32_stub.so', 286 | 'plugins/xnu_user.so', 287 | ] 288 | 289 | for file in files: 290 | patch_file(CURRENT_DIRECTORY.joinpath(file)) 291 | 292 | elif OS_NAME == 'Windows': 293 | files = [ 294 | 'hv.exe', 295 | 'hvui.exe', 296 | 'ida.dll', 297 | 'ida32.dll', 298 | 'dbgsrv/linux_server', 299 | 'dbgsrv/linux_server32', 300 | 'dbgsrv/mac_server', 301 | 'dbgsrv/mac_server32', 302 | 'dbgsrv/mac_server_arm', 303 | 'dbgsrv/mac_server_arme', 304 | 'dbgsrv/win32_remote32', 305 | 'dbgsrv/win64_remote.exe', 306 | 'plugins/armlinux_stub.dll', 307 | 'plugins/arm_mac_stub.dll', 308 | 'plugins/dalvik_user.dll', 309 | 'plugins/gdb_user.dll', 310 | 'plugins/ios_user.dll', 311 | 'plugins/linux_stub.dll', 312 | 'plugins/mac_stub.dll', 313 | 'plugins/pin_user.dll', 314 | 'plugins/win32_stub.dll', 315 | 'plugins/xnu_user.dll', 316 | ] 317 | 318 | for file in files: 319 | patch_file(CURRENT_DIRECTORY.joinpath(file)) 320 | 321 | elif OS_NAME == 'iOS': 322 | files = [ 323 | 'hv', 324 | 'hvui', 325 | 'libida.dylib', 326 | 'libida32.dylib', 327 | 'dbgsrv/linux_server', 328 | 'dbgsrv/linux_server32', 329 | 'dbgsrv/mac_server', 330 | 'dbgsrv/mac_server32', 331 | 'dbgsrv/mac_server_arm', 332 | 'dbgsrv/mac_server_arme', 333 | 'dbgsrv/win32_remote32', 334 | 'dbgsrv/win64_remote.exe', 335 | 'plugins/armlinux_stub.dylib', 336 | 'plugins/arm_mac_stub.dylib', 337 | 'plugins/dalvik_user.dylib', 338 | 'plugins/gdb_user.dylib', 339 | 'plugins/ios_user.dylib', 340 | 'plugins/linux_stub.dylib', 341 | 'plugins/mac_stub.dylib', 342 | 'plugins/pin_user.dylib', 343 | 'plugins/win32_stub.dylib', 344 | 'plugins/xnu_user.dylib', 345 | ] 346 | 347 | for file in files: 348 | patch_file(CURRENT_DIRECTORY.joinpath(file)) 349 | 350 | license_path = CURRENT_DIRECTORY.joinpath('idapro.hexlic') 351 | is_valid_license = False 352 | if license_path.exists(): 353 | with open(license_path, 'r') as f: 354 | license_package = from_alphabetical_json(f.read()) 355 | if sign_license_package(license_package, private_key, public_key) == license_package['signature']: 356 | is_valid_license = True 357 | if is_valid_license: 358 | return 0 359 | 360 | # Set up 361 | 362 | start_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 363 | end_date = '2038-01-19 03:14:07' 364 | owner = 'RenardDev' 365 | name = 'RenardDev' 366 | email = 'zeze839@gmail.com' 367 | 368 | license_id = generate_id(ID_5=0x00) 369 | 370 | # Add-ons 371 | 372 | add_ons_list = [ 373 | 'HEXX86', 374 | 'HEXX64', 375 | 'HEXARM', 376 | 'HEXARM64', 377 | 'HEXMIPS', 378 | 'HEXMIPS64', 379 | 'HEXPPC', 380 | 'HEXPPC64', 381 | 'HEXRV64', 382 | 'HEXARC', 383 | 'HEXARC64' 384 | ] 385 | 386 | add_ons = [] 387 | for idx, add_on in enumerate(add_ons_list): 388 | license_id_copy = license_id.copy() 389 | license_id_copy[5] += idx + 1 390 | add_ons.append(generate_add_on(add_on, format_id(license_id), start_date, end_date, format_id(license_id_copy))) 391 | 392 | # Licenses 393 | 394 | licenses = [ 395 | generate_license('named', 'IDAPRO', 'ida-pro', 'Licensed by RenardDev', 1, start_date, end_date, start_date, owner, add_ons, [], format_id(license_id)) 396 | ] 397 | 398 | # Package 399 | 400 | license_package = generate_license_package(1, name, email, licenses) 401 | license_package['signature'] = sign_license_package(license_package, private_key, public_key) 402 | 403 | # File 404 | 405 | serialized = to_alphabetical_json(license_package) 406 | with open(license_path, 'w') as f: 407 | f.write(serialized) 408 | print('INFO: License generated!') 409 | 410 | if 'hexvault' in argv: 411 | if OS_NAME == 'Linux': 412 | patch_file(CURRENT_DIRECTORY.joinpath('vault_server')) 413 | 414 | license_path = CURRENT_DIRECTORY.joinpath('teams_server.hexlic') 415 | is_valid_license = False 416 | if license_path.exists(): 417 | with open(license_path, 'r') as f: 418 | license_package = from_alphabetical_json(f.read()) 419 | if sign_license_package(license_package, private_key, public_key) == license_package['signature']: 420 | is_valid_license = True 421 | if is_valid_license: 422 | return 0 423 | 424 | # Set up 425 | 426 | start_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 427 | end_date = '2038-01-19 03:14:07' 428 | seats = 2147483647 429 | owner = '00:00:00:00:00:00' 430 | name = 'RenardDev' 431 | email = 'zeze839@gmail.com' 432 | 433 | license_id = generate_id(ID_5=0x00) 434 | 435 | # Add-ons 436 | 437 | add_ons_list = [ 438 | 'TEAMS' 439 | ] 440 | 441 | add_ons = [] 442 | for idx, add_on in enumerate(add_ons_list): 443 | license_id_copy = license_id.copy() 444 | license_id_copy[5] += idx + 1 445 | add_ons.append(generate_add_on(add_on, format_id(license_id), start_date, end_date, format_id(license_id_copy))) 446 | 447 | # Licenses 448 | 449 | licenses = [ 450 | generate_license('named', 'TEAMS_SERVER', 'teams-server', 'Licensed by RenardDev', seats, start_date, end_date, start_date, owner, add_ons, [], format_id(license_id)) 451 | ] 452 | 453 | # Package 454 | 455 | license_package = generate_license_package(1, name, email, licenses) 456 | license_package['signature'] = sign_license_package(license_package, private_key, public_key) 457 | 458 | # File 459 | 460 | serialized = to_alphabetical_json(license_package) 461 | with open(license_path, 'w') as f: 462 | f.write(serialized) 463 | print('INFO: License generated!') 464 | 465 | if 'lumina' in argv: 466 | if OS_NAME == 'Linux': 467 | patch_file(CURRENT_DIRECTORY.joinpath('lumina_server')) 468 | patch_file(CURRENT_DIRECTORY.joinpath('lc')) 469 | 470 | license_path = CURRENT_DIRECTORY.joinpath('lumina_server.hexlic') 471 | is_valid_license = False 472 | if license_path.exists(): 473 | with open(license_path, 'r') as f: 474 | license_package = from_alphabetical_json(f.read()) 475 | if sign_license_package(license_package, private_key, public_key) == license_package['signature']: 476 | is_valid_license = True 477 | if is_valid_license: 478 | return 0 479 | 480 | # Set up 481 | 482 | start_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 483 | end_date = '2038-01-19 03:14:07' 484 | seats = 2147483647 485 | owner = '00:00:00:00:00:00' 486 | name = 'RenardDev' 487 | email = 'zeze839@gmail.com' 488 | 489 | license_id = generate_id(ID_5=0x00) 490 | 491 | # Add-ons 492 | 493 | add_ons_list = [ 494 | 'LUMINA' 495 | ] 496 | 497 | add_ons = [] 498 | for idx, add_on in enumerate(add_ons_list): 499 | license_id_copy = license_id.copy() 500 | license_id_copy[5] += idx + 1 501 | add_ons.append(generate_add_on(add_on, format_id(license_id), start_date, end_date, format_id(license_id_copy))) 502 | 503 | # Licenses 504 | 505 | licenses = [ 506 | generate_license('named', 'LUMINA_SERVER', 'lumina-server', 'Licensed by RenardDev', seats, start_date, end_date, start_date, owner, add_ons, [], format_id(license_id)) 507 | ] 508 | 509 | # Package 510 | 511 | license_package = generate_license_package(1, name, email, licenses) 512 | license_package['signature'] = sign_license_package(license_package, private_key, public_key) 513 | 514 | # File 515 | 516 | serialized = to_alphabetical_json(license_package) 517 | with open(license_path, 'w') as f: 518 | f.write(serialized) 519 | print('INFO: License generated!') 520 | 521 | if 'hexlicsrv' in argv: 522 | if OS_NAME == 'Linux': 523 | patch_file(CURRENT_DIRECTORY.joinpath('license_server')) 524 | patch_file(CURRENT_DIRECTORY.joinpath('lsadm')) 525 | 526 | license_path = CURRENT_DIRECTORY.joinpath('license_server.hexlic') 527 | is_valid_license = False 528 | if license_path.exists(): 529 | with open(license_path, 'r') as f: 530 | license_package = from_alphabetical_json(f.read()) 531 | if sign_license_package(license_package, private_key, public_key) == license_package['signature']: 532 | is_valid_license = True 533 | if is_valid_license: 534 | return 0 535 | 536 | # Set up 537 | 538 | start_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 539 | end_date = '2038-01-19 03:14:07' 540 | seats = 2147483647 541 | owner_hexlicsrv = '00:00:00:00:00:00' 542 | owner = 'RenardDev' 543 | name = 'RenardDev' 544 | email = 'zeze839@gmail.com' 545 | 546 | hexlicsrv_license_id = generate_id(ID_5=0x00) 547 | license_id = generate_id(ID_5=0x00) 548 | 549 | # Add-ons 550 | 551 | add_ons_list = [ 552 | 'HEXX86', 553 | 'HEXX64', 554 | 'HEXARM', 555 | 'HEXARM64', 556 | 'HEXMIPS', 557 | 'HEXMIPS64', 558 | 'HEXPPC', 559 | 'HEXPPC64', 560 | 'HEXRV64', 561 | 'HEXARC', 562 | 'HEXARC64' 563 | ] 564 | 565 | add_ons = [] 566 | for idx, add_on in enumerate(add_ons_list): 567 | license_id_copy = license_id.copy() 568 | license_id_copy[5] += idx + 1 569 | add_ons.append(generate_add_on(add_on, format_id(license_id), start_date, end_date, format_id(license_id_copy))) 570 | 571 | # Licenses 572 | 573 | licenses = [ 574 | generate_license('named', 'LICENSE_SERVER', 'license-server', 'Licensed by RenardDev', seats, start_date, end_date, start_date, owner_hexlicsrv, [], [], format_id(hexlicsrv_license_id)), 575 | generate_license('floating', 'IDAPRO', 'ida-pro', 'Licensed by RenardDev', seats, start_date, end_date, start_date, owner, add_ons, [], format_id(license_id)) 576 | ] 577 | 578 | # Package 579 | 580 | license_package = generate_license_package(1, name, email, licenses) 581 | license_package['signature'] = sign_license_package(license_package, private_key, public_key) 582 | 583 | # File 584 | 585 | serialized = to_alphabetical_json(license_package) 586 | with open(license_path, 'w') as f: 587 | f.write(serialized) 588 | print('INFO: License generated!') 589 | 590 | return 0 591 | 592 | if __name__ == '__main__': 593 | sys.exit(main(sys.argv)) 594 | -------------------------------------------------------------------------------- /hexlicsrv/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /hexvault/CA/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /hexvault/config/hexvault.conf: -------------------------------------------------------------------------------- 1 | sqlite3;Data Source=/opt/hexvault/data/hexvault.sqlite3; 2 | -------------------------------------------------------------------------------- /hexvault/data/store/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /hexvault/docker-compose.yml: -------------------------------------------------------------------------------- 1 | 2 | services: 3 | hexvault: 4 | container_name: hexvault 5 | build: 6 | context: ./image 7 | restart: always 8 | environment: 9 | - VAULT_HOST=reversing.example.com 10 | - VAULT_PORT=65433 # Optional; Default: 65433 11 | volumes: 12 | - ./CA:/opt/hexvault/CA 13 | - ./config:/opt/hexvault/config 14 | - ./logs:/opt/hexvault/logs 15 | - ./data:/opt/hexvault/data 16 | ports: 17 | - "65433:65433" 18 | -------------------------------------------------------------------------------- /hexvault/image/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:12 2 | 3 | EXPOSE 65433 4 | 5 | RUN apt-get update && \ 6 | apt-get install -y python3 && \ 7 | apt-get clean && \ 8 | rm -rf /var/lib/apt/lists/* 9 | 10 | COPY hexvault90_x64linux.run /tmp/hexvault90_x64linux.run 11 | COPY entrypoint.sh /entrypoint.sh 12 | COPY patch.py /opt/hexvault/patch.py 13 | 14 | RUN chmod +x /entrypoint.sh && \ 15 | echo -e '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\ny\n\ny\n\nn\ny\n\n' | /tmp/hexvault90_x64linux.run --mode text && \ 16 | rm /tmp/hexvault90_x64linux.run && \ 17 | mkdir -p /opt/hexvault/{CA,config,data} 18 | 19 | ENTRYPOINT ["/entrypoint.sh"] 20 | -------------------------------------------------------------------------------- /hexvault/image/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Installation and configuration paths 4 | INSTALL_PATH="/opt/hexvault" 5 | CA_PATH="${INSTALL_PATH}/CA" 6 | CONFIG_PATH="${INSTALL_PATH}/config" 7 | LOGS_PATH="${INSTALL_PATH}/logs" 8 | DATA_PATH="${INSTALL_PATH}/data" 9 | SCHEMA_LOCK="${CONFIG_PATH}/hexvault_schema.lock" 10 | 11 | # Default Variables 12 | VAULT_HOST="${VAULT_HOST:-localhost}" 13 | VAULT_PORT="${VAULT_PORT:-65433}" 14 | 15 | # Ensure directory structure 16 | mkdir -p "$CA_PATH" "$CONFIG_PATH" "$LOGS_PATH" "$DATA_PATH" 17 | 18 | # Set working directory 19 | cd "$INSTALL_PATH" || { echo "Failed to change directory to $INSTALL_PATH"; exit 1; } 20 | 21 | # Generate configuration file if it doesn't exist 22 | CONFIG_FILE="${CONFIG_PATH}/hexvault.conf" 23 | if [[ ! -f "$CONFIG_FILE" ]]; then 24 | echo "sqlite3;Data Source=${DATA_PATH}/hexvault.sqlite3;" > "$CONFIG_FILE" 25 | chmod 640 "$CONFIG_FILE" 26 | fi 27 | 28 | # Check for Certification Authority files 29 | if [[ ! -f "${CA_PATH}/CA.pem" || ! -f "${CA_PATH}/CA.key" ]]; then 30 | echo "ERROR: Certification Authority files are missing in $CA_PATH!" 31 | sleep 5 32 | exit 1 33 | fi 34 | 35 | # Apply patch 36 | python3 "${INSTALL_PATH}/patch.py" hexvault || { echo "Patch script failed"; exit 1; } 37 | chown root:root "${INSTALL_PATH}/vault_server" 38 | chmod 755 "${INSTALL_PATH}/vault_server" 39 | 40 | # Recreate schema if not already done 41 | if [[ ! -f "$SCHEMA_LOCK" ]]; then 42 | "${INSTALL_PATH}/vault_server" -f "$CONFIG_FILE" -d "$DATA_PATH" --recreate-schema 43 | touch "$SCHEMA_LOCK" 44 | fi 45 | 46 | # Generate TLS certificate chain 47 | openssl req -newkey rsa:2048 -keyout "${CONFIG_PATH}/hexvault.key" \ 48 | -out "${CONFIG_PATH}/hexvault.csr" -nodes -subj "/CN=${VAULT_HOST}" || { 49 | echo "Failed to create TLS certificate request" 50 | exit 1 51 | } 52 | 53 | openssl x509 -req -in "${CONFIG_PATH}/hexvault.csr" -CA "${CA_PATH}/CA.pem" \ 54 | -CAkey "${CA_PATH}/CA.key" -CAcreateserial -out "${CONFIG_PATH}/hexvault.crt" \ 55 | -days 365 -sha512 -extfile <(cat <<-EOF 56 | [req] 57 | distinguished_name=req_distinguished_name 58 | [req_distinguished_name] 59 | [v3_req] 60 | keyUsage = critical, digitalSignature, keyEncipherment 61 | extendedKeyUsage = serverAuth 62 | subjectAltName = @alt_names 63 | [alt_names] 64 | DNS.1 = "$VAULT_HOST" 65 | EOF 66 | ) || { echo "Failed to generate TLS certificate"; exit 1; } 67 | 68 | # Clean up certificate request 69 | rm -f "${CONFIG_PATH}/hexvault.csr" 70 | 71 | # Set permissions 72 | chmod 640 "$CONFIG_FILE" "${CONFIG_PATH}/hexvault.crt" "${CONFIG_PATH}/hexvault.key" "${INSTALL_PATH}/teams_server.hexlic" 73 | 74 | # Start vault server 75 | "${INSTALL_PATH}/vault_server" -f "$CONFIG_FILE" \ 76 | -p "$VAULT_PORT" \ 77 | -l "${LOGS_PATH}/vault_server.log" \ 78 | -c "${CONFIG_PATH}/hexvault.crt" \ 79 | -k "${CONFIG_PATH}/hexvault.key" \ 80 | -L "${INSTALL_PATH}/teams_server.hexlic" \ 81 | -d "$DATA_PATH" 82 | 83 | sleep 30 84 | -------------------------------------------------------------------------------- /hexvault/image/patch.py: -------------------------------------------------------------------------------- 1 | 2 | # Imports 3 | 4 | import platform 5 | import sys 6 | import hashlib 7 | import json 8 | 9 | from pathlib import Path 10 | from random import randint 11 | from datetime import datetime 12 | 13 | # General 14 | 15 | CURRENT_DIRECTORY = Path(__file__).parent 16 | OS_NAME = platform.system() 17 | 18 | ORIGINAL_ROOT_CA_CERTIFICATE = bytes.fromhex('2D2D2D2D2D424547494E2043455254494649434154452D2D2D2D2D0A4D4949463054434341376D6741774942416749554C7A4B74454F50395137562F4C2F4734526E76344C3376712F6845774451594A4B6F5A496876634E4151454E0A425141775644454C4D416B474131554542684D43516B5578447A414E42674E564241634D426B78707736686E5A5445564D424D47413155454367774D534756340A4C564A6865584D67553045754D5230774777594456515144444252495A586774556D46356379425451533467556D39766443424451544165467730794D4441310A4D4451784D5441794D446861467730304D4441304D6A6B784D5441794D4468614D465178437A414A42674E5642415954416B4A464D51387744515944565151480A44415A4D61634F6F5A3255784654415442674E5642416F4D4445686C6543315359586C7A49464E424C6A45644D4273474131554541777755534756344C564A680A65584D675530457549464A766233516751304577676749694D4130474353714753496233445145424151554141344943447741776767494B416F4943415144420A727345683438564E796A4350524F53597A773576694163664475426F4441486533624952594D61476D3261366F6D5358537A54303252416970536C4F366E4A5A0A2F50674E4569706158594C6245586D727247646E5364427538756235317431374164476347597A7A506A534970495648356D5832694F624864533367794E7A700A4A4B4A515543444D3646644A61385A637A744B772B6258734E3166744B615A437A4863755542633850356C6B6952476375596662694872693543303270476F310A3379344F7A3939536F74384B5566774E6842794F4F474F77655979666E394E676D6871686B427532372B367278706D7552376D48794F68666E4C732B707351300A796A4536627A756C32696C5746724F53614C41784B6268424C4C5144574359654276586D4530497A6D5A56626F32447154552B4E575245553661766D5252427A0A36526E5A484655686C324C56624A354172343542617752333862524E726F36564E4354713839724258564665436E6B394A613676345A416F576D6A4A757048430A70585449786F65626B6F655741774943757A36336357735268317932617164675136763979564572413634476867436B704A4F383248447441395369716765330A542B7267556E6A3170636C6C474B6778414659634B686C434C6C342B626D306F686C784630574638564D68472F54424C4E48334D6C4A466A6C4D6F4277516E6C0A4150686545675A576F5153456A416B7A524C55725277376B566B2F51743847356846474C6233556A4538534B44504B5259534241554E2F75503859484B46716F0A3261727054436931444F345371583872367A717A736C565466367557546971384D4E6B5A2F2B374E5972312F4A50543235694D6C7736736136673447555070510A7A685261507931396F62476534337534766A7079736539673576715839703375394D49313478336B36514944415141426F3447614D4947584D423047413155640A4467515742425161784E6163664D37584B6A4B4975744948726336746A6945394454416642674E5648534D454744415767425161784E6163664D37584B6A4B490A75744948726336746A6945394454415042674E5648524D4241663845425441444151482F4D41344741315564447745422F77514541774942686A413042674E560A485238454C5441724D436D674A36416C68694E6F644852774F69387659334A734C6D686C6543317959586C7A4C6D4E76625339796232393058324E684C6D4E790A6244414E42676B71686B6947397730424151304641414F4341674541644B7034496E70526B357A30426A50733643634A53674B624348304D585A7162742F454D0A2F34644A50766D4136744165784A7076396539426D542F444F423834514232787A516C45694E4F42372F56346A336F44696A356D4D77527971594C32346C33670A4841617677632B644C72707A582F3534755A6D4839624B7337796A33666B2F7655336537746837323041724C322F595A6A485632577830424D63732B595669740A70687647326D7875313644547069646D733370436A3235654549534A76586665385845664B4F503146784743706D4B7878367150486C4E41534F70357A6477560A6945696D6B677555777A43736D6D5049357245574C58644C52786330436B66666D62734E6D734638535A7A333843697775526C6963684444645A754A586A69370A6A6E5A46376830344D6F32414B507436774A392B36367259714469677650397348474B70517035687231444D756B46476E656933533968354B703865446852580A593234792F434A564E4F307278596F4650556E4F77625355463346777534665833457A71356557374E304E6C37733058484578622F5039666D685078514256310A677772363635696E71355A77443848397577474556703349425439634852753869655A7251444D49315571504F792B3245574E507459344B786D6765725462630A4E3056483442754538746478544755636B67344A5462734E525562717853586D534C396A4131644C425436336C624D4C49553036644964714E627078453447560A4D674F4C777177782F42462B465A6751547474646A6D7065786D6C364E49445647444278667945434A3576647778624B4D4952666F376670306A52706A5A70500A3862773442506E783059344E704D7A4B78695753306937726539694561666468364774704E796E4B55304A46534B7249776D4965634B462B5A345A55452F314B0A2B742F464F67493D0A2D2D2D2D2D454E442043455254494649434154452D2D2D2D2D0A00') 19 | ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS = bytes.fromhex('4D4949463054434341376D6741774942416749554C7A4B74454F50395137562F4C2F4734526E76344C3376712F6845774451594A4B6F5A496876634E4151454E425141775644454C4D416B474131554542684D43516B5578447A414E42674E564241634D426B78707736686E5A5445564D424D47413155454367774D534756344C564A6865584D67553045754D5230774777594456515144444252495A586774556D46356379425451533467556D39766443424451544165467730794D4441314D4451784D5441794D446861467730304D4441304D6A6B784D5441794D4468614D465178437A414A42674E5642415954416B4A464D513877445159445651514844415A4D61634F6F5A3255784654415442674E5642416F4D4445686C6543315359586C7A49464E424C6A45644D4273474131554541777755534756344C564A6865584D675530457549464A766233516751304577676749694D4130474353714753496233445145424151554141344943447741776767494B416F494341514442727345683438564E796A4350524F53597A773576694163664475426F4441486533624952594D61476D3261366F6D5358537A54303252416970536C4F366E4A5A2F50674E4569706158594C6245586D727247646E5364427538756235317431374164476347597A7A506A534970495648356D5832694F624864533367794E7A704A4B4A515543444D3646644A61385A637A744B772B6258734E3166744B615A437A4863755542633850356C6B6952476375596662694872693543303270476F313379344F7A3939536F74384B5566774E6842794F4F474F77655979666E394E676D6871686B427532372B367278706D7552376D48794F68666E4C732B70735130796A4536627A756C32696C5746724F53614C41784B6268424C4C5144574359654276586D4530497A6D5A56626F32447154552B4E575245553661766D5252427A36526E5A484655686C324C56624A354172343542617752333862524E726F36564E4354713839724258564665436E6B394A613676345A416F576D6A4A7570484370585449786F65626B6F655741774943757A36336357735268317932617164675136763979564572413634476867436B704A4F38324844744139536971676533542B7267556E6A3170636C6C474B6778414659634B686C434C6C342B626D306F686C784630574638564D68472F54424C4E48334D6C4A466A6C4D6F4277516E6C4150686545675A576F5153456A416B7A524C55725277376B566B2F51743847356846474C6233556A4538534B44504B5259534241554E2F75503859484B46716F3261727054436931444F345371583872367A717A736C565466367557546971384D4E6B5A2F2B374E5972312F4A50543235694D6C7736736136673447555070517A685261507931396F62476534337534766A7079736539673576715839703375394D49313478336B36514944415141426F3447614D4947584D423047413155644467515742425161784E6163664D37584B6A4B4975744948726336746A6945394454416642674E5648534D454744415767425161784E6163664D37584B6A4B4975744948726336746A6945394454415042674E5648524D4241663845425441444151482F4D41344741315564447745422F77514541774942686A413042674E56485238454C5441724D436D674A36416C68694E6F644852774F69387659334A734C6D686C6543317959586C7A4C6D4E76625339796232393058324E684C6D4E796244414E42676B71686B6947397730424151304641414F4341674541644B7034496E70526B357A30426A50733643634A53674B624348304D585A7162742F454D2F34644A50766D4136744165784A7076396539426D542F444F423834514232787A516C45694E4F42372F56346A336F44696A356D4D77527971594C32346C33674841617677632B644C72707A582F3534755A6D4839624B7337796A33666B2F7655336537746837323041724C322F595A6A485632577830424D63732B5956697470687647326D7875313644547069646D733370436A3235654549534A76586665385845664B4F503146784743706D4B7878367150486C4E41534F70357A6477566945696D6B677555777A43736D6D5049357245574C58644C52786330436B66666D62734E6D734638535A7A333843697775526C6963684444645A754A586A69376A6E5A46376830344D6F32414B507436774A392B36367259714469677650397348474B70517035687231444D756B46476E656933533968354B70386544685258593234792F434A564E4F307278596F4650556E4F77625355463346777534665833457A71356557374E304E6C37733058484578622F5039666D68507851425631677772363635696E71355A77443848397577474556703349425439634852753869655A7251444D49315571504F792B3245574E507459344B786D6765725462634E3056483442754538746478544755636B67344A5462734E525562717853586D534C396A4131644C425436336C624D4C49553036644964714E627078453447564D674F4C777177782F42462B465A6751547474646A6D7065786D6C364E49445647444278667945434A3576647778624B4D4952666F376670306A52706A5A70503862773442506E783059344E704D7A4B78695753306937726539694561666468364774704E796E4B55304A46534B7249776D4965634B462B5A345A55452F314B2B742F464F67493D00') 20 | ORIGINAL_PUBLIC_MODULUS = bytes.fromhex('EDFD425CF978546E8911225884436C57140525650BCF6EBFE80EDBC5FB1DE68F4C66C29CB22EB668788AFCB0ABBB718044584B810F8970CDDF227385F75D5DDDD91D4F18937A08AA83B28C49D12DC92E7505BB38809E91BD0FBD2F2E6AB1D2E33C0C55D5BDDD478EE8BF845FCEF3C82B9D2929ECB71F4D1B3DB96E3A8E7AAF93') 21 | 22 | PRIVATE_KEY = bytes.fromhex('77C86ABBB7F3BB134436797B68FF47BEB1A5457816608DBFB72641814DD464DD640D711D5732D3017A1C4E63D835822F00A4EAB619A2C4791CF33F9F57F9C2AE4D9EED9981E79AC9B8F8A411F68F25B9F0C05D04D11E22A3A0D8D4672B56A61F1532282FF4E4E74759E832B70E98B9D102D07E9FB9BA8D15810B144970029874') 23 | NEW_PUBLIC_MODULUS = bytes.fromhex('EDFD42CBF978546E8911225884436C57140525650BCF6EBFE80EDBC5FB1DE68F4C66C29CB22EB668788AFCB0ABBB718044584B810F8970CDDF227385F75D5DDDD91D4F18937A08AA83B28C49D12DC92E7505BB38809E91BD0FBD2F2E6AB1D2E33C0C55D5BDDD478EE8BF845FCEF3C82B9D2929ECB71F4D1B3DB96E3A8E7AAF93') 24 | 25 | HAVE_NEW_ROOT_CA_CERTIFICATE = False 26 | if CURRENT_DIRECTORY.joinpath('CA').joinpath('CA.pem').exists(): 27 | NEW_ROOT_CA_CERTIFICATE = b'' 28 | with open(CURRENT_DIRECTORY.joinpath('CA').joinpath('CA.pem'), 'rb') as f: 29 | NEW_ROOT_CA_CERTIFICATE += f.read() 30 | NEW_ROOT_CA_CERTIFICATE += b'\x00' 31 | 32 | NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS = NEW_ROOT_CA_CERTIFICATE \ 33 | .replace(b'-----BEGIN CERTIFICATE-----', b'') \ 34 | .replace(b'-----END CERTIFICATE-----', b'') \ 35 | .replace(b'\r\n', b'') \ 36 | .replace(b'\r', b'') \ 37 | .replace(b'\n', b'') 38 | 39 | if len(NEW_ROOT_CA_CERTIFICATE) > len(ORIGINAL_ROOT_CA_CERTIFICATE) or \ 40 | len(NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) > len(ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS): 41 | print('New CA certificate is too big!') 42 | else: 43 | NEW_ROOT_CA_CERTIFICATE += b'\x00' * (len(ORIGINAL_ROOT_CA_CERTIFICATE) - len(NEW_ROOT_CA_CERTIFICATE)) 44 | NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS += b'\x00' * (len(ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) - len(NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS)) 45 | 46 | HAVE_NEW_ROOT_CA_CERTIFICATE = True 47 | 48 | # Crypto functions 49 | 50 | def bytes_to_bigint(data: bytes) -> int: 51 | return int.from_bytes(data, byteorder='little') 52 | 53 | def bigint_to_bytes(n: int) -> bytes: 54 | return n.to_bytes((n.bit_length() + 7) // 8, byteorder='little') 55 | 56 | def decrypt_message(message: bytes, public_key: int, exponent: int = 0x13) -> bytes: 57 | decrypted = pow(bytes_to_bigint(message), exponent, public_key) 58 | decrypted = bigint_to_bytes(decrypted) 59 | return decrypted[::-1] 60 | 61 | def encrypt_message(message: bytes, private_key: int, public_key: int) -> bytes: 62 | encrypted = pow(bytes_to_bigint(message[::-1]), private_key, public_key) 63 | encrypted = bigint_to_bytes(encrypted) 64 | return encrypted 65 | 66 | # License 67 | 68 | # IDAPRO - IDA Pro 69 | # IDAEDU - IDA Educational 70 | # IDAPC - IDA Home for Intel x64 71 | # IDAARM - IDA Home for ARM 72 | # IDAPPC - IDA Home for PowerPC 73 | # IDAMIPS - IDA Home for MIPS 74 | # IDAM68K - IDA Home for Motorola 68K 75 | # IDABASE - Hex-Rays Base 76 | # IDACORE - Hex-Rays Core 77 | # IDAULT - Hex-Rays Ultra 78 | 79 | # code 80 | # HEXX64 - x64 Decompiler 81 | # HEXX86 - x86 Decompiler 82 | # HEXARM64 - ARM64 Decompiler 83 | # HEXARM - ARM Decompiler 84 | # HEXPPC64 - PowerPC64 Decompiler 85 | # HEXPPC - PowerPC Decompiler 86 | # HEXMIPS64 - MIPS64 Decompiler 87 | # HEXMIPS - MIPS Decompiler 88 | # HEXRV64 - RISC-V64 Decompiler 89 | # HEXRV - RISC-V Decompiler 90 | # HEXARC - ARC Decompiler 91 | # HEXARC64 - ARC64 Decompiler 92 | # HEXCX64 - x64 Decompiler (cloud) 93 | # HEXCX86 - x86 Decompiler (cloud) 94 | # HEXCARM64 - ARM64 Decompiler (cloud) 95 | # HEXCARM - ARM Decompiler (cloud) 96 | # HEXCPPC64 - PowerPC64 Decompiler (cloud) 97 | # HEXCPPC - PowerPC Decompiler (cloud) 98 | # HEXCMIPS64 - MIPS64 Decompiler (cloud) 99 | # HEXCMIPS - MIPS Decompiler (cloud) 100 | # HEXCRV64 - RISC-V64 Decompiler (cloud) 101 | # HEXCRV - RISC-V Decompiler (cloud) 102 | # HEXCARC - ARC Decompiler (cloud) 103 | # HEXCARC64 - ARC64 Decompiler (cloud) 104 | # LUMINA - Lumina Server 105 | # TEAMS - Vault Server 106 | 107 | def generate_add_on(code: str, owner: str, start_date: str, end_date: str, id: str) -> dict: 108 | data = { 109 | 'code': code, 110 | 'owner': owner, 111 | 'start_date': start_date, 112 | 'end_date': end_date, 113 | 'id': id 114 | } 115 | 116 | return data 117 | 118 | # product_id 119 | # IDAPRO 120 | # IDAHOME 121 | # IDAFREE 122 | # TEAMS_SERVER 123 | # LUMINA_SERVER 124 | # LICENSE_SERVER 125 | 126 | # edition_id: 127 | # ida-pro 128 | # ida-pro-classroom 129 | # ida-home-pc 130 | # ida-home-arm 131 | # ida-home-mips 132 | # ida-home-ppc 133 | # ida-home-riscv 134 | # ida-free 135 | # teams-server 136 | # lumina-server 137 | # license-server 138 | 139 | def generate_license(license_type: str, product_id: str, edition_id: str, description: str, seats: int, start_date: str, end_date: str, issued_on: str, owner: str, add_ons: list, features: list, id: str) -> dict: 140 | data = { 141 | 'license_type': license_type, 142 | 'product_id': product_id, 143 | 'edition_id': edition_id, 144 | 'description': description, 145 | 'seats': seats, 146 | 'start_date': start_date, 147 | 'end_date': end_date, 148 | 'issued_on': issued_on, 149 | 'owner': owner, 150 | 'add_ons': add_ons, 151 | 'features': features, 152 | 'id': id 153 | } 154 | 155 | return data 156 | 157 | def generate_license_package(version: int, name: str, email: str, licenses: list) -> dict: 158 | if version == 1: 159 | data = { 160 | 'header': { 'version': version }, 161 | 'payload': { 162 | 'name': name, 163 | 'email': email, 164 | 'licenses': licenses 165 | } 166 | } 167 | 168 | return data 169 | 170 | def to_alphabetical_json(d: dict) -> str: 171 | return json.dumps(d, sort_keys=True, separators=(',', ':')) 172 | 173 | def from_alphabetical_json(s: str) -> dict: 174 | return json.loads(s) 175 | 176 | def sign_license_package(license: dict, private_key: int, public_key: int) -> str: 177 | data = { 'payload': license['payload'] } 178 | data_str = to_alphabetical_json(data) 179 | 180 | buffer = bytearray(128) 181 | 182 | # First 33 bytes are random 183 | for i in range(33): 184 | buffer[i] = 0x42 185 | 186 | # Compute sha256 of the data 187 | sha256 = hashlib.sha256() 188 | sha256.update(data_str.encode()) 189 | digest = sha256.digest() 190 | 191 | # Copy the sha256 digest to the buffer 192 | for i in range(32): 193 | buffer[33 + i] = digest[i] 194 | 195 | # Encrypt the buffer 196 | encrypted = encrypt_message(buffer, private_key, public_key) 197 | 198 | return encrypted.hex().upper() 199 | 200 | # Patch 201 | 202 | def patch_file(file_path: Path) -> bool: 203 | data = None 204 | 205 | if file_path.exists(): 206 | with open(file_path, 'rb') as f: 207 | data = f.read() 208 | 209 | backup_file_path = file_path.parent / (file_path.name + '.bak') 210 | 211 | if not backup_file_path.exists(): 212 | with open(backup_file_path, 'wb') as sf: 213 | sf.write(data) 214 | else: 215 | with open(backup_file_path, 'rb') as sf: 216 | data = sf.read() 217 | 218 | if data: 219 | if HAVE_NEW_ROOT_CA_CERTIFICATE: 220 | if data.find(NEW_PUBLIC_MODULUS[:6]) != -1 or data.find(NEW_ROOT_CA_CERTIFICATE) != -1 or data.find(NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) != -1: 221 | print(f'INFO: `{file_path.name}` already has a patch.') 222 | return False 223 | 224 | if data.find(ORIGINAL_PUBLIC_MODULUS[:6]) == -1 and data.find(ORIGINAL_ROOT_CA_CERTIFICATE) == -1 and data.find(ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) == -1: 225 | print(f'ERROR: Patch for `{file_path.name}` is not supported!') 226 | return False 227 | else: 228 | if data.find(NEW_PUBLIC_MODULUS[:6]) != -1: 229 | print(f'INFO: `{file_path.name}` already has a patch.') 230 | return False 231 | 232 | if data.find(ORIGINAL_PUBLIC_MODULUS[:6]) == -1: 233 | print(f'ERROR: Patch for `{file_path.name}` is not supported!') 234 | return False 235 | 236 | data = data.replace(ORIGINAL_PUBLIC_MODULUS[:6], NEW_PUBLIC_MODULUS[:6]) 237 | 238 | if HAVE_NEW_ROOT_CA_CERTIFICATE: 239 | data = data.replace(ORIGINAL_ROOT_CA_CERTIFICATE, NEW_ROOT_CA_CERTIFICATE) 240 | data = data.replace(ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS, NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) 241 | 242 | with open(file_path, 'wb') as f: 243 | f.write(data) 244 | 245 | print(f'INFO: `{file_path.name}` successful patched.') 246 | 247 | # Main 248 | 249 | def generate_id(ID_0: int = randint(0x00, 0xFF), ID_1: int = randint(0x00, 0xFF), 250 | ID_2: int = randint(0x00, 0xFF), ID_3: int = randint(0x00, 0xFF), 251 | ID_4: int = randint(0x00, 0xFF), ID_5: int = randint(0x00, 0xFF)) -> list: 252 | return [ID_0, ID_1, ID_2, ID_3, ID_4, ID_5] 253 | 254 | def format_id(id:list) -> str: 255 | return f'{id[0]:02X}-{id[1]:02X}{id[2]:02X}-{id[3]:02X}{id[4]:02X}-{id[5]:02X}' 256 | 257 | def main(argv: list) -> int: 258 | 259 | private_key = bytes_to_bigint(PRIVATE_KEY) 260 | public_key = bytes_to_bigint(NEW_PUBLIC_MODULUS) 261 | 262 | if 'ida-pro' in argv: 263 | if OS_NAME == 'Linux': 264 | files = [ 265 | 'hv', 266 | 'hvui', 267 | 'libida.so', 268 | 'libida32.so', 269 | 'dbgsrv/linux_server', 270 | 'dbgsrv/linux_server32', 271 | 'dbgsrv/mac_server', 272 | 'dbgsrv/mac_server32', 273 | 'dbgsrv/mac_server_arm', 274 | 'dbgsrv/mac_server_arme', 275 | 'dbgsrv/win32_remote32', 276 | 'dbgsrv/win64_remote.exe', 277 | 'plugins/armlinux_stub.so', 278 | 'plugins/arm_mac_stub.so', 279 | 'plugins/dalvik_user.so', 280 | 'plugins/gdb_user.so', 281 | 'plugins/ios_user.so', 282 | 'plugins/linux_stub.so', 283 | 'plugins/mac_stub.so', 284 | 'plugins/pin_user.so', 285 | 'plugins/win32_stub.so', 286 | 'plugins/xnu_user.so', 287 | ] 288 | 289 | for file in files: 290 | patch_file(CURRENT_DIRECTORY.joinpath(file)) 291 | 292 | elif OS_NAME == 'Windows': 293 | files = [ 294 | 'hv.exe', 295 | 'hvui.exe', 296 | 'ida.dll', 297 | 'ida32.dll', 298 | 'dbgsrv/linux_server', 299 | 'dbgsrv/linux_server32', 300 | 'dbgsrv/mac_server', 301 | 'dbgsrv/mac_server32', 302 | 'dbgsrv/mac_server_arm', 303 | 'dbgsrv/mac_server_arme', 304 | 'dbgsrv/win32_remote32', 305 | 'dbgsrv/win64_remote.exe', 306 | 'plugins/armlinux_stub.dll', 307 | 'plugins/arm_mac_stub.dll', 308 | 'plugins/dalvik_user.dll', 309 | 'plugins/gdb_user.dll', 310 | 'plugins/ios_user.dll', 311 | 'plugins/linux_stub.dll', 312 | 'plugins/mac_stub.dll', 313 | 'plugins/pin_user.dll', 314 | 'plugins/win32_stub.dll', 315 | 'plugins/xnu_user.dll', 316 | ] 317 | 318 | for file in files: 319 | patch_file(CURRENT_DIRECTORY.joinpath(file)) 320 | 321 | elif OS_NAME == 'iOS': 322 | files = [ 323 | 'hv', 324 | 'hvui', 325 | 'libida.dylib', 326 | 'libida32.dylib', 327 | 'dbgsrv/linux_server', 328 | 'dbgsrv/linux_server32', 329 | 'dbgsrv/mac_server', 330 | 'dbgsrv/mac_server32', 331 | 'dbgsrv/mac_server_arm', 332 | 'dbgsrv/mac_server_arme', 333 | 'dbgsrv/win32_remote32', 334 | 'dbgsrv/win64_remote.exe', 335 | 'plugins/armlinux_stub.dylib', 336 | 'plugins/arm_mac_stub.dylib', 337 | 'plugins/dalvik_user.dylib', 338 | 'plugins/gdb_user.dylib', 339 | 'plugins/ios_user.dylib', 340 | 'plugins/linux_stub.dylib', 341 | 'plugins/mac_stub.dylib', 342 | 'plugins/pin_user.dylib', 343 | 'plugins/win32_stub.dylib', 344 | 'plugins/xnu_user.dylib', 345 | ] 346 | 347 | for file in files: 348 | patch_file(CURRENT_DIRECTORY.joinpath(file)) 349 | 350 | license_path = CURRENT_DIRECTORY.joinpath('idapro.hexlic') 351 | is_valid_license = False 352 | if license_path.exists(): 353 | with open(license_path, 'r') as f: 354 | license_package = from_alphabetical_json(f.read()) 355 | if sign_license_package(license_package, private_key, public_key) == license_package['signature']: 356 | is_valid_license = True 357 | if is_valid_license: 358 | return 0 359 | 360 | # Set up 361 | 362 | start_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 363 | end_date = '2038-01-19 03:14:07' 364 | owner = 'RenardDev' 365 | name = 'RenardDev' 366 | email = 'zeze839@gmail.com' 367 | 368 | license_id = generate_id(ID_5=0x00) 369 | 370 | # Add-ons 371 | 372 | add_ons_list = [ 373 | 'HEXX86', 374 | 'HEXX64', 375 | 'HEXARM', 376 | 'HEXARM64', 377 | 'HEXMIPS', 378 | 'HEXMIPS64', 379 | 'HEXPPC', 380 | 'HEXPPC64', 381 | 'HEXRV64', 382 | 'HEXARC', 383 | 'HEXARC64' 384 | ] 385 | 386 | add_ons = [] 387 | for idx, add_on in enumerate(add_ons_list): 388 | license_id_copy = license_id.copy() 389 | license_id_copy[5] += idx + 1 390 | add_ons.append(generate_add_on(add_on, format_id(license_id), start_date, end_date, format_id(license_id_copy))) 391 | 392 | # Licenses 393 | 394 | licenses = [ 395 | generate_license('named', 'IDAPRO', 'ida-pro', 'Licensed by RenardDev', 1, start_date, end_date, start_date, owner, add_ons, [], format_id(license_id)) 396 | ] 397 | 398 | # Package 399 | 400 | license_package = generate_license_package(1, name, email, licenses) 401 | license_package['signature'] = sign_license_package(license_package, private_key, public_key) 402 | 403 | # File 404 | 405 | serialized = to_alphabetical_json(license_package) 406 | with open(license_path, 'w') as f: 407 | f.write(serialized) 408 | print('INFO: License generated!') 409 | 410 | if 'hexvault' in argv: 411 | if OS_NAME == 'Linux': 412 | patch_file(CURRENT_DIRECTORY.joinpath('vault_server')) 413 | 414 | license_path = CURRENT_DIRECTORY.joinpath('teams_server.hexlic') 415 | is_valid_license = False 416 | if license_path.exists(): 417 | with open(license_path, 'r') as f: 418 | license_package = from_alphabetical_json(f.read()) 419 | if sign_license_package(license_package, private_key, public_key) == license_package['signature']: 420 | is_valid_license = True 421 | if is_valid_license: 422 | return 0 423 | 424 | # Set up 425 | 426 | start_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 427 | end_date = '2038-01-19 03:14:07' 428 | seats = 2147483647 429 | owner = '00:00:00:00:00:00' 430 | name = 'RenardDev' 431 | email = 'zeze839@gmail.com' 432 | 433 | license_id = generate_id(ID_5=0x00) 434 | 435 | # Add-ons 436 | 437 | add_ons_list = [ 438 | 'TEAMS' 439 | ] 440 | 441 | add_ons = [] 442 | for idx, add_on in enumerate(add_ons_list): 443 | license_id_copy = license_id.copy() 444 | license_id_copy[5] += idx + 1 445 | add_ons.append(generate_add_on(add_on, format_id(license_id), start_date, end_date, format_id(license_id_copy))) 446 | 447 | # Licenses 448 | 449 | licenses = [ 450 | generate_license('named', 'TEAMS_SERVER', 'teams-server', 'Licensed by RenardDev', seats, start_date, end_date, start_date, owner, add_ons, [], format_id(license_id)) 451 | ] 452 | 453 | # Package 454 | 455 | license_package = generate_license_package(1, name, email, licenses) 456 | license_package['signature'] = sign_license_package(license_package, private_key, public_key) 457 | 458 | # File 459 | 460 | serialized = to_alphabetical_json(license_package) 461 | with open(license_path, 'w') as f: 462 | f.write(serialized) 463 | print('INFO: License generated!') 464 | 465 | if 'lumina' in argv: 466 | if OS_NAME == 'Linux': 467 | patch_file(CURRENT_DIRECTORY.joinpath('lumina_server')) 468 | patch_file(CURRENT_DIRECTORY.joinpath('lc')) 469 | 470 | license_path = CURRENT_DIRECTORY.joinpath('lumina_server.hexlic') 471 | is_valid_license = False 472 | if license_path.exists(): 473 | with open(license_path, 'r') as f: 474 | license_package = from_alphabetical_json(f.read()) 475 | if sign_license_package(license_package, private_key, public_key) == license_package['signature']: 476 | is_valid_license = True 477 | if is_valid_license: 478 | return 0 479 | 480 | # Set up 481 | 482 | start_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 483 | end_date = '2038-01-19 03:14:07' 484 | seats = 2147483647 485 | owner = '00:00:00:00:00:00' 486 | name = 'RenardDev' 487 | email = 'zeze839@gmail.com' 488 | 489 | license_id = generate_id(ID_5=0x00) 490 | 491 | # Add-ons 492 | 493 | add_ons_list = [ 494 | 'LUMINA' 495 | ] 496 | 497 | add_ons = [] 498 | for idx, add_on in enumerate(add_ons_list): 499 | license_id_copy = license_id.copy() 500 | license_id_copy[5] += idx + 1 501 | add_ons.append(generate_add_on(add_on, format_id(license_id), start_date, end_date, format_id(license_id_copy))) 502 | 503 | # Licenses 504 | 505 | licenses = [ 506 | generate_license('named', 'LUMINA_SERVER', 'lumina-server', 'Licensed by RenardDev', seats, start_date, end_date, start_date, owner, add_ons, [], format_id(license_id)) 507 | ] 508 | 509 | # Package 510 | 511 | license_package = generate_license_package(1, name, email, licenses) 512 | license_package['signature'] = sign_license_package(license_package, private_key, public_key) 513 | 514 | # File 515 | 516 | serialized = to_alphabetical_json(license_package) 517 | with open(license_path, 'w') as f: 518 | f.write(serialized) 519 | print('INFO: License generated!') 520 | 521 | if 'hexlicsrv' in argv: 522 | if OS_NAME == 'Linux': 523 | patch_file(CURRENT_DIRECTORY.joinpath('license_server')) 524 | patch_file(CURRENT_DIRECTORY.joinpath('lsadm')) 525 | 526 | license_path = CURRENT_DIRECTORY.joinpath('license_server.hexlic') 527 | is_valid_license = False 528 | if license_path.exists(): 529 | with open(license_path, 'r') as f: 530 | license_package = from_alphabetical_json(f.read()) 531 | if sign_license_package(license_package, private_key, public_key) == license_package['signature']: 532 | is_valid_license = True 533 | if is_valid_license: 534 | return 0 535 | 536 | # Set up 537 | 538 | start_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 539 | end_date = '2038-01-19 03:14:07' 540 | seats = 2147483647 541 | owner_hexlicsrv = '00:00:00:00:00:00' 542 | owner = 'RenardDev' 543 | name = 'RenardDev' 544 | email = 'zeze839@gmail.com' 545 | 546 | hexlicsrv_license_id = generate_id(ID_5=0x00) 547 | license_id = generate_id(ID_5=0x00) 548 | 549 | # Add-ons 550 | 551 | add_ons_list = [ 552 | 'HEXX86', 553 | 'HEXX64', 554 | 'HEXARM', 555 | 'HEXARM64', 556 | 'HEXMIPS', 557 | 'HEXMIPS64', 558 | 'HEXPPC', 559 | 'HEXPPC64', 560 | 'HEXRV64', 561 | 'HEXARC', 562 | 'HEXARC64' 563 | ] 564 | 565 | add_ons = [] 566 | for idx, add_on in enumerate(add_ons_list): 567 | license_id_copy = license_id.copy() 568 | license_id_copy[5] += idx + 1 569 | add_ons.append(generate_add_on(add_on, format_id(license_id), start_date, end_date, format_id(license_id_copy))) 570 | 571 | # Licenses 572 | 573 | licenses = [ 574 | generate_license('named', 'LICENSE_SERVER', 'license-server', 'Licensed by RenardDev', seats, start_date, end_date, start_date, owner_hexlicsrv, [], [], format_id(hexlicsrv_license_id)), 575 | generate_license('floating', 'IDAPRO', 'ida-pro', 'Licensed by RenardDev', seats, start_date, end_date, start_date, owner, add_ons, [], format_id(license_id)) 576 | ] 577 | 578 | # Package 579 | 580 | license_package = generate_license_package(1, name, email, licenses) 581 | license_package['signature'] = sign_license_package(license_package, private_key, public_key) 582 | 583 | # File 584 | 585 | serialized = to_alphabetical_json(license_package) 586 | with open(license_path, 'w') as f: 587 | f.write(serialized) 588 | print('INFO: License generated!') 589 | 590 | return 0 591 | 592 | if __name__ == '__main__': 593 | sys.exit(main(sys.argv)) 594 | -------------------------------------------------------------------------------- /hexvault/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /ida/CA/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /ida/patch.py: -------------------------------------------------------------------------------- 1 | 2 | # Imports 3 | 4 | import platform 5 | import sys 6 | import hashlib 7 | import json 8 | 9 | from pathlib import Path 10 | from random import randint 11 | from datetime import datetime 12 | 13 | # General 14 | 15 | CURRENT_DIRECTORY = Path(__file__).parent 16 | OS_NAME = platform.system() 17 | 18 | ORIGINAL_ROOT_CA_CERTIFICATE = bytes.fromhex('2D2D2D2D2D424547494E2043455254494649434154452D2D2D2D2D0A4D4949463054434341376D6741774942416749554C7A4B74454F50395137562F4C2F4734526E76344C3376712F6845774451594A4B6F5A496876634E4151454E0A425141775644454C4D416B474131554542684D43516B5578447A414E42674E564241634D426B78707736686E5A5445564D424D47413155454367774D534756340A4C564A6865584D67553045754D5230774777594456515144444252495A586774556D46356379425451533467556D39766443424451544165467730794D4441310A4D4451784D5441794D446861467730304D4441304D6A6B784D5441794D4468614D465178437A414A42674E5642415954416B4A464D51387744515944565151480A44415A4D61634F6F5A3255784654415442674E5642416F4D4445686C6543315359586C7A49464E424C6A45644D4273474131554541777755534756344C564A680A65584D675530457549464A766233516751304577676749694D4130474353714753496233445145424151554141344943447741776767494B416F4943415144420A727345683438564E796A4350524F53597A773576694163664475426F4441486533624952594D61476D3261366F6D5358537A54303252416970536C4F366E4A5A0A2F50674E4569706158594C6245586D727247646E5364427538756235317431374164476347597A7A506A534970495648356D5832694F624864533367794E7A700A4A4B4A515543444D3646644A61385A637A744B772B6258734E3166744B615A437A4863755542633850356C6B6952476375596662694872693543303270476F310A3379344F7A3939536F74384B5566774E6842794F4F474F77655979666E394E676D6871686B427532372B367278706D7552376D48794F68666E4C732B707351300A796A4536627A756C32696C5746724F53614C41784B6268424C4C5144574359654276586D4530497A6D5A56626F32447154552B4E575245553661766D5252427A0A36526E5A484655686C324C56624A354172343542617752333862524E726F36564E4354713839724258564665436E6B394A613676345A416F576D6A4A757048430A70585449786F65626B6F655741774943757A36336357735268317932617164675136763979564572413634476867436B704A4F383248447441395369716765330A542B7267556E6A3170636C6C474B6778414659634B686C434C6C342B626D306F686C784630574638564D68472F54424C4E48334D6C4A466A6C4D6F4277516E6C0A4150686545675A576F5153456A416B7A524C55725277376B566B2F51743847356846474C6233556A4538534B44504B5259534241554E2F75503859484B46716F0A3261727054436931444F345371583872367A717A736C565466367557546971384D4E6B5A2F2B374E5972312F4A50543235694D6C7736736136673447555070510A7A685261507931396F62476534337534766A7079736539673576715839703375394D49313478336B36514944415141426F3447614D4947584D423047413155640A4467515742425161784E6163664D37584B6A4B4975744948726336746A6945394454416642674E5648534D454744415767425161784E6163664D37584B6A4B490A75744948726336746A6945394454415042674E5648524D4241663845425441444151482F4D41344741315564447745422F77514541774942686A413042674E560A485238454C5441724D436D674A36416C68694E6F644852774F69387659334A734C6D686C6543317959586C7A4C6D4E76625339796232393058324E684C6D4E790A6244414E42676B71686B6947397730424151304641414F4341674541644B7034496E70526B357A30426A50733643634A53674B624348304D585A7162742F454D0A2F34644A50766D4136744165784A7076396539426D542F444F423834514232787A516C45694E4F42372F56346A336F44696A356D4D77527971594C32346C33670A4841617677632B644C72707A582F3534755A6D4839624B7337796A33666B2F7655336537746837323041724C322F595A6A485632577830424D63732B595669740A70687647326D7875313644547069646D733370436A3235654549534A76586665385845664B4F503146784743706D4B7878367150486C4E41534F70357A6477560A6945696D6B677555777A43736D6D5049357245574C58644C52786330436B66666D62734E6D734638535A7A333843697775526C6963684444645A754A586A69370A6A6E5A46376830344D6F32414B507436774A392B36367259714469677650397348474B70517035687231444D756B46476E656933533968354B703865446852580A593234792F434A564E4F307278596F4650556E4F77625355463346777534665833457A71356557374E304E6C37733058484578622F5039666D685078514256310A677772363635696E71355A77443848397577474556703349425439634852753869655A7251444D49315571504F792B3245574E507459344B786D6765725462630A4E3056483442754538746478544755636B67344A5462734E525562717853586D534C396A4131644C425436336C624D4C49553036644964714E627078453447560A4D674F4C777177782F42462B465A6751547474646A6D7065786D6C364E49445647444278667945434A3576647778624B4D4952666F376670306A52706A5A70500A3862773442506E783059344E704D7A4B78695753306937726539694561666468364774704E796E4B55304A46534B7249776D4965634B462B5A345A55452F314B0A2B742F464F67493D0A2D2D2D2D2D454E442043455254494649434154452D2D2D2D2D0A00') 19 | ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS = bytes.fromhex('4D4949463054434341376D6741774942416749554C7A4B74454F50395137562F4C2F4734526E76344C3376712F6845774451594A4B6F5A496876634E4151454E425141775644454C4D416B474131554542684D43516B5578447A414E42674E564241634D426B78707736686E5A5445564D424D47413155454367774D534756344C564A6865584D67553045754D5230774777594456515144444252495A586774556D46356379425451533467556D39766443424451544165467730794D4441314D4451784D5441794D446861467730304D4441304D6A6B784D5441794D4468614D465178437A414A42674E5642415954416B4A464D513877445159445651514844415A4D61634F6F5A3255784654415442674E5642416F4D4445686C6543315359586C7A49464E424C6A45644D4273474131554541777755534756344C564A6865584D675530457549464A766233516751304577676749694D4130474353714753496233445145424151554141344943447741776767494B416F494341514442727345683438564E796A4350524F53597A773576694163664475426F4441486533624952594D61476D3261366F6D5358537A54303252416970536C4F366E4A5A2F50674E4569706158594C6245586D727247646E5364427538756235317431374164476347597A7A506A534970495648356D5832694F624864533367794E7A704A4B4A515543444D3646644A61385A637A744B772B6258734E3166744B615A437A4863755542633850356C6B6952476375596662694872693543303270476F313379344F7A3939536F74384B5566774E6842794F4F474F77655979666E394E676D6871686B427532372B367278706D7552376D48794F68666E4C732B70735130796A4536627A756C32696C5746724F53614C41784B6268424C4C5144574359654276586D4530497A6D5A56626F32447154552B4E575245553661766D5252427A36526E5A484655686C324C56624A354172343542617752333862524E726F36564E4354713839724258564665436E6B394A613676345A416F576D6A4A7570484370585449786F65626B6F655741774943757A36336357735268317932617164675136763979564572413634476867436B704A4F38324844744139536971676533542B7267556E6A3170636C6C474B6778414659634B686C434C6C342B626D306F686C784630574638564D68472F54424C4E48334D6C4A466A6C4D6F4277516E6C4150686545675A576F5153456A416B7A524C55725277376B566B2F51743847356846474C6233556A4538534B44504B5259534241554E2F75503859484B46716F3261727054436931444F345371583872367A717A736C565466367557546971384D4E6B5A2F2B374E5972312F4A50543235694D6C7736736136673447555070517A685261507931396F62476534337534766A7079736539673576715839703375394D49313478336B36514944415141426F3447614D4947584D423047413155644467515742425161784E6163664D37584B6A4B4975744948726336746A6945394454416642674E5648534D454744415767425161784E6163664D37584B6A4B4975744948726336746A6945394454415042674E5648524D4241663845425441444151482F4D41344741315564447745422F77514541774942686A413042674E56485238454C5441724D436D674A36416C68694E6F644852774F69387659334A734C6D686C6543317959586C7A4C6D4E76625339796232393058324E684C6D4E796244414E42676B71686B6947397730424151304641414F4341674541644B7034496E70526B357A30426A50733643634A53674B624348304D585A7162742F454D2F34644A50766D4136744165784A7076396539426D542F444F423834514232787A516C45694E4F42372F56346A336F44696A356D4D77527971594C32346C33674841617677632B644C72707A582F3534755A6D4839624B7337796A33666B2F7655336537746837323041724C322F595A6A485632577830424D63732B5956697470687647326D7875313644547069646D733370436A3235654549534A76586665385845664B4F503146784743706D4B7878367150486C4E41534F70357A6477566945696D6B677555777A43736D6D5049357245574C58644C52786330436B66666D62734E6D734638535A7A333843697775526C6963684444645A754A586A69376A6E5A46376830344D6F32414B507436774A392B36367259714469677650397348474B70517035687231444D756B46476E656933533968354B70386544685258593234792F434A564E4F307278596F4650556E4F77625355463346777534665833457A71356557374E304E6C37733058484578622F5039666D68507851425631677772363635696E71355A77443848397577474556703349425439634852753869655A7251444D49315571504F792B3245574E507459344B786D6765725462634E3056483442754538746478544755636B67344A5462734E525562717853586D534C396A4131644C425436336C624D4C49553036644964714E627078453447564D674F4C777177782F42462B465A6751547474646A6D7065786D6C364E49445647444278667945434A3576647778624B4D4952666F376670306A52706A5A70503862773442506E783059344E704D7A4B78695753306937726539694561666468364774704E796E4B55304A46534B7249776D4965634B462B5A345A55452F314B2B742F464F67493D00') 20 | ORIGINAL_PUBLIC_MODULUS = bytes.fromhex('EDFD425CF978546E8911225884436C57140525650BCF6EBFE80EDBC5FB1DE68F4C66C29CB22EB668788AFCB0ABBB718044584B810F8970CDDF227385F75D5DDDD91D4F18937A08AA83B28C49D12DC92E7505BB38809E91BD0FBD2F2E6AB1D2E33C0C55D5BDDD478EE8BF845FCEF3C82B9D2929ECB71F4D1B3DB96E3A8E7AAF93') 21 | 22 | PRIVATE_KEY = bytes.fromhex('77C86ABBB7F3BB134436797B68FF47BEB1A5457816608DBFB72641814DD464DD640D711D5732D3017A1C4E63D835822F00A4EAB619A2C4791CF33F9F57F9C2AE4D9EED9981E79AC9B8F8A411F68F25B9F0C05D04D11E22A3A0D8D4672B56A61F1532282FF4E4E74759E832B70E98B9D102D07E9FB9BA8D15810B144970029874') 23 | NEW_PUBLIC_MODULUS = bytes.fromhex('EDFD42CBF978546E8911225884436C57140525650BCF6EBFE80EDBC5FB1DE68F4C66C29CB22EB668788AFCB0ABBB718044584B810F8970CDDF227385F75D5DDDD91D4F18937A08AA83B28C49D12DC92E7505BB38809E91BD0FBD2F2E6AB1D2E33C0C55D5BDDD478EE8BF845FCEF3C82B9D2929ECB71F4D1B3DB96E3A8E7AAF93') 24 | 25 | HAVE_NEW_ROOT_CA_CERTIFICATE = False 26 | if CURRENT_DIRECTORY.joinpath('CA').joinpath('CA.pem').exists(): 27 | NEW_ROOT_CA_CERTIFICATE = b'' 28 | with open(CURRENT_DIRECTORY.joinpath('CA').joinpath('CA.pem'), 'rb') as f: 29 | NEW_ROOT_CA_CERTIFICATE += f.read() 30 | NEW_ROOT_CA_CERTIFICATE += b'\x00' 31 | 32 | NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS = NEW_ROOT_CA_CERTIFICATE \ 33 | .replace(b'-----BEGIN CERTIFICATE-----', b'') \ 34 | .replace(b'-----END CERTIFICATE-----', b'') \ 35 | .replace(b'\r\n', b'') \ 36 | .replace(b'\r', b'') \ 37 | .replace(b'\n', b'') 38 | 39 | if len(NEW_ROOT_CA_CERTIFICATE) > len(ORIGINAL_ROOT_CA_CERTIFICATE) or \ 40 | len(NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) > len(ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS): 41 | print('New CA certificate is too big!') 42 | else: 43 | NEW_ROOT_CA_CERTIFICATE += b'\x00' * (len(ORIGINAL_ROOT_CA_CERTIFICATE) - len(NEW_ROOT_CA_CERTIFICATE)) 44 | NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS += b'\x00' * (len(ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) - len(NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS)) 45 | 46 | HAVE_NEW_ROOT_CA_CERTIFICATE = True 47 | 48 | # Crypto functions 49 | 50 | def bytes_to_bigint(data: bytes) -> int: 51 | return int.from_bytes(data, byteorder='little') 52 | 53 | def bigint_to_bytes(n: int) -> bytes: 54 | return n.to_bytes((n.bit_length() + 7) // 8, byteorder='little') 55 | 56 | def decrypt_message(message: bytes, public_key: int, exponent: int = 0x13) -> bytes: 57 | decrypted = pow(bytes_to_bigint(message), exponent, public_key) 58 | decrypted = bigint_to_bytes(decrypted) 59 | return decrypted[::-1] 60 | 61 | def encrypt_message(message: bytes, private_key: int, public_key: int) -> bytes: 62 | encrypted = pow(bytes_to_bigint(message[::-1]), private_key, public_key) 63 | encrypted = bigint_to_bytes(encrypted) 64 | return encrypted 65 | 66 | # License 67 | 68 | # IDAPRO - IDA Pro 69 | # IDAEDU - IDA Educational 70 | # IDAPC - IDA Home for Intel x64 71 | # IDAARM - IDA Home for ARM 72 | # IDAPPC - IDA Home for PowerPC 73 | # IDAMIPS - IDA Home for MIPS 74 | # IDAM68K - IDA Home for Motorola 68K 75 | # IDABASE - Hex-Rays Base 76 | # IDACORE - Hex-Rays Core 77 | # IDAULT - Hex-Rays Ultra 78 | 79 | # code 80 | # HEXX64 - x64 Decompiler 81 | # HEXX86 - x86 Decompiler 82 | # HEXARM64 - ARM64 Decompiler 83 | # HEXARM - ARM Decompiler 84 | # HEXPPC64 - PowerPC64 Decompiler 85 | # HEXPPC - PowerPC Decompiler 86 | # HEXMIPS64 - MIPS64 Decompiler 87 | # HEXMIPS - MIPS Decompiler 88 | # HEXRV64 - RISC-V64 Decompiler 89 | # HEXRV - RISC-V Decompiler 90 | # HEXARC - ARC Decompiler 91 | # HEXARC64 - ARC64 Decompiler 92 | # HEXCX64 - x64 Decompiler (cloud) 93 | # HEXCX86 - x86 Decompiler (cloud) 94 | # HEXCARM64 - ARM64 Decompiler (cloud) 95 | # HEXCARM - ARM Decompiler (cloud) 96 | # HEXCPPC64 - PowerPC64 Decompiler (cloud) 97 | # HEXCPPC - PowerPC Decompiler (cloud) 98 | # HEXCMIPS64 - MIPS64 Decompiler (cloud) 99 | # HEXCMIPS - MIPS Decompiler (cloud) 100 | # HEXCRV64 - RISC-V64 Decompiler (cloud) 101 | # HEXCRV - RISC-V Decompiler (cloud) 102 | # HEXCARC - ARC Decompiler (cloud) 103 | # HEXCARC64 - ARC64 Decompiler (cloud) 104 | # LUMINA - Lumina Server 105 | # TEAMS - Vault Server 106 | 107 | def generate_add_on(code: str, owner: str, start_date: str, end_date: str, id: str) -> dict: 108 | data = { 109 | 'code': code, 110 | 'owner': owner, 111 | 'start_date': start_date, 112 | 'end_date': end_date, 113 | 'id': id 114 | } 115 | 116 | return data 117 | 118 | # product_id 119 | # IDAPRO 120 | # IDAHOME 121 | # IDAFREE 122 | # TEAMS_SERVER 123 | # LUMINA_SERVER 124 | # LICENSE_SERVER 125 | 126 | # edition_id: 127 | # ida-pro 128 | # ida-pro-classroom 129 | # ida-home-pc 130 | # ida-home-arm 131 | # ida-home-mips 132 | # ida-home-ppc 133 | # ida-home-riscv 134 | # ida-free 135 | # teams-server 136 | # lumina-server 137 | # license-server 138 | 139 | def generate_license(license_type: str, product_id: str, edition_id: str, description: str, seats: int, start_date: str, end_date: str, issued_on: str, owner: str, add_ons: list, features: list, id: str) -> dict: 140 | data = { 141 | 'license_type': license_type, 142 | 'product_id': product_id, 143 | 'edition_id': edition_id, 144 | 'description': description, 145 | 'seats': seats, 146 | 'start_date': start_date, 147 | 'end_date': end_date, 148 | 'issued_on': issued_on, 149 | 'owner': owner, 150 | 'add_ons': add_ons, 151 | 'features': features, 152 | 'id': id 153 | } 154 | 155 | return data 156 | 157 | def generate_license_package(version: int, name: str, email: str, licenses: list) -> dict: 158 | if version == 1: 159 | data = { 160 | 'header': { 'version': version }, 161 | 'payload': { 162 | 'name': name, 163 | 'email': email, 164 | 'licenses': licenses 165 | } 166 | } 167 | 168 | return data 169 | 170 | def to_alphabetical_json(d: dict) -> str: 171 | return json.dumps(d, sort_keys=True, separators=(',', ':')) 172 | 173 | def from_alphabetical_json(s: str) -> dict: 174 | return json.loads(s) 175 | 176 | def sign_license_package(license: dict, private_key: int, public_key: int) -> str: 177 | data = { 'payload': license['payload'] } 178 | data_str = to_alphabetical_json(data) 179 | 180 | buffer = bytearray(128) 181 | 182 | # First 33 bytes are random 183 | for i in range(33): 184 | buffer[i] = 0x42 185 | 186 | # Compute sha256 of the data 187 | sha256 = hashlib.sha256() 188 | sha256.update(data_str.encode()) 189 | digest = sha256.digest() 190 | 191 | # Copy the sha256 digest to the buffer 192 | for i in range(32): 193 | buffer[33 + i] = digest[i] 194 | 195 | # Encrypt the buffer 196 | encrypted = encrypt_message(buffer, private_key, public_key) 197 | 198 | return encrypted.hex().upper() 199 | 200 | # Patch 201 | 202 | def patch_file(file_path: Path) -> bool: 203 | data = None 204 | 205 | if file_path.exists(): 206 | with open(file_path, 'rb') as f: 207 | data = f.read() 208 | 209 | backup_file_path = file_path.parent / (file_path.name + '.bak') 210 | 211 | if not backup_file_path.exists(): 212 | with open(backup_file_path, 'wb') as sf: 213 | sf.write(data) 214 | else: 215 | with open(backup_file_path, 'rb') as sf: 216 | data = sf.read() 217 | 218 | if data: 219 | if HAVE_NEW_ROOT_CA_CERTIFICATE: 220 | if data.find(NEW_PUBLIC_MODULUS[:6]) != -1 or data.find(NEW_ROOT_CA_CERTIFICATE) != -1 or data.find(NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) != -1: 221 | print(f'INFO: `{file_path.name}` already has a patch.') 222 | return False 223 | 224 | if data.find(ORIGINAL_PUBLIC_MODULUS[:6]) == -1 and data.find(ORIGINAL_ROOT_CA_CERTIFICATE) == -1 and data.find(ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) == -1: 225 | print(f'ERROR: Patch for `{file_path.name}` is not supported!') 226 | return False 227 | else: 228 | if data.find(NEW_PUBLIC_MODULUS[:6]) != -1: 229 | print(f'INFO: `{file_path.name}` already has a patch.') 230 | return False 231 | 232 | if data.find(ORIGINAL_PUBLIC_MODULUS[:6]) == -1: 233 | print(f'ERROR: Patch for `{file_path.name}` is not supported!') 234 | return False 235 | 236 | data = data.replace(ORIGINAL_PUBLIC_MODULUS[:6], NEW_PUBLIC_MODULUS[:6]) 237 | 238 | if HAVE_NEW_ROOT_CA_CERTIFICATE: 239 | data = data.replace(ORIGINAL_ROOT_CA_CERTIFICATE, NEW_ROOT_CA_CERTIFICATE) 240 | data = data.replace(ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS, NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) 241 | 242 | with open(file_path, 'wb') as f: 243 | f.write(data) 244 | 245 | print(f'INFO: `{file_path.name}` successful patched.') 246 | 247 | # Main 248 | 249 | def generate_id(ID_0: int = randint(0x00, 0xFF), ID_1: int = randint(0x00, 0xFF), 250 | ID_2: int = randint(0x00, 0xFF), ID_3: int = randint(0x00, 0xFF), 251 | ID_4: int = randint(0x00, 0xFF), ID_5: int = randint(0x00, 0xFF)) -> list: 252 | return [ID_0, ID_1, ID_2, ID_3, ID_4, ID_5] 253 | 254 | def format_id(id:list) -> str: 255 | return f'{id[0]:02X}-{id[1]:02X}{id[2]:02X}-{id[3]:02X}{id[4]:02X}-{id[5]:02X}' 256 | 257 | def main(argv: list) -> int: 258 | 259 | private_key = bytes_to_bigint(PRIVATE_KEY) 260 | public_key = bytes_to_bigint(NEW_PUBLIC_MODULUS) 261 | 262 | if 'ida-pro' in argv: 263 | if OS_NAME == 'Linux': 264 | files = [ 265 | 'hv', 266 | 'hvui', 267 | 'libida.so', 268 | 'libida32.so', 269 | 'dbgsrv/linux_server', 270 | 'dbgsrv/linux_server32', 271 | 'dbgsrv/mac_server', 272 | 'dbgsrv/mac_server32', 273 | 'dbgsrv/mac_server_arm', 274 | 'dbgsrv/mac_server_arme', 275 | 'dbgsrv/win32_remote32', 276 | 'dbgsrv/win64_remote.exe', 277 | 'plugins/armlinux_stub.so', 278 | 'plugins/arm_mac_stub.so', 279 | 'plugins/dalvik_user.so', 280 | 'plugins/gdb_user.so', 281 | 'plugins/ios_user.so', 282 | 'plugins/linux_stub.so', 283 | 'plugins/mac_stub.so', 284 | 'plugins/pin_user.so', 285 | 'plugins/win32_stub.so', 286 | 'plugins/xnu_user.so', 287 | ] 288 | 289 | for file in files: 290 | patch_file(CURRENT_DIRECTORY.joinpath(file)) 291 | 292 | elif OS_NAME == 'Windows': 293 | files = [ 294 | 'hv.exe', 295 | 'hvui.exe', 296 | 'ida.dll', 297 | 'ida32.dll', 298 | 'dbgsrv/linux_server', 299 | 'dbgsrv/linux_server32', 300 | 'dbgsrv/mac_server', 301 | 'dbgsrv/mac_server32', 302 | 'dbgsrv/mac_server_arm', 303 | 'dbgsrv/mac_server_arme', 304 | 'dbgsrv/win32_remote32', 305 | 'dbgsrv/win64_remote.exe', 306 | 'plugins/armlinux_stub.dll', 307 | 'plugins/arm_mac_stub.dll', 308 | 'plugins/dalvik_user.dll', 309 | 'plugins/gdb_user.dll', 310 | 'plugins/ios_user.dll', 311 | 'plugins/linux_stub.dll', 312 | 'plugins/mac_stub.dll', 313 | 'plugins/pin_user.dll', 314 | 'plugins/win32_stub.dll', 315 | 'plugins/xnu_user.dll', 316 | ] 317 | 318 | for file in files: 319 | patch_file(CURRENT_DIRECTORY.joinpath(file)) 320 | 321 | elif OS_NAME == 'iOS': 322 | files = [ 323 | 'hv', 324 | 'hvui', 325 | 'libida.dylib', 326 | 'libida32.dylib', 327 | 'dbgsrv/linux_server', 328 | 'dbgsrv/linux_server32', 329 | 'dbgsrv/mac_server', 330 | 'dbgsrv/mac_server32', 331 | 'dbgsrv/mac_server_arm', 332 | 'dbgsrv/mac_server_arme', 333 | 'dbgsrv/win32_remote32', 334 | 'dbgsrv/win64_remote.exe', 335 | 'plugins/armlinux_stub.dylib', 336 | 'plugins/arm_mac_stub.dylib', 337 | 'plugins/dalvik_user.dylib', 338 | 'plugins/gdb_user.dylib', 339 | 'plugins/ios_user.dylib', 340 | 'plugins/linux_stub.dylib', 341 | 'plugins/mac_stub.dylib', 342 | 'plugins/pin_user.dylib', 343 | 'plugins/win32_stub.dylib', 344 | 'plugins/xnu_user.dylib', 345 | ] 346 | 347 | for file in files: 348 | patch_file(CURRENT_DIRECTORY.joinpath(file)) 349 | 350 | license_path = CURRENT_DIRECTORY.joinpath('idapro.hexlic') 351 | is_valid_license = False 352 | if license_path.exists(): 353 | with open(license_path, 'r') as f: 354 | license_package = from_alphabetical_json(f.read()) 355 | if sign_license_package(license_package, private_key, public_key) == license_package['signature']: 356 | is_valid_license = True 357 | if is_valid_license: 358 | return 0 359 | 360 | # Set up 361 | 362 | start_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 363 | end_date = '2038-01-19 03:14:07' 364 | owner = 'RenardDev' 365 | name = 'RenardDev' 366 | email = 'zeze839@gmail.com' 367 | 368 | license_id = generate_id(ID_5=0x00) 369 | 370 | # Add-ons 371 | 372 | add_ons_list = [ 373 | 'HEXX86', 374 | 'HEXX64', 375 | 'HEXARM', 376 | 'HEXARM64', 377 | 'HEXMIPS', 378 | 'HEXMIPS64', 379 | 'HEXPPC', 380 | 'HEXPPC64', 381 | 'HEXRV64', 382 | 'HEXARC', 383 | 'HEXARC64' 384 | ] 385 | 386 | add_ons = [] 387 | for idx, add_on in enumerate(add_ons_list): 388 | license_id_copy = license_id.copy() 389 | license_id_copy[5] += idx + 1 390 | add_ons.append(generate_add_on(add_on, format_id(license_id), start_date, end_date, format_id(license_id_copy))) 391 | 392 | # Licenses 393 | 394 | licenses = [ 395 | generate_license('named', 'IDAPRO', 'ida-pro', 'Licensed by RenardDev', 1, start_date, end_date, start_date, owner, add_ons, [], format_id(license_id)) 396 | ] 397 | 398 | # Package 399 | 400 | license_package = generate_license_package(1, name, email, licenses) 401 | license_package['signature'] = sign_license_package(license_package, private_key, public_key) 402 | 403 | # File 404 | 405 | serialized = to_alphabetical_json(license_package) 406 | with open(license_path, 'w') as f: 407 | f.write(serialized) 408 | print('INFO: License generated!') 409 | 410 | if 'hexvault' in argv: 411 | if OS_NAME == 'Linux': 412 | patch_file(CURRENT_DIRECTORY.joinpath('vault_server')) 413 | 414 | license_path = CURRENT_DIRECTORY.joinpath('teams_server.hexlic') 415 | is_valid_license = False 416 | if license_path.exists(): 417 | with open(license_path, 'r') as f: 418 | license_package = from_alphabetical_json(f.read()) 419 | if sign_license_package(license_package, private_key, public_key) == license_package['signature']: 420 | is_valid_license = True 421 | if is_valid_license: 422 | return 0 423 | 424 | # Set up 425 | 426 | start_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 427 | end_date = '2038-01-19 03:14:07' 428 | seats = 2147483647 429 | owner = '00:00:00:00:00:00' 430 | name = 'RenardDev' 431 | email = 'zeze839@gmail.com' 432 | 433 | license_id = generate_id(ID_5=0x00) 434 | 435 | # Add-ons 436 | 437 | add_ons_list = [ 438 | 'TEAMS' 439 | ] 440 | 441 | add_ons = [] 442 | for idx, add_on in enumerate(add_ons_list): 443 | license_id_copy = license_id.copy() 444 | license_id_copy[5] += idx + 1 445 | add_ons.append(generate_add_on(add_on, format_id(license_id), start_date, end_date, format_id(license_id_copy))) 446 | 447 | # Licenses 448 | 449 | licenses = [ 450 | generate_license('named', 'TEAMS_SERVER', 'teams-server', 'Licensed by RenardDev', seats, start_date, end_date, start_date, owner, add_ons, [], format_id(license_id)) 451 | ] 452 | 453 | # Package 454 | 455 | license_package = generate_license_package(1, name, email, licenses) 456 | license_package['signature'] = sign_license_package(license_package, private_key, public_key) 457 | 458 | # File 459 | 460 | serialized = to_alphabetical_json(license_package) 461 | with open(license_path, 'w') as f: 462 | f.write(serialized) 463 | print('INFO: License generated!') 464 | 465 | if 'lumina' in argv: 466 | if OS_NAME == 'Linux': 467 | patch_file(CURRENT_DIRECTORY.joinpath('lumina_server')) 468 | patch_file(CURRENT_DIRECTORY.joinpath('lc')) 469 | 470 | license_path = CURRENT_DIRECTORY.joinpath('lumina_server.hexlic') 471 | is_valid_license = False 472 | if license_path.exists(): 473 | with open(license_path, 'r') as f: 474 | license_package = from_alphabetical_json(f.read()) 475 | if sign_license_package(license_package, private_key, public_key) == license_package['signature']: 476 | is_valid_license = True 477 | if is_valid_license: 478 | return 0 479 | 480 | # Set up 481 | 482 | start_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 483 | end_date = '2038-01-19 03:14:07' 484 | seats = 2147483647 485 | owner = '00:00:00:00:00:00' 486 | name = 'RenardDev' 487 | email = 'zeze839@gmail.com' 488 | 489 | license_id = generate_id(ID_5=0x00) 490 | 491 | # Add-ons 492 | 493 | add_ons_list = [ 494 | 'LUMINA' 495 | ] 496 | 497 | add_ons = [] 498 | for idx, add_on in enumerate(add_ons_list): 499 | license_id_copy = license_id.copy() 500 | license_id_copy[5] += idx + 1 501 | add_ons.append(generate_add_on(add_on, format_id(license_id), start_date, end_date, format_id(license_id_copy))) 502 | 503 | # Licenses 504 | 505 | licenses = [ 506 | generate_license('named', 'LUMINA_SERVER', 'lumina-server', 'Licensed by RenardDev', seats, start_date, end_date, start_date, owner, add_ons, [], format_id(license_id)) 507 | ] 508 | 509 | # Package 510 | 511 | license_package = generate_license_package(1, name, email, licenses) 512 | license_package['signature'] = sign_license_package(license_package, private_key, public_key) 513 | 514 | # File 515 | 516 | serialized = to_alphabetical_json(license_package) 517 | with open(license_path, 'w') as f: 518 | f.write(serialized) 519 | print('INFO: License generated!') 520 | 521 | if 'hexlicsrv' in argv: 522 | if OS_NAME == 'Linux': 523 | patch_file(CURRENT_DIRECTORY.joinpath('license_server')) 524 | patch_file(CURRENT_DIRECTORY.joinpath('lsadm')) 525 | 526 | license_path = CURRENT_DIRECTORY.joinpath('license_server.hexlic') 527 | is_valid_license = False 528 | if license_path.exists(): 529 | with open(license_path, 'r') as f: 530 | license_package = from_alphabetical_json(f.read()) 531 | if sign_license_package(license_package, private_key, public_key) == license_package['signature']: 532 | is_valid_license = True 533 | if is_valid_license: 534 | return 0 535 | 536 | # Set up 537 | 538 | start_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 539 | end_date = '2038-01-19 03:14:07' 540 | seats = 2147483647 541 | owner_hexlicsrv = '00:00:00:00:00:00' 542 | owner = 'RenardDev' 543 | name = 'RenardDev' 544 | email = 'zeze839@gmail.com' 545 | 546 | hexlicsrv_license_id = generate_id(ID_5=0x00) 547 | license_id = generate_id(ID_5=0x00) 548 | 549 | # Add-ons 550 | 551 | add_ons_list = [ 552 | 'HEXX86', 553 | 'HEXX64', 554 | 'HEXARM', 555 | 'HEXARM64', 556 | 'HEXMIPS', 557 | 'HEXMIPS64', 558 | 'HEXPPC', 559 | 'HEXPPC64', 560 | 'HEXRV64', 561 | 'HEXARC', 562 | 'HEXARC64' 563 | ] 564 | 565 | add_ons = [] 566 | for idx, add_on in enumerate(add_ons_list): 567 | license_id_copy = license_id.copy() 568 | license_id_copy[5] += idx + 1 569 | add_ons.append(generate_add_on(add_on, format_id(license_id), start_date, end_date, format_id(license_id_copy))) 570 | 571 | # Licenses 572 | 573 | licenses = [ 574 | generate_license('named', 'LICENSE_SERVER', 'license-server', 'Licensed by RenardDev', seats, start_date, end_date, start_date, owner_hexlicsrv, [], [], format_id(hexlicsrv_license_id)), 575 | generate_license('floating', 'IDAPRO', 'ida-pro', 'Licensed by RenardDev', seats, start_date, end_date, start_date, owner, add_ons, [], format_id(license_id)) 576 | ] 577 | 578 | # Package 579 | 580 | license_package = generate_license_package(1, name, email, licenses) 581 | license_package['signature'] = sign_license_package(license_package, private_key, public_key) 582 | 583 | # File 584 | 585 | serialized = to_alphabetical_json(license_package) 586 | with open(license_path, 'w') as f: 587 | f.write(serialized) 588 | print('INFO: License generated!') 589 | 590 | return 0 591 | 592 | if __name__ == '__main__': 593 | sys.exit(main(sys.argv)) 594 | -------------------------------------------------------------------------------- /lumina/CA/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /lumina/config/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /lumina/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /lumina/db_data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /lumina/docker-compose.yml: -------------------------------------------------------------------------------- 1 | 2 | services: 3 | db: 4 | container_name: db 5 | image: mysql:8.0.40 6 | restart: always 7 | environment: 8 | MYSQL_ROOT_PASSWORD: lumina 9 | MYSQL_DATABASE: lumina 10 | MYSQL_USER: lumina 11 | MYSQL_PASSWORD: lumina 12 | volumes: 13 | - ./db_data:/var/lib/mysql 14 | - ./my.cnf:/etc/mysql/my.cnf:ro 15 | ports: 16 | - "3306:3306" 17 | 18 | lumina: 19 | container_name: lumina 20 | depends_on: 21 | - db 22 | build: 23 | context: ./image 24 | restart: always 25 | environment: 26 | MYSQL_HOST: db 27 | MYSQL_DATABASE: lumina 28 | MYSQL_USER: lumina 29 | MYSQL_PASSWORD: lumina 30 | LUMINA_HOST: reversing.example.com 31 | LUMINA_PORT: 443 # Optional; Default: 443 32 | 33 | # Optional Vault integration 34 | VAULT_HOST: reversing.example.com 35 | VAULT_PORT: 65433 36 | volumes: 37 | - ./CA:/opt/lumina/CA 38 | - ./config:/opt/lumina/config 39 | - ./logs:/opt/lumina/logs 40 | - ./data:/opt/lumina/data 41 | ports: 42 | - "443:443" 43 | 44 | phpmyadmin: 45 | container_name: phpmyadmin 46 | depends_on: 47 | - db 48 | image: phpmyadmin/phpmyadmin:latest 49 | restart: always 50 | environment: 51 | PMA_HOST: db 52 | MYSQL_ROOT_PASSWORD: lumina 53 | ports: 54 | - "8080:80" 55 | -------------------------------------------------------------------------------- /lumina/image/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:12 2 | 3 | EXPOSE 443 4 | 5 | RUN apt-get update && \ 6 | apt-get install -y netcat-openbsd python3 && \ 7 | apt-get clean && \ 8 | rm -rf /var/lib/apt/lists/* 9 | 10 | COPY lumina90_x64linux.run /tmp/lumina90_x64linux.run 11 | COPY entrypoint.sh /entrypoint.sh 12 | COPY patch.py /opt/lumina/patch.py 13 | 14 | RUN chmod +x /entrypoint.sh && \ 15 | echo -e '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\ny\n\ny\n\n\n\n\n\n\ny\n\n\nn\ny\n\n' | /tmp/lumina90_x64linux.run --mode text && \ 16 | rm /tmp/lumina90_x64linux.run && \ 17 | mkdir -p /opt/lumina/{CA,config,data} 18 | 19 | ENTRYPOINT ["/entrypoint.sh"] 20 | -------------------------------------------------------------------------------- /lumina/image/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Installation paths 4 | INSTALL_PATH="/opt/lumina" 5 | CA_PATH="${INSTALL_PATH}/CA" 6 | CONFIG_PATH="${INSTALL_PATH}/config" 7 | LOGS_PATH="${INSTALL_PATH}/logs" 8 | DATA_PATH="${INSTALL_PATH}/data" 9 | SCHEMA_LOCK="${CONFIG_PATH}/lumina_schema.lock" 10 | 11 | # Database and Server Variables with Defaults 12 | MYSQL_HOST="${MYSQL_HOST:-localhost}" 13 | MYSQL_PORT="${MYSQL_PORT:-3306}" 14 | MYSQL_DATABASE="${MYSQL_DATABASE:-lumina}" 15 | MYSQL_USER="${MYSQL_USER:-lumina}" 16 | MYSQL_PASSWORD="${MYSQL_PASSWORD:-lumina}" 17 | LUMINA_HOST="${LUMINA_HOST:-localhost}" 18 | LUMINA_PORT="${LUMINA_PORT:-443}" 19 | 20 | # Ensure directory structure 21 | mkdir -p "$CA_PATH" "$CONFIG_PATH" "$LOGS_PATH" "$DATA_PATH" 22 | 23 | # Wait for database connection 24 | wait_for_db() { 25 | until nc -z "$MYSQL_HOST" "$MYSQL_PORT"; do 26 | echo "Waiting for database connection on $MYSQL_HOST:$MYSQL_PORT..." 27 | sleep 5 28 | done 29 | echo "Database connection established." 30 | } 31 | 32 | wait_for_db 33 | 34 | # Generate configuration file if it doesn't exist 35 | CONFIG_FILE="${CONFIG_PATH}/lumina.conf" 36 | if [[ ! -f "$CONFIG_FILE" ]]; then 37 | cat > "$CONFIG_FILE" <<-EOL 38 | CONNSTR="mysql;Server=$MYSQL_HOST;Port=$MYSQL_PORT;Database=$MYSQL_DATABASE;Uid=$MYSQL_USER;Pwd=$MYSQL_PASSWORD;" 39 | EOL 40 | [[ -n "$VAULT_HOST" && -n "$VAULT_PORT" ]] && echo "VAULT_HOST=\"$VAULT_HOST:$VAULT_PORT\"" >> "$CONFIG_FILE" 41 | chmod 640 "$CONFIG_FILE" 42 | fi 43 | 44 | # Verify Certification Authority files 45 | if [[ ! -f "${CA_PATH}/CA.pem" || ! -f "${CA_PATH}/CA.key" ]]; then 46 | echo "ERROR: Certification Authority files are missing in $CA_PATH!" 47 | sleep 5 48 | exit 1 49 | fi 50 | 51 | # Apply patch and set permissions 52 | python3 "${INSTALL_PATH}/patch.py" lumina || { echo "Patch script failed"; exit 1; } 53 | chown root:root "${INSTALL_PATH}/lumina_server" "${INSTALL_PATH}/lc" 54 | chmod 755 "${INSTALL_PATH}/lumina_server" "${INSTALL_PATH}/lc" 55 | 56 | # Recreate schema if necessary 57 | if [[ ! -f "$SCHEMA_LOCK" ]]; then 58 | SCHEMA_TYPE="lumina" 59 | [[ -n "$VAULT_HOST" && -n "$VAULT_PORT" ]] && SCHEMA_TYPE="vault" 60 | "${INSTALL_PATH}/lumina_server" -f "$CONFIG_FILE" --recreate-schema "$SCHEMA_TYPE" 61 | touch "$SCHEMA_LOCK" 62 | fi 63 | 64 | # Generate TLS certificate chain 65 | openssl req -newkey rsa:2048 -keyout "${CONFIG_PATH}/lumina.key" \ 66 | -out "${CONFIG_PATH}/lumina.csr" -nodes -subj "/CN=${LUMINA_HOST}" || { 67 | echo "Failed to create TLS certificate request" 68 | exit 1 69 | } 70 | 71 | openssl x509 -req -in "${CONFIG_PATH}/lumina.csr" -CA "${CA_PATH}/CA.pem" \ 72 | -CAkey "${CA_PATH}/CA.key" -CAcreateserial -out "${CONFIG_PATH}/lumina.crt" \ 73 | -days 365 -sha512 -extfile <(cat <<-EOF 74 | [req] 75 | distinguished_name=req_distinguished_name 76 | [req_distinguished_name] 77 | [v3_req] 78 | keyUsage = critical, digitalSignature, keyEncipherment 79 | extendedKeyUsage = serverAuth 80 | subjectAltName = @alt_names 81 | [alt_names] 82 | DNS.1 = "$LUMINA_HOST" 83 | EOF 84 | ) || { echo "Failed to generate TLS certificate"; exit 1; } 85 | 86 | # Clean up the certificate request file 87 | rm -f "${CONFIG_PATH}/lumina.csr" 88 | 89 | # Set ownership and permissions 90 | chown lumina:lumina "$CONFIG_FILE" "${CONFIG_PATH}/lumina.crt" "${CONFIG_PATH}/lumina.key" "${INSTALL_PATH}/lumina_server.hexlic" 91 | chmod 640 "$CONFIG_FILE" "${CONFIG_PATH}/lumina.crt" "${CONFIG_PATH}/lumina.key" "${INSTALL_PATH}/lumina_server.hexlic" 92 | 93 | # Start the Lumina server 94 | "${INSTALL_PATH}/lumina_server" -f "$CONFIG_FILE" \ 95 | -p "$LUMINA_PORT" \ 96 | -D "$DATA_PATH" \ 97 | -l "${LOGS_PATH}/lumina_server.log" \ 98 | -c "${CONFIG_PATH}/lumina.crt" \ 99 | -k "${CONFIG_PATH}/lumina.key" \ 100 | -L "${INSTALL_PATH}/lumina_server.hexlic" 101 | 102 | sleep 30 103 | -------------------------------------------------------------------------------- /lumina/image/patch.py: -------------------------------------------------------------------------------- 1 | 2 | # Imports 3 | 4 | import platform 5 | import sys 6 | import hashlib 7 | import json 8 | 9 | from pathlib import Path 10 | from random import randint 11 | from datetime import datetime 12 | 13 | # General 14 | 15 | CURRENT_DIRECTORY = Path(__file__).parent 16 | OS_NAME = platform.system() 17 | 18 | ORIGINAL_ROOT_CA_CERTIFICATE = bytes.fromhex('2D2D2D2D2D424547494E2043455254494649434154452D2D2D2D2D0A4D4949463054434341376D6741774942416749554C7A4B74454F50395137562F4C2F4734526E76344C3376712F6845774451594A4B6F5A496876634E4151454E0A425141775644454C4D416B474131554542684D43516B5578447A414E42674E564241634D426B78707736686E5A5445564D424D47413155454367774D534756340A4C564A6865584D67553045754D5230774777594456515144444252495A586774556D46356379425451533467556D39766443424451544165467730794D4441310A4D4451784D5441794D446861467730304D4441304D6A6B784D5441794D4468614D465178437A414A42674E5642415954416B4A464D51387744515944565151480A44415A4D61634F6F5A3255784654415442674E5642416F4D4445686C6543315359586C7A49464E424C6A45644D4273474131554541777755534756344C564A680A65584D675530457549464A766233516751304577676749694D4130474353714753496233445145424151554141344943447741776767494B416F4943415144420A727345683438564E796A4350524F53597A773576694163664475426F4441486533624952594D61476D3261366F6D5358537A54303252416970536C4F366E4A5A0A2F50674E4569706158594C6245586D727247646E5364427538756235317431374164476347597A7A506A534970495648356D5832694F624864533367794E7A700A4A4B4A515543444D3646644A61385A637A744B772B6258734E3166744B615A437A4863755542633850356C6B6952476375596662694872693543303270476F310A3379344F7A3939536F74384B5566774E6842794F4F474F77655979666E394E676D6871686B427532372B367278706D7552376D48794F68666E4C732B707351300A796A4536627A756C32696C5746724F53614C41784B6268424C4C5144574359654276586D4530497A6D5A56626F32447154552B4E575245553661766D5252427A0A36526E5A484655686C324C56624A354172343542617752333862524E726F36564E4354713839724258564665436E6B394A613676345A416F576D6A4A757048430A70585449786F65626B6F655741774943757A36336357735268317932617164675136763979564572413634476867436B704A4F383248447441395369716765330A542B7267556E6A3170636C6C474B6778414659634B686C434C6C342B626D306F686C784630574638564D68472F54424C4E48334D6C4A466A6C4D6F4277516E6C0A4150686545675A576F5153456A416B7A524C55725277376B566B2F51743847356846474C6233556A4538534B44504B5259534241554E2F75503859484B46716F0A3261727054436931444F345371583872367A717A736C565466367557546971384D4E6B5A2F2B374E5972312F4A50543235694D6C7736736136673447555070510A7A685261507931396F62476534337534766A7079736539673576715839703375394D49313478336B36514944415141426F3447614D4947584D423047413155640A4467515742425161784E6163664D37584B6A4B4975744948726336746A6945394454416642674E5648534D454744415767425161784E6163664D37584B6A4B490A75744948726336746A6945394454415042674E5648524D4241663845425441444151482F4D41344741315564447745422F77514541774942686A413042674E560A485238454C5441724D436D674A36416C68694E6F644852774F69387659334A734C6D686C6543317959586C7A4C6D4E76625339796232393058324E684C6D4E790A6244414E42676B71686B6947397730424151304641414F4341674541644B7034496E70526B357A30426A50733643634A53674B624348304D585A7162742F454D0A2F34644A50766D4136744165784A7076396539426D542F444F423834514232787A516C45694E4F42372F56346A336F44696A356D4D77527971594C32346C33670A4841617677632B644C72707A582F3534755A6D4839624B7337796A33666B2F7655336537746837323041724C322F595A6A485632577830424D63732B595669740A70687647326D7875313644547069646D733370436A3235654549534A76586665385845664B4F503146784743706D4B7878367150486C4E41534F70357A6477560A6945696D6B677555777A43736D6D5049357245574C58644C52786330436B66666D62734E6D734638535A7A333843697775526C6963684444645A754A586A69370A6A6E5A46376830344D6F32414B507436774A392B36367259714469677650397348474B70517035687231444D756B46476E656933533968354B703865446852580A593234792F434A564E4F307278596F4650556E4F77625355463346777534665833457A71356557374E304E6C37733058484578622F5039666D685078514256310A677772363635696E71355A77443848397577474556703349425439634852753869655A7251444D49315571504F792B3245574E507459344B786D6765725462630A4E3056483442754538746478544755636B67344A5462734E525562717853586D534C396A4131644C425436336C624D4C49553036644964714E627078453447560A4D674F4C777177782F42462B465A6751547474646A6D7065786D6C364E49445647444278667945434A3576647778624B4D4952666F376670306A52706A5A70500A3862773442506E783059344E704D7A4B78695753306937726539694561666468364774704E796E4B55304A46534B7249776D4965634B462B5A345A55452F314B0A2B742F464F67493D0A2D2D2D2D2D454E442043455254494649434154452D2D2D2D2D0A00') 19 | ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS = bytes.fromhex('4D4949463054434341376D6741774942416749554C7A4B74454F50395137562F4C2F4734526E76344C3376712F6845774451594A4B6F5A496876634E4151454E425141775644454C4D416B474131554542684D43516B5578447A414E42674E564241634D426B78707736686E5A5445564D424D47413155454367774D534756344C564A6865584D67553045754D5230774777594456515144444252495A586774556D46356379425451533467556D39766443424451544165467730794D4441314D4451784D5441794D446861467730304D4441304D6A6B784D5441794D4468614D465178437A414A42674E5642415954416B4A464D513877445159445651514844415A4D61634F6F5A3255784654415442674E5642416F4D4445686C6543315359586C7A49464E424C6A45644D4273474131554541777755534756344C564A6865584D675530457549464A766233516751304577676749694D4130474353714753496233445145424151554141344943447741776767494B416F494341514442727345683438564E796A4350524F53597A773576694163664475426F4441486533624952594D61476D3261366F6D5358537A54303252416970536C4F366E4A5A2F50674E4569706158594C6245586D727247646E5364427538756235317431374164476347597A7A506A534970495648356D5832694F624864533367794E7A704A4B4A515543444D3646644A61385A637A744B772B6258734E3166744B615A437A4863755542633850356C6B6952476375596662694872693543303270476F313379344F7A3939536F74384B5566774E6842794F4F474F77655979666E394E676D6871686B427532372B367278706D7552376D48794F68666E4C732B70735130796A4536627A756C32696C5746724F53614C41784B6268424C4C5144574359654276586D4530497A6D5A56626F32447154552B4E575245553661766D5252427A36526E5A484655686C324C56624A354172343542617752333862524E726F36564E4354713839724258564665436E6B394A613676345A416F576D6A4A7570484370585449786F65626B6F655741774943757A36336357735268317932617164675136763979564572413634476867436B704A4F38324844744139536971676533542B7267556E6A3170636C6C474B6778414659634B686C434C6C342B626D306F686C784630574638564D68472F54424C4E48334D6C4A466A6C4D6F4277516E6C4150686545675A576F5153456A416B7A524C55725277376B566B2F51743847356846474C6233556A4538534B44504B5259534241554E2F75503859484B46716F3261727054436931444F345371583872367A717A736C565466367557546971384D4E6B5A2F2B374E5972312F4A50543235694D6C7736736136673447555070517A685261507931396F62476534337534766A7079736539673576715839703375394D49313478336B36514944415141426F3447614D4947584D423047413155644467515742425161784E6163664D37584B6A4B4975744948726336746A6945394454416642674E5648534D454744415767425161784E6163664D37584B6A4B4975744948726336746A6945394454415042674E5648524D4241663845425441444151482F4D41344741315564447745422F77514541774942686A413042674E56485238454C5441724D436D674A36416C68694E6F644852774F69387659334A734C6D686C6543317959586C7A4C6D4E76625339796232393058324E684C6D4E796244414E42676B71686B6947397730424151304641414F4341674541644B7034496E70526B357A30426A50733643634A53674B624348304D585A7162742F454D2F34644A50766D4136744165784A7076396539426D542F444F423834514232787A516C45694E4F42372F56346A336F44696A356D4D77527971594C32346C33674841617677632B644C72707A582F3534755A6D4839624B7337796A33666B2F7655336537746837323041724C322F595A6A485632577830424D63732B5956697470687647326D7875313644547069646D733370436A3235654549534A76586665385845664B4F503146784743706D4B7878367150486C4E41534F70357A6477566945696D6B677555777A43736D6D5049357245574C58644C52786330436B66666D62734E6D734638535A7A333843697775526C6963684444645A754A586A69376A6E5A46376830344D6F32414B507436774A392B36367259714469677650397348474B70517035687231444D756B46476E656933533968354B70386544685258593234792F434A564E4F307278596F4650556E4F77625355463346777534665833457A71356557374E304E6C37733058484578622F5039666D68507851425631677772363635696E71355A77443848397577474556703349425439634852753869655A7251444D49315571504F792B3245574E507459344B786D6765725462634E3056483442754538746478544755636B67344A5462734E525562717853586D534C396A4131644C425436336C624D4C49553036644964714E627078453447564D674F4C777177782F42462B465A6751547474646A6D7065786D6C364E49445647444278667945434A3576647778624B4D4952666F376670306A52706A5A70503862773442506E783059344E704D7A4B78695753306937726539694561666468364774704E796E4B55304A46534B7249776D4965634B462B5A345A55452F314B2B742F464F67493D00') 20 | ORIGINAL_PUBLIC_MODULUS = bytes.fromhex('EDFD425CF978546E8911225884436C57140525650BCF6EBFE80EDBC5FB1DE68F4C66C29CB22EB668788AFCB0ABBB718044584B810F8970CDDF227385F75D5DDDD91D4F18937A08AA83B28C49D12DC92E7505BB38809E91BD0FBD2F2E6AB1D2E33C0C55D5BDDD478EE8BF845FCEF3C82B9D2929ECB71F4D1B3DB96E3A8E7AAF93') 21 | 22 | PRIVATE_KEY = bytes.fromhex('77C86ABBB7F3BB134436797B68FF47BEB1A5457816608DBFB72641814DD464DD640D711D5732D3017A1C4E63D835822F00A4EAB619A2C4791CF33F9F57F9C2AE4D9EED9981E79AC9B8F8A411F68F25B9F0C05D04D11E22A3A0D8D4672B56A61F1532282FF4E4E74759E832B70E98B9D102D07E9FB9BA8D15810B144970029874') 23 | NEW_PUBLIC_MODULUS = bytes.fromhex('EDFD42CBF978546E8911225884436C57140525650BCF6EBFE80EDBC5FB1DE68F4C66C29CB22EB668788AFCB0ABBB718044584B810F8970CDDF227385F75D5DDDD91D4F18937A08AA83B28C49D12DC92E7505BB38809E91BD0FBD2F2E6AB1D2E33C0C55D5BDDD478EE8BF845FCEF3C82B9D2929ECB71F4D1B3DB96E3A8E7AAF93') 24 | 25 | HAVE_NEW_ROOT_CA_CERTIFICATE = False 26 | if CURRENT_DIRECTORY.joinpath('CA').joinpath('CA.pem').exists(): 27 | NEW_ROOT_CA_CERTIFICATE = b'' 28 | with open(CURRENT_DIRECTORY.joinpath('CA').joinpath('CA.pem'), 'rb') as f: 29 | NEW_ROOT_CA_CERTIFICATE += f.read() 30 | NEW_ROOT_CA_CERTIFICATE += b'\x00' 31 | 32 | NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS = NEW_ROOT_CA_CERTIFICATE \ 33 | .replace(b'-----BEGIN CERTIFICATE-----', b'') \ 34 | .replace(b'-----END CERTIFICATE-----', b'') \ 35 | .replace(b'\r\n', b'') \ 36 | .replace(b'\r', b'') \ 37 | .replace(b'\n', b'') 38 | 39 | if len(NEW_ROOT_CA_CERTIFICATE) > len(ORIGINAL_ROOT_CA_CERTIFICATE) or \ 40 | len(NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) > len(ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS): 41 | print('New CA certificate is too big!') 42 | else: 43 | NEW_ROOT_CA_CERTIFICATE += b'\x00' * (len(ORIGINAL_ROOT_CA_CERTIFICATE) - len(NEW_ROOT_CA_CERTIFICATE)) 44 | NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS += b'\x00' * (len(ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) - len(NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS)) 45 | 46 | HAVE_NEW_ROOT_CA_CERTIFICATE = True 47 | 48 | # Crypto functions 49 | 50 | def bytes_to_bigint(data: bytes) -> int: 51 | return int.from_bytes(data, byteorder='little') 52 | 53 | def bigint_to_bytes(n: int) -> bytes: 54 | return n.to_bytes((n.bit_length() + 7) // 8, byteorder='little') 55 | 56 | def decrypt_message(message: bytes, public_key: int, exponent: int = 0x13) -> bytes: 57 | decrypted = pow(bytes_to_bigint(message), exponent, public_key) 58 | decrypted = bigint_to_bytes(decrypted) 59 | return decrypted[::-1] 60 | 61 | def encrypt_message(message: bytes, private_key: int, public_key: int) -> bytes: 62 | encrypted = pow(bytes_to_bigint(message[::-1]), private_key, public_key) 63 | encrypted = bigint_to_bytes(encrypted) 64 | return encrypted 65 | 66 | # License 67 | 68 | # code 69 | # HEXX86 70 | # HEXX64 71 | # HEXARM 72 | # HEXARM64 73 | # HEXMIPS 74 | # HEXMIPS64 75 | # HEXPPC 76 | # HEXPPC64 77 | # HEXRV 78 | # HEXRV64 79 | # HEXARC 80 | # HEXARC64 81 | # 82 | # HEXCX86 83 | # HEXCX64 84 | # HEXCARM 85 | # HEXCARM64 86 | # HEXCMIPS 87 | # HEXCMIPS64 88 | # HEXCPPC 89 | # HEXCPPC64 90 | # HEXCRV 91 | # HEXCRV64 92 | # HEXCARC 93 | # HEXCARC64 94 | # 95 | # LUMINA 96 | # TEAMS 97 | 98 | def generate_add_on(code: str, owner: str, start_date: str, end_date: str, id: str) -> dict: 99 | data = { 100 | 'code': code, 101 | 'owner': owner, 102 | 'start_date': start_date, 103 | 'end_date': end_date, 104 | 'id': id 105 | } 106 | 107 | return data 108 | 109 | # product_id 110 | # IDAPRO 111 | # IDAHOME 112 | # IDAFREE 113 | # TEAMS_SERVER 114 | # LUMINA_SERVER 115 | # LICENSE_SERVER 116 | 117 | # edition_id: 118 | # ida-pro 119 | # ida-pro-classroom 120 | # ida-home-pc 121 | # ida-home-arm 122 | # ida-home-mips 123 | # ida-home-ppc 124 | # ida-home-riscv 125 | # ida-free 126 | # teams-server 127 | # lumina-server 128 | # license-server 129 | 130 | def generate_license(license_type: str, product_id: str, edition_id: str, description: str, seats: int, start_date: str, end_date: str, issued_on: str, owner: str, add_ons: list, features: list, id: str) -> dict: 131 | data = { 132 | 'license_type': license_type, 133 | 'product_id': product_id, 134 | 'edition_id': edition_id, 135 | 'description': description, 136 | 'seats': seats, 137 | 'start_date': start_date, 138 | 'end_date': end_date, 139 | 'issued_on': issued_on, 140 | 'owner': owner, 141 | 'add_ons': add_ons, 142 | 'features': features, 143 | 'id': id 144 | } 145 | 146 | return data 147 | 148 | def generate_license_package(version: int, name: str, email: str, licenses: list) -> dict: 149 | if version == 1: 150 | data = { 151 | 'header': { 'version': version }, 152 | 'payload': { 153 | 'name': name, 154 | 'email': email, 155 | 'licenses': licenses 156 | } 157 | } 158 | 159 | return data 160 | 161 | def to_alphabetical_json(d: dict) -> str: 162 | return json.dumps(d, sort_keys=True, separators=(',', ':')) 163 | 164 | def from_alphabetical_json(s: str) -> dict: 165 | return json.loads(s) 166 | 167 | def sign_license_package(license: dict, private_key: int, public_key: int) -> str: 168 | data = { 'payload': license['payload'] } 169 | data_str = to_alphabetical_json(data) 170 | 171 | buffer = bytearray(128) 172 | 173 | # First 33 bytes are random 174 | for i in range(33): 175 | buffer[i] = 0x42 176 | 177 | # Compute sha256 of the data 178 | sha256 = hashlib.sha256() 179 | sha256.update(data_str.encode()) 180 | digest = sha256.digest() 181 | 182 | # Copy the sha256 digest to the buffer 183 | for i in range(32): 184 | buffer[33 + i] = digest[i] 185 | 186 | # Encrypt the buffer 187 | encrypted = encrypt_message(buffer, private_key, public_key) 188 | 189 | return encrypted.hex().upper() 190 | 191 | # Patch 192 | 193 | def patch_file(file_path: Path) -> bool: 194 | data = None 195 | 196 | if file_path.exists(): 197 | with open(file_path, 'rb') as f: 198 | data = f.read() 199 | 200 | backup_file_path = file_path.parent / (file_path.name + '.bak') 201 | 202 | if not backup_file_path.exists(): 203 | with open(backup_file_path, 'wb') as sf: 204 | sf.write(data) 205 | else: 206 | with open(backup_file_path, 'rb') as sf: 207 | data = sf.read() 208 | 209 | if data: 210 | if HAVE_NEW_ROOT_CA_CERTIFICATE: 211 | if data.find(NEW_PUBLIC_MODULUS[:6]) != -1 or data.find(NEW_ROOT_CA_CERTIFICATE) != -1 or data.find(NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) != -1: 212 | print(f'INFO: `{file_path.name}` already has a patch.') 213 | return False 214 | 215 | if data.find(ORIGINAL_PUBLIC_MODULUS[:6]) == -1 and data.find(ORIGINAL_ROOT_CA_CERTIFICATE) == -1 and data.find(ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) == -1: 216 | print(f'ERROR: Patch for `{file_path.name}` is not supported!') 217 | return False 218 | else: 219 | if data.find(NEW_PUBLIC_MODULUS[:6]) != -1: 220 | print(f'INFO: `{file_path.name}` already has a patch.') 221 | return False 222 | 223 | if data.find(ORIGINAL_PUBLIC_MODULUS[:6]) == -1: 224 | print(f'ERROR: Patch for `{file_path.name}` is not supported!') 225 | return False 226 | 227 | data = data.replace(ORIGINAL_PUBLIC_MODULUS[:6], NEW_PUBLIC_MODULUS[:6]) 228 | 229 | if HAVE_NEW_ROOT_CA_CERTIFICATE: 230 | data = data.replace(ORIGINAL_ROOT_CA_CERTIFICATE, NEW_ROOT_CA_CERTIFICATE) 231 | data = data.replace(ORIGINAL_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS, NEW_ROOT_CA_CERTIFICATE_WITHOUT_HEADERS) 232 | 233 | with open(file_path, 'wb') as f: 234 | f.write(data) 235 | 236 | print(f'INFO: `{file_path.name}` successful patched.') 237 | 238 | # Main 239 | 240 | def generate_id(ID_0: int = randint(0x00, 0xFF), ID_1: int = randint(0x00, 0xFF), 241 | ID_2: int = randint(0x00, 0xFF), ID_3: int = randint(0x00, 0xFF), 242 | ID_4: int = randint(0x00, 0xFF), ID_5: int = randint(0x00, 0xFF)) -> list: 243 | return [ID_0, ID_1, ID_2, ID_3, ID_4, ID_5] 244 | 245 | def format_id(id:list) -> str: 246 | return f'{id[0]:02X}-{id[1]:02X}{id[2]:02X}-{id[3]:02X}{id[4]:02X}-{id[5]:02X}' 247 | 248 | def main(argv: list) -> int: 249 | 250 | private_key = bytes_to_bigint(PRIVATE_KEY) 251 | public_key = bytes_to_bigint(NEW_PUBLIC_MODULUS) 252 | 253 | if 'ida-pro' in argv: 254 | if OS_NAME == 'Linux': 255 | files = [ 256 | 'hv', 257 | 'hvui', 258 | 'libida.so', 259 | 'libida32.so', 260 | 'dbgsrv/linux_server', 261 | 'dbgsrv/linux_server32', 262 | 'dbgsrv/mac_server', 263 | 'dbgsrv/mac_server32', 264 | 'dbgsrv/mac_server_arm', 265 | 'dbgsrv/mac_server_arme', 266 | 'dbgsrv/win32_remote32', 267 | 'dbgsrv/win64_remote.exe', 268 | 'plugins/armlinux_stub.so', 269 | 'plugins/arm_mac_stub.so', 270 | 'plugins/dalvik_user.so', 271 | 'plugins/gdb_user.so', 272 | 'plugins/ios_user.so', 273 | 'plugins/linux_stub.so', 274 | 'plugins/mac_stub.so', 275 | 'plugins/pin_user.so', 276 | 'plugins/win32_stub.so', 277 | 'plugins/xnu_user.so', 278 | ] 279 | 280 | for file in files: 281 | patch_file(CURRENT_DIRECTORY.joinpath(file)) 282 | 283 | elif OS_NAME == 'Windows': 284 | files = [ 285 | 'hv.exe', 286 | 'hvui.exe', 287 | 'ida.dll', 288 | 'ida32.dll', 289 | 'dbgsrv/linux_server', 290 | 'dbgsrv/linux_server32', 291 | 'dbgsrv/mac_server', 292 | 'dbgsrv/mac_server32', 293 | 'dbgsrv/mac_server_arm', 294 | 'dbgsrv/mac_server_arme', 295 | 'dbgsrv/win32_remote32', 296 | 'dbgsrv/win64_remote.exe', 297 | 'plugins/armlinux_stub.dll', 298 | 'plugins/arm_mac_stub.dll', 299 | 'plugins/dalvik_user.dll', 300 | 'plugins/gdb_user.dll', 301 | 'plugins/ios_user.dll', 302 | 'plugins/linux_stub.dll', 303 | 'plugins/mac_stub.dll', 304 | 'plugins/pin_user.dll', 305 | 'plugins/win32_stub.dll', 306 | 'plugins/xnu_user.dll', 307 | ] 308 | 309 | for file in files: 310 | patch_file(CURRENT_DIRECTORY.joinpath(file)) 311 | 312 | elif OS_NAME == 'iOS': 313 | files = [ 314 | 'hv', 315 | 'hvui', 316 | 'libida.dylib', 317 | 'libida32.dylib', 318 | 'dbgsrv/linux_server', 319 | 'dbgsrv/linux_server32', 320 | 'dbgsrv/mac_server', 321 | 'dbgsrv/mac_server32', 322 | 'dbgsrv/mac_server_arm', 323 | 'dbgsrv/mac_server_arme', 324 | 'dbgsrv/win32_remote32', 325 | 'dbgsrv/win64_remote.exe', 326 | 'plugins/armlinux_stub.dylib', 327 | 'plugins/arm_mac_stub.dylib', 328 | 'plugins/dalvik_user.dylib', 329 | 'plugins/gdb_user.dylib', 330 | 'plugins/ios_user.dylib', 331 | 'plugins/linux_stub.dylib', 332 | 'plugins/mac_stub.dylib', 333 | 'plugins/pin_user.dylib', 334 | 'plugins/win32_stub.dylib', 335 | 'plugins/xnu_user.dylib', 336 | ] 337 | 338 | for file in files: 339 | patch_file(CURRENT_DIRECTORY.joinpath(file)) 340 | 341 | license_path = CURRENT_DIRECTORY.joinpath('idapro.hexlic') 342 | is_valid_license = False 343 | if license_path.exists(): 344 | with open(license_path, 'r') as f: 345 | license_package = from_alphabetical_json(f.read()) 346 | if sign_license_package(license_package, private_key, public_key) == license_package['signature']: 347 | is_valid_license = True 348 | if is_valid_license: 349 | return 0 350 | 351 | # Set up 352 | 353 | start_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 354 | end_date = '2038-01-19 03:14:07' 355 | owner = 'RenardDev' 356 | name = 'RenardDev' 357 | email = 'zeze839@gmail.com' 358 | 359 | license_id = generate_id(ID_5=0x00) 360 | 361 | # Add-ons 362 | 363 | add_ons_list = [ 364 | 'HEXX86', 365 | 'HEXX64', 366 | 'HEXARM', 367 | 'HEXARM64', 368 | 'HEXMIPS', 369 | 'HEXMIPS64', 370 | 'HEXPPC', 371 | 'HEXPPC64', 372 | 'HEXRV64', 373 | 'HEXARC', 374 | 'HEXARC64' 375 | ] 376 | 377 | add_ons = [] 378 | for idx, add_on in enumerate(add_ons_list): 379 | license_id_copy = license_id.copy() 380 | license_id_copy[5] += idx + 1 381 | add_ons.append(generate_add_on(add_on, format_id(license_id), start_date, end_date, format_id(license_id_copy))) 382 | 383 | # Licenses 384 | 385 | licenses = [ 386 | generate_license('named', 'IDAPRO', 'ida-pro', 'Licensed by RenardDev', 1, start_date, end_date, start_date, owner, add_ons, [], format_id(license_id)) 387 | ] 388 | 389 | # Package 390 | 391 | license_package = generate_license_package(1, name, email, licenses) 392 | license_package['signature'] = sign_license_package(license_package, private_key, public_key) 393 | 394 | # File 395 | 396 | serialized = to_alphabetical_json(license_package) 397 | with open(license_path, 'w') as f: 398 | f.write(serialized) 399 | print('INFO: License generated!') 400 | 401 | if 'hexvault' in argv: 402 | if OS_NAME == 'Linux': 403 | patch_file(CURRENT_DIRECTORY.joinpath('vault_server')) 404 | 405 | license_path = CURRENT_DIRECTORY.joinpath('teams_server.hexlic') 406 | is_valid_license = False 407 | if license_path.exists(): 408 | with open(license_path, 'r') as f: 409 | license_package = from_alphabetical_json(f.read()) 410 | if sign_license_package(license_package, private_key, public_key) == license_package['signature']: 411 | is_valid_license = True 412 | if is_valid_license: 413 | return 0 414 | 415 | # Set up 416 | 417 | start_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 418 | end_date = '2038-01-19 03:14:07' 419 | seats = 2147483647 420 | owner = '00:00:00:00:00:00' 421 | name = 'RenardDev' 422 | email = 'zeze839@gmail.com' 423 | 424 | license_id = generate_id(ID_5=0x00) 425 | 426 | # Add-ons 427 | 428 | add_ons_list = [ 429 | 'TEAMS' 430 | ] 431 | 432 | add_ons = [] 433 | for idx, add_on in enumerate(add_ons_list): 434 | license_id_copy = license_id.copy() 435 | license_id_copy[5] += idx + 1 436 | add_ons.append(generate_add_on(add_on, format_id(license_id), start_date, end_date, format_id(license_id_copy))) 437 | 438 | # Licenses 439 | 440 | licenses = [ 441 | generate_license('named', 'TEAMS_SERVER', 'teams-server', 'Licensed by RenardDev', seats, start_date, end_date, start_date, owner, add_ons, [], format_id(license_id)) 442 | ] 443 | 444 | # Package 445 | 446 | license_package = generate_license_package(1, name, email, licenses) 447 | license_package['signature'] = sign_license_package(license_package, private_key, public_key) 448 | 449 | # File 450 | 451 | serialized = to_alphabetical_json(license_package) 452 | with open(license_path, 'w') as f: 453 | f.write(serialized) 454 | print('INFO: License generated!') 455 | 456 | if 'lumina' in argv: 457 | if OS_NAME == 'Linux': 458 | patch_file(CURRENT_DIRECTORY.joinpath('lumina_server')) 459 | patch_file(CURRENT_DIRECTORY.joinpath('lc')) 460 | 461 | license_path = CURRENT_DIRECTORY.joinpath('lumina_server.hexlic') 462 | is_valid_license = False 463 | if license_path.exists(): 464 | with open(license_path, 'r') as f: 465 | license_package = from_alphabetical_json(f.read()) 466 | if sign_license_package(license_package, private_key, public_key) == license_package['signature']: 467 | is_valid_license = True 468 | if is_valid_license: 469 | return 0 470 | 471 | # Set up 472 | 473 | start_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 474 | end_date = '2038-01-19 03:14:07' 475 | seats = 2147483647 476 | owner = '00:00:00:00:00:00' 477 | name = 'RenardDev' 478 | email = 'zeze839@gmail.com' 479 | 480 | license_id = generate_id(ID_5=0x00) 481 | 482 | # Add-ons 483 | 484 | add_ons_list = [ 485 | 'LUMINA' 486 | ] 487 | 488 | add_ons = [] 489 | for idx, add_on in enumerate(add_ons_list): 490 | license_id_copy = license_id.copy() 491 | license_id_copy[5] += idx + 1 492 | add_ons.append(generate_add_on(add_on, format_id(license_id), start_date, end_date, format_id(license_id_copy))) 493 | 494 | # Licenses 495 | 496 | licenses = [ 497 | generate_license('named', 'LUMINA_SERVER', 'lumina-server', 'Licensed by RenardDev', seats, start_date, end_date, start_date, owner, add_ons, [], format_id(license_id)) 498 | ] 499 | 500 | # Package 501 | 502 | license_package = generate_license_package(1, name, email, licenses) 503 | license_package['signature'] = sign_license_package(license_package, private_key, public_key) 504 | 505 | # File 506 | 507 | serialized = to_alphabetical_json(license_package) 508 | with open(license_path, 'w') as f: 509 | f.write(serialized) 510 | print('INFO: License generated!') 511 | 512 | if 'hexlicsrv' in argv: 513 | if OS_NAME == 'Linux': 514 | patch_file(CURRENT_DIRECTORY.joinpath('license_server')) 515 | patch_file(CURRENT_DIRECTORY.joinpath('lsadm')) 516 | 517 | license_path = CURRENT_DIRECTORY.joinpath('license_server.hexlic') 518 | is_valid_license = False 519 | if license_path.exists(): 520 | with open(license_path, 'r') as f: 521 | license_package = from_alphabetical_json(f.read()) 522 | if sign_license_package(license_package, private_key, public_key) == license_package['signature']: 523 | is_valid_license = True 524 | if is_valid_license: 525 | return 0 526 | 527 | # Set up 528 | 529 | start_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 530 | end_date = '2038-01-19 03:14:07' 531 | seats = 2147483647 532 | owner_hexlicsrv = '00:00:00:00:00:00' 533 | owner = 'RenardDev' 534 | name = 'RenardDev' 535 | email = 'zeze839@gmail.com' 536 | 537 | hexlicsrv_license_id = generate_id(ID_5=0x00) 538 | license_id = generate_id(ID_5=0x00) 539 | 540 | # Add-ons 541 | 542 | add_ons_list = [ 543 | 'HEXX86', 544 | 'HEXX64', 545 | 'HEXARM', 546 | 'HEXARM64', 547 | 'HEXMIPS', 548 | 'HEXMIPS64', 549 | 'HEXPPC', 550 | 'HEXPPC64', 551 | 'HEXRV64', 552 | 'HEXARC', 553 | 'HEXARC64' 554 | ] 555 | 556 | add_ons = [] 557 | for idx, add_on in enumerate(add_ons_list): 558 | license_id_copy = license_id.copy() 559 | license_id_copy[5] += idx + 1 560 | add_ons.append(generate_add_on(add_on, format_id(license_id), start_date, end_date, format_id(license_id_copy))) 561 | 562 | # Licenses 563 | 564 | licenses = [ 565 | generate_license('named', 'LICENSE_SERVER', 'license-server', 'Licensed by RenardDev', seats, start_date, end_date, start_date, owner_hexlicsrv, [], [], format_id(hexlicsrv_license_id)), 566 | generate_license('floating', 'IDAPRO', 'ida-pro', 'Licensed by RenardDev', seats, start_date, end_date, start_date, owner, add_ons, [], format_id(license_id)) 567 | ] 568 | 569 | # Package 570 | 571 | license_package = generate_license_package(1, name, email, licenses) 572 | license_package['signature'] = sign_license_package(license_package, private_key, public_key) 573 | 574 | # File 575 | 576 | serialized = to_alphabetical_json(license_package) 577 | with open(license_path, 'w') as f: 578 | f.write(serialized) 579 | print('INFO: License generated!') 580 | 581 | return 0 582 | 583 | if __name__ == '__main__': 584 | sys.exit(main(sys.argv)) 585 | -------------------------------------------------------------------------------- /lumina/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /lumina/my.cnf: -------------------------------------------------------------------------------- 1 | [mysqld] 2 | default-authentication-plugin=mysql_native_password 3 | -------------------------------------------------------------------------------- /shell.9.1.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [HKEY_CLASSES_ROOT\*\shell\IDA Professional 9.1] 4 | "Icon"="C:\\Program Files\\IDA Professional 9.1\\ida.ico" 5 | @="IDA Professional 9.1" 6 | 7 | [HKEY_CLASSES_ROOT\*\shell\IDA Professional 9.1\command] 8 | @="\"C:\\Program Files\\IDA Professional 9.1\\ida.exe\" \"%1\"" 9 | -------------------------------------------------------------------------------- /shell.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [HKEY_CLASSES_ROOT\*\shell\IDA Professional 9.0] 4 | "Icon"="C:\\Program Files\\IDA Professional 9.0\\ida.ico" 5 | @="IDA Professional 9.0" 6 | 7 | [HKEY_CLASSES_ROOT\*\shell\IDA Professional 9.0\command] 8 | @="\"C:\\Program Files\\IDA Professional 9.0\\ida.exe\" \"%1\"" 9 | --------------------------------------------------------------------------------