Skip to content

Commit

Permalink
🗓 Jul 4, 2023 9:02:35 PM
Browse files Browse the repository at this point in the history
🤖 types added/updated
🧪 tests added/updated
🚀 loop methods updated on core
🎨 small changes
  • Loading branch information
securisec committed Jul 5, 2023
1 parent 7b6314f commit dc247f1
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 94 deletions.
24 changes: 24 additions & 0 deletions chepy/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,19 @@ def _convert_to_str(self) -> str:
# todo check more types here
raise NotImplementedError

def _str_to_bytes(self, s: str) -> bytes: # pragma: no cover
"""Converts a str to bytes
Args:
s (str): String
Returns:
bytes: Bytes
"""
if isinstance(s, bytes):
return s
return s.encode()

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 Expand Up @@ -1061,6 +1074,9 @@ def loop(self, iterations: int, callback: str, args: dict = {}):
>>> c.loop(iterations=6, callback='hmac_hash', args={'key': 'secret'})
securisec
"""
if type(callback).__name__ == 'method':
# this allows for both method and string passing
callback = callback.__name__
assert isinstance(callback, str), "Callback must be a string"
assert isinstance(iterations, int), "Iterations must be an intiger"
assert isinstance(args, dict), "Args must be a dick"
Expand Down Expand Up @@ -1097,6 +1113,10 @@ def loop_list(self, callback: str, args: dict = {}):
>>> c.loop_list('to_hex').loop_list('hmac_hash', {'key': 'secret'})
['5cbe6ca2a66b380aec1449d4ebb0d40ac5e1b92e', '30d75bf34740e8781cd4ec7b122e3efd8448e270']
"""
if type(callback).__name__ == 'method':
# this allows for both method and string passing
callback = callback.__name__

assert isinstance(self.state, list), "State is not a list"
assert isinstance(callback, str), "Callback must be a string"
hold = []
Expand Down Expand Up @@ -1154,7 +1174,11 @@ def loop_dict(self, keys: list, callback: str, args: dict = {}):
{"another": "aaaa"},
]
"""
if type(callback).__name__ == 'method':
# this allows for both method and string passing
callback = callback.__name__
assert isinstance(callback, str), "Callback must be a string"

hold = {}
current_state = self.state
# find the last index that this method was run
Expand Down
15 changes: 10 additions & 5 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
from typing import Any, List, Mapping, Tuple, Union, TypeVar, Literal, Callable

jsonpickle: Any

Expand All @@ -18,11 +18,16 @@ class ChepyCore:
log_level: Any = ...
log_format: str = ...
def __init__(self, *data: Any) -> None: ...
def _convert_to_bytes(self) -> bytes: ...
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: ...
@property
def state(self): ...
@state.setter
def state(self: ChepyCoreT, val: Any) -> None: ...
def fork(self: ChepyCoreT, methods: List[Tuple[Union[str, object], dict]]) -> ChepyCoreT: ...
def fork(self: ChepyCoreT, methods: List[Tuple[Union[str, Callable], dict]]) -> ChepyCoreT: ...
def for_each(self: ChepyCoreT, methods: List[Tuple[Union[str, object], dict]]) -> ChepyCoreT: ...
def set_state(self: ChepyCoreT, data: Any) -> ChepyCoreT: ...
def create_state(self: ChepyCoreT): ...
Expand Down Expand Up @@ -56,9 +61,9 @@ class ChepyCore:
def save_recipe(self: ChepyCoreT, path: str) -> ChepyCoreT: ...
def load_recipe(self: ChepyCoreT, path: str) -> ChepyCoreT: ...
def run_script(self: ChepyCoreT, path: str, save_state: bool=...) -> ChepyCoreT: ...
def loop(self: ChepyCoreT, iterations: int, callback: str, args: dict=...) -> ChepyCoreT: ...
def loop_list(self: ChepyCoreT, callback: str, args: dict=...) -> ChepyCoreT: ...
def loop_dict(self: ChepyCoreT, keys: list, callback: str, args: dict=...) -> ChepyCoreT: ...
def loop(self: ChepyCoreT, iterations: int, callback: Union[str, Callable], args: dict=...) -> ChepyCoreT: ...
def loop_list(self: ChepyCoreT, callback: Union[str, Callable], args: dict=...) -> ChepyCoreT: ...
def loop_dict(self: ChepyCoreT, keys: list, callback: Union[str, Callable], args: dict=...) -> ChepyCoreT: ...
def debug(self: ChepyCoreT, verbose: bool=...) -> ChepyCoreT: ...
def reset(self: ChepyCoreT): ...
def load_command(self: ChepyCoreT): ...
Expand Down
62 changes: 11 additions & 51 deletions chepy/modules/encryptionencoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ def __check_mode(self, mode) -> None:
def _convert_key(
self, key, iv, key_format: str, iv_format: str
) -> EncryptionEncodingT: # pragma: no cover
if isinstance(key, str):
key = key.encode()
key = self._str_to_bytes(key)
# modify key according to mode
if key_format == "hex":
key = binascii.unhexlify(key)
Expand All @@ -66,8 +65,7 @@ def _convert_key(
key = key.decode().encode("latin-1")

# modify iv according to mode
if isinstance(iv, str):
iv = iv.encode()
iv = self._str_to_bytes(iv)
if iv_format == "hex":
iv = binascii.unhexlify(iv)
if iv_format == "base64" or iv_format == "b64":
Expand Down Expand Up @@ -101,7 +99,7 @@ def rotate(self, rotate_by: int) -> EncryptionEncodingT:
lookup = str.maketrans(
lc + uc, lc[rotate_by:] + lc[:rotate_by] + uc[rotate_by:] + uc[:rotate_by]
)
self.state = self.state.translate(lookup)
self.state = self.state.translate(lookup).encode()
return self

@ChepyDecorators.call_stack
Expand Down Expand Up @@ -132,7 +130,7 @@ def rotate_bruteforce(self) -> EncryptionEncodingT:
lc + uc,
lc[rotate_by:] + lc[:rotate_by] + uc[rotate_by:] + uc[:rotate_by],
)
hold[str(rotate_by)] = self.state.translate(lookup)
hold[str(rotate_by)] = self.state.translate(lookup).encode()
self.state = hold
return self

Expand Down Expand Up @@ -164,7 +162,7 @@ def rot_47(self, rotation: int = 47) -> EncryptionEncodingT:
Examples:
>>> Chepy("some").rot_47().out
"D@>6"
b"D@>6"
"""
decoded_string = ""
for char in self._convert_to_str():
Expand All @@ -173,7 +171,7 @@ def rot_47(self, rotation: int = 47) -> EncryptionEncodingT:
decoded_string += decoded_char
else:
decoded_string += char # pragma: no cover
self.state = decoded_string
self.state = decoded_string.encode()
return self

@ChepyDecorators.call_stack
Expand All @@ -193,7 +191,7 @@ def rot_47_bruteforce(self) -> EncryptionEncodingT:
decoded_string += decoded_char
else:
decoded_string += char # pragma: no cover
hold[str(r)] = decoded_string
hold[str(r)] = decoded_string.encode()
self.state = hold
return self

Expand Down Expand Up @@ -265,7 +263,8 @@ def rot_8000(self):
# otherwise, rotate it and add it to the string
outstring += rotlist[char]

return outstring
self.state = outstring.encode()
return self

@ChepyDecorators.call_stack
def xor(
Expand Down Expand Up @@ -300,12 +299,8 @@ def xor(
key = binascii.hexlify(base64.b64decode(key.encode()))
key = binascii.unhexlify(key)
x = bytearray(b"")
try:
for char, key_val in zip(self._convert_to_str(), itertools.cycle(key)):
x.append(ord(char) ^ key_val)
except:
for char, key_val in zip(self._convert_to_bytes(), itertools.cycle(key)):
x.append(char ^ key_val)
for char, key_val in zip(self._convert_to_bytes(), itertools.cycle(key)):
x.append(char ^ key_val)

self.state = x
return self
Expand Down Expand Up @@ -397,41 +392,6 @@ def jwt_sign(self, secret: str, algorithms: str = "HS256") -> EncryptionEncoding
self.state = jwt.encode(data, key=secret, algorithm=algorithms)
return self

@ChepyDecorators.call_stack
def jwt_bruteforce(
self, wordlist: str, b64_encode: bool = False, algorithm: list = ["HS256"]
) -> EncryptionEncodingT:
"""Brute force JWT token secret
This method will use the provided wordlist to try and bruteforce the
verification.
Args:
wordlist (str): Required. Path to a wordlist
b64_encode (bool, optional): Encoded the words in base64. Defaults to False.
algorithm (list, optional): Array of valid algorithms. Defaults to ["HS256"].
Returns:
Chepy: The Chepy object.
"""
with open(pathlib.Path(wordlist).expanduser().absolute()) as words:
for word in words:
try:
word = word.strip()
if b64_encode: # pragma: no cover
word = base64.b64encode(word)
j = jwt.decode(self._convert_to_str(), word, algorithms=algorithm)
self.state = {
"paylod": j,
"header": jwt.get_unverified_header(self._convert_to_str()),
"secret": word,
}
return self
except jwt.InvalidSignatureError:
continue
else: # pragma: no cover
return self

@ChepyDecorators.call_stack
def jwt_token_generate_none_alg(
self, headers: Dict[str, Any] = {}
Expand Down
1 change: 0 additions & 1 deletion chepy/modules/encryptionencoding.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ class EncryptionEncoding(ChepyCore):
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: ...
def jwt_bruteforce(self: EncryptionEncodingT, wordlist: str, b64_encode: bool=..., algorithm: list=...) -> EncryptionEncodingT: ...
def jwt_token_generate_none_alg(self: EncryptionEncodingT, headers: Dict[str, Any]=...) -> EncryptionEncodingT: ...
def jwt_token_generate_embedded_jwk(self: EncryptionEncodingT, private_key_pem: str, private_key_passphrase: str = ..., headers: dict = ..., alg: str = Union["RS256", "RS512"]) -> EncryptionEncodingT: ...
def rc4_encrypt(self: EncryptionEncodingT, key: str, key_format: RC4_FORMAT=...) -> EncryptionEncodingT: ...
Expand Down
14 changes: 9 additions & 5 deletions chepy/modules/extractors.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ def extract_hashes(self) -> ExtractorsT:
return self

@ChepyDecorators.call_stack
def extract_strings(self, length: int = 4, join_by: str = "\n") -> ExtractorsT:
def extract_strings(
self, length: int = 4, join_by: Union[str, bytes] = "\n"
) -> ExtractorsT:
"""Extract strings from state
Args:
Expand All @@ -73,7 +75,7 @@ def extract_strings(self, length: int = 4, join_by: str = "\n") -> ExtractorsT:
"""
pattern = b"[^\x00-\x1F\x7F-\xFF]{" + str(length).encode() + b",}"
matches = re.findall(pattern, self._convert_to_bytes())
self.state = join_by.join([m.decode() for m in matches])
self.state = self._str_to_bytes(join_by).join([m for m in matches])
return self

@ChepyDecorators.call_stack
Expand Down Expand Up @@ -123,7 +125,7 @@ def extract_email(self, is_binary: bool = False) -> ExtractorsT:
matched = list(
filter(
lambda x: re.search(pattern, x),
self.extract_strings().o.encode().splitlines(),
self.extract_strings().o.splitlines(),
)
)
else: # pragma: no cover
Expand Down Expand Up @@ -543,7 +545,7 @@ def decode_zero_width(
Returns:
Chepy: The Chepy object.
"""

def set_use_chars(newchars):
global _zw_chars, _zw_radix, _zw_codelengthText
if len(newchars) >= 2:
Expand All @@ -554,7 +556,9 @@ def set_use_chars(newchars):

def split_zerowidth_characters(str1):
result = {}
result["originalText"] = old_re.sub("[" + "".join(_zw_chars) + "]", "", str1)
result["originalText"] = old_re.sub(
"[" + "".join(_zw_chars) + "]", "", str1
)
result["hiddenText"] = old_re.sub("[^" + "".join(_zw_chars) + "]", "", str1)
return result

Expand Down
10 changes: 8 additions & 2 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,12 @@ def test_loop():
.o
== b"securisec"
)
c = Chepy("VmpGb2QxTXhXWGxTYmxKV1lrZDRWVmx0ZEV0alZsSllaVWRHYWxWVU1Eaz0=")
assert (
c.loop(6, c.from_base64)
.o
== b"securisec"
)


def test_loop_list():
Expand All @@ -180,7 +186,7 @@ def test_loop_list():
"30d75bf34740e8781cd4ec7b122e3efd8448e270",
]
c1 = Chepy(["an", "array"])
c1.loop_list("to_hex").loop_list("hmac_hash", {"key": "secret"})
c1.loop_list("to_hex").loop_list(c.hmac_hash, {"key": "secret"})
assert c1.o == [
"5cbe6ca2a66b380aec1449d4ebb0d40ac5e1b92e",
"30d75bf34740e8781cd4ec7b122e3efd8448e270",
Expand All @@ -199,7 +205,7 @@ def test_loop_dict():
]

d = Chepy({"some": "hahahaha", "lol": "aahahah"})
d.loop_dict(["some"], "to_upper_case")
d.loop_dict(["some"], d.to_upper_case)
assert d.o == {"some": "HAHAHAHA", "lol": "aahahah"}

e = Chepy({"some": "hahahaha", "lol": "aahahah"})
Expand Down
Loading

0 comments on commit dc247f1

Please sign in to comment.