├── .coveragerc ├── .dockerignore ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── tests_multi_os.yml ├── .gitignore ├── .gitmodules ├── .readthedocs.yml ├── Dockerfile ├── LICENSE ├── MANIFEST.in ├── Makefile ├── README.md ├── TODO ├── all_tests.sh ├── chepy ├── __init__.py ├── __init__.pyi ├── __main__.py ├── __version__.py ├── __version__.pyi ├── config.py ├── config.pyi ├── core.py ├── core.pyi ├── extras │ ├── __init__.py │ ├── __init__.pyi │ ├── bruteforce.py │ ├── bruteforce.pyi │ ├── characters.py │ ├── characters.pyi │ ├── combinatons.py │ ├── combinatons.pyi │ ├── crypto.py │ ├── crypto.pyi │ ├── misc.py │ └── misc.pyi └── modules │ ├── __init__.py │ ├── __init__.pyi │ ├── aritmeticlogic.py │ ├── aritmeticlogic.pyi │ ├── codetidy.py │ ├── codetidy.pyi │ ├── compression.py │ ├── compression.pyi │ ├── dataformat.py │ ├── dataformat.pyi │ ├── datetimemodule.py │ ├── datetimemodule.pyi │ ├── encryptionencoding.py │ ├── encryptionencoding.pyi │ ├── exceptions.py │ ├── exceptions.pyi │ ├── extractors.py │ ├── extractors.pyi │ ├── hashing.py │ ├── hashing.pyi │ ├── internal │ ├── __init__.py │ ├── __init__.pyi │ ├── cli.py │ ├── cli.pyi │ ├── colors.py │ ├── colors.pyi │ ├── constants.py │ ├── constants.pyi │ ├── helpers.py │ ├── ls47.py │ └── rison.py │ ├── language.py │ ├── language.pyi │ ├── links.py │ ├── links.pyi │ ├── networking.py │ ├── networking.pyi │ ├── other.py │ ├── other.pyi │ ├── publickey.py │ ├── publickey.pyi │ ├── search.py │ ├── search.pyi │ ├── utils.py │ └── utils.pyi ├── cli.py ├── docs ├── Makefile ├── assets │ ├── cc_encoding.png │ ├── clicolors.png │ ├── ctf.gif │ ├── hmac_hash.png │ └── plugin.gif ├── chepy.md ├── cli.md ├── conf.py ├── config.md ├── core.md ├── examples.md ├── extras.rst ├── faq.md ├── index.md ├── internal.rst ├── make.bat ├── modules.rst ├── modules │ ├── aritmeticlogic.rst │ ├── codetidy.rst │ ├── compression.rst │ ├── dataformat.rst │ ├── datetimemodule.rst │ ├── encryptionencoding.rst │ ├── extractors.rst │ ├── hashing.rst │ ├── language.rst │ ├── links.rst │ ├── multimedia.rst │ ├── networking.rst │ ├── other.rst │ ├── publickey.rst │ └── utils.rst ├── plugins.md ├── pullrequest.md ├── requirements.txt └── usage.md ├── logo.png ├── requirements.txt ├── setup.cfg ├── setup.py ├── tests ├── __init__.py ├── files │ ├── elf │ ├── encoding │ ├── fake_secrets.txt │ ├── ff.exe │ ├── flags │ ├── hello │ ├── keyboard.pcap │ ├── lsb.png │ ├── msb.png │ ├── pbuf │ ├── pkcs12 │ ├── private.pem │ ├── public.pem │ ├── qr.png │ ├── qr │ │ ├── aztec.qr.png │ │ └── basic.qr.png │ ├── script.py │ ├── test.db │ ├── test.der │ ├── test.html │ ├── test.js │ ├── test.json │ ├── test.pcapng │ ├── test.pem │ ├── test.tar.gz │ ├── test.xml │ ├── test.zip │ ├── vuln_code │ └── wordlist.txt ├── test_aritmeticlogic.py ├── test_cli.py ├── test_codetidy.py ├── test_compression.py ├── test_conf.py ├── test_core.py ├── test_ctf.py ├── test_dataformat.py ├── test_datetime.py ├── test_encryptionencoding.py ├── test_extractors.py ├── test_extras │ ├── __init__.py │ ├── test_bruteforce.py │ ├── test_characters.py │ ├── test_combinations.py │ ├── test_crypto_extras.py │ └── test_misc.py ├── test_file_encoding.py ├── test_hashing.py ├── test_language.py ├── test_links.py ├── test_networking.py ├── test_other.py ├── test_publickey.py ├── test_search.py └── test_utils.py └── tests_plugins ├── _test_git.py ├── test_additionalextractors.py ├── test_binary.py ├── test_extract_plugin.py ├── test_forensics.py ├── test_hash.py ├── test_ml.py ├── test_multimedia.py ├── test_pcap.py ├── test_protobuf.py ├── test_qr.py ├── test_sqlite.py └── test_useragent.py /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | omit = 3 | chepy/__main__.py 4 | chepy/config.py 5 | chepy/modules/internal/cli.py 6 | chepy/chepy_plugins/* 7 | 8 | 9 | [report] 10 | fail_under = 100 11 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .gitignore -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. Do keep in mind that Chepy is attempting to provide functionality that a web app does, which makes it difficult at times to work with certain types of user input. 12 | 13 | **To Reproduce** 14 | Provide sufficient detail to reproduce the bug. Make sure to provide link to file, and data required to reproduce. 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Screenshots** 20 | If applicable, add screenshots to help explain your problem. 21 | 22 | **Desktop (please complete the following information):** 23 | - OS: [e.g. iOS] 24 | - Python Version [e.g. 22] 25 | - Chepy Version [e.g. 22] 26 | 27 | **Additional context** 28 | Add any other context about the problem here. 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | **Make sure to include data and expected output** 13 | 14 | **Describe the solution you'd like** 15 | A clear and concise description of what you want to happen. 16 | 17 | **Describe alternatives you've considered** 18 | A clear and concise description of any alternative solutions or features you've considered. 19 | 20 | **Additional context** 21 | Add any other context or screenshots about the feature request here. 22 | -------------------------------------------------------------------------------- /.github/workflows/tests_multi_os.yml: -------------------------------------------------------------------------------- 1 | name: tests 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | test: 7 | 8 | runs-on: ${{ matrix.os }} 9 | strategy: 10 | fail-fast: false 11 | max-parallel: 6 12 | matrix: 13 | os: [ubuntu-latest, windows-latest, macOS-latest] 14 | python-version: 15 | - "3.12" 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Set up Python ${{ matrix.python-version }} 20 | uses: actions/setup-python@v5 21 | with: 22 | python-version: ${{ matrix.python-version }} 23 | cache: 'pip' 24 | 25 | # - uses: actions/cache@v3 26 | # if: startsWith(runner.os, 'Linux') 27 | # with: 28 | # path: ~/.cache/pip 29 | # key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} 30 | # restore-keys: | 31 | # ${{ runner.os }}-pip- 32 | 33 | # - uses: actions/cache@v3 34 | # if: startsWith(runner.os, 'macOS') 35 | # with: 36 | # path: ~/Library/Caches/pip 37 | # key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} 38 | # restore-keys: | 39 | # ${{ runner.os }}-pip- 40 | 41 | # - uses: actions/cache@v3 42 | # if: startsWith(runner.os, 'Windows') 43 | # with: 44 | # path: ~\AppData\Local\pip\Cache 45 | # key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} 46 | # restore-keys: | 47 | # ${{ runner.os }}-pip- 48 | 49 | - name: Install 50 | # if: steps.devcache.outs.cache-hit != 'true' 51 | run: | 52 | git submodule update --init --recursive 53 | pip install -r requirements.txt 54 | python -m pip install --upgrade pip 55 | pip install .[extras] 56 | 57 | - name: Install test requirements 58 | run: | 59 | pip install sphinx recommonmark pytest==8.1.1 pytest-cov==5.0.0 pyperclip 60 | 61 | - name: Test with pytest 62 | env: 63 | COVERAGE_CORE: sysmon 64 | run: | 65 | pytest -v --disable-pytest-warnings --cov-report=xml --cov=chepy --cov-config=.coveragerc tests/ 66 | coverage report -m 67 | 68 | - name: Test plugins osx 69 | if: matrix.os == 'macOS-latest' 70 | run: | 71 | sed -iE 's/enableplugins = false/enableplugins = true/' ~/.chepy/chepy.conf 72 | sed -iE '/chepy/d' chepy/chepy_plugins/requirements.txt 73 | pip install -r chepy/chepy_plugins/requirements.txt 74 | pip install . 75 | pytest -v --disable-pytest-warnings tests_plugins/ 76 | python -c "from chepy import Chepy" 77 | 78 | - name: Test plugins ubuntu 79 | if: contains(matrix.os, 'ubuntu') 80 | run: | 81 | sed -i 's/enableplugins = false/enableplugins = true/' ~/.chepy/chepy.conf 82 | sed -i '/chepy/d' chepy/chepy_plugins/requirements.txt 83 | pip install -r chepy/chepy_plugins/requirements.txt 84 | pip install . 85 | pytest --disable-pytest-warnings tests_plugins/ 86 | python -c "from chepy import Chepy" 87 | 88 | - name: Test plugins windows 89 | if: matrix.os == 'windows-latest' 90 | run: | 91 | Set-Content -Path ~/.chepy/chepy.conf -Value (Get-Content ~/.chepy/chepy.conf | %{$_ -replace "enableplugins = false","enableplugins = true"}) 92 | Set-Content -Path chepy/chepy_plugins/requirements.txt -Value (Get-Content -Path chepy/chepy_plugins/requirements.txt | Select-String -Pattern 'chepy' -NotMatch) 93 | pip install -r chepy/chepy_plugins/requirements.txt 94 | pytest --disable-pytest-warnings tests_plugins/ 95 | python -c "from chepy import Chepy" 96 | 97 | # - name: Test with bandit 98 | # run: | 99 | # bandit --recursive chepy/ --ignore-nosec --skip B101,B413,B303,B310,B112,B304,B320,B410,B404,B608,B311,B324 100 | 101 | # - name: Test docs 102 | # if: ${{ !env.ACT }} && contains(matrix.os, 'ubuntu') 103 | # run: | 104 | # make -C docs/ clean html 105 | 106 | publish: 107 | runs-on: ubuntu-latest 108 | needs: test 109 | if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') 110 | steps: 111 | - uses: actions/checkout@v4 112 | - name: setup 113 | uses: actions/setup-python@v5 114 | with: 115 | python-version: "3.10" 116 | - name: build 117 | run: | 118 | python setup.py sdist 119 | - name: publish 120 | uses: pypa/gh-action-pypi-publish@v1.4.2 121 | if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') 122 | with: 123 | user: __token__ 124 | password: ${{ secrets.PYPI_PASSWORD }} 125 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | pyvenv.cfg 3 | .envrc 4 | hexfile.bin 5 | share/ 6 | 7 | .bandit.json 8 | .scannerwork 9 | .DS_Store 10 | .vscode/ 11 | .test 12 | ignore/ 13 | node_modules/ 14 | 15 | # Byte-compiled / optimized / DLL files 16 | __pycache__/ 17 | *.py[cod] 18 | *$py.class 19 | 20 | # C extensions 21 | *.so 22 | 23 | # Distribution / packaging 24 | .Python 25 | build/ 26 | develop-eggs/ 27 | dist/ 28 | downloads/ 29 | eggs/ 30 | .eggs/ 31 | lib/ 32 | lib64/ 33 | parts/ 34 | sdist/ 35 | var/ 36 | wheels/ 37 | *.egg-info/ 38 | .installed.cfg 39 | *.egg 40 | MANIFEST 41 | 42 | # PyInstaller 43 | # Usually these files are written by a python script from a template 44 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 45 | *.manifest 46 | *.spec 47 | 48 | # Installer logs 49 | pip-log.txt 50 | pip-delete-this-directory.txt 51 | 52 | # Unit test / coverage reports 53 | htmlcov/ 54 | .tox/ 55 | .coverage 56 | .coverage.* 57 | .cache 58 | nosetests.xml 59 | coverage.xml 60 | *.cover 61 | .hypothesis/ 62 | .pytest_cache/ 63 | 64 | # Translations 65 | *.mo 66 | *.pot 67 | 68 | # Django stuff: 69 | *.log 70 | local_settings.py 71 | db.sqlite3 72 | 73 | # Flask stuff: 74 | instance/ 75 | .webassets-cache 76 | 77 | # Scrapy stuff: 78 | .scrapy 79 | 80 | # Sphinx documentation 81 | docs/_build/ 82 | 83 | # PyBuilder 84 | target/ 85 | 86 | # Jupyter Notebook 87 | .ipynb_checkpoints 88 | 89 | # pyenv 90 | .python-version 91 | 92 | # celery beat schedule file 93 | celerybeat-schedule 94 | 95 | # SageMath parsed files 96 | *.sage.py 97 | 98 | # Environments 99 | .env 100 | .venv 101 | env/ 102 | venv/ 103 | ENV/ 104 | env.bak/ 105 | venv.bak/ 106 | 107 | # Spyder project settings 108 | .spyderproject 109 | .spyproject 110 | 111 | # Rope project settings 112 | .ropeproject 113 | 114 | # mkdocs documentation 115 | /site 116 | 117 | # mypy 118 | .mypy_cache/ 119 | sonar-project.properties.local 120 | slim.report.json 121 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "chepy/chepy_plugins"] 2 | path = chepy/chepy_plugins 3 | url = https://github.com/securisec/chepy_plugins 4 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | build: 4 | os: ubuntu-22.04 5 | tools: 6 | python: "3.10" 7 | 8 | python: 9 | install: 10 | - method: pip 11 | path: . 12 | - requirements: docs/requirements.txt 13 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.8.0 2 | 3 | WORKDIR /chepy 4 | COPY requirements.txt /chepy 5 | RUN pip install -r /chepy/requirements.txt \ 6 | && pip install python-magic virtualenv \ 7 | && virtualenv -p python3 /chepy/venv \ 8 | && pip install pytest pytest-cov bandit \ 9 | && pip install scapy markdown pefile pyelftools pydriller requests 10 | 11 | COPY . /chepy/ 12 | RUN cd /chepy \ 13 | && sed -i '/chepy/d' chepy/chepy_plugins/requirements.txt \ 14 | && pip install -e . \ 15 | && venv/bin/pip3 install . \ 16 | && venv/bin/pip3 install -r chepy/chepy_plugins/requirements.txt \ 17 | && mkdir -p /chepy/venv/lib/python3.8/site-packages/chepy/chepy/chepy_plugins \ 18 | && cp -r /chepy/chepy/chepy_plugins/data/ /chepy/venv/lib/python3.8/site-packages/chepy/chepy_plugins/ \ 19 | && pip install -r /chepy/chepy/chepy_plugins/requirements.txt 20 | 21 | RUN cd /chepy/ && pytest --disable-pytest-warnings --cov-report=xml --cov=chepy --cov-config=.coveragerc tests/ 22 | RUN sed -i 's/enableplugins = false/enableplugins = true/' /root/.chepy/chepy.conf 23 | RUN cd /chepy/ && pytest --disable-pytest-warnings tests_plugins/ 24 | RUN python -c "from chepy import Chepy" 25 | 26 | RUN cd /chepy/ && bandit --recursive chepy/ --ignore-nosec --skip B101,B413,B303,B310,B112,B304,B320,B410,B404,B608 27 | RUN rm -rf /chepy/tests \ 28 | && rm -rf /chepy/build \ 29 | && rm -rf /chepy/dist \ 30 | && rm -rf /chepy/ignore \ 31 | && rm -rf /chepy/docs \ 32 | && rm -rf /chepy/plugins_test 33 | 34 | 35 | FROM python:3.8.0-slim 36 | COPY --from=0 /chepy /chepy 37 | RUN apt update \ 38 | && apt install exiftool libmagic-dev -y \ 39 | && apt-get clean \ 40 | && rm -rf /var/lib/apt/lists/* \ 41 | && /chepy/venv/bin/chepy -v \ 42 | && sed -i 's/enableplugins = false/enableplugins = true/' /root/.chepy/chepy.conf 43 | WORKDIR /data 44 | VOLUME ["/data"] 45 | 46 | ENTRYPOINT ["/chepy/venv/bin/chepy"] 47 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include requirements.txt 2 | include chepy/chepy_plugins/data/* -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: test test-all 2 | 3 | 4 | test: 5 | COVERAGE_CORE=sysmon python -m pytest --noconftest -v --disable-pytest-warnings --cov-report=xml --cov=chepy --cov-config=.coveragerc tests/ 6 | 7 | test-all: test 8 | COVERAGE_CORE=sysmon python -m pytest --noconftest -v --disable-pytest-warnings tests_plugins/ 9 | 10 | # git log --format=%B 4.0.0..5.0.0 | sed '/^\s*$/d' | sort | uniq -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | ![](https://github.com/securisec/chepy/workflows/tests/badge.svg) 6 | 7 | 8 | 9 | [![](https://img.shields.io/readthedocs/chepy.svg?logo=read-the-docs&label=Docs)](http://chepy.readthedocs.io/en/latest/) 10 | [![](https://img.shields.io/pypi/v/chepy.svg?logo=pypi&label=pypi)](https://pypi.python.org/pypi/chepy) 11 | 12 | [![](https://codecov.io/gh/securisec/chepy/branch/master/graph/badge.svg?token=q3pRktSVBu)](https://codecov.io/gh/securisec/chepy) 13 | 14 | [![](https://img.shields.io/badge/code%20style-black-000000.svg?label=Style)](https://github.com/securisec/chepy) 15 | ![](https://img.shields.io/github/license/securisec/chepy?label=License) 16 | 17 | [![](https://pepy.tech/badge/chepy)](https://pepy.tech/project/chepy) 18 | 19 | 20 | 21 | # Chepy 22 | 23 | 24 | ![Solving a CTF with Chepy](https://raw.githubusercontent.com/securisec/chepy/master/docs/assets/ctf.gif) 25 | 26 | Chepy is a python library with a handy cli that is aimed to mirror some of the capabilities of [CyberChef](https://gchq.github.io/CyberChef/). A reasonable amount of effort was put behind Chepy to make it compatible to the various functionalities that CyberChef offers, all in a pure Pythonic manner. There are some key advantages and disadvantages that Chepy has over Cyberchef. The Cyberchef concept of _stacking_ different modules is kept alive in Chepy. 27 | 28 | There is still a long way to go for Chepy as it does not offer every single ability of Cyberchef. 29 | 30 | ## Feel free to give the project a ⭐️! 31 | 32 | ## Docs 33 | [Refer to the docs for full usage information](http://chepy.readthedocs.io/en/latest/) 34 | 35 | ## Example 36 | [For all usage and examples, see the docs.](http://chepy.readthedocs.io/en/latest/) 37 | 38 | Chepy has a stacking mechanism similar to Cyberchef. For example, this in Cyberchef: 39 | 40 | 41 | 42 | This is equivalent to 43 | 44 | ```python 45 | from chepy import Chepy 46 | 47 | file_path = "/tmp/demo/encoding" 48 | 49 | print( 50 | Chepy(file_path) 51 | .load_file() 52 | .reverse() 53 | .rot_13() 54 | .from_base64() 55 | .from_base32() 56 | .hexdump_to_str() 57 | .o 58 | ) 59 | 60 | ``` 61 | 62 | ## Chepy vs Cyberchef 63 | 64 | #### Advantages 65 | - Chepy is pure python with a supporting and accessible python api 66 | - Chepy has a CLI 67 | - Chepy CLI has full autocompletion. 68 | - Supports pe, elf, and other various file format specific parsing. 69 | - Extendable via [plugins](https://chepy-plugins.readthedocs.io/en/latest/) 70 | - Infinitely scalable as it can leverage the full Python library. 71 | - Chepy can interface with the full Cyberchef web app to a certain degree. It is easy to move from Chepy to Cyberchef if need be. 72 | - The Chepy python library is significantly faster than the Cyberchef Node library. 73 | - Works with HTTP/S requests without CORS issues. 74 | - `magic` support via the Chepy ML plugin. 75 | 76 | #### Disadvantages 77 | - Chepy does not offer every single thing that Cyberchef does 78 | 79 | 80 | ## Installation 81 | Chepy can be installed in a few ways. 82 | 83 | ### Pypi 84 | ```bash 85 | pip3 install chepy 86 | # optionally with extra requirements 87 | pip3 install chepy[extras] 88 | ``` 89 | 90 | ### Git 91 | ```bash 92 | git clone --recursive https://github.com/securisec/chepy.git 93 | cd chepy 94 | pip3 install -e . 95 | # I use -e here so that if I update later with git pull, I dont have it install it again (unless dependencies have changed) 96 | ``` 97 | 98 | 102 | 103 | #### Standalone binary 104 | One can build Chepy to be a standalone binary also. This includes packaging all the dependencies together. 105 | ```bash 106 | git clone https://github.com/securisec/chepy.git 107 | cd chepy 108 | pip install . 109 | pip install pyinstaller 110 | pyinstaller cli.py --name chepy --onefile 111 | ``` 112 | The binary will be in the dist/ folder. 113 | 114 | ### Plugins 115 | [Check here for plugins docs](https://chepy-plugins.readthedocs.io/en/latest/) 116 | 117 | ### Used by 118 | [Remnux linux](https://docs.remnux.org/discover-the-tools/examine+static+properties/deobfuscation#chepy) 119 | 120 | ```eval_rst 121 | .. toctree:: 122 | :maxdepth: 3 123 | :caption: Contents: 124 | 125 | usage.md 126 | examples.md 127 | cli.rst 128 | chepy.md 129 | core.md 130 | modules.rst 131 | extras.rst 132 | plugins.md 133 | pullrequest.md 134 | config.md 135 | faq.md 136 | 137 | 138 | Indices and tables 139 | ================== 140 | 141 | * :ref:`genindex` 142 | * :ref:`modindex` 143 | * :ref:`search` 144 | ``` 145 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | Fix: 2 | 3 | Code: 4 | ☐ add more examples in docstrings 5 | ☐ Luhn validator https://guptaavi352.medium.com/ctflearn-writeups-9f247c2fe94c 6 | 7 | New ideas: 8 | ☐ rubber ducky encode/decode 9 | ☐ save registers https://t.co/pBNRufibY8?amp=1 10 | ☐ cbor encode/decode https://github.com/agronholm/cbor2 (plugin) 11 | ☐ fuzzy search 12 | ☐ 🚧 pgp, generate, encrypt, decrypt, verify 13 | ☐ swap little and big endian 14 | ☐ ignore error method 15 | ☐ swap bytes 16 | ☐ homophonic decoder 17 | ☐ append method for core to add data to the state 18 | ☐ qr create 19 | ☐ random from state 20 | ☐ ascii shift cipher kqfl ? snyjHYK"8fwymdxf~xdm8qq5$ = niteCTF{3arth_says_h3ll0} somewhat 21 | ☐ ✨ affine bruteforce 22 | ☐ ✨ zero-width encode 23 | ☐ ✨ hill cipher encode/decode/brute 24 | ☐ 💡 maybe a decorator function to convert all inputs into bytes when possible? this will allow for a consistant bytes approach to all functions 25 | ☐ ✨ amf encode/decode 26 | ☐ ✨ aes cmac 27 | ☐ ✨ whitespace encoding https://www.dcode.fr/whitespace-language 28 | ☐ beaufort 29 | ☐ 🔥 update python_requires in setup.py on python version change 30 | ☐ update base85 https://github.com/gorakhargosh/mom/blob/master/mom/codec/base85.py#L343 31 | 32 | Bug: 33 | 34 | Extras: 35 | ☐ xor two files 36 | 37 | Cli: 38 | ☐ optionally show output window in a split screen window 39 | ☐ lower the chepy prompt lower. that empty space is not being used 40 | ☐ write to file with prompt toolkit path autocomplete 41 | ☐ pipe input to chepy 42 | 43 | Enhance: 44 | 45 | Plugins: 46 | 47 | Misc: 48 | ☐ cyberchef recipe to chepy recipe converter 49 | 50 | Archive: 51 | ✔ @high disable plugins from code 52 | ✔ 🐙 update config to use envars for plugins 53 | ✔ register support in callstack 54 | ✔ ecb no padding in aes/des 55 | ✔ update ml model with different spacing for hex, binary etc 56 | -------------------------------------------------------------------------------- /all_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function check_test { 4 | "$@" 5 | local status=$? 6 | if [ $status -ne 0 ]; then 7 | echo -e "\n\033[31;7m$1 Failed" >&2 8 | exit 9 | fi 10 | return $status 11 | } 12 | 13 | # pytest and coverage 14 | check_test pytest --disable-pytest-warnings --cov=chepy --cov-config=.coveragerc tests/ 15 | 16 | # pytest plugins 17 | check_test pytest --disable-pytest-warnings tests_plugins/ 18 | 19 | # bandit 20 | check_test bandit --recursive chepy/ --ignore-nosec --skip B101,B413,B303,B310,B112,B304,B320,B410,B404 21 | 22 | # docs 23 | check_test make -C docs/ clean html 24 | 25 | # plugin docs 26 | check_test make -C ~/dev/chepy_plugins/docs clean html 27 | 28 | # build docker 29 | # check_test docker build -t chepy . 30 | -------------------------------------------------------------------------------- /chepy/__init__.py: -------------------------------------------------------------------------------- 1 | import pretty_errors 2 | from docstring_parser import parse as _doc_parse 3 | from types import FunctionType 4 | 5 | from .modules.aritmeticlogic import AritmeticLogic 6 | from .modules.codetidy import CodeTidy 7 | from .modules.compression import Compression 8 | from .modules.dataformat import DataFormat 9 | from .modules.datetimemodule import DateTime 10 | from .modules.encryptionencoding import EncryptionEncoding 11 | from .modules.extractors import Extractors 12 | from .modules.hashing import Hashing 13 | from .modules.language import Language 14 | from .modules.links import Links 15 | from .modules.networking import Networking 16 | from .modules.other import Other 17 | from .modules.publickey import Publickey 18 | from .modules.search import Search 19 | from .modules.utils import Utils 20 | from .modules.internal.colors import cyan 21 | 22 | from .config import ChepyConfig 23 | 24 | _plugins = ChepyConfig().load_plugins() 25 | 26 | 27 | class Chepy( 28 | AritmeticLogic, 29 | CodeTidy, 30 | Compression, 31 | DataFormat, 32 | DateTime, 33 | EncryptionEncoding, 34 | Extractors, 35 | Hashing, 36 | Language, 37 | Links, 38 | Networking, 39 | Other, 40 | Publickey, 41 | Search, 42 | Utils, 43 | *_plugins 44 | ): 45 | """Chepy class that exposes all functionality of Chepy and its plugins.""" 46 | 47 | pass 48 | 49 | 50 | def show_plugins(): # pragma: no cover 51 | hold = {} 52 | for p in _plugins: 53 | hold[p.__name__] = [ 54 | name 55 | for name, attr in vars(p).items() 56 | if isinstance(attr, FunctionType) and not name.startswith("_") 57 | ] 58 | return hold 59 | 60 | 61 | def search_chepy_methods(search: str) -> None: # pragma: no cover 62 | """Search for Chepy methods 63 | 64 | Args: 65 | search (str): String to search for 66 | """ 67 | methods = dir(Chepy) 68 | for method in methods: 69 | if search in method and not method.startswith("_"): 70 | docs = _doc_parse(getattr(Chepy, method).__doc__).short_description 71 | print(cyan(method), docs) 72 | -------------------------------------------------------------------------------- /chepy/__init__.pyi: -------------------------------------------------------------------------------- 1 | from typing import Dict, List 2 | 3 | from .modules.aritmeticlogic import AritmeticLogic 4 | from .modules.codetidy import CodeTidy 5 | from .modules.compression import Compression 6 | from .modules.dataformat import DataFormat 7 | from .modules.datetimemodule import DateTime 8 | from .modules.encryptionencoding import EncryptionEncoding 9 | from .modules.extractors import Extractors 10 | from .modules.hashing import Hashing 11 | from .modules.language import Language 12 | from .modules.links import Links 13 | from .modules.multimedia import Multimedia 14 | from .modules.networking import Networking 15 | from .modules.other import Other 16 | from .modules.publickey import Publickey 17 | from .modules.search import Search 18 | from .modules.utils import Utils 19 | 20 | class Chepy( 21 | AritmeticLogic, 22 | CodeTidy, 23 | Compression, 24 | DataFormat, 25 | DateTime, 26 | EncryptionEncoding, 27 | Extractors, 28 | Hashing, 29 | Language, 30 | Links, 31 | Multimedia, 32 | Networking, 33 | Other, 34 | Publickey, 35 | Search, 36 | Utils, 37 | ): ... 38 | 39 | def search_chepy_methods(search: str) -> None: ... 40 | def show_plugins() -> Dict[str, List[str]]: ... 41 | -------------------------------------------------------------------------------- /chepy/__version__.py: -------------------------------------------------------------------------------- 1 | __version__ = "7.4.0" # pragma: no cover 2 | __author__ = "@securisec" # pragma: no cover 3 | -------------------------------------------------------------------------------- /chepy/__version__.pyi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/chepy/__version__.pyi -------------------------------------------------------------------------------- /chepy/config.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | import logging 4 | import importlib 5 | import inspect 6 | import pkgutil 7 | import json 8 | from pathlib import Path 9 | from configparser import ConfigParser 10 | 11 | 12 | class ChepyConfig(object): 13 | def __init__(self): 14 | home = Path.home() 15 | self.chepy_dir = ( 16 | Path(".chepy").resolve() 17 | if Path(".chepy").exists() 18 | else Path(home / ".chepy") 19 | ) 20 | self.chepy_conf = Path(self.chepy_dir / "chepy.conf") 21 | 22 | if not self.chepy_conf.exists(): # pragma: no cover 23 | self.chepy_dir.mkdir(exist_ok=True) 24 | c = ConfigParser() 25 | 26 | c["Plugins"] = { 27 | "EnablePlugins": "false", 28 | "PluginPath": str(Path(__file__).parent / "chepy_plugins"), 29 | } 30 | c["Cli"] = {} 31 | cli_options = c["Cli"] 32 | cli_options["history_path"] = str(self.chepy_dir / "chepy_history") 33 | cli_options["prompt_char"] = ">" 34 | cli_options["prompt_colors"] = "#00ffff #ff0000 #ffd700" 35 | cli_options["show_rprompt"] = "false" 36 | cli_options["prompt_rprompt"] = "#00ff48" 37 | cli_options["prompt_bottom_toolbar"] = "#000000" 38 | cli_options["prompt_toolbar_version"] = "#00ff48" 39 | cli_options["prompt_toolbar_states"] = "#60cdd5" 40 | cli_options["prompt_toolbar_buffers"] = "#ff00ff" 41 | cli_options["prompt_toolbar_type"] = "#ffd700" 42 | cli_options["prompt_toolbar_plugins"] = "#ffccbc" 43 | cli_options["prompt_toolbar_errors"] = "#ff0000" 44 | cli_options["prompt_cli_method"] = "#ffd700" 45 | cli_options["prompt_plugin_method"] = "#30d8ff" 46 | cli_options["cli_info_color"] = "#c2c2ff" 47 | cli_options["prompt_search_background"] = "#00aaaa #000000" 48 | cli_options["prompt_search_fuzzy"] = "#00aaaa" 49 | 50 | Path(str(self.chepy_dir / "chepy_history")).touch() 51 | if not self.chepy_conf.exists(): 52 | with open(str(self.chepy_conf), "w") as f: 53 | c.write(f) 54 | 55 | self.config = ConfigParser() 56 | self.config.read(str(self.chepy_conf)) 57 | 58 | plugin_path = self.__get_conf_value("None", "PluginPath", "Plugins") 59 | self.enable_plugins = json.loads( 60 | self.__get_conf_value("false", "EnablePlugins", "Plugins") 61 | ) 62 | 63 | plugin_envar = os.environ.get("CHEPY_PLUGINS", "") 64 | if plugin_envar == "true": 65 | self.enable_plugins = True 66 | elif plugin_envar != "": 67 | self.enable_plugins = False 68 | 69 | if self.enable_plugins: 70 | if plugin_path != "None": 71 | self.plugin_path = Path(plugin_path).expanduser().resolve() 72 | else: 73 | self.plugin_path = Path(plugin_path) 74 | else: 75 | self.plugin_path = Path("None") 76 | 77 | self.history_path = self.__get_conf_value( 78 | str(self.chepy_dir / "chepy_history"), "history_path" 79 | ) 80 | self.prompt_char = self.__get_conf_value(">", "prompt_char") 81 | self.prompt_colors = self.__get_conf_value( 82 | "#00ffff #ff0000 #ffd700", "prompt_colors" 83 | ) 84 | self.show_rprompt = json.loads(self.__get_conf_value("false", "show_rprompt")) 85 | self.prompt_rprompt = self.__get_conf_value("#00ff48", "prompt_rprompt") 86 | self.prompt_bottom_toolbar = self.__get_conf_value( 87 | "#000000", "prompt_bottom_toolbar" 88 | ) 89 | self.prompt_toolbar_version = self.__get_conf_value( 90 | "#00ff48", "prompt_toolbar_version" 91 | ) 92 | self.prompt_toolbar_states = self.__get_conf_value( 93 | "#60cdd5", "prompt_toolbar_states" 94 | ) 95 | self.prompt_toolbar_buffers = self.__get_conf_value( 96 | "#ff00ff", "prompt_toolbar_buffers" 97 | ) 98 | self.prompt_toolbar_type = self.__get_conf_value( 99 | "#ffd700", "prompt_toolbar_type" 100 | ) 101 | self.prompt_toolbar_plugins = self.__get_conf_value( 102 | "#ffccbc", "prompt_toolbar_plugins" 103 | ) 104 | self.prompt_toolbar_errors = self.__get_conf_value( 105 | "#ff0000", "prompt_toolbar_errors" 106 | ) 107 | self.prompt_search_background = self.__get_conf_value( 108 | "#00aaaa #000000", "prompt_search_background" 109 | ) 110 | self.prompt_search_fuzzy = self.__get_conf_value( 111 | "#00aaaa", "prompt_search_fuzzy" 112 | ) 113 | self.prompt_cli_method = self.__get_conf_value("#ffd700", "prompt_cli_method") 114 | self.prompt_plugin_method = self.__get_conf_value( 115 | "#30d8ff", "prompt_plugin_method" 116 | ) 117 | self.cli_info_color = self.__get_conf_value("#c2c2ff", "cli_info_color") 118 | 119 | def __get_conf_value(self, default: str, option: str, section: str = "Cli"): 120 | if self.config.has_section(section): 121 | if self.config.has_option(section, option): 122 | return self.config[section][option] 123 | else: 124 | return default 125 | else: 126 | return default 127 | 128 | def load_plugins(self): # pragma: no cover 129 | plugins = [] 130 | if self.plugin_path.stem != "None": 131 | sys.path.append(str(self.plugin_path)) 132 | 133 | my_plugins = [ 134 | importlib.import_module(name) 135 | for finder, name, ispkg in pkgutil.iter_modules() 136 | if (name.startswith("chepy_") and name != "chepy_plugins") 137 | ] 138 | 139 | for plugin in my_plugins: 140 | try: 141 | klass, mod = inspect.getmembers(plugin, inspect.isclass)[0] 142 | loaded = getattr(plugin, klass) 143 | plugins.append(loaded) 144 | except: 145 | logging.warning(f"Error loading {plugin.__name__}") 146 | return plugins 147 | -------------------------------------------------------------------------------- /chepy/config.pyi: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | 3 | class ChepyConfig: 4 | chepy_dir: Any = ... 5 | chepy_conf: Any = ... 6 | config: Any = ... 7 | enable_plugins: Any = ... 8 | plugin_path: Any = ... 9 | history_path: Any = ... 10 | prompt_char: Any = ... 11 | prompt_colors: Any = ... 12 | show_rprompt: Any = ... 13 | prompt_rprompt: Any = ... 14 | prompt_bottom_toolbar: Any = ... 15 | prompt_toolbar_version: Any = ... 16 | prompt_toolbar_states: Any = ... 17 | prompt_toolbar_buffers: Any = ... 18 | prompt_toolbar_type: Any = ... 19 | prompt_toolbar_plugins: Any = ... 20 | prompt_toolbar_errors: Any = ... 21 | prompt_cli_method: Any = ... 22 | prompt_plugin_method: Any = ... 23 | cli_info_color: Any = ... 24 | def __init__(self) -> None: ... 25 | def load_plugins(self): ... 26 | -------------------------------------------------------------------------------- /chepy/core.pyi: -------------------------------------------------------------------------------- 1 | import logging 2 | from typing import Any, List, Mapping, Tuple, Union, TypeVar, Literal, Callable, Dict 3 | 4 | jsonpickle: Any 5 | 6 | ChepyCoreT = TypeVar('ChepyCoreT', bound='ChepyCore') 7 | 8 | class ChepyDecorators: 9 | @staticmethod 10 | def call_stack(func: Any, *args: Any, **kwargs: Any): ... 11 | @staticmethod 12 | def is_stdout(func: Any, *args: Any, **kwargs: Any): ... 13 | 14 | class ChepyCore: 15 | states: Any = ... 16 | buffers: Any = ... 17 | write: Any = ... 18 | bake: Any = ... 19 | cyberchef: Any = ... 20 | read_file: Any = ... 21 | log_level: Any = ... 22 | log_format: str = ... 23 | _registers: Dict[str, Union[str, bytes]] = ... 24 | _log: logging.Logger = ... 25 | def __init__(self, *data: Any) -> None: ... 26 | def _convert_to_bytes(self) -> bytes: ... 27 | def _to_bytes(self, data: Any) -> bytes: ... 28 | def _convert_to_bytearray(self) -> bytearray: ... 29 | def _convert_to_str(self) -> str: ... 30 | def _convert_to_int(self) -> int: ... 31 | def _str_to_bytes(self, s: str) -> bytes: ... 32 | def _get_nested_value(self: ChepyCoreT, data: dict, key:str, split_by: str=".") -> Any: ... 33 | def _bytes_to_str(self, s: bytes) -> str: ... 34 | @property 35 | def state(self): ... 36 | @state.setter 37 | def state(self: ChepyCoreT, val: Any) -> None: ... 38 | def fork(self: ChepyCoreT, methods: List[Union[Tuple[Union[str, Callable], dict], Tuple[Union[str, Callable[None, ChepyCoreT]],]]]) -> ChepyCoreT: ... 39 | def for_each(self: ChepyCoreT, methods: List[Union[Tuple[Union[str, Callable], Dict[str, Any]], Tuple[Union[str, Callable[None, ChepyCoreT]],]]], merge: Union[str, bytes, None]=None) -> ChepyCoreT: ... 40 | def set_state(self: ChepyCoreT, data: Any) -> ChepyCoreT: ... 41 | def create_state(self: ChepyCoreT): ... 42 | def copy_state(self: ChepyCoreT, index: int=...) -> ChepyCoreT: ... 43 | def change_state(self: ChepyCoreT, index: int) -> ChepyCoreT: ... 44 | def switch_state(self: ChepyCoreT, index: int) -> ChepyCoreT: ... 45 | def delete_state(self: ChepyCoreT, index: int) -> ChepyCoreT: ... 46 | def get_state(self: ChepyCoreT, index: int) -> ChepyCoreT: ... 47 | def save_buffer(self: ChepyCoreT, index: int=...) -> ChepyCoreT: ... 48 | def load_buffer(self: ChepyCoreT, index: int) -> ChepyCoreT: ... 49 | def delete_buffer(self: ChepyCoreT, index: int) -> ChepyCoreT: ... 50 | def substring(self: ChepyCoreT, pattern: str, group: int=...) -> ChepyCoreT: ... 51 | @property 52 | def o(self): ... 53 | @property 54 | def out(self: ChepyCoreT) -> ChepyCoreT: ... 55 | def out_as_any(self: ChepyCoreT) -> str: ... 56 | def get_by_index(self: ChepyCoreT, *indexes: int) -> ChepyCoreT: ... 57 | def get_by_key(self: ChepyCoreT, *keys: Union[str, bytes], py_style: bool=False, split_key: Union[str, None] = '.') -> ChepyCoreT: ... 58 | def copy_to_clipboard(self: ChepyCoreT) -> None: ... 59 | def copy(self: ChepyCoreT) -> None: ... 60 | def web(self: ChepyCoreT, magic: bool=..., cyberchef_url: str=...) -> None: ... 61 | def http_request(self: ChepyCoreT, method: str=..., params: dict=..., json: dict=..., headers: dict=..., cookies: dict=...) -> ChepyCoreT: ... 62 | def load_from_url(self: ChepyCoreT, method: str=..., params: dict=..., json: dict=..., headers: dict=..., cookies: dict=...) -> ChepyCoreT: ... 63 | def load_dir(self: ChepyCoreT, pattern: str=...) -> ChepyCoreT: ... 64 | def load_file(self: ChepyCoreT, binary_mode: bool=..., encoding: Union[str, None]=...) -> ChepyCoreT: ... 65 | def write_to_file(self: ChepyCoreT, path: str) -> None: ... 66 | def write_binary(self: ChepyCoreT, path: str) -> None: ... 67 | @property 68 | def recipe(self) -> List[Dict[str, Union[str, Dict[str, Any]]]]: ... 69 | def run_recipe(self: ChepyCoreT, recipes: List[Mapping[str, Union[str, Mapping[str, Any]]]]) -> ChepyCoreT: ... 70 | def save_recipe(self: ChepyCoreT, path: str) -> ChepyCoreT: ... 71 | def load_recipe(self: ChepyCoreT, path: str) -> ChepyCoreT: ... 72 | def run_script(self: ChepyCoreT, path: str, save_state: bool=...) -> ChepyCoreT: ... 73 | def loop(self: ChepyCoreT, iterations: int, callback: Union[str, Callable], args: dict=...) -> ChepyCoreT: ... 74 | def loop_list(self: ChepyCoreT, callback: Union[str, Callable], args: dict=...) -> ChepyCoreT: ... 75 | def loop_dict(self: ChepyCoreT, keys: list, callback: Union[str, Callable], args: dict=...) -> ChepyCoreT: ... 76 | def debug(self: ChepyCoreT, verbose: bool=...) -> ChepyCoreT: ... 77 | def reset(self: ChepyCoreT) -> ChepyCoreT: ... 78 | def print(self: ChepyCoreT) -> ChepyCoreT: ... 79 | def load_command(self: ChepyCoreT) -> ChepyCoreT: ... 80 | def pretty(self: ChepyCoreT, indent: int=...) -> ChepyCoreT: ... 81 | def plugins(self: ChepyCoreT, enable: Literal['true', 'false']) -> None: ... 82 | def set_plugin_path(self: ChepyCoreT, path: str) -> None: ... 83 | def subsection(self: ChepyCoreT, pattern: str, methods: List[Tuple[Union[str, object], dict]], group: int=...) -> ChepyCoreT: ... 84 | def callback(self: ChepyCoreT, callback_function: Callable[[Any], Any]) -> ChepyCoreT: ... 85 | def register(self: ChepyCoreT, pattern: Union[str, bytes], ignore_case: bool=False, multiline: bool=False, dotall: bool=False, unicode: bool=False, extended: bool=False) -> ChepyCoreT: ... 86 | def prefix(self: ChepyCoreT, data: Union[str, bytes]) -> ChepyCoreT: ... 87 | def suffix(self: ChepyCoreT, data: Union[str, bytes]) -> ChepyCoreT: ... 88 | def get_register(self: ChepyCoreT, key: str) -> Union[str, bytes]: ... 89 | def set_register(self: ChepyCoreT, key: str, val: Union[str, bytes]) -> ChepyCoreT: ... 90 | def dump_json(self: ChepyCoreT) -> ChepyCoreT: ... 91 | def walk_dir(self: ChepyCoreT) -> ChepyCoreT: ... 92 | def search_dir(self: ChepyCoreT, pattern: Union[str, bytes]) -> ChepyCoreT: ... 93 | -------------------------------------------------------------------------------- /chepy/extras/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/chepy/extras/__init__.py -------------------------------------------------------------------------------- /chepy/extras/__init__.pyi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/chepy/extras/__init__.pyi -------------------------------------------------------------------------------- /chepy/extras/bruteforce.py: -------------------------------------------------------------------------------- 1 | import zipfile 2 | from pathlib import Path 3 | 4 | 5 | def _expand_path(path): 6 | return str(Path(path).expanduser().absolute()) 7 | 8 | 9 | def zip_password_bruteforce(path: str, wordlist: str) -> str: 10 | z = zipfile.ZipFile(_expand_path(path)) 11 | with open(_expand_path(wordlist)) as f: 12 | for password in f: 13 | password = password.strip().encode() 14 | try: 15 | z.setpassword(password) 16 | z.testzip() 17 | return password 18 | except RuntimeError: # pragma: no cover 19 | continue 20 | -------------------------------------------------------------------------------- /chepy/extras/bruteforce.pyi: -------------------------------------------------------------------------------- 1 | def zip_password_bruteforce(path: str, wordlist: str) -> str: ... 2 | -------------------------------------------------------------------------------- /chepy/extras/characters.py: -------------------------------------------------------------------------------- 1 | from string import ascii_lowercase, ascii_uppercase, digits 2 | 3 | 4 | def base64_char_sets() -> dict: 5 | """Get various combinations of base64 character sets 6 | 7 | Returns: 8 | dict: Dict of various char sets 9 | """ 10 | return { 11 | "standard": ascii_uppercase + ascii_lowercase + digits + "+/=", # A-Za-z0-9+/= 12 | "url_safe": ascii_uppercase + ascii_lowercase + digits + "-_", # A-Za-z0-9-_ 13 | "filename_safe": ascii_uppercase 14 | + ascii_lowercase 15 | + digits 16 | + "+\\-=", # A-Za-z0-9+\-= 17 | "itoa64": "./" 18 | + digits 19 | + ascii_uppercase 20 | + ascii_lowercase 21 | + "=", # ./0-9A-Za-z= 22 | "xml": ascii_uppercase + ascii_lowercase + digits + "_.", # A-Za-z0-9_. 23 | "y64": ascii_uppercase + ascii_lowercase + digits + "._-", # A-Za-z0-9._- 24 | "z64": digits + ascii_lowercase + ascii_uppercase + "+/=", # 0-9a-zA-Z+/= 25 | "radix64": digits + ascii_uppercase + ascii_lowercase + "+/=", # 0-9A-Za-z+/= 26 | "uuencoding": " -_", 27 | "xxencoding": "+\\-" 28 | + digits 29 | + ascii_uppercase 30 | + ascii_lowercase, # +\-0-9A-Za-z 31 | "unix_crypt": "./" + digits + ascii_uppercase + ascii_lowercase, # ./0-9A-Za-z 32 | } 33 | -------------------------------------------------------------------------------- /chepy/extras/characters.pyi: -------------------------------------------------------------------------------- 1 | def base64_char_sets() -> dict: ... 2 | -------------------------------------------------------------------------------- /chepy/extras/combinatons.py: -------------------------------------------------------------------------------- 1 | import itertools 2 | from typing import List, Any, Iterator 3 | 4 | 5 | def generate_combo( 6 | words: List[Any], min_length: int = 0, max_length: int = None, join_by: str = None 7 | ) -> Iterator[tuple]: 8 | """Creates all possible combinations from the `words` being passed. 9 | Returns a generator. `length` controls the length of the permutations. 10 | 11 | Args: 12 | words (List[Any]): List of strings. 13 | min_length (int, optional): Minimum length of permutations. By default, 0 which 14 | will generate all 15 | max_length (int, optional): Maximum length of permutations. 16 | By default, it is the length of the `words` list 17 | 18 | Returns: 19 | Iterator[tuple]: A generator containing tuples of combinations 20 | """ 21 | if min_length > 0 and max_length is not None: 22 | for L in range(min_length, max_length + 1): 23 | for subset in itertools.permutations(words, L): 24 | yield join_by.join(subset) if join_by is not None else subset 25 | elif max_length is None: 26 | for L in range(min_length, len(words) + 1): 27 | for subset in itertools.permutations(words, L): 28 | yield join_by.join(subset) if join_by is not None else subset 29 | else: 30 | for subset in itertools.permutations(words, max_length): 31 | yield join_by.join(subset) if join_by is not None else subset 32 | 33 | 34 | def hex_chars() -> list: 35 | """Returns an array of all the hex characters 36 | 37 | Returns: 38 | list: List of all hex characters 39 | """ 40 | return list("{:02x}".format(x) for x in range(0, 256)) 41 | 42 | -------------------------------------------------------------------------------- /chepy/extras/combinatons.pyi: -------------------------------------------------------------------------------- 1 | from typing import Any, Iterator, List 2 | 3 | def generate_combo(words: List[Any], min_length: int=..., max_length: int=..., join_by: str=...) -> Iterator[tuple]: ... 4 | def hex_chars() -> list: ... 5 | -------------------------------------------------------------------------------- /chepy/extras/crypto.py: -------------------------------------------------------------------------------- 1 | import json 2 | import lazy_import 3 | from typing import Iterator, Dict, List, Union 4 | from binascii import hexlify, unhexlify 5 | from itertools import cycle 6 | from urllib.request import urlopen 7 | RSA = lazy_import.lazy_module("Crypto.PublicKey.RSA") 8 | 9 | from .combinatons import generate_combo, hex_chars 10 | from chepy import Chepy 11 | 12 | 13 | def factordb(n: int) -> dict: # pragma: no cover 14 | """Query the factordb api and get primes if available 15 | 16 | Args: 17 | n (int): n is the modulus for the public key and the private keys 18 | 19 | Returns: 20 | dict: response from api as a dictionary. None if status code is not 200 21 | """ 22 | res = urlopen("http://factordb.com/api/?query={}".format(str(n))) 23 | if res.status != 200: 24 | return None 25 | return json.loads(res.read().decode()) 26 | 27 | 28 | def construct_private_key( 29 | n: int, e: int, d: int, format: str = "PEM", passphrase: str = None 30 | ) -> str: # pragma: no cover 31 | """Construct a private key given n, e and d 32 | 33 | Args: 34 | n (int): n 35 | e (int): e 36 | d (int): d 37 | format (str, optional): Supports PEM, DER and OpenSSH. Defaults to "PEM". 38 | passphrase (str, optional): [description]. Defaults to None. 39 | 40 | Returns: 41 | str: Private key 42 | """ 43 | valid_formats = ["PEM", "DER", "OpenSSH"] 44 | assert format in valid_formats, "Valid formats are {}".format( 45 | " ".join(valid_formats) 46 | ) 47 | priv = RSA.construct((n, e, d)) 48 | return priv.export_key(format=format, passphrase=passphrase) 49 | 50 | 51 | def xor_bruteforce_multi( 52 | data: str, min: int = 0, max: int = None, errors: str = "backslashreplace" 53 | ) -> Iterator[Dict[str, str]]: 54 | """Bruteforce multibyte xor encryption. For faster results, use pypy3. 55 | It is important to set the min and max values if the key size is known. 56 | 57 | Args: 58 | data (str): XORed data 59 | min (int, optional): Minimum key length. Default will start at 1 byte 60 | . Defaults to 0. 61 | max (int, optional): Maximum key length. Maximum value is 257 bytes. Defaults to None. 62 | errors (str, optional): How should the errors be handled? Defaults to backslashreplace. 63 | Valid options are replace, ignore, backslashreplace 64 | 65 | Returns: 66 | Iterator[Dict[str, str]]: A dictionary where key is key, and value is xored data 67 | 68 | Yields: 69 | Iterator[Dict[str, str]]: A generator which contains a dictionary with the 70 | keys: `key` and `out` 71 | """ 72 | for key in generate_combo( 73 | hex_chars(), min_length=min, max_length=max, join_by="" 74 | ): # pragma: no cover 75 | yield { 76 | "key": key, 77 | "out": Chepy(data).xor(key).bytearray_to_str(errors=errors).o, 78 | } 79 | 80 | 81 | def xor_repeating_key( 82 | data1: bytes, data2: bytes, min: int = 1, max: int = 257 83 | ) -> Union[bytes, None]: # pragma: no cover 84 | """Recover repeating key xor keys. 85 | 86 | Args: 87 | data1 (bytes): File 1 path 88 | data2 (bytes): File 2 path 89 | min (int, optional): Min chars to test. Defaults to 1. 90 | max (int, optional): Max chars to test. Defaults to 257. 91 | 92 | Returns: 93 | Union[bytes, None]: Key as hex bytes or None if no key found 94 | """ 95 | 96 | def find_same(s: bytes): 97 | i = (s + s).find(s, 1, -1) 98 | return None if i == -1 else s[:i] 99 | 100 | for i in range(min, max): 101 | d1 = data1[:i] 102 | 103 | d2 = data2[:i] 104 | 105 | x = bytes(a ^ b for a, b in zip(d1, d2)) 106 | o = find_same(x) 107 | if o is not None: 108 | return o 109 | 110 | 111 | def xor(data: bytes, key: bytes) -> bytes: # pragma: no cover 112 | """XOR data with a hex key 113 | 114 | Args: 115 | data (bytes): Data to be xored 116 | key (bytes): Hex key to xor data with 117 | 118 | Returns: 119 | bytes: XORed data 120 | 121 | Example: 122 | >>> xor(b"hello", unhexlify(b"aabbccdd")) 123 | b'c2dea0b1c5' 124 | """ 125 | return hexlify(bytes(a ^ b for a, b in zip(data, cycle(key)))) 126 | 127 | 128 | def one_time_pad_crib( 129 | cipherText1: Union[bytes, str], cipherText2: Union[bytes, str], crib: bytes 130 | ) -> List[str]: 131 | """One time pad crib attack. 132 | 133 | Args: 134 | cipherText1 (Union[bytes, str]): Cipher text 1 as hex 135 | cipherText2 (Union[bytes, str]): Cipher text 2 as hex 136 | crib (bytes): Crib (known text) as bytes 137 | 138 | Returns: 139 | List[str]: List of possible plaintexts 140 | """ 141 | cipherText1 = unhexlify(cipherText1) 142 | cipherText2 = unhexlify(cipherText2) 143 | xored = bytearray(a ^ b for a, b in zip(cipherText1, cipherText2)) 144 | hold = [] 145 | for offset in range(0, len(xored) - len(crib) + 1): 146 | piece = xored[offset : offset + len(crib)] 147 | piece = bytearray(a ^ b for a, b in zip(crib, piece)) 148 | if all(32 <= c <= 126 for c in piece): 149 | piece = ( 150 | ("." * offset) 151 | + piece.decode() 152 | + ("." * (len(xored) - len(crib) - offset)) 153 | ) 154 | hold.append(piece) 155 | return hold 156 | 157 | 158 | def generate_rsa_keypair( 159 | bits: int = 1024, passphrase: str = None 160 | ) -> Dict[str, dict]: # pragma: no cover 161 | """Generates an RSA keypair with the specified number of bits. 162 | 163 | Args: 164 | bits: The number of bits for the RSA keypair. 165 | 166 | Returns: 167 | A tuple of the RSA public key and RSA private key, both in PEM format. 168 | """ 169 | 170 | keypair = RSA.generate(bits) 171 | return { 172 | "pem": { 173 | "public": keypair.publickey().exportKey("PEM"), 174 | "private": keypair.exportKey("PEM", passphrase=passphrase), 175 | }, 176 | "der": { 177 | "public": keypair.publickey().exportKey("DER"), 178 | "private": keypair.exportKey("DER", passphrase=passphrase), 179 | }, 180 | } 181 | -------------------------------------------------------------------------------- /chepy/extras/crypto.pyi: -------------------------------------------------------------------------------- 1 | from typing import Dict, Iterator, Union, Any 2 | 3 | def factordb(n: int) -> dict: ... 4 | def construct_private_key(n: int, e: int, d: int, format: str=..., passphrase: str=...) -> str: ... 5 | def xor_bruteforce_multi(data: str, min: int=..., max: int=..., errors: str=...) -> Iterator[Dict[str, str]]: ... 6 | def xor_repeating_key(data1:bytes, data2: bytes, min: int =..., max: int = ...) -> Union[bytes, None]: ... 7 | def generate_rsa_keypair(bits: int=..., passphrase: str=...) -> Dict[str, Dict[str, Any]] : ... -------------------------------------------------------------------------------- /chepy/extras/misc.py: -------------------------------------------------------------------------------- 1 | import collections 2 | import math 3 | from typing import Any 4 | 5 | 6 | def shannon_entropy(data: Any, unit="shannon") -> float: 7 | """Calculate the Shannon entropy of any data type. Units 8 | could be `natural`, `shannon` or `hartley` 9 | 10 | - 0 represents no randomness (i.e. all the bytes in the data have the same value) 11 | whereas 8, the maximum, represents a completely random string. 12 | - Standard English text usually falls somewhere between 3.5 and 5. 13 | - Properly encrypted or compressed data of a reasonable length should have an entropy of over 7.5. 14 | 15 | Args: 16 | data (Any): Any data type 17 | unit (str, optional): Unit type. Defaults to "shannon". 18 | 19 | Returns: 20 | float: Calculated entropy 21 | """ 22 | base = {"shannon": 2.0, "natural": math.exp(1), "hartley": 10.0} 23 | 24 | if len(data) <= 1: # pragma: no cover 25 | return 0 26 | 27 | counts = collections.Counter() 28 | 29 | for d in data: 30 | counts[d] += 1 31 | 32 | ent = 0 33 | 34 | probs = [float(c) / len(data) for c in counts.values()] 35 | for p in probs: 36 | if p > 0.0: 37 | ent -= p * math.log(p, base[unit]) 38 | 39 | return ent 40 | 41 | 42 | def index_of_coincidence(data: Any) -> float: 43 | """Index of Coincidence (IC) is the probability of two randomly 44 | selected characters being the same. 45 | 46 | - 0 represents complete randomness (all characters are unique), whereas 1 represents no randomness (all characters are identical). 47 | - English text generally has an IC of between 0.67 to 0.78. 48 | - 'Random' text is determined by the probability that each letter occurs the same number of times as another. 49 | 50 | `Reference `__ 51 | 52 | Args: 53 | data (Any): Any data type 54 | 55 | Returns: 56 | float: IC as float 57 | """ 58 | cipher_flat = "".join([x.upper() for x in data.split() if x.isalpha()]) 59 | 60 | N = len(cipher_flat) 61 | freqs = collections.Counter(cipher_flat) 62 | alphabet = map(chr, range(ord("A"), ord("Z") + 1)) 63 | freqsum = 0.0 64 | 65 | for letter in alphabet: 66 | freqsum += freqs[letter] * (freqs[letter] - 1) 67 | 68 | try: 69 | IC = freqsum / (N * (N - 1)) 70 | except ZeroDivisionError: 71 | IC = 0 72 | 73 | return IC 74 | -------------------------------------------------------------------------------- /chepy/extras/misc.pyi: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | 3 | def shannon_entropy(data: Any, unit: Any=...) -> float: ... 4 | def index_of_coincidence(data: Any) -> float: ... 5 | -------------------------------------------------------------------------------- /chepy/modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/chepy/modules/__init__.py -------------------------------------------------------------------------------- /chepy/modules/__init__.pyi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/chepy/modules/__init__.pyi -------------------------------------------------------------------------------- /chepy/modules/aritmeticlogic.pyi: -------------------------------------------------------------------------------- 1 | from ..core import ChepyCore 2 | from typing import Any, TypeVar, Union, Literal 3 | 4 | AritmeticLogicT = TypeVar("AritmeticLogicT", bound="AritmeticLogic") 5 | 6 | class AritmeticLogic(ChepyCore): 7 | def __init__(self, *data: Any) -> None: ... 8 | state: Any = ... 9 | def add(self: AritmeticLogicT, n: Union[int, str]) -> AritmeticLogicT: ... 10 | def addition(self: AritmeticLogicT, delimiter: Union[str, None]=None) -> AritmeticLogicT: ... 11 | def sub(self: AritmeticLogicT, n: Union[int, str]) -> AritmeticLogicT: ... 12 | def subtract(self: AritmeticLogicT, delimiter: Union[str, None]=None) -> AritmeticLogicT: ... 13 | def multiply(self: AritmeticLogicT, n: int) -> AritmeticLogicT: ... 14 | def divide(self: AritmeticLogicT, n: int) -> AritmeticLogicT: ... 15 | def power(self: AritmeticLogicT, n: int) -> AritmeticLogicT: ... 16 | def sum(self: AritmeticLogicT) -> AritmeticLogicT: ... 17 | def mean(self: AritmeticLogicT) -> AritmeticLogicT: ... 18 | def median(self: AritmeticLogicT) -> AritmeticLogicT: ... 19 | def int_to_base(self: AritmeticLogicT, base: Union[int, str]) -> AritmeticLogicT: ... 20 | def bit_shift_right(self: AritmeticLogicT, amount: int=1, operation_type: Literal['logical', 'arithmetic']='logical') -> AritmeticLogicT: ... 21 | def bit_shift_left(self: AritmeticLogicT, amount: int=1) -> AritmeticLogicT: ... 22 | -------------------------------------------------------------------------------- /chepy/modules/codetidy.py: -------------------------------------------------------------------------------- 1 | from typing import TypeVar 2 | 3 | import json 4 | import random 5 | 6 | import pydash 7 | import regex as re 8 | from ..core import ChepyCore, ChepyDecorators 9 | 10 | CodeTidyT = TypeVar("CodeTidyT", bound="CodeTidy") 11 | 12 | 13 | class CodeTidy(ChepyCore): 14 | def __init__(self, *data): 15 | super().__init__(*data) 16 | 17 | @ChepyDecorators.call_stack 18 | def minify_json(self) -> CodeTidyT: 19 | """Minify JSON string 20 | 21 | Returns: 22 | Chepy: The Chepy object. 23 | 24 | Examples: 25 | >>> c = Chepy("/path/to/file.json").load_file() 26 | >>> print(c.minify_json()) 27 | """ 28 | self.state = json.dumps( 29 | json.loads(self._convert_to_str()), separators=(",", ":") 30 | ) 31 | return self 32 | 33 | @ChepyDecorators.call_stack 34 | def beautify_json(self, indent: int = 2) -> CodeTidyT: 35 | """Beautify minified JSON 36 | 37 | Args: 38 | indent (int, optional): Indent level. Defaults to 2. 39 | 40 | Returns: 41 | Chepy: The Chepy object. 42 | 43 | Examples: 44 | >>> c = Chepy("/path/to/file.json").load_file() 45 | >>> print(c.beautify_json(indent=4)) 46 | """ 47 | self.state = json.dumps(json.loads(self._convert_to_str()), indent=indent) 48 | return self 49 | 50 | @ChepyDecorators.call_stack 51 | def to_upper_case(self, by: str = "all") -> CodeTidyT: 52 | """Convert string to uppercase 53 | 54 | Args: 55 | by (str, optional): Convert all, by word or by sentence. Defaults to 'all'. 56 | 57 | Returns: 58 | Chepy: The Chepy object. 59 | 60 | Examples: 61 | Uppercase by word 62 | 63 | >>> Chepy("some String").to_upper_case(by="word").o 64 | "Some String" 65 | 66 | Uppercase by sentence 67 | 68 | >>> Chepy("some String").to_upper_case(by="sentence").o 69 | "Some string" 70 | 71 | Uppercase all 72 | 73 | >>> Chepy("some String").to_upper_case(by="all").o 74 | "SOME STRING" 75 | """ 76 | assert by in [ 77 | "all", 78 | "word", 79 | "sentence", 80 | ], "Valid options are all, word and sentence" 81 | if by == "all": 82 | self.state = self._convert_to_str().upper() 83 | elif by == "word": 84 | self.state = self._convert_to_str().title() 85 | elif by == "sentence": 86 | self.state = self._convert_to_str().capitalize() 87 | return self 88 | 89 | @ChepyDecorators.call_stack 90 | def to_lower_case(self) -> CodeTidyT: 91 | """Convert string to lowercase 92 | 93 | Converts every character in the input to lower case. 94 | 95 | Returns: 96 | Chepy: The Chepy object. 97 | 98 | Examples: 99 | >>> Chepy("HelLo WorLd").to_lower_case().o 100 | "hello world" 101 | """ 102 | self.state = self._convert_to_str().lower() 103 | return self 104 | 105 | @ChepyDecorators.call_stack 106 | def to_snake_case(self) -> CodeTidyT: 107 | """Convert string to snake case 108 | 109 | Converts the input string to snake case. Snake case is all lower case 110 | with underscores as word boundaries. e.g. this_is_snake_case. 111 | 112 | Returns: 113 | Chepy: The Chepy object. 114 | 115 | Examples: 116 | >>> Chepy("helloWorld").to_snake_case().o 117 | "hello_world" 118 | """ 119 | s1 = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", self._convert_to_str()) 120 | self.state = re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower() 121 | return self 122 | 123 | @ChepyDecorators.call_stack 124 | def to_camel_case(self, ignore_space: bool = False) -> CodeTidyT: 125 | """Convert string to camel case 126 | 127 | Converts the input string to camel case. Camel case is all lower case 128 | except letters after word boundaries which are uppercase. e.g. thisIsCamelCase 129 | 130 | Args: 131 | ignore_space (bool, optional): Ignore space boundaries. Defaults to False. 132 | 133 | Returns: 134 | Chepy: The Chepy object. 135 | 136 | Examples: 137 | >>> Chepy("some Data_test").to_camel_case().o 138 | "someDataTest" 139 | 140 | To ignore space, we can set the `ignore_space` to True 141 | >>> Chepy("some Data_test").to_camel_case(ignore_space=True).o 142 | "some DataTest" 143 | """ 144 | if ignore_space: 145 | r = re.compile(r"_.|\-.") 146 | else: 147 | r = re.compile(r"_.|\-.|\s.") 148 | self.state = r.sub(lambda x: x.group()[1].upper(), self._convert_to_str()) 149 | return self 150 | 151 | @ChepyDecorators.call_stack 152 | def to_kebab_case(self) -> CodeTidyT: 153 | """Convert string to kebab case 154 | 155 | Converts the input string to kebab case. Kebab case is all lower case 156 | with dashes as word boundaries. e.g. this-is-kebab-case. 157 | 158 | Returns: 159 | Chepy: The Chepy object. 160 | 161 | Examples: 162 | >>> Chepy("Some data_test").to_kebab_case().o 163 | "some-data-test" 164 | """ 165 | self.state = pydash.kebab_case(self._convert_to_str()) 166 | return self 167 | 168 | @ChepyDecorators.call_stack 169 | def swap_case(self) -> CodeTidyT: 170 | """Swap case in a string 171 | 172 | Returns: 173 | Chepy: The Chepy object. 174 | 175 | Examples: 176 | >>> Chepy("SoMe TeXt").swap_case().o 177 | "sOmE tExT" 178 | """ 179 | self.state = pydash.swap_case(self._convert_to_str()) 180 | return self 181 | 182 | @ChepyDecorators.call_stack 183 | def to_leetspeak(self, special_chars: bool = True) -> CodeTidyT: 184 | """Convert string to l33t speak 185 | 186 | Args: 187 | special_chars (bool, optional): Use special chars in conversion. Defaults to True. 188 | 189 | Returns: 190 | Chepy: The Chepy object 191 | 192 | Examples: 193 | >>> Chepy("somexValue").to_leetspeak().o 194 | "50m3%V@1u3" 195 | """ 196 | chars = {"B": "8", "E": "3", "L": "1", "O": "0", "S": "5", "T": "7", "Z": "2"} 197 | special = {"A": "@", "C": "(", "I": "!", "X": "%"} 198 | if special_chars: 199 | chars = {**chars, **special} 200 | hold = "" 201 | for char in list(self._convert_to_str()): 202 | upper = char.upper() 203 | char_to_append = chars.get(upper) 204 | if char_to_append: 205 | hold += char_to_append 206 | else: 207 | hold += char 208 | self.state = hold 209 | return self 210 | 211 | @ChepyDecorators.call_stack 212 | def random_case(self) -> CodeTidyT: 213 | """Randomly change the case 214 | 215 | Returns: 216 | Chepy: The Chepy object. 217 | """ 218 | string = self._convert_to_str() 219 | string_length = len(string) 220 | 221 | random_indices = random.sample(range(string_length), string_length) 222 | random_chars = [] 223 | for i in random_indices: 224 | if random.choice([True, False]): 225 | random_chars.append(string[i].upper()) 226 | else: 227 | random_chars.append(string[i].lower()) 228 | 229 | string_list = list(string) 230 | for index, char in zip(random_indices, random_chars): 231 | if 0 <= index < len(string_list): 232 | string_list[index] = char 233 | self.state = "".join(string_list) 234 | return self 235 | -------------------------------------------------------------------------------- /chepy/modules/codetidy.pyi: -------------------------------------------------------------------------------- 1 | from ..core import ChepyCore 2 | from typing import Any, TypeVar, Literal 3 | 4 | pydash: Any 5 | CodeTidyT = TypeVar('CodeTidyT', bound='CodeTidy') 6 | 7 | class CodeTidy(ChepyCore): 8 | def __init__(self, *data: Any) -> None: ... 9 | state: Any = ... 10 | def minify_json(self: CodeTidyT) -> CodeTidyT: ... 11 | def beautify_json(self: CodeTidyT, indent: int=...) -> CodeTidyT: ... 12 | def to_upper_case(self: CodeTidyT, by: Literal['all', 'word', 'sentence']=...) -> CodeTidyT: ... 13 | def to_lower_case(self: CodeTidyT) -> CodeTidyT: ... 14 | def to_snake_case(self: CodeTidyT) -> CodeTidyT: ... 15 | def to_camel_case(self: CodeTidyT, ignore_space: bool=...) -> CodeTidyT: ... 16 | def to_kebab_case(self: CodeTidyT) -> CodeTidyT: ... 17 | def swap_case(self: CodeTidyT) -> CodeTidyT: ... 18 | def to_leetspeak(self: CodeTidyT, special_chars: bool=...) -> CodeTidyT: ... 19 | def random_case(self) -> CodeTidyT: ... 20 | -------------------------------------------------------------------------------- /chepy/modules/compression.pyi: -------------------------------------------------------------------------------- 1 | from ..core import ChepyCore 2 | from typing import Any, TypeVar, Literal 3 | 4 | CompressionT = TypeVar('CompressionT', bound='Compression') 5 | 6 | class Compression(ChepyCore): 7 | def __init__(self, *data: Any) -> None: ... 8 | state: Any = ... 9 | def fix_zip_header(self: CompressionT) -> CompressionT: ... 10 | def zip_info(self: CompressionT) -> CompressionT: ... 11 | def zip_list_files(self: CompressionT) -> CompressionT: ... 12 | def unzip_one(self: CompressionT, file: str, password: str=...) -> CompressionT: ... 13 | def unzip_all(self: CompressionT, password: str=...) -> CompressionT: ... 14 | def create_zip_file(self: CompressionT, file_name: str) -> CompressionT: ... 15 | def zip_compress(self: CompressionT, file_name: str) -> CompressionT: ... 16 | def zip_compress_symlink(self: CompressionT, file_name: str, target_file: str) -> CompressionT: ... 17 | def tar_list_files(self: CompressionT, mode: Literal["gz", "bz2", "xz", ""]=...) -> CompressionT: ... 18 | def tar_extract_one(self: CompressionT, filename: str, mode: Literal["gz", "bz2", "xz", ""]=...) -> CompressionT: ... 19 | def tar_extract_all(self: CompressionT, mode: Literal["gz", "bz2", "xz", ""]=...) -> CompressionT: ... 20 | def tar_compress(self: CompressionT, filename: str, mode: Literal["gz", "bz2", "xz", ""]=...) -> CompressionT: ... 21 | def gzip_compress(self: CompressionT, file_name: str=...) -> CompressionT: ... 22 | def gzip_decompress(self: CompressionT) -> CompressionT: ... 23 | def bzip_compress(self: CompressionT) -> CompressionT: ... 24 | def bzip_decompress(self: CompressionT) -> CompressionT: ... 25 | def zlib_compress(self: CompressionT, level: int=...) -> CompressionT: ... 26 | def zlib_decompress(self: CompressionT) -> CompressionT: ... 27 | def lzma_compress(self: CompressionT) -> CompressionT: ... 28 | def lzma_decompress(self: CompressionT) -> CompressionT: ... 29 | def raw_inflate(self: CompressionT) -> CompressionT: ... 30 | def raw_deflate(self: CompressionT) -> CompressionT: ... 31 | def lz4_compress(self: CompressionT) -> CompressionT: ... 32 | def lz4_decompress(self: CompressionT) -> CompressionT: ... 33 | def lz77_compress(self: CompressionT, window_size: int = 13, lookahead_buffer_size: int = 6) -> CompressionT: ... 34 | def lz77_decompress(self: CompressionT, window_size: int = 13, lookahead_buffer_size: int = 6) -> CompressionT: ... 35 | -------------------------------------------------------------------------------- /chepy/modules/datetimemodule.py: -------------------------------------------------------------------------------- 1 | import time 2 | from datetime import datetime 3 | from typing import TypeVar 4 | 5 | from ..core import ChepyCore, ChepyDecorators 6 | 7 | DateTimeT = TypeVar("DateTimeT", bound="DateTime") 8 | 9 | 10 | class DateTime(ChepyCore): 11 | def __init__(self, *data): 12 | super().__init__(*data) 13 | 14 | @ChepyDecorators.call_stack 15 | def from_unix_timestamp(self, format: str = "%c", utc: bool = False) -> DateTimeT: 16 | """Convert UNIX timestamp to datetime 17 | 18 | Args: 19 | format: Format to use for datetime.strftime() 20 | utc: Whether to use UTC or local timezone 21 | 22 | Returns: 23 | Chepy: The Chepy object. 24 | 25 | Examples: 26 | >>> Chepy("1573426649").from_unix_timestamp() 27 | "Sun Nov 10 17:57:29 2019" 28 | """ 29 | data = self._convert_to_int() 30 | if utc: 31 | self.state = datetime.utcfromtimestamp(data).strftime(format) 32 | else: 33 | self.state = datetime.fromtimestamp(data).strftime(format) 34 | return self 35 | 36 | @ChepyDecorators.call_stack 37 | def to_unix_timestamp(self) -> DateTimeT: # pragma: no cover 38 | """Convert datetime string to unix ts 39 | 40 | The format for the string is %a %b %d %H:%M:%S %Y, which is equivalent to 41 | %c from datatime. 42 | 43 | Returns: 44 | Chepy: The Chepy object. 45 | 46 | Examples: 47 | >>> Chepy("Sun Nov 10 17:57:29 2019").to_unix_timestamp() 48 | "1573426649" 49 | """ 50 | self.state = int( 51 | time.mktime(time.strptime(self._convert_to_str(), "%a %b %d %H:%M:%S %Y")) 52 | ) 53 | return self 54 | -------------------------------------------------------------------------------- /chepy/modules/datetimemodule.pyi: -------------------------------------------------------------------------------- 1 | from ..core import ChepyCore 2 | from typing import Any, TypeVar 3 | 4 | DateTimeT = TypeVar("DateTimeT", bound="DateTime") 5 | 6 | class DateTime(ChepyCore): 7 | def __init__(self, *data: Any) -> None: ... 8 | state: Any = ... 9 | def from_unix_timestamp(self: DateTimeT, format: str = ..., utc: bool = ...) -> DateTimeT: ... 10 | def to_unix_timestamp(self: DateTimeT) -> DateTimeT: ... 11 | -------------------------------------------------------------------------------- /chepy/modules/exceptions.py: -------------------------------------------------------------------------------- 1 | class StateNotList(Exception): # pragma: no cover 2 | def __init__(self, msg="State is not a list", *args, **kwargs): 3 | super().__init__(msg, *args, **kwargs) 4 | 5 | 6 | class StateNotDict(Exception): # pragma: no cover 7 | def __init__(self, msg="State is not a dict", *args, **kwargs): 8 | super().__init__(msg, *args, **kwargs) 9 | -------------------------------------------------------------------------------- /chepy/modules/exceptions.pyi: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | 3 | class StateNotList(Exception): 4 | def __init__(self, msg: str = ..., *args: Any, **kwargs: Any) -> None: ... 5 | 6 | class StateNotDict(Exception): 7 | def __init__(self, msg: str = ..., *args: Any, **kwargs: Any) -> None: ... 8 | -------------------------------------------------------------------------------- /chepy/modules/extractors.pyi: -------------------------------------------------------------------------------- 1 | from ..core import ChepyCore 2 | from typing import Any, TypeVar, Union, List 3 | 4 | parsel: Any 5 | 6 | ExtractorsT = TypeVar('ExtractorsT', bound='Extractors') 7 | 8 | class Extractors(ChepyCore): 9 | def __init__(self, *data: Any) -> None: ... 10 | state: Any = ... 11 | def extract_hashes(self: ExtractorsT) -> ExtractorsT: ... 12 | def extract_strings(self: ExtractorsT, length: int=..., join_by: str=...) -> ExtractorsT: ... 13 | def extract_ips(self: ExtractorsT, is_binary: bool=...) -> ExtractorsT: ... 14 | def extract_email(self: ExtractorsT, is_binary: bool=...) -> ExtractorsT: ... 15 | def extract_mac_address(self: ExtractorsT, is_binary: bool=...) -> ExtractorsT: ... 16 | def extract_urls(self: ExtractorsT, is_binary: bool=...) -> ExtractorsT: ... 17 | def extract_domains(self: ExtractorsT, is_binary: bool=...) -> ExtractorsT: ... 18 | def javascript_comments(self: ExtractorsT) -> ExtractorsT: ... 19 | def extract_google_api(self: ExtractorsT) -> ExtractorsT: ... 20 | def extract_google_captcha(self: ExtractorsT) -> ExtractorsT: ... 21 | def extract_google_oauth(self: ExtractorsT) -> ExtractorsT: ... 22 | def extract_aws_keyid(self: ExtractorsT) -> ExtractorsT: ... 23 | def extract_aws_s3_url(self: ExtractorsT) -> ExtractorsT: ... 24 | def extract_facebook_access_token(self: ExtractorsT) -> ExtractorsT: ... 25 | def extract_auth_basic(self: ExtractorsT) -> ExtractorsT: ... 26 | def extract_auth_bearer(self: ExtractorsT) -> ExtractorsT: ... 27 | def extract_mailgun_api(self: ExtractorsT) -> ExtractorsT: ... 28 | def extract_twilio_api(self: ExtractorsT) -> ExtractorsT: ... 29 | def extract_twilio_sid(self: ExtractorsT) -> ExtractorsT: ... 30 | def extract_paypal_bt(self: ExtractorsT) -> ExtractorsT: ... 31 | def extract_square_oauth(self: ExtractorsT) -> ExtractorsT: ... 32 | def extract_square_access(self: ExtractorsT) -> ExtractorsT: ... 33 | def extract_stripe_api(self: ExtractorsT) -> ExtractorsT: ... 34 | def extract_github(self: ExtractorsT) -> ExtractorsT: ... 35 | def extract_rsa_private(self: ExtractorsT) -> ExtractorsT: ... 36 | def extract_dsa_private(self: ExtractorsT) -> ExtractorsT: ... 37 | def extract_jwt_token(self: ExtractorsT) -> ExtractorsT: ... 38 | def extract_base64(self: ExtractorsT, min: int=...) -> ExtractorsT: ... 39 | def find_continuous_patterns(self: ExtractorsT, str2: Union[str, bytes], min_value: int=...) -> ExtractorsT: ... 40 | def find_longest_continious_pattern(self: ExtractorsT, str2: Union[str, bytes]) -> ExtractorsT: ... 41 | def extract_zero_width_chars_tags(self: ExtractorsT) -> ExtractorsT: ... 42 | def decode_zero_width(self: ExtractorsT, chars: str=...) -> ExtractorsT: ... 43 | def xpath_selector(self: ExtractorsT, query: str, index:int=None, namespaces: str=None) -> ExtractorsT: ... 44 | def css_selector(self: ExtractorsT, query: str) -> ExtractorsT: ... 45 | def extract_html_comments(self: ExtractorsT) -> ExtractorsT: ... 46 | def extract_html_tags(self: ExtractorsT, tag: List[str]) -> ExtractorsT: ... 47 | def aws_account_id_from_access_key(self: ExtractorsT) -> ExtractorsT: ... 48 | -------------------------------------------------------------------------------- /chepy/modules/hashing.pyi: -------------------------------------------------------------------------------- 1 | from ..core import ChepyCore 2 | from typing import Any, TypeVar, Union 3 | from typing_extensions import Literal as Literal 4 | 5 | type_password_hashes = Literal[ 6 | "apr_md5_crypt", 7 | "argon2", 8 | "atlassian_pbkdf2_sha1", 9 | "bcrypt", 10 | "bcrypt_sha256", 11 | "bigcrypt", 12 | "bsd_nthash", 13 | "bsdi_crypt", 14 | "cisco_asa", 15 | "cisco_pix", 16 | "cisco_type7", 17 | "crypt16", 18 | "cta_pbkdf2_sha1", 19 | "des_crypt", 20 | "django_digest", 21 | "dlitz_pbkdf2_sha1", 22 | "fshp", 23 | "grub_pbkdf2_sha512", 24 | "hex_digest", 25 | "ldap_crypt", 26 | "ldap_hex_md5", 27 | "ldap_hex_sha1", 28 | "ldap_md5", 29 | "ldap_pbkdf2_digest", 30 | "ldap_plaintext", 31 | "ldap_salted_md5", 32 | "ldap_salted_sha1", 33 | "ldap_salted_sha256", 34 | "ldap_salted_sha512", 35 | "ldap_sha1", 36 | "lmhash", 37 | "md5_crypt", 38 | "msdcc", 39 | "msdcc2", 40 | "mssql2000", 41 | "mssql2005", 42 | "mysql323", 43 | "mysql41", 44 | "nthash", 45 | "oracle10", 46 | "oracle11", 47 | "pbkdf2_digest", 48 | "phpass", 49 | "postgres_md5", 50 | "roundup_plaintext", 51 | "scram", 52 | "scrypt", 53 | "sha1_crypt", 54 | "sha256_crypt", 55 | "sha512_crypt", 56 | "sun_md5_crypt", 57 | "unix_disabled", 58 | ] 59 | 60 | HashingT = TypeVar('HashingT', bound='Hashing') 61 | hmac: Any 62 | MD2: Any 63 | MD4: Any 64 | MD5: Any 65 | SHA512: Any 66 | SHA1: Any 67 | SHA256: Any 68 | keccak: Any 69 | SHAKE128: Any 70 | SHAKE256: Any 71 | RIPEMD: Any 72 | BLAKE2s: Any 73 | BLAKE2b: Any 74 | KDF: Any 75 | 76 | class Hashing(ChepyCore): 77 | def __init__(self, *data: Any) -> None: ... 78 | state: Any = ... 79 | def sha1(self: HashingT) -> HashingT: ... 80 | def sha2_256(self: HashingT) -> HashingT: ... 81 | def sha2_512(self: HashingT) -> HashingT: ... 82 | def sha2_512_truncate(self: HashingT, truncate: Literal[256, 224]=...) -> HashingT: ... 83 | def sha2_384(self: HashingT) -> HashingT: ... 84 | def sha2_224(self: HashingT) -> HashingT: ... 85 | def sha3_512(self: HashingT) -> HashingT: ... 86 | def sha3_256(self: HashingT) -> HashingT: ... 87 | def sha3_384(self: HashingT) -> HashingT: ... 88 | def sha3_224(self: HashingT) -> HashingT: ... 89 | def md2(self: HashingT) -> HashingT: ... 90 | def md4(self: HashingT) -> HashingT: ... 91 | def md5(self: HashingT) -> HashingT: ... 92 | def keccak_512(self: HashingT) -> HashingT: ... 93 | def keccak_384(self: HashingT) -> HashingT: ... 94 | def keccak_256(self: HashingT) -> HashingT: ... 95 | def keccak_224(self: HashingT) -> HashingT: ... 96 | def shake_256(self: HashingT, size: int=...) -> HashingT: ... 97 | def shake_128(self: HashingT, size: int=...) -> HashingT: ... 98 | def ripemd_160(self: HashingT) -> HashingT: ... 99 | def blake_2b(self: HashingT, bits: Literal[512, 384, 256, 160, 128]=..., key: bytes=...) -> HashingT: ... 100 | def blake_2s(self: HashingT, bits: Literal[256, 160, 128]=..., key: bytes=...) -> HashingT: ... 101 | def crc8_checksum(self: HashingT) -> HashingT: ... 102 | def crc16_checksum(self: HashingT) -> HashingT: ... 103 | def crc32_checksum(self: HashingT) -> HashingT: ... 104 | def hmac_hash(self: HashingT, key: bytes=..., digest: Literal['md5', 'sha1', 'sha256', 'sha512']=...) -> HashingT: ... 105 | def derive_pbkdf2_key(self: HashingT, password: Union[str, bytes], salt: Union[str, bytes], key_size: int=..., iterations: int=..., hash_type: Literal['md5', 'sha1', 'sha256', 'sha512']=..., hex_salt: bool=..., show_full_key: bool=...) -> Any: ... 106 | def bcrypt_hash(self: HashingT, rounds: int=...) -> HashingT: ... 107 | def bcrypt_compare(self: HashingT, hash: str) -> HashingT: ... 108 | def scrypt_hash(self: HashingT, salt: str=..., key_length: int=..., N: int=..., r: int=..., p: int=...) -> HashingT: ... 109 | def password_hashing(self: HashingT, format: type_password_hashes, **kwargs) -> HashingT: ... 110 | -------------------------------------------------------------------------------- /chepy/modules/internal/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/chepy/modules/internal/__init__.py -------------------------------------------------------------------------------- /chepy/modules/internal/__init__.pyi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/chepy/modules/internal/__init__.pyi -------------------------------------------------------------------------------- /chepy/modules/internal/cli.pyi: -------------------------------------------------------------------------------- 1 | from prompt_toolkit.completion import Completer 2 | from typing import Any 3 | 4 | module: Any 5 | options: Any 6 | config: Any 7 | 8 | class CliCompleter(Completer): 9 | def get_completions(self, document: Any, complete_event: Any) -> None: ... 10 | 11 | def functions_cli(): ... 12 | def get_doc(method: str) -> Any: ... 13 | def cli_edit_state(fire: object, args: list) -> Any: ... 14 | def cli_highlight(fire: object, highlight: str) -> Any: ... 15 | def get_cli_options(): ... 16 | def print_in_colors(out: Any) -> None: ... 17 | def cli_state_type(fire: object) -> Any: ... 18 | def cli_get_state(fire: object, index: int) -> Any: ... 19 | def cli_show_length(fire: object) -> Any: ... 20 | def cli_show_dict_keys(fire: object, pretty: bool=...) -> Any: ... 21 | def cli_show_states(fire: object, pretty: bool=...) -> Any: ... 22 | def cli_show_buffers(fire: object, pretty: bool=...) -> Any: ... 23 | def cli_get_attr(fire: object, attr: str) -> Any: ... 24 | def cli_pretty_print(fire: object) -> Any: ... 25 | def cli_plugin_path(config: Any) -> None: ... 26 | def cli_show_errors(errors: Any) -> None: ... 27 | def cli_go_back() -> None: ... 28 | def cli_delete_history() -> None: ... 29 | def cli_exit(fire: object) -> Any: ... 30 | -------------------------------------------------------------------------------- /chepy/modules/internal/colors.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from colorama import Fore, Back 3 | 4 | 5 | def yellow_background(s: str) -> str: # pragma: no cover 6 | """Yellow color string if tty 7 | 8 | Args: 9 | s (str): String to color 10 | 11 | Returns: 12 | str: Colored string 13 | """ 14 | if sys.stdout.isatty(): 15 | return Back.YELLOW + Fore.BLACK + s + Fore.RESET + Back.RESET 16 | else: 17 | return s 18 | 19 | 20 | def red(s: str) -> str: # pragma: no cover 21 | """Red color string if tty 22 | 23 | Args: 24 | s (str): String to color 25 | 26 | Returns: 27 | str: Colored string 28 | 29 | Examples: 30 | >>> from chepy.modules.internal.colors import red 31 | >>> print(RED("some string")) 32 | """ 33 | if sys.stdout.isatty(): 34 | return Fore.RED + s + Fore.RESET 35 | else: 36 | return s 37 | 38 | 39 | def blue(s: str) -> str: # pragma: no cover 40 | """Blue color string if tty 41 | 42 | Args: 43 | s (str): String to color 44 | 45 | Returns: 46 | str: Colored string 47 | 48 | Examples: 49 | >>> from chepy.modules.internal.colors import blue 50 | >>> print(BLUE("some string")) 51 | """ 52 | if sys.stdout.isatty(): 53 | return Fore.BLUE + s + Fore.RESET 54 | else: 55 | return s 56 | 57 | 58 | def cyan(s: str) -> str: # pragma: no cover 59 | """Cyan color string if tty 60 | 61 | Args: 62 | s (str): String to color 63 | 64 | Returns: 65 | str: Colored string 66 | 67 | Examples: 68 | >>> from chepy.modules.internal.colors import cyan 69 | >>> print(CYAN("some string")) 70 | """ 71 | if sys.stdout.isatty(): 72 | return Fore.CYAN + s + Fore.RESET 73 | else: 74 | return s 75 | 76 | 77 | def green(s: str) -> str: # pragma: no cover 78 | """Green color string if tty 79 | 80 | Args: 81 | s (str): String to color 82 | 83 | Returns: 84 | str: Colored string 85 | 86 | Examples: 87 | >>> from chepy.modules.internal.colors import green 88 | >>> print(GREEN("some string")) 89 | """ 90 | if sys.stdout.isatty(): 91 | return Fore.GREEN + s + Fore.RESET 92 | else: 93 | return s 94 | 95 | 96 | def yellow(s: str) -> str: # pragma: no cover 97 | """Yellow color string if tty 98 | 99 | Args: 100 | s (str): String to color 101 | 102 | Returns: 103 | str: Colored string 104 | 105 | Examples: 106 | >>> from chepy.modules.internal.colors import yellow 107 | >>> print(YELLOW("some string")) 108 | """ 109 | if sys.stdout.isatty(): 110 | return Fore.YELLOW + s + Fore.RESET 111 | else: 112 | return s 113 | 114 | 115 | def magenta(s: str) -> str: # pragma: no cover 116 | """Magenta color string if tty 117 | 118 | Args: 119 | s (str): String to color 120 | 121 | Returns: 122 | str: Colored string 123 | 124 | Examples: 125 | >>> from chepy.modules.internal.colors import magenta 126 | >>> print(MAGENTA("some string")) 127 | """ 128 | if sys.stdout.isatty(): 129 | return Fore.MAGENTA + s + Fore.RESET 130 | else: 131 | return s 132 | -------------------------------------------------------------------------------- /chepy/modules/internal/colors.pyi: -------------------------------------------------------------------------------- 1 | def yellow_background(s: str) -> str: ... 2 | def red(s: str) -> str: ... 3 | def blue(s: str) -> str: ... 4 | def cyan(s: str) -> str: ... 5 | def green(s: str) -> str: ... 6 | def yellow(s: str) -> str: ... 7 | def magenta(s: str) -> str: ... 8 | -------------------------------------------------------------------------------- /chepy/modules/internal/constants.pyi: -------------------------------------------------------------------------------- 1 | from typing import Any, Dict, List 2 | 3 | class Encoding: 4 | py_encodings: Any = ... 5 | py_text_encodings: Any = ... 6 | asciichars: Any = ... 7 | brailles: Any = ... 8 | wingdings: dict = ... 9 | NATO_CONSTANTS_DICT: Dict[str, str] = ... 10 | LEETCODE: List[List[str]] = ... 11 | BASE91_ALPHABET: List[str] = ... 12 | 13 | class EncryptionConsts: 14 | MORSE_CODE_DICT: Any = ... 15 | 16 | class PcapUSB: 17 | qwerty_map: Any = ... 18 | qwerty_modifier: Any = ... 19 | dvorak: Any = ... 20 | dvorak_modifier: Any = ... 21 | -------------------------------------------------------------------------------- /chepy/modules/internal/ls47.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # This software is hereby released into public domain. Use it wisely. 5 | # 6 | # Originally written by Mirek Kratochvil (2017) 7 | # Python3 port by Bernhard Esslinger (Feb 2018) 8 | 9 | import random 10 | 11 | letters = "_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()" 12 | tiles = list(zip(letters, map(lambda x: (x // 7, x % 7), range(7 * 7)))) 13 | 14 | 15 | def check_key(key): # pragma: no cover 16 | if len(key) != len(letters): 17 | raise ValueError("Wrong key size") 18 | cnts = {} 19 | for c in letters: 20 | cnts[c] = 0 21 | for c in key: 22 | if not c in cnts: 23 | raise ValueError("Letter " + c + " not in LS47!") 24 | cnts[c] += 1 25 | if cnts[c] > 1: 26 | raise ValueError("Letter " + c + " duplicated in key!") 27 | 28 | 29 | def find_ix(letter): # pragma: no cover 30 | m = [l for l in tiles if l[0] == letter] 31 | if len(m) != 1: 32 | raise ValueError("Letter " + letter + " not in LS47!") 33 | for (l, pos) in m: 34 | return pos 35 | 36 | 37 | def find_pos(key, letter): # pragma: no cover 38 | p = key.find(letter) 39 | if p >= 0 and p < 7 * 7: 40 | return (p // 7, p % 7) 41 | raise ValueError("Letter " + letter + " not in key?!") 42 | 43 | 44 | def add_pos(a, b): # pragma: no cover 45 | return ((a[0] + b[0]) % 7, (a[1] + b[1]) % 7) 46 | 47 | 48 | def sub_pos(a, b): 49 | return ((a[0] - b[0]) % 7, (a[1] - b[1]) % 7) 50 | 51 | 52 | def find_at_pos(key, coord): # pragma: no cover 53 | return key[coord[1] + coord[0] * 7] 54 | 55 | 56 | def rotate_right(key, row, n): # pragma: no cover 57 | mid = key[7 * row : 7 * (row + 1)] 58 | n = (7 - n % 7) % 7 59 | return key[: 7 * row] + mid[n:] + mid[:n] + key[7 * (row + 1) :] 60 | 61 | 62 | def rotate_down(key, col, n): # pragma: no cover 63 | lines = [key[i * 7 : (i + 1) * 7] for i in range(7)] 64 | lefts = [l[:col] for l in lines] 65 | mids = [l[col] for l in lines] 66 | rights = [l[col + 1 :] for l in lines] 67 | n = (7 - n % 7) % 7 68 | mids = mids[n:] + mids[:n] 69 | return "".join(lefts[i] + mids[i] + rights[i] for i in range(7)) 70 | 71 | 72 | def rotate_marker_right(m, row, n): # pragma: no cover 73 | if m[0] != row: 74 | return (m[0], m[1]) 75 | else: 76 | return (m[0], (m[1] + n) % 7) 77 | 78 | 79 | def rotate_marker_down(m, col, n): # pragma: no cover 80 | if m[1] != col: 81 | return (m[0], m[1]) 82 | else: 83 | return ((m[0] + n) % 7, m[1]) 84 | 85 | 86 | def derive_key(password): # pragma: no cover 87 | i = 0 88 | k = letters 89 | for c in password: 90 | (row, col) = find_ix(c) 91 | k = rotate_down(rotate_right(k, i, col), i, row) 92 | i = (i + 1) % 7 93 | return k 94 | 95 | 96 | def encrypt(key, plaintext): # pragma: no cover 97 | check_key(key) 98 | mp = (0, 0) 99 | ciphertext = "" 100 | for p in plaintext: 101 | pp = find_pos(key, p) 102 | mix = find_ix(find_at_pos(key, mp)) 103 | cp = add_pos(pp, mix) 104 | c = find_at_pos(key, cp) 105 | ciphertext += c 106 | 107 | key = rotate_right(key, pp[0], 1) 108 | cp = find_pos(key, c) 109 | key = rotate_down(key, cp[1], 1) 110 | mp = add_pos(mp, find_ix(c)) 111 | return ciphertext 112 | 113 | 114 | def decrypt(key, ciphertext): # pragma: no cover 115 | check_key(key) 116 | mp = (0, 0) 117 | plaintext = "" 118 | for c in ciphertext: 119 | cp = find_pos(key, c) 120 | mix = find_ix(find_at_pos(key, mp)) 121 | pp = sub_pos(cp, mix) 122 | p = find_at_pos(key, pp) 123 | plaintext += p 124 | 125 | key = rotate_right(key, pp[0], 1) 126 | cp = find_pos(key, c) 127 | key = rotate_down(key, cp[1], 1) 128 | mp = add_pos(mp, find_ix(c)) 129 | return plaintext 130 | 131 | 132 | def encrypt_pad(key, plaintext, signature, padding_size): # pragma: no cover 133 | 134 | # TODO it would also be great to randomize the message length. 135 | 136 | check_key(key) 137 | padding = "".join( 138 | map(lambda x: letters[random.randint(0, len(letters) - 1)], range(padding_size)) 139 | ) 140 | 141 | return encrypt(key, padding + plaintext + "---" + signature) 142 | 143 | 144 | def decrypt_pad(key, padding_size, ciphertext): # pragma: no cover 145 | check_key(key) 146 | return decrypt(key, ciphertext)[padding_size:] 147 | -------------------------------------------------------------------------------- /chepy/modules/language.py: -------------------------------------------------------------------------------- 1 | import unicodedata 2 | from typing import TypeVar 3 | 4 | import emoji 5 | import regex as re 6 | 7 | from ..core import ChepyCore, ChepyDecorators 8 | 9 | LanguageT = TypeVar("LanguageT", bound="Language") 10 | 11 | 12 | class Language(ChepyCore): 13 | def __init__(self, *data): 14 | super().__init__(*data) 15 | 16 | @ChepyDecorators.call_stack 17 | def search_perl_unicode_props(self, lang: str) -> LanguageT: 18 | """Search using perl unicode properties. 19 | https://perldoc.perl.org/perluniprops#(%5Cd+)-in-the-info-column-gives-the-number-of-Unicode-code-points-matched-by-this-property. 20 | 21 | Args: 22 | lang (str): Required. A string value identifying the language. 23 | 24 | Returns: 25 | Chepy: The Chepy object. 26 | """ 27 | self.state = re.findall(r"\p{" + lang + "}", self._convert_to_str()) 28 | return self 29 | 30 | @ChepyDecorators.call_stack 31 | def find_emojis(self) -> LanguageT: 32 | """Find emojis, symbols, pictographs, map symbols and flags 33 | 34 | Returns: 35 | Chepy: The Chepy object. 36 | """ 37 | self.state = [e.get("emoji") for e in emoji.emoji_list(self._convert_to_str())] 38 | return self 39 | 40 | @ChepyDecorators.call_stack 41 | def encode(self, encoding: str, errors: str = "backslashreplace") -> LanguageT: 42 | """Encode the string using the given encoding. 43 | 44 | Args: 45 | encoding (str): Encoding to use. 46 | errors (str, optional): How to handle errors when encoding. Defaults to 'backslashreplace'. 47 | 48 | Returns: 49 | Chepy: The Chepy object. 50 | """ 51 | self.state = self._convert_to_str().encode(encoding, errors=errors) 52 | return self 53 | 54 | @ChepyDecorators.call_stack 55 | def encode_us_ascii_7_bit(self) -> LanguageT: 56 | """Encode state using US ascii 7 bit 57 | 58 | Returns: 59 | Chepy: The Chepy object. 60 | """ 61 | data = self._convert_to_str() 62 | self.state = "".join(chr(ord(c) & 127) for c in data) 63 | return self 64 | 65 | @ChepyDecorators.call_stack 66 | def decode(self, encoding: str, errors: str = "backslashreplace") -> LanguageT: 67 | """Decode the string using the given encoding. 68 | 69 | Args: 70 | encoding (str): Encoding to use. 71 | errors (str, optional): How to handle errors when decoding. Defaults to 'backslashreplace'. 72 | 73 | Returns: 74 | Chepy: The Chepy object. 75 | """ 76 | self.state = self._convert_to_bytes().decode(encoding, errors=errors) 77 | return self 78 | 79 | @ChepyDecorators.call_stack 80 | def remove_diacritics(self) -> LanguageT: 81 | """Replaces accented characters latin character equivalent. 82 | 83 | Returns: 84 | Chepy: The Chepy object. 85 | """ 86 | self.state = unicodedata.normalize("NFKD", self._convert_to_str()).encode( 87 | "ascii", errors="ignore" 88 | ) 89 | return self 90 | 91 | @ChepyDecorators.call_stack 92 | def unicode_to_str(self, as_bytes=False) -> LanguageT: 93 | """Escape any \\u characters to its proper unicode representation 94 | 95 | Args: 96 | as_bytes (bool): Treat state as bytes. This does not handle %u or U+ encodings 97 | 98 | Returns: 99 | Chepy: The Chepy object. 100 | """ 101 | if as_bytes: 102 | self.state = self._convert_to_bytes().decode( 103 | "unicode-escape", errors="backslashreplace" 104 | ) 105 | else: 106 | data = self._convert_to_str() 107 | cleaned_string = re.sub(r"(\\u|%u|U\+)", r"\\u", data) 108 | self.state = bytes(cleaned_string, "utf-8").decode( 109 | "unicode-escape", errors="backslashreplace" 110 | ) 111 | return self 112 | 113 | @ChepyDecorators.call_stack 114 | def str_to_unicode(self, prefix: str = "\\u", all_chars: bool = False) -> LanguageT: 115 | """Convert unicode to str 116 | 117 | Args: 118 | prefix (str): Prefix character. 119 | all_chars (bool): Force convert all chars to unicode. 120 | 121 | Returns: 122 | Chepy: The Chepy object. 123 | """ 124 | data = self._convert_to_str() 125 | if all_chars: 126 | hold = [] 127 | for d in data: 128 | hold.append("{}{:04x}".format(prefix, ord(d))) 129 | self.state = "".join(hold) 130 | return self 131 | self.state = data.encode("unicode_escape") 132 | return self 133 | -------------------------------------------------------------------------------- /chepy/modules/language.pyi: -------------------------------------------------------------------------------- 1 | from ..core import ChepyCore 2 | from typing import Any, Literal, TypeVar 3 | 4 | LanguageT = TypeVar("LanguageT", bound="Language") 5 | 6 | ENCODINGS = Literal[ 7 | "utf_16_le", 8 | "utf_16_be", 9 | "utf_7", 10 | "utf_8", 11 | "cp500", 12 | "cp037", 13 | "cp874", 14 | "cp932", 15 | "gbk", 16 | "gb2312", 17 | "cp949", 18 | "cp950", 19 | "cp1250", 20 | "cp1251", 21 | "cp1252", 22 | "cp1253", 23 | "cp1254", 24 | "cp1255", 25 | "cp1256", 26 | "cp1257", 27 | "cp1258", 28 | "iso8859_2", 29 | "iso8859_3", 30 | "iso8859_4", 31 | "iso8859_5", 32 | "iso8859_6", 33 | "iso8859_7", 34 | "iso8859_8", 35 | "iso8859_9", 36 | "iso8859_10", 37 | "iso8859_11", 38 | "iso8859_13", 39 | "iso8859_14", 40 | "iso8859_15", 41 | "ascii", 42 | "unicode-escape", 43 | ] 44 | 45 | class Language(ChepyCore): 46 | def __init__(self, *data: Any) -> None: ... 47 | state: Any = ... 48 | def search_perl_unicode_props(self: LanguageT, lang: str) -> LanguageT: ... 49 | def find_emojis(self: LanguageT) -> LanguageT: ... 50 | def encode(self: LanguageT, encoding: ENCODINGS, errors: Literal['ignore', 'replace', 'backslashreplace']=...) -> LanguageT: ... 51 | def encode_us_ascii_7_bit(self: LanguageT) -> LanguageT: ... 52 | def decode(self: LanguageT, encoding: ENCODINGS, errors: Literal['ignore', 'replace', 'backslashreplace']=...) -> LanguageT: ... 53 | def remove_diacritics(self: LanguageT) -> LanguageT: ... 54 | def unicode_to_str(self: LanguageT, as_bytes: bool=False) -> LanguageT: ... 55 | def str_to_unicode(self: LanguageT, prefix: Literal['\\u', '%u', 'U+']='\\u', all_chars: bool=False) -> LanguageT: ... 56 | -------------------------------------------------------------------------------- /chepy/modules/links.py: -------------------------------------------------------------------------------- 1 | import base64 2 | from typing import TypeVar 3 | 4 | import regex as re 5 | 6 | from ..core import ChepyCore, ChepyDecorators 7 | 8 | LinksT = TypeVar("LinksT", bound="Links") 9 | 10 | 11 | class Links(ChepyCore): 12 | def __init__(self, *data): 13 | super().__init__(*data) 14 | 15 | @ChepyDecorators.call_stack 16 | def pastebin_to_raw(self) -> LinksT: 17 | """Convert a pastebin link to raw pastebin link 18 | 19 | Returns: 20 | Chepy: The Chepy object. 21 | 22 | Examples: 23 | >>> Chepy("https://pastebin.com/abCD").pastebin_to_raw() 24 | 'https://pastebin.com/raw/abCD' 25 | """ 26 | self.state = re.sub(r"(pastebin\.com)(/)", r"\1/raw\2", self._convert_to_str()) 27 | return self 28 | 29 | @ChepyDecorators.call_stack 30 | def github_to_raw(self) -> LinksT: 31 | """Convert a github link to raw github link 32 | 33 | Returns: 34 | Chepy: The Chepy object. 35 | 36 | Examples: 37 | >>> Chepy("https://github.com/securisec/chepy/blob/master/README.md").github_to_raw() 38 | 'https://raw.githubusercontent.com/securisec/chepy/master/README.md' 39 | """ 40 | self.state = re.sub( 41 | "/blob", 42 | "", 43 | re.sub( 44 | r"(github\.com)(/)", 45 | r"raw.githubusercontent.com\2", 46 | self._convert_to_str(), 47 | ), 48 | ) 49 | return self 50 | 51 | @ChepyDecorators.call_stack 52 | def google_search_ei_to_epoch(self) -> LinksT: 53 | """Convert a google search ei query param to epoch 54 | 55 | Returns: 56 | Chepy: The Chepy object. 57 | 58 | Examples: 59 | >>> Chepy("Bh8hYqykHc64mAXkkoTgCg==").google_search_ei_to_epoch() 60 | 1646337798 61 | """ 62 | decoded = base64.urlsafe_b64decode(self._convert_to_str()) 63 | timestamp = ord(chr(decoded[0])) 64 | timestamp += ord(chr(decoded[1])) * 256 65 | timestamp += ord(chr(decoded[2])) * 256**2 66 | timestamp += ord(chr(decoded[3])) * 256**3 67 | self.state = timestamp 68 | return self 69 | -------------------------------------------------------------------------------- /chepy/modules/links.pyi: -------------------------------------------------------------------------------- 1 | from ..core import ChepyCore 2 | from typing import Any, TypeVar 3 | 4 | LinksT = TypeVar('LinksT', bound='Links') 5 | 6 | class Links(ChepyCore): 7 | def __init__(self, *data: Any) -> None: ... 8 | state: Any = ... 9 | def pastebin_to_raw(self: LinksT) -> LinksT: ... 10 | def github_to_raw(self: LinksT) -> LinksT: ... 11 | def google_search_ei_to_epoch(self: LinksT) -> LinksT: ... 12 | -------------------------------------------------------------------------------- /chepy/modules/networking.py: -------------------------------------------------------------------------------- 1 | import collections 2 | import ipaddress 3 | import socket 4 | import ssl 5 | import urllib.parse as _py_urlparse 6 | from typing import TypeVar 7 | 8 | import regex as re 9 | 10 | from ..core import ChepyCore, ChepyDecorators 11 | 12 | NetworkingT = TypeVar("NetworkingT", bound="Networking") 13 | 14 | 15 | class Networking(ChepyCore): 16 | def __init__(self, *data): 17 | super().__init__(*data) 18 | 19 | @ChepyDecorators.call_stack 20 | def defang_url(self) -> NetworkingT: 21 | """Make a URL harmless 22 | 23 | Takes a Universal Resource Locator (URL) and 'Defangs' it; 24 | meaning the URL becomes invalid, neutralising the risk of accidentally 25 | clicking on a malicious link. This is often used when dealing with 26 | malicious links or IOCs. 27 | 28 | Returns: 29 | Chepy: The Chepy object. 30 | 31 | Examples: 32 | >>> Chepy("https://app.google.com/?lol=some data&a=1").defang_url().o 33 | "hxxps://app[.]google[.]com/?lol=some data&a=1" 34 | """ 35 | self.state = re.sub(r"(^htt)", "hxx", self._convert_to_str()) 36 | self.state = re.sub(r"\.", "[.]", self._convert_to_str()) 37 | return self 38 | 39 | @ChepyDecorators.call_stack 40 | def refang_url(self) -> NetworkingT: 41 | """Refangs a URL so that it is clickable 42 | 43 | Returns: 44 | Chepy: The Chepy object. 45 | 46 | Examples: 47 | >>> Chepy("hxxps://app[.]google[.]com/?lol=some data&a=1").refang_url().o 48 | "https://app.google.com/?lol=some data&a=1" 49 | """ 50 | self.state = re.sub(r"(^hxx)", "htt", self._convert_to_str()) 51 | self.state = re.sub(r"\[\.\]", ".", self._convert_to_str()) 52 | return self 53 | 54 | @ChepyDecorators.call_stack 55 | def defang_ip(self) -> NetworkingT: 56 | """Make an IP address harmless 57 | 58 | Takes a IPv4 or IPv6 address and 'Defangs' it, meaning the 59 | IP becomes invalid, removing the risk of accidentally utilising 60 | it as an IP address. 61 | 62 | Returns: 63 | Chepy: The Chepy object. 64 | 65 | Examples: 66 | >>> Chepy("2001:4860:4860::8844").defang_ip().o 67 | "2001[:]4860[:]4860[:][:]8844" 68 | 69 | >>> Chepy("127.0.0.1").defang_ip().o 70 | "127[.]0[.]0[.]1" 71 | """ 72 | if ":" in self._convert_to_str(): 73 | self.state = re.sub(r":", "[:]", self._convert_to_str()) 74 | else: 75 | self.state = re.sub(r"\.|:", "[.]", self._convert_to_str()) 76 | return self 77 | 78 | @ChepyDecorators.call_stack 79 | def refang_ip(self) -> NetworkingT: 80 | """Refangs an IP address 81 | 82 | Returns: 83 | Chepy: The Chepy object. 84 | 85 | Examples: 86 | >>> Chepy("127[.]0[.]0[.]1").refang_ip().o 87 | "127.0.0.1" 88 | """ 89 | self.state = re.sub(r"\[\.\]|\[\:\]", ".", self._convert_to_str()) 90 | return self 91 | 92 | @ChepyDecorators.call_stack 93 | def parse_uri(self) -> NetworkingT: 94 | """Parse a URI 95 | 96 | Returns: 97 | Chepy: The Chepy object. 98 | 99 | Examples: 100 | >>> Chepy("http://example.com/resource?foo=bar#fragment").parse_uri().o 101 | { 102 | "scheme": "http", 103 | "location": "example.com", 104 | "path": "/resource", 105 | "params": "", 106 | "query": {"foo": ["bar"]}, 107 | "fragment": "fragment", 108 | } 109 | """ 110 | parsed = _py_urlparse.urlparse(self._convert_to_str()) 111 | self.state = { 112 | "scheme": parsed.scheme, 113 | "location": parsed.netloc, 114 | "path": parsed.path, 115 | "params": parsed.params, 116 | "query": _py_urlparse.parse_qs(parsed.query), 117 | "fragment": parsed.fragment, 118 | } 119 | return self 120 | 121 | @ChepyDecorators.call_stack 122 | def parse_ip_range(self) -> NetworkingT: 123 | """Enumerate IP address in a CIDR range 124 | 125 | Returns: 126 | Chepy: The Chepy object. 127 | 128 | Examples: 129 | >>> Chepy("10.10.10.1/24").parse_ip_range().o 130 | [ 131 | "10.10.10.1", 132 | "10.10.10.2, 133 | ... 134 | "10.10.10.254" 135 | ] 136 | """ 137 | self.state = [ 138 | str(i) 139 | for i in ipaddress.ip_network(self._convert_to_str(), strict=False).hosts() 140 | ] 141 | return self 142 | 143 | @ChepyDecorators.call_stack 144 | def parse_ipv6(self) -> NetworkingT: 145 | """Get longhand and shorthand of IPv6 146 | 147 | Returns: 148 | Chepy: The Chepy object. 149 | 150 | Examples: 151 | >>> Chepy("2001:4860:4860::8888").parse_ipv6().o 152 | { 153 | "long": "2001:4860:4860:0000:0000:0000:0000:8888", 154 | "short": "2001:4860:4860::8888", 155 | } 156 | """ 157 | ip = ipaddress.ip_address(self._convert_to_str()) 158 | self.state = {"long": ip.exploded, "short": ip.compressed} 159 | return self 160 | 161 | @ChepyDecorators.call_stack 162 | def get_ssl_cert(self, port: int = 443) -> NetworkingT: 163 | """Get the server side SSL certificate for a domain 164 | 165 | Args: 166 | port (int, optional): Server port. Defaults to 443. 167 | 168 | Returns: 169 | Chepy: The Chepy object 170 | 171 | Examples: 172 | >>> Chepy('google.com').get_ssl_cert().o 173 | { 174 | 'subject': { 175 | 'commonName': '*.google.com', 176 | 'organizationName': 'Google LLC', 177 | ... 178 | 'caIssuers': ('http://pki.goog/gsr2/GTS1O1.crt',), 179 | 'crlDistributionPoints': ('http://crl.pki.goog/GTS1O1.crl',) 180 | } 181 | """ 182 | domain = re.sub(r"^\w+://", "", self._convert_to_str()) 183 | with socket.create_connection((domain, port)) as sock: 184 | context = ssl.create_default_context() 185 | context.check_hostname = False 186 | with context.wrap_socket(sock, server_hostname=domain) as sslsock: 187 | cert = sslsock.getpeercert() 188 | final = {} 189 | for key in cert.keys(): 190 | if key == "subject" or key == "issuer": 191 | final[key] = dict( 192 | collections.ChainMap(*list(map(dict, cert[key]))) 193 | ) 194 | elif key == "subjectAltName": 195 | final[key] = list( 196 | map(lambda x: dict([x]), cert["subjectAltName"]) 197 | ) 198 | else: 199 | final[key] = cert[key] 200 | self.state = final 201 | return self 202 | 203 | @ChepyDecorators.call_stack 204 | def int_to_ip(self) -> NetworkingT: 205 | """Convert an integer to an IP address 206 | 207 | Returns: 208 | Chepy: The Chepy object. 209 | 210 | Examples: 211 | >>> Chepy(3232235777).int_to_ip().o 212 | """ 213 | self.state = str(ipaddress.ip_address(self._convert_to_int())) 214 | return self 215 | 216 | @ChepyDecorators.call_stack 217 | def ip_to_int(self) -> NetworkingT: 218 | """Convert an integer to an IP address 219 | 220 | Returns: 221 | Chepy: The Chepy object. 222 | 223 | Examples: 224 | >>> Chepy(3232235777).int_to_ip().o 225 | """ 226 | self.state = int(ipaddress.ip_address(self._convert_to_str())) 227 | return self 228 | -------------------------------------------------------------------------------- /chepy/modules/networking.pyi: -------------------------------------------------------------------------------- 1 | from ..core import ChepyCore 2 | from typing import Any, TypeVar 3 | 4 | NetworkingT = TypeVar('NetworkingT', bound='Networking') 5 | 6 | class Networking(ChepyCore): 7 | def __init__(self, *data: Any) -> None: ... 8 | state: Any = ... 9 | def defang_url(self: NetworkingT) -> NetworkingT: ... 10 | def refang_url(self: NetworkingT) -> NetworkingT: ... 11 | def defang_ip(self: NetworkingT) -> NetworkingT: ... 12 | def refang_ip(self: NetworkingT) -> NetworkingT: ... 13 | def parse_uri(self: NetworkingT) -> NetworkingT: ... 14 | def parse_ip_range(self: NetworkingT) -> NetworkingT: ... 15 | def parse_ipv6(self: NetworkingT) -> NetworkingT: ... 16 | def int_to_ip(self: NetworkingT) -> NetworkingT: ... 17 | def ip_to_int(self: NetworkingT) -> NetworkingT: ... 18 | def get_ssl_cert(self: NetworkingT, port: int=...) -> NetworkingT: ... 19 | -------------------------------------------------------------------------------- /chepy/modules/other.py: -------------------------------------------------------------------------------- 1 | from typing import TypeVar 2 | from uuid import uuid4 3 | 4 | from ..core import ChepyCore, ChepyDecorators 5 | 6 | OtherT = TypeVar("OtherT", bound="Other") 7 | 8 | 9 | class Other(ChepyCore): 10 | def __init__(self, *data): 11 | super().__init__(*data) 12 | 13 | @ChepyDecorators.call_stack 14 | def generate_uuid(self) -> OtherT: 15 | """Generate v4 UUID 16 | 17 | Generates an RFC 4122 version 4 compliant Universally Unique Identifier 18 | (UUID), also known as a Globally Unique Identifier (GUID). A version 4 19 | UUID relies on random numbers 20 | 21 | Returns: 22 | str: A random UUID 23 | 24 | Examples: 25 | >>> Chepy('').generate_uuid() 26 | 92644a99-632a-47c1-b169-5a141172924b 27 | """ 28 | self.state = str(uuid4()) 29 | return self 30 | -------------------------------------------------------------------------------- /chepy/modules/other.pyi: -------------------------------------------------------------------------------- 1 | from ..core import ChepyCore 2 | from typing import Any, TypeVar 3 | 4 | OtherT = TypeVar('OtherT', bound='Other') 5 | 6 | class Other(ChepyCore): 7 | def __init__(self, *data: Any) -> None: ... 8 | state: Any = ... 9 | def generate_uuid(self: OtherT) -> OtherT: ... 10 | -------------------------------------------------------------------------------- /chepy/modules/publickey.pyi: -------------------------------------------------------------------------------- 1 | from ..core import ChepyCore 2 | from typing import Any, Literal, TypeVar, Union 3 | 4 | RSA: Any 5 | OpenSSL: Any 6 | PublickeyT = TypeVar('PublickeyT', bound='Publickey') 7 | 8 | class Publickey(ChepyCore): 9 | def __init__(self, *data: Any) -> None: ... 10 | state: Any = ... 11 | def parse_x509_pem(self: PublickeyT) -> PublickeyT: ... 12 | def parse_x509_der_hex(self: PublickeyT) -> PublickeyT: ... 13 | def public_from_x509(self: PublickeyT) -> PublickeyT: ... 14 | def pem_to_der_hex(self: PublickeyT) -> PublickeyT: ... 15 | def der_hex_to_pem(self: PublickeyT) -> PublickeyT: ... 16 | def parse_public_pem(self: PublickeyT) -> PublickeyT: ... 17 | def parse_private_pem(self: PublickeyT) -> PublickeyT: ... 18 | def dump_pkcs12_cert(self: PublickeyT, password: Union[str, bytes]) -> PublickeyT: ... 19 | def generate_rsa_keypair(self: PublickeyT, bits:int=..., format:str=..., passphrase:str=...) -> PublickeyT: ... 20 | def generate_ecc_keypair(self: PublickeyT, curve:Literal['p256', 'p384', 'p521']='p256', format:Literal['PEM', 'DER']='PEM') -> PublickeyT: ... 21 | -------------------------------------------------------------------------------- /chepy/modules/search.py: -------------------------------------------------------------------------------- 1 | from typing import TypeVar, Union 2 | 3 | import regex as re 4 | 5 | from ..core import ChepyCore, ChepyDecorators 6 | 7 | SearchT = TypeVar("SearchT", bound="Search") 8 | 9 | 10 | class Search(ChepyCore): 11 | def __init__(self, *data): 12 | super().__init__(*data) 13 | 14 | """Class that is geared towards regex searches of secrets 15 | 16 | `Reference `__ 17 | """ 18 | 19 | @ChepyDecorators.call_stack 20 | def search(self, pattern: Union[str, bytes]) -> SearchT: 21 | """Search. Group matches are returned as tuples. 22 | 23 | Args: 24 | pattern (Union[str, bytes]): Bytes pattern to search 25 | 26 | Returns: 27 | Chepy: The Chepy object. 28 | 29 | Examples: 30 | >>> Chepy("abcdefg123 and again abcdefg123").search("abc(de)fg(12)(3)").o 31 | [('abcdefg123', 'de', '12', '3'), ('abcdefg123', 'de', '12', '3')] 32 | """ 33 | pattern = self._str_to_bytes(pattern) 34 | self.state = re.findall(pattern, self._convert_to_bytes()) 35 | return self 36 | 37 | @ChepyDecorators.call_stack 38 | def search_list(self, pattern: Union[str, bytes]) -> SearchT: 39 | """Search all items in a list. List items are coerced into bytes first. 40 | Group matches are returned as tuples. 41 | 42 | Args: 43 | pattern (Union[str, bytes]): Bytes pattern to search 44 | 45 | Returns: 46 | Chepy: The Chepy object. 47 | """ 48 | assert isinstance(self.state, list), "State is not a list" 49 | 50 | converted = [self._to_bytes(s) for s in self.state] 51 | pattern = self._str_to_bytes(pattern) 52 | pc = re.compile(pattern) 53 | 54 | hold = [] 55 | for search in converted: 56 | matches = pc.findall(search) 57 | if len(matches) > 0: 58 | hold.append(matches) 59 | 60 | self.state = hold 61 | return self 62 | 63 | @ChepyDecorators.call_stack 64 | def search_ctf_flags(self, prefix: str, postfix: str = ".+?\\{*\\}") -> SearchT: 65 | """Search CTF style flags. 66 | 67 | This by default assumes that the flag format is similar 68 | to something like picoCTF{some_flag} as an example. 69 | 70 | Args: 71 | prefix (str): Prefix of the flag. Like `picoCTF` 72 | postfix (str, optional): Regex for the remainder of the flag. 73 | Defaults to '.+\\{.+\\}'. 74 | 75 | Returns: 76 | Chepy: The Chepy object. 77 | 78 | Examples: 79 | >>> Chepy("tests/files/flags").read_file().search_ctf_flags("pico").get_by_index(0) 80 | picoCTF{r3source_pag3_f1ag} 81 | """ 82 | self.state = re.findall(prefix + postfix, self._convert_to_str(), re.IGNORECASE) 83 | return self 84 | 85 | @ChepyDecorators.call_stack 86 | def search_slack_tokens(self) -> SearchT: 87 | """Search slack tokens 88 | 89 | Returns: 90 | Chepy: The Chepy object. 91 | 92 | Examples: 93 | >>> Chepy("tests/files/flags").read_file().search_slack_tokens().get_by_index(0) 94 | xoxp...859 95 | """ 96 | self.state = re.findall( 97 | "(xox[p|b|o|a]-[0-9]{12}-[0-9]{12}-[0-9]{12}-[a-z0-9]{32})", 98 | self._convert_to_str(), 99 | ) 100 | return self 101 | 102 | @ChepyDecorators.call_stack 103 | def search_slack_webhook(self) -> SearchT: 104 | """Search slack webhook 105 | 106 | Returns: 107 | Chepy: The Chepy object. 108 | """ 109 | self.state = re.findall( 110 | r"https://hooks\.slack\.com/services/T[a-zA-Z0-9_]{8}/B[a-zA-Z0-9_]{8}/[a-zA-Z0-9_]{24}", 111 | self._convert_to_str(), 112 | ) 113 | return self 114 | 115 | @ChepyDecorators.call_stack 116 | def search_private_key(self) -> SearchT: 117 | """Search varios private key headers 118 | 119 | Returns: 120 | Chepy: The Chepy object. 121 | """ 122 | self.state = re.findall( 123 | "-----BEGIN (RSA|OPENSSH|DSA|EC) PRIVATE KEY-----", self._convert_to_str() 124 | ) 125 | return self 126 | 127 | @ChepyDecorators.call_stack 128 | def search_twilio_key(self) -> SearchT: 129 | """Search for Twilio api key 130 | 131 | Returns: 132 | Chepy: The Chepy object. 133 | """ 134 | self.state = re.findall("SK[a-z0-9]{32}", self._convert_to_str()) 135 | return self 136 | 137 | @ChepyDecorators.call_stack 138 | def search_aws_key(self) -> SearchT: 139 | """Search for AWS key id 140 | 141 | Returns: 142 | Chepy: The Chepy object. 143 | """ 144 | self.state = re.findall("AKIA[0-9A-Z]{16}", self._convert_to_str()) 145 | return self 146 | -------------------------------------------------------------------------------- /chepy/modules/search.pyi: -------------------------------------------------------------------------------- 1 | from ..core import ChepyCore 2 | from typing import Any, TypeVar, Union 3 | 4 | SearchT = TypeVar('SearchT', bound='Search') 5 | 6 | class Search(ChepyCore): 7 | def __init__(self, *data: Any) -> None: ... 8 | state: Any = ... 9 | def search(self: SearchT, pattern: Union[str, bytes]) -> SearchT: ... 10 | def search_list(self: SearchT, pattern: Union[str, bytes]) -> SearchT: ... 11 | def search_ctf_flags(self: SearchT, prefix: str, postfix: str=...) -> SearchT: ... 12 | def search_slack_tokens(self: SearchT) -> SearchT: ... 13 | def search_slack_webhook(self: SearchT) -> SearchT: ... 14 | def search_private_key(self: SearchT) -> SearchT: ... 15 | def search_twilio_key(self: SearchT) -> SearchT: ... 16 | def search_aws_key(self: SearchT) -> SearchT: ... 17 | -------------------------------------------------------------------------------- /chepy/modules/utils.pyi: -------------------------------------------------------------------------------- 1 | from ..core import ChepyCore 2 | from typing import Any, Literal, TypeVar, Union 3 | 4 | UtilsT = TypeVar('UtilsT', bound='Utils') 5 | 6 | class Utils(ChepyCore): 7 | def __init__(self, *data: Any) -> None: ... 8 | state: Any = ... 9 | def reverse(self: UtilsT, count: int=...) -> UtilsT: ... 10 | def count_occurances(self: UtilsT, regex: str, case_sensitive: bool=...) -> UtilsT: ... 11 | def remove_whitespace(self: UtilsT, spaces: bool=..., carriage_return: bool=..., line_feeds: bool=..., tabs: bool=..., form_feeds: bool=...) -> UtilsT: ... 12 | def remove_nullbytes(self: UtilsT) -> UtilsT: ... 13 | def regex_search(self: UtilsT, pattern: str, is_bytes: bool=False, ignore_case: bool=False, multiline: bool=False, dotall: bool=False, unicode: bool=False, extended: bool=False) -> UtilsT: ... 14 | def split_by_char(self: UtilsT, delimiter: str=...) -> UtilsT: ... 15 | def split_by_regex(self: UtilsT, pattern: str=..., trim: Any=...) -> UtilsT: ... 16 | def split_by_n(self: UtilsT, n: int) -> UtilsT: ... 17 | def split_lines(self: UtilsT) -> UtilsT: ... 18 | def split_chunks(self: UtilsT, chunk_size: int) -> UtilsT: ... 19 | def select_every_n(self: UtilsT, n: int, start: int=...) -> UtilsT: ... 20 | def unique(self: UtilsT) -> UtilsT: ... 21 | def sort_list(self: UtilsT, reverse: bool=...) -> UtilsT: ... 22 | def sort_dict_key(self: UtilsT, reverse: bool=...) -> UtilsT: ... 23 | def sort_dict_value(self: UtilsT, reverse: Any=...) -> UtilsT: ... 24 | def filter_list(self: UtilsT, by: Union[str, dict], regex: bool=...) -> UtilsT: ... 25 | def filter_list_by_length(self: UtilsT, length: int, exact: bool=...) -> UtilsT: ... 26 | def filter_dict_key(self: UtilsT, by: str) -> UtilsT: ... 27 | def filter_dict_value(self: UtilsT, by: str) -> UtilsT: ... 28 | def slice(self: UtilsT, start: int=..., end: int=...) -> UtilsT: ... 29 | def strip_ansi(self: UtilsT) -> UtilsT: ... 30 | def strip(self: UtilsT, pattern: str, ignore_case: bool=...) -> UtilsT: ... 31 | def strip_non_printable(self: UtilsT) -> UtilsT: ... 32 | def find_replace(self: UtilsT, pattern: Union[bytes, str], repl: Union[bytes, str], ignore_case: bool=...) -> UtilsT: ... 33 | def escape_string(self: UtilsT) -> UtilsT: ... 34 | def unescape_string(self: UtilsT) -> UtilsT: ... 35 | def color_hex_to_rgb(self: UtilsT) -> UtilsT: ... 36 | def diff(self: UtilsT, state: int=..., buffer: int=..., colors: bool=False, swap: bool=False, only_changes: bool=False) -> UtilsT: ... 37 | def pad(self: UtilsT, width: int, direction: Literal['left', 'right']=..., char: str=...) -> UtilsT: ... 38 | def count(self: UtilsT) -> UtilsT: ... 39 | def set(self: UtilsT) -> UtilsT: ... 40 | def regex_to_str(self: UtilsT, all_combo: bool=...) -> UtilsT: ... 41 | def shuffle(self: UtilsT) -> UtilsT: ... 42 | def drop_bytes(self: UtilsT, start: int, length: int) -> UtilsT: ... 43 | def without(self: UtilsT, *values: Any) -> UtilsT: ... 44 | def pick(self: UtilsT, *values: Any) -> UtilsT: ... 45 | def expand_alpha_range(self: UtilsT, join_by: Union[str, None]=None) -> UtilsT: ... 46 | def split_and_count(self: UtilsT, pattern: Union[str, bytes], threshold: int=None) -> UtilsT: ... 47 | -------------------------------------------------------------------------------- /cli.py: -------------------------------------------------------------------------------- 1 | from chepy.__main__ import main 2 | 3 | if __name__ == "__main__": 4 | main() 5 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/assets/cc_encoding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/docs/assets/cc_encoding.png -------------------------------------------------------------------------------- /docs/assets/clicolors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/docs/assets/clicolors.png -------------------------------------------------------------------------------- /docs/assets/ctf.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/docs/assets/ctf.gif -------------------------------------------------------------------------------- /docs/assets/hmac_hash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/docs/assets/hmac_hash.png -------------------------------------------------------------------------------- /docs/assets/plugin.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/docs/assets/plugin.gif -------------------------------------------------------------------------------- /docs/chepy.md: -------------------------------------------------------------------------------- 1 | # Chepy Class 2 | 3 | The **Chepy** class in the main class for Chepy, and includes all the methods from all the different classes under modules. This class takes ***args** as its argument, and each argument that is passed to it becomes its own state. 4 | 5 | ```python 6 | >>> from chepy import Chepy 7 | >>> c = Chepy("some data", "/some/path/file") 8 | >>> c.states 9 | {0: "some data", 1: "/some/path/file"} 10 | ``` 11 | 12 | ```eval_rst 13 | .. automodule:: chepy 14 | :members: 15 | :inherited-members: 16 | ``` -------------------------------------------------------------------------------- /docs/cli.md: -------------------------------------------------------------------------------- 1 | # Chepy CLI 2 | 3 | Chepy CLI is a fully dynamically generated cli that combines the power for python-fire and prompt_toolkit to create its cli. The cli is used very similar to how the main `Chepy` class is used as it allows for method chaining. We know from the docs that some of the methods in the `Chepy` class takes optional or required arguments. In the cli, these are passed as flags. Refer to the [examples](./examples.md) for use cases. 4 | 5 | ## Cli options 6 | ```bash 7 | usage: chepy [-h] [-v] [-r RECIPE] [data [data ...]] 8 | 9 | positional arguments: 10 | data 11 | 12 | optional arguments: 13 | -h, --help show this help message and exit 14 | -v, --version show program's version number and exit 15 | -r RECIPE, --recipe RECIPE 16 | ``` 17 | 18 | ## Cli magic markers 19 | There are three special characters in the cli. 20 | 21 | - `!` If a line begins with `!` it is interpreted as a shell command. For example: `! ls -la` 22 | - `#` If a line begins with `#` it is interpreted as a comment. For example: `# hello` 23 | - `?` If a line begins with `?` it provides help for the provided Chepy method. For example: `? to_hex` 24 | 25 | ### Cli Recipes 26 | The cli can be run in a non interactive mode using the `-r` flag. This flag will load the recipe that is supplied and run it on the arguments that is provided. 27 | 28 | ```bash 29 | # Example 30 | chepy -r test.recipe a.png 31 | ``` 32 | 33 | ### Using builtins 34 | 35 | One of the more advanced functions of the cli allows the user to use arbitrary builtin methods when the state does not contain a Chepy object. 36 | 37 | Consider this example in code. We will parse a User agent string in this case: 38 | ```python 39 | >>> ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36" 40 | >>> c = Chepy(ua).parse_user_agent() 41 | {'user_agent': {'family': 'Other', 'major': None, 'minor': None, 'patch': None}, 'os': {'family': 'Other', 'major': None, 'minor': None, 'patch': None, 'patch_minor': None}, 'device': {'family': 'Other', 'brand': None, 'model': None}, 'string': 'ua'} 42 | # The state type currently is Chepy 43 | >>> c.o 44 | # The state type now is a dict 45 | >>> c.get("user_agent").get("family") 46 | "Chrome" 47 | # we are using the dict builtin method get to pull the values based on keys 48 | ``` 49 | 50 | This same behavior is replicated in the Chepy cli. 51 | 52 | [![asciicast](https://asciinema.org/a/BTBg3PLFeiN21UBcpjYxWWLnc.svg)](https://asciinema.org/a/BTBg3PLFeiN21UBcpjYxWWLnc) 53 | 54 | ### Cli only methods 55 | For completeness sake everything is document here, but the only functions that are callable from the CLI are functions that start with `cli_`. 56 | 57 | ### Cli shell commands 58 | It is possible to run shell commands from the cli py starting the command with a `!`. 59 | 60 | ```bash 61 | >>> !ls -la | grep py 62 | ``` 63 | This will run the following command inside the Chepy cli 64 | 65 | ```eval_rst 66 | .. automodule:: chepy.modules.internal.cli 67 | :members: 68 | ``` -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | import os 14 | import sys 15 | from recommonmark.transform import AutoStructify 16 | 17 | sys.path.insert(0, os.path.abspath(".")) 18 | 19 | 20 | def setup(app): 21 | app.add_config_value( 22 | "recommonmark_config", 23 | { 24 | "enable_eval_rst": True, 25 | }, 26 | True, 27 | ) 28 | app.add_transform(AutoStructify) 29 | 30 | 31 | # -- Project information ----------------------------------------------------- 32 | 33 | project = "Chepy" 34 | copyright = "2025, @securisec" 35 | author = "@securisec" 36 | 37 | master_doc = "index" 38 | 39 | 40 | # -- General configuration --------------------------------------------------- 41 | 42 | # Add any Sphinx extension module names here, as strings. They can be 43 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 44 | # ones. 45 | extensions = ["sphinx.ext.autodoc", "sphinx.ext.napoleon", "recommonmark"] 46 | 47 | # Add any paths that contain templates here, relative to this directory. 48 | templates_path = ["_templates"] 49 | 50 | # List of patterns, relative to source directory, that match files and 51 | # directories to ignore when looking for source files. 52 | # This pattern also affects html_static_path and html_extra_path. 53 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] 54 | 55 | 56 | # -- Options for HTML output ------------------------------------------------- 57 | 58 | # The theme to use for HTML and HTML Help pages. See the documentation for 59 | # a list of builtin themes. 60 | # 61 | html_theme = "alabaster" 62 | html_logo = "../logo.png" 63 | 64 | html_theme_options = {"fixed_sidebar": False} 65 | 66 | # Add any paths that contain custom static files (such as style sheets) here, 67 | # relative to this directory. They are copied after the builtin static files, 68 | # so a file named "default.css" will overwrite the builtin "default.css". 69 | html_static_path = ["_static"] 70 | 71 | autodoc_member_order = "groupwise" 72 | 73 | source_suffix = { 74 | ".rst": "restructuredtext", 75 | ".txt": "markdown", 76 | ".md": "markdown", 77 | } 78 | 79 | -------------------------------------------------------------------------------- /docs/config.md: -------------------------------------------------------------------------------- 1 | # Config 2 | 3 | Chepy is set to look at the present working directory for a a folder called **.chepy** for config files. By default, Chepy config files are stored in a folder called **.chepy** in the users home directory. There are two files in it. 4 | 5 | If any of the config options are missing, Chepy will automatically assign default values to it. If **.chepy** folder is detected, but config options have been set, then Chepy will automatically create a set of default config options. 6 | 7 | ## chepy.conf 8 | ### Plugin.enableplugins 9 | This should be set to either `true` or `false` to control if plugins should be loaded by Chepy. This can be optionally controlled via the `CHEPY_PLUGINS` environment variable. Valid values are `true` and `false`. 10 | ### Plugin.pluginpath 11 | This path controls where chepy will look for plugins and extensions. For more information, see [plugins](/plugins) 12 | 13 | ### Cli.history_path 14 | Path where the chepy cli history is stored. Defaults to *USERHOME/.chepy/chepy_history* 15 | ### Cli.prompt_colors 16 | Controls the colors of **>>>** in chepy prompt. Should be space seperated 3 hex color codes. Defaults to *#00ffff #ff0000 #ffd700* 17 | ### Cli.show_rprompt 18 | Controls visibility of the right prompt. Value should be *true* or *false*. Defaults to *false*. 19 | ### Cli.prompt_rprompt 20 | Controls the colors of of the right prompt. Defaults to *#00ff48* 21 | ### Cli.prompt_bottom_toolbar 22 | Controls the color of the bottom toolbar. Defaults to *#000000* 23 | ### Cli.prompt_toolbar_version 24 | Controls the color of the version in the toolbar. Defaults to *#00ff48* 25 | ### Cli.prompt_toolbar_states 26 | Controls the color of the states in the toolbar. Defaults to *#60cdd5* 27 | ### Cli.prompt_toolbar_buffers 28 | Controls the color of the buffers in the toolbar. Defaults to *#ff00ff* 29 | ### Cli.prompt_toolbar_type 30 | Controls the color of the current state type in the toolbar. Defaults to *#ffd700* 31 | ### Cli.prompt_toolbar_errors 32 | Controls the color of the errors in the toolbar. Defaults to *#ff0000* 33 | ### Cli.prompt_cli_method 34 | Controls the color of the cli methods. Defaults to *#00d700* 35 | ### Cli.prompt_plugin_method 36 | Controls the color of the plugin methods. Defaults to *#30d8ff* 37 | ### Cli.cli_info_color 38 | Controls the color of the output from `cli_*` methods. Defaults to *#ffb4ad* 39 | ### Cli.prompt_search_background 40 | Background background color for cli selection. Defaults to *#00aaaa #000000* 41 | ### Cli.prompt_search_fuzzy 42 | Background background color for cli fuzzy match. Defaults to *#00aaaa* 43 | 44 | 45 | ### chepy_history 46 | This file saves the history of all the commands in that have been run in the chepy cli. 47 | 48 | ### Valid chepy.conf file contents 49 | ``` 50 | [Plugins] 51 | enableplugins = false 52 | pluginpath = /path/to/chepy_install/chepy/chepy/chepy_plugins 53 | 54 | [Cli] 55 | history_path = /path/to/home/.chepy/chepy_history 56 | prompt_char = > 57 | prompt_colors = #00ffff #ff0000 #ffd700 58 | show_rprompt = false 59 | prompt_rprompt = #00ff48 60 | prompt_bottom_toolbar = #000000 61 | prompt_toolbar_version = #00ff48 62 | prompt_toolbar_states = #60cdd5 63 | prompt_toolbar_buffers = #ff00ff 64 | prompt_toolbar_type = #ffd700 65 | prompt_toolbar_errors = #ff0000 66 | ``` 67 | -------------------------------------------------------------------------------- /docs/core.md: -------------------------------------------------------------------------------- 1 | # ChepyCore class 2 | 3 | The `ChepyCore` class for Chepy is primarily used as an interface for all the current modules/classes in Chepy, or for plugin development. The `ChepyCore` class is what provides the various attributes like **states**, **buffers**, etc and is required to use and extend Chepy. 4 | 5 | The most important `ChepyCore` attributes and methods are: 6 | - **state** The state is where all objects are always stored when modified by any methods. 7 | - **\_convert_to_*** methods These are helper methods that ensures data is being accessed and put in the state in the correct manner. For example, `binasii.unhexlify` requires a bytes like object. We can use 8 | ``` 9 | self.state = binasii.unhexlify(self._convert_to_bytes()) 10 | ``` 11 | This will ensure that the correct data type is being used at all times. 12 | 13 | ```eval_rst 14 | .. automodule:: chepy.core 15 | :members: 16 | :undoc-members: 17 | :private-members: 18 | ``` 19 | -------------------------------------------------------------------------------- /docs/extras.rst: -------------------------------------------------------------------------------- 1 | Extras 2 | ====== 3 | 4 | Bruteforce 5 | """""""""" 6 | .. automodule:: chepy.extras.bruteforce 7 | :members: 8 | 9 | Combinations 10 | """""""""""" 11 | .. automodule:: chepy.extras.combinatons 12 | :members: 13 | 14 | Crypto 15 | """""" 16 | .. automodule:: chepy.extras.crypto_extras 17 | :members: 18 | 19 | Misc 20 | """" 21 | .. automodule:: chepy.extras.misc 22 | :members: -------------------------------------------------------------------------------- /docs/faq.md: -------------------------------------------------------------------------------- 1 | # FAQ 2 | 3 | ## Chepy is failing to load due to a config issue. 4 | Chepy is in constant development, and in future versions, it is quite possible that new options are included for the chepy.conf file. If you are facing an issue with config keys failing to load, delete the `$HOME/.chepy/chepy.conf` file. On next load, Chepy will set a valid working conf file. 5 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | ../README.md -------------------------------------------------------------------------------- /docs/internal.rst: -------------------------------------------------------------------------------- 1 | Chepy Internal 2 | ============== 3 | 4 | Colors 5 | """""" 6 | .. automodule:: chepy.modules.internal.colors 7 | :members: 8 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/modules.rst: -------------------------------------------------------------------------------- 1 | Modules 2 | ======= 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Contents: 7 | 8 | modules/aritmeticlogic.rst 9 | modules/codetidy.rst 10 | modules/compression.rst 11 | modules/dataformat.rst 12 | modules/datetimemodule.rst 13 | modules/encryptionencoding.rst 14 | modules/extractors.rst 15 | modules/hashing.rst 16 | modules/language.rst 17 | modules/links.rst 18 | modules/multimedia.rst 19 | modules/networking.rst 20 | modules/other.rst 21 | modules/publickey.rst 22 | modules/utils.rst 23 | internal.rst 24 | 25 | 26 | Exceptions 27 | """""""""" 28 | .. automodule:: chepy.modules.exceptions 29 | :members: 30 | -------------------------------------------------------------------------------- /docs/modules/aritmeticlogic.rst: -------------------------------------------------------------------------------- 1 | AritmeticLogic 2 | """""""""""""" 3 | .. autoclass:: chepy.modules.aritmeticlogic.AritmeticLogic 4 | :members: -------------------------------------------------------------------------------- /docs/modules/codetidy.rst: -------------------------------------------------------------------------------- 1 | CodeTidy 2 | """""""" 3 | .. autoclass:: chepy.modules.codetidy.CodeTidy 4 | :members: -------------------------------------------------------------------------------- /docs/modules/compression.rst: -------------------------------------------------------------------------------- 1 | Compression 2 | """"""""""" 3 | .. autoclass:: chepy.modules.compression.Compression 4 | :members: -------------------------------------------------------------------------------- /docs/modules/dataformat.rst: -------------------------------------------------------------------------------- 1 | DataFormat 2 | """""""""" 3 | .. autoclass:: chepy.modules.dataformat.DataFormat 4 | :members: -------------------------------------------------------------------------------- /docs/modules/datetimemodule.rst: -------------------------------------------------------------------------------- 1 | DateTime 2 | """""""" 3 | .. autoclass:: chepy.modules.datetimemodule.DateTime 4 | :members: -------------------------------------------------------------------------------- /docs/modules/encryptionencoding.rst: -------------------------------------------------------------------------------- 1 | 2 | EncryptionEncoding 3 | """""""""""""""""" 4 | .. autoclass:: chepy.modules.encryptionencoding.EncryptionEncoding 5 | :members: -------------------------------------------------------------------------------- /docs/modules/extractors.rst: -------------------------------------------------------------------------------- 1 | Extractors 2 | """""""""" 3 | .. autoclass:: chepy.modules.extractors.Extractors 4 | :members: -------------------------------------------------------------------------------- /docs/modules/hashing.rst: -------------------------------------------------------------------------------- 1 | Hashing 2 | """"""" 3 | .. autoclass:: chepy.modules.hashing.Hashing 4 | :members: 5 | -------------------------------------------------------------------------------- /docs/modules/language.rst: -------------------------------------------------------------------------------- 1 | Language 2 | """""""" 3 | .. autoclass:: chepy.modules.language.Language 4 | :members: -------------------------------------------------------------------------------- /docs/modules/links.rst: -------------------------------------------------------------------------------- 1 | Links 2 | """""""""""""" 3 | .. autoclass:: chepy.modules.links.Links 4 | :members: -------------------------------------------------------------------------------- /docs/modules/multimedia.rst: -------------------------------------------------------------------------------- 1 | Multimedia 2 | """""""""" 3 | .. autoclass:: chepy.modules.multimedia.Multimedia 4 | :members: -------------------------------------------------------------------------------- /docs/modules/networking.rst: -------------------------------------------------------------------------------- 1 | 2 | Networking 3 | """""""""" 4 | .. autoclass:: chepy.modules.networking.Networking 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/modules/other.rst: -------------------------------------------------------------------------------- 1 | 2 | Other 3 | """"" 4 | .. autoclass:: chepy.modules.other.Other 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/modules/publickey.rst: -------------------------------------------------------------------------------- 1 | 2 | Publickey 3 | """"""""" 4 | .. autoclass:: chepy.modules.publickey.Publickey 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/modules/utils.rst: -------------------------------------------------------------------------------- 1 | 2 | Utils 3 | """"" 4 | .. autoclass:: chepy.modules.utils.Utils 5 | :members: -------------------------------------------------------------------------------- /docs/plugins.md: -------------------------------------------------------------------------------- 1 | # Chepy Plugins 2 | 3 | Chepy allows users to extend Chepy and add plugins to it. This documentation describes how to create or load plugins in Chepy. For current official Chepy plugins, [refer to this docs](https://chepy-plugins.readthedocs.io/en/latest/), or [this repo](https://github.com/securisec/chepy_plugins). These plugins are disabled by default, but can be enabled using the config file. If an import requirement fails for any of the built in plugins, it will show a message showing which one failed. 4 | 5 | To use the existing plugin path directory, use `cli_plugin_path` from the cli to identify the plugin path, or refer to the chepy.conf file. 6 | 7 | ## chepy.conf file 8 | The chepy.conf file is what controls various aspects of how chepy runs. This file can be located in the users home directory. Plugins can be enabled or disabled with `Plugins.enableplugins` in the **chepy.conf** file. 9 | 10 | The default Chepy conf file on setup looks like this: 11 | 12 | ```bash 13 | [Plugins] 14 | enableplugins = true 15 | pluginpath = None 16 | # this needs to be an absolute path. Plugins are loaded from this directory 17 | 18 | [Cli] 19 | historypath = /home/hapsida/.chepy/chepy_history 20 | # controls where the Chepy cli history is saved. This path will be set to 21 | # the users home dir automatically on setup. 22 | ``` 23 | 24 | ## Plugins folder location 25 | The location of the plugins folder can be found in the `chepy.conf` file. To use custom plugins, set the value of `pluginpath` in this file. 26 | 27 | ```bash 28 | [Plugin] 29 | pluginpath = /some/dir/ 30 | ``` 31 | 32 | Chepy will attempt to read the plugins folder (if one is set) to resolve any plugins from it. 33 | 34 | ## Creating plugins 35 | ### Naming plugins 36 | Because Chepy utilizes name spaces to load its plugins, all plugin files needs to be named as **chepy_some_plugin.py**. This ensures that there are no namespace conflicts. 37 | 38 | Plugin files should be placed in the directory that is specified by the `pluginpath` in chepy.conf 39 | https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html 40 | ### Plugin module 41 | All Chepy plugins have to follow a specific format for best results. 42 | 43 | - ChepyCore needs to be inherited in the plugin class 44 | - Methods must have [google style docstrings](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html). 45 | - Methods should preferably be prefixed with something that distinguishes them. For example `myplugin_somemethod`. This avoids namespace conflicts. 46 | 47 | ### Sample plugin 48 | ![Plugin](./assets/plugin.gif) 49 | [Asciinema](https://asciinema.org/a/apIR9AWO3EZpHrfKYfagVZk06) 50 | 51 | This is a bare bones example of how a Chepy plugin works. In this case, `myplugin_method` will be available in both Chepy cli (with auto completion) and the Chepy library. 52 | 53 | The only thing this plugin at the moment will do is take whatever value is in the state, and multiply it with 20. All methods in Chepy plugins should set the value of `self.state` and should return `self`. This allows chaining with other methods that are available. 54 | 55 | ```python 56 | import chepy.core 57 | 58 | class MyPlugin(chepy.core.ChepyCore): 59 | 60 | @chepy.core.ChepyDecorators.call_stack 61 | def myplugin_method(self): 62 | """another method 63 | 64 | Returns: 65 | ChepyPlugin: The chepy object 66 | """ 67 | self.state = self.state * 20 68 | return self 69 | ``` 70 | 71 | Lets breakdown this sample plugin. 72 | 73 | #### Importing ChepyCore 74 | 75 | ```python 76 | import chepy.core 77 | 78 | class MyPlugin(chepy.core.ChepyCore): 79 | 80 | @chepy.core.ChepyDecorators.call_stack 81 | def myplugin_method(self): 82 | ``` 83 | All Chepy plugins needs to inherit the **ChepyCore** class. This ensures that all the core attributes and methods from ChepyCore are available to the plugin. 84 | 85 | The **ChepyDecorators** class offers stack methods to decorate plugin methods with. In this example, the `call_stack` decorator is being applied to the `myplugin_method` method. Although using the decorator is not required, it is recommended. This decorator ensures that that external plugins are also able to use the recipe feature. 86 | 87 | #### Docstrings 88 | ```python 89 | """another method 90 | 91 | Returns: 92 | Chepy: The chepy object 93 | """ 94 | ``` 95 | 96 | This is an example of Google style docstrings in python. Chepy cli parses these doc strings to show the help message and command completion dynamically. Although this can be omitted, it is strong recommended to have them to leverage the best capabilities of Chepy. The return type of `ChepyPlugin` is important for both autocompletion, and also highlighting the method as a plugin method. 97 | 98 | #### Method body 99 | This could be any code that the method is trying to accomplish 100 | 101 | #### Returns 102 | ```python 103 | self.state = self.state * 20 104 | return self 105 | ``` 106 | ```eval_rst 107 | .. important:: 108 | These two lines are very important. Both Chepy cli and library allows the user to chain various methods with each other. 109 | ``` 110 | 111 | - `self.state = ...` This line ensures that the value being produced by the method can be accessed by other methods in Chepy. 112 | - `return self` This line ensures that methods can be changed together. Example, 113 | 114 | In the example gif and asciinema, we can see how we first load the hello string to chepy, then call our myplugin_method, and then modify the output with to_hex followed by base64_encode. 115 | 116 | #### Using plugins in script 117 | As all plugins found in the directory is loaded automatically by Chepy at init, using plugins in script is super simple. 118 | 119 | This code is equivalent to what is happening in the gif and asciinema. 120 | 121 | ```python 122 | from chepy import Chepy 123 | 124 | c = Chepy("hello").myplugin_method().to_hex().base64_encode() 125 | print(c) 126 | ``` 127 | 128 | ```eval_rst 129 | .. tip:: 130 | If you do create a plugin that is helpful, feel free to share it, or make a pull request! 131 | ``` 132 | -------------------------------------------------------------------------------- /docs/pullrequest.md: -------------------------------------------------------------------------------- 1 | # Pull requests 2 | 3 | Pull requests for Chepy are very welcome, but the following guidelines needs to be followed. 4 | 5 | ## Code Style 6 | Chepy uses [python black](https://github.com/psf/black) for its code style and formatting. All pull requests should have proper formatting applied. 7 | 8 | ## Commit messages 9 | Commit messages should always have proper flair indicating the changes. The first line of the commit message should include the emojis of what was changed followed by multiline description of what was added. 10 | 11 | ### Example commit message 12 | ``` 13 | ✅🔅ℹ️🧨📚 14 | 15 | 🔅 added new ability 16 | 🧨 refactored something 17 | ℹ️ updated something 18 | ℹ️ fixed something 19 | ✅ added a new method 20 | ✅ added another new method 21 | 📚 added new docs 22 | ``` 23 | 24 | ### The current flairs in use are: 25 | 26 | - 🔅 A new feature has been added. This could be tests files, new arguments etc. 27 | - ℹ️ An update has been made to an existing feature 28 | - 🧨 A major refactor has taken place. This could be anything in the Cli or ChepyCore classes. 29 | - 🐍 A new python dependency has been added 30 | - ✅ New method has been added 31 | - 📚 Added new documentation 32 | 33 | ## Tests 34 | Chepy maintains a 100% Codecov coverage, and all pull requests are required to submit complimentary tests. The tests should include all paths, including coverage for optional arguments, if loops etc. Failing the 100% coverage will automatically fail the configured Github Actions. 35 | 36 | Tests requires the following dev dependencies: 37 | - pytest 38 | - pytest-cov 39 | - sphinx 40 | - recommonmark 41 | - bandit 42 | 43 | To run tests for coverage and pytest, use: 44 | ```bash 45 | pytest --disable-pytest-warnings --cov-report=xml --cov=chepy --cov-config=.coveragerc tests/ 46 | ``` 47 | 48 | For bandit tests, use: 49 | ```bash 50 | bandit --recursive chepy/ --ignore-nosec --skip B101,B413,B303,B310,B112,B304,B320,B410 51 | ``` 52 | 53 | Finally for docs tests, use: 54 | ```bash 55 | make -C docs/ clean html 56 | ``` 57 | 58 | The most convenient way to run all the tests are via the handy `all_tests.sh` from the root directory. 59 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | recommonmark 2 | sphinx==5.0 3 | docutils==0.16 -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/logo.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | base58 2 | colorama 3 | crccheck 4 | decorator 5 | docstring-parser 6 | emoji==2.0.0 7 | exrex 8 | fire==0.6.0 9 | hexdump 10 | jmespath==1.0.1 11 | jsonpickle 12 | lazy-import 13 | lz4==4.3.2 14 | msgpack==1.0.4 15 | parsel==1.9.1 16 | passlib==1.7.4 17 | PGPy==0.6.0 18 | pretty-errors==1.2.25 19 | prompt_toolkit>=2.0.8 20 | pycipher 21 | pycryptodome 22 | pydash 23 | pyjwt==1.7.1 24 | pyOpenSSL==23.2.0 25 | pyperclip 26 | PyYAML 27 | regex 28 | setuptools 29 | typing_extensions -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | 4 | [tool:pytest] 5 | testpaths = tests tests_plugins -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=undefined-variable 2 | from setuptools import setup, find_packages 3 | from os import path 4 | 5 | # get version and author information 6 | with open("chepy/__version__.py", "r") as f: 7 | exec(f.read()) 8 | 9 | 10 | def read_requirements(): 11 | with open("requirements.txt") as f: 12 | return f.read().splitlines() 13 | 14 | 15 | requirements = read_requirements() 16 | # if sys.platform == "linux": 17 | # requirements.append("python-magic") 18 | # else: 19 | # requirements.append("python-magic-bin==0.4.14") 20 | 21 | this_directory = path.abspath(path.dirname(__file__)) 22 | with open(path.join(this_directory, "README.md"), "r", encoding='utf8') as f: 23 | long_description = f.read() 24 | 25 | core_extra_deps = ["requests"] 26 | 27 | plugin_deps = [ 28 | "scapy", 29 | "Markdown", 30 | "chepy", 31 | "pefile", 32 | "pyelftools", 33 | "ua-parser==0.8.0", 34 | "pydriller", 35 | "pyexiftool", 36 | ] 37 | 38 | setup( 39 | long_description=long_description, 40 | long_description_content_type="text/markdown", 41 | name="chepy", 42 | license="GPL", 43 | version=__version__, 44 | author=__author__, 45 | url="https://github.com/securisec/chepy", 46 | project_urls={ 47 | "Documentation": "https://chepy.readthedocs.io/en/latest/", 48 | "Source Code": "https://github.com/securisec/chepy", 49 | }, 50 | extras_require={"extras": core_extra_deps + plugin_deps}, 51 | packages=find_packages(exclude=(["tests", "docs"])), 52 | install_requires=requirements, 53 | classifiers=[ 54 | "Programming Language :: Python :: 3.12", 55 | ], 56 | python_requires="<3.13", 57 | entry_points={"console_scripts": ["chepy = chepy.__main__:main"]}, 58 | ) 59 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/tests/__init__.py -------------------------------------------------------------------------------- /tests/files/elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/tests/files/elf -------------------------------------------------------------------------------- /tests/files/encoding: -------------------------------------------------------------------------------- 1 | =0GDAqREMS0EEWHGOEHJWWRAZqGDHAyHDSxDWyHImRHEEcIGOAyZMqHDPyHFScIDUSyDASREMS0EYS0AWEyJMyRARyHDQWGGUSxJAqREEy1EIWHFOAIDXqHHP1HDRyIDUSyHQySFPImEGW0AOAHHWqHIPy0GHcIDSAyJAS0DEEmEGWHGOEHJOqHHP1HIOMwDVIREFySFESHEMcIGOAxZMqHDP5HFRSIDSIyHASREMS0EEWHGOExEEOSJn5HGSMwDSSxJBqREEEmEHWHFAExZOIHDX1HERyIDUSyDASREMyxD0DxJUE0DFOIDPyHFRAGDSEyJAS0DlR1EOWHFYIIJOqHHP1HDRyIDUgHD3ZSEP50E0DHFOASAAqHDF1HFRSIGUEyDWS0DPM0EEWHGOEHJOqHHFAHJLAyDVIyD3R0DEI1EKWHFEEyJOIHIn1HDQSIDVWyDASREMS0EEWHGISxAnyxHP9HJVSIDSqyDBS0HM10EOW0GUEHHOIxIX1HDRyIDUSyDASRETSSHFWyGUIxAPIHDX10ERSIJUEyDWqRElRHEOWIGQEHJOqHHP1HDRyIFPEQGFq0EQWSHOWHFYExZOIRIF5HDQWGHUSxDW1HEMS0EEWHGOEHJOq0FOqGIHcIHCEQEWS0HO50EOcIGUEHHEqRJPyHDGWxDUSyDASREMS0EEW1DMuSJP9RIQqGDQSIJWqyDWSRImRHEHcxGOAHHSuHHP1HDRyIDUSyDAIID24RHUAxIMuHHOI0Dl4HDQAGHUSxDBgREESHEKWHGOEHJOqHHP1HDRMHHDE0FmHRF2VHEOcIGWEHHEy0IPyHEHAGDSSxJASREMS0EEWHGOEHJWWRAmZGFLcxHDSxDW1HEmRHEIcyGOAyJIqHDPyHDRyIDUSyDASREMS0E -------------------------------------------------------------------------------- /tests/files/fake_secrets.txt: -------------------------------------------------------------------------------- 1 | google_api 'AIzalYn6W299E9kH-aHZSB3aKTYAgHxXwfzZg4q' 2 | google_captcha '6Lrjv_b_jgnybWRwKSn2P6lop58PGZ_NfewZWnRT' 3 | google_oauth 'ya29.L1dpWwGJlKJSxV' 4 | amazon_aws_access_key_id 'AKIAFKOE7IY2PL5ETITY' 5 | amazon_mws_auth_toke 'amzn.mws.f90f3ce6-9b5a-26a7-9a87-4ff8052be2ec' 6 | amazon_aws_url 'uknEsH.s3.amazonawsscom' 7 | facebook_access_token 'EAACEdEose0cBAlAQcZw0' 8 | authorization_basic 'Basic YWRtaW46cGFzcw==' 9 | authorization_bearer 'Bearer AbCdEf123456' 10 | authorization_api 'api\ry\r\t|\x0c\x0c\nyy\t\t e\x0b *wV' 11 | mailgun_api_key 'key-LPxoYCANGEFkAMHBur4jTjbZ69ngpdbI' 12 | twilio_api_key 'SK5d1d319A6Acf7EC9BDeDb8CCe4D76BA8' 13 | twilio_account_sid 'ACXvJ0lkU-BhvkmBkZPUWAxExvPSF6s5En' 14 | twilio_app_sid 'APNLX3uzXotXDUKvurSeS95o8O3RpYuuy6' 15 | paypal_braintree_access_token 'access_token$production$x0lb8affpzmmnufd$3ea7cb281754b7da7eca131ef9642324' 16 | square_oauth_secret 'sq0csp-2WvLIfSstr6_FWefA3c p_oeTw0RtICeBsIlUTShsRo' 17 | square_access_token 'sqOatp-TDt6aBq8Z_Oup1JezKC1cK' 18 | stripe_standard_api 'sk_live_2ZNCghgpavpDMUO3EhdQAael' 19 | stripe_restricted_api 'rk_live_z59MoCJoFc114PpJlP1OnB1O' 20 | github_access_token 'XAmHSVQTebqE8dtcr-:AbSbAztZPEZu@github.commm' 21 | rsa_private_key '-----BEGIN RSA PRIVATE KEY-----' 22 | ssh_dsa_private_key '-----BEGIN DSA PRIVATE KEY-----' 23 | ssh_dc_private_key '-----BEGIN EC PRIVATE KEY-----' 24 | pgp_private_block '-----BEGIN PGP PRIVATE KEY BLOCK-----' 25 | json_web_token 'eyj6be8n6rBOO4Z.0g4Jh3nPB0V4a' -------------------------------------------------------------------------------- /tests/files/ff.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/tests/files/ff.exe -------------------------------------------------------------------------------- /tests/files/flags: -------------------------------------------------------------------------------- 1 | picoCTF{r3source_pag3_f1ag} 2 | xoxb-808882645436-350102357778-949755564313-1v9kucs6pv4o208oj4zh9sxqt76a5859 3 | -----BEGIN RSA PRIVATE KEY----- 4 | https://hooks.slack.com/services/TcVcxBEKs/BA0jbQKMR/z3VwrVaDmA9SHtThW4CF5x2C 5 | SKombv8u2t28ved9jt3xiyelsrbcij86mq 6 | AKIAIYVSTL2JD4XQORJ8 7 | -------------------------------------------------------------------------------- /tests/files/hello: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/tests/files/hello -------------------------------------------------------------------------------- /tests/files/keyboard.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/tests/files/keyboard.pcap -------------------------------------------------------------------------------- /tests/files/lsb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/tests/files/lsb.png -------------------------------------------------------------------------------- /tests/files/msb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/tests/files/msb.png -------------------------------------------------------------------------------- /tests/files/pbuf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/tests/files/pbuf -------------------------------------------------------------------------------- /tests/files/pkcs12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/tests/files/pkcs12 -------------------------------------------------------------------------------- /tests/files/private.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICWwIBAAKBgQDDhjb/e1alLSQk+2UmXjuYmJ1CuYHRWkfmKdf5MhNell2PhrTM 3 | tT4ljNb7PTi+n8WcwihAxHVNfKvgSQt6q/yuVPj5t51159XJHov+ySANFsTUxsUw 4 | YzHUJ5yeeHbbcWgNwehHMPGSdDuZ/XnXH3VIk50FIRNjzrrMpHuQso58ewIDAQAB 5 | AoGAczd000n//efC49QMf/aJkdtk2Dvuhsp3kebYcO0UQunCimArzHGFBKWgzX3/ 6 | IT2POlejVr8uDJJJyinhDNGqXJw9ZEs33f89B7JBGjViS83d9qWypHOg2/OfAt6S 7 | LNICmpPSmKSSJtenFx7XjV0LdG/+b8rENpNy+8TafThnYekCQQDv8oRfMnur8lLq 8 | oG2Fg8RJvq6OA8UOcE4Duo0uPba0uec48kfhBvLsCVhW/vDBDU14o5nUoFKn1sBa 9 | 7jU7Mb0fAkEA0JrhtcBNgUd93tp0jSC6T/qNUOVcJjFZWjamB/X4fPesiNw/azV5 10 | OaGpn9wp7swX56DCcLdIR57T9oRw5DX5JQJAWH4Oh7VsmuuR3Ooxui3wdGoYolON 11 | l1efzgw9CTLFcT2mov/ntnwDlz2TEPKRBAHN8pITp7FBCplO87oqc5xSbQJAfpT9 12 | UaSXY1NWddxpzRmG9PE8v1HuUN6xMaTnqvz/BBXmhEXh1dRk8yu+GlsmttjxyIQs 13 | eOk+2vbt+DD1sAVwYQJAF3kq/lbmROIyAOekpXYFCIWU11mHfxSVuxmYjUYLVRGZ 14 | bmwesS2DFBX5scKK27uMng7nBB9QukZ5kitK4cKelA== 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /tests/files/public.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDhjb/e1alLSQk+2UmXjuYmJ1C 3 | uYHRWkfmKdf5MhNell2PhrTMtT4ljNb7PTi+n8WcwihAxHVNfKvgSQt6q/yuVPj5 4 | t51159XJHov+ySANFsTUxsUwYzHUJ5yeeHbbcWgNwehHMPGSdDuZ/XnXH3VIk50F 5 | IRNjzrrMpHuQso58ewIDAQAB 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /tests/files/qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/tests/files/qr.png -------------------------------------------------------------------------------- /tests/files/qr/aztec.qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/tests/files/qr/aztec.qr.png -------------------------------------------------------------------------------- /tests/files/qr/basic.qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/tests/files/qr/basic.qr.png -------------------------------------------------------------------------------- /tests/files/script.py: -------------------------------------------------------------------------------- 1 | def cpy_script(s): 2 | return s * 2 -------------------------------------------------------------------------------- /tests/files/test.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/tests/files/test.db -------------------------------------------------------------------------------- /tests/files/test.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/tests/files/test.der -------------------------------------------------------------------------------- /tests/files/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Example Domain 5 | 6 | 7 | 8 | 9 | 36 | 37 | 38 | 39 |
40 |

Example Domain

41 |

This domain is for use in illustrative examples in documents. You may use this 42 | domain in literature without prior coordination or asking for permission.

43 |

More information...

44 | 45 |
46 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /tests/files/test.js: -------------------------------------------------------------------------------- 1 | // comment 2 | 3 | function namedFunction(argument1, argument2) { 4 | return 5 | } 6 | 7 | var es6function = (vars) => { 8 | /* some 9 | * comment 10 | */ 11 | } 12 | 13 | /** 14 | * another multline 15 | * comment 16 | */ -------------------------------------------------------------------------------- /tests/files/test.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/tests/files/test.pcapng -------------------------------------------------------------------------------- /tests/files/test.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANS+nHld7b5B7TBy 3 | ObzsK/nI1vx9MiDYfT2B8vgkvTJq19dqXv5tRS2qTFLuR4EGQCq7ZXXHG91ohkDa 4 | a7P1nHtYPIZrw9KQF334o0Pr47x1VN5frqdaHC+iD6ca0Fc9G86UOLDEStAnWYI3 5 | +MuBy9fPKjDYGBjmQYLbRV8aM+NVAgMBAAECgYAl5v/Br7ZXmy9C3lbjDcCX8+w5 6 | d6SirW9CshAznXgHr3lc65qZAaa9iAWpEMK0fgSYmGJvJVYVkDW7AC8IFM4X6GQm 7 | UffWlbZiYCng/iYF4f6oM1YwFHnP+WiM/Q9HtjFGyd9vl4n3bzlalH0s1NeTN1hS 8 | aWkFnVKVkIslpFrSgQJBAPAH8AqhXfWYLtuWSLFYko0lxQ7Av90bZ6VeSjmYVSpq 9 | d8OgJR9Gfd2qW43wt893YeG1nqQhD2ZAw8KTGJ9ywMkCQQDi5fKYQFl4RcZrRlAJ 10 | A5Osn3vZQJ6M1eKqVG9C//M4HpfoZt/cPAjEn8OFdypd89AFO4bZ/vOcaey4YoHG 11 | yAAtAkEA0tvmPzBqvikmYLiwuzq3407ewYsKAU7lyhv+0IHFrzFAbJXuhn8CawwQ 12 | yaxBjPuu/Pzzk/OG96jFT9SwuMGyIQJABDFRkUSnIpTPfM34zqHVSbxMspACHgIZ 13 | xSH4SFmoaeIO1omIG260jsWQ/FdeXgwSTPZzoHWYlMxURnfzg/PQJQJBAOGzpygC 14 | Ku+m5Ua+kOFZ03GYjK5eXjNDdrpfdsfEsp6CBXtWH4JacDiXZSKFoN/WjWuSxsTb 15 | z8I+Uc4jeVU4tzk= 16 | -----END PRIVATE KEY----- 17 | -----BEGIN CERTIFICATE----- 18 | MIICeTCCAeICCQDi5dgCpKMeHTANBgkqhkiG9w0BAQsFADCBgDELMAkGA1UEBhMC 19 | VVMxDDAKBgNVBAgMA2xvbDEMMAoGA1UEBwwDbnljMRIwEAYDVQQKDAlzZWN1cmlz 20 | ZWMxDjAMBgNVBAsMBWNvZGVyMRIwEAYDVQQDDAlzZWN1cmlzZWMxHTAbBgkqhkiG 21 | 9w0BCQEWDm5vbmVAZW1haWwuY29tMB4XDTE5MTEwMjE1MjUwOFoXDTIwMTEwMTE1 22 | MjUwOFowgYAxCzAJBgNVBAYTAlVTMQwwCgYDVQQIDANsb2wxDDAKBgNVBAcMA255 23 | YzESMBAGA1UECgwJc2VjdXJpc2VjMQ4wDAYDVQQLDAVjb2RlcjESMBAGA1UEAwwJ 24 | c2VjdXJpc2VjMR0wGwYJKoZIhvcNAQkBFg5ub25lQGVtYWlsLmNvbTCBnzANBgkq 25 | hkiG9w0BAQEFAAOBjQAwgYkCgYEA1L6ceV3tvkHtMHI5vOwr+cjW/H0yINh9PYHy 26 | +CS9MmrX12pe/m1FLapMUu5HgQZAKrtldccb3WiGQNprs/Wce1g8hmvD0pAXffij 27 | Q+vjvHVU3l+up1ocL6IPpxrQVz0bzpQ4sMRK0CdZgjf4y4HL188qMNgYGOZBgttF 28 | Xxoz41UCAwEAATANBgkqhkiG9w0BAQsFAAOBgQChhviBdift0P/j00TYxnPPNS58 29 | wQSFm54UNQ/vjM12yZ+C5c3268Vo8jSP7mI5R3wn6XztjUSXkDg5/3IL3kojti/h 30 | nyhBHx2QCVke7BxWw3HWkbZ/1BKl0HnCGyd5HDTuOtlBmTS+QrJoNpdsn0zq4fvc 31 | igbV1IJdKTBAiZzaOQ== 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /tests/files/test.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/tests/files/test.tar.gz -------------------------------------------------------------------------------- /tests/files/test.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/tests/files/test.zip -------------------------------------------------------------------------------- /tests/files/vuln_code: -------------------------------------------------------------------------------- 1 | {"body":"r\"\"\"\nDjango settings for tag project.\nGenerated by 'django-admin startproject' using Django 1.9.7.\nFor more information on this file, see\nhttps:\/\/docs.djangoproject.com\/en\/1.9\/topics\/settings\/\nFor the full list of settings and their values, see\nhttps:\/\/docs.djangoproject.com\/en\/1.9\/ref\/settings\/\n\"\"\"\n\nimport os\nimport environ\n\nenv = environ.Env()\n\n\n# Build paths inside the project like this: os.path.join(BASE_DIR, ...)\nBASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))\n# Quick-start development settings - unsuitable for production\n# See https:\/\/docs.djangoproject.com\/en\/1.9\/howto\/deployment\/checklist\/\n\n# SECURITY WARNING: keep the secret key used in production secret!\nSECRET_KEY = env('DJANGO_SECRET_KEY', default='osx*hq-(zkj=&&o!d%u&e-=^1%6y0gvsu9d)-#39k$i1(1+5&$')\n\n# SECURITY WARNING: don't run with debug turned on in production!\nDEBUG = env.bool('DJANGO_DEBUG', default=True)\n\nALLOWED_HOSTS = ['*']\n\nLOGIN_REDIRECT_URL = '\/profile'\n\n# Application definition\n\nINSTALLED_APPS = [\n 'django.contrib.admin',\n 'django.contrib.auth',\n 'django.contrib.contenttypes',\n 'django.contrib.sessions',\n 'django.contrib.messages',\n 'django.contrib.staticfiles',\n 'debug_toolbar',\n 'tags',\n 'crispy_forms',\n 'storages'\n\n]\nCRISPY_TEMPLATE_PACK = 'bootstrap3'\n\nMIDDLEWARE_CLASSES = [\n 'django.middleware.security.SecurityMiddleware',\n 'django.contrib.sessions.middleware.SessionMiddleware',\n 'django.middleware.common.CommonMiddleware',\n 'django.middleware.csrf.CsrfViewMiddleware',\n 'django.contrib.auth.middleware.AuthenticationMiddleware',\n 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',\n 'django.contrib.messages.middleware.MessageMiddleware',\n 'django.middleware.clickjacking.XFrameOptionsMiddleware',\n 'debug_toolbar.middleware.DebugToolbarMiddleware',\n]\n\nROOT_URLCONF = 'tag.urls'\n\nTEMPLATES = [\n {\n 'BACKEND': 'django.template.backends.django.DjangoTemplates',\n 'DIRS': ['templates'],\n 'APP_DIRS': True,\n 'OPTIONS': {\n 'context_processors': [\n 'django.template.context_processors.debug',\n 'django.template.context_processors.request',\n 'django.contrib.auth.context_processors.auth',\n 'django.contrib.messages.context_processors.messages',\n ],\n },\n },\n]\n\nWSGI_APPLICATION = 'tag.wsgi.application'\n\n\n# Database\n# https:\/\/docs.djangoproject.com\/en\/1.9\/ref\/settings\/#databases\n\n\nDATABASES = {\n 'default': {\n 'ENGINE': 'django.db.backends.sqlite3',\n 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),\n }\n}\n\n# Password validation\n# https:\/\/docs.djangoproject.com\/en\/1.9\/ref\/settings\/#auth-password-validators\n\nAUTH_PASSWORD_VALIDATORS = [\n {\n 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',\n },\n {\n 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',\n },\n {\n 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',\n },\n {\n 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',\n },\n]\n\n\n# Internationalization\n# https:\/\/docs.djangoproject.com\/en\/1.9\/topics\/i18n\/\n\nLANGUAGE_CODE = 'en-us'\n\nTIME_ZONE = 'UTC'\n\nUSE_I18N = True\n\nUSE_L10N = True\n\nUSE_TZ = True\n\n\n# Static files (CSS, JavaScript, Images)\n# https:\/\/docs.djangoproject.com\/en\/1.9\/howto\/static-files\/\n\nPROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))\n\nSTATIC_ROOT = os.path.join(PROJECT_ROOT, 'staticfiles')\nSTATIC_URL = '\/static\/'\n\n# Extra places for collectstatic to find static files.\nSTATICFILES_DIRS = (\n os.path.join(PROJECT_ROOT, 'static'),\n)\nMEDIA_ROOT = os.path.join(BASE_DIR, 'tags\/images')\n# MEDIA_ROOT = \"\/Users\/adamsiwiec\/Desktop\/Tag\/tag\/tags\/images\/\"\n# MEDIA_URL = \"\/images\/\"\n\n# Update database configuration with $DATABASE_URL.\nimport dj_database_url\ndb_from_env = dj_database_url.config(conn_max_age=500)\nDATABASES['default'].update(db_from_env)\n\n\n# Simplified static file serving.\n# https:\/\/warehouse.python.org\/project\/whitenoise\/\n\n# STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'\n\nAWS_HEADERS = { # see http:\/\/developer.yahoo.com\/performance\/rules.html#expires\n 'Expires': 'Thu, 31 Dec 2099 20:00:00 GMT',\n 'Cache-Control': 'max-age=94608000',\n }\n\nAWS_STORAGE_BUCKET_NAME = env('S3_BUCKET', default='tagyourit')\nAWS_ACCESS_KEY_ID = env('AWS_ACCESS_KEY_ID', default='AKIAIDO23IONYN4UVTDQ')\nAWS_SECRET_ACCESS_KEY = env('AWS_SECRET_ACCESS_KEY', default='NXekk3ZVc55rQ06RkEXhmUWNvPw5X\/AZt5FrdNXr')\n\n# Tell django-storages that when coming up with the URL for an item in S3 storage, keep\n# it simple - just use this domain plus the path. (If this isn't set, things get complicated).\n# This controls how the `static` template tag from `staticfiles` gets expanded, if you're using it.\n# We also use it in the next setting.\nAWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME\n\n# This is used by the `static` template tag from `static`, if you're using that. Or if anything else\n# refers directly to STATIC_URL. So it's safest to always set it.\nSTATIC_URL = \"https:\/\/%s\/\" % AWS_S3_CUSTOM_DOMAIN\n\n# Tell the staticfiles app to use S3Boto storage when writing the collected static files (when\n# you run `collectstatic`).\n# STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage'\n\nSTATICFILES_LOCATION = 'static'\nMEDIAFILES_LOCATION = 'media'\nimport tag.custom_storages\nSTATICFILES_STORAGE = 'tag.custom_storages.StaticStorage'\nSTATIC_URL = \"https:\/\/%s\/%s\/\" % (AWS_S3_CUSTOM_DOMAIN, STATICFILES_LOCATION)\n\n\nMEDIA_URL = \"https:\/\/%s\/%s\/\" % (AWS_S3_CUSTOM_DOMAIN, MEDIAFILES_LOCATION)\nDEFAULT_FILE_STORAGE = 'tag.custom_storages.MediaStorage'\n\n\nBROKER_URL = os.getenv('REDIS_URL', 'redis:\/\/localhost:6379')\nCELERY_RESULT_BACKEND = os.getenv('REDIS_URL', 'redis:\/\/localhost:6379')\nCELERY_ACCEPT_CONTENT = ['json']\nCELERY_TASK_SERIALIZER = 'json'\nCELERY_RESULT_SERIALIZER = 'json'\nCELERY_TIMEZONE = 'UTC'\n","status":200,"headers":["Content-Security-Policy","Strict-Transport-Security","X-Content-Type-Options","X-Frame-Options","X-XSS-Protection","ETag","Content-Type","Cache-Control","X-Geo-Block-List","X-GitHub-Request-Id","Content-Encoding","Content-Length","Accept-Ranges","Date","Via","Connection","X-Served-By","X-Cache","X-Cache-Hits","X-Timer","Vary","Access-Control-Allow-Origin","X-Fastly-Request-ID","Expires","Source-Age"]} -------------------------------------------------------------------------------- /tests/files/wordlist.txt: -------------------------------------------------------------------------------- 1 | password 2 | secret 3 | super -------------------------------------------------------------------------------- /tests/test_aritmeticlogic.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | 4 | def test_add(): 5 | assert Chepy("40").add(1).to_int().o == 51 6 | assert Chepy("hello").add("ff").o == b"gdkkn" 7 | assert Chepy(9).add("01").o == b":" 8 | 9 | 10 | def test_multiply(): 11 | assert Chepy("0x40").multiply(2).o == 128 12 | 13 | 14 | def test_divide(): 15 | assert Chepy("0x40").divide(2).o == 32 16 | 17 | 18 | def test_divide_float(): 19 | assert Chepy("179").divide(178).to_hex().o == b"17b8803f" 20 | 21 | 22 | def test_power(): 23 | assert Chepy("0x02").power(2).o == 4 24 | 25 | 26 | def test_sum(): 27 | assert Chepy(["0x40", 10]).sum().o == 74 28 | 29 | 30 | def test_mean(): 31 | assert Chepy(["0x40", 10]).mean().o == 37 32 | 33 | 34 | def test_median(): 35 | assert Chepy(["0x40", 10, 20]).median().o == 20 36 | 37 | 38 | def test_sub(): 39 | assert Chepy("40").sub(1).o == b"3/" 40 | assert Chepy("hello").sub("10").o == b"XU\\\\_" 41 | assert Chepy("hello").sub(10).o == b"^[bbe" 42 | # assert Chepy(9).add('01').o == b':' 43 | 44 | 45 | def test_subtract(): 46 | assert Chepy("10 9 x").subtract().o == 1 47 | 48 | 49 | def test_addition(): 50 | assert Chepy("10 9 x").addition().o == 19 51 | 52 | 53 | def test_int_to_base(): 54 | assert Chepy("067165").int_to_base(8).o == 28277 55 | 56 | 57 | def test_bitwise_operations(): 58 | assert Chepy("A").bit_shift_right(3).o == b"\x08" 59 | assert Chepy(b"414243").bit_shift_right().o == b"\x1a\x18\x1a\x19\x1a\x19" 60 | assert Chepy("A").bit_shift_left().o == b"\x82" 61 | assert Chepy("414243").from_hex().bit_shift_left(7).o == b"\x80\x00\x80" 62 | -------------------------------------------------------------------------------- /tests/test_cli.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import inspect 3 | import fire 4 | from docstring_parser import parse as _parse_doc 5 | from chepy import Chepy 6 | from chepy.modules.internal.cli import get_cli_options 7 | 8 | chepy = dir(Chepy) 9 | 10 | 11 | def test_options(): 12 | options = dict() 13 | for method in chepy: 14 | try: 15 | attributes = getattr(Chepy, method) 16 | if not method.startswith("_") and not isinstance(attributes, property): 17 | args = inspect.getfullargspec(attributes).args 18 | parsed_doc = _parse_doc(attributes.__doc__) 19 | if len(args) == 1: 20 | options[method] = { 21 | "options": list( 22 | map(lambda d: {"flag": d, "meta": ""}, args[1:]) 23 | ), 24 | "meta": parsed_doc.short_description, 25 | "returns": parsed_doc.returns.type_name, 26 | } 27 | else: 28 | options[method] = { 29 | "options": list( 30 | map( 31 | lambda d: { 32 | "flag": d[1], 33 | "meta": parsed_doc.params[d[0]].description, 34 | }, 35 | enumerate(args[1:]), 36 | ) 37 | ), 38 | "meta": parsed_doc.short_description, 39 | "returns": parsed_doc.returns.type_name, 40 | } 41 | except: 42 | print("Error in method", method) 43 | raise 44 | return options 45 | 46 | 47 | def test_cli_options(): 48 | get_cli_options() 49 | 50 | 51 | def test_fire1(): 52 | assert fire.Fire(Chepy, command=["A", "-", "to_hex"]).o == b"41" 53 | 54 | 55 | def test_fire2(): 56 | assert ( 57 | fire.Fire(Chepy, command=["abc", "-", "hmac_hash", "--digest", "md5"]).o 58 | == b"dd2701993d29fdd0b032c233cec63403" 59 | ) 60 | 61 | 62 | def test_fire3(): 63 | fire_obj = fire.Fire(Chepy, command=["abc", "-", "hmac_hash", "--digest", "md5"]) 64 | assert type(fire_obj) == Chepy 65 | -------------------------------------------------------------------------------- /tests/test_codetidy.py: -------------------------------------------------------------------------------- 1 | import string 2 | from chepy import Chepy 3 | 4 | 5 | def test_minify_json(): 6 | assert len(Chepy("tests/files/test.json").load_file().minify_json().o) == 5648 7 | 8 | 9 | def test_beautify_json(): 10 | assert ( 11 | len(Chepy("tests/files/test.json").load_file().minify_json().beautify_json().o) 12 | > 6000 13 | ) 14 | 15 | 16 | def test_to_uppercase(): 17 | assert Chepy("some String").to_upper_case(by="word").o == b"Some String" 18 | assert Chepy("some String").to_upper_case(by="sentence").o == b"Some string" 19 | assert Chepy("some String").to_upper_case(by="all").o == b"SOME STRING" 20 | 21 | 22 | def test_to_snake_case(): 23 | assert Chepy("helloWorld").to_snake_case().o == b"hello_world" 24 | 25 | 26 | def test_to_camel_case(): 27 | assert Chepy("some Data_test").to_camel_case().o == b"someDataTest" 28 | assert ( 29 | Chepy("some Data_test").to_camel_case(ignore_space=True).o == b"some DataTest" 30 | ) 31 | 32 | 33 | def test_to_kebab_case(): 34 | assert Chepy("Some data_test").to_kebab_case().o == b"some-data-test" 35 | 36 | 37 | def test_remove_whitespace(): 38 | assert ( 39 | Chepy("some long space\n\ttab space\flol").remove_whitespace().o 40 | == b"somelongspacetabspacelol" 41 | ) 42 | 43 | 44 | def test_swap_case(): 45 | assert Chepy("SoMe TeXt").swap_case().o == b"sOmE tExT" 46 | 47 | 48 | def test_lower_case(): 49 | assert Chepy("HelLo WorLd").to_lower_case().o == b"hello world" 50 | 51 | 52 | def test_leet_speak(): 53 | assert Chepy("somexValue").to_leetspeak().o == b"50m3%V@1u3" 54 | assert Chepy("somexValue").to_leetspeak(False).o == b"50m3xVa1u3" 55 | 56 | 57 | def test_random_case(): 58 | data = string.ascii_letters * 5 59 | assert Chepy(data).random_case().o != data 60 | -------------------------------------------------------------------------------- /tests/test_compression.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | import re 3 | 4 | 5 | def test_fix_zip_header(): 6 | assert ( 7 | Chepy( 8 | "4834434b1400000008003a9d7f502a0ae5b6230000002a00000008001c00666c61672e747874555409000340d5835e40d5835e75780b000104e803000004e8030000f3f109ae2e294a4ccf4c8ecf2bcd4d4a2d8acfcd2f4a8dcfc9cc4e8dcf4512aee50200504b01021e031400000008003a9d7f502a0ae5b6230000002a000000080018000000000001000000808100000000666c61672e747874555405000340d5835e75780b000104e803000004e8030000504b050600000000010001004e000000650000000000" 9 | ) 10 | .from_hex() 11 | .fix_zip_header() 12 | .unzip_one("flag.txt") 13 | .trim() 14 | .o 15 | == b"LLS{tragic_number_more_like_magic_number}" 16 | ) 17 | 18 | 19 | def test_zip_info(): 20 | assert ( 21 | Chepy("tests/files/test.zip") 22 | .read_file() 23 | .zip_info() 24 | .get_by_index(0) 25 | .get_by_key("encrypted") 26 | .o 27 | == True 28 | ) 29 | 30 | 31 | def test_zip_extract_one(): 32 | assert ( 33 | Chepy("tests/files/test.zip").read_file().unzip_one("lol.txt", "password").o 34 | == b"lol\n" 35 | ) 36 | 37 | 38 | def test_zip_list_files(): 39 | assert len(Chepy("tests/files/test.zip").load_file().zip_list_files().o) == 2 40 | 41 | 42 | def test_zip_extract_all(): 43 | assert ( 44 | Chepy("tests/files/test.zip") 45 | .load_file() 46 | .unzip_all("password") 47 | .get_by_index(1) 48 | .o 49 | == b"StormCTF{Misc2:B73dba52ceDA4dDccb31Ec1b1cDa24Ff}" 50 | ) 51 | 52 | 53 | def test_create_zip(): 54 | assert ( 55 | Chepy("A").to_hex().create_zip_file("some.txt").to_hex().slice(0, 8).o 56 | == b"504b0304" 57 | ) 58 | 59 | 60 | def test_zip_compress(): 61 | c = Chepy("some data").zip_compress("file").o 62 | assert c[:2] == b"PK" 63 | assert b"some data" in c 64 | 65 | 66 | def test_zip_compress_symlink(): 67 | c = Chepy("some data").zip_compress_symlink("file", "target").o 68 | assert c[:2] == b"PK" 69 | assert b"target" in c 70 | 71 | 72 | def test_gzip_compress(): 73 | assert Chepy("A").to_hex().gzip_compress().to_hex().slice(0, 6).o == b"1f8b08" 74 | 75 | 76 | def test_gzip_decompress(): 77 | assert Chepy("A").to_hex().gzip_compress().gzip_decompress().o == b"41" 78 | 79 | 80 | def test_bzip(): 81 | c = Chepy("some data").bzip_compress() 82 | assert ( 83 | c.state 84 | == b'BZh91AY&SY\x9f\xe2\xaa\x9d\x00\x00\x03\x91\x80@\x00&\x02\x8c\x00 \x00"\x1ahz\x10\xc0\x86k\xef\n\x82\xeeH\xa7\n\x12\x13\xfcUS\xa0' 85 | ) 86 | assert c.bzip_decompress().o == b"some data" 87 | 88 | 89 | def test_zlib_compress(): 90 | assert ( 91 | Chepy("some text").zlib_compress().to_hex().o 92 | == b"78da2bcecf4d552849ad28010011e8039a" 93 | ) 94 | 95 | 96 | def test_zlib_decompress(): 97 | assert ( 98 | Chepy("789c0580a10d000008c35ee1b9ca05c104e737b761ca5711e8039a") 99 | .hex_to_bytes() 100 | .zlib_decompress() 101 | .o 102 | == b"some text" 103 | ) 104 | 105 | 106 | def test_lzma_compress(): 107 | assert ( 108 | Chepy("some data").lzma_compress().to_hex().o 109 | == b"fd377a585a000004e6d6b4460200210116000000742fe5a3010008736f6d65206461746100000000bb22facdd6fa557b000121096c18c5d51fb6f37d010000000004595a" 110 | ) 111 | 112 | 113 | def test_lzma_decompress(): 114 | assert ( 115 | Chepy( 116 | "fd377a585a000004e6d6b4460200210116000000742fe5a3010008736f6d65206461746100000000bb22facdd6fa557b000121096c18c5d51fb6f37d010000000004595a" 117 | ) 118 | .from_hex() 119 | .lzma_decompress() 120 | .o 121 | == b"some data" 122 | ) 123 | 124 | 125 | def test_tar_list_files(): 126 | assert Chepy("tests/files/test.tar.gz").read_file().tar_list_files().o == [ 127 | "test.js", 128 | "test.json", 129 | ] 130 | assert Chepy("tests/files/test.tar.gz").read_file().tar_list_files(mode="gz").o == [ 131 | "test.js", 132 | "test.json", 133 | ] 134 | 135 | 136 | def test_tar_extract_one(): 137 | assert ( 138 | b"comment" 139 | in Chepy("tests/files/test.tar.gz").read_file().tar_extract_one("test.js").o 140 | ) 141 | assert ( 142 | b"comment" 143 | in Chepy("tests/files/test.tar.gz") 144 | .read_file() 145 | .tar_extract_one("test.js", mode="gz") 146 | .o 147 | ) 148 | 149 | 150 | def test_tar_extract_all(): 151 | assert len(Chepy("tests/files/test.tar.gz").read_file().tar_extract_all().o) == 2 152 | assert ( 153 | len(Chepy("tests/files/test.tar.gz").read_file().tar_extract_all(mode="gz").o) 154 | == 2 155 | ) 156 | 157 | 158 | def test_tar_compress(): 159 | assert len(Chepy("logo.png").read_file().tar_compress("some.png").o) > 50000 160 | assert ( 161 | len(Chepy("logo.png").read_file().tar_compress("some.png", mode="").o) > 50000 162 | ) 163 | 164 | 165 | def test_raw_deflate_inflate(): 166 | assert Chepy("securisec").raw_deflate().raw_inflate().o == b"securisec" 167 | 168 | 169 | def test_lz4_compress(): 170 | assert ( 171 | Chepy("data").lz4_compress().to_hex().o 172 | == b"04224d1868400400000000000000cd040000806461746100000000" 173 | ) 174 | 175 | 176 | def test_lz4_decompress(): 177 | assert ( 178 | Chepy("04224d1868400400000000000000cd040000806461746100000000") 179 | .from_hex() 180 | .lz4_decompress() 181 | .o 182 | == b"data" 183 | ) 184 | 185 | def test_lz77(): 186 | input_str = "(0,0,O)(0,0,M)(0,0,G)(1,1,G)(3,3, )(0,0,Y)(10,1,U)(4,1,A)(0,0,R)(0,0,E)(4,1,C)(0,0,L)(9,1,S)(6,2,T)(5,1, )(3,1,H)(7,2,F)(13,1,A)(1,1,A)(2,2,G)(36,7,C)(28,5,C)(6,5,W)(3,1,L)(1,1, )(0,0,N)(10,1,W)(40,3,I)(15,1, )(3,3,T)(48,6,G)(5,1,E)(0,0,K)(22,1,{)(25,1,I)(38,1,E)(1,1,E)(3,3,E)(7,7,E)(15,15,_)(38,3,O)(2,2,O)(5,5,O)(11,11,O)(3,3,_)(63,23,})" 187 | array_of_arrays = [] 188 | regex = r"\((\d+),(\d+),([A-Z\s_{}]+)\)" 189 | matches = re.findall(regex, input_str) 190 | 191 | for match in matches: 192 | param1, param2, param3 = match 193 | array_of_arrays.append([int(param1), int(param2), param3]) 194 | 195 | assert b'EKO{' in Chepy(array_of_arrays).lz77_decompress().o 196 | 197 | assert Chepy('OMGGGGGG').lz77_compress(1).o[1] == [0, 0, 'M'] -------------------------------------------------------------------------------- /tests/test_conf.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from chepy.config import ChepyConfig 3 | 4 | 5 | def test_config(): 6 | config = ChepyConfig() 7 | config_dir = Path.home() / ".chepy" 8 | assert config.history_path == str(config_dir / "chepy_history") 9 | assert str(config.chepy_conf) == str(config_dir / "chepy.conf") 10 | assert Path(config.chepy_conf).exists() 11 | assert Path(config.history_path).exists() 12 | assert config.prompt_bottom_toolbar.startswith("#") 13 | assert config.prompt_rprompt.startswith("#") 14 | assert config.prompt_toolbar_buffers.startswith("#") 15 | assert config.prompt_toolbar_errors.startswith("#") 16 | assert config.prompt_toolbar_states.startswith("#") 17 | assert config.prompt_toolbar_type.startswith("#") 18 | assert config.prompt_toolbar_version.startswith("#") 19 | assert config.prompt_char is not None 20 | assert len(config.prompt_colors.split()) == 3 21 | -------------------------------------------------------------------------------- /tests/test_ctf.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | """ 4 | general tests for CTF solvers 5 | """ 6 | 7 | 8 | def test_csaw_23_breakthevault(): 9 | assert ( 10 | Chepy( 11 | "5346815611816381158830026000575759913046890410767282609674124748425112753245783703275530777684185849448083" 12 | ) 13 | .to_base(16) 14 | .from_hex() 15 | .rotate_right(4) 16 | .from_base64() 17 | .o 18 | == b"csawctf{w@11_ST_1s_n0t_n3ce$$@ry}" 19 | ) 20 | 21 | 22 | def test_hero_v5_heap(): 23 | key = "c45c60232c9847e2" 24 | payload = "kSDIsBFTYa3+aLqEpVLXtspdLse8WclEhbqGLiqvM6k=" 25 | 26 | c = ( 27 | Chepy(payload) 28 | .from_base64() 29 | .aes_decrypt(key=key, key_format="utf-8", mode="ECB") 30 | ) 31 | assert c.o == b"Hero{D1G_1NT0_J4V4_H34P}" 32 | 33 | 34 | def test_africe_23_own_reality(): 35 | k = ".__..._..__...._.___._...___._...__.__...__.._._._....__._._._..._...__..____.__._._._._.__.___..__._.__.__.___..__.____.___.___.__.___.._._____.__..._..__._.._.___._...___..__._._____..__..__..___.....__._...__.._._.__.._._.__...._..__._....___.._.__..._...__._....__..._..__.___.__.._._.__.._._..__.._..__..__..__..__...__._._.__...._..__..._..__..__.__..__..__..._..__.._...__...__.__...__.__...._..__.__..__..__...__..__..__.._...__.___._____._" 36 | c = Chepy(k).find_replace("\\.", "0").find_replace("_", "1").from_binary() 37 | assert c.o == b"battleCTF{Unknown_bits_384eea49b417ee2ff5a13fbdcca6f327}" 38 | 39 | 40 | def test_springforward_23_hours_behind(): 41 | c = Chepy("vqkk{0vtg_b1um_e1tt_b3tt}") 42 | c.rotate_bruteforce().dict_get_items().filter_list("nicc") 43 | assert c.o == b"nicc{0nly_t1me_w1ll_t3ll}" 44 | 45 | 46 | def test_bsides_c5(): 47 | c = ( 48 | Chepy( 49 | "BtC8EzBDHPOhKvzY6zyWRuy4lFMQNxDk9zLIG93n50uD83gxB9vg5jq7ZQJ50xpHMrUCwk4dRwtA0yGRSIDTFZ" 50 | ) 51 | .from_base62() 52 | .reverse() 53 | .from_octal() 54 | .o 55 | == b"th3_cak3_is_a_li3" 56 | ) 57 | 58 | c = ( 59 | Chepy("MjBfcDAweF9ycm1hdV9ta3ozdmsza2ZqM19tcHlpX3B5aTN2") 60 | .from_base64() 61 | .vigenere_decode("key") 62 | .o 63 | == b"20_f00t_thick_imp3rm3abl3_clay_lay3r" 64 | ) 65 | 66 | c = ( 67 | Chepy( 68 | "ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnpkV0lpT2lJeE1qTTBOVFkzT0Rrd0lpd2libUZ0WlNJNklscHFSbnBoUmpsNllVZEdkMDB5VW1aWk0wcG9XVEp6ZW1OcVZTSXNJbWxoZENJNk1UVXhOakl6T1RBeU1uMC5QUkFfMlVfUHVZWEZHb1BWdGxEc2JnaHhvWDA1czNnTGVoVFJEdC1VeUgw" 69 | ) 70 | .from_base64() 71 | .jwt_decode() 72 | .get_by_key("payload") 73 | .get_by_key("name") 74 | .from_base64() 75 | .o 76 | == b"f1sh_shap3d_crack3r5" 77 | ) 78 | 79 | assert ( 80 | Chepy( 81 | "e6 96 37 33 27 f5 27 33 47 37 56 97 c6 f6 07 f5 46 33 47 16 27 57 47 16 37 e6 57" 82 | ) 83 | .reverse() 84 | .remove_whitespace() 85 | .from_hex() 86 | .o 87 | == b"unsaturat3d_polyest3r_r3sin" 88 | ) 89 | -------------------------------------------------------------------------------- /tests/test_datetime.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | 4 | def test_from_unix_timestamp(): 5 | assert Chepy("1573426649").from_unix_timestamp().o[-4:] == b"2019" 6 | assert Chepy("1546573919").from_unix_timestamp(utc=True).o[-4:] == b"2019" 7 | 8 | 9 | # def test_to_unix_timestamp(): 10 | # assert Chepy("Sun Nov 10 17:57:29 2019").to_unix_timestamp().o == 1573426649 11 | -------------------------------------------------------------------------------- /tests/test_extras/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/94da185ee9b1700f32da75028b2909fc83a1aeb9/tests/test_extras/__init__.py -------------------------------------------------------------------------------- /tests/test_extras/test_bruteforce.py: -------------------------------------------------------------------------------- 1 | from chepy.extras.bruteforce import * 2 | 3 | 4 | def test_zip_brute(): 5 | assert ( 6 | zip_password_bruteforce("tests/files/test.zip", "tests/files/wordlist.txt") 7 | == b"password" 8 | ) 9 | 10 | -------------------------------------------------------------------------------- /tests/test_extras/test_characters.py: -------------------------------------------------------------------------------- 1 | from chepy.extras.characters import base64_char_sets 2 | 3 | 4 | def test_base64_chars(): 5 | assert base64_char_sets() == { 6 | "standard": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", 7 | "url_safe": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", 8 | "filename_safe": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+\\-=", 9 | "itoa64": "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=", 10 | "xml": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.", 11 | "y64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-", 12 | "z64": "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/=", 13 | "radix64": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/=", 14 | "uuencoding": " -_", 15 | "xxencoding": "+\\-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 16 | "unix_crypt": "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 17 | } 18 | 19 | -------------------------------------------------------------------------------- /tests/test_extras/test_combinations.py: -------------------------------------------------------------------------------- 1 | from chepy.extras.combinatons import * 2 | 3 | 4 | def test_all_combinations(): 5 | combo = generate_combo(["a", 1, "\x10"]) 6 | assert type(next(combo)) == tuple 7 | assert len([x for x in combo]) == 15 8 | assert len(list(generate_combo(['a', 'b', 'c'], 2, 3))) == 12 9 | assert len(list(generate_combo(['a', 'b', 'c'], max_length=2))) == 6 10 | 11 | def test_all_hex(): 12 | assert len(hex_chars()) == 256 13 | -------------------------------------------------------------------------------- /tests/test_extras/test_crypto_extras.py: -------------------------------------------------------------------------------- 1 | from chepy.extras.crypto import one_time_pad_crib 2 | 3 | 4 | def test_one_time_pad_crib(): 5 | assert ( 6 | one_time_pad_crib( 7 | "51060328ac104b70881b267fb254d7914948e697aff2ce1c07c91c51b4ff2a172b6477c7e006", 8 | "560b032eb6481826df19237ce403d7c34c4db194fff59a4f559a4d09b6fa72157a642797e31a", 9 | b"a" * 38, 10 | )[0] 11 | == "flag{9276cdb76a3dd6b1f523209cd9c0a11b}" 12 | ) 13 | -------------------------------------------------------------------------------- /tests/test_extras/test_misc.py: -------------------------------------------------------------------------------- 1 | from chepy.extras.misc import * 2 | 3 | 4 | def test_shannon_entropy(): 5 | assert shannon_entropy("some text") == 2.725480556997868 6 | assert shannon_entropy("some text", unit="hartley") == 0.8204514002553331 7 | assert shannon_entropy("some text", unit="natural") == 1.8891591637540215 8 | 9 | 10 | def test_IC(): 11 | with open("tests/files/hello", "rb") as f: 12 | data = f.read() 13 | assert index_of_coincidence(data) == 0 14 | -------------------------------------------------------------------------------- /tests/test_file_encoding.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from chepy import Chepy 3 | 4 | path = str(Path().absolute() / "tests/files/encoding") 5 | 6 | 7 | def test_read_file(): 8 | c = Chepy(path).load_file() 9 | assert c.out[0:10] == b"=0GDAqREMS" 10 | 11 | 12 | def test_rot_13(): 13 | c = Chepy(path).load_file() 14 | assert c.rot_13().out[:10] == b"=0TQNdERZF" 15 | 16 | 17 | def test_reverse(): 18 | c = Chepy(path).load_file() 19 | assert c.reverse().out[0:10] == b"E0SMERSADy" 20 | 21 | 22 | def test_flag(): 23 | c = Chepy(path).load_file() 24 | assert ( 25 | c.reverse().rot_13().from_base64().from_base32().str_from_hexdump().out 26 | == b"StormCTF{Spot3:DcEC6181F48e3B9D3dF77Dd827BF34e0}" 27 | ) 28 | -------------------------------------------------------------------------------- /tests/test_hashing.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | 4 | def test_sha1(): 5 | assert Chepy("A").sha1().out == b"6dcd4ce23d88e2ee9568ba546c007c63d9131c1b" 6 | 7 | 8 | def test_sha2_256(): 9 | assert ( 10 | Chepy("A").sha2_256().out 11 | == b"559aead08264d5795d3909718cdd05abd49572e84fe55590eef31a88a08fdffd" 12 | ) 13 | 14 | 15 | def test_sha2_512(): 16 | assert ( 17 | Chepy("A").sha2_512().out 18 | == b"21b4f4bd9e64ed355c3eb676a28ebedaf6d8f17bdc365995b319097153044080516bd083bfcce66121a3072646994c8430cc382b8dc543e84880183bf856cff5" 19 | ) 20 | 21 | 22 | def test_sha2_384(): 23 | assert ( 24 | Chepy("A").sha2_384().out 25 | == b"ad14aaf25020bef2fd4e3eb5ec0c50272cdfd66074b0ed037c9a11254321aac0729985374beeaa5b80a504d048be1864" 26 | ) 27 | 28 | 29 | def test_sha2_224(): 30 | assert ( 31 | Chepy("A").sha2_224().out 32 | == b"5cfe2cddbb9940fb4d8505e25ea77e763a0077693dbb01b1a6aa94f2" 33 | ) 34 | 35 | 36 | def test_sha2_512_truncate(): 37 | assert ( 38 | Chepy("abc").sha2_512_truncate().out 39 | == b"53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23" 40 | ) 41 | 42 | 43 | def test_sha3_512(): 44 | assert ( 45 | Chepy("A").sha3_512().out 46 | == b"f5f0eaa9ca3fd0c4e0d72a3471e4b71edaabe2d01c4b25e16715004ed91e663a1750707cc9f04430f19b995f4aba21b0ec878fc5c4eb838a18df5bf9fdc949df" 47 | ) 48 | 49 | 50 | def test_sha3_256(): 51 | assert ( 52 | Chepy("A").sha3_256().out 53 | == b"1c9ebd6caf02840a5b2b7f0fc870ec1db154886ae9fe621b822b14fd0bf513d6" 54 | ) 55 | 56 | 57 | def test_sha3_384(): 58 | assert ( 59 | Chepy("A").sha3_384().out 60 | == b"15000d20f59aa483b5eac0a1f33abe8e09dea1054d173d3e7443c68035b99240b50f7abdb9553baf220320384c6b1cd6" 61 | ) 62 | 63 | 64 | def test_sha3_224(): 65 | assert ( 66 | Chepy("A").sha3_224().out 67 | == b"97e2f98c0938943ab1a18a1721a04dff922ecc1ad14d4bbf905c02ca" 68 | ) 69 | 70 | 71 | def test_md2(): 72 | assert Chepy("A").md2().out == b"08e2a3810d8426443ecacaf47aeedd17" 73 | 74 | 75 | def test_md4(): 76 | assert Chepy("A").md4().out == b"d5ef20eeb3f75679f86cf57f93ed0ffe" 77 | 78 | 79 | def test_md5(): 80 | assert Chepy("A").md5().out == b"7fc56270e7a70fa81a5935b72eacbe29" 81 | 82 | 83 | def test_keccak_384(): 84 | assert ( 85 | Chepy("A").keccak_384().out 86 | == b"5c744cf4b4e3fb8967189e9744261a74f0ef31cdd8850554c737803585ac109039b73c22c50ea866c94debf1061f37a4" 87 | ) 88 | 89 | 90 | def test_keccak_256(): 91 | assert ( 92 | Chepy("A").keccak_256().out 93 | == b"03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760" 94 | ) 95 | 96 | 97 | def test_keccak_224(): 98 | assert ( 99 | Chepy("A").keccak_224().out 100 | == b"ef40b16ff375c834e91412489889f36538748c5454f4b02ba750b65e" 101 | ) 102 | 103 | 104 | def test_keccak_512(): 105 | assert ( 106 | Chepy("A").keccak_512().out 107 | == b"421a35a60054e5f383b6137e43d44e998f496748cc77258240ccfaa8730b51f40cf47c1bc09c728a8cd4f096731298d51463f15af89543fed478053346260c38" 108 | ) 109 | 110 | 111 | def test_shake_256(): 112 | assert ( 113 | Chepy("A").shake_256().out 114 | == b"5e6812c0bbaaee6440dcc8b81ca6809645f7512e06cf5acb57bd16dc3a2bfc57dc2bf9e6d8941950594bef5191d8394691f86edffcad6c5ebad9365f282f37a8" 115 | ) 116 | 117 | 118 | def test_shake_128(): 119 | assert ( 120 | Chepy("A").shake_128(128).out 121 | == b"a5ba3aeee1525b4ae5439e54cd711f14850251e02c5999a53f61374c0ae089ef905a30c6abe132988c3eb233aaa2a79737fd245f87eda8b635a53720865a8604512a7ca47defb8993adae051e8390881d86968edf631d97f00b4ebef58ad183dc49d97dacc1e6bf1f38a99784dcfe517e4aa3b22401a9b35fd184c19626b8b53" 122 | ) 123 | 124 | 125 | def test_ripemd_160(): 126 | assert Chepy("A").ripemd_160().out == b"ddadef707ba62c166051b9e3cd0294c27515f2bc" 127 | 128 | 129 | def test_blake_2b(): 130 | assert ( 131 | Chepy("A").blake_2b(bits=128, key="key").out 132 | == b"6d2e4cba3bc564e02d1a76f585a6795d" 133 | ) 134 | 135 | 136 | def test_blake_2s(): 137 | assert ( 138 | Chepy("A").blake_2s(bits=128, key="key").out 139 | == b"4e33cc702e9d08c28a5e9691f23bc66a" 140 | ) 141 | 142 | 143 | def test_crc8_checksum(): 144 | assert Chepy("abc").crc8_checksum().out == b"5f" 145 | 146 | 147 | def test_crc16_checksum(): 148 | assert Chepy("a").crc16_checksum().out == b"e8c1" 149 | 150 | 151 | def test_crc32_checksum(): 152 | assert Chepy("a").crc32_checksum().out == b"e8b7be43" 153 | 154 | 155 | def test_hmac_hash(): 156 | assert Chepy("abc").hmac_hash("", "md5").out == b"dd2701993d29fdd0b032c233cec63403" 157 | assert ( 158 | Chepy("abc").hmac_hash("", "sha1").out 159 | == b"9b4a918f398d74d3e367970aba3cbe54e4d2b5d9" 160 | ) 161 | assert ( 162 | Chepy("abc").hmac_hash("", "sha256").out 163 | == b"fd7adb152c05ef80dccf50a1fa4c05d5a3ec6da95575fc312ae7c5d091836351" 164 | ) 165 | assert ( 166 | Chepy("abc").hmac_hash("", "sha512").out 167 | == b"29689f6b79a8dd686068c2eeae97fd8769ad3ba65cb5381f838358a8045a358ee3ba1739c689c7805e31734fb6072f87261d1256995370d55725cba00d10bdd0" 168 | ) 169 | 170 | 171 | def test_bcrypt_hash(): 172 | assert Chepy("abc").bcrypt_hash().out.decode().startswith("$2a$10") 173 | 174 | 175 | def test_bcrypt_compare(): 176 | assert Chepy("abc").bcrypt_compare( 177 | "$2a$10$SpXMRnrQ4IQqC710xMHfAu0BBr4nJkuPqDvzhiAACnykgn87iE2S2" 178 | ) 179 | 180 | 181 | def test_scrypt_hash(): 182 | assert ( 183 | Chepy("abc").scrypt_hash(salt="", key_length=16).out 184 | == b"f352f3374cf4e344dde4108b96985248" 185 | ) 186 | 187 | 188 | def test_derive_pbkdf2_key(): 189 | assert ( 190 | Chepy(".") 191 | .derive_pbkdf2_key( 192 | "mR3m", "d9016d44c374f5fb62604683f4d61578", show_full_key=True 193 | ) 194 | .o[:10] 195 | == b"7c8898f222" 196 | ) 197 | assert ( 198 | Chepy(".").derive_pbkdf2_key("mR3m", "d9016d44c374f5fb62604683f4d61578").o 199 | == b"7c8898f22239ce49aad28e6d16266b8dc1d681f86d2a56c76ebad5cfac1b0dd6" 200 | ) 201 | assert ( 202 | Chepy(".") 203 | .derive_pbkdf2_key("mR3m", "d9016d44c374f5fb62604683f4d61578", hash_type="md5") 204 | .o[:10] 205 | == b"f7918edc04" 206 | ) 207 | assert ( 208 | Chepy(".") 209 | .derive_pbkdf2_key( 210 | "mR3m", "d9016d44c374f5fb62604683f4d61578", hash_type="sha256" 211 | ) 212 | .o[:10] 213 | == b"16b0a769cb" 214 | ) 215 | assert ( 216 | Chepy(".") 217 | .derive_pbkdf2_key( 218 | "mR3m", "d9016d44c374f5fb62604683f4d61578", hash_type="sha512" 219 | ) 220 | .o[:10] 221 | == b"6d2a9c4b24" 222 | ) 223 | 224 | 225 | def test_password_hashing(): 226 | password = "lol" 227 | assert ( 228 | Chepy(password).password_hashing("lmhash").o 229 | == b"7d0fbaebf878e771aad3b435b51404ee" 230 | ) 231 | assert ( 232 | Chepy(password).password_hashing("msdcc", user="lol").o 233 | == b"5a487b0cda9a56e7e25464d81da162a2" 234 | ) 235 | -------------------------------------------------------------------------------- /tests/test_links.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | 4 | def test_pastebin_to_raw(): 5 | assert ( 6 | Chepy("https://pastebin.com/abCD").pastebin_to_raw().o 7 | == b"https://pastebin.com/raw/abCD" 8 | ) 9 | 10 | 11 | def test_github_to_raw(): 12 | assert ( 13 | Chepy("https://github.com/securisec/chepy/blob/master/README.md") 14 | .github_to_raw() 15 | .o 16 | == b"https://raw.githubusercontent.com/securisec/chepy/master/README.md" 17 | ) 18 | 19 | 20 | def test_google_search_ei_to_epoch(): 21 | assert Chepy("Bh8hYqykHc64mAXkkoTgCg==").google_search_ei_to_epoch().o == 1646337798 22 | 23 | 24 | # def test_to_unix_timestamp(): 25 | # assert Chepy("Sun Nov 10 17:57:29 2019").to_unix_timestamp().o == 1573426649 26 | -------------------------------------------------------------------------------- /tests/test_networking.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | 4 | def test_defang_url(): 5 | assert ( 6 | Chepy("https://app.google.com/?lol=some data&a=1").defang_url().o 7 | == b"hxxps://app[.]google[.]com/?lol=some data&a=1" 8 | ) 9 | 10 | 11 | def test_refang_url(): 12 | assert ( 13 | Chepy("hxxps://app[.]google[.]com/?lol=some data&a=1").refang_url().o 14 | == b"https://app.google.com/?lol=some data&a=1" 15 | ) 16 | 17 | 18 | def test_defang_ip(): 19 | assert ( 20 | Chepy("2001:4860:4860::8844").defang_ip().o == b"2001[:]4860[:]4860[:][:]8844" 21 | ) 22 | assert Chepy("127.0.0.1").defang_ip().o == b"127[.]0[.]0[.]1" 23 | 24 | 25 | def test_refang_ip(): 26 | assert Chepy("127[.]0[.]0[.]1").refang_ip().o == b"127.0.0.1" 27 | 28 | 29 | def test_parse_uri(): 30 | assert Chepy("http://example.com/resource?foo=bar#fragment").parse_uri().o == { 31 | "scheme": "http", 32 | "location": "example.com", 33 | "path": "/resource", 34 | "params": "", 35 | "query": {"foo": ["bar"]}, 36 | "fragment": "fragment", 37 | } 38 | 39 | 40 | def test_parse_ip_range(): 41 | assert len(Chepy("10.10.10.1/24").parse_ip_range().o) == 254 42 | 43 | 44 | def test_parse_ipv6(): 45 | assert Chepy("2001:4860:4860::8888").parse_ipv6().o == { 46 | "long": "2001:4860:4860:0000:0000:0000:0000:8888", 47 | "short": "2001:4860:4860::8888", 48 | } 49 | 50 | 51 | def test_get_cert(): 52 | assert Chepy("google.com").get_ssl_cert().o["subject"]["commonName"] != "" 53 | 54 | 55 | def test_int_to_ip(): 56 | assert Chepy("2130706433").int_to_ip().o == b"127.0.0.1" 57 | assert Chepy("127.0.0.1").ip_to_int().o == 2130706433 58 | -------------------------------------------------------------------------------- /tests/test_other.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | 4 | def test_uuid(): 5 | assert len(Chepy('').generate_uuid().o) == 36 6 | 7 | -------------------------------------------------------------------------------- /tests/test_publickey.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from chepy import Chepy 3 | 4 | path = str(Path().absolute() / "tests/files/test.pem") 5 | 6 | 7 | def test_parse_x509_pem(): 8 | assert Chepy(path).load_file().parse_x509_pem().o == { 9 | "version": 0, 10 | "serial": 16349711528102141469, 11 | "algo": b"sha256WithRSAEncryption", 12 | "before": b"20191102152508Z", 13 | "after": b"20201101152508Z", 14 | "issuer": { 15 | "C": "US", 16 | "ST": "lol", 17 | "L": "nyc", 18 | "O": "securisec", 19 | "OU": "coder", 20 | "CN": "securisec", 21 | "email": "none@email.com", 22 | }, 23 | "subject": { 24 | "C": "US", 25 | "ST": "lol", 26 | "L": "nyc", 27 | "O": "securisec", 28 | "OU": "coder", 29 | "CN": "securisec", 30 | "email": "none@email.com", 31 | }, 32 | "pubkey": {"bits": 1024}, 33 | } 34 | 35 | 36 | def test_parse_x509_der_hex(): 37 | assert Chepy( 38 | str(Path().absolute() / "tests/files/test.der") 39 | ).load_file().parse_x509_der_hex().o == { 40 | "version": 0, 41 | "serial": 16349711528102141469, 42 | "algo": b"sha256WithRSAEncryption", 43 | "before": b"20191102152508Z", 44 | "after": b"20201101152508Z", 45 | "issuer": { 46 | "C": "US", 47 | "ST": "lol", 48 | "L": "nyc", 49 | "O": "securisec", 50 | "OU": "coder", 51 | "CN": "securisec", 52 | "email": "none@email.com", 53 | }, 54 | "subject": { 55 | "C": "US", 56 | "ST": "lol", 57 | "L": "nyc", 58 | "O": "securisec", 59 | "OU": "coder", 60 | "CN": "securisec", 61 | "email": "none@email.com", 62 | }, 63 | "pubkey": {"bits": 1024}, 64 | } 65 | 66 | 67 | def test_pem_to_der(): 68 | assert Chepy(path).load_file().pem_to_der_hex().to_hex().o.decode()[0:6] == "308202" 69 | 70 | 71 | def test_der_hex_to_pem(): 72 | assert ( 73 | Chepy(str(Path().absolute() / "tests/files/test.der")) 74 | .load_file() 75 | .der_hex_to_pem() 76 | .o.decode() 77 | == """-----BEGIN CERTIFICATE----- 78 | MIICeTCCAeICCQDi5dgCpKMeHTANBgkqhkiG9w0BAQsFADCBgDELMAkGA1UEBhMC 79 | VVMxDDAKBgNVBAgMA2xvbDEMMAoGA1UEBwwDbnljMRIwEAYDVQQKDAlzZWN1cmlz 80 | ZWMxDjAMBgNVBAsMBWNvZGVyMRIwEAYDVQQDDAlzZWN1cmlzZWMxHTAbBgkqhkiG 81 | 9w0BCQEWDm5vbmVAZW1haWwuY29tMB4XDTE5MTEwMjE1MjUwOFoXDTIwMTEwMTE1 82 | MjUwOFowgYAxCzAJBgNVBAYTAlVTMQwwCgYDVQQIDANsb2wxDDAKBgNVBAcMA255 83 | YzESMBAGA1UECgwJc2VjdXJpc2VjMQ4wDAYDVQQLDAVjb2RlcjESMBAGA1UEAwwJ 84 | c2VjdXJpc2VjMR0wGwYJKoZIhvcNAQkBFg5ub25lQGVtYWlsLmNvbTCBnzANBgkq 85 | hkiG9w0BAQEFAAOBjQAwgYkCgYEA1L6ceV3tvkHtMHI5vOwr+cjW/H0yINh9PYHy 86 | +CS9MmrX12pe/m1FLapMUu5HgQZAKrtldccb3WiGQNprs/Wce1g8hmvD0pAXffij 87 | Q+vjvHVU3l+up1ocL6IPpxrQVz0bzpQ4sMRK0CdZgjf4y4HL188qMNgYGOZBgttF 88 | Xxoz41UCAwEAATANBgkqhkiG9w0BAQsFAAOBgQChhviBdift0P/j00TYxnPPNS58 89 | wQSFm54UNQ/vjM12yZ+C5c3268Vo8jSP7mI5R3wn6XztjUSXkDg5/3IL3kojti/h 90 | nyhBHx2QCVke7BxWw3HWkbZ/1BKl0HnCGyd5HDTuOtlBmTS+QrJoNpdsn0zq4fvc 91 | igbV1IJdKTBAiZzaOQ== 92 | -----END CERTIFICATE----- 93 | """ 94 | ) 95 | 96 | 97 | def test_pkcs12(): 98 | assert ( 99 | "-----BEGIN PRIVATE KEY-----" 100 | in Chepy("tests/files/pkcs12") 101 | .read_file() 102 | .dump_pkcs12_cert("mimikatz") 103 | .get_by_key("private") 104 | .o.decode() 105 | ) 106 | 107 | 108 | def test_parse_public(): 109 | assert ( 110 | Chepy("tests/files/public.pem").load_file().parse_public_pem().get_by_key("e").o 111 | == 65537 112 | ) 113 | 114 | 115 | def test_parse_private(): 116 | assert ( 117 | Chepy("tests/files/private.pem") 118 | .load_file() 119 | .parse_private_pem() 120 | .get_by_key("p") 121 | .o 122 | == 12567061504848007717323266435513666403545525206525105210732583342352560503165028238964437465562703567713719610893680829859726382850796095548144718531640607 123 | ) 124 | 125 | 126 | def test_public_from_x509(): 127 | assert ( 128 | Chepy("tests/files/test.pem").load_file().public_from_x509().o 129 | == b"-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUvpx5Xe2+Qe0wcjm87Cv5yNb8\nfTIg2H09gfL4JL0yatfXal7+bUUtqkxS7keBBkAqu2V1xxvdaIZA2muz9Zx7WDyG\na8PSkBd9+KND6+O8dVTeX66nWhwvog+nGtBXPRvOlDiwxErQJ1mCN/jLgcvXzyow\n2BgY5kGC20VfGjPjVQIDAQAB\n-----END PUBLIC KEY-----\n" 130 | ) 131 | 132 | 133 | def test_generate_rsa_keypair(): 134 | k = Chepy("").generate_rsa_keypair().o 135 | assert b"PUBLIC" in k["public"] 136 | assert b"PRIVATE" in k["private"] 137 | 138 | 139 | def test_generate_ecc_keypair(): 140 | k = Chepy("").generate_ecc_keypair().o 141 | assert "PUBLIC" in k["public"] 142 | assert "PRIVATE" in k["private"] 143 | -------------------------------------------------------------------------------- /tests/test_search.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | 4 | def test_search(): 5 | assert Chepy("abcdefg123 and again abcdefg124").search(r"abc(de)fg(12)(\d)").o == [ 6 | (b"de", b"12", b"3"), 7 | (b"de", b"12", b"4"), 8 | ] 9 | 10 | 11 | def test_search_list(): 12 | assert Chepy( 13 | ["InfoSeCon2023{1af5856c70878f8566085bc13849ef4d}", True, 123, ["a", "b"]] 14 | ).search_list("Info.+").o == [[b"InfoSeCon2023{1af5856c70878f8566085bc13849ef4d}"]] 15 | 16 | 17 | def test_ctf_flags(): 18 | assert ( 19 | Chepy("tests/files/flags") 20 | .read_file() 21 | .search_ctf_flags("pico") 22 | .get_by_index(0) 23 | .o 24 | == b"picoCTF{r3source_pag3_f1ag}" 25 | ) 26 | 27 | 28 | def test_find_slack_tokenss(): 29 | assert ( 30 | Chepy("tests/files/flags").read_file().search_slack_tokens().get_by_index(0).o 31 | == b"xoxb-808882645436-350102357778-949755564313-1v9kucs6pv4o208oj4zh9sxqt76a5859" 32 | ) 33 | 34 | 35 | def test_search_private(): 36 | assert len(Chepy("tests/files/flags").read_file().search_private_key().o) == 1 37 | 38 | 39 | def test_slack_webhook(): 40 | assert len(Chepy("tests/files/flags").read_file().search_slack_webhook().o) == 1 41 | 42 | 43 | def test_twilio_key(): 44 | assert len(Chepy("tests/files/flags").read_file().search_twilio_key().o) == 1 45 | 46 | 47 | def test_aws_key(): 48 | assert len(Chepy("tests/files/flags").read_file().search_aws_key().o) == 1 49 | -------------------------------------------------------------------------------- /tests_plugins/_test_git.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | 4 | def test_git_author(): 5 | assert Chepy("chepy/chepy_plugins").git_authors().o.get("securisec") 6 | 7 | 8 | def test_git_code_search(): 9 | assert len(Chepy("chepy/chepy_plugins").git_search_code("markdown").o) > 0 10 | 11 | -------------------------------------------------------------------------------- /tests_plugins/test_additionalextractors.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | 4 | def test_jpath(): 5 | assert ( 6 | Chepy("tests/files/test.json") 7 | .load_file() 8 | .jpath_selector("[*].name.first") 9 | .get_by_index(2) 10 | .o 11 | == b"Long" 12 | ) 13 | 14 | 15 | # def test_php_deserialzie(): 16 | # assert Chepy( 17 | # 'a:3:{i:1;s:6:"elem 1";i:2;s:6:"elem 2";i:3;s:7:" elem 3";}' 18 | # ).php_deserialize().o == {1: b"elem 1", 2: b"elem 2", 3: b" elem 3"} 19 | 20 | 21 | def test_minify_xml(): 22 | assert len(Chepy("tests/files/test.xml").load_file().minify_xml().o) == 6392 23 | 24 | 25 | def test_beautify_xml(): 26 | assert ( 27 | len(Chepy("tests/files/test.xml").load_file().minify_xml().beautify_xml().o) 28 | == 7690 29 | ) 30 | -------------------------------------------------------------------------------- /tests_plugins/test_binary.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | 4 | def test_pe_get_certs(): 5 | assert ( 6 | Chepy("tests/files/ff.exe") 7 | .read_file() 8 | .pe_get_certificates() 9 | .get_by_index(0) 10 | .get_by_key("serial") 11 | .o 12 | == 17154717934120587862167794914071425081 13 | ) 14 | 15 | 16 | def test_pe_imports(): 17 | assert ( 18 | len( 19 | Chepy("tests/files/ff.exe") 20 | .read_file() 21 | .pe_imports() 22 | .get_by_key( 23 | b"api-ms-win-crt-filesystem-l1-1-0.dll", py_style=True, split_key=None 24 | ) 25 | .o 26 | ) 27 | == 2 28 | ) 29 | 30 | 31 | def test_pe_exports(): 32 | assert len(Chepy("tests/files/ff.exe").read_file().pe_exports().o) == 94 33 | 34 | 35 | def test_elf_imports(): 36 | assert ( 37 | len( 38 | Chepy("tests/files/elf") 39 | .load_file() 40 | .elf_imports() 41 | .get_by_key(".rela.dyn", py_style=True, split_key=None) 42 | .o 43 | ) 44 | == 9 45 | ) 46 | -------------------------------------------------------------------------------- /tests_plugins/test_extract_plugin.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | 4 | def test_extract_common_secrets(): 5 | assert ( 6 | len( 7 | Chepy("tests/files/vuln_code") 8 | .load_file() 9 | .extract_common_secrets() 10 | .get_by_key("KEY") 11 | .o 12 | ) 13 | == 6 14 | ) 15 | -------------------------------------------------------------------------------- /tests_plugins/test_forensics.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | 4 | # def test_file_mime(): 5 | # assert Chepy("logo.png").load_file().file_mime().o == "image/png" 6 | 7 | 8 | # def test_file_magic(): 9 | # assert ( 10 | # Chepy("logo.png").read_file().file_magic().o 11 | # == "PNG image data, 1920 x 1080, 8-bit/color RGBA, non-interlaced" 12 | # ) 13 | 14 | 15 | def test_get_metadata(): 16 | assert Chepy("logo.png").load_file().get_metadata().o == { 17 | "Bits/pixel": "32", 18 | "Compression": "deflate", 19 | "Compression rate": "138.6x", 20 | "Creation date": "2019-11-30 21:40:30", 21 | "Endianness": "Big endian", 22 | "Image DPI height": "3780 DPI", 23 | "Image DPI width": "3780 DPI", 24 | "Image height": "1080 pixels", 25 | "Image width": "1920 pixels", 26 | "MIME type": "image/png", 27 | "Pixel format": "RGBA", 28 | } 29 | 30 | 31 | def test_embedded(): 32 | Chepy("logo.png").load_file().embedded_files() 33 | assert True 34 | -------------------------------------------------------------------------------- /tests_plugins/test_hash.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | def test_identify_hash(): 4 | assert ( 5 | Chepy("6dcd4ce23d88e2ee9568ba546c007c63d9131c1b").identify_hash().o[0]["name"] 6 | == "SHA-1" 7 | ) -------------------------------------------------------------------------------- /tests_plugins/test_ml.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | 4 | def test_ml_detect(): 5 | assert ( 6 | Chepy("https%3A%2F%2Fwww.pennington.com%2Fcategories%2Fwp-content") 7 | .ml_detect() 8 | .o.get("from_url_encode") 9 | != None 10 | ) 11 | data = "5ZXN4aSn4N2ZVzGA6Q7NbqCRJa2XBt2CEKAvgDUoQj8x9vBJqcrk5fBKZh5XqdAoKnyXMeNmE21QQAqZcKZPamT8he6s8nYRU1unmSb2eAmnnBv8NWSs9f6BgsJ3DGPpdbPm8b9kDSMDTLfZ1" 12 | assert Chepy(data).ml_detect().o.get("from_base58") != None 13 | assert Chepy(data).from_base58().ml_detect().o.get("from_hex") != None 14 | assert ( 15 | Chepy(data).from_base58().from_hex().ml_detect().o.get("lzma_decompress") 16 | != None 17 | ) 18 | 19 | 20 | def test_ml_magic(): 21 | assert ( 22 | Chepy("Ca6wMuk9H4Y3rYb8uMQordMrH6JbvsaWx2Ua7dNQvF1tujWPvi2AEijEKsD6Mpe7Ld37T1y") 23 | .ml_magic() 24 | .o[-1] 25 | == b"hello world" 26 | ) 27 | 28 | assert ( 29 | Chepy( 30 | "KZWTCNCVGFEXSUTOJJHFM3LIKVMWWZDPKZLFS522I44VOYSHPB5FSVLDGVLGWMKXKNWGYWSNI5UFAVSHPBQWGMKOONREM4COKJWHATKXK52GCWKWLJLVE3SGLBREQQTTLFMHAV2NNRNHCU3KKJMGEVS2JFKWY2DXMFDEU42XNM4VMYSYKIZVMMC2MFJDC4CFKVWXATSSIZNDMV2WKJHWIMLMK5JW4SSUMJDEUV2ZK52EOTJROBCVE3DQNRLFIRS2K5VWI43BI5LHEV3MNBLVEM3IOZKWURTLKIYXARTBIZNGSUSWOBMFOVSSI5SDERSHMEZWIWDCLBJFSVTKIEYVEMKZPFGVIUTIKIYVUMC2KVLGWVRSJJDWGRSSK5QWWWT2KZVEM22XK5DEQYKFGVHGERLQMFLDCWSTKMZEK52NJBUFOYJSKJKFM23EGRKWYWSXKVMGIUCVKQYDS===" 31 | ) 32 | .ml_magic(10) 33 | .o[-1] 34 | == b"InfoSeCon2023{1af5856c70878f8566085bc13849ef4d}" 35 | ) 36 | -------------------------------------------------------------------------------- /tests_plugins/test_multimedia.py: -------------------------------------------------------------------------------- 1 | import re 2 | from chepy import Chepy 3 | 4 | 5 | def test_image_resize(): 6 | assert len(Chepy("logo.png").read_file().resize_image(128, 128, "png").o) > 0 7 | assert ( 8 | len(Chepy("logo.png").read_file().resize_image(128, 128, "png", "hamming").o) 9 | > 0 10 | ) 11 | assert ( 12 | len(Chepy("logo.png").read_file().resize_image(128, 128, "png", "box").o) 13 | != 4900 14 | ) 15 | assert ( 16 | len(Chepy("logo.png").read_file().resize_image(128, 128, "png", "bilinear").o) 17 | > 0 18 | ) 19 | assert ( 20 | len(Chepy("logo.png").read_file().resize_image(128, 128, "png", "antialias").o) 21 | > 0 22 | ) 23 | 24 | 25 | def test_split_color_channels(): 26 | assert len(Chepy("logo.png").load_file().split_color_channels("png").o) == 3 27 | 28 | 29 | def test_rotate_image(): 30 | c1 = Chepy("logo.png").load_file().o 31 | c2 = Chepy("logo.png").load_file().rotate_image(180, "png").o 32 | assert c1 != c2 33 | 34 | 35 | def test_grayscale_image(): 36 | c1 = Chepy("logo.png").load_file().o 37 | c2 = Chepy("logo.png").load_file().grayscale_image("png").o 38 | assert c1 != c2 39 | 40 | 41 | def test_blur_image(): 42 | c1 = Chepy("logo.png").load_file().o 43 | c2 = Chepy("logo.png").load_file().blur_image("png").o 44 | c3 = Chepy("logo.png").load_file().blur_image(extension="png", gaussian=True).o 45 | assert c1 != c2 46 | assert c1 != c3 47 | 48 | 49 | def test_invert_image(): 50 | c1 = Chepy("logo.png").load_file().o 51 | c2 = Chepy("logo.png").load_file().invert_image("png").o 52 | assert c1 != c2 53 | 54 | 55 | def test_image_opacity(): 56 | c1 = Chepy("logo.png").load_file().o 57 | c2 = Chepy("logo.png").load_file().image_opacity(10, "png").o 58 | assert c1 != c2 59 | 60 | 61 | def test_image_contrast(): 62 | c1 = Chepy("logo.png").load_file().o 63 | c2 = Chepy("logo.png").load_file().image_contrast(10, "png").o 64 | assert c1 != c2 65 | 66 | 67 | def test_image_brightness(): 68 | c1 = Chepy("logo.png").load_file().o 69 | c2 = Chepy("logo.png").load_file().image_brightness(10, "png").o 70 | assert c1 != c2 71 | 72 | 73 | def test_image_sharpness(): 74 | c1 = Chepy("logo.png").load_file().o 75 | c2 = Chepy("logo.png").load_file().image_sharpness(10, "png").o 76 | assert c1 != c2 77 | 78 | 79 | def test_image_color(): 80 | c1 = Chepy("logo.png").load_file().o 81 | c2 = Chepy("logo.png").load_file().image_color(10, "png").o 82 | assert c1 != c2 83 | 84 | 85 | def test_image_add_text(): 86 | c1 = Chepy("logo.png").load_file().o 87 | c2 = Chepy("logo.png").load_file().image_add_text("some text").o 88 | assert c1 != c2 89 | 90 | 91 | def test_convert_image(): 92 | assert ( 93 | Chepy("logo.png").load_file().convert_image("jpeg").to_hex().o[0:6] == b"ffd8ff" 94 | ) 95 | 96 | 97 | def test_lsb_by_channel(): 98 | assert re.search( 99 | b"4E34B38257200616FB75CD869B8C3CF0", 100 | Chepy("tests/files/lsb.png").read_file().lsb_dump_by_channel().from_binary().o, 101 | ) 102 | 103 | 104 | def test_msb_by_channel(): 105 | assert re.search( 106 | b"MSB_really_sucks", 107 | Chepy("tests/files/msb.png") 108 | .read_file() 109 | .msb_dump_by_channel("b", True) 110 | .from_binary() 111 | .o, 112 | ) 113 | -------------------------------------------------------------------------------- /tests_plugins/test_pcap.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | 4 | def test_pcap_dns(): 5 | assert ( 6 | len( 7 | Chepy("tests/files/test.pcapng") 8 | .debug(True) 9 | .read_pcap() 10 | .pcap_dns_queries() 11 | .set() 12 | .o 13 | ) 14 | == 3 15 | ) 16 | 17 | 18 | def test_pcap_http_streams(): 19 | assert len(Chepy("tests/files/test.pcapng").read_pcap().pcap_http_streams().o) == 4 20 | 21 | 22 | def test_pcap_payload(): 23 | assert Chepy("tests/files/test.pcapng").read_pcap().pcap_payload( 24 | layer="ICMP" 25 | ).o == [b"secret", b"message"] 26 | 27 | 28 | def test_packet_to_dict(): 29 | assert ( 30 | Chepy("tests/files/test.pcapng").read_pcap().pcap_to_dict().o[0]["IP"]["src"] 31 | == "10.10.10.11" 32 | ) 33 | 34 | 35 | def test_pcap_layer_stats(): 36 | assert ( 37 | Chepy("tests/files/test.pcapng") 38 | .read_pcap() 39 | .pcap_layer_stats() 40 | .get_by_key("DNS") 41 | .o 42 | == 6 43 | ) 44 | 45 | 46 | def test_pcap_convo(): 47 | assert ( 48 | Chepy("tests/files/test.pcapng") 49 | .read_pcap() 50 | .pcap_convos() 51 | .get_by_key("10.10.10.11", split_key="", py_style=True) 52 | .o["ICMP"] 53 | ) 54 | 55 | 56 | def test_usb_keyboard(): 57 | c = Chepy("tests/files/keyboard.pcap").read_pcap().pcap_usb_keyboard() 58 | assert b"KAIZEN" in c.o 59 | 60 | 61 | def test_raw_payload_offset(): 62 | assert Chepy("tests/files/test.pcapng").read_pcap().pcap_payload_offset( 63 | "ICMP", -20 64 | ).o == [b"secret", b"message"] 65 | -------------------------------------------------------------------------------- /tests_plugins/test_protobuf.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | 4 | def test_protobuf_dict(): 5 | c = Chepy("tests/files/pbuf").load_file() 6 | assert c.protobuf_decode_dict().o["1"] == 1617862179230365600 7 | 8 | 9 | def test_protobuf_json(): 10 | c = Chepy("tests/files/pbuf").load_file() 11 | assert c.protobuf_decode_json(True).json_to_dict().o["1"] == "1617862179230365600" 12 | -------------------------------------------------------------------------------- /tests_plugins/test_qr.py: -------------------------------------------------------------------------------- 1 | # from chepy import Chepy 2 | 3 | # BASE = "tests/files/qr/{}.qr.png" 4 | 5 | 6 | # def test_qr(): 7 | # assert Chepy(BASE.format("basic")).load_file().qr_decode().o == b"hello" 8 | 9 | 10 | # def test_qr_other(): 11 | # assert Chepy(BASE.format("aztec")).load_file().qr_decode_other().o == "hello" 12 | -------------------------------------------------------------------------------- /tests_plugins/test_sqlite.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | DB_FILE = "tests/files/test.db" 4 | 5 | 6 | def test_sqlite_get_columns(): 7 | assert len(Chepy(DB_FILE).sqlite_get_columns("customers").o) == 13 8 | 9 | 10 | def test_sqlite_get_tables(): 11 | assert len(Chepy(DB_FILE).sqlite_get_tables().o) == 13 12 | 13 | 14 | def test_sqlite_dump_table(): 15 | assert len(Chepy(DB_FILE).sqlite_dump_table("customers").o) == 59 16 | 17 | def test_sqlite_query(): 18 | assert len(Chepy(DB_FILE).sqlite_query("select * from customers where company is not null").o) == 10 19 | -------------------------------------------------------------------------------- /tests_plugins/test_useragent.py: -------------------------------------------------------------------------------- 1 | from chepy import Chepy 2 | 3 | 4 | def test_parse_user_agent(): 5 | ua = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.10; rv:62.0) Gecko/20100101 Firefox/62.0" 6 | assert Chepy(ua).parse_user_agent().o == { 7 | "user_agent": {"family": "Firefox", "major": "62", "minor": "0", "patch": None}, 8 | "os": { 9 | "family": "Mac OS X", 10 | "major": "10", 11 | "minor": "10", 12 | "patch": None, 13 | "patch_minor": None, 14 | }, 15 | "device": {"family": "Other", "brand": None, "model": None}, 16 | "string": "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.10; rv:62.0) Gecko/20100101 Firefox/62.0", 17 | } 18 | --------------------------------------------------------------------------------