├── 2017 ├── ASIS-CTF-Finals │ └── Gracias │ │ ├── README.md │ │ ├── enc_pubkey.txt │ │ ├── exploit.py │ │ └── gracias.py ├── ASIS-CTF-Quals │ └── DLP │ │ └── README.md ├── CSAW-CTF-Quals │ └── BabyCrypt │ │ ├── README.md │ │ └── exploit.py ├── Hack.lu-CTF │ └── prime-enigma │ │ ├── README.md │ │ ├── ciphertext.txt │ │ ├── exploit.py │ │ └── script.py ├── MeePwn-CTF │ ├── Simpler-Than-RSA │ │ ├── README.md │ │ ├── enc.txt │ │ ├── exploit.py │ │ ├── pubkey.txt │ │ └── simple.py │ └── math │ │ ├── exploit.py │ │ └── test.py ├── Plaid-CTF │ └── Multicast │ │ ├── data.txt │ │ ├── exploit.sage │ │ └── exploit.sage.py └── Tokyo-Westerns-CTF │ └── baby-dlp │ ├── b1.sh │ ├── exploit.py │ ├── flag │ └── server.py ├── 2018 ├── ACEBEAR-Security-Contest │ └── CNVService │ │ ├── AES_CNV_COOKIE.py │ │ ├── CNVService.py │ │ ├── README.md │ │ └── exploit.py ├── CSAW-Finals │ └── DisastrousSecurity │ │ ├── MTRecover.py │ │ ├── MTRecover.pyc │ │ ├── MersenneTwister.py │ │ ├── exploit.py │ │ ├── main.py │ │ └── test.key ├── Codegate-CTF-Preliminary │ └── RSAbaby │ │ ├── README.md │ │ ├── RSAbaby.py │ │ ├── Result.txt │ │ └── exploit.py ├── HITB-XCTF-CTF-Quals │ └── Easy_pub │ │ └── easy_pub.py ├── HITCON-CTF │ └── Lost-Key │ │ └── exploit.py ├── HackIT-CTF │ └── Into-the-Darkness │ │ ├── README.md │ │ ├── data.txt │ │ └── exploit.py ├── Insomni'Hack-Teaser │ └── Rule86 │ │ ├── README.md │ │ ├── bootstrap_prng.py │ │ ├── exploit.py │ │ ├── hint.gif.enc │ │ ├── rule86.txt │ │ ├── rule86.txt.enc │ │ ├── super_cipher.py.enc │ │ └── test.gif ├── Meepwn-CTF-Quals │ └── bazik │ │ ├── 1.png │ │ ├── 2.png │ │ ├── exploit.sage │ │ ├── publickey.pem │ │ └── readpublickeypara.py ├── Midnight-CTF-Quals │ └── hm4c │ │ ├── Pictures │ │ └── Picture1.png │ │ ├── README.md │ │ ├── Server │ │ ├── flag.py │ │ └── hm4c.py │ │ ├── exploit.py │ │ ├── hm4c.py │ │ └── hm4c.sh ├── N1CTF │ ├── RSA_Padding │ │ ├── Pictures │ │ │ ├── 1.gif │ │ │ ├── 2.gif │ │ │ ├── 3.gif │ │ │ ├── 4.gif │ │ │ ├── 5.gif │ │ │ ├── 6.gif │ │ │ ├── 7.gif │ │ │ ├── 8.gif │ │ │ ├── pow.png │ │ │ └── server.png │ │ ├── README.md │ │ └── exploit.py │ └── baby_N1ES │ │ ├── N1ES.py │ │ ├── challenge.py │ │ └── exploit.py ├── Pragyan-CTF │ └── RSA's-Quest │ │ └── README.md ├── README.md ├── Swamp-CTF │ └── Locked-Dugeons-2 │ │ ├── README.md │ │ └── enter_the_dungeon2.py ├── Tokyo-Westerns │ └── Revolutional-Secure-Angou │ │ ├── Pictures │ │ ├── 1.gif │ │ ├── 2.gif │ │ ├── 3.gif │ │ ├── 4.gif │ │ ├── 5.gif │ │ └── 6.gif │ │ ├── README.md │ │ ├── exploit.py │ │ ├── flag.encrypted │ │ ├── generator.rb │ │ └── publickey.pem ├── VolgaCTF-Quals │ └── Nonsense │ │ ├── Pictures │ │ ├── Picture1.png │ │ ├── Picture10.gif │ │ ├── Picture11.gif │ │ ├── Picture2.png │ │ ├── Picture3.png │ │ ├── Picture4.png │ │ ├── Picture5.png │ │ ├── Picture6.png │ │ ├── Picture7.gif │ │ ├── Picture8.gif │ │ └── Picture9.gif │ │ ├── README.md │ │ ├── exploit.py │ │ ├── signatures │ │ └── task.py ├── b00t2root'18 │ └── RSA-2 │ │ └── exploit.sage ├── hxp-CTF │ └── daring │ │ ├── Pictures │ │ ├── 1.gif │ │ ├── 2.gif │ │ └── 3.gif │ │ ├── README.md │ │ ├── aes.enc │ │ ├── exploit.py │ │ ├── pubkey.txt │ │ ├── rsa.enc │ │ └── vuln.py └── noxCTF │ ├── Decryptor │ ├── README.md │ └── exploit.py │ ├── Trinity │ ├── README.md │ └── exploit.py │ └── WTF │ ├── README.md │ └── exploit.py └── README.md /2017/ASIS-CTF-Finals/Gracias/README.md: -------------------------------------------------------------------------------- 1 | # Gracias (Crypto, 287p) 2 | 3 | ``` 4 | Some people think that combination of cryptographic systems will definitely improve the security. That’s your turn to prove them wrong. 5 | ``` 6 | 7 | In this task, we get [encryption script](gracias.py) to exploit upon. 8 | The task is not really difficult as it looks like. The challenge is to break the given multi-prime based RSA encryption. 9 | 10 | A few steps in the encryption: 11 | 1. Private and Public keys are generated using the same function `make_pubpri(nbit)` 12 | a. The function generates primes `p` , `q` and `r` like conventional RSA encryption 13 | b. Along with public keys `n` and `e`, the function also generates a 2*nbit safe prime number `a` and another number `g` following the criteria given below 14 | c. So, the public key actually contains `n`, `e`, `a`, `g` and the private key contains `n`, `d`, `a`, `g` 15 | 2. The encryption function `encrypt(m, pub)` works as follows: 16 | a. Using the public key generated in Step-1, it generates two numbers k and K as `k = getRandomRange(2, a)` and `K = pow(g, k, a)` 17 | b. Now, instead of encrypting the message `m` using the public keys, it does the following operation to get ciphertext `c1` and `c2`: 18 | (i) `c1, c2 = pow(k, e, n), (m * K) % a` 19 | c. Returns `c1` and `c2` as ciphertext 20 | 21 | The attack on this will work as follows: 22 | 1. Using `c1`, `e` and `n`, get the value of `k` 23 | 2. Calculate `K` using `k` generated in Step-1 24 | 3. Finally calculate message `m` as `m = (c2 * (k^(-1) mod n)) mod n` 25 | 26 | A direct Wiener's Attack will not work in this case since it doesn't exactly follow the criteria of `d` being less than `N^(1/4)`. 27 | 28 | You can check this variant of Wiener Attack which works when the size of `d` is just a few bits greater than `N^(1/4)`. Paper on a variant of Wiener Attack [here](https://www.math.tugraz.at/~cecc08/abstracts/cecc08_abstract_20.pdf). 29 | 30 | Conclusion from the paper which is significant for exploit of this challenge: 31 | 1. Along with d being the denominator of the convergent of the continued fraction of (e/n), the decryption exponent can also be written in the form: 32 | a. `d = r*q(m+1) + s*q(m)` 33 | 34 | Here q(m+1) and q(m) are the (m+1)th and mth denominators of the convergents of the continued fraction of (e/n) respectively. 35 | 36 | This is a script implementing the above conclusion: 37 | 38 | ```python 39 | def wiener(e, n): 40 | m = 12345 41 | c = pow(m, e, n) 42 | q0 = 1 43 | 44 | list1 = continued_fraction(Integer(e)/Integer(n)) 45 | conv = list1.convergents() 46 | for i in conv: 47 | k = i.numerator() 48 | q1 = i.denominator() 49 | 50 | for r in range(20): 51 | for s in range(20): 52 | d = r*q1 + s*q0 53 | m1 = pow(c, d, n) 54 | if m1 == m: 55 | return d 56 | q0 = q1 57 | ``` 58 | which will give us the decryption exponent: 59 | 60 | `d = 100556095937036905102538523179832446199526507742826168666218687736467897968451` 61 | 62 | Then we can write the following code to get the flag: 63 | ```python 64 | from Crypto.Util.number import * 65 | 66 | k = pow(c1, d, n) 67 | K = pow(g, k, a) 68 | print long_to_bytes(c2 * inverse(K, a) % a) 69 | ``` 70 | 71 | This gives us the flag: `ASIS{Wiener_at7ack_iN_mUlt1_Prim3_RSA_iZ_f34sible_t0O!}` 72 | 73 | If you want to check how I approached the challenge in detail, checkout my blog [here](https://masterpessimistaa.wordpress.com/2017/11/24/asis-finals-ctf-2017-gracias-writeup/). 74 | The complete exploit script [here](exploit.py) 75 | 76 | 77 | -------------------------------------------------------------------------------- /2017/ASIS-CTF-Finals/Gracias/enc_pubkey.txt: -------------------------------------------------------------------------------- 1 | c = (1569733526826523065259704222721381245770313117205865099913421859731162526943498524936251685846967970606251353344665893442015804015671457823645874503670136308040791285744658847419176471348768113798503897694020110157476679833746227801224812046930570487233225157924912272791212802495997329083436189937249314855532400635293522270501567950040825794060896420481676398789310029592608176167251882124182145471818654414925639589921023176070657483148482403065241178276749773L, 139537660044872985880471632333334179976891152860359271230202507995985566816703080930428310461057387079799847266510420206696052591677854190150642820963140050439023069266243433278700748622126726137374130247097863526461696642750021196138340072411724739383716017406022211953417323065831672315854246554523225039827L) 2 | pubkey = (1696852658826990842058316561963467335977986730245296081842693913454799128341723605666024757923000936875008280288574503060506225324560725525210728761064310034604441130912702077320696660565727540525259413564999213382434231194132697630244074950529107794905761549606578049632101483460345878198682237227139704889943489709170676301481918176902970896183163611197618458670928730764124354693594769219086662173889094843054787693685403229558143793832013288487194871165461567L, 814161885590044357190593282132583612817366020133424034468187008267919006610450334193936389251944312061685926620628676079561886595567219325737685515818965422518820810326234612624290774570873983198113409686391355443155606621049101005048872030700143084978689888823664771959905075795440800042648923901406744546140059930315752131296763893979780940230041254506456283030727953969468933552050776243515721233426119581636614777596169466339421956338478341355508343072697451L, 171012227587318507773834753911094468358648971527111097308935888531930900156798659257578479378777764146070352809723708236353390208094909385240006920137781562826981091183813955039359863361624869703055918575613667858215532572602435432258750639197322091887713402631456113333645709142822182724397962837201266977523L, 96969753191136466007366303619618019752521508403657426306543836447071659732926802256183021740376016065813234292694535879838415771865207311953800116203362150588941093508091412441933752168889516206420588410478242229762908362637083786338280959547015086176046206126019992386890758970740552952647510652431386064722L) 3 | -------------------------------------------------------------------------------- /2017/ASIS-CTF-Finals/Gracias/exploit.py: -------------------------------------------------------------------------------- 1 | from sage.all import continued_fraction, Integer 2 | from Crypto.Util.number import * 3 | 4 | def wiener(e, n): 5 | m = 12345 6 | c = pow(m, e, n) 7 | q0 = 1 8 | 9 | list1 = continued_fraction(Integer(e)/Integer(n)) 10 | conv = list1.convergents() 11 | for i in conv: 12 | k = i.numerator() 13 | q1 = i.denominator() 14 | 15 | for r in range(20): 16 | for s in range(20): 17 | d = r*q1 + s*q0 18 | m1 = pow(c, d, n) 19 | if m1 == m: 20 | return d 21 | q0 = q1 22 | 23 | pubkey = (1696852658826990842058316561963467335977986730245296081842693913454799128341723605666024757923000936875008280288574503060506225324560725525210728761064310034604441130912702077320696660565727540525259413564999213382434231194132697630244074950529107794905761549606578049632101483460345878198682237227139704889943489709170676301481918176902970896183163611197618458670928730764124354693594769219086662173889094843054787693685403229558143793832013288487194871165461567L, 814161885590044357190593282132583612817366020133424034468187008267919006610450334193936389251944312061685926620628676079561886595567219325737685515818965422518820810326234612624290774570873983198113409686391355443155606621049101005048872030700143084978689888823664771959905075795440800042648923901406744546140059930315752131296763893979780940230041254506456283030727953969468933552050776243515721233426119581636614777596169466339421956338478341355508343072697451L, 171012227587318507773834753911094468358648971527111097308935888531930900156798659257578479378777764146070352809723708236353390208094909385240006920137781562826981091183813955039359863361624869703055918575613667858215532572602435432258750639197322091887713402631456113333645709142822182724397962837201266977523L, 96969753191136466007366303619618019752521508403657426306543836447071659732926802256183021740376016065813234292694535879838415771865207311953800116203362150588941093508091412441933752168889516206420588410478242229762908362637083786338280959547015086176046206126019992386890758970740552952647510652431386064722L) 24 | c = (1569733526826523065259704222721381245770313117205865099913421859731162526943498524936251685846967970606251353344665893442015804015671457823645874503670136308040791285744658847419176471348768113798503897694020110157476679833746227801224812046930570487233225157924912272791212802495997329083436189937249314855532400635293522270501567950040825794060896420481676398789310029592608176167251882124182145471818654414925639589921023176070657483148482403065241178276749773L, 139537660044872985880471632333334179976891152860359271230202507995985566816703080930428310461057387079799847266510420206696052591677854190150642820963140050439023069266243433278700748622126726137374130247097863526461696642750021196138340072411724739383716017406022211953417323065831672315854246554523225039827L) 25 | 26 | n, e, a, g = pubkey 27 | c1, c2 = c 28 | 29 | print "e: ", e 30 | print "n: ", n 31 | 32 | d = wiener(e, n) 33 | 34 | print "d: ", d 35 | 36 | k = pow(c1, d, n) 37 | K = pow(g, k, a) 38 | m = long_to_bytes(c2 * inverse(K, a) % a) 39 | print m 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /2017/ASIS-CTF-Finals/Gracias/gracias.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from gmpy import * 4 | from Crypto.Util.number import * 5 | import gensafeprime 6 | from flag import FLAG 7 | 8 | def make_pubpri(nbit): 9 | p, q, r = [ getPrime(nbit) for _ in xrange(3)] 10 | n = p * q * r 11 | phi = (p-1)*(q-1)*(r-1) 12 | l = min([p, q, r]) 13 | d = getPrime(1 << 8) 14 | e = inverse(d, phi) 15 | a = gensafeprime.generate(2*nbit) 16 | while True: 17 | g = getRandomRange(2, a) 18 | if pow(g, 2, a) != 1 and pow(g, a/2, a) != 1: 19 | break 20 | return (n, e, a, g), (n, d, a, g) 21 | 22 | def encrypt(m, pub): 23 | n, e, a, g = pub 24 | k = getRandomRange(2, a) 25 | K = pow(g, k, a) 26 | c1, c2 = pow(k, e, n), (m * K) % a 27 | return c1, c2 28 | 29 | nbit = 512 30 | pubkey, privkey = make_pubpri(nbit) 31 | m = bytes_to_long(FLAG) 32 | c = encrypt(m, pubkey) 33 | print 'c =', c 34 | print 'pubkey =', pubkey -------------------------------------------------------------------------------- /2017/ASIS-CTF-Quals/DLP/README.md: -------------------------------------------------------------------------------- 1 | # DLP 2 | 3 | Challenge Points: 158 4 | 5 | Ciphertext is generated as following: 6 | ```python 7 | def encrypt(nbit, msg): 8 | msg = bytes_to_long(msg) 9 | p = getPrime(nbit) 10 | q = getPrime(nbit) 11 | n = p*q 12 | s = getPrime(4) 13 | enc = pow(n+1, msg, n**(s+1)) 14 | return n, enc 15 | ``` 16 | 17 | We know that enc = (n+1)msg mod ns+1 18 | Thus, according to Binomial Theorem we can write: 19 | The expansion of (n+1)msg is as follows: 20 | ![equation](https://latex.codecogs.com/png.latex?\small&space;{msg\choose&space;0}n^{msg}&space;+&space;{msg\choose&space;1}n^{msg-1}&space;+&space;{msg\choose&space;2}n^{msg-2}&space;+&space;...&space;+&space;{msg\choose&space;msg-1}n&space;+&space;{msg\choose&space;msg}n^{0}) 21 | And so we can also write, 22 | ![equation](https://latex.codecogs.com/png.latex?\small&space;({msg\choose&space;0}n^{msg-2}&space;+&space;{msg\choose&space;1}n^{msg-3}&space;+&space;...&space;+&space;{msg\choose&space;msg-2})n^2&space;+&space;{msg\choose&space;msg-1}n&space;+&space;{msg\choose&space;msg}n^{0}) 23 | Which can be written as, 24 | ![equation](https://latex.codecogs.com/png.latex?\small&space;(x)n^2&space;+&space;mn&space;+&space;1) where, 25 | ![equation](https://latex.codecogs.com/png.latex?\small&space;x&space;=&space;{msg\choose&space;0}n^{msg-2}&space;+&space;{msg\choose&space;1}n^{msg-3}&space;+&space;...&space;+&space;{msg\choose&space;msg-2}) 26 | If we take the above result and **divide it with n^2**, the following can be written: ![equation](https://latex.codecogs.com/png.latex?\small&space;xn^2&space;+&space;mn&space;+&space;1&space;\equiv&space;mn+1&space;\pmod&space;{n^2}) 27 | Since, ns+1 is always greater than and divisible by n2, we can now calculate the message `msg` as: 28 | ![equation](https://latex.codecogs.com/png.latex?\small&space;enc&space;\equiv&space;(n+1)^{msg}&space;\pmod&space;{n^{s+1}}) 29 | ![equation](https://latex.codecogs.com/png.latex?\small&space;enc&space;\equiv&space;(msg*n&space;+&space;1)&space;\pmod&space;{n^2}) 30 | Therefore, 31 | ![equation](https://latex.codecogs.com/png.latex?{m&space;=&space;\frac{(enc\mod&space;n^2)&space;-&space;1}{n}}) 32 | 33 | Surprisingly, this is the single line exploit to the challenge: 34 | ```python 35 | hex(int((enc%n^2-1)/n))[2:].replace("L","").decode("hex") 36 | ``` 37 | 38 | 39 | -------------------------------------------------------------------------------- /2017/CSAW-CTF-Quals/BabyCrypt/README.md: -------------------------------------------------------------------------------- 1 | # BabyCrypt (Crypto, 350) 2 | 3 | This challenge was a bit overrated, there were no complications in the challenge, as you will see when we discuss the writeup. 4 | 5 | In this challenge, we are supposed to get the flag which is present in the server. The server has an input-output program running, which gives AES-ECB encryption of the input given to it. The encryption takes place as follows: 6 | 1. Takes the input from the user 7 | 2. Appends `secret` (which is the flag here) to the input 8 | 3. Pads to make it a multiple of blocksize 9 | 4. Encrypts the resultant string using AES in ECB mode 10 | 5. Gives the ciphertext as the output 11 | 12 | As you can see, we are only in control of the input which we are supposed to give to the server. Using the input that we give, we need to get the `secret` which is the flag. 13 | Let us have a look at how the blocks are divided when we send an input of size equal to the blocksize (16 in this case): 14 | ``` 15 | 1st Block | 2nd Block | 3rd Block | ... 16 | Input | Secret | secret+padding ... 17 | ``` 18 | The first block contains 16 bytes of our input, which is known to us. When we send an input of size one less than the blocksize, then the block division is as follows: 19 | ``` 20 | 1st Block | 2nd Block | 3rd Block | ... 21 | x | Secret[1:17] | secret[17:]+padding ... 22 | ``` 23 | Here `x = 15 bytes input + 1 byte secret`. 24 | We know the first 15 bytes of block #1, we can simply brute force 256 possibilities of the 16th byte in block #1 by checking the corresponding ciphertexts of block #1. 25 | 26 | ![picture](https://i.imgur.com/bta3KOp.png) 27 | 28 | For the second byte we send 14 random bytes + 1 byte of secret(we got from previous step) as the input to the server and then brute force for 2nd byte of secret which again has 256 possibilties. We keep on continuing this process to get each byte of the secret and finally get the flag: 29 | 30 | ![picture2](https://i.imgur.com/BFvygKf.png) 31 | 32 | Flag: `flag{Crypt0_is_s0_h@rd_t0_d0...}` 33 | 34 | In case you want to know how I approached the problem in detail, checkout my blogpost [here](https://amritabi0s.wordpress.com/2017/09/18/csaw-quals-2017-babycrypt-writeup/). 35 | Check my complete exploit script for this challenge [here](exploit.py). 36 | -------------------------------------------------------------------------------- /2017/CSAW-CTF-Quals/BabyCrypt/exploit.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | import string 3 | 4 | r = remote("crypto.chal.csaw.io","1578") 5 | plaintext = "" 6 | blocksize = 16 7 | for k in range(2): 8 | b = "" 9 | for i in range(1,17): 10 | string_sent = "a"*(16-i) 11 | 12 | r.recv() 13 | r.sendline(string_sent) 14 | g1 = r.recvuntil("\n")[16:-1] 15 | g1 = g1[:32+k*32] 16 | print "String sent: ",string_sent 17 | for j in range(256): 18 | r.recv() 19 | r.sendline(string_sent + plaintext + b + chr(j)) 20 | g2 = r.recvuntil("\n")[16:-1] 21 | g2 = g2[:32+k*32] 22 | if g1 == g2 and chr(j) in string.printable and j!=10 and j!=0: 23 | print chr(j), j 24 | b += chr(j) 25 | break 26 | plaintext += b 27 | print plaintext 28 | -------------------------------------------------------------------------------- /2017/Hack.lu-CTF/prime-enigma/README.md: -------------------------------------------------------------------------------- 1 | # Prime Enigma 2 | 3 | **Challenge Points**: 50(+ 100) 4 | 5 | **Challenge Description**: Hey there fellow lizard how nice of you to drop by! Did you know those filthy humans really think that some numbers have special meanings? Seven, 13 and for some strange reason even 9000. Go and show them that a good prime does not make a secure cryptosystem! 6 | 7 | The following encryption is taking place: 8 | ```python 9 | g = 5 10 | d = key 11 | m = int(flag.encode('hex'), 16) % p 12 | 13 | B = pow(g, d, p) # Equation-1 14 | k = pow(A, d, p) # Equation-2 15 | c = k * m % p # Equation-3 16 | ``` 17 | Values p, A, g, B, c are known. 18 | **Encryption System**: ElGamal 19 | 20 | Prerequisites: 21 | 1. Cyclic Groups 22 | 2. Discrete Logarithm Problem 23 | 3. Basic Number Theory 24 | In case you are interested in understanding the exploit, but don't have much knowledge about Cyclic Groups and DLP, you can read about it here on my blog post: [Cyclic Groups, DLP and Baby Step Giant Step Algorithm](https://masterpessimistaa.wordpress.com/2018/01/14/dlp-and-baby-step-giant-step-algorithm/). 25 | 26 | The entire exploit summed up: 27 | 1. We need to calculate the value of `d` by solving `Equation-1` 28 | 2. Calculate `k` using the value of `d` obtained from Step-1 in order to solve `Equation-2` 29 | 3. Calculate m = c * mod_inv(k, p) using the value of `k` obtained from Step-2 in order to solve `Equation-3` 30 | 31 | **Solving Step-1**: 32 | We know from the property of Cyclic Groups that ![equation](https://latex.codecogs.com/png.latex?g^{|G|}&space;\equiv&space;1&space;\mod&space;p), where `|G|` is the cardinality/order of the Cyclic Group `G`. Cardinality i.e. the number of elements in the Cyclic Group, in this case, is `p-1`. Therefore we can write: ![equation](https://latex.codecogs.com/png.latex?g^{p-1}&space;\equiv&space;1&space;\mod&space;p) which is also known as [Fermat's Little Theorem](https://en.wikipedia.org/wiki/Fermat%27s_little_theorem). 33 | 34 | Note that B = p-1, which makes solving DLP a lot easier. We can now write: 35 | ![equation](https://latex.codecogs.com/png.latex?p-1\equiv&space;g^d&space;\mod&space;p) 36 | which can also be written as: 37 | ![equation](https://latex.codecogs.com/png.latex?g^d\equiv&space;-1&space;\mod&space;p) 38 | Upon squaring, we have: 39 | ![equation](https://latex.codecogs.com/png.latex?g^{2d}\equiv&space;1&space;\mod&space;p) 40 | Comparing the above equation with ![equation](https://latex.codecogs.com/png.latex?g^{p-1}&space;\equiv&space;1&space;\mod&space;p), we can write: 41 | **d = (p-1)/2** 42 | 43 | **Solving Step-2**: 44 | Simple compute: ![equation](https://latex.codecogs.com/png.latex?k&space;=&space;A^d&space;\mod&space;p) 45 | 46 | **Solving Step-3**: 47 | Simply compute: ![equation](https://latex.codecogs.com/png.latex?m&space;=&space;ck^{-1}&space;\mod&space;p) 48 | 49 | Checkout the entire exploit script [here](exploit.py) 50 | -------------------------------------------------------------------------------- /2017/Hack.lu-CTF/prime-enigma/ciphertext.txt: -------------------------------------------------------------------------------- 1 | 1044388881413152506679602719846529545831269060992135009022588756444338172022322690710444046669809783930111585737890362691860127079270495454517218673016928427459146001866885779762982229321192368303346235204368051010309155674155697460347176946394076535157284994895284821633700921811716738972451834979455897010306333468590751358365138782250372269117968985194322444535687415522007151638638141456178420621277822674995027990278673458629544391736919766299005511505446177668154446234882665961680796576903199116089347634947187778906528008004756692571666922964122566174582776707332452371001272163776841229318324903125740713574141005124561965913888899753461735347970011693256316751660678950830027510255804846105583465055446615090444309583050775808509297040039680057435342253926566240898195863631588888936364129920059308455669454034010391478238784189888594672336242763795138176353222845524644040094258962433613354036104643881925238489224010194193088911666165584229424668165441688927790460608264864204237717002054744337988941974661214699689706521543006262604535890998125752275942608772174376107314217749233048217904944409836238235772306749874396760463376480215133461333478395682746608242585133953883882226786118030184028136755970045385534758453246 2 | 626538023179183383530326775878874061243537575637678230775990839517480703838547661223043351239918394865532739593994849154430591305198322288328417436892902443505917379006443598061697092201021536603987285163299838045075649512028921956548205676208712226470308113290505059049053554206416767772651512039632936795232724801922443388952796545084060280910673215063573749033668717290815841834685051547255093401042248880082370281195663905731764841136214458769095907569163184276786105979509363239839613385785232307550226120692268670717158539363476974302593377514937470953649913863219081380729197866499068054753726732556988368232198510160183731571741889761632557457157261911256679728707526809880224074940827825962124087677609578885077944156589121586951372962667391498824853627326311588259929756093569512874696625507873168095797130866697040006079191565592914811736694534863664544646201900855732710994613768016495896341014229622129847800138058041138449691835652916517559125407914079964177419733079221280850917496784527992741048638603428068452948455069671414667008770873913118369984179054902139270844669700487715140145038503768704763641223894377872853332484296603268546135216483844722413025955229649646292980986542646384960063297213437076185709400450 3 | -------------------------------------------------------------------------------- /2017/Hack.lu-CTF/prime-enigma/exploit.py: -------------------------------------------------------------------------------- 1 | from Crypto.Util.number import * 2 | import gmpy2 3 | 4 | B = 1044388881413152506679602719846529545831269060992135009022588756444338172022322690710444046669809783930111585737890362691860127079270495454517218673016928427459146001866885779762982229321192368303346235204368051010309155674155697460347176946394076535157284994895284821633700921811716738972451834979455897010306333468590751358365138782250372269117968985194322444535687415522007151638638141456178420621277822674995027990278673458629544391736919766299005511505446177668154446234882665961680796576903199116089347634947187778906528008004756692571666922964122566174582776707332452371001272163776841229318324903125740713574141005124561965913888899753461735347970011693256316751660678950830027510255804846105583465055446615090444309583050775808509297040039680057435342253926566240898195863631588888936364129920059308455669454034010391478238784189888594672336242763795138176353222845524644040094258962433613354036104643881925238489224010194193088911666165584229424668165441688927790460608264864204237717002054744337988941974661214699689706521543006262604535890998125752275942608772174376107314217749233048217904944409836238235772306749874396760463376480215133461333478395682746608242585133953883882226786118030184028136755970045385534758453246 5 | c = 626538023179183383530326775878874061243537575637678230775990839517480703838547661223043351239918394865532739593994849154430591305198322288328417436892902443505917379006443598061697092201021536603987285163299838045075649512028921956548205676208712226470308113290505059049053554206416767772651512039632936795232724801922443388952796545084060280910673215063573749033668717290815841834685051547255093401042248880082370281195663905731764841136214458769095907569163184276786105979509363239839613385785232307550226120692268670717158539363476974302593377514937470953649913863219081380729197866499068054753726732556988368232198510160183731571741889761632557457157261911256679728707526809880224074940827825962124087677609578885077944156589121586951372962667391498824853627326311588259929756093569512874696625507873168095797130866697040006079191565592914811736694534863664544646201900855732710994613768016495896341014229622129847800138058041138449691835652916517559125407914079964177419733079221280850917496784527992741048638603428068452948455069671414667008770873913118369984179054902139270844669700487715140145038503768704763641223894377872853332484296603268546135216483844722413025955229649646292980986542646384960063297213437076185709400450 6 | p = 1044388881413152506679602719846529545831269060992135009022588756444338172022322690710444046669809783930111585737890362691860127079270495454517218673016928427459146001866885779762982229321192368303346235204368051010309155674155697460347176946394076535157284994895284821633700921811716738972451834979455897010306333468590751358365138782250372269117968985194322444535687415522007151638638141456178420621277822674995027990278673458629544391736919766299005511505446177668154446234882665961680796576903199116089347634947187778906528008004756692571666922964122566174582776707332452371001272163776841229318324903125740713574141005124561965913888899753461735347970011693256316751660678950830027510255804846105583465055446615090444309583050775808509297040039680057435342253926566240898195863631588888936364129920059308455669454034010391478238784189888594672336242763795138176353222845524644040094258962433613354036104643881925238489224010194193088911666165584229424668165441688927790460608264864204237717002054744337988941974661214699689706521543006262604535890998125752275942608772174376107314217749233048217904944409836238235772306749874396760463376480215133461333478395682746608242585133953883882226786118030184028136755970045385534758453247 7 | g = 5 8 | A = 1026312539297800437474663698165859314949881437729617621666434357798219198741950468733395500361477359726152747087790103309627020498122003777642051150130697457594304849673838709900017711265818285080832347734747895550397950729716624922572654209637755195129162139245110756558638081495998280747642920484467428206475906559638681536868548289456924005274209311355030582255692087426910634838198143851507435754029135363794578075936092774722678311786272841489629294721103591751528609388061794369341067986401129462942050916582521451289187645626081017578576190303952351748434876686541368607656026867091583868645619423975306245327421218767449273192101105293424028461698783545171866070124432565063559495566733441286372612161876492134408160732339966921175762866198980795890946054558528891296203285979664329713156129091098226212735763844909789916934266711879564086741733061623347281499025678164709559814150194881622611023214199434022258730549350019749882889143749385314934896284396513061241138504029046053964944026179039768718830854958634216721133676746317913559932277050177463811150719675119168868527853864167729206220819613297736800799391257602899169041109002518019207734013899840092155297682096290489330476118066934735827328128343402508975429994312 9 | 10 | d = (p-1)/2 11 | k = pow(A, d, p) 12 | k_inv = inverse(k, p) 13 | m = (k_inv*c) % p 14 | print long_to_bytes(m) 15 | -------------------------------------------------------------------------------- /2017/Hack.lu-CTF/prime-enigma/script.py: -------------------------------------------------------------------------------- 1 | from secret import flag, key 2 | 3 | f = open('ciphertext.txt', 'w') 4 | 5 | p = 1044388881413152506679602719846529545831269060992135009022588756444338172022322690710444046669809783930111585737890362691860127079270495454517218673016928427459146001866885779762982229321192368303346235204368051010309155674155697460347176946394076535157284994895284821633700921811716738972451834979455897010306333468590751358365138782250372269117968985194322444535687415522007151638638141456178420621277822674995027990278673458629544391736919766299005511505446177668154446234882665961680796576903199116089347634947187778906528008004756692571666922964122566174582776707332452371001272163776841229318324903125740713574141005124561965913888899753461735347970011693256316751660678950830027510255804846105583465055446615090444309583050775808509297040039680057435342253926566240898195863631588888936364129920059308455669454034010391478238784189888594672336242763795138176353222845524644040094258962433613354036104643881925238489224010194193088911666165584229424668165441688927790460608264864204237717002054744337988941974661214699689706521543006262604535890998125752275942608772174376107314217749233048217904944409836238235772306749874396760463376480215133461333478395682746608242585133953883882226786118030184028136755970045385534758453247 6 | g = 5 7 | A = 1026312539297800437474663698165859314949881437729617621666434357798219198741950468733395500361477359726152747087790103309627020498122003777642051150130697457594304849673838709900017711265818285080832347734747895550397950729716624922572654209637755195129162139245110756558638081495998280747642920484467428206475906559638681536868548289456924005274209311355030582255692087426910634838198143851507435754029135363794578075936092774722678311786272841489629294721103591751528609388061794369341067986401129462942050916582521451289187645626081017578576190303952351748434876686541368607656026867091583868645619423975306245327421218767449273192101105293424028461698783545171866070124432565063559495566733441286372612161876492134408160732339966921175762866198980795890946054558528891296203285979664329713156129091098226212735763844909789916934266711879564086741733061623347281499025678164709559814150194881622611023214199434022258730549350019749882889143749385314934896284396513061241138504029046053964944026179039768718830854958634216721133676746317913559932277050177463811150719675119168868527853864167729206220819613297736800799391257602899169041109002518019207734013899840092155297682096290489330476118066934735827328128343402508975429994312 8 | d = key 9 | m = int(flag.encode('hex'), 16) % p 10 | 11 | B = pow(g, d, p) 12 | k = pow(A, d, p) 13 | c = k * m % p 14 | 15 | f.write(str(B) + '\n') 16 | f.write(str(c) + '\n') 17 | 18 | f.close() 19 | -------------------------------------------------------------------------------- /2017/MeePwn-CTF/Simpler-Than-RSA/README.md: -------------------------------------------------------------------------------- 1 | # Simpler Than RSA 2 | 3 | Challenge Points: 100 4 | 5 | We are given an encryption script [simple.py](simple.py). Values of n, g, h are public other than the ciphertext. The following function is used to generate values for the challenge: 6 | ![picture](https://i.imgur.com/0QUHha4.png) 7 | The encryption function: 8 | ![picture](https://i.imgur.com/ORlFqDf.png) 9 | As we can see, the ciphertext for each character in the plaintext is generated separately. For the `ith` byte of message we can write the corresponding ciphertext as: 10 | ![equation](https://latex.codecogs.com/gif.latex?c_i=((g^{m_i}\mod&space;n)*(h^{r}\mod&space;n))\mod&space;n) 11 | Given: ![equation](https://latex.codecogs.com/gif.latex?h=g^{n}\mod&space;n) 12 | We can now write: 13 | ![equation](https://latex.codecogs.com/gif.latex?c_i=((g^{m_i}\mod&space;n)*(g^{nr}\mod&space;n))\mod&space;n) 14 | which gives us ![equation](https://latex.codecogs.com/gif.latex?c_i=g^{m_i+nr}\mod&space;n) 15 | Since n=p*p*q, 16 | ![equation](https://latex.codecogs.com/gif.latex?c_i=g^{m_i+p^{2}qr}\mod&space;n) 17 | Raising both sides by (p-1)*(q-1), we have: 18 | ![equation](https://latex.codecogs.com/gif.latex?c_i^{(p-1)*(q-1)}\mod&space;n=g^{(m_i+p^{2}qr)*(p-1)*(q-1)}\mod&space;n) 19 | ![equation](https://latex.codecogs.com/gif.latex?c_i^{(p-1)*(q-1)}\mod&space;n=g^{(m_i*(p-1)*(q-1))+(p*(p-1)*(q-1)*nr)}\mod&space;n) 20 | Since phi(n) = p*(p-1)*(q-1), 21 | ![equation](https://latex.codecogs.com/gif.latex?c_i^{(p-1)*(q-1)}\mod&space;n=(g^{(m_i*(p-1)*(q-1))}*g^{nr\phi(n)})\mod&space;n) 22 | Euler's theorem states that when GCD(a, n) == 1: ![equation](https://latex.codecogs.com/gif.latex?a^{\phi(n)}\equiv1\mod&space;n) 23 | We can now write, 24 | Equation(a): ![equation](https://latex.codecogs.com/gif.latex?c_i^{(p-1)*(q-1)}\mod&space;n=g^{m_i*(p-1)*(q-1)}.1\mod&space;n) 25 | We have now eliminated `r` from the equation, let us first get the factors of n, trying it on [factordb.com](factordb.com) gives us the factors as: 26 | ``` 27 | p = 1057817919251064684989791981 28 | q = 1103935256393984899021164397 29 | ``` 30 | Now that we have the factors, we can use Equation(a) to get solution for each ciphertext byte. For each byte, we just have to check for 256 possibilities of corresponding message byte and a total of 54*256 brute-force checks to get the flag(We already know the other values in Equation(a): p,q,ciphertext byte). The exploit: 31 | ```python 32 | list1 = open("enc.txt",'r').read()[1:-2] 33 | list1 = list1.split(",") 34 | list1 = [int(i[:-1]) for i in list1] 35 | list1 = [pow(i, (p-1)*(q-1), n) for i in list1] 36 | msg = "" 37 | for i in list1: 38 | for j in range(1, 256): 39 | if pow(g, j*(p-1)*(q-1), n) == i: 40 | msg += chr(j) 41 | print msg 42 | ``` 43 | This gives us the flag: MeePwnCTF{well_is_fact0rizati0n_0nly_w4y_to_s0lve_it?} 44 | Check out the entire exploit script [here](exploit.py) 45 | 46 | -------------------------------------------------------------------------------- /2017/MeePwn-CTF/Simpler-Than-RSA/enc.txt: -------------------------------------------------------------------------------- 1 | [1042684026433440609442082085056733059350277230855631475910449335289565957026925888L, 337451979363258259789969117391527857381178461709773977486124377788140579446959643L, 955044246855117318302069848746627916980637349888954523552188603828273408620783185L, 565084528151941455613387670829541401837686258558304725363697970401158298304784226L, 1217257199494998716855441753878986048959547533911751395319106679987808998530722005L, 500431401136979664818320806505265313829298163109190333815615071157569573408761776L, 918364738570517634370611128928418073524271175997413722821007998543195365584145047L, 1231818404429995719463458343454764290314747233553619629902141039984717307144020885L, 578663363706556074852662555903558050626510818844939214634690712022753850484044077L, 170573141141793020278685561667014942396340687197982787584671361315770701412232820L, 525046404028002961161648698133126471909762913783905233407759137018767422695415644L, 548918541683229869313458652944252600295112072416629330975730507209045241266103104L, 1097888538672145356012505481951969976746432194049237781078685846091302406138295450L, 467055824810727038529002950991149449402485370247343520114443047715384113252663243L, 379325228947504950566222318955652420189554769276755237788381017120582088704791796L, 808135517143354496893964869359259307455178022544381266003759602027195395780858971L, 232206696206622845104449934990777760916638497611027428059484100417419468488368534L, 611231502156630905749534239244947175924425232566020566839692916151929122262556160L, 266317680779170923895607136980535234290396471711461778811550899033797067803838490L, 458442169696983024890517742499158555610082173984048562536247204694360339657234325L, 173156860778775111311074302992389403207838028758953619505920477407616091727957249L, 327701451317276442403593523928518039719286029867533592333080575014882858204660392L, 1061889651976594791626195662010361995350291121541576461530446716234559629390059206L, 501107468516571472868902583880130438298825499145194993732906902954639206415408661L, 793462123972295663612808938124574874398657924694272939619742740367249265250881187L, 419580729971386599858472445685002497860174205402938481254320715563201540618526181L, 1095670842511297949652166375966107611580541850315423104099581710112461928501516645L, 1207404101728741308518114885496775915613418535791624006547396431596035842097919854L, 63257756791404477719948396035346460877053804738003821615924989712602434088623116L, 709743404772556668186521811311910146690879578711491970215935941312652194503904278L, 472145667401895260338686064243470672627707713552548730414485106260542589178719305L, 671679182553553455773258809387401495029229971280677124071355178172582087439182089L, 795683594959663064302728712706823881033923895027131034114737749301583410828859935L, 788511687111620345727088836755516496428115065618134997006646145097528302404655271L, 493455498376449391174132961453557751413575238351804592824587799692504725075730030L, 1071336432168555760392522471606603558083343440707490972056560901765084761996537479L, 76414279730707452882500835328589558586805800097281864786868179845530554318636818L, 1026789233929477564953495880177610952920067780854127113113934470636602509593246257L, 1220456099417710433363957577456670914480321272794999438920511570648408214807875401L, 831001855794529333359541390744984608592774868529241373516540331083225538929223854L, 406700540669900202178972508513521627652422698239818055618399192500676530118703988L, 535793870780869641948563592689023912632863260901941937211057060307409713921739965L, 908165522898293977370960880692560887898587015153655232763363739940417879927826149L, 916463042698051909403902218425035797085521743060997736870228165259059940402603712L, 1124064575055728289901493663250187815236366261544380516480084011806758657972869579L, 302544873761485689612490183241038411927316560916804219683347601892406383914571353L, 326809752614724517585542018284901481393260541798889339649409227233748588383860516L, 828292723696438834080952146252731883891295126479141546958923438287859173086057154L, 835877660712133206131980242990809426528248997858916518574414436451562226433887025L, 145587585798997332370407645289128453608803108424500991984349925153212212859373727L, 463948250139563696175107900326108271430940645044009515704115508942300583165355378L, 944242052057563352409261236875599145504153562928055236566287627433096232314943101L, 579193856270128178962709647899702648998261560149392089962175236519890756116448359L, 1167987057311285845643231967769257342900085143163437221731184706561190379437889873L] 2 | -------------------------------------------------------------------------------- /2017/MeePwn-CTF/Simpler-Than-RSA/exploit.py: -------------------------------------------------------------------------------- 1 | import gmpy2 2 | import pickle 3 | from Crypto.Util.number import * 4 | 5 | n = 1235280093599323856390922798440377476467763531842392869674688408727824382702235317 6 | g = 1110549711091392805024587195974719739929628997819528005374351081843256209971586072 7 | h = 610466084395822279908554174354632326166097007218620288020807622478449585661028278 8 | 9 | p = 1057817919251064684989791981 10 | q = 1103935256393984899021164397 11 | assert (p**2)*q == n 12 | 13 | phin = p*(p-1)*(q-1) 14 | list1 = open("enc.txt",'r').read()[1:-2] 15 | list1 = list1.split(",") 16 | list1 = [int(i[:-1]) for i in list1] 17 | 18 | # Exploit 19 | list1 = [pow(i, (p-1)*(q-1), n) for i in list1] 20 | msg = "" 21 | for i in list1: 22 | for j in range(1, 256): 23 | if pow(g, j*(p-1)*(q-1), n) == i: 24 | msg += chr(j) 25 | print msg -------------------------------------------------------------------------------- /2017/MeePwn-CTF/Simpler-Than-RSA/pubkey.txt: -------------------------------------------------------------------------------- 1 | 1235280093599323856390922798440377476467763531842392869674688408727824382702235317:1110549711091392805024587195974719739929628997819528005374351081843256209971586072:610466084395822279908554174354632326166097007218620288020807622478449585661028278 2 | -------------------------------------------------------------------------------- /2017/MeePwn-CTF/Simpler-Than-RSA/simple.py: -------------------------------------------------------------------------------- 1 | from Crypto.Util.number import * 2 | import random 3 | from flag import FLAG 4 | 5 | def generate(nbits): 6 | p = getPrime(nbits) 7 | q = getPrime(nbits) 8 | n = p * q * p 9 | g = random.randint(1, n) 10 | h = pow(g, n, n) 11 | return (n, g, h) 12 | 13 | def encrypt(m, n, g, h): 14 | r = random.randint(1, n) 15 | c = pow(pow(g, m, n) * pow(h, r, n), 1, n) 16 | return c 17 | 18 | m = [ord(char) for char in FLAG] 19 | n, g, h = generate(90) 20 | open("pubkey.txt", "w").write("{0}:{1}:{2}".format(n, g, h)) 21 | 22 | c = [encrypt(mi, n, g, h) for mi in m] 23 | open("enc.txt", "w").write(str(c)) 24 | -------------------------------------------------------------------------------- /2017/MeePwn-CTF/math/exploit.py: -------------------------------------------------------------------------------- 1 | import itertools 2 | from Crypto.Util.number import * 3 | from hashlib import md5 4 | import string 5 | 6 | hack = 64364485357060434848865708402537097493512746702748009007197338675 7 | 8 | # Generating all possible values of pad 9 | factor_list = [3, 3, 5, 5, 7, 107, 487, 607, 28249, 29287, 420577267963, 3680317203978923, 1002528655290265069] 10 | factor_combinations = [x for i in range(1, len(factor_list)-1) for x in itertools.combinations(factor_list, i)] 11 | list1 = [] 12 | for i in range(len(factor_combinations)): 13 | prod = 1 14 | for j in factor_combinations[i]: 15 | prod *= j 16 | if prod not in list1: 17 | list1.append(prod) 18 | 19 | # Possible values of pad 20 | possible_pad = [] 21 | for i in list1: 22 | if size(i) == 128 and hack%i==0: 23 | possible_pad.append(i) 24 | 25 | # Printing all the possible last characters 26 | possible_lastchar = [chr(i) for i in list1 if i<256 and chr(i) in string.printable and chr(i) not in string.whitespace] 27 | print possible_lastchar 28 | 29 | def hack(plaintext): 30 | assert len(plaintext) == 14 31 | hack = 0 32 | pad = bytes_to_long(md5(flag).digest()) 33 | for char in flag: 34 | hack += pad 35 | hack *= ord(char) 36 | return hack 37 | 38 | def attack(pad1, last_char): 39 | temp_hack = hack 40 | -------------------------------------------------------------------------------- /2017/MeePwn-CTF/math/test.py: -------------------------------------------------------------------------------- 1 | from Crypto.Util.number import * 2 | from hashlib import md5 3 | 4 | flag = "AAAAAAAAAAAAAA" 5 | assert len(flag) == 14 6 | pad = bytes_to_long(md5(flag).digest()) 7 | 8 | hack = 0 9 | 10 | for char in flag: 11 | hack+= pad 12 | hack*= ord(char) 13 | 14 | print hack -------------------------------------------------------------------------------- /2017/Plaid-CTF/Multicast/data.txt: -------------------------------------------------------------------------------- 1 | 69083553146183344839772978505267712546348345951915552104934666999364893606414967631473531356169090286677897220956536147203986323670778671853966574104550916190831974039291113434428713226539656233005536401237618731903013444912424490954403050283261443145833828774338405850464149745370010921929208582803372719662 2 | 1847353606880715823527099792264841437499256859046112182901817731898583109812226034453486290034759426343181112477498401843027934563915568068662901070357638240406212287869791959600724393823543974271939728800168160170264361943043888105413027223078955278440961637038127459036967868261370295558665462738851664674 3 | 13924397671629169794872532654354896735104301636897981275021597449713744312702850679542667853889775700566291452624971794825605462609659305736119167763171202028684488729179106128850062049316631850373987498751231054904292395688010798166991604433834113228237987911867991301264314792383410544657232986272138720776 4 | 107176667955056054888106289112863406099193890480114548290390156586316295797860714447523894766296345238663487884525751440074160698573876676529510120482633305843604033670838833224316621039974842663423971964367617383524243164757298543267528648455662196669719411550337416706436014652957797379123891565563380621721 5 | 27025595670607123748133955387986761928986723842407963667833744851457582823949409825451502999363014637018266381381800334740959357732693327871649715849440610655814448606276225985636706847320729571129651265791968308846145775455134446011658371731137714821594128627843120134392299295278193619998726010683820300906 6 | 76626521446699164152465241536023395842467420530412705255543098462161399927889232797875074266701010280661667851769988806969262190694662659916308198862288454347865777843483804317714263754964326435968683758707252482706186266157923587034286069745922345373717550980870551177895535541280767243258161167226140529179 7 | 74820001900443652318294067181707795319993357148314983190736617977547527951708569170206478241294503335669164830735894900549009883421968340647253048091278584463455833751347773269310148496440204410893225151858930449694234125324321395015257722229646579662704510552084383728048226410232141635889320648460673299335 8 | 116940935524323795130742526994657925027084667081524402264947741484054748546876541534619667289853985612350852220069194599338546449074832255593771931123087798582432365325897386813589970457955530817464044545954375253380129491859158211405510009895941963611340400391118219478974834168088677930751757315159110921841 9 | 3004029671513060545517047598385797934912754972599429487078366757715733246340760740484289209221138121568405251845847578856114711659946228365274190780159966913357682874178318970562635144717761245951754408952773122354583612422645258507146795630561366955268226048296864853067903656400207186949463324893914485565 10 | 39916349286626463801197107509708900778499859478703695888378041406302001988773262878930035955207487249221227735861868182215434820807844055889132141226547303138247159556705455695270756436706739886462479337109843197568024375533105139465029460850504284879314129902197486373473299170494478698741715992027042335920 11 | 14108999386222915459940913638433135402751523880380098398237968303803785854582535395117824943688282642164021530817702254201291805032640778641839809162886268856556652703619578965302291774447936003759868066323907388148146727752981125365333046242305065445858381847752308536916145502431706840471314490470498925933 12 | 100668102943542293762890526110731145470895119442621421158649868631915746146377966542031367735374167457406299434355768725246104804285632863373024153609404762902208230939718098090168262799174612923680636870557478441319366190063047687786785211877198536555745316733683533528849562416675658775836498023052914901749 13 | 42305211872257990504112591982462712826623117527580306258621876854892728665082535381823460722212076449810881809439537932537619270097066694079814712136330261508201872405339882571623217945205024525421229411985020496914748229102523658456972139082089291624782533401385935487411288676903751198610145921301518231107 14 | 37927948227203538741746385301195518552457676697015260677758470292294745311488915679784285945487731017142600921756814455642818173556814139042013977633776585763163271296255014647248684364947573160457459801483696377003575286309739820627536302900476424058673287304085337544422656511271366685116274814463373028939 15 | 29808378278310626950656040722768610557513777159495566134112105939237344988328390169388824486265334935284692186547128505302437631500267072936205473588904993250984366335171085215776781494184026623681600861765081754836053424849422843633084928107942855476866942904060229897408614881375916806167293356422910088562 16 | 80450031402201203587730534009338660865222026164984422981250298135548464160260574889923232542563882168618899594606271070764435488631855210441010916420059803623249294290301484880522559794167514055495411717729597100446344174893389277795663285345593590647340104666332031316803275436638414115193469755829893511487 17 | 35798442949372217448131245718267683892608947365147471016957781854054771928382329233065506241624702265207177594187978141208820788381204095301540789196845409818326829309725267401115274448449544207730582441399296587733377747658506089439891602945020732454221665678849354836056443444544603686977883511757122333808 18 | 15148604454321045616017299717211628700774278430049633748723698755621714384646643282913626328387905917563070000934175316190944226369346680779250458706206743862204417104832969982264440206554850551723416393459529398494316425018200651517022177685036277113534264161058597282135279496222169055121895473052233762246 19 | 90847039947327313643774540191254303763104502856236195148227169238729840332433440088244863054796973078431673232305152421572163200464861625035107176753552370732936207870756803675490237581973525804663863823181351604257906567409397759543713937699041851977124940235865938476195092603195522703292454934101412022811 20 | 93862849424043561789940054837392625966883465717813492561917969675964529083848723311514364070936115132154848096497003118110036719543385624344289211314373383330520240583297483284951457880437389550791045654411987778690675595035123064122359417085803319134114455113012761800931917960807358624095094896528184569953 21 | -------------------------------------------------------------------------------- /2017/Plaid-CTF/Multicast/exploit.sage: -------------------------------------------------------------------------------- 1 | from sage.all import * 2 | from Crypto.Util.number import * 3 | 4 | obj1 = open("data.txt","r") 5 | data = [] 6 | for i in obj1.readlines(): 7 | data.append(i) 8 | for i in range(len(data)): 9 | data[i] = int(data[i].strip("\n")) 10 | 11 | a = [data[i] for i in range(0,len(data),4)] 12 | b = [data[i] for i in range(1,len(data),4)] 13 | c = [data[i] for i in range(2,len(data),4)] 14 | n = [data[i] for i in range(3,len(data),4)] 15 | t = [] 16 | N = 1 17 | for i in n: 18 | N *= i 19 | 20 | # Applying Chinese Remainder Theorem 21 | for i in n: 22 | t.append(crt([1,0,0,0,0],[i]+[j for j in n if j!=i])) 23 | 24 | # Applying Coppersmith's Theorem 25 | e = 5 26 | gx = 0 27 | P. = PolynomialRing(Zmod(N)) 28 | for i in range(5): 29 | gx += t[i]*((a[i]*x+b[i])^e - c[i]) 30 | 31 | gx = gx.monic() 32 | assert gx.is_monic() 33 | 34 | list1 = gx.small_roots() 35 | for i in list1: 36 | print long_to_bytes(i) 37 | -------------------------------------------------------------------------------- /2017/Plaid-CTF/Multicast/exploit.sage.py: -------------------------------------------------------------------------------- 1 | 2 | # This file was *autogenerated* from the file exploit.sage 3 | from sage.all_cmdline import * # import sage library 4 | 5 | _sage_const_3 = Integer(3); _sage_const_2 = Integer(2); _sage_const_1 = Integer(1); _sage_const_0 = Integer(0); _sage_const_5 = Integer(5); _sage_const_4 = Integer(4) 6 | from sage.all import * 7 | from Crypto.Util.number import * 8 | 9 | obj1 = open("data.txt","r") 10 | data = [] 11 | for i in obj1.readlines(): 12 | data.append(i) 13 | for i in range(len(data)): 14 | data[i] = int(data[i].strip("\n")) 15 | 16 | a = [data[i] for i in range(_sage_const_0 ,len(data),_sage_const_4 )] 17 | b = [data[i] for i in range(_sage_const_1 ,len(data),_sage_const_4 )] 18 | c = [data[i] for i in range(_sage_const_2 ,len(data),_sage_const_4 )] 19 | n = [data[i] for i in range(_sage_const_3 ,len(data),_sage_const_4 )] 20 | t = [] 21 | N = _sage_const_1 22 | for i in n: 23 | N *= i 24 | 25 | # Applying Chinese Remainder Theorem 26 | for i in n: 27 | t.append(crt([_sage_const_1 ,_sage_const_0 ,_sage_const_0 ,_sage_const_0 ,_sage_const_0 ],[i]+[j for j in n if j!=i])) 28 | 29 | # Applying Coppersmith's Theorem 30 | e = _sage_const_5 31 | gx = _sage_const_0 32 | P = PolynomialRing(Zmod(N), names=('x',)); (x,) = P._first_ngens(1) 33 | for i in range(_sage_const_5 ): 34 | gx += t[i]*((a[i]*x+b[i])**e - c[i]) 35 | 36 | gx = gx.monic() 37 | assert gx.is_monic() 38 | 39 | list1 = gx.small_roots() 40 | for i in list1: 41 | print long_to_bytes(i) 42 | 43 | -------------------------------------------------------------------------------- /2017/Tokyo-Westerns-CTF/baby-dlp/b1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | python server.py -------------------------------------------------------------------------------- /2017/Tokyo-Westerns-CTF/baby-dlp/exploit.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | from Crypto.Util.number import * 3 | 4 | r = remote("localhost","1234") 5 | 6 | p = 160634950613302858781995506902938412625377360249559915379491492274326359260806831823821711441204122060415286351711411013883400510041411782176467940678464161205204391247137689678794367049197824119717278923753940984084059450704378828123780678883777306239500480793044460796256306557893061457956479624163771194201 7 | bits = size(p) 8 | g = 2 9 | 10 | r.sendline("0") 11 | gm = int(r.recv()[2:].replace("L","").rstrip("\n"), 16) 12 | max_size = 4 + bits//4 13 | 14 | pt = "" 15 | try: 16 | cnt = 0 17 | while True: 18 | s = hex(pow(2, cnt))[2:].replace("L","") 19 | r.sendline(s) 20 | temp = r.recv().rstrip("\n")[2:].replace("L","") 21 | if int(temp, 16) == ((gm % p) * pow(g, int(s, 16), p)) % p: 22 | pt += "0" 23 | else: 24 | pt += "1" 25 | cnt += 1 26 | if cnt%8 == 0: 27 | print hex(int(pt[::-1], 2))[2:].replace("L","").decode("hex") 28 | except: 29 | pass 30 | print hex(int(pt[::-1], 2))[2:].replace("L","").decode("hex") 31 | -------------------------------------------------------------------------------- /2017/Tokyo-Westerns-CTF/baby-dlp/flag: -------------------------------------------------------------------------------- 1 | TWCTF{0f97c1c3ac2aedbd7fb8cd39d50f2b561d31f770} -------------------------------------------------------------------------------- /2017/Tokyo-Westerns-CTF/baby-dlp/server.py: -------------------------------------------------------------------------------- 1 | # Python 3 2 | from signal import alarm 3 | from Crypto.Util.number import * 4 | 5 | p = 160634950613302858781995506902938412625377360249559915379491492274326359260806831823821711441204122060415286351711411013883400510041411782176467940678464161205204391247137689678794367049197824119717278923753940984084059450704378828123780678883777306239500480793044460796256306557893061457956479624163771194201 6 | g = 2 7 | 8 | bits = size(p) 9 | 10 | with open("flag", "r") as f: 11 | flag = f.readline().strip().encode("latin1") 12 | m = bytes_to_long(flag) 13 | 14 | def run(fin, fout): 15 | alarm(1200) 16 | try: 17 | while True: 18 | line = fin.readline()[:4+bits//4] 19 | s = int(line, 16) # Note: input is HEX 20 | c = pow(g, m ^ s, p) 21 | fout.write(hex(c) + "\n") 22 | fout.flush() 23 | except: 24 | pass 25 | 26 | if __name__ == "__main__": 27 | run(sys.stdin, sys.stdout) 28 | -------------------------------------------------------------------------------- /2018/ACEBEAR-Security-Contest/CNVService/AES_CNV_COOKIE.py: -------------------------------------------------------------------------------- 1 | from hashlib import md5 2 | from base64 import b64decode 3 | from base64 import b64encode 4 | from Crypto.Cipher import AES 5 | from time import ctime 6 | from Secret import __HIDDEN__, __SECRET__ 7 | 8 | BLOCK_SIZE = 16 9 | 10 | pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * \ 11 | chr(BLOCK_SIZE - len(s) % BLOCK_SIZE) 12 | unpad = lambda s: s[:-ord(s[len(s) - 1:])] 13 | 14 | def xor(dest, src): 15 | if len(dest) == 0: 16 | return src 17 | elif len(src) == 0: 18 | return dest 19 | elif len(dest) >= len(src): 20 | return ''.join(chr(ord(dest[i])^ord(src[i])) for i in range(len(src))) 21 | else: 22 | return ''.join(chr(ord(dest[i])^ord(src[i])) for i in range(len(dest))) 23 | 24 | 25 | class AES_CNV: 26 | 27 | def __init__(self, key): 28 | assert len(key) == BLOCK_SIZE 29 | self.key = key 30 | 31 | def encrypt(self, plain_text, iv): 32 | assert len(iv) == 16 33 | plain_text = pad(plain_text) 34 | assert len(plain_text)%BLOCK_SIZE == 0 35 | cipher_text = '' 36 | aes = AES.new(self.key, AES.MODE_ECB) 37 | h = iv 38 | for i in range(len(plain_text)//BLOCK_SIZE): 39 | block = plain_text[i*16:i*16+16] 40 | block = xor(block, h) 41 | cipher_block = aes.encrypt(block) 42 | cipher_text += cipher_block 43 | h = md5(cipher_block).digest() 44 | return iv+cipher_text 45 | 46 | def decrypt(self, cipher_text): 47 | assert len(cipher_text)%BLOCK_SIZE == 0 48 | iv = cipher_text[:16] 49 | cipher_text = cipher_text[16:] 50 | aes = AES.new(self.key, AES.MODE_ECB) 51 | h = iv 52 | plain_text = '' 53 | for i in range(len(cipher_text)//BLOCK_SIZE): 54 | block = cipher_text[i*16:i*16+16] 55 | plain_block = aes.decrypt(block) 56 | plain_block = xor(plain_block, h) 57 | plain_text += plain_block 58 | h = md5(block).digest() 59 | return unpad(plain_text) 60 | 61 | class Cookie: 62 | 63 | def __init__(self, key): 64 | assert len(key) == BLOCK_SIZE 65 | self.key = key 66 | 67 | def register(self, name, username): 68 | name = pad(name) 69 | iv = xor(name, md5(__HIDDEN__).digest()) 70 | cookie = "CNVService" + "*" + "user="+ username + "*" + ctime() + "*" + __SECRET__ 71 | aescnv = AES_CNV(self.key) 72 | cookie = aescnv.encrypt(cookie, iv) 73 | return b64encode(cookie) 74 | 75 | def authentication(self, cookie): 76 | cookie = b64decode(cookie) 77 | name = cookie[:16] 78 | name = xor(name, md5(__HIDDEN__).digest()) 79 | if ord(name[-1]) < 16: 80 | name = unpad(name) 81 | aescnv = AES_CNV(self.key) 82 | cookie = aescnv.decrypt(cookie) 83 | info = cookie.split("*") 84 | if info[0] != "CNVService": 85 | return None, None, None 86 | elif info[-1] != __SECRET__: 87 | return None, None, None 88 | elif "user=" != info[1][:5]: 89 | return None, None, None 90 | elif len(info[1].split("=")) == 2: 91 | return name, info[1].split("=")[1], info[2] 92 | else: 93 | return None, None, None 94 | -------------------------------------------------------------------------------- /2018/ACEBEAR-Security-Contest/CNVService/CNVService.py: -------------------------------------------------------------------------------- 1 | import os 2 | import socket 3 | import threading 4 | import time 5 | import SocketServer 6 | from AES_CNV_COOKIE import Cookie, BLOCK_SIZE 7 | from Crypto import Random 8 | from Secret import __FLAG__ 9 | 10 | host, port = '0.0.0.0', 4444 11 | BUFF_SIZE = 1024 12 | 13 | class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): 14 | allow_reuse_address = True 15 | 16 | class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler): 17 | 18 | def Register(self): 19 | self.request.sendall("*****************************REGISTER*****************************\n") 20 | self.request.sendall("Name: ") 21 | name = self.request.recv(BUFF_SIZE).strip() 22 | self.request.sendall("Username: ") 23 | username = self.request.recv(BUFF_SIZE).strip() 24 | if "root" in username: 25 | self.request.sendall("Can not register root user!\n") 26 | else: 27 | cookie = self.cookie.register(name, username) 28 | self.request.sendall("Cookie: %s\n" %cookie) 29 | self.request.sendall("***************************END REGISTER***************************\n") 30 | 31 | def Login(self): 32 | self.request.sendall("*******************************LOGIN******************************\n") 33 | self.request.sendall("Cookie: ") 34 | cookie = self.request.recv(BUFF_SIZE).strip() 35 | name, username, time = self.cookie.authentication(cookie) 36 | if username == None: 37 | self.request.sendall("Don't attack my service, hacker!\n") 38 | self.request.sendall("***************************LOGIN FALSE****************************\n") 39 | else: 40 | self.request.sendall("**************************LOGIN SUCCESS***************************\n") 41 | self.request.sendall("Welcome CNV service: %s\n" %name) 42 | self.request.sendall("Username: %s\n" %username) 43 | self.request.sendall("Time register: %s\n" %time) 44 | if username != "root": 45 | self.request.sendall("Sorry! This service support only root user! Please waiting service upgrade.\n") 46 | return False 47 | else: 48 | self.request.sendall("***************************Root Servive***************************\n") 49 | self.request.sendall("This is flag: %s\n" %__FLAG__) 50 | return True 51 | 52 | def handle(self): 53 | self.key = Random.new().read(BLOCK_SIZE) 54 | self.cookie = Cookie(self.key) 55 | self.request.settimeout(1) 56 | self.countuser = 0 57 | self.request.sendall("***************************CNVService*****************************\n") 58 | self.request.sendall("* Challenge created by CNV *\n") 59 | self.request.sendall("* My blog: https://chung96vn.blogspot.com *\n") 60 | self.request.sendall("***************************CNVService*****************************\n") 61 | while True: 62 | self.request.sendall("********************Menu********************\n") 63 | self.request.sendall("* 1 - Register *\n") 64 | self.request.sendall("* 2 - Login *\n") 65 | self.request.sendall("********************************************\n") 66 | self.request.sendall("Your choice: ") 67 | try: 68 | choice = int(self.request.recv(BUFF_SIZE).strip()) 69 | except: 70 | choice = 0 71 | if choice == 1: 72 | if self.countuser < 2: 73 | if self.Register(): 74 | self.countuser += 1 75 | else: 76 | self.request.sendall("Can not register more than two user!\n") 77 | elif choice == 2: 78 | self.Login() 79 | break 80 | else: 81 | self.request.sendall("Invalid choice!\n") 82 | break 83 | def main(): 84 | server = ThreadedTCPServer((host, port), ThreadedTCPRequestHandler) 85 | server_thread = threading.Thread(target=server.serve_forever) 86 | server_thread.daemon = True 87 | server_thread.start() 88 | print "Server loop running in thread:", server_thread.name 89 | server_thread.join() 90 | 91 | if __name__ == '__main__': 92 | main() 93 | -------------------------------------------------------------------------------- /2018/ACEBEAR-Security-Contest/CNVService/README.md: -------------------------------------------------------------------------------- 1 | # CNVService 2 | 3 | **Challenge Points**: 856 4 | 5 | **Challenge Description**: 6 | 7 | Check out my writeup for this challenge on my blog [here](https://masterpessimistaa.wordpress.com/2018/01/31/cnvservice-acebear-ctf-2018-writeup/) 8 | 9 | -------------------------------------------------------------------------------- /2018/ACEBEAR-Security-Contest/CNVService/exploit.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | from hashlib import md5 3 | 4 | def xor(dest, src): 5 | if len(dest) == 0: 6 | return src 7 | elif len(src) == 0: 8 | return dest 9 | elif len(dest) >= len(src): 10 | return ''.join(chr(ord(dest[i])^ord(src[i])) for i in range(len(src))) 11 | else: 12 | return ''.join(chr(ord(dest[i])^ord(src[i])) for i in range(len(dest))) 13 | 14 | def Register(name, username): 15 | r = remote('cnvservice.acebear.site', '1337') 16 | r.recvuntil("choice: ") 17 | r.send('1') 18 | r.recvuntil("Name: ") 19 | r.send(name+"\x00"*50) 20 | r.recvuntil("Username: ") 21 | r.send(username) 22 | cookie = r.recvline()[8:] 23 | r.close() 24 | return cookie 25 | 26 | def Login(cookie): 27 | r = remote('cnvservice.acebear.site', '1337') 28 | r.recvuntil("choice: ") 29 | r.send('2') 30 | r.recvuntil("Cookie: ") 31 | r.send(cookie) 32 | message = r.recvall() 33 | r.close() 34 | return message 35 | 36 | input_username = "roo7++++++++++++" 37 | favorable_username = "root*+++++++++++" 38 | cookie = Register('', input_username) 39 | cookie = cookie.decode("base64") 40 | 41 | #Vectors for XORing 42 | iv = cookie[:16] 43 | second_vector = md5(cookie[16:32]).digest() 44 | third_vector = md5(cookie[32:48]).digest() 45 | 46 | payload = xor(second_vector, favorable_username) 47 | payload = xor(payload, third_vector) 48 | 49 | # Registration 50 | cookie2 = Register('', input_username + payload) 51 | cookie2 = cookie2.decode("base64") 52 | attack_block = cookie2[48:64] 53 | 54 | #Logging in as root 55 | attack_cookie = iv + cookie[16:32] + attack_block + cookie[32:] 56 | print Login(attack_cookie.encode("base64")) 57 | -------------------------------------------------------------------------------- /2018/CSAW-Finals/DisastrousSecurity/MTRecover.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | 4 | class MT19937Recover: 5 | """Reverses the Mersenne Twister based on 624 observed outputs. 6 | 7 | The internal state of a Mersenne Twister can be recovered by observing 8 | 624 generated outputs of it. However, if those are not directly 9 | observed following a twist, another output is required to restore the 10 | internal index. 11 | 12 | See also https://en.wikipedia.org/wiki/Mersenne_Twister#Pseudocode . 13 | 14 | """ 15 | def unshiftRight(self, x, shift): 16 | res = x 17 | for i in range(32): 18 | res = x ^ res >> shift 19 | return res 20 | 21 | def unshiftLeft(self, x, shift, mask): 22 | res = x 23 | for i in range(32): 24 | res = x ^ (res << shift & mask) 25 | return res 26 | 27 | def untemper(self, v): 28 | """ Reverses the tempering which is applied to outputs of MT19937 """ 29 | 30 | v = self.unshiftRight(v, 18) 31 | v = self.unshiftLeft(v, 15, 0xefc60000) 32 | v = self.unshiftLeft(v, 7, 0x9d2c5680) 33 | v = self.unshiftRight(v, 11) 34 | return v 35 | 36 | def go(self, outputs, forward=True): 37 | """Reverses the Mersenne Twister based on 624 observed values. 38 | 39 | Args: 40 | outputs (List[int]): list of >= 624 observed outputs from the PRNG. 41 | However, >= 625 outputs are required to correctly recover 42 | the internal index. 43 | forward (bool): Forward internal state until all observed outputs 44 | are generated. 45 | 46 | Returns: 47 | Returns a random.Random() object. 48 | """ 49 | 50 | result_state = None 51 | 52 | assert len(outputs) >= 624 # need at least 624 values 53 | 54 | ivals = [] 55 | for i in range(624): 56 | ivals.append(self.untemper(outputs[i])) 57 | 58 | if len(outputs) >= 625: 59 | # We have additional outputs and can correctly 60 | # recover the internal index by bruteforce 61 | challenge = outputs[624] 62 | for i in range(1, 626): 63 | state = (3, tuple(ivals+[i]), None) 64 | r = random.Random() 65 | r.setstate(state) 66 | 67 | if challenge == r.getrandbits(32): 68 | result_state = state 69 | break 70 | else: 71 | # With only 624 outputs we assume they were the first observed 624 72 | # outputs after a twist --> we set the internal index to 624. 73 | result_state = (3, tuple(ivals+[624]), None) 74 | 75 | rand = random.Random() 76 | rand.setstate(result_state) 77 | 78 | if forward: 79 | for i in range(624, len(outputs)): 80 | assert rand.getrandbits(32) == outputs[i] 81 | 82 | return rand 83 | 84 | 85 | def test_PythonMT19937Recover(): 86 | """Just a testcase to ensure correctness""" 87 | mtb = MT19937Recover() 88 | 89 | r1 = random.Random(0x31337) 90 | 91 | # just some discarded random numbers to move internal state forward 92 | [r1.getrandbits(32) for _ in range(1234)] 93 | 94 | # the actual leak of 1000 values 95 | n = [r1.getrandbits(32) for _ in range(1000)] 96 | 97 | r2 = mtb.go(n) 98 | 99 | assert r1.getrandbits(32) == r2.getrandbits(32) 100 | 101 | 102 | test_PythonMT19937Recover() 103 | -------------------------------------------------------------------------------- /2018/CSAW-Finals/DisastrousSecurity/MTRecover.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/CSAW-Finals/DisastrousSecurity/MTRecover.pyc -------------------------------------------------------------------------------- /2018/CSAW-Finals/DisastrousSecurity/MersenneTwister.py: -------------------------------------------------------------------------------- 1 | 2 | class MT19937: 3 | """Classical Mersenne Twister Implementation.""" 4 | 5 | def __init__(self, seed=None): 6 | self.mt = [0 for i in range(624)] 7 | self.index = 624 8 | if seed is not None: 9 | self.seed(seed) 10 | 11 | def seed(self, seed): 12 | self.mt[0] = seed 13 | for i in range(1, 624): 14 | self.mt[i] = self._int32(0x6c078965 * 15 | (self.mt[i - 1] ^ (self.mt[i - 1] >> 30)) + i) 16 | 17 | def extract(self): 18 | """ Extracts a 32bit word """ 19 | if self.index >= 624: 20 | self.twist() 21 | 22 | x = self.mt[self.index] 23 | x ^= x >> 11 24 | x ^= (x << 7) & 0x9d2c5680 25 | x ^= (x << 15) & 0xefc60000 26 | x ^= x >> 18 27 | 28 | self.index += 1 29 | return self._int32(x) 30 | 31 | def twist(self): 32 | """ The twist operation. Advances the internal state """ 33 | for i in range(624): 34 | upper = 0x80000000 35 | lower = 0x7fffffff 36 | 37 | x = self._int32((self.mt[i] & upper) + 38 | (self.mt[(i + 1) % 624] & lower)) 39 | self.mt[i] = self.mt[(i + 397) % 624] ^ (x >> 1) 40 | 41 | if x & 1 != 0: 42 | self.mt[i] ^= 0x9908b0df 43 | 44 | self.index = 0 45 | 46 | def _int32(self, x): 47 | return x & 0xffffffff 48 | 49 | 50 | class PythonMT19937(MT19937): 51 | """Minimalistic Mersenne Twister implementation with python's custom seed, 52 | which allows for the seed to be larger than 32 bit. 53 | 54 | Returns 32bit values via extract(). 55 | """ 56 | def __init__(self, seed=None): 57 | MT19937.__init__(self) 58 | if seed is not None: 59 | self.seed(seed) 60 | 61 | def seed(self, n): 62 | lower = 0xffffffff 63 | keys = [] 64 | 65 | while n: 66 | keys.append(n & lower) 67 | n >>= 32 68 | 69 | if len(keys) == 0: 70 | keys.append(0) 71 | 72 | self.init_by_array(keys) 73 | 74 | def init_by_array(self, keys): 75 | MT19937.seed(self, 0x12bd6aa) 76 | i, j = 1, 0 77 | for _ in range(max(624, len(keys))): 78 | self.mt[i] = self._int32((self.mt[i] ^ ((self.mt[i-1] ^ 79 | (self.mt[i-1] >> 30)) * 0x19660d)) + keys[j] + j) 80 | i += 1 81 | j += 1 82 | if i >= 624: 83 | self.mt[0] = self.mt[623] 84 | i = 1 85 | j %= len(keys) 86 | 87 | for _ in range(623): 88 | self.mt[i] = self._int32((self.mt[i] ^ ((self.mt[i-1] ^ 89 | (self.mt[i-1] >> 30)) * 0x5d588b65)) - i) 90 | i += 1 91 | if i >= 624: 92 | self.mt[0] = self.mt[623] 93 | i = 1 94 | 95 | self.mt[0] = 0x80000000 96 | 97 | 98 | def test_PythonMT19937(): 99 | import random 100 | seed = 0x31337 101 | 102 | mtorig = random.Random(seed) 103 | mt = PythonMT19937(seed) 104 | 105 | for i in range(1337): 106 | r1 = mtorig.getrandbits(32) 107 | r2 = mt.extract() 108 | 109 | assert r1 == r2 110 | 111 | test_PythonMT19937() 112 | -------------------------------------------------------------------------------- /2018/CSAW-Finals/DisastrousSecurity/exploit.py: -------------------------------------------------------------------------------- 1 | from MTRecover import MT19937Recover 2 | from Crypto.Util.number import * 3 | from Crypto.PublicKey import ElGamal 4 | from cryptography.hazmat.primitives.asymmetric.utils import encode_dss_signature 5 | from cryptography.hazmat.primitives.asymmetric.dsa import * 6 | import random 7 | import struct 8 | import requests 9 | import json 10 | import hashlib 11 | 12 | local = "http://localhost:5000/" 13 | remote = "http://crypto.chal.csaw.io:1009/" 14 | 15 | def chunk(inputstr, size): 16 | return [inputstr[i:i+size] for i in range(0, len(inputstr), size)] 17 | 18 | def mersennebreaker(output_list): 19 | assert len(output_list) > 624 20 | mtr = MT19937Recover() 21 | r2 = mtr.go(output_list) 22 | return r2 23 | 24 | def _forgotpassword(): 25 | req = requests.get(remote + "forgotpass") 26 | return str(req.text[33:]).decode("hex") 27 | 28 | def _get_publickey(): 29 | req = requests.get(remote + "public_key") 30 | return (json.loads(req.text)['p'], json.loads(req.text)['q'], json.loads(req.text)['y'], json.loads(req.text)['g']) 31 | 32 | def _get_sign(data): 33 | req = requests.get(remote + "sign/" + data) 34 | return (json.loads(req.text)['r'], json.loads(req.text)['s']) 35 | 36 | def _get_secretkey(r, s, q, h, r2): 37 | k = r2.randrange(2, q) 38 | rinv = inverse(r, q) 39 | x = (rinv * (s*k - h)) % q 40 | return x 41 | 42 | def _get_challenge(): 43 | req = requests.get(remote + "challenge") 44 | return req.text 45 | 46 | def _sign(data, g, k, p, q, x): 47 | kinv = inverse(k, q) 48 | r = pow(g, k, p) % q 49 | h = bytes_to_long(hashlib.sha256(data).digest()) 50 | s = (kinv * (h + r*x)) % q 51 | return (r, s) 52 | 53 | 54 | outputs = [] 55 | for i in range(313): 56 | randnum = _forgotpassword() 57 | chunks = chunk(randnum, 4)[::-1] 58 | for j in range(len(chunks)): 59 | chunks[j] = bytes_to_long(chunks[j]) 60 | outputs.extend(chunks) 61 | print "mersenne breaking iterator value: ", i 62 | 63 | r2 = mersennebreaker(outputs) 64 | assert r2.getrandbits(64) == bytes_to_long(_forgotpassword()) 65 | 66 | # Getting public key parameter values 67 | p, q, y, g = _get_publickey() 68 | 69 | # Signing some data 70 | r, s = _get_sign("testmsg") 71 | h = bytes_to_long(hashlib.sha1("testmsg").digest()) 72 | # Getting the value of secret key 73 | x = _get_secretkey(r, s, q, h, r2) 74 | 75 | assert y == pow(g, x, p) 76 | 77 | # Get string to be signed 78 | sign_string = _get_challenge() 79 | 80 | print "Sign string: ", sign_string 81 | print "p: ", p 82 | print "secret key: ", x 83 | 84 | sig = _sign(sign_string, g, 13, p, q, x) 85 | r1, s1 = sig 86 | signa = encode_dss_signature(r1, s1).encode("hex") 87 | 88 | req = requests.post(remote + "capture",data={"signature":signa, "challenge":sign_string}) 89 | print req.text 90 | -------------------------------------------------------------------------------- /2018/CSAW-Finals/DisastrousSecurity/main.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | import hashlib 3 | import json 4 | import os 5 | import random 6 | import struct 7 | 8 | from cryptography.exceptions import InvalidSignature 9 | from cryptography.fernet import Fernet, InvalidToken 10 | from cryptography.hazmat.backends import default_backend 11 | from cryptography.hazmat.primitives import hashes 12 | from cryptography.hazmat.primitives.asymmetric.rsa import _modinv 13 | from cryptography.hazmat.primitives.serialization import load_pem_private_key 14 | 15 | from flask import Flask, abort, request 16 | 17 | 18 | app = Flask(__name__) 19 | 20 | 21 | with open("ctf.key", "rb") as f: 22 | pem_data = f.read() 23 | 24 | ctf_key = load_pem_private_key( 25 | pem_data, password=None, backend=default_backend() 26 | ) 27 | 28 | CSAW_FLAG = open("flag").read().strip() 29 | FERNET = Fernet(Fernet.generate_key()) 30 | 31 | 32 | @app.route("/capture", methods=["POST"]) 33 | def capture(): 34 | sig = binascii.unhexlify(request.form["signature"]) 35 | challenge = request.form["challenge"].encode("ascii") 36 | try: 37 | FERNET.decrypt(challenge) 38 | except InvalidToken: 39 | print ("Here") 40 | abort(400) 41 | try: 42 | ctf_key.public_key().verify(sig, challenge, hashes.SHA256()) 43 | return "flag{%s}" % CSAW_FLAG 44 | except InvalidSignature: 45 | print ("Here2") 46 | abort(400) 47 | 48 | 49 | @app.route("/challenge") 50 | def challenge(): 51 | return FERNET.encrypt(b"challenged!") 52 | 53 | 54 | @app.route("/sign/") 55 | def signer(data): 56 | r, s = sign(ctf_key, data) 57 | return json.dumps({"r": r, "s": s}) 58 | 59 | 60 | @app.route("/forgotpass") 61 | def returnrand(): 62 | # Generate a random value for the reset URL so it isn't guessable 63 | random_value = binascii.hexlify(struct.pack(">Q", random.getrandbits(64))) 64 | return "https://innitech.local/resetpass/{}".format( 65 | random_value.decode("ascii") 66 | ) 67 | 68 | 69 | @app.route("/resetpass/") 70 | def resetpass(key): 71 | # TODO: Implement this later. Innitech doesn"t utilize users in this system 72 | # right now anyway. 73 | return "", 500 74 | 75 | 76 | @app.route("/public_key") 77 | def public_key(): 78 | pn = ctf_key.private_numbers() 79 | return json.dumps({ 80 | "g": pn.public_numbers.parameter_numbers.g, 81 | "q": pn.public_numbers.parameter_numbers.q, 82 | "p": pn.public_numbers.parameter_numbers.p, 83 | "y": pn.public_numbers.y 84 | }) 85 | 86 | 87 | @app.route("/") 88 | def main(): 89 | return "Welcome to Innitech. Good luck!" 90 | 91 | 92 | def sign(ctf_key, data): 93 | data = data.encode("ascii") 94 | pn = ctf_key.private_numbers() 95 | g = pn.public_numbers.parameter_numbers.g 96 | q = pn.public_numbers.parameter_numbers.q 97 | p = pn.public_numbers.parameter_numbers.p 98 | x = pn.x 99 | k = random.randrange(2, q) 100 | kinv = _modinv(k, q) 101 | r = pow(g, k, p) % q 102 | h = hashlib.sha1(data).digest() 103 | h = int.from_bytes(h, "big") 104 | s = kinv * (h + r * x) % q 105 | return (r, s) 106 | 107 | 108 | if __name__ == "__main__": 109 | app.run(host="0.0.0.0") 110 | -------------------------------------------------------------------------------- /2018/CSAW-Finals/DisastrousSecurity/test.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/CSAW-Finals/DisastrousSecurity/test.key -------------------------------------------------------------------------------- /2018/Codegate-CTF-Preliminary/RSAbaby/README.md: -------------------------------------------------------------------------------- 1 | # RSAbaby 2 | The idea behind the challenge involved knowledge of basic Number Theory which was pretty cool. 3 | 4 | We are given a couple of parameters and an encryption script which is used for encrypting the message. Everything in the script works normally except the `GenerateKeys` function: 5 | ![picture](https://i.imgur.com/RdXt8bo.png) 6 | There is are two extra variables other than the regular public key parameters whose values are known: `g` and `h` 7 | 8 | I think the challenge creators left two different intentional vulnerabilities- one was bit by bit decryption and the other was a simple application of number theory. We discuss exploiting `g` using simple yet interesting application of number theory 9 | 10 | ## The exploit 11 | We know that: 12 | ![equation](https://latex.codecogs.com/gif.latex?g=d*(p-0xdeadbeef)) 13 | ![equation](https://latex.codecogs.com/gif.latex?eg=ed*(p-0xdeadbeef)) 14 | ![equation](https://latex.codecogs.com/gif.latex?2^{eg}=2^{ed*(p-0xdeadbeef)}) 15 | ![equation](https://latex.codecogs.com/gif.latex?2^{eg}\mod&space;n=2^{ed*(p-0xdeadbeef)}\mod&space;n) 16 | Thus we can write, 17 | ![equation](https://latex.codecogs.com/gif.latex?2^{ed*(p-0xdeadbeef)}=2^{(1+k\phi(n))*(p-0xdeadbeef)}) 18 | ![equation](https://latex.codecogs.com/gif.latex?2^{(1+k\phi(n))*(p-0xdeadbeef)}=(2*2^{k\phi(n)})^{(p-0xdeadbeef)}) 19 | ![equation](https://latex.codecogs.com/gif.latex?(2*2^{k\phi(n)})^{(p-0xdeadbeef)}=2^{(p-0xdeadbeef)}*2^{k*\phi(n)*(p-0xdeadebeef)}) 20 | We know from Euler's Theorem that when GCD(a, n) == 1: 21 | ![equation](https://latex.codecogs.com/gif.latex?a^{\phi(n)}\equiv1\mod&space;n) 22 | ![equation](https://latex.codecogs.com/gif.latex?2^{(p-0xdeadbeef)}*2^{k*\phi(n)*(p-0xdeadebeef)}\equiv2^{p-0xdeadebeef}*1\mod&space;n) 23 | ![equation](https://latex.codecogs.com/gif.latex?2^{eg}\mod&space;n=2^{p-0xdeadbeef}\mod&space;n) 24 | ![equation](https://latex.codecogs.com/gif.latex?2^{eg}*2^{0xdeadbeef}\mod&space;n=2^{p}\mod&space;n) 25 | We know from Fermat's Little Theorem that when GCD(a, p) == 1: 26 | ![equation](https://latex.codecogs.com/gif.latex?a^{p}\equiv&space;a\mod&space;p) 27 | We can now write: 28 | ![equation](https://latex.codecogs.com/gif.latex?2^{eg}*2^{0xdeadbeef}\mod&space;n=(kp+2)\mod&space;n) 29 | Thus, 30 | ![equation](https://latex.codecogs.com/gif.latex?2^{eg}*2^{0xdeadbeef}-2\mod&space;n=kp\mod&space;n) 31 | will be a factor of the RSA modulus N. 32 | We can easily get one of the factors of N as p = GCD(2^(eg + 0xdeadbeef) mod N - 2, N) and q = N/p 33 | 34 | ## Exploit script 35 | Checkout the complete exploit script [here](exploit.py) -------------------------------------------------------------------------------- /2018/Codegate-CTF-Preliminary/RSAbaby/RSAbaby.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | #-*- coding:utf-8 -*- 3 | 4 | from gmpy2 import * 5 | import sys 6 | import time 7 | import struct 8 | 9 | def PrintIntro(): 10 | print "██████╗ ███████╗ █████╗ ██████╗ █████╗ ██████╗ ██╗ ██╗" 11 | print "██╔══██╗██╔════╝██╔══██╗██╔══██╗██╔══██╗██╔══██╗╚██╗ ██╔╝" 12 | print "██████╔╝███████╗███████║██████╔╝███████║██████╔╝ ╚████╔╝ " 13 | print "██╔══██╗╚════██║██╔══██║██╔══██╗██╔══██║██╔══██╗ ╚██╔╝ " 14 | print "██║ ██║███████║██║ ██║██████╔╝██║ ██║██████╔╝ ██║ " 15 | print "╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝╚═════╝ ╚═╝ " 16 | 17 | def xgcd(b, n): 18 | x0, x1, y0, y1 = 1, 0, 0, 1 19 | while n != 0: 20 | q, b, n = b // n, n, b % n 21 | x0, x1 = x1, x0 - q * x1 22 | y0, y1 = y1, y0 - q * y1 23 | return b, x0, y0 24 | 25 | def mulinv(b, n): 26 | g, x, _ = xgcd(b, n) 27 | if g == 1: 28 | return x % n 29 | 30 | def GenerateN(randomST): 31 | k1 = mpz_urandomb(randomST, 2048) 32 | k2 = mpz_urandomb(randomST, 2048) 33 | 34 | p = next_prime(k1) 35 | q = next_prime(k2) 36 | 37 | if is_prime(p, 50) and is_prime(q, 50): 38 | return [p, q] 39 | 40 | def GenerateKeys(p, q): 41 | e = 65537 42 | n = p * q 43 | pi_n = (p-1)*(q-1) 44 | d = mulinv(e, pi_n) 45 | h = (d+p)^(d-p) 46 | g = d*(p-0xdeadbeef) 47 | 48 | return [e, n, h, g] 49 | 50 | def EncryptMsg(): 51 | Flag = "########################################" 52 | 53 | PrintIntro() 54 | 55 | f = open("/dev/urandom") 56 | seed = f.read(8) 57 | f.close() 58 | randomST = random_state(struct.unpack(">Q", seed)[0]) 59 | 60 | print("[*] Generating Key ...\n") 61 | p, q = GenerateN(randomST) 62 | e, N, hint, gint = GenerateKeys(p, q) 63 | time.sleep(2) 64 | 65 | print("[*] Completed !!!\n") 66 | time.sleep(1) 67 | 68 | Flag = Flag.ljust(255, "\x2a") 69 | Flag = int(Flag.encode('hex'),16) 70 | 71 | EncryptedData = powmod(Flag, e, N) 72 | 73 | print("[*] Encrypted Data : %d\n" % EncryptedData) 74 | print("[*] N : %d\n" % N) 75 | print("[*] h : %d\n" % hint) 76 | print("[*] g : %d\n" % gint) 77 | 78 | if __name__ == '__main__': 79 | EncryptMsg() 80 | -------------------------------------------------------------------------------- /2018/Codegate-CTF-Preliminary/RSAbaby/Result.txt: -------------------------------------------------------------------------------- 1 | [*] Encrypted Data : 380838525806255337893946743050327173947433371586247814759050430578204300094635270877953690129762202769875996939276197842147224857220372679703619497806927398399795108952962442891905146440202908075035070979097412854358636621348531277713225298087614167276769631514565642627640343771883615641654535423058064397195504442204533423747451626752470200734177912209703945585196661670059908372263823148356525332391696830864610833871912286943309315368473809329884078356658600058695228563250424729883958206468130236010169302227516477051342268478958591705205358855157076547042386496593253499052139707216013118968009859098636706611794339780312391554420587540660796607687910531233690474314728367495027785278881971814489961127141923005420385579115964806930701533734013794866357390109761177291603859980361697959155126598284421792362843501361967548503757576918138895493498276658301936707818035503138088925361983300854592909022681075014994189523262500924039153521343614460622246152945716505290603455309333333560506091410274263241508522602811994582040578653226240563907254131889033343189265841619698442130035569880428826546382882121430886993470180883869383405219173399698928360778092640513571913940390199302310817294277155376000921294944591121246587133744 2 | 3 | [*] N : 523639805914061918270627443134741619704989339108811345591765650823383811679404400743730300288077320843234806116907796484315512386749183735427076044515394957782722144465236043561036957495670530886847413432636828661793513741180618385135095922719611444315861194066682307139969523206842728092440966461922557111209480112023032164065707216752568624317883094770784553451376502893748762652573604180632157059219119741129827017117558208565054860250853978397405747507844727903363351081745897472675235414693294079400158465019978970101063161094836772073302365997371679643083941089269169502839517043186914783290465318781726781533226599462066259256698885200843104424722505593942510854302401488139137362276492532699951880474157691347473741517183512613811731637427562990396497067805682564174185792379491573312640862381843195615293946630128509982267460922475624107750277459002662884836031305873522960659017891138316482378312004790485681371129328860344989214941450460756203906709954285455206483931555441550631622907560476932030275168094874500348941952385811045752980245084909805234648503736291123092594689494187215718382724496356220857628352007757197464098872772987476828030721472777531411032286344430474215475330008833588291692767417022829531866323051 4 | 5 | [*] h : 200972731730097636976827049698214756107439330058946586294810837394189769656758467301378455256704981506024979360358854939307759891385801491668590432728409172325924823845795802068569504027458509726942683684845099685005724309372842055251251103232234279320256975662933177657993600463290652464246399357992101963313348397652939723188131041888535203383479379782750484175239116419074864386243581748425119257869351582631464696880797553969260415636591522791709442079709586828716914705946883433533874750682958642851920347897328709815665287336267018234850211541263570668304013958387590188226346947851729783080697306777656948546082 6 | 7 | [*] g : 14511485561279877242490049924164262671564856980418706493772866848857612385453104346586350276227873984815502106112389832011566814347565705873657427101510533972939335373118027470906354834216983842099812965592939768854241417529908124711818216182341332507918374220901579987851767888710421089266081280013256600425746557269742268670300714949183260246617797156425767983027415373581836147225552931559016487193903056680274018867169067069164417868649729813464306199388375773268972224468436723728788928618254041886532217172217283880677562744928063668302190530092708676086756514664006766909499651097644447881334032649057611965077951245778537347658519214651268439995915614667939336569800565797702566887133370244643122543689011224353239395653153094885449557256699923700742653930928887024447374907536229536501931493386170594869542262576409686250950887746501725676758035668270309685358291271363775138099327895323451901829587908987436831617628346535627562925010698445652286450107659802164994355539623617745529876829000553355956755914526849056343372137493951531663650121127924626353148067965144997177441402726593083629261964699315644045714647617156724816370270635144953182744245498998992807987174252376199074131496163299914588620694929584594866873400406185502626180264465104468365933575409921644759774899908018217623256295871823903858740112075223018089096313796599554636163186830200265892525403238639070366999401808068998639590975305617369688731214141047568939908240058088089504343104889824160334560324387496383256518400827927341943755279126157377196722373876343583757261084975726106468397487366825775319965557539853162973895788663508023419482720093445137085452233528426725965549266605359644884153719762909553953900709890192728260024241748671796401590112629479273363064208874240854298225057415248756216847693518038319188675206377870041466557414694779134628404260587970 -------------------------------------------------------------------------------- /2018/Codegate-CTF-Preliminary/RSAbaby/exploit.py: -------------------------------------------------------------------------------- 1 | from Crypto.Util.number import * 2 | g = 14511485561279877242490049924164262671564856980418706493772866848857612385453104346586350276227873984815502106112389832011566814347565705873657427101510533972939335373118027470906354834216983842099812965592939768854241417529908124711818216182341332507918374220901579987851767888710421089266081280013256600425746557269742268670300714949183260246617797156425767983027415373581836147225552931559016487193903056680274018867169067069164417868649729813464306199388375773268972224468436723728788928618254041886532217172217283880677562744928063668302190530092708676086756514664006766909499651097644447881334032649057611965077951245778537347658519214651268439995915614667939336569800565797702566887133370244643122543689011224353239395653153094885449557256699923700742653930928887024447374907536229536501931493386170594869542262576409686250950887746501725676758035668270309685358291271363775138099327895323451901829587908987436831617628346535627562925010698445652286450107659802164994355539623617745529876829000553355956755914526849056343372137493951531663650121127924626353148067965144997177441402726593083629261964699315644045714647617156724816370270635144953182744245498998992807987174252376199074131496163299914588620694929584594866873400406185502626180264465104468365933575409921644759774899908018217623256295871823903858740112075223018089096313796599554636163186830200265892525403238639070366999401808068998639590975305617369688731214141047568939908240058088089504343104889824160334560324387496383256518400827927341943755279126157377196722373876343583757261084975726106468397487366825775319965557539853162973895788663508023419482720093445137085452233528426725965549266605359644884153719762909553953900709890192728260024241748671796401590112629479273363064208874240854298225057415248756216847693518038319188675206377870041466557414694779134628404260587970 3 | N = 523639805914061918270627443134741619704989339108811345591765650823383811679404400743730300288077320843234806116907796484315512386749183735427076044515394957782722144465236043561036957495670530886847413432636828661793513741180618385135095922719611444315861194066682307139969523206842728092440966461922557111209480112023032164065707216752568624317883094770784553451376502893748762652573604180632157059219119741129827017117558208565054860250853978397405747507844727903363351081745897472675235414693294079400158465019978970101063161094836772073302365997371679643083941089269169502839517043186914783290465318781726781533226599462066259256698885200843104424722505593942510854302401488139137362276492532699951880474157691347473741517183512613811731637427562990396497067805682564174185792379491573312640862381843195615293946630128509982267460922475624107750277459002662884836031305873522960659017891138316482378312004790485681371129328860344989214941450460756203906709954285455206483931555441550631622907560476932030275168094874500348941952385811045752980245084909805234648503736291123092594689494187215718382724496356220857628352007757197464098872772987476828030721472777531411032286344430474215475330008833588291692767417022829531866323051 4 | Encrypted_Data = 380838525806255337893946743050327173947433371586247814759050430578204300094635270877953690129762202769875996939276197842147224857220372679703619497806927398399795108952962442891905146440202908075035070979097412854358636621348531277713225298087614167276769631514565642627640343771883615641654535423058064397195504442204533423747451626752470200734177912209703945585196661670059908372263823148356525332391696830864610833871912286943309315368473809329884078356658600058695228563250424729883958206468130236010169302227516477051342268478958591705205358855157076547042386496593253499052139707216013118968009859098636706611794339780312391554420587540660796607687910531233690474314728367495027785278881971814489961127141923005420385579115964806930701533734013794866357390109761177291603859980361697959155126598284421792362843501361967548503757576918138895493498276658301936707818035503138088925361983300854592909022681075014994189523262500924039153521343614460622246152945716505290603455309333333560506091410274263241508522602811994582040578653226240563907254131889033343189265841619698442130035569880428826546382882121430886993470180883869383405219173399698928360778092640513571913940390199302310817294277155376000921294944591121246587133744 5 | e = 65537 6 | 7 | # Using Euler's Theorem and Fermat's Little Theorem we have 8 | t1 = pow(2, e*g, N) 9 | t2 = pow(2, 0xdeadbeef, N) 10 | p = GCD((t1*t2)-2,N) 11 | 12 | assert N % p == 0 13 | q = N / p 14 | phin = (p-1)*(q-1) 15 | d = inverse(e, phin) 16 | m = pow(Encrypted_Data, d, N) 17 | print long_to_bytes(m) 18 | -------------------------------------------------------------------------------- /2018/HITB-XCTF-CTF-Quals/Easy_pub/easy_pub.py: -------------------------------------------------------------------------------- 1 | from Crypto.PublicKey import RSA, ElGamal 2 | from Crypto.Util.number import bytes_to_long, long_to_bytes, GCD, inverse, size 3 | from Crypto import Random 4 | from hashlib import sha256 5 | from time import time 6 | from random import randint, seed 7 | from signal import alarm 8 | from os import urandom 9 | 10 | 11 | class cipher(object): 12 | def __init__(self): 13 | self.rsa = RSA.generate(1024) 14 | self.elgamal = ElGamal.generate(128, Random.new().read) 15 | 16 | def encrypt(self, msg): 17 | return self.rsa.encrypt(msg, None)[0] 18 | 19 | def decrypt(self, sec): 20 | return self.rsa.decrypt(sec) 21 | 22 | def sign(self, msg): 23 | msg = long_to_bytes(msg) 24 | h = sha256(msg).digest() 25 | 26 | seed(time()) 27 | k = randint(1, self.elgamal.p - 1) 28 | while GCD(k, self.elgamal.p - 1) != 1: 29 | k = randint(1, self.elgamal.p - 1) 30 | 31 | return self.elgamal.sign(h, k) 32 | 33 | def verify(self, msg, sig): 34 | msg = long_to_bytes(msg) 35 | h = sha256(msg).digest() 36 | return self.elgamal.verify(h, sig) 37 | 38 | 39 | def main(): 40 | with open('admin.key', 'r') as f: 41 | admin_k = f.readline() 42 | cry = cipher() 43 | print('welcome to Fantasy Terram') 44 | print(cry.rsa.e) 45 | print(cry.rsa.n) 46 | print(cry.elgamal.p) 47 | print(cry.elgamal.g) 48 | print(cry.elgamal.y) 49 | 50 | alarm(200) 51 | while True: 52 | choice = input("Please [r]egister or [l]ogin :>>") 53 | 54 | if not choice: 55 | break 56 | if choice[0] == 'r': 57 | r = randint(1, 3) 58 | # if r in(2, 3): 59 | # print('Sorry, you cannot register now. Good luck.') 60 | # exit() 61 | name = input('please input your username:>>') 62 | name = bytes(name, 'ISO-8859-1') 63 | if name == b'admin': 64 | tmp = input("please impurt admin's key:>>") 65 | if tmp != admin_k: 66 | print('Liar! Get out of here!') 67 | exit() 68 | else: 69 | print('Welcom admin!') 70 | with open('flag', 'r') as f: 71 | print(f.readline()) 72 | exit() 73 | msg = name + b'\x00' + bytes(admin_k, 'ISO-8859-1') 74 | if size(bytes_to_long(msg)) > 700: 75 | print('Too long username') 76 | continue 77 | msg = msg + urandom(120 - len(msg)) 78 | msg = bytes_to_long(msg) 79 | if msg % 2 == 1: 80 | msg += 1 81 | sig = cry.sign(msg) 82 | ticket = cry.encrypt(msg) 83 | print(ticket) 84 | print(sig[0]) 85 | print(sig[1]) 86 | 87 | elif choice[0] == 'l': 88 | ticket = int(input('ticket:>>')) 89 | sig0 = int(input('sig[0]')) 90 | sig1 = int(input('sig[1]')) 91 | msg = cry.decrypt(ticket) 92 | if msg % 2 == 1: 93 | print('A bit is wrong, may be something is wrong.') 94 | continue 95 | if cry.verify(msg, (sig0, sig1)) == cry.verify(msg, (sig1, sig0)): 96 | print('Wrong signature!') 97 | msg = long_to_bytes(msg) 98 | name = msg.split(b'\x00')[0] 99 | print('Welcome!{}'.format(name)) 100 | else: 101 | break 102 | 103 | 104 | if __name__ == '__main__': 105 | main() 106 | -------------------------------------------------------------------------------- /2018/HITCON-CTF/Lost-Key/exploit.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | from Crypto.Util.number import * 3 | from Crypto.PublicKey import * 4 | import math 5 | 6 | def encrypt(m): 7 | m=long_to_bytes(m) 8 | r.recvuntil("cmd: ") 9 | r.sendline("A") 10 | r.recvuntil("input: ") 11 | r.sendline(m.encode("hex")) 12 | return int(r.recvline().strip(),16) 13 | 14 | def decrypt(m): 15 | m=long_to_bytes(m) 16 | r.recvuntil("cmd: ") 17 | r.sendline("B") 18 | r.recvuntil("input: ") 19 | r.sendline(m.encode("hex")) 20 | return int(r.recvline().strip(),16) 21 | 22 | r = remote("18.179.251.168", "21700") 23 | r.recvline().strip() 24 | flag_enc = bytes_to_long(r.recvline().strip().decode("hex")) 25 | 26 | # Finding the modulus 27 | c1 = encrypt(2) 28 | c2 = encrypt(3) 29 | c3 = encrypt(5) 30 | c4 = encrypt(2**2) 31 | c5 = encrypt(3**2) 32 | c6 = encrypt(5**2) 33 | N = GCD(GCD(c1**2 - c4, c2**2 - c5), c3**2 - c6) 34 | print "Modulus: ", N 35 | 36 | for j in range(2, 1000000): 37 | assert N % j != 0 38 | 39 | # LS Byte Oracle Attack 40 | flag = "\n" 41 | for i in range(1,60): 42 | inv = inverse(256**i, N) 43 | _multiplier = encrypt(inv) 44 | chosen_ct = flag_enc*_multiplier 45 | output = decrypt(chosen_ct) 46 | flag_char = (output - (bytes_to_long(flag)*inv) % N) % 256 47 | flag = chr(flag_char) + flag 48 | print flag 49 | -------------------------------------------------------------------------------- /2018/HackIT-CTF/Into-the-Darkness/README.md: -------------------------------------------------------------------------------- 1 | # Into The Darkness 2 | 3 | Detailed explanation coming soon I hope :P 4 | 5 | Exploit script for this challenge: [exploit.py](exploit.py) 6 | 7 | If you want to know CBC Bit Flipping attack, read about it here: https://masterpessimistaa.wordpress.com/2017/05/03/cbc-bit-flipping-attack/ 8 | 9 | Similar Challenges: 10 | 1. CTFZone CTF Quals 2018: [USSH-3.0](https://masterpessimistaa.wordpress.com/2018/07/23/exploiting-cookie-auth-mechanism-ctfzone-ussh-3-0-write-up/) 11 | 2. ACEBEAR CTF 2018: [CNVService](https://masterpessimistaa.wordpress.com/2018/01/31/cnvservice-acebear-ctf-2018-writeup/) 12 | 13 | 14 | tl;dr chained CBC Bit Flipping Attack -------------------------------------------------------------------------------- /2018/HackIT-CTF/Into-the-Darkness/data.txt: -------------------------------------------------------------------------------- 1 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 2 | Sending cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713aeb2102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 3 |

Session 7b22757365726e616d65223a226775657374222c22697341646d696e223a6661f8db609eb9c85573eaaa0c13121e69d2b5d31602ecb3a46d3ae023b9118283ff1b22757365726e616d65223a226775657374222c22697341646d696e223a66616c73657d is not valid!

4 | 5 | 6 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 7 | Sending cookie: b202b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 8 |

Session 8822757365726e616d65223a226775657374222c22697341646d696e223a66616c73657d is not valid!

9 | 10 | 11 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 12 | Sending cookie: 4b22b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 13 |

Session 7102757365726e616d65223a226775657374222c22697341646d696e223a66616c73657d is not valid!

14 | 15 | 16 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 17 | Sending cookie: 41b2b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 18 |

Session 7b92757365726e616d65223a226775657374222c22697341646d696e223a66616c73657d is not valid!

19 | 20 | 21 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 22 | Sending cookie: 410b295305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 23 |

Session 7b2be57365726e616d65223a226775657374222c22697341646d696e223a66616c73657d is not valid!

24 | 25 | 26 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 27 | Sending cookie: 4102b25305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 28 | Into Darkness

Into Darkness

Welcome to Into Darkness

You are not admin

Username:

29 | 30 | 31 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 32 | Sending cookie: 4102bb2305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 33 |

Session 7b22770365726e616d65223a226775657374222c22697341646d696e223a66616c73657d is not valid!

34 | 35 | 36 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 37 | Sending cookie: 4102b9b205ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 38 | Into Darkness

Into Darkness

Welcome to Into Darkness

You are not admin

Username:

39 | 40 | 41 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 42 | Sending cookie: 4102b95b25ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 43 | Into Darkness

Into Darkness

Welcome to Into Darkness

You are not admin

Username:

44 | 45 | 46 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 47 | Sending cookie: 4102b953b2ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 48 | Into Darkness

Into Darkness

Welcome to Into Darkness

You are not admin

Username:

49 | 50 | 51 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 52 | Sending cookie: 4102b9530b2f8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 53 | Into Darkness

Into Darkness

Welcome to Into Darkness

You are not admin

Username:

54 | 55 | 56 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 57 | Sending cookie: 4102b95305b28c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 58 | Into Darkness

Into Darkness

Welcome to Into Darkness

You are not admin

Username:

59 | 60 | 61 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 62 | Sending cookie: 4102b95305fb2c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 63 | Into Darkness

Into Darkness

Welcome to Into Darkness

You are not admin

Username:

64 | 65 | 66 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 67 | Sending cookie: 4102b95305ffb26edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 68 | Into Darkness

Into Darkness

Welcome to Into Darkness

You are not admin

Username:

69 | 70 | 71 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 72 | Sending cookie: 4102b95305ff8b2edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 73 | Into Darkness

Into Darkness

Welcome to Into Darkness

You are not admin

Username:

74 | 75 | 76 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 77 | Sending cookie: 4102b95305ff8cb2dd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 78 | Into Darkness

Into Darkness

Welcome to Into Darkness

You are not admin

Username:

79 | 80 | 81 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 82 | Sending cookie: 4102b95305ff8c6b2d61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 83 | Into Darkness

Into Darkness

Welcome to Into Darkness

You are not admin

Username:

84 | 85 | 86 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 87 | Sending cookie: 4102b95305ff8c6eb261110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 88 |

Session 7b22757365726e610265223a226775657374222c22697341646d696e223a66616c73657d is not valid!

89 | 90 | 91 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 92 | Sending cookie: 4102b95305ff8c6edb21110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 93 | Into Darkness

Into Darkness

Welcome to Into Darkness

You are not admin

Username:

94 | 95 | 96 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 97 | Sending cookie: 4102b95305ff8c6eddb2110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 98 | Into Darkness

Into Darkness

Welcome to Into Darkness

You are not admin

Username:

99 | 100 | 101 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 102 | Sending cookie: 4102b95305ff8c6edd6b210c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 103 |

Session 7b22757365726e616d6f123a226775657374222c22697341646d696e223a66616c73657d is not valid!

104 | 105 | 106 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 107 | Sending cookie: 4102b95305ff8c6edd61b20c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 108 |

Session 7b22757365726e616d65813a226775657374222c22697341646d696e223a66616c73657d is not valid!

109 | 110 | 111 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 112 | Sending cookie: 4102b95305ff8c6edd611b2c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 113 |

Session 7b22757365726e616d65281a226775657374222c22697341646d696e223a66616c73657d is not valid!

114 | 115 | 116 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 117 | Sending cookie: 4102b95305ff8c6edd6111b21467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 118 |

Session 7b22757365726e616d652284226775657374222c22697341646d696e223a66616c73657d is not valid!

119 | 120 | 121 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 122 | Sending cookie: 4102b95305ff8c6edd61110b2467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 123 |

Session 7b22757365726e616d65223d126775657374222c22697341646d696e223a66616c73657d is not valid!

124 | 125 | 126 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 127 | Sending cookie: 4102b95305ff8c6edd61110cb267f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 128 |

Session 7b22757365726e616d65223a846775657374222c22697341646d696e223a66616c73657d is not valid!

129 | 130 | 131 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 132 | Sending cookie: 4102b95305ff8c6edd61110c1b27f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 133 |

Session 7b22757365726e616d65223a2d2775657374222c22697341646d696e223a66616c73657d is not valid!

134 | 135 | 136 | Default cookie: 4102b95305ff8c6edd61110c1467f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 137 | Sending cookie: 4102b95305ff8c6edd61110c14b2f63deb0f221f9539783e4685773c1f7488c985d5a21a4768bf9ee90b7a69f460ac032a53f80d79700dc0bdb25e27db713ae2 138 | -------------------------------------------------------------------------------- /2018/HackIT-CTF/Into-the-Darkness/exploit.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | hexchars = "0123456789abcdef" 4 | 5 | def xor(s1, s2): 6 | res = [chr(ord(i) ^ ord(j)) for i, j in zip(s1, s2)] 7 | return "".join(res) 8 | 9 | def get_cookie(request_obj): 10 | cookie_list = [] 11 | for cookie in request_obj.cookies: 12 | cookie_list.append(cookie.value) 13 | return cookie_list 14 | 15 | def test_cookie(cookie_val): 16 | f = open("data.txt","w") 17 | _len = len(cookie_val.decode("hex")) 18 | def_flip = "b2" 19 | for i in range(_len): 20 | send_cookie_val = cookie_val[0:i-1] + def_flip + cookie_val[i+1:] 21 | f.write("Default cookie: " + cookie_val + "\n") 22 | f.write("Sending cookie: " + send_cookie_val + "\n") 23 | print "i: ", i 24 | print "Default cookie: " + cookie_val 25 | print "Sending cookie: " + send_cookie_val 26 | temp = send_cookie(send_cookie_val) 27 | print temp 28 | f.write(temp + "\n") 29 | f.write("\n\n") 30 | print "\n" 31 | 32 | 33 | def send_cookie(cookie_val): 34 | for i in cookie_val: 35 | assert i in hexchars 36 | session_cookie = {"session": cookie_val} 37 | re = requests.get("http://185.168.131.153/", cookies=session_cookie) 38 | return re.text 39 | 40 | def chunks(inputstr, blocksize): 41 | list1 = [] 42 | for i in range(0, len(inputstr), blocksize): 43 | list1.append(inputstr[i:i+blocksize]) 44 | return list1 45 | 46 | 47 | re = requests.get("http://185.168.131.153/") 48 | cookie_val = get_cookie(re)[0] 49 | print "Request cookie values: ", cookie_val 50 | print "Length of cookie in hex decoded form: ", len(cookie_val.decode("hex")) 51 | print "Text for request: ", send_cookie(cookie_val) 52 | 53 | print "\n" 54 | 55 | def process(string1, p1, p2): 56 | return xor(xor(string1.decode("hex"), p1), p2).encode("hex") 57 | 58 | send_corrupt_cookie = cookie_val[0:32] + cookie_val[32:64] + process(cookie_val[64:96], "lse}\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c","ue}\r\r\r\r\r\r\r\r\r\r\r\r\r") + cookie_val[96:] 59 | recv_str = send_cookie(send_corrupt_cookie) 60 | recv_str = recv_str[120:-42].decode("hex") 61 | flip1 = recv_str[16:32] 62 | 63 | print "\n" 64 | 65 | send_corrupt_cookie = cookie_val[0:32] + process(cookie_val[32:64], flip1, 'in","isAdmin":tr') + process(cookie_val[64:96], "lse}\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c","ue}\r\r\r\r\r\r\r\r\r\r\r\r\r") + cookie_val[96:] 66 | recv_str = send_cookie(send_corrupt_cookie) 67 | recv_str = recv_str[120:-42].decode("hex") 68 | flip2 = recv_str[:16] 69 | 70 | send_corrupt_cookie = process(cookie_val[0:32], flip2, '{"username":"adm') + process(cookie_val[32:64], flip1, 'in","isAdmin":tr') + process(cookie_val[64:96], "lse}\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c","ue}\r\r\r\r\r\r\r\r\r\r\r\r\r") + cookie_val[96:] 71 | print send_cookie(send_corrupt_cookie) 72 | -------------------------------------------------------------------------------- /2018/Insomni'Hack-Teaser/Rule86/README.md: -------------------------------------------------------------------------------- 1 | # Rule86 2 | 3 | **Points**: 78 4 | 5 | **Description**: Kevin is working on a new synchronous stream cipher, but he has been re-using his key. 6 | 7 | Check out my writeup for this challenge [here](https://masterpessimistaa.wordpress.com/2018/01/23/rule86-insomnihack-teaser-2018-writeup/) 8 | Other write-ups using z3 to solve the challenge: [https://ctftime.org/writeup/8563](https://ctftime.org/writeup/8563) -------------------------------------------------------------------------------- /2018/Insomni'Hack-Teaser/Rule86/bootstrap_prng.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Bootstrapping PRNG 4 | RULE = [86 >> i & 1 for i in range(8)] 5 | N_BYTES = 32 6 | N = 8 * N_BYTES 7 | 8 | def next(x): 9 | x = (x & 1) << N+1 | x << 1 | x >> N-1 10 | y = 0 11 | for i in range(N): 12 | y |= RULE[(x >> i) & 7] << i 13 | return y 14 | 15 | # Bootstrap the PNRG 16 | keystream = 84607154736791766065800361525374060783583128122748167105652288627872379068488 17 | for i in range(N//2): 18 | keystream = next(keystream) 19 | print (keystream) 20 | -------------------------------------------------------------------------------- /2018/Insomni'Hack-Teaser/Rule86/exploit.py: -------------------------------------------------------------------------------- 1 | from Crypto.Util.number import * 2 | 3 | revrule = {'0':[], '1':[]} 4 | RULE = [86 >> i & 1 for i in range(8)] 5 | N_BYTES = 32 6 | N = 8 * N_BYTES 7 | 8 | for bit in [0,1]: 9 | for i in range(len(RULE)): 10 | if RULE[i]==bit: 11 | revrule[str(bit)].append(bin(i)[2:].zfill(3)[::-1]) 12 | 13 | def next(x): 14 | x = (x & 1) << N+1 | x << 1 | x >> N-1 15 | y = 0 16 | for i in range(N): 17 | y |= RULE[(x >> i) & 7] << i 18 | return y 19 | 20 | def xor(s1, s2): 21 | res = "".join(map(lambda x: chr(ord(x[0]) ^ ord(x[1])), zip(s1, s2))) 22 | return res 23 | 24 | def str_to_int(str1): 25 | return int(str1[::-1].encode("hex"), 16) 26 | 27 | def int_to_str(num): 28 | return hex(num)[2:].replace("L","").zfill(64).decode("hex")[::-1] 29 | 30 | def invnext2(y): 31 | bin_str = bin(y)[2:].zfill(N)[::-1] 32 | valid = [''] 33 | for i in range(0, len(bin_str)): 34 | bit = bin_str[i] 35 | newvalid = [] 36 | for v in valid: 37 | for subset in revrule[bit]: 38 | if i == 0: 39 | newvalid.append(subset) 40 | elif i != 0 and v[-2:] == subset[:2]: 41 | newvalid.append(v[:-2] + subset) 42 | valid = newvalid 43 | for v in valid: 44 | if v[:2] == v[-2:]: 45 | b1 = int(v[::-1], 2) 46 | return b1 47 | 48 | ct = open("hint.gif.enc", "rb").read() 49 | ct1 = open("rule86.txt","r").read() 50 | ct2 = open("rule86.txt.enc","rb").read() 51 | ct3 = open("super_cipher.py.enc","rb").read() 52 | ct4 = open("test.gif","wb") 53 | 54 | keystream = xor(ct1, ct2) 55 | print xor(keystream, ct3) 56 | sub_keystream = keystream[:32] 57 | sub_keystream = str_to_int(sub_keystream) 58 | 59 | for i in range(0, len(ct), 32): 60 | ct4.write(xor(ct[i:i+32], int_to_str(sub_keystream))) 61 | sub_keystream = next(sub_keystream) 62 | 63 | y = str_to_int(keystream[:32]) 64 | for c in range(N//2): 65 | step = invnext2(y) 66 | x = (step >> 1) & 2**256-1 67 | y = x 68 | print int_to_str(y) 69 | -------------------------------------------------------------------------------- /2018/Insomni'Hack-Teaser/Rule86/hint.gif.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/Insomni'Hack-Teaser/Rule86/hint.gif.enc -------------------------------------------------------------------------------- /2018/Insomni'Hack-Teaser/Rule86/rule86.txt: -------------------------------------------------------------------------------- 1 | What is Rule 86? 2 | 3 | Rule 86 DOES NOT state that: 4 | - any and all buttons, valves, switches, latches, or anything else may be pushed or turned more than once until one is certain that all buttons, valves, switches, latches, etc, has been pushed at least once each 5 | - every time someone speaks your name, it creates a duplicate of you 6 | - if one divides 86 by the sugar content of sap, you can estimate the amount of sap required to produce a gallon of syrup 7 | - sharing a kiss is forbidden 8 | 9 | Rule 86 is... something else. 10 | -------------------------------------------------------------------------------- /2018/Insomni'Hack-Teaser/Rule86/rule86.txt.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/Insomni'Hack-Teaser/Rule86/rule86.txt.enc -------------------------------------------------------------------------------- /2018/Insomni'Hack-Teaser/Rule86/super_cipher.py.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/Insomni'Hack-Teaser/Rule86/super_cipher.py.enc -------------------------------------------------------------------------------- /2018/Insomni'Hack-Teaser/Rule86/test.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/Insomni'Hack-Teaser/Rule86/test.gif -------------------------------------------------------------------------------- /2018/Meepwn-CTF-Quals/bazik/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/Meepwn-CTF-Quals/bazik/1.png -------------------------------------------------------------------------------- /2018/Meepwn-CTF-Quals/bazik/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/Meepwn-CTF-Quals/bazik/2.png -------------------------------------------------------------------------------- /2018/Meepwn-CTF-Quals/bazik/exploit.sage: -------------------------------------------------------------------------------- 1 | def stereotype(known, e, n, c): 2 | P. = PolynomialRing(Zmod(n)) 3 | f = (known + x)^e - c 4 | f = f.monic() 5 | m = f.small_roots() 6 | print m 7 | 8 | c = 42160160680171369239369476150445713714693174609727550335830976621039454448288920460900938895349082293064658763297124640451443874804179131996606124156364291422217754764739446818518768094097523386418754071448828700038973608038959934937085120721652892003721400394916476714812474802422779736863491901594508394894 9 | n = 123326733596960514263758597679057384418140701948552533698368022009587519622612706225552831546580947594744544352369336530068144502340902309556467425257067113077066735008735316017343608206941169106313094857750548581267098327593102380031600017725686830608349665217539239928428017208096317433402177217674046444813 10 | e = 3 11 | known = 279194786064165631462403655571007005294665174222443770940031343055849950569774655464736942913588929603436045601725648607914471752112311886315257902L 12 | stereotype(known, e, n, c) -------------------------------------------------------------------------------- /2018/Meepwn-CTF-Quals/bazik/publickey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCvn4NdkKI/ptM/N+aixwf3MKEx 3 | ww2rv15dn2RYdkZ+pPmXkQ25gW+0utqQPm8n8rQthV8Oze4Di2c+isry8ZNTaTNz 4 | QzzYJkHVniXYXy+9wY1IZoir/eOIjIHWJ/Q3FhIAGM3sAlFkIFeH6LhWedz5nup4 5 | aEY//9brqtoo4h2VDQIBAw== 6 | -----END PUBLIC KEY----- -------------------------------------------------------------------------------- /2018/Meepwn-CTF-Quals/bazik/readpublickeypara.py: -------------------------------------------------------------------------------- 1 | from Crypto.PublicKey import * 2 | 3 | key = RSA.importKey(open("publickey.pem").read()) 4 | print "Modulus: ", key.n 5 | print "Public Key exponent: ", key.e -------------------------------------------------------------------------------- /2018/Midnight-CTF-Quals/hm4c/Pictures/Picture1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/Midnight-CTF-Quals/hm4c/Pictures/Picture1.png -------------------------------------------------------------------------------- /2018/Midnight-CTF-Quals/hm4c/README.md: -------------------------------------------------------------------------------- 1 | # Hm4c 2 | 3 | **Challenge Points**: 50 4 | 5 | **Challenge Description**: Some n00b implemented a HMAC, I'm sure you can pwn it 6 | 7 | We are given [hm4c.py](hm4c.py) running on `crypto.midnightsunctf.se` and port number `31337`. The script basically generates a custom HMAC of `FLAG` + (`input` that we give to it). This is how the HMAC is generated: 8 | ![Picture1](Pictures/Picture1.png) 9 | As we can see, the server returns the SHA256 hash of `(FLAG ^ input) + input`. This is what makes this challenge vulnerable to Bit by Bit Decryption, let us see how: 10 | 1. To get the SHA256 of FLAG we just send base64 encoded string of `\x00` as the output will be SHA256((FLAG ^ 0) + 0) = SHA256(FLAG) 11 | 2. Starting from LSB, we analyse the value returned by the function when the last bit of our input is **1** 12 | - If the last bit of FLAG is 1 then the last bit of `(FLAG ^ input) + input` will be `(1 ^ 1) + 1 = 0 + 1 = 1` which is the same as the last bit of the FLAG and hence the HMAC won't change. 13 | - If the last bit of FLAG is not 1, then the last bit of `(FLAG ^ input) + input` will be `(0 ^ 1) + 1 = 10`; although the last bit is same here again, but notice that one bit of just before the last bit has changed and hence the HMAC will change. 14 | 3. Now, we can use the same concept to get every bit of FLAG as follows: 15 | - Send 1, 2, 4, 8, ..., 2**`i` as an input and check if the the output for each input matches with the SHA256 of FLAG obtained in Step-1. 16 | - If it matches, then the `i`th bit of FLAG is 1, otherwise it is 0 17 | 18 | 19 | 20 | I wrote the following python implementation of the exploit: 21 | ```python 22 | flag = "" 23 | r = process("./hm4c.sh") 24 | r.recvline().replace("\n","") 25 | for i in range(256): 26 | r.recvline().replace("\n","") 27 | r.recvline().replace("\n","") 28 | r.recvline().replace("\n","") 29 | r.sendline("1") 30 | r.recvline().replace("\n","") 31 | 32 | r.sendline(int_to_base64(1< n 132 | 133 | ### The vulnerability 134 | Allowing user controlled padding exposes the challenge to the attack described below 135 | 136 | ### The exploit 137 | Note that the server appends sha256 of the input to the message before encryption. 138 | 139 | First, we send ‘2’ as an input to the server and get the ciphertext: 140 | ```python 141 | c1 = 14550589053226237723784378782911157204367764723816957959635387925652898370034365455451983914571405062459535687617841302966938233065296973978472553109061974458935966754832788411876301179210585984208608247433383774246743661884093657109502619626436726032508763685599880808525861655167503719155953736308920858354069083437923495143680174206534169208623366776314544036377265501358254923029291010047210371394197963442022610746743020719292018028518885149189744832788117626194748311114409968846879212425054195323473068436359069318372735069308398135560733890706617536127579272964863500568572120716434126233695562326533941909353 142 | ``` 143 | The following computation happens when we send the input as ‘2’: 144 | 1. hash1 = int(sha256('2').hexdigest(), 16) 145 | 2. c1 = pow(m + hash1, e, n) 146 | 147 | 148 | 149 | Next, send '1' as an input to the server and get the ciphertext: 150 | ```python 151 | c2 = 14550589053226237723784378782911157204367764723813789158271625147472004207734354619642445255036997940341703539883653916130592718879734436263217819317202435434496341973502556894834798718992952369685841347018901038478081710519253844078907000973324354805502890255414196801758171762906898874914776720897920729518384393581853690034053515213192846817920534901501370942556249012415259244063185938984570137371682805276444650716010228924732495062415330875872004691866847132147232457398743319930259327973290858489741376000333603734294893832124907092640953321640151851853501528390729805151850605432707293088635480863375398001441 152 | ``` 153 | The following computation happens when we send the input as ‘1’: 154 | 1. hash2 = int(sha256('1').hexdigest(), 16) 155 | 2. c2 = pow(m + hash2, e, n) 156 | 157 | 158 | 159 | Now that we have values of hash1(or h1), hash2(or h2), c1 and c2, we can use them to get m. Let us see how: 160 | ![picture](Pictures/1.gif) 161 | ![picture](Pictures/2.gif) 162 | ![picture](Pictures/3.gif) 163 | ![picture](Pictures/4.gif) 164 | ![picture](Pictures/5.gif) 165 | ![picture](Pictures/6.gif) 166 | ![picture](Pictures/7.gif) 167 | ![picture](Pictures/8.gif) 168 | where a = 3, b = 3*(h1 + h2), c = (h1^2 + h1*h2 + h2^2) – x 169 | 170 | I wrote the following code to implement the above calculation and get the flag: 171 | ```python 172 | import hashlib 173 | import gmpy2 174 | from Crypto.Util.number import * 175 | 176 | hash1 = int(hashlib.sha256('2').hexdigest(), 16) 177 | hash2 = int(hashlib.sha256('1').hexdigest(), 16) 178 | diff = hash1 - hash2 179 | print "diff: ", diff 180 | 181 | # M1 = M2 + diff 182 | n = 21727106551797231400330796721401157037131178503238742210927927256416073956351568958100038047053002307191569558524956627892618119799679572039939819410371609015002302388267502253326720505214690802942662248282638776986759094777991439524946955458393011802700815763494042802326575866088840712980094975335414387283865492939790773300256234946983831571957038601270911425008907130353723909371646714722730577923843205527739734035515152341673364211058969041089741946974118237091455770042750971424415176552479618605177552145594339271192853653120859740022742221562438237923294609436512995857399568803043924319953346241964071252941L 183 | e = 3 184 | 185 | c1 = 14550589053226237723784378782911157204367764723816957959635387925652898370034365455451983914571405062459535687617841302966938233065296973978472553109061974458935966754832788411876301179210585984208608247433383774246743661884093657109502619626436726032508763685599880808525861655167503719155953736308920858354069083437923495143680174206534169208623366776314544036377265501358254923029291010047210371394197963442022610746743020719292018028518885149189744832788117626194748311114409968846879212425054195323473068436359069318372735069308398135560733890706617536127579272964863500568572120716434126233695562326533941909353 186 | c2 = 14550589053226237723784378782911157204367764723813789158271625147472004207734354619642445255036997940341703539883653916130592718879734436263217819317202435434496341973502556894834798718992952369685841347018901038478081710519253844078907000973324354805502890255414196801758171762906898874914776720897920729518384393581853690034053515213192846817920534901501370942556249012415259244063185938984570137371682805276444650716010228924732495062415330875872004691866847132147232457398743319930259327973290858489741376000333603734294893832124907092640953321640151851853501528390729805151850605432707293088635480863375398001441 187 | assert c2 < n 188 | assert c1 < n 189 | assert c1 > c2 190 | res = (c1 - c2) / (hash1 - hash2) 191 | 192 | a = 3 193 | b = 3*(hash1 + hash2) 194 | c = (hash1**2 + hash1*hash2 + hash2**2) - res 195 | assert b**2 - 4*a*c >= 0 196 | 197 | det = gmpy2.iroot(b**2 - 4*a*c, 2) 198 | #Result of the above operation 199 | det = 895117860555194221639962847152553327251877885494596369020458400464169641215830527612022789636620223733091925404109820014339798528983673228478908782900199621057014409705139235003835944181120537080102658020544028036693589036615231884111568905196654L 200 | sol1 = (det - b)/(2*a) 201 | print long_to_bytes(sol1) 202 | ``` 203 | Running the above exploit script gives us: Welcom to Nu1L CTF, Congratulations, You get flag, and flag is **N1CTF{f7efbf4e5f5ef78ca1fb9c8f5eb02635}**. Check out the entire exploit [here](exploit.py) 204 | 205 | 206 | -------------------------------------------------------------------------------- /2018/N1CTF/RSA_Padding/exploit.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | import gmpy2 3 | from Crypto.Util.number import * 4 | 5 | hash1 = int(hashlib.sha256('2').hexdigest(), 16) 6 | hash2 = int(hashlib.sha256('1').hexdigest(), 16) 7 | diff = hash1 - hash2 8 | print "diff: ", diff 9 | 10 | # M1 = M2 + diff 11 | n = 21727106551797231400330796721401157037131178503238742210927927256416073956351568958100038047053002307191569558524956627892618119799679572039939819410371609015002302388267502253326720505214690802942662248282638776986759094777991439524946955458393011802700815763494042802326575866088840712980094975335414387283865492939790773300256234946983831571957038601270911425008907130353723909371646714722730577923843205527739734035515152341673364211058969041089741946974118237091455770042750971424415176552479618605177552145594339271192853653120859740022742221562438237923294609436512995857399568803043924319953346241964071252941L 12 | e = 3 13 | 14 | c1 = 14550589053226237723784378782911157204367764723816957959635387925652898370034365455451983914571405062459535687617841302966938233065296973978472553109061974458935966754832788411876301179210585984208608247433383774246743661884093657109502619626436726032508763685599880808525861655167503719155953736308920858354069083437923495143680174206534169208623366776314544036377265501358254923029291010047210371394197963442022610746743020719292018028518885149189744832788117626194748311114409968846879212425054195323473068436359069318372735069308398135560733890706617536127579272964863500568572120716434126233695562326533941909353 15 | c2 = 14550589053226237723784378782911157204367764723813789158271625147472004207734354619642445255036997940341703539883653916130592718879734436263217819317202435434496341973502556894834798718992952369685841347018901038478081710519253844078907000973324354805502890255414196801758171762906898874914776720897920729518384393581853690034053515213192846817920534901501370942556249012415259244063185938984570137371682805276444650716010228924732495062415330875872004691866847132147232457398743319930259327973290858489741376000333603734294893832124907092640953321640151851853501528390729805151850605432707293088635480863375398001441 16 | assert c2 < n 17 | assert c1 < n 18 | assert c1 > c2 19 | res = (c1 - c2) / (hash1 - hash2) 20 | 21 | a = 3 22 | b = 3*(hash1 + hash2) 23 | c = (hash1**2 + hash1*hash2 + hash2**2) - res 24 | assert b**2 - 4*a*c >= 0 25 | 26 | det = gmpy2.iroot(b**2 - 4*a*c, 2) 27 | #Result of the above operation 28 | det = 895117860555194221639962847152553327251877885494596369020458400464169641215830527612022789636620223733091925404109820014339798528983673228478908782900199621057014409705139235003835944181120537080102658020544028036693589036615231884111568905196654L 29 | sol1 = (det - b)/(2*a) 30 | print long_to_bytes(sol1) -------------------------------------------------------------------------------- /2018/N1CTF/baby_N1ES/N1ES.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | def round_add(a, b): 3 | f = lambda x, y: x + y - 2 * (x & y) 4 | res = '' 5 | for i in range(len(a)): 6 | res += chr(f(ord(a[i]), ord(b[i]))) 7 | return res 8 | 9 | def permutate(table, block): 10 | return list(map(lambda x: block[x], table)) 11 | 12 | def string_to_bits(data): 13 | data = [ord(c) for c in data] 14 | l = len(data) * 8 15 | result = [0] * l 16 | pos = 0 17 | for ch in data: 18 | for i in range(0,8): 19 | result[(pos<<3)+i] = (ch>>i) & 1 20 | pos += 1 21 | return result 22 | 23 | s_box = [54, 132, 138, 83, 16, 73, 187, 84, 146, 30, 95, 21, 148, 63, 65, 189, 188, 151, 72, 161, 116, 63, 161, 91, 37, 24, 126, 107, 87, 30, 117, 185, 98, 90, 0, 42, 140, 70, 86, 0, 42, 150, 54, 22, 144, 153, 36, 90, 149, 54, 156, 8, 59, 40, 110, 56,1, 84, 103, 22, 65, 17, 190, 41, 99, 151, 119, 124, 68, 17, 166, 125, 95, 65, 105, 133, 49, 19, 138, 29, 110, 7, 81, 134, 70, 87, 180, 78, 175, 108, 26, 121, 74, 29, 68, 162, 142, 177, 143, 86, 129, 101, 117, 41, 57, 34, 177, 103, 61, 135, 191, 74, 69, 147, 90, 49, 135, 124, 106, 19, 89, 38, 21, 41, 17, 155, 83, 38, 159, 179, 19, 157, 68, 105, 151, 166, 171, 122, 179, 114, 52, 183, 89, 107, 113, 65, 161, 141, 18, 121, 95, 4, 95, 101, 81, 156, 17, 190, 38, 84, 9, 171, 180, 59, 45, 15, 34, 89, 75, 164, 190, 140, 6, 41, 188, 77, 165, 105, 5, 107, 31, 183, 107, 141, 66, 63, 10, 9, 125, 50, 2, 153, 156, 162, 186, 76, 158, 153, 117, 9, 77, 156, 11, 145, 12, 169, 52, 57, 161, 7, 158, 110, 191, 43, 82, 186, 49, 102, 166, 31, 41, 5, 189, 27] 24 | 25 | def generate(o): 26 | k = permutate(s_box,o) 27 | b = [] 28 | for i in range(0, len(k), 7): 29 | b.append(k[i:i+7] + [1]) 30 | c = [] 31 | for i in range(32): 32 | pos = 0 33 | x = 0 34 | for j in b[i]: 35 | x += (j<>i) & 1 14 | pos += 1 15 | return result 16 | 17 | def generate(o): 18 | k = permutate(s_box,o) 19 | b = [] 20 | for i in range(0, len(k), 7): 21 | b.append(k[i:i+7] + [1]) 22 | c = [] 23 | for i in range(32): 24 | pos = 0 25 | x = 0 26 | for j in b[i]: 27 | x += (j< inp_size_limit: 78 | continue 79 | dec_recv_str = aescipher.decrypt_wrapper(enc_strrecv_str) 80 | sys.stdout.write(b64encode(md5(dec_recv_str).digest())) 81 | sys.stdout.write("\n") 82 | sys.stdout.flush() -------------------------------------------------------------------------------- /2018/Tokyo-Westerns/Revolutional-Secure-Angou/Pictures/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/Tokyo-Westerns/Revolutional-Secure-Angou/Pictures/1.gif -------------------------------------------------------------------------------- /2018/Tokyo-Westerns/Revolutional-Secure-Angou/Pictures/2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/Tokyo-Westerns/Revolutional-Secure-Angou/Pictures/2.gif -------------------------------------------------------------------------------- /2018/Tokyo-Westerns/Revolutional-Secure-Angou/Pictures/3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/Tokyo-Westerns/Revolutional-Secure-Angou/Pictures/3.gif -------------------------------------------------------------------------------- /2018/Tokyo-Westerns/Revolutional-Secure-Angou/Pictures/4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/Tokyo-Westerns/Revolutional-Secure-Angou/Pictures/4.gif -------------------------------------------------------------------------------- /2018/Tokyo-Westerns/Revolutional-Secure-Angou/Pictures/5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/Tokyo-Westerns/Revolutional-Secure-Angou/Pictures/5.gif -------------------------------------------------------------------------------- /2018/Tokyo-Westerns/Revolutional-Secure-Angou/Pictures/6.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/Tokyo-Westerns/Revolutional-Secure-Angou/Pictures/6.gif -------------------------------------------------------------------------------- /2018/Tokyo-Westerns/Revolutional-Secure-Angou/README.md: -------------------------------------------------------------------------------- 1 | # Revolutionary Secure Angou 2 | 3 | **Challenge Points**: 4 | 5 | **Challenge Description**: [No Description] 6 | 7 | In this challenge, we are given an encryption script written in ruby that encrypts the flag using RSA. We are also given the [public key](publickey.pem) and [ciphertext](flag.encrypted). Let us analyse the encryption script first: 8 | 9 | ```ruby 10 | require 'openssl' 11 | 12 | e = 65537 13 | while true 14 | p = OpenSSL::BN.generate_prime(1024, false) 15 | q = OpenSSL::BN.new(e).mod_inverse(p) 16 | next unless q.prime? 17 | key = OpenSSL::PKey::RSA.new 18 | key.set_key(p.to_i * q.to_i, e, nil) 19 | File.write('publickey.pem', key.to_pem) 20 | File.binwrite('flag.encrypted', key.public_encrypt(File.binread('flag'))) 21 | break 22 | end 23 | ``` 24 | As you can see, private key parameters are not generated as they are supposed to be. Specifically, although `p` is a pseudo-random prime generated using OpenSSL, but `q` is generated as ![picture](Pictures/1.gif). Looks fishy! Also, there are no other suspicious lines of code as everything else looks fine. So now we know where we have to focus to find the exploit! 25 | 26 | We want to find someway to get the value of `p`, and we can use the equation for `q` to get this. Let us see how: 27 | ![picture](Pictures/2.gif) 28 | In the above equation, `k` is the multiplier. Now, if we multiply the above equation with `q` on both sides, we will have: 29 | ![picture](Pictures/3.gif) 30 | We know that n = p*q, hence the simplification above. 31 | 32 | Great, now we have a simple quadratic equation, to get the value of `q`, knowing the value of `e` and `n`. Although, we don't know the value of `k`, we can brute-force the value of `k`. To solve the above quadratic equation: 33 | ![picture](Pictures/4.gif) 34 | So as per the above formula, there are two possible values of `q`; but we can remove the negative sign since `q` is very large and cannot be less than one. This gives us: 35 | ![picture](Pictures/5.gif) 36 | 37 | To get the value of `q`, iterate check for every value of `k`, if ![picture](Pictures/6.gif) is a perfect square. If it does, then we have got the value of `q`! I implemented this using the following script: 38 | ```python 39 | for k in range(1, 1000000): 40 | # Checking for perfect equare 41 | if gmpy2.iroot(1+4*e*n*k, 2)[1] == True: 42 | # Calculating q 43 | q = (1 + int(gmpy2.iroot(1+4*e*n*k, 2)[0]))/(2*e) 44 | if n % q == 0: 45 | factor = q 46 | print k 47 | break 48 | ``` 49 | This gave me the value of `q` as: 117776309990537864360810812340917258096636219871129327152749744175094693075913995854147376703562090249517854407162616412941789644355136574651545193852293544566513866746012759544621873312628262933928953504305148673201262843795559879423287920215664535429854303448257904097546288383796049755601625835244054479553 50 | 51 | Now that we have `q`, we can calculate `p` and hence the private key to get the flag: 52 | ```python 53 | from Crypto.PublicKey import RSA 54 | from Crypto.Util.number import * 55 | import gmpy2 56 | 57 | key = RSA.importKey(open("publickey.pem").read()) 58 | n = key.n 59 | e = key.e 60 | print n 61 | print e 62 | 63 | for k in range(1, 1000000): 64 | if gmpy2.iroot(1+4*e*n*k, 2)[1] == True: 65 | q = (1 + int(gmpy2.iroot(1+4*e*n*k, 2)[0]))/(2*e) 66 | if n % q == 0: 67 | factor = q 68 | print k 69 | print "q: ", q 70 | break 71 | ct = open("flag.encrypted").read() 72 | ct = bytes_to_long(ct) 73 | p = n/factor 74 | phin = (p-1)*(q-1) 75 | d = inverse(e, phin) 76 | print long_to_bytes(pow(ct, d, n)) 77 | ``` 78 | 79 | Ran the above script and got the flag as: **TWCTF{9c10a83c122a9adfe6586f498655016d3267f195}** ! 80 | 81 | You can check out the exploit script here- [exploit.py](exploit.py) -------------------------------------------------------------------------------- /2018/Tokyo-Westerns/Revolutional-Secure-Angou/exploit.py: -------------------------------------------------------------------------------- 1 | from Crypto.PublicKey import RSA 2 | from Crypto.Util.number import * 3 | import gmpy2 4 | 5 | key = RSA.importKey(open("publickey.pem").read()) 6 | n = key.n 7 | e = key.e 8 | print n 9 | print e 10 | 11 | for k in range(1, 1000000): 12 | if gmpy2.iroot(1+4*e*n*k, 2)[1] == True: 13 | q = (1 + int(gmpy2.iroot(1+4*e*n*k, 2)[0]))/(2*e) 14 | if n % q == 0: 15 | factor = q 16 | print k 17 | print "q: ", q 18 | break 19 | ct = open("flag.encrypted").read() 20 | ct = bytes_to_long(ct) 21 | p = n/factor 22 | phin = (p-1)*(q-1) 23 | d = inverse(e, phin) 24 | print long_to_bytes(pow(ct, d, n)) 25 | -------------------------------------------------------------------------------- /2018/Tokyo-Westerns/Revolutional-Secure-Angou/flag.encrypted: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/Tokyo-Westerns/Revolutional-Secure-Angou/flag.encrypted -------------------------------------------------------------------------------- /2018/Tokyo-Westerns/Revolutional-Secure-Angou/generator.rb: -------------------------------------------------------------------------------- 1 | require 'openssl' 2 | 3 | e = 65537 4 | while true 5 | p = OpenSSL::BN.generate_prime(1024, false) 6 | q = OpenSSL::BN.new(e).mod_inverse(p) 7 | next unless q.prime? 8 | key = OpenSSL::PKey::RSA.new 9 | key.set_key(p.to_i * q.to_i, e, nil) 10 | File.write('publickey.pem', key.to_pem) 11 | File.binwrite('flag.encrypted', key.public_encrypt(File.binread('flag'))) 12 | break 13 | end -------------------------------------------------------------------------------- /2018/Tokyo-Westerns/Revolutional-Secure-Angou/publickey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhSkGPqCtO0Ypb5L3I1Z3 3 | LqTnA/e3kiDBjeG348oKdyjRnmncSLhoXNYE9Yh6T486lFocoVk88IbTSOxNySFC 4 | CD/J4iA8ZTAxHuUQvlCkKu5KY+f6Zr/ONRL8L7EXQCpVzfCJd3DBu4by2TBtpbiZ 5 | 0pTtvLF62H4XWSzMP2KxMFckGBcyrHR0zyO+tyKDM3PvB7apIYjPKLz+8msjaK2j 6 | j39P2JIdvjtkiOS5ICj/vUauJti0PJqG27xj8LUTmLtUCY/3AEtkavtC8kNUq2ot 7 | MO/u6LMzRzq+HMkutopGWBnZ6aD/WP6vLHIq5lt87cnjC+kVAp1pNCUjuYGtg5XN 8 | 9wIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /2018/VolgaCTF-Quals/Nonsense/Pictures/Picture1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/VolgaCTF-Quals/Nonsense/Pictures/Picture1.png -------------------------------------------------------------------------------- /2018/VolgaCTF-Quals/Nonsense/Pictures/Picture10.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/VolgaCTF-Quals/Nonsense/Pictures/Picture10.gif -------------------------------------------------------------------------------- /2018/VolgaCTF-Quals/Nonsense/Pictures/Picture11.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/VolgaCTF-Quals/Nonsense/Pictures/Picture11.gif -------------------------------------------------------------------------------- /2018/VolgaCTF-Quals/Nonsense/Pictures/Picture2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/VolgaCTF-Quals/Nonsense/Pictures/Picture2.png -------------------------------------------------------------------------------- /2018/VolgaCTF-Quals/Nonsense/Pictures/Picture3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/VolgaCTF-Quals/Nonsense/Pictures/Picture3.png -------------------------------------------------------------------------------- /2018/VolgaCTF-Quals/Nonsense/Pictures/Picture4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/VolgaCTF-Quals/Nonsense/Pictures/Picture4.png -------------------------------------------------------------------------------- /2018/VolgaCTF-Quals/Nonsense/Pictures/Picture5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/VolgaCTF-Quals/Nonsense/Pictures/Picture5.png -------------------------------------------------------------------------------- /2018/VolgaCTF-Quals/Nonsense/Pictures/Picture6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/VolgaCTF-Quals/Nonsense/Pictures/Picture6.png -------------------------------------------------------------------------------- /2018/VolgaCTF-Quals/Nonsense/Pictures/Picture7.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/VolgaCTF-Quals/Nonsense/Pictures/Picture7.gif -------------------------------------------------------------------------------- /2018/VolgaCTF-Quals/Nonsense/Pictures/Picture8.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/VolgaCTF-Quals/Nonsense/Pictures/Picture8.gif -------------------------------------------------------------------------------- /2018/VolgaCTF-Quals/Nonsense/Pictures/Picture9.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/VolgaCTF-Quals/Nonsense/Pictures/Picture9.gif -------------------------------------------------------------------------------- /2018/VolgaCTF-Quals/Nonsense/README.md: -------------------------------------------------------------------------------- 1 | # Nonsense 2 | 3 | **Challenge Points**: 200 4 | **Challenge Description**: We've intercepted several consecutive signatures. Take everything you need and find the secret key. Send it to us in hex. 5 | 6 | We are given [task.py](task.py) as the script used to sign data. 7 | Following are the public parameters: `g`, `y`, `p`, `q`, `a`, `b`, `m`, `message` 8 | 9 | Following is the code for signing data: 10 | ![picture1](Pictures/Picture1.png) 11 | Particularly, the above function has a vulnerability: `k` is being generated using LCG when it is supposed to be generated using a secure algorithm. This is how two values of `k` are being used to sign different messages: 12 | ![picture2](Pictures/Picture2.png) 13 | And the LCG: 14 | ![picture3](Pictures/Picture3.png) 15 | 16 | ## The Exploit 17 | Since we have signatures of two messages whose nonces (ie. `k`) are generated using LCG, we can write: 18 | ![picture4](Pictures/Picture4.png) 19 | ![picture5](Pictures/Picture5.png) 20 | We know from LCG that 21 | ![picture6](Pictures/Picture6.png) 22 | Note that values of `m` and `q` are the same, we can then write s2 as: 23 | ![picture7](Pictures/Picture7.gif) 24 | Multiplying both sides by their respective `k`, we have: 25 | ![picture8](Pictures/Picture8.gif) 26 | ![picture9](Pictures/Picture9.gif) 27 | Multiplying the above equation with s1, we have: 28 | ![picture10](Pictures/Picture10.gif) 29 | Arranging the terms we get `x` as: 30 | ![picture11](Pictures/Picture11.gif) 31 | 32 | I wrote the following script [exploit.py](exploit.py) to implement the above exploit: 33 | ```python 34 | import hashlib 35 | from Crypto.Util.number import * 36 | 37 | # Signature function body variables 38 | g = 88125476599184486094790650278890368754888757655708027167453919435240304366395317529470831972495061725782138055221217302201589783769854366885231779596493602609634987052252863192229681106120745605931395095346012008056087730365567429009621913663891364224332141824100071928803984724198563312854816667719924760795 39 | y = 18433140630820275907539488836516835408779542939919052226997023049612786224410259583219376467254099629677919271852380455772458762645735404211432242965871926570632297310903219184400775850110990886397212284518923292433738871549404880989194321082225561448101852260505727288411231941413212099434438610673556403084 40 | p = 89884656743115795425395461605176038709311877189759878663122975144592708970495081723016152663257074178905267744494172937616748015651504839967430700901664125135185879852143653824715409554960402343311756382635207838848036159350785779959423221882215217326708017212309285537596191495074550701770862125817284985959 41 | q = 1118817215266473099401489299835945027713635248219 42 | 43 | # LCG parameters 44 | a = 3437776292996777467976657547577967657547 45 | b = 828669865469592426262363475477574643634 46 | m = 1118817215266473099401489299835945027713635248219 47 | 48 | assert m == q 49 | 50 | msg1 = "VolgaCTF{nKpV/dmkBeQ0n9Mz0g9eGQ==}" 51 | h1 = int(hashlib.md5(msg1).hexdigest(), 16) 52 | msg2 = "VolgaCTF{KtetaQ4YT8PhTL3O4vsfDg==}" 53 | h2 = int(hashlib.md5(msg2).hexdigest(), 16) 54 | 55 | r1 = 1030409245884476193717141088285092765299686864672 56 | r2 = 403903893160663712713225718481237860747338118174 57 | 58 | s1 = 830067187231135666416948244755306407163838542785 59 | s2 = 803753330562964683180744246754284061126230157465 60 | 61 | inv1 = inverse(s2*a*r1 - s1*r2, q) 62 | x = ((s1*h2 - s1*s2*b - s2*a*h1)*inv1) % q 63 | print hex(x)[2:].replace("L","") 64 | ``` 65 | Got the secret key (in hex) as: **9d529e2da84117fe72a1770a79cec6ece4065212** -------------------------------------------------------------------------------- /2018/VolgaCTF-Quals/Nonsense/exploit.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | from Crypto.Util.number import * 3 | 4 | # Signature function body variables 5 | g = 88125476599184486094790650278890368754888757655708027167453919435240304366395317529470831972495061725782138055221217302201589783769854366885231779596493602609634987052252863192229681106120745605931395095346012008056087730365567429009621913663891364224332141824100071928803984724198563312854816667719924760795 6 | y = 18433140630820275907539488836516835408779542939919052226997023049612786224410259583219376467254099629677919271852380455772458762645735404211432242965871926570632297310903219184400775850110990886397212284518923292433738871549404880989194321082225561448101852260505727288411231941413212099434438610673556403084 7 | p = 89884656743115795425395461605176038709311877189759878663122975144592708970495081723016152663257074178905267744494172937616748015651504839967430700901664125135185879852143653824715409554960402343311756382635207838848036159350785779959423221882215217326708017212309285537596191495074550701770862125817284985959 8 | q = 1118817215266473099401489299835945027713635248219 9 | 10 | # LCG parameters 11 | a = 3437776292996777467976657547577967657547 12 | b = 828669865469592426262363475477574643634 13 | m = 1118817215266473099401489299835945027713635248219 14 | 15 | assert m == q 16 | 17 | msg1 = "VolgaCTF{nKpV/dmkBeQ0n9Mz0g9eGQ==}" 18 | h1 = int(hashlib.md5(msg1).hexdigest(), 16) 19 | msg2 = "VolgaCTF{KtetaQ4YT8PhTL3O4vsfDg==}" 20 | h2 = int(hashlib.md5(msg2).hexdigest(), 16) 21 | 22 | r1 = 1030409245884476193717141088285092765299686864672 23 | r2 = 403903893160663712713225718481237860747338118174 24 | 25 | s1 = 830067187231135666416948244755306407163838542785 26 | s2 = 803753330562964683180744246754284061126230157465 27 | 28 | inv1 = inverse(s2*a*r1 - s1*r2, q) 29 | x = ((s1*h2 - s1*s2*b - s2*a*h1)*inv1) % q 30 | print hex(x)[2:].replace("L","") -------------------------------------------------------------------------------- /2018/VolgaCTF-Quals/Nonsense/signatures: -------------------------------------------------------------------------------- 1 | ('VolgaCTF{nKpV/dmkBeQ0n9Mz0g9eGQ==}', 1030409245884476193717141088285092765299686864672, 830067187231135666416948244755306407163838542785) 2 | ('VolgaCTF{KtetaQ4YT8PhTL3O4vsfDg==}', 403903893160663712713225718481237860747338118174, 803753330562964683180744246754284061126230157465) 3 | ('VolgaCTF{8NXrNihQFZHXN/aLQeYKtg==}', 573204611556272128788136170196175308321188191436, 91103585122319085944642441222968347176761155259) 4 | ('VolgaCTF{uDh3jKDKW2utTkblP43NQw==}', 988208923601321592314278832250352152086708201148, 535902494423594375360085340272213659149931817732) 5 | ('VolgaCTF{gtE4LCuhT5drcDunvKz/oQ==}', 398664332680411743333343859695363011153860369916, 392831307484494740050270232580899453387203218646) 6 | ('VolgaCTF{rS9IEsyvXHOCUo0/TL2c1A==}', 1069308776596602518230279648695605679674084062212, 1092197517441497735860968374670599451237193808469) 7 | ('VolgaCTF{4gEh/j9EGwZ20NEoBieDbQ==}', 299126738734367538949359921058714964192219834697, 1033663138335940105270395993670462206279669465530) 8 | ('VolgaCTF{RwpewhJhMGH0MORFtXQfAw==}', 45947153576235029841784762518202071246619636555, 160232137675713914067049553022084774145041067326) 9 | ('VolgaCTF{i7QjVusEQboUz2tPx/Uxkw==}', 158481243947457932495342738131507924205209157088, 260728631055453998945003114392349125641429319965) 10 | ('VolgaCTF{nQwf/+78QMObu3S3Oh1Olg==}', 117030185689896730023482874167356847173848413476, 645757721193000290408806214518814010431656731046) 11 | 12 | -------------------------------------------------------------------------------- /2018/VolgaCTF-Quals/Nonsense/task.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | import gmpy2 3 | import os 4 | from secret import x, seed 5 | 6 | 7 | class DSA(): 8 | def __init__(self): 9 | self.g = 88125476599184486094790650278890368754888757655708027167453919435240304366395317529470831972495061725782138055221217302201589783769854366885231779596493602609634987052252863192229681106120745605931395095346012008056087730365567429009621913663891364224332141824100071928803984724198563312854816667719924760795 10 | self.y = 18433140630820275907539488836516835408779542939919052226997023049612786224410259583219376467254099629677919271852380455772458762645735404211432242965871926570632297310903219184400775850110990886397212284518923292433738871549404880989194321082225561448101852260505727288411231941413212099434438610673556403084 11 | self.p = 89884656743115795425395461605176038709311877189759878663122975144592708970495081723016152663257074178905267744494172937616748015651504839967430700901664125135185879852143653824715409554960402343311756382635207838848036159350785779959423221882215217326708017212309285537596191495074550701770862125817284985959 12 | self.q = 1118817215266473099401489299835945027713635248219 13 | self.x = x 14 | 15 | def sign(self, m, k): 16 | h = int(hashlib.md5(m).hexdigest(), 16) 17 | r = pow(self.g, k, self.p) % self.q 18 | s = int(((self.x * r + h) * gmpy2.invert(k, self.q)) % self.q) 19 | return (r, s) 20 | 21 | def verify(self, m, r, s): 22 | if 0 < r and r < self.q and 0 < s and s < self.q: 23 | h = int(hashlib.md5(m).hexdigest(), 16) 24 | w = gmpy2.invert(s, self.q) 25 | u1 = (h * w) % self.q 26 | u2 = (r * w) % self.q 27 | v = ((pow(self.g, u1, self.p) * pow(self.y, u2, self.p)) % self.p) % self.q 28 | return v == r 29 | return None 30 | 31 | 32 | class LCG(): 33 | def __init__(self): 34 | self.a = 3437776292996777467976657547577967657547 35 | self.b = 828669865469592426262363475477574643634 36 | self.m = 1118817215266473099401489299835945027713635248219 37 | self.seed = seed 38 | self.state = (self.a * self.seed + self.b) % self.m 39 | 40 | def next_number(self): 41 | self.state = (self.a * self.state + self.b) % self.m 42 | return self.state 43 | 44 | 45 | generator = LCG() 46 | signature = DSA() 47 | 48 | for _ in range(2): 49 | message = "VolgaCTF{" + os.urandom(16).encode('hex') + "}" 50 | k = generator.next_number() 51 | (r, s) = signature.sign(message, k) 52 | print (message, r, s) 53 | print signature.verify(message, r, s) -------------------------------------------------------------------------------- /2018/b00t2root'18/RSA-2/exploit.sage: -------------------------------------------------------------------------------- 1 | from sage.all import * 2 | 3 | # All the variable names mean the same as mentioned in the explanation 4 | # For eg, a,b are the values in the function f = ax + b 5 | 6 | def gcd(a, b): 7 | while b: 8 | a, b = b, a % b 9 | return a.monic() 10 | 11 | def franklinreiter(C1, C2, e, N): 12 | P. = PolynomialRing(Zmod(N)) 13 | g1 = (X + 124757617046649L)^e - C1 14 | g2 = (X + 107148233566056L)^e - C2 15 | print "Result" 16 | return -gcd(g1, g2).coefficients()[0] 17 | c1 = 87410813732157727701928184577314318681587457726095432638836338681211650253979034474596959990411435773763619929643745595561018045828590610328140736165000754846648327232298646701600080979346670157972588491030528441191645554122003288005262778737855011793921980764813901447954145380508985385929190951189001811183 18 | c2 = 13405530225102142120310029551994876557837309021095393214835868463875586021351445304878372433515568058695315045246405214821866800311993984428311760617739453096525618753380012567374424357402936368910846206438489444245873338816383688500972351617863313954864557810634214028546221991063291427532826592675208605764 19 | n = 114725527397185618184017233206819193913174443780510744606142335459665478168081417742295326326458510125306461590118257162988125409459000413629137879229803717947627133370343339582895822944017711093729671794212087753322731071609302218014807365556283824229308384059742494244873283137838666434755861643308137132991 20 | e = 12289 21 | 22 | flag = franklinreiter(c1, c2, e, n) 23 | print hex(int(flag))[2:].replace("L","").decode("hex") -------------------------------------------------------------------------------- /2018/hxp-CTF/daring/Pictures/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/hxp-CTF/daring/Pictures/1.gif -------------------------------------------------------------------------------- /2018/hxp-CTF/daring/Pictures/2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/hxp-CTF/daring/Pictures/2.gif -------------------------------------------------------------------------------- /2018/hxp-CTF/daring/Pictures/3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/hxp-CTF/daring/Pictures/3.gif -------------------------------------------------------------------------------- /2018/hxp-CTF/daring/README.md: -------------------------------------------------------------------------------- 1 | # Daring 2 | 3 | **Challenge Points**: 4 | 5 | **Challenge Description**: We encrypted our flag, but we lost the keys. Can you help? 6 | 7 | This was a simple yet a very tricky challenge made by `yyyyyyy` aimed at testing your basics. In this challenge you are given a small script: 8 | 9 | ```python 10 | #!/usr/bin/env python3 11 | import os 12 | from Crypto.Cipher import AES 13 | from Crypto.Hash import SHA256 14 | from Crypto.Util import Counter 15 | from Crypto.PublicKey import RSA 16 | 17 | flag = open('flag.txt', 'rb').read().strip() 18 | 19 | key = RSA.generate(1024, e=3) 20 | open('pubkey.txt', 'w').write(key.publickey().exportKey('PEM').decode() + '\n') 21 | open('rsa.enc', 'wb').write(pow(int.from_bytes(flag.ljust(128, b'\0'), 'big'), key.e, key.n).to_bytes(128, 'big')) 22 | 23 | key = SHA256.new(key.exportKey('DER')).digest() 24 | open('aes.enc', 'wb').write(AES.new(key, AES.MODE_CTR, counter=Counter.new(128)).encrypt(flag)) 25 | ``` 26 | 27 | If you analyse the script carefully, you will notice that the same flag is encrypted in two independent ways: 28 | 1. The flag is padded with `\x00` (null byte) to make the plaintext of size 128 bytes and then encrypted using the public key where `e = 3` 29 | 2. SHA256 of the private key of used for encryption using RSA is calculated, the result of which is then used as a symmetric key to encrypt the `unpadded` flag using AES in CTR mode. 30 | 31 | Some observations: 32 | 1. We all know that `e = 3` is vulnerable to root attacks, but here in our challenge, since the flag is padded with null bytes to make it of size 128 bytes, the root attack won't work since `pt`^3 > `n` (`pt` is the padded plaintext and `n` is the RSA modulus) and hence will wrap around while calculating the ciphertext. 33 | 2. When some plaintext is encrypted in CTR mode, remember that the ciphertext size is exactly of the same size as plaintext, since CTR mode is similar to a stream cipher. 34 | 35 | Based on the above observations, we will try to move ahead: 36 | 1. Size of ciphertext of AES encrypted flag is 43 bytes. This implies that the original size of the flag is 43 bytes. 37 | 2. From (1), we can say that: 38 | + plaintext = flag + '\x00'\*(128-43) = flag + '\x00'\*85 39 | + ciphertext ![picture](Pictures/1.gif) 40 | + ciphertext ![picture](Pictures/2.gif) 41 | 42 | To get **flag3 % n**, we can compute: 43 | 44 | ![picture](Pictures/3.gif) 45 | 46 | and get the value of `x` = flag3 % n 47 | 48 | 49 | Probably **flag3 > n**, since flag is of 43 bytes. But we can write: 50 | 1. x = flag3 % n 51 | 2. flag3 = x + k*n 52 | 53 | So, now if we add multiples of `n` to `x` and check if the resultant value is a perfect cube, we can get the flag by taking the cube root. This part of the challenge is similar to Iowe challenge from CSAW CTF Qualifiers 2018: https://ctftime.org/task/6668 54 | 55 | I wrote the following script to solve the challenge: 56 | ```python 57 | #!/usr/bin/env python3 58 | import os 59 | from Crypto.Cipher import AES 60 | from Crypto.Hash import SHA256 61 | from Crypto.Util import Counter 62 | from Crypto.Util.number import * 63 | from Crypto.PublicKey import RSA 64 | import gmpy2 65 | 66 | pubkey = RSA.importKey(open("pubkey.txt").read()) 67 | e = pubkey.e 68 | n = pubkey.n 69 | rsa_enc = int.from_bytes(open("rsa.enc","rb").read(), 'big') 70 | 71 | assert GCD(2, n) == 1 72 | # 680 * 3 = 2040 73 | inv = pow(inverse(2, n), 2040, n) 74 | aes_enc = open("aes.enc","rb").read() 75 | 76 | # From here we get the size of the actual flag 77 | assert len(aes_enc) == 43 78 | print(int.from_bytes(b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".ljust(128,b'\0'), 'big') == int.from_bytes(b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 'big') << 680) 79 | 80 | rsa_enc = rsa_enc*inv % n 81 | for i in range(1000): 82 | ans = gmpy2.iroot(rsa_enc + i*n, 3)[1] 83 | if ans == True: 84 | print("Gotit", i) 85 | pt = int(gmpy2.iroot(rsa_enc + i*n, 3)[0]) 86 | print(pt.to_bytes(43, 'big')) 87 | break 88 | ``` 89 | Exploit script here: [exploit.py](exploit.py) 90 | -------------------------------------------------------------------------------- /2018/hxp-CTF/daring/aes.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/hxp-CTF/daring/aes.enc -------------------------------------------------------------------------------- /2018/hxp-CTF/daring/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os 3 | from Crypto.Cipher import AES 4 | from Crypto.Hash import SHA256 5 | from Crypto.Util import Counter 6 | from Crypto.Util.number import * 7 | from Crypto.PublicKey import RSA 8 | import gmpy2 9 | 10 | pubkey = RSA.importKey(open("pubkey.txt").read()) 11 | e = pubkey.e 12 | n = pubkey.n 13 | rsa_enc = int.from_bytes(open("rsa.enc","rb").read(), 'big') 14 | 15 | assert GCD(2, n) == 1 16 | # 680 * 3 = 2040 17 | inv = pow(inverse(2, n), 2040, n) 18 | aes_enc = open("aes.enc","rb").read() 19 | 20 | # From here we get the size of the actual flag 21 | assert len(aes_enc) == 43 22 | print(int.from_bytes(b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".ljust(128,b'\0'), 'big') == int.from_bytes(b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 'big') << 680) 23 | 24 | rsa_enc = rsa_enc*inv % n 25 | for i in range(1000): 26 | ans = gmpy2.iroot(rsa_enc + i*n, 3)[1] 27 | if ans == True: 28 | print("Gotit", i) 29 | pt = int(gmpy2.iroot(rsa_enc + i*n, 3)[0]) 30 | print(pt.to_bytes(43, 'big')) 31 | break 32 | -------------------------------------------------------------------------------- /2018/hxp-CTF/daring/pubkey.txt: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC7LPIneSm9M962IJh4Op5Dwr9k 3 | aud5nAOXZZvafTrbkfAMmFUv7u/VmNzvPiTWhuaHgKEhyzVFp9XXdp4u+KoQ41wd 4 | H4LS7SJq5eWGaEU9riDcP1MF2orO+OWDgbzx9hgdz5k3LyEHTrmsUgUQNsHCVsZi 5 | FQr8/gZPzYYTRWMYcwIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /2018/hxp-CTF/daring/rsa.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashutosh1206/Crypto-CTF-Writeups/02d6e5dca10ade04164fea6199590666b10b9070/2018/hxp-CTF/daring/rsa.enc -------------------------------------------------------------------------------- /2018/hxp-CTF/daring/vuln.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os 3 | from Crypto.Cipher import AES 4 | from Crypto.Hash import SHA256 5 | from Crypto.Util import Counter 6 | from Crypto.PublicKey import RSA 7 | 8 | flag = open('flag.txt', 'rb').read().strip() 9 | 10 | key = RSA.generate(1024, e=3) 11 | open('pubkey.txt', 'w').write(key.publickey().exportKey('PEM').decode() + '\n') 12 | open('rsa.enc', 'wb').write(pow(int.from_bytes(flag.ljust(128, b'\0'), 'big'), key.e, key.n).to_bytes(128, 'big')) 13 | 14 | key = SHA256.new(key.exportKey('DER')).digest() 15 | open('aes.enc', 'wb').write(AES.new(key, AES.MODE_CTR, counter=Counter.new(128)).encrypt(flag)) 16 | 17 | -------------------------------------------------------------------------------- /2018/noxCTF/Decryptor/README.md: -------------------------------------------------------------------------------- 1 | # Decryptor 2 | 3 | **Challenge Points**: 447 4 | 5 | **Challenge Description**: I created this nice decryptor for RSA ciphertexts, you should try it out! 6 | 7 | 8 | Chosen Ciphertext Attack on RSA unpadded encryption. Similar challenge writeup: https://masterpessimistaa.wordpress.com/2018/03/04/pragyan-ctf-rsas-quest/ 9 | 10 | Full exploit script for this challenge: 11 | ```python 12 | from pwn import * 13 | from Crypto.Util.number import * 14 | 15 | r = remote("chal.noxale.com","4242") 16 | r.recvline().strip() 17 | 18 | N = 140165355674296399459239442258630641339281917770736077969396713192714338090714726890918178888723629353043167144351074222216025145349467583141291274172356560132771690830020353668100494447956043734613525952945037667879068512918232837185005693504551982611886445611514773529698595162274883360353962852882911457919 19 | e = 65537 20 | c = 86445915530920147553767348020686132564453377048106098831426077547738998373682256014690928256854752252580894971618956714013602556152722531577337080534714463052378206442086672725486411296963581166836329721403101091377505869510101752378162287172126836920825099014089297075416142603776647872962582390687281063434 21 | 22 | chosen_ct = (c * pow(2, e, N)) % N 23 | r.sendline(hex(chosen_ct)[2:].replace("L","")) 24 | 25 | _pt = int(r.recvline().strip(), 16) 26 | print long_to_bytes(_pt/2) 27 | ``` 28 | 29 | Running this script gives us the flag: **noxCTF{0u7sm4r73d}** 30 | -------------------------------------------------------------------------------- /2018/noxCTF/Decryptor/exploit.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | from Crypto.Util.number import * 3 | 4 | r = remote("chal.noxale.com","4242") 5 | r.recvline().strip() 6 | 7 | N = 140165355674296399459239442258630641339281917770736077969396713192714338090714726890918178888723629353043167144351074222216025145349467583141291274172356560132771690830020353668100494447956043734613525952945037667879068512918232837185005693504551982611886445611514773529698595162274883360353962852882911457919 8 | e = 65537 9 | c = 86445915530920147553767348020686132564453377048106098831426077547738998373682256014690928256854752252580894971618956714013602556152722531577337080534714463052378206442086672725486411296963581166836329721403101091377505869510101752378162287172126836920825099014089297075416142603776647872962582390687281063434 10 | 11 | chosen_ct = (c * pow(2, e, N)) % N 12 | r.sendline(hex(chosen_ct)[2:].replace("L","")) 13 | 14 | _pt = int(r.recvline().strip(), 16) 15 | print long_to_bytes(_pt/2) 16 | -------------------------------------------------------------------------------- /2018/noxCTF/Trinity/README.md: -------------------------------------------------------------------------------- 1 | # Trinity 2 | 3 | **Challenge Points**: 794 4 | 5 | **Challenge Description**: Neo, you are the chosen one. The only person who can make sense of these numbers. Do it. 6 | 7 | 8 | You might want to see our approach for solving [WTF](../WTF/) before moving further in this writeup (Guessing work in this challenge is related to `WTF` challenge). 9 | 10 | In this challenge, we get three ciphertext-modulus pairs: 11 | ``` 12 | N = 331310324212000030020214312244232222400142410423413104441140203003243002104333214202031202212403400220031202142322434104143104244241214204444443323000244130122022422310201104411044030113302323014101331214303223312402430402404413033243132101010422240133122211400434023222214231402403403200012221023341333340042343122302113410210110221233241303024431330001303404020104442443120130000334110042432010203401440404010003442001223042211442001413004 13 | c = 310020004234033304244200421414413320341301002123030311202340222410301423440312412440240244110200112141140201224032402232131204213012303204422003300004011434102141321223311243242010014140422411342304322201241112402132203101131221223004022003120002110230023341143201404311340311134230140231412201333333142402423134333211302102413111111424430032440123340034044314223400401224111323000242234420441240411021023100222003123214343030122032301042243 14 | 15 | 16 | N = 302240000040421410144422133334143140011011044322223144412002220243001141141114123223331331304421113021231204322233120121444434210041232214144413244434424302311222143224402302432102242132244032010020113224011121043232143221203424243134044314022212024343100042342002432331144300214212414033414120004344211330224020301223033334324244031204240122301242232011303211220044222411134403012132420311110302442344021122101224411230002203344140143044114 17 | c = 112200203404013430330214124004404423210041321043000303233141423344144222343401042200334033203124030011440014210112103234440312134032123400444344144233020130110134042102220302002413321102022414130443041144240310121020100310104334204234412411424420321211112232031121330310333414423433343322024400121200333330432223421433344122023012440013041401423202210124024431040013414313121123433424113113414422043330422002314144111134142044333404112240344 18 | 19 | 20 | N = 332200324410041111434222123043121331442103233332422341041340412034230003314420311333101344231212130200312041044324431141033004333110021013020140020011222012300020041342040004002220210223122111314112124333211132230332124022423141214031303144444134403024420111423244424030030003340213032121303213343020401304243330001314023030121034113334404440421242240113103203013341231330004332040302440011324004130324034323430143102401440130242321424020323 21 | c = 10013444120141130322433204124002242224332334011124210012440241402342100410331131441303242011002101323040403311120421304422222200324402244243322422444414043342130111111330022213203030324422101133032212042042243101434342203204121042113212104212423330331134311311114143200011240002111312122234340003403312040401043021433112031334324322123304112340014030132021432101130211241134422413442312013042141212003102211300321404043012124332013240431242 22 | ``` 23 | 24 | This looks like we need to do Hastad's Broadcast Attack with e=3, you can read about it in Crypton [here](https://github.com/ashutosh1206/Crypton/tree/master/RSA-encryption/Attack-Hastad-Broadcast). But the moduli looked somewhat strange to me; also the attack did not work on these moduli. All the numbers only contained digits from `0` to `4`. So they can be base-5 numbers. 25 | 26 | I converted them back to base-10 (decimal) numbers, implemented the attack using p4-team's [crypto-commons](https://github.com/p4-team/crypto-commons/blob/master/crypto_commons/rsa/rsa_commons.py) library code and got the flag! 27 | 28 | ```python 29 | from crypto_commons.generic import long_to_bytes 30 | from crypto_commons.rsa.rsa_commons import hastad_broadcast 31 | 32 | n1 = "331310324212000030020214312244232222400142410423413104441140203003243002104333214202031202212403400220031202142322434104143104244241214204444443323000244130122022422310201104411044030113302323014101331214303223312402430402404413033243132101010422240133122211400434023222214231402403403200012221023341333340042343122302113410210110221233241303024431330001303404020104442443120130000334110042432010203401440404010003442001223042211442001413004" 33 | c1 = "310020004234033304244200421414413320341301002123030311202340222410301423440312412440240244110200112141140201224032402232131204213012303204422003300004011434102141321223311243242010014140422411342304322201241112402132203101131221223004022003120002110230023341143201404311340311134230140231412201333333142402423134333211302102413111111424430032440123340034044314223400401224111323000242234420441240411021023100222003123214343030122032301042243" 34 | 35 | n2 = "302240000040421410144422133334143140011011044322223144412002220243001141141114123223331331304421113021231204322233120121444434210041232214144413244434424302311222143224402302432102242132244032010020113224011121043232143221203424243134044314022212024343100042342002432331144300214212414033414120004344211330224020301223033334324244031204240122301242232011303211220044222411134403012132420311110302442344021122101224411230002203344140143044114" 36 | c2 = "112200203404013430330214124004404423210041321043000303233141423344144222343401042200334033203124030011440014210112103234440312134032123400444344144233020130110134042102220302002413321102022414130443041144240310121020100310104334204234412411424420321211112232031121330310333414423433343322024400121200333330432223421433344122023012440013041401423202210124024431040013414313121123433424113113414422043330422002314144111134142044333404112240344" 37 | 38 | n3 = "332200324410041111434222123043121331442103233332422341041340412034230003314420311333101344231212130200312041044324431141033004333110021013020140020011222012300020041342040004002220210223122111314112124333211132230332124022423141214031303144444134403024420111423244424030030003340213032121303213343020401304243330001314023030121034113334404440421242240113103203013341231330004332040302440011324004130324034323430143102401440130242321424020323" 39 | c3 = "10013444120141130322433204124002242224332334011124210012440241402342100410331131441303242011002101323040403311120421304422222200324402244243322422444414043342130111111330022213203030324422101133032212042042243101434342203204121042113212104212423330331134311311114143200011240002111312122234340003403312040401043021433112031334324322123304112340014030132021432101130211241134422413442312013042141212003102211300321404043012124332013240431242" 40 | 41 | n1 = int(n1, 5) 42 | n2 = int(n2, 5) 43 | n3 = int(n3, 5) 44 | c1 = int(c1, 5) 45 | c2 = int(c2, 5) 46 | c3 = int(c3, 5) 47 | 48 | print(long_to_bytes(hastad_broadcast([(c1, n1), (c2, n2), (c3, n3)]))) 49 | ``` 50 | Got the flag on running the above script: **noxCTF{D4mn_y0u_h4s74d_wh47_4_b100dy_b4s74rd!}** -------------------------------------------------------------------------------- /2018/noxCTF/Trinity/exploit.py: -------------------------------------------------------------------------------- 1 | from crypto_commons.generic import long_to_bytes 2 | from crypto_commons.rsa.rsa_commons import hastad_broadcast 3 | 4 | n1 = "331310324212000030020214312244232222400142410423413104441140203003243002104333214202031202212403400220031202142322434104143104244241214204444443323000244130122022422310201104411044030113302323014101331214303223312402430402404413033243132101010422240133122211400434023222214231402403403200012221023341333340042343122302113410210110221233241303024431330001303404020104442443120130000334110042432010203401440404010003442001223042211442001413004" 5 | c1 = "310020004234033304244200421414413320341301002123030311202340222410301423440312412440240244110200112141140201224032402232131204213012303204422003300004011434102141321223311243242010014140422411342304322201241112402132203101131221223004022003120002110230023341143201404311340311134230140231412201333333142402423134333211302102413111111424430032440123340034044314223400401224111323000242234420441240411021023100222003123214343030122032301042243" 6 | 7 | n2 = "302240000040421410144422133334143140011011044322223144412002220243001141141114123223331331304421113021231204322233120121444434210041232214144413244434424302311222143224402302432102242132244032010020113224011121043232143221203424243134044314022212024343100042342002432331144300214212414033414120004344211330224020301223033334324244031204240122301242232011303211220044222411134403012132420311110302442344021122101224411230002203344140143044114" 8 | c2 = "112200203404013430330214124004404423210041321043000303233141423344144222343401042200334033203124030011440014210112103234440312134032123400444344144233020130110134042102220302002413321102022414130443041144240310121020100310104334204234412411424420321211112232031121330310333414423433343322024400121200333330432223421433344122023012440013041401423202210124024431040013414313121123433424113113414422043330422002314144111134142044333404112240344" 9 | 10 | n3 = "332200324410041111434222123043121331442103233332422341041340412034230003314420311333101344231212130200312041044324431141033004333110021013020140020011222012300020041342040004002220210223122111314112124333211132230332124022423141214031303144444134403024420111423244424030030003340213032121303213343020401304243330001314023030121034113334404440421242240113103203013341231330004332040302440011324004130324034323430143102401440130242321424020323" 11 | c3 = "10013444120141130322433204124002242224332334011124210012440241402342100410331131441303242011002101323040403311120421304422222200324402244243322422444414043342130111111330022213203030324422101133032212042042243101434342203204121042113212104212423330331134311311114143200011240002111312122234340003403312040401043021433112031334324322123304112340014030132021432101130211241134422413442312013042141212003102211300321404043012124332013240431242" 12 | 13 | n1 = int(n1, 5) 14 | n2 = int(n2, 5) 15 | n3 = int(n3, 5) 16 | c1 = int(c1, 5) 17 | c2 = int(c2, 5) 18 | c3 = int(c3, 5) 19 | 20 | print(long_to_bytes(hastad_broadcast([(c1, n1), (c2, n2), (c3, n3)]))) 21 | -------------------------------------------------------------------------------- /2018/noxCTF/WTF/README.md: -------------------------------------------------------------------------------- 1 | # WTF 2 | 3 | **Challenge Points**: 742 4 | 5 | **Challenge Description**: Um uhhhhhhhhh WTF IS THIS?! I give up. Now you try to solve this. 6 | 7 | *Disclaimer*: Guessing involved in this challenge, so proceed at your own risk 8 | 9 | In this challenge we are given N, e, c like every other RSA challenge, except for the fact that the values are encoded using some weird encoding technique. Googling about it leads to nothing, here are the public key values and ciphertext 10 | 11 | ``` 12 | N = "lObAbAbSBlZOOEBllOEbblTlOAbOlTSBATZBbOSAEZTZEAlSOggTggbTlEgBOgSllEEOEZZOSSAOlBlAgBBBBbbOOSSTOTEOllbZgElgbZSZbbSTTOEBZZSBBEEBTgESEgAAAlAOAEbTZBZZlOZSOgBAOBgOAZEZbOBZbETEOSBZSSElSSZlbBSgbTBOTBSBBSOZOAEBEBZEZASbOgZBblbblTSbBTObAElTSTOlSTlATESEEbSTBOlBlZOlAOETAZAgTBTSAEbETZOlElBEESObbTOOlgAZbbOTBOBEgAOBAbZBObBTg" 13 | e = "lBlbSbTASTTSZTEASTTEBOOAEbEbOOOSBAgABTbZgSBAZAbBlBBEAZlBlEbSSSETAlSOlAgAOTbETAOTSZAZBSbOlOOZlZTETAOSSSlTZOElOOABSZBbZTSAZSlASTZlBBEbEbOEbSTAZAZgAgTlOTSEBEAlObEbbgZBlgOEBTBbbSZAZBBSSZBOTlTEAgBBSZETAbBgEBTATgOZBTllOOSSTlSSTOSSZSZAgSZATgbSOEOTgTTOAABSZEZBEAZBOOTTBSgSZTZbOTgZTTElSOATOAlbBZTBlOTgOSlETgTBOglgETbT" 14 | c = "SOSBOEbgOZTZBEgZAOSTTSObbbbTOObETTbBAlOSBbABggTOBSObZBbbggggZZlbBblgEABlATBESZgASBbOZbASbAAOZSSgbAOZlEgTAlgblBTbBSTAEBgEOEbgSZgSlgBlBSZOObSlgAOSbbOOgEbllAAZgBATgEAZbBEBOAAbZTggbOEZSSBOOBZZbAAlTBgBOglTSSESOTbbSlTAZATEOZbgbgOBZBBBBTBTOSBgEZlOBTBSbgbTlZBbbOBbTSbBASBTlglSEAEgTOSOblAbEgBAbOlbOETAEZblSlEllgTTbbgb" 15 | ``` 16 | 17 | Looking at such a big value of `e`, it had to be Wiener's Attack or it's variant. But we cannot move further without decoding the values. 18 | 19 | 20 | The part below is purely guessing 21 | 22 | So, one of my teammates suggested looking at the distinct characters in the encoded strings. Here are the distinct characters present in the encoded strings: 23 | > ['A', 'b', 'E', 'g', 'l', 'O', 'S', 'B', 'T', 'Z'] 24 | 25 | 10 distinct characters, 10 digits in decimal system. So, each character represents a digit. But how do we map them? 26 | > 'O' --> 0 27 | > 'l' --> 1 28 | > 'Z' --> 2 29 | > 'E' --> 3 30 | > 'A' --> 4 31 | > 'S' --> 5 32 | > 'b' --> 6 33 | > 'T' --> 7 34 | > 'B' --> 8 35 | > 'g' --> 9 36 | 37 | Now, there is nothing significant left in the challenge, all that is left is to implement a simple Wiener's Attack, for which I wrote a sage/python implementation and got the flag: 38 | ```python 39 | from sage.all import * 40 | from Crypto.Util.number import * 41 | 42 | def mapping(str1): 43 | for i in str1: 44 | if i not in "AbEglOSBTZ": 45 | print i 46 | str1 = str1.replace("O", '0') 47 | str1 = str1.replace("l", '1') 48 | str1 = str1.replace("Z", '2') 49 | str1 = str1.replace("E", '3') 50 | str1 = str1.replace("A", '4') 51 | str1 = str1.replace("S", '5') 52 | str1 = str1.replace("b", '6') 53 | str1 = str1.replace("T", '7') 54 | str1 = str1.replace("B", '8') 55 | str1 = str1.replace("g", '9') 56 | return str1 57 | 58 | def wiener(e, n): 59 | m = 12345 60 | c = pow(m, e, n) 61 | lst = continued_fraction(Integer(e)/Integer(n)) 62 | conv = lst.convergents() 63 | for i in conv: 64 | k = i.numerator() 65 | d = int(i.denominator()) 66 | try: 67 | m1 = pow(c, d, n) 68 | if m1 == m: 69 | print "[*] Found d: ", d 70 | return d 71 | except: 72 | continue 73 | return -1 74 | 75 | N = "lObAbAbSBlZOOEBllOEbblTlOAbOlTSBATZBbOSAEZTZEAlSOggTggbTlEgBOgSllEEOEZZOSSAOlBlAgBBBBbbOOSSTOTEOllbZgElgbZSZbbSTTOEBZZSBBEEBTgESEgAAAlAOAEbTZBZZlOZSOgBAOBgOAZEZbOBZbETEOSBZSSElSSZlbBSgbTBOTBSBBSOZOAEBEBZEZASbOgZBblbblTSbBTObAElTSTOlSTlATESEEbSTBOlBlZOlAOETAZAgTBTSAEbETZOlElBEESObbTOOlgAZbbOTBOBEgAOBAbZBObBTg" 76 | e = "lBlbSbTASTTSZTEASTTEBOOAEbEbOOOSBAgABTbZgSBAZAbBlBBEAZlBlEbSSSETAlSOlAgAOTbETAOTSZAZBSbOlOOZlZTETAOSSSlTZOElOOABSZBbZTSAZSlASTZlBBEbEbOEbSTAZAZgAgTlOTSEBEAlObEbbgZBlgOEBTBbbSZAZBBSSZBOTlTEAgBBSZETAbBgEBTATgOZBTllOOSSTlSSTOSSZSZAgSZATgbSOEOTgTTOAABSZEZBEAZBOOTTBSgSZTZbOTgZTTElSOATOAlbBZTBlOTgOSlETgTBOglgETbT" 77 | c = "SOSBOEbgOZTZBEgZAOSTTSObbbbTOObETTbBAlOSBbABggTOBSObZBbbggggZZlbBblgEABlATBESZgASBbOZbASbAAOZSSgbAOZlEgTAlgblBTbBSTAEBgEOEbgSZgSlgBlBSZOObSlgAOSbbOOgEbllAAZgBATgEAZbBEBOAAbZTggbOEZSSBOOBZZbAAlTBgBOglTSSESOTbbSlTAZATEOZbgbgOBZBBBBTBTOSBgEZlOBTBSbgbTlZBbbOBbTSbBASBTlglSEAEgTOSOblAbEgBAbOlbOETAEZblSlEllgTTbbgb" 78 | N = int(mapping(N)) 79 | e = int(mapping(e)) 80 | c = int(mapping(c)) 81 | 82 | d = wiener(e, N) 83 | print long_to_bytes(pow(c, d, N)) 84 | ``` 85 | In case you want to learn Wiener's Attack, you can learn about it on Crypton [here](https://github.com/ashutosh1206/Crypton/tree/master/RSA-encryption/Attack-Wiener). 86 | 87 | Running this script gives us the flag as: **noxCTF{RSA_1337_10rd}**. -------------------------------------------------------------------------------- /2018/noxCTF/WTF/exploit.py: -------------------------------------------------------------------------------- 1 | from sage.all import * 2 | from Crypto.Util.number import * 3 | 4 | def mapping(str1): 5 | for i in str1: 6 | if i not in "AbEglOSBTZ": 7 | print i 8 | str1 = str1.replace("O", '0') 9 | str1 = str1.replace("l", '1') 10 | str1 = str1.replace("Z", '2') 11 | str1 = str1.replace("E", '3') 12 | str1 = str1.replace("A", '4') 13 | str1 = str1.replace("S", '5') 14 | str1 = str1.replace("b", '6') 15 | str1 = str1.replace("T", '7') 16 | str1 = str1.replace("B", '8') 17 | str1 = str1.replace("g", '9') 18 | return str1 19 | 20 | def wiener(e, n): 21 | m = 12345 22 | c = pow(m, e, n) 23 | lst = continued_fraction(Integer(e)/Integer(n)) 24 | conv = lst.convergents() 25 | for i in conv: 26 | k = i.numerator() 27 | d = int(i.denominator()) 28 | try: 29 | m1 = pow(c, d, n) 30 | if m1 == m: 31 | print "[*] Found d: ", d 32 | return d 33 | except: 34 | continue 35 | return -1 36 | 37 | N = "lObAbAbSBlZOOEBllOEbblTlOAbOlTSBATZBbOSAEZTZEAlSOggTggbTlEgBOgSllEEOEZZOSSAOlBlAgBBBBbbOOSSTOTEOllbZgElgbZSZbbSTTOEBZZSBBEEBTgESEgAAAlAOAEbTZBZZlOZSOgBAOBgOAZEZbOBZbETEOSBZSSElSSZlbBSgbTBOTBSBBSOZOAEBEBZEZASbOgZBblbblTSbBTObAElTSTOlSTlATESEEbSTBOlBlZOlAOETAZAgTBTSAEbETZOlElBEESObbTOOlgAZbbOTBOBEgAOBAbZBObBTg" 38 | e = "lBlbSbTASTTSZTEASTTEBOOAEbEbOOOSBAgABTbZgSBAZAbBlBBEAZlBlEbSSSETAlSOlAgAOTbETAOTSZAZBSbOlOOZlZTETAOSSSlTZOElOOABSZBbZTSAZSlASTZlBBEbEbOEbSTAZAZgAgTlOTSEBEAlObEbbgZBlgOEBTBbbSZAZBBSSZBOTlTEAgBBSZETAbBgEBTATgOZBTllOOSSTlSSTOSSZSZAgSZATgbSOEOTgTTOAABSZEZBEAZBOOTTBSgSZTZbOTgZTTElSOATOAlbBZTBlOTgOSlETgTBOglgETbT" 39 | c = "SOSBOEbgOZTZBEgZAOSTTSObbbbTOObETTbBAlOSBbABggTOBSObZBbbggggZZlbBblgEABlATBESZgASBbOZbASbAAOZSSgbAOZlEgTAlgblBTbBSTAEBgEOEbgSZgSlgBlBSZOObSlgAOSbbOOgEbllAAZgBATgEAZbBEBOAAbZTggbOEZSSBOOBZZbAAlTBgBOglTSSESOTbbSlTAZATEOZbgbgOBZBBBBTBTOSBgEZlOBTBSbgbTlZBbbOBbTSbBASBTlglSEAEgTOSOblAbEgBAbOlbOETAEZblSlEllgTTbbgb" 40 | N = int(mapping(N)) 41 | e = int(mapping(e)) 42 | c = int(mapping(c)) 43 | 44 | d = wiener(e, N) 45 | print long_to_bytes(pow(c, d, N)) 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Crypto-CTF-Writeups 2 | Writeups to Crypto Challenges in CTFs 3 | --------------------------------------------------------------------------------