Encodings
ASCII
ASCII is a 7-bit encoding standard which allows the representation of
text using the integers 0-127.
1 2 3 arr = [99 , 114 , 121 , 112 , 116 , 111 , 123 , 65 , 83 , 67 , 73 , 73 , 95 , 112 , 114 , 49 , 110 , 116 , 52 , 98 , 108 , 51 , 125 ] result = "" .join(chr (x) for x in arr) print (result)
1 2 ❯ python encoding.py crypto{ASCII_pr1nt4bl3}
crypto{ASCII_pr1nt4bl3}
Hex
Hexadecimal can be used to represent ASCII strings. First each letter
is converted to an ordinal number according to the ASCII table. Then the
decimal numbers are converted to base-16 numbers.
1 2 3 a = 0x63727970746f7b596f755f77696c6c5f62655f776f726b696e675f776974685f6865785f737472696e67735f615f6c6f747d result = bytes .fromhex(hex (a)[2 :]).decode() print (result)
1 2 ❯ python hex.py crypto{You_will_be_working_with_hex_strings_a_lot}
crypto{You_will_be_working_with_hex_strings_a_lot}
Base64
Base64 allows us to represent binary data as an ASCII string using an
alphabet of 64 characters.
1 2 3 4 import base64h = '72bca9b68fc16ac7beeb8f849dca1d8a783e8acf9679bf9269f7bf' a = base64.b64encode(bytes .fromhex(h)) print (a.decode())
1 crypto/Base+64+Encoding+is+Web+Safe/
crypto/Base+64+Encoding+is+Web+Safe/
Bytes and Big Integers
Cryptosystems like RSA works on numbers, but messages are made up of
characters. The most common way is to take the ordinal bytes of the
message, convert them into hexadecimal, and concatenate.
1 2 3 4 from Crypto.Util.number import *enc = "11515195063862318899931685488813747395775516287289682636499965282714637259206269" result = long_to_bytes(int (enc)).decode() print (result)
1 crypto{3nc0d1n6_4ll_7h3_w4y_d0wn}
crypto{3nc0d1n6_4ll_7h3_w4y_d0wn}
Encoding Challenge
Automating the decoding process for 100 levels.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 import base64import codecsimport jsonfrom Crypto.Util.number import *from pwn import *def base64_decode (encoded ): return base64.b64decode(encoded.encode()).decode() def rot13_decode (encoded ): return codecs.decode(encoded, "rot13" ) def hex_decode (encoded ): return bytes .fromhex(encoded).decode() def bigint_decode (encoded ): return bytes .fromhex(encoded[2 :]).decode() def utf8_decode (encoded ): return "" .join([chr (x) for x in encoded]) r = remote("socket.cryptohack.org" , 13377 , level="debug" ) def json_recv (): return json.loads(r.recvline().decode()) def json_send (hsh ): r.sendline(json.dumps(hsh).encode()) def decode (type , encoded ): match type : case "base64" : return base64_decode(encoded) case "rot13" : return rot13_decode(encoded) case "hex" : return hex_decode(encoded) case "bigint" : return bigint_decode(encoded) case "utf-8" : return utf8_decode(encoded) case _: return None while True : received = json_recv() if "flag" in received: print (f"Flag: {received['flag' ]} " ) break to_send = {"decoded" : decode(received["type" ], received["encoded" ])} json_send(to_send)
crypto{3nc0d3_d3c0d3_3nc0d3}
XOR
XOR Starter
XOR each character of the string label with the integer
13.
1 2 3 4 5 from pwn import xora = "label" b = 13 result = xor(a.encode(), b).decode() print (f"crypto{{{result} }}" )
crypto{aloha}
XOR Properties
Using XOR properties: Commutative, Associative, Identity, and
Self-Inverse.
1 2 3 4 5 6 7 8 9 10 from pwn import xorKEY1 = "a6c8b6733c9b22de7bc0253266a3867df55acde8635e19c73313" KEY2_KEY1 = "37dcb292030faa90d07eec17e3b1c6d8daf94c35d4c9191a5e1e" KEY2_KEY3 = "c1545756687e7573db23aa1c3452a098b71a7fbf0fddddde5fc1" FLAG_K1_K2_K3 = "04ee9855208a2cd59091d04767ae47963170d1660df7f56f5faf" k1_k2_k3 = xor(bytes .fromhex(KEY1), bytes .fromhex(KEY2_KEY3)) FLAG = xor(bytes .fromhex(FLAG_K1_K2_K3), k1_k2_k3) print (FLAG.decode())
crypto{x0r_i5_ass0c1at1v3}
Favourite byte
XOR with a single secret byte.
1 2 3 4 5 6 from pwn import xordata = bytes .fromhex("73626960647f6b206821204f21254f7d694f7624662065622127234f726927756d" ) for i in range (256 ): res = xor(data, i) if b"crypto" in res: print (res.decode())
crypto{0x10_15_my_f4v0ur173_by7e}
You either know, XOR you
don't
Brute-forcing the key using the known flag format
crypto{.
1 2 3 4 5 from pwn import xorciphertext = bytes .fromhex("0e0b213f26041e480b26217f27342e175d0e070a3c5b103e2526217f27342e175d0e077e263451150104" ) key_part = xor(ciphertext[:7 ], b"crypto{" ) key = b"myXORkey" print (xor(ciphertext, key).decode())
crypto{1f_y0u_Kn0w_En0uGH_y0u_Kn0w_1t_4ll}
Lemur XOR
Visual XOR between the RGB bytes of two images.
1 2 3 4 5 6 from PIL import Imageimport numpy as npimg_flag = np.array(Image.open ("./flag.png" )) img_lemur = np.array(Image.open ("./lemur.png" )) result = np.bitwise_xor(img_flag, img_lemur) Image.fromarray(result).save("./result.png" )
crypto{X0Rly_n0t!}
Mathematics
Greatest Common Divisor
Using Euclid's Algorithm to find the GCD.
1 2 3 4 5 6 def gcd (a, b ): while b: a, b = b, a % b return a print (gcd(66528 , 52920 ))
1512
Extended GCD
Finding integers \(u, v\) such that
\(a \cdot u + b \cdot v = \gcd(a,
b)\) .
1 2 3 4 5 6 7 8 9 10 11 def extended_gcd (a, b ): if a == 0 : return b, 0 , 1 gcd, x1, y1 = extended_gcd(b % a, a) x = y1 - (b // a) * x1 y = x1 return gcd, x, y p, q = 26513 , 32321 g, u, v = extended_gcd(p, q) print (min (u, v))
-8404
Modular Arithmetic 1
Finding the remainder of \(a\)
divided by \(m\) .
1 2 3 x = 11 % 6 y = 8146798528947 % 17 print (min (x, y))
2
Modular Arithmetic 2
Fermat's Little Theorem: \(a^{p-1} \equiv 1
\pmod{p}\) if \(p\) is prime and
\(p \nmid a\) .
1 2 p = 65537 print (pow (273246787654 , 65536 , 65537 ))
1
Modular Arithmetic 3
Finding the multiplicative inverse \(d =
3^{-1} \pmod{13}\) .
9
Privacy-Enhanced Mail?
Extracting the private key \(d\)
from a PEM-formatted RSA key.
1 2 3 4 from Crypto.PublicKey import RSAwith open ("privacy_enhanced_mail.pem" , "r" ) as f: key = RSA.import_key(f.read()) print (key.d)
15682700288056331364787171045819973654991149949197959929860861228180021707316851924456205543665565810892674190059831330231436970914474774562714945620519144389785158908994181951348846017432506464163564960993784254153395406799101314760033445065193429592512349952020982932218524462341002102063435489318813316464511621736943938440710470694912336237680219746204595128959161800595216366237538296447335375818871952520026993102148328897083547184286493241191505953601668858941129790966909236941127851370202421135897091086763569884760099112291072056970636380417349019579768748054760104838790424708988260443926906673795975104689
CERTainly not
Finding the modulus of a DER-encoded x509 RSA certificate.
1 2 3 4 from Crypto.PublicKey import RSAwith open ("2048b-rsa-example-cert.der" , "rb" ) as f: key = RSA.import_key(f.read()) print (key.n)
22825373692019530804306212864609512775374171823993708516509897631547513634635856375624003737068034549047677999310941837454378829351398302382629658264078775456838626207507725494030600516872852306191255492926495965536379271875310457319107936020730050476235278671528265817571433919561175665096171189758406136453987966255236963782666066962654678464950075923060327358691356632908606498231755963567382339010985222623205586923466405809217426670333410014429905146941652293366212903733630083016398810887356019977409467374742266276267137547021576874204809506045914964491063393800499167416471949021995447722415959979785959569497
SSH Keys
Extracting the modulus \(n\) from an
SSH public key.
1 2 3 4 from Crypto.PublicKey import RSAwith open ("bruce_rsa.pub" , "rb" ) as f: key = RSA.import_key(f.read()) print (key.n)
3931406272922523448436194599820093016241472658151801552845094518579507815990600459669259603645261532927611152984942840889898756532060894857045175300145765800633499005451738872081381267004069865557395638550041114206143085403607234109293286336393552756893984605214352988705258638979454736514997314223669075900783806715398880310695945945147755132919037973889075191785977797861557228678159538882153544717797100401096435062359474129755625453831882490603560134477043235433202708948615234536984715872113343812760102812323180391544496030163653046931414723851374554873036582282389904838597668286543337426581680817796038711228401443244655162199302352017964997866677317161014083116730535875521286631858102768961098851209400973899393964931605067856005410998631842673030901078008408649613538143799959803685041566964514489809211962984534322348394428010908984318940411698961150731204316670646676976361958828528229837610795843145048243492909
Transparency
Using subfinder to find subdomains and locating the flag
on one of them.
1 2 3 4 5 6 ❯ subfinder -d cryptohack.org ... thetransparencyflagishere.cryptohack.org ❯ curl https://thetransparencyflagishere.cryptohack.org crypto{thx_redpwn_for_inspiration}
crypto{thx_redpwn_for_inspiration}