Exploit Notes

# Cryptography

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.

``````"WVLY0mgH0RtUI"
"5d41402abc4b2a76b9719d911017c592"
``````

Also we can use online tools to decrypt.

## Identify the Cipher

### 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
``````

## 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

1. Online Tools

2. Cracking Tools

First of all, you need to put the hash into the file like the following.

``````echo -n '4bc9ae2b9236c2ad02d81491dcb51d5f' > hash.txt
``````

If you don't know which hash type it is, Example Hashes may help you.

For brute forcing without wordlists in Hashcat, use the following command.

``````hashcat -m <hash-mode> -a 3 '?a?a?a?a?a'
``````

## 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

``````openssl enc -in /etc/passwd -out /tmp/passwd
openssl enc -in /tmp/passwd -out /etc/passwd
``````

## Useful Commands

• Generate Random Strings

``````# Hex encoded password
openssl rand -hex 4
``````

#### Tools by HDKS

Fuzzagotchi

Automatic web fuzzer.

aut0rec0n

Auto reconnaissance CLI.

Hash Cracker

Hash identifier.