Cryptography
Cryptography is for secure communications. It uses a wide variety of techniques.
CyberChef Magic
CyberChef is a swiss army knife for cryptography.
Especially, "Magic" tool can process the given hashes automatically.
So it's recommended to use the "Magic" at first. It can be found on the left pane.
quipqiup
quipqiup is an online cryptogram solver. It can solve substitution ciphers often found in newspapers, including puzzles like cryptoquips and patristocrats.
OSINT
Before cracking, hashes might be revealed online so worth searching them with search engines.
Below are Google Dorks for this purpose. Note that hashes are surrounded with double-quotes.
Also we can use online tools to decrypt.
Identify the Cipher
Online Tools
CLIs
Manual Identification
The following cryptos mean "hello".
# Base32
NBSWY3DPEB3W64TMMQ======
# Base58
StV1DL6CwTryKyV
# Base64
aGVsbG8gd29ybGQ=
# Binary
01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111 01110010 01101100 01100100
# Decimal
104 101 108 108 111 32 119 111 114 108 100
# Hex
68 65 6c 6c 6f 20 77 6f 72 6c 64
68656c6c6f20776f726c64
# Morse Code
.... . .-.. .-.. ---
.-- --- .-. .-.. -..
# MD4
aa010fbc1d14c795d86ef98c95479d17
# MD5
5eb63bbbe01eeed093cb22bb8f5acdc3
# ROT13
uryyb jbeyq
# ROT47
96==@ H@C=5
# SHA1
2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
# SHA256
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
# SHA512
9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
Binary Data Manual Operations
Using Python.
1. Change Hex to Base
import codecs
hex = "49276d206b6e6f"
b64 = codecs.encode(codecs.decode(hex, 'hex'), 'base64').decode()
print(b64)
2. XOR
- Basic XOR
hex1 = "1c0111001f010100061a024b53535009181c"
hex2 = "686974207468652062756c6c277320657965"
xored_hex = hex(int(hex1, 16) ^ int(hex2, 16))
# Display without prefix '0x' by slicing [2:]
print(xored_hex[2:])
- Single-Byte XOR
# Basic function
def single_byte_xor(text: bytes, key: int) -> bytes:
return bytes([b ^ key for b in text])
# ---------------------------------------------------------------
# Enctyption
ciphertext = single_byte_xor(b"hello", 69)
print(ciphertext)
# Decryption
ciphertext = single_byte_xor(b"- ))*", 69)
print(ciphertext)
- Crack Single-Byte XOR
import random
import string
from collections import Counter
from typing import Tuple
def single_byte_xor(text: bytes, key: int) -> str:
return bytes([b ^ key for b in text])
def fitting_quotient(text: bytes) -> float:
counter = Counter(text)
dist_text = [
(counter.get(ord(ch), 0) * 100) / len(text)
for ch in occurence_english
]
return sum([abs(a - b) for a, b in zip(dist_english, dist_text)]) / len(dist_text)
def decipher(text: bytes) -> Tuple[bytes, int]:
original_text, encryption_key, min_fq = None, None, None
for k in range(256):
# Generate the plaintext using encryption key 'k'
_text = single_byte_xor(text, k)
# Compute the fitting quotient for this decrypted plaintext
fq = fitting_quotient(_text)
# If the fitting quotient of this generated plaintext is less than the minimum seen till now 'min_fq' we update.
if min_fq is None or fq < min_fq:
encryption_key, original_text, min_fq = k, _text, fq
# Return the text and key that has the minimum fitting quotient
return original_text, encryption_key
plaintext = b"Hello world"
plaintext = plaintext.lower()
key = 82
ciphertext = single_byte_xor(plaintext, key)
occurence_english = {
'a': 8.2389258, 'b': 1.5051398, 'c': 2.8065007, 'd': 4.2904556,
'e': 12.813865, 'f': 2.2476217, 'g': 2.0327458, 'h': 6.1476691,
'i': 6.1476691, 'j': 0.1543474, 'k': 0.7787989, 'l': 4.0604477,
'm': 2.4271893, 'n': 6.8084376, 'o': 7.5731132, 'p': 1.9459884,
'q': 0.0958366, 'r': 6.0397268, 's': 6.3827211, 't': 9.1357551,
'u': 2.7822893, 'v': 0.9866131, 'w': 2.3807842, 'x': 0.1513210,
'y': 1.9913847, 'z': 0.0746517
}
dist_english = list(occurence_english.values())
sentences = [
b'His mind was blown that there was nothing in space except space itself.',
b'I love bacon, beer, birds, and baboons.',
b'With a single flip of the coin, his life changed forever.',
b'The three-year-old girl ran down the beach as the kite flew behind her.',
]
for sentence in sentences:
sentence = sentence.lower()
encryption_key = random.randint(10, 220)
assert decipher(single_byte_xor(sentence, encryption_key)) == (sentence, encryption_key,)
(_plaintext, _key) = decipher(single_byte_xor(sentence, encryption_key))
print(_plaintext)
print(_key)
print("\n")
Crack Hashes
-
Online Tools
-
Cracking Tools
First of all, you need to put the hash into the file like the following.
If you don't know which hash type it is, **[Example Hashes](https://hashcat.net/wiki/doku.php?id=example_hashes)** may help you.
For brute forcing without wordlists in Hashcat, use the following command.
Wordlists for Cracking
Fetch Wordlists
Wordlistctl is a CLI that fetches, installs and searches wordlist archives from websites and torrent peers.
To fetch the wordlist, run as follow:
# -l: Wordlist
# -d: Decompress and remove archive
wordlistctl fetch -l dogs -d /usr/share/wordlists/misc/dogs.txt
wordlistctl fetch -l top_1000_usa_malenames_english -d /usr/share/wordlists/misc/top_1000_usa_malename_english.txt
wordlistctl fetch -l femalenames-usa-top1000 -d /usr/share/wordlists/usernames/femalenames-usa-top1000
Custom Wordlist
Below are some techniques to customize wordlists.
# Replace all 'c' with '$'
sed 's/c/$/g' origin.txt > new.txt
# Toggle the case of the second character
sed 's/\(.\)\(.\)\(.*\)/\1\U\2\E\3/g' origin.txt > new.txt
Encrypt Files
Useful Commands
- Generate Random Strings