├── 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 | 
21 | And so we can also write,
22 | 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 | n^2&space;+&space;mn&space;+&space;1) where,
25 | 
26 | If we take the above result and **divide it with n^2**, the following can be written: 
27 | Since, ns+1 is always greater than and divisible by n2, we can now calculate the message `msg` as:
28 | ^{msg}&space;\pmod&space;{n^{s+1}})
29 | &space;\pmod&space;{n^2})
30 | Therefore,
31 | &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 | 
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 | 
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 , 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:  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 | 
36 | which can also be written as:
37 | 
38 | Upon squaring, we have:
39 | 
40 | Comparing the above equation with , we can write:
41 | **d = (p-1)/2**
42 |
43 | **Solving Step-2**:
44 | Simple compute: 
45 |
46 | **Solving Step-3**:
47 | Simply compute: 
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 | 
7 | The encryption function:
8 | 
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 | *(h^{r}\mod&space;n))\mod&space;n)
11 | Given: 
12 | We can now write:
13 | *(g^{nr}\mod&space;n))\mod&space;n)
14 | which gives us 
15 | Since n=p*p*q,
16 | 
17 | Raising both sides by (p-1)*(q-1), we have:
18 | *(q-1)}\mod&space;n=g^{(m_i+p^{2}qr)*(p-1)*(q-1)}\mod&space;n)
19 | *(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 | *(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: }\equiv1\mod&space;n)
23 | We can now write,
24 | Equation(a): *(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 | 
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 | )
13 | )
14 | })
15 | }\mod&space;n)
16 | Thus we can write,
17 | }=2^{(1+k\phi(n))*(p-0xdeadbeef)})
18 | )*(p-0xdeadbeef)}=(2*2^{k\phi(n)})^{(p-0xdeadbeef)})
19 | })^{(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 | }\equiv1\mod&space;n)
22 | }*2^{k*\phi(n)*(p-0xdeadebeef)}\equiv2^{p-0xdeadebeef}*1\mod&space;n)
23 | 
24 | 
25 | We know from Fermat's Little Theorem that when GCD(a, p) == 1:
26 | 
27 | We can now write:
28 | \mod&space;n)
29 | Thus,
30 | 
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!
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 | 
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 | 
161 | 
162 | 
163 | 
164 | 
165 | 
166 | 
167 | 
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 . 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 | 
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 | 
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 | 
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 | 
36 |
37 | To get the value of `q`, iterate check for every value of `k`, if  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 | 
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 | 
13 | And the LCG:
14 | 
15 |
16 | ## The Exploit
17 | Since we have signatures of two messages whose nonces (ie. `k`) are generated using LCG, we can write:
18 | 
19 | 
20 | We know from LCG that
21 | 
22 | Note that values of `m` and `q` are the same, we can then write s2 as:
23 | 
24 | Multiplying both sides by their respective `k`, we have:
25 | 
26 | 
27 | Multiplying the above equation with s1, we have:
28 | 
29 | Arranging the terms we get `x` as:
30 | 
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 
40 | + ciphertext 
41 |
42 | To get **flag3 % n**, we can compute:
43 |
44 | 
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 |
--------------------------------------------------------------------------------