Skip to content

Commit

Permalink
🗓 Jul 21, 2023 9:12:39 PM
Browse files Browse the repository at this point in the history
🐙 xor_bruteforce check for crib
🐙 some new helper code
✨ from/to twin hex
✨ from/to base36
🧪 tests added/updated
  • Loading branch information
securisec committed Jul 22, 2023
1 parent 1f0de54 commit 615bac8
Show file tree
Hide file tree
Showing 10 changed files with 261 additions and 35 deletions.
45 changes: 23 additions & 22 deletions .github/workflows/tests_multi_os.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,36 @@ jobs:
- "3.10"

steps:
- uses: actions/checkout@v2.3.4
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- uses: actions/cache@v3
if: startsWith(runner.os, 'Linux')
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-

- uses: actions/cache@v3
if: startsWith(runner.os, 'macOS')
with:
path: ~/Library/Caches/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
# - uses: actions/cache@v3
# if: startsWith(runner.os, 'Linux')
# with:
# path: ~/.cache/pip
# key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
# restore-keys: |
# ${{ runner.os }}-pip-

- uses: actions/cache@v3
if: startsWith(runner.os, 'Windows')
with:
path: ~\AppData\Local\pip\Cache
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
# - uses: actions/cache@v3
# if: startsWith(runner.os, 'macOS')
# with:
# path: ~/Library/Caches/pip
# key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
# restore-keys: |
# ${{ runner.os }}-pip-

# - uses: actions/cache@v3
# if: startsWith(runner.os, 'Windows')
# with:
# path: ~\AppData\Local\pip\Cache
# key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
# restore-keys: |
# ${{ runner.os }}-pip-

- name: Install
# if: steps.devcache.outs.cache-hit != 'true'
Expand Down
9 changes: 4 additions & 5 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ Fix:
Code:
☐ add more examples in docstrings
☐ Luhn validator https://guptaavi352.medium.com/ctflearn-writeups-9f247c2fe94c
☐ 🚀 add crib for xor bruteforce

New ideas:
☐ rubber ducky encode/decode
Expand Down Expand Up @@ -32,7 +31,6 @@ New ideas:
☐ ✨ shuffle
☐ ✨ cetacean encode/decode
☐ ✨ ls47 enc/dec
☐ ✨ decorator that will show warning message if unexpected results in stdout

Bug:

Expand All @@ -42,7 +40,6 @@ Extras:
Cli:
☐ optionally show output window in a split screen window
☐ lower the chepy prompt lower. that empty space is not being used
☐ pyinstaller package as single file
☐ write to file with prompt toolkit path autocomplete
☐ pipe input to chepy

Expand All @@ -51,9 +48,7 @@ Enhance:
Plugins:

Methods:
☐ windings decoding/encoding ♐︎●︎♋︎♑︎❀︎♏︎📁︎🖮︎🖲︎📂︎♍︎♏︎⌛︎🖰︎♐︎🖮︎📂︎🖰︎📂︎🖰︎🖰︎♍︎📁︎🗏︎🖮︎🖰︎♌︎📂︎♍︎📁︎♋︎🗏︎♌︎♎︎♍︎🖲︎♏︎❝︎ f︎l︎a︎g︎{︎e︎0︎7︎9︎1︎c︎e︎6︎8︎f︎7︎1︎8︎1︎8︎8︎c︎0︎3︎7︎8︎b︎1︎c︎0︎a︎3︎b︎d︎c︎9︎e︎}︎
☐ magic method from cyberchef
☐ base 36
☐ base 62
☐ base 92

Expand All @@ -67,6 +62,10 @@ Misc:
☐ cyberchef recipe to chepy recipe converter

Archive:
✔ 🚀 add crib for xor bruteforce
✔ ✨ twin hex encoder/decoder
✔ ✨ base36 encoder decoder
✔ ✨ decorator that will show warning message if unexpected results in stdout
✔ ✨ concat method
✔ ✨ nt hash
✔ ✨ lm hash
Expand Down
15 changes: 15 additions & 0 deletions chepy/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,21 @@ def _str_to_bytes(self, s: str) -> bytes: # pragma: no cover
return s
return s.encode()

def _bytes_to_str(self, s: bytes) -> str: # pragma: no cover
"""Converts a bytes to str
Args:
s (str): String
Returns:
str: String
"""
if s is None:
return s
if isinstance(s, bytes):
return s.decode()
return s

def _convert_to_int(self) -> int:
"""This method is used to coerce the curret object in
the state variable into an int. The method should be
Expand Down
7 changes: 5 additions & 2 deletions chepy/core.pyi
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, List, Mapping, Tuple, Union, TypeVar, Literal, Callable
from typing import Any, List, Mapping, Tuple, Union, TypeVar, Literal, Callable, Dict

jsonpickle: Any

Expand All @@ -22,7 +22,8 @@ class ChepyCore:
def _convert_to_bytearray(self) -> bytearray: ...
def _convert_to_str(self) -> str: ...
def _convert_to_int(self) -> int: ...
def _str_to_bytes(self, s: str) -> int: ...
def _str_to_bytes(self, s: str) -> bytes: ...
def _bytes_to_str(self, s: bytes) -> str: ...
@property
def state(self): ...
@state.setter
Expand Down Expand Up @@ -56,6 +57,8 @@ class ChepyCore:
def load_file(self: ChepyCoreT, binary_mode: bool=...) -> ChepyCoreT: ...
def write_to_file(self: ChepyCoreT, path: str) -> None: ...
def write_binary(self: ChepyCoreT, path: str) -> None: ...
@property
def recipe(self) -> List[Dict[str, Union[str, Dict[str, Any]]]]: ...
def run_recipe(self: ChepyCoreT, recipes: List[Mapping[str, Union[str, Mapping[str, Any]]]]) -> ChepyCoreT: ...
def save_recipe(self: ChepyCoreT, path: str) -> ChepyCoreT: ...
def load_recipe(self: ChepyCoreT, path: str) -> ChepyCoreT: ...
Expand Down
147 changes: 147 additions & 0 deletions chepy/modules/dataformat.py
Original file line number Diff line number Diff line change
Expand Up @@ -1489,3 +1489,150 @@ def from_wingdings(self) -> DataFormatT:
hold += conv.get(ord(i), i)
self.state = hold.encode()
return self

@ChepyDecorators.call_stack
def from_twin_hex(self) -> DataFormatT:
"""Decode twin hex
Returns:
Chepy: The Chepy object.
"""
spaceChar = " "
cypherBase = []
for x in range(32, 128):
for y in range(32, 128):
thisPair = chr(x) + chr(y)
cypherBase.append(thisPair)

def tripleSplit(strInput):
outArray = []
thisTriple = ""
i = 0
while i < len(strInput):
thisTriple = strInput[i]
i += 1
if i < len(strInput):
thisTriple += strInput[i]
else: # pragma: no cover
thisTriple += spaceChar
i += 1
if i < len(strInput):
thisTriple += strInput[i]
else: # pragma: no cover
thisTriple += spaceChar
outArray.append(thisTriple)
i += 1
return outArray

def base36_encode(string):
return int(string, 36)

inputArray = tripleSplit(self._convert_to_str())
strOutput = ""
thisPair = ""
for code in inputArray:
if code and len(code):
thisCode = base36_encode(code)
thisPair = cypherBase[thisCode]
strOutput += thisPair
self.state = strOutput.encode()
return self

@ChepyDecorators.call_stack
def to_twin_hex(self) -> DataFormatT:
"""Encode to twin hex encoding
Returns:
Chepy: The Chepy object.
"""

def base36_decode(number):
alphabet = "0123456789abcdefghijklmnopqrstuvwxyz"
if number == 0: # pragma: no cover
return "0"
base36 = ""
while number != 0:
number, i = divmod(number, 36)
base36 = alphabet[i] + base36
return base36

def dHex(thisPair):
intCode = cypherBase.index(thisPair)
strOutput = base36_decode(intCode)
if len(strOutput) == 2: # pragma: no cover
return strOutput + spaceChar
else:
return strOutput

spaceChar = " "
cypherBase = []
for x in range(32, 128):
for y in range(32, 128):
thisPair = chr(x) + chr(y)
cypherBase.append(thisPair)

strInput = self._convert_to_str()
strOutput = ""
thisPair = ""
i = 0
while i < len(strInput):
thisPair = strInput[i]
i += 1
if i < len(strInput):
thisPair += strInput[i]
else: # pragma: no cover
thisPair += spaceChar
strOutput += dHex(thisPair)
i += 1
self.state = strOutput.encode()
return self

@ChepyDecorators.call_stack
def from_base36(
self, delimiter: Union[str, bytes] = " ", join_by: Union[str, bytes] = " "
) -> DataFormatT:
"""Decode Base36 data
Args:
delimiter (Union[str, bytes], optional): Delimiter to split groups of ints by. Defaults to ' '.
join_by (Union[str, bytes], optional): Join final output by. Defaults to ' '.
Returns:
Chepy: The Chepy object.
"""
delimiter = self._bytes_to_str(delimiter)
join_by = self._bytes_to_str(join_by)
data = self._convert_to_str().split(delimiter)
hold = []

alphabet = "0123456789abcdefghijklmnopqrstuvwxyz"
for number in data:
number = int(number)
if number == 0:
return "0" # pragma: no cover
base36 = ""
while number != 0:
number, i = divmod(number, 36)
base36 = alphabet[i] + base36
hold.append(base36)
self.state = join_by.join(hold)
return self

@ChepyDecorators.call_stack
def to_base36(self, join_by: Union[str, bytes] = b" ") -> DataFormatT:
"""Encode to Base 36
Args:
join_by (Union[str, bytes], optional): Join final output by. Defaults to b' '.
Returns:
Chepy: The Chepy object.
"""
join_by = self._str_to_bytes(join_by)
data = self._convert_to_str()
data = re.compile(r"[^a-zA-Z0-9]").sub(" ", data).split()
hold = []
for d in data:
hold.append(str(int(d.strip(), 36)).encode())
self.state = join_by.join(hold)
return self
8 changes: 6 additions & 2 deletions chepy/modules/dataformat.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,9 @@ class DataFormat(ChepyCore):
def long_to_bytes(self: DataFormatT) -> DataFormatT: ...
def bytes_to_long(self: DataFormatT) -> DataFormatT: ...
def concat(self: DataFormatT, data: Union[str, bytes]) -> DataFormatT: ...
def to_wingdings(self) -> DataFormatT: ...
def from_wingdings(self) -> DataFormatT: ...
def to_wingdings(self: DataFormatT) -> DataFormatT: ...
def from_wingdings(self: DataFormatT) -> DataFormatT: ...
def to_twin_hex(self: DataFormatT) -> DataFormatT: ...
def from_twin_hex(self: DataFormatT) -> DataFormatT: ...
def to_base36(self: DataFormatT, join_by: Union[str, bytes]=...) -> DataFormatT: ...
def from_base36(self: DataFormatT, delimiter: Union[str, bytes]=..., join_by: Union[str, bytes]=...) -> DataFormatT: ...
14 changes: 11 additions & 3 deletions chepy/modules/encryptionencoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import codecs
import itertools
import string
from typing import Literal, TypeVar, Dict, Any
from typing import Literal, TypeVar, Dict, Any, Union

import lazy_import

Expand Down Expand Up @@ -313,14 +313,17 @@ def xor(
return self

@ChepyDecorators.call_stack
def xor_bruteforce(self, length: int = 100) -> EncryptionEncodingT:
def xor_bruteforce(
self, length: int = 100, crib: Union[bytes, str, None] = None
) -> EncryptionEncodingT:
"""Brute force single byte xor
For multibyte xor bruteforce, use chepy.extras.crypto_extras.xor_bruteforce_multi
function
Args:
length (int, optional): How to bytes to bruteforce. Defaults to 100.
crib (Union[bytes, str, None], optional): Check for crib in xored value. Defaults to None.
Returns:
Chepy: The Chepy object.
Expand All @@ -339,13 +342,18 @@ def xor_bruteforce(self, length: int = 100) -> EncryptionEncodingT:
>>> c.xor("03").bytearray_to_str()
pf`qfw
"""
crib = self._str_to_bytes(crib)
original = self.state
found = {}
keys = hex_chars()
self.state = original[:length]
for key in keys:
self.xor(key)
found[key] = self.state
if crib is not None:
if crib in self.state:
found[key] = self.state
else:
found[key] = self.state
self.state = original[:length]
self.state = found
return self
Expand Down
2 changes: 1 addition & 1 deletion chepy/modules/encryptionencoding.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class EncryptionEncoding(ChepyCore):
def rot_47_bruteforce(self: EncryptionEncodingT) -> EncryptionEncodingT: ...
def rot_8000(self: EncryptionEncodingT) -> EncryptionEncodingT: ...
def xor(self: EncryptionEncodingT, key: Union[str, bytearray], key_type: Literal['hex', 'utf', 'base64', 'decimal']=..., ascii: bool=...) -> EncryptionEncodingT: ...
def xor_bruteforce(self: EncryptionEncodingT, length: int=...) -> EncryptionEncodingT: ...
def xor_bruteforce(self: EncryptionEncodingT, length: int=..., crib: Union[str, bytes, None]=...) -> EncryptionEncodingT: ...
def jwt_decode(self: EncryptionEncodingT) -> EncryptionEncodingT: ...
def jwt_verify(self: EncryptionEncodingT, secret: str, algorithm: list=...) -> EncryptionEncodingT: ...
def jwt_sign(self: EncryptionEncodingT, secret: str, algorithms: str=...) -> EncryptionEncodingT: ...
Expand Down
Loading

0 comments on commit 615bac8

Please sign in to comment.