├── tests ├── __init__.py ├── test_extras │ ├── __init__.py │ ├── test_bruteforce.py │ ├── test_combinations.py │ ├── test_crypto_extras.py │ ├── test_misc.py │ └── test_characters.py ├── files │ ├── wordlist.txt │ ├── script.py │ ├── elf │ ├── pbuf │ ├── ff.exe │ ├── hello │ ├── pkcs12 │ ├── qr.png │ ├── lsb.png │ ├── msb.png │ ├── test.db │ ├── test.der │ ├── test.zip │ ├── test.pcapng │ ├── test.tar.gz │ ├── keyboard.pcap │ ├── qr │ │ ├── aztec.qr.png │ │ └── basic.qr.png │ ├── test.js │ ├── flags │ ├── public.pem │ ├── encoding │ ├── private.pem │ ├── fake_secrets.txt │ ├── test.html │ ├── test.pem │ └── vuln_code ├── test_other.py ├── test_datetime.py ├── test_file_encoding.py ├── test_links.py ├── test_conf.py ├── test_search.py ├── test_aritmeticlogic.py ├── test_networking.py ├── test_codetidy.py ├── test_cli.py ├── test_ctf.py ├── test_publickey.py ├── test_compression.py └── test_hashing.py ├── .dockerignore ├── chepy ├── __version__.pyi ├── extras │ ├── __init__.py │ ├── __init__.pyi │ ├── characters.pyi │ ├── bruteforce.pyi │ ├── misc.pyi │ ├── combinatons.pyi │ ├── crypto.pyi │ ├── bruteforce.py │ ├── characters.py │ ├── combinatons.py │ ├── misc.py │ └── crypto.py ├── modules │ ├── __init__.py │ ├── __init__.pyi │ ├── internal │ │ ├── __init__.py │ │ ├── __init__.pyi │ │ ├── colors.pyi │ │ ├── constants.pyi │ │ ├── cli.pyi │ │ ├── colors.py │ │ └── ls47.py │ ├── exceptions.pyi │ ├── other.pyi │ ├── exceptions.py │ ├── links.pyi │ ├── datetimemodule.pyi │ ├── search.pyi │ ├── other.py │ ├── networking.pyi │ ├── codetidy.pyi │ ├── publickey.pyi │ ├── aritmeticlogic.pyi │ ├── language.pyi │ ├── datetimemodule.py │ ├── links.py │ ├── compression.pyi │ ├── extractors.pyi │ ├── utils.pyi │ ├── hashing.pyi │ ├── language.py │ ├── search.py │ ├── codetidy.py │ └── networking.py ├── __version__.py ├── config.pyi ├── __init__.pyi ├── __init__.py ├── core.pyi └── config.py ├── docs ├── index.md ├── requirements.txt ├── assets │ ├── ctf.gif │ ├── plugin.gif │ ├── clicolors.png │ ├── hmac_hash.png │ └── cc_encoding.png ├── modules │ ├── links.rst │ ├── utils.rst │ ├── codetidy.rst │ ├── language.rst │ ├── other.rst │ ├── hashing.rst │ ├── dataformat.rst │ ├── datetimemodule.rst │ ├── extractors.rst │ ├── multimedia.rst │ ├── compression.rst │ ├── publickey.rst │ ├── networking.rst │ ├── aritmeticlogic.rst │ └── encryptionencoding.rst ├── internal.rst ├── faq.md ├── extras.rst ├── chepy.md ├── Makefile ├── modules.rst ├── make.bat ├── core.md ├── pullrequest.md ├── conf.py ├── cli.md ├── config.md └── plugins.md ├── logo.png ├── MANIFEST.in ├── cli.py ├── setup.cfg ├── .gitmodules ├── .coveragerc ├── tests_plugins ├── test_hash.py ├── _test_git.py ├── test_qr.py ├── test_extract_plugin.py ├── test_protobuf.py ├── test_sqlite.py ├── test_useragent.py ├── test_additionalextractors.py ├── test_forensics.py ├── test_binary.py ├── test_ml.py ├── test_pcap.py └── test_multimedia.py ├── .readthedocs.yml ├── Makefile ├── requirements.txt ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── workflows │ └── tests_multi_os.yml ├── all_tests.sh ├── setup.py ├── Dockerfile ├── TODO ├── .gitignore └── README.md /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .gitignore -------------------------------------------------------------------------------- /chepy/__version__.pyi: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chepy/extras/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chepy/extras/__init__.pyi: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chepy/modules/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chepy/modules/__init__.pyi: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | ../README.md -------------------------------------------------------------------------------- /tests/test_extras/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chepy/modules/internal/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chepy/modules/internal/__init__.pyi: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/files/wordlist.txt: -------------------------------------------------------------------------------- 1 | password 2 | secret 3 | super -------------------------------------------------------------------------------- /tests/files/script.py: -------------------------------------------------------------------------------- 1 | def cpy_script(s): 2 | return s * 2 -------------------------------------------------------------------------------- /chepy/extras/characters.pyi: -------------------------------------------------------------------------------- 1 | def base64_char_sets() -> dict: ... 2 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | recommonmark 2 | sphinx==5.0 3 | docutils==0.16 -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/logo.png -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include requirements.txt 2 | include chepy/chepy_plugins/data/* -------------------------------------------------------------------------------- /tests/files/elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/tests/files/elf -------------------------------------------------------------------------------- /tests/files/pbuf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/tests/files/pbuf -------------------------------------------------------------------------------- /tests/files/ff.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/tests/files/ff.exe -------------------------------------------------------------------------------- /tests/files/hello: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/tests/files/hello -------------------------------------------------------------------------------- /tests/files/pkcs12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/tests/files/pkcs12 -------------------------------------------------------------------------------- /tests/files/qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/tests/files/qr.png -------------------------------------------------------------------------------- /cli.py: -------------------------------------------------------------------------------- 1 | from chepy.__main__ import main 2 | 3 | if __name__ == "__main__": 4 | main() 5 | -------------------------------------------------------------------------------- /docs/assets/ctf.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/docs/assets/ctf.gif -------------------------------------------------------------------------------- /tests/files/lsb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/tests/files/lsb.png -------------------------------------------------------------------------------- /tests/files/msb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/tests/files/msb.png -------------------------------------------------------------------------------- /tests/files/test.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/tests/files/test.db -------------------------------------------------------------------------------- /tests/files/test.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/tests/files/test.der -------------------------------------------------------------------------------- /tests/files/test.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/tests/files/test.zip -------------------------------------------------------------------------------- /chepy/extras/bruteforce.pyi: -------------------------------------------------------------------------------- 1 | def zip_password_bruteforce(path: str, wordlist: str) -> str: ... 2 | -------------------------------------------------------------------------------- /docs/assets/plugin.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/docs/assets/plugin.gif -------------------------------------------------------------------------------- /tests/files/test.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/tests/files/test.pcapng -------------------------------------------------------------------------------- /tests/files/test.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/tests/files/test.tar.gz -------------------------------------------------------------------------------- /docs/assets/clicolors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/docs/assets/clicolors.png -------------------------------------------------------------------------------- /docs/assets/hmac_hash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/docs/assets/hmac_hash.png -------------------------------------------------------------------------------- /tests/files/keyboard.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/tests/files/keyboard.pcap -------------------------------------------------------------------------------- /docs/assets/cc_encoding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/docs/assets/cc_encoding.png -------------------------------------------------------------------------------- /tests/files/qr/aztec.qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/tests/files/qr/aztec.qr.png -------------------------------------------------------------------------------- /tests/files/qr/basic.qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securisec/chepy/HEAD/tests/files/qr/basic.qr.png -------------------------------------------------------------------------------- /docs/modules/links.rst: -------------------------------------------------------------------------------- 1 | Links 2 | """""""""""""" 3 | .. autoclass:: chepy.modules.links.Links 4 | :members: -------------------------------------------------------------------------------- /docs/modules/utils.rst: -------------------------------------------------------------------------------- 1 | 2 | Utils 3 | """"" 4 | .. autoclass:: chepy.modules.utils.Utils 5 | :members: -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | 4 | [tool:pytest] 5 | testpaths = tests tests_plugins -------------------------------------------------------------------------------- /chepy/__version__.py: -------------------------------------------------------------------------------- 1 | __version__ = "7.5.0" # pragma: no cover 2 | __author__ = "@securisec" # pragma: no cover 3 | -------------------------------------------------------------------------------- /docs/modules/codetidy.rst: -------------------------------------------------------------------------------- 1 | CodeTidy 2 | """""""" 3 | .. autoclass:: chepy.modules.codetidy.CodeTidy 4 | :members: -------------------------------------------------------------------------------- /docs/modules/language.rst: -------------------------------------------------------------------------------- 1 | Language 2 | """""""" 3 | .. autoclass:: chepy.modules.language.Language 4 | :members: -------------------------------------------------------------------------------- /docs/modules/other.rst: -------------------------------------------------------------------------------- 1 | 2 | Other 3 | """"" 4 | .. autoclass:: chepy.modules.other.Other 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/modules/hashing.rst: -------------------------------------------------------------------------------- 1 | Hashing 2 | """"""" 3 | .. autoclass:: chepy.modules.hashing.Hashing 4 | :members: 5 | -------------------------------------------------------------------------------- /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/extractors.rst: -------------------------------------------------------------------------------- 1 | Extractors 2 | """""""""" 3 | .. autoclass:: chepy.modules.extractors.Extractors 4 | :members: -------------------------------------------------------------------------------- /docs/modules/multimedia.rst: -------------------------------------------------------------------------------- 1 | Multimedia 2 | """""""""" 3 | .. autoclass:: chepy.modules.multimedia.Multimedia 4 | :members: -------------------------------------------------------------------------------- /docs/modules/compression.rst: -------------------------------------------------------------------------------- 1 | Compression 2 | """"""""""" 3 | .. autoclass:: chepy.modules.compression.Compression 4 | :members: -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "chepy/chepy_plugins"] 2 | path = chepy/chepy_plugins 3 | url = https://github.com/securisec/chepy_plugins 4 | -------------------------------------------------------------------------------- /docs/modules/publickey.rst: -------------------------------------------------------------------------------- 1 | 2 | Publickey 3 | """"""""" 4 | .. autoclass:: chepy.modules.publickey.Publickey 5 | :members: 6 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /docs/modules/networking.rst: -------------------------------------------------------------------------------- 1 | 2 | Networking 3 | """""""""" 4 | .. autoclass:: chepy.modules.networking.Networking 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/modules/aritmeticlogic.rst: -------------------------------------------------------------------------------- 1 | AritmeticLogic 2 | """""""""""""" 3 | .. autoclass:: chepy.modules.aritmeticlogic.AritmeticLogic 4 | :members: -------------------------------------------------------------------------------- /docs/internal.rst: -------------------------------------------------------------------------------- 1 | Chepy Internal 2 | ============== 3 | 4 | Colors 5 | """""" 6 | .. automodule:: chepy.modules.internal.colors 7 | :members: 8 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /docs/modules/encryptionencoding.rst: -------------------------------------------------------------------------------- 1 | 2 | EncryptionEncoding 3 | """""""""""""""""" 4 | .. autoclass:: chepy.modules.encryptionencoding.EncryptionEncoding 5 | :members: -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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 | ) -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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 | def generate_random_string(length: int=8) -> str: ... 6 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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_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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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_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_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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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: -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | base58 2 | colorama 3 | crccheck 4 | decorator 5 | docstring-parser 6 | emoji==2.0.0 7 | exrex 8 | fire==0.7.1 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 30 | pretty-errors==1.2.25 -------------------------------------------------------------------------------- /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]] : ... -------------------------------------------------------------------------------- /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 | ``` -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /tests/files/encoding: -------------------------------------------------------------------------------- 1 | =0GDAqREMS0EEWHGOEHJWWRAZqGDHAyHDSxDWyHImRHEEcIGOAyZMqHDPyHFScIDUSyDASREMS0EYS0AWEyJMyRARyHDQWGGUSxJAqREEy1EIWHFOAIDXqHHP1HDRyIDUSyHQySFPImEGW0AOAHHWqHIPy0GHcIDSAyJAS0DEEmEGWHGOEHJOqHHP1HIOMwDVIREFySFESHEMcIGOAxZMqHDP5HFRSIDSIyHASREMS0EEWHGOExEEOSJn5HGSMwDSSxJBqREEEmEHWHFAExZOIHDX1HERyIDUSyDASREMyxD0DxJUE0DFOIDPyHFRAGDSEyJAS0DlR1EOWHFYIIJOqHHP1HDRyIDUgHD3ZSEP50E0DHFOASAAqHDF1HFRSIGUEyDWS0DPM0EEWHGOEHJOqHHFAHJLAyDVIyD3R0DEI1EKWHFEEyJOIHIn1HDQSIDVWyDASREMS0EEWHGISxAnyxHP9HJVSIDSqyDBS0HM10EOW0GUEHHOIxIX1HDRyIDUSyDASRETSSHFWyGUIxAPIHDX10ERSIJUEyDWqRElRHEOWIGQEHJOqHHP1HDRyIFPEQGFq0EQWSHOWHFYExZOIRIF5HDQWGHUSxDW1HEMS0EEWHGOEHJOq0FOqGIHcIHCEQEWS0HO50EOcIGUEHHEqRJPyHDGWxDUSyDASREMS0EEW1DMuSJP9RIQqGDQSIJWqyDWSRImRHEHcxGOAHHSuHHP1HDRyIDUSyDAIID24RHUAxIMuHHOI0Dl4HDQAGHUSxDBgREESHEKWHGOEHJOqHHP1HDRMHHDE0FmHRF2VHEOcIGWEHHEy0IPyHEHAGDSSxJASREMS0EEWHGOEHJWWRAmZGFLcxHDSxDW1HEmRHEIcyGOAyJIqHDPyHDRyIDUSyDASREMS0E -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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/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 | -------------------------------------------------------------------------------- /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/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_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/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/files/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |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 | 44 | 45 |
2 |
3 |
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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 | 
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 |
--------------------------------------------------------------------------------
/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/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 | LOGGER = logging.getLogger("chepy")
12 |
13 |
14 | class ChepyConfig(object):
15 | def __init__(self):
16 | home = Path.home()
17 | self.chepy_dir = (
18 | Path(".chepy").resolve()
19 | if Path(".chepy").exists()
20 | else Path(home / ".chepy")
21 | )
22 | self.chepy_conf = Path(self.chepy_dir / "chepy.conf")
23 |
24 | if not self.chepy_conf.exists(): # pragma: no cover
25 | self.chepy_dir.mkdir(exist_ok=True)
26 | c = ConfigParser()
27 |
28 | c["Plugins"] = {
29 | "EnablePlugins": "false",
30 | "PluginPath": str(Path(__file__).parent / "chepy_plugins"),
31 | }
32 | c["Cli"] = {}
33 | cli_options = c["Cli"]
34 | cli_options["history_path"] = str(self.chepy_dir / "chepy_history")
35 | cli_options["prompt_char"] = ">"
36 | cli_options["prompt_colors"] = "#00ffff #ff0000 #ffd700"
37 | cli_options["show_rprompt"] = "false"
38 | cli_options["prompt_rprompt"] = "#00ff48"
39 | cli_options["prompt_bottom_toolbar"] = "#000000"
40 | cli_options["prompt_toolbar_version"] = "#00ff48"
41 | cli_options["prompt_toolbar_states"] = "#60cdd5"
42 | cli_options["prompt_toolbar_buffers"] = "#ff00ff"
43 | cli_options["prompt_toolbar_type"] = "#ffd700"
44 | cli_options["prompt_toolbar_plugins"] = "#ffccbc"
45 | cli_options["prompt_toolbar_errors"] = "#ff0000"
46 | cli_options["prompt_cli_method"] = "#ffd700"
47 | cli_options["prompt_plugin_method"] = "#30d8ff"
48 | cli_options["cli_info_color"] = "#c2c2ff"
49 | cli_options["prompt_search_background"] = "#00aaaa #000000"
50 | cli_options["prompt_search_fuzzy"] = "#00aaaa"
51 |
52 | Path(str(self.chepy_dir / "chepy_history")).touch()
53 | if not self.chepy_conf.exists():
54 | with open(str(self.chepy_conf), "w") as f:
55 | c.write(f)
56 |
57 | self.config = ConfigParser()
58 | self.config.read(str(self.chepy_conf))
59 |
60 | plugin_path = self.__get_conf_value("None", "PluginPath", "Plugins")
61 | self.enable_plugins = json.loads(
62 | self.__get_conf_value("false", "EnablePlugins", "Plugins")
63 | )
64 |
65 | plugin_envar = os.environ.get("CHEPY_PLUGINS", "")
66 | if plugin_envar == "true":
67 | self.enable_plugins = True
68 | elif plugin_envar != "":
69 | self.enable_plugins = False
70 |
71 | if self.enable_plugins:
72 | if plugin_path != "None":
73 | self.plugin_path = Path(plugin_path).expanduser().resolve()
74 | else:
75 | self.plugin_path = Path(plugin_path)
76 | else:
77 | self.plugin_path = Path("None")
78 |
79 | self.history_path = self.__get_conf_value(
80 | str(self.chepy_dir / "chepy_history"), "history_path"
81 | )
82 | self.prompt_char = self.__get_conf_value(">", "prompt_char")
83 | self.prompt_colors = self.__get_conf_value(
84 | "#00ffff #ff0000 #ffd700", "prompt_colors"
85 | )
86 | self.show_rprompt = json.loads(self.__get_conf_value("false", "show_rprompt"))
87 | self.prompt_rprompt = self.__get_conf_value("#00ff48", "prompt_rprompt")
88 | self.prompt_bottom_toolbar = self.__get_conf_value(
89 | "#000000", "prompt_bottom_toolbar"
90 | )
91 | self.prompt_toolbar_version = self.__get_conf_value(
92 | "#00ff48", "prompt_toolbar_version"
93 | )
94 | self.prompt_toolbar_states = self.__get_conf_value(
95 | "#60cdd5", "prompt_toolbar_states"
96 | )
97 | self.prompt_toolbar_buffers = self.__get_conf_value(
98 | "#ff00ff", "prompt_toolbar_buffers"
99 | )
100 | self.prompt_toolbar_type = self.__get_conf_value(
101 | "#ffd700", "prompt_toolbar_type"
102 | )
103 | self.prompt_toolbar_plugins = self.__get_conf_value(
104 | "#ffccbc", "prompt_toolbar_plugins"
105 | )
106 | self.prompt_toolbar_errors = self.__get_conf_value(
107 | "#ff0000", "prompt_toolbar_errors"
108 | )
109 | self.prompt_search_background = self.__get_conf_value(
110 | "#00aaaa #000000", "prompt_search_background"
111 | )
112 | self.prompt_search_fuzzy = self.__get_conf_value(
113 | "#00aaaa", "prompt_search_fuzzy"
114 | )
115 | self.prompt_cli_method = self.__get_conf_value("#ffd700", "prompt_cli_method")
116 | self.prompt_plugin_method = self.__get_conf_value(
117 | "#30d8ff", "prompt_plugin_method"
118 | )
119 | self.cli_info_color = self.__get_conf_value("#c2c2ff", "cli_info_color")
120 |
121 | def __get_conf_value(self, default: str, option: str, section: str = "Cli"):
122 | if self.config.has_section(section):
123 | if self.config.has_option(section, option):
124 | return self.config[section][option]
125 | else:
126 | return default
127 | else:
128 | return default
129 |
130 | def load_plugins(self): # pragma: no cover
131 | plugins = []
132 | if self.plugin_path.stem != "None":
133 | sys.path.append(str(self.plugin_path))
134 |
135 | my_plugins = [
136 | importlib.import_module(name)
137 | for finder, name, ispkg in pkgutil.iter_modules()
138 | if (name.startswith("chepy_") and name != "chepy_plugins")
139 | ]
140 |
141 | for plugin in my_plugins:
142 | try:
143 | klass, mod = inspect.getmembers(plugin, inspect.isclass)[0]
144 | loaded = getattr(plugin, klass)
145 | plugins.append(loaded)
146 | except:
147 | LOGGER.warning(f"Error loading {plugin.__name__}")
148 | return plugins
149 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------