# Bi0sCTF ### Challengename Source code của chall như sau ```python from ecdsa.ecdsa import Public_key, Private_key from ecdsa import ellipticcurve from hashlib import md5 import random import os import json flag = open("flag", "rb").read()[:-1] magic = os.urandom(16) p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff a = ###REDACTED### b = ###REDACTED### G = ###REDACTED### q = G.order() def bigsur(a,b): a,b = [[a,b],[b,a]][len(a) < len(b)] return bytes([i ^ j for i,j in zip(a,bytes([int(bin(int(b.hex(),16))[2:].zfill(len(f'{int(a.hex(), 16):b}'))[:len(a) - len(b)] + bin(int(b.hex(),16))[2:].zfill(len(bin(int(a.hex(), 16))[2:]))[:len(bin(int(a.hex(), 16))[2:]) - len(bin(int(b.hex(), 16))[2:])][i:i+8], 2) for i in range(0,len(bin(int(a.hex(), 16))[2:]) - len(bin(int(b.hex(), 16))[2:]),8)]) + b)]) def bytes_to_long(s): return int.from_bytes(s, 'big') def genkeys(): d = random.randint(1,q-1) pubkey = Public_key(G, d*G) return pubkey, Private_key(pubkey, d) def sign(msg,nonce,privkey): hsh = md5(msg).digest() nunce = md5(bigsur(nonce,magic)).digest() sig = privkey.sign(bytes_to_long(hsh), bytes_to_long(nunce)) return json.dumps({"msg": msg.hex(), "r": hex(sig.r), "s": hex(sig.s)}) def enc(privkey): x = int(flag.hex(),16) y = pow((x**3 + a*x + b) % p, (p+3)//4, p) F = ellipticcurve.Point('--REDACTED--', x, y) Q = F * privkey.secret_multiplier return (int(Q.x()), int(Q.y())) pubkey, privkey = genkeys() print("Public key:",(int(pubkey.point.x()),int(pubkey.point.y()))) print("Encrypted flag:",enc(privkey)) nonces = set() for _ in '01': try: msg = bytes.fromhex(input("Message: ")) nonce = bytes.fromhex(input("Nonce: ")) if nonce in nonces: print("Nonce already used") continue nonces.add(nonce) print(sign(msg,nonce,privkey)) except ValueError: print("No hex?") exit() ``` Bây giờ, ta bị giấu mất các hệ số của đường cong, ta phải tìm lại được a, b, và điểm G. Ta có được output như sau, mình lấy 1 trường hợp thui nha, tại netcat thì ra nhiều điểm khác nhau 7472616e616e68 6e6861747a69747474 ```python Public key: (62074580829368582344059231535288679141854304453511261626881417078003669760040, 226249697667264697300099616199091032472367422876468248704729481898424740978) Encrypted flag: (80287585214899514117739968699898788173171686319245191029720093652663358176191, 78593019850865466334887789419596022034295179434341282152257703613890819344938) Message: 7472616e616e68 Nonce: 00 {"msg": "7472616e616e68", "r": "0x8d3cb76e42b44cb553ade47f54317c1f924cb1f328422a403781e1bd7017d71d", "s": "0xe0ad72631b049d0461142c9af0fa605b588d0695be99d76c3320bae3fb3b8dcf"} Message: 6e6861747a69747474 Nonce: 0000 {"msg": "6e6861747a69747474", "r": "0x8d3cb76e42b44cb553ade47f54317c1f924cb1f328422a403781e1bd7017d71d", "s": "0xf40567aae8f2a85d7b1c624cb9678a9377753fc4422f6fa0bb81f56de9cb0d5f"} ``` Thì ta được ta có 2 điểm trên đường cong, từ đó ta có được hệ như sau $y_1^2 = x_1^3 + ax_1 + b$ $y_2^2 = x_2^3 + ax_2 + b$ Trừ 2 vế ta được: $(y_1^2 - y_2^2) = (x_1^3 - x_2^3) + a(x_1 - x_2)$ Thay số vào rồi mình tìm được giá trị a nhaaa Có được a rồi thì mình thay vào đường cong là sẽ thu được b nha $y_2^2 - x_2^3 - ax_2 = b$ ``` sage: x1 = 62074580829368582344059231535288679141854304453511261626881417078003669760040 sage: y1 = 226249697667264697300099616199091032472367422876468248704729481898424740978 sage: x2 = 80287585214899514117739968699898788173171686319245191029720093652663358176191 sage: y2 = 78593019850865466334887789419596022034295179434341282152257703613890819344938 sage: p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff sage: sage: ((y1^2 - y2^2)-(x1^3-x2^3))%p 54639013156592795321042211493830327093952145597201788208516029723979065248453 sage: inverse_mod(x1-x2,p) 110394729342389623135386530330724442026697300440596599519364760623105599517533 sage: (54639013156592795321042211493830327093952145597201788208516029723979065248453*110394729 ....: 342389623135386530330724442026697300440596599519364760623105599517533)%p 115792089210356248762697446949407573530086143415290314195533631308867097853948 sage: a = 115792089210356248762697446949407573530086143415290314195533631308867097853948 sage: b = y2^2 - x2^3 - a*x2 sage: n <function numerical_approx at 0x7f8602cb4700> sage: b -517541509172278353837322976445306630893606020082443635100444562615446483964660266092691083682905263177697996252260475724215503247617815238531561262586484929690043313108695439871968309220258853078678068617527449419818350910053664095 sage: b%p 41058363725152142129326129780047268409114441015993725554835256314039467401291 sage: b = 41058363725152142129326129780047268409114441015993725554835256314039467401291 sage: a,b (115792089210356248762697446949407573530086143415290314195533631308867097853948, 41058363725152142129326129780047268409114441015993725554835256314039467401291) sage: ``` ``` a = 115792089210356248762697446949407573530086143415290314195533631308867097853948 b = 41058363725152142129326129780047268409114441015993725554835256314039467401291 ``` Có a,b rồi, mình sẽ search trên google và được đường [**LINK**](https://neuromancer.sk/std/secg/secp256r1) này. Từ đó mình có được các thông số của nó gồm: ``` p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff a = 0 =xffffffff00000001000000000000000000000000fffffffffffffffffffffffc 0 =xffffffff00000001000000000000000000000000fffffffffffffffffffffffc b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b G = (0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296, 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5) n = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 h = 0x1 ``` Bài này thuộc dạng $ECDSA with repeat Nonce$, thì để repeat được nonce, ta chỉ cần nhập nonce thứ nhất là `00` và nonce thứ hai là `0000`. Từ đó, ta có thể làm theo như đường [**link**](https://crypto.stackexchange.com/questions/71764/is-it-safe-to-reuse-a-ecdsa-nonce-for-two-signatures-if-the-public-keys-are-diff) này Ta có được 2 giá trị là $r_1$ $s_1$ $r_2$ $s_2$, với $x_1$x_2$ là private key, $k$ là nonce, thì ta có được rằng $s_1 = k^{-1}(H(m_1) + r_1x_1)$ $s_2 = k^{-1}(H(m_2) + r_2x_2)$ Ta có được rằng $\frac{s_1}{s_2} = \frac{k^{-1}(H(m_1) + r_1x_1)}{k^{-1}(H(m_2) + r_2x_2)} $ $\frac{s_1(H(m_2) + r_2x_2)}{s_2} = H(m_1) + r_1x_1$ $\frac{s_1(H(m_2) + r_2x_2) - s_2H(m_1)}{r_1s_2} = x_1$ Giờ ta thay $x_1$ vào $s_1 = k^{-1}(H(m_1) + r_1x_1)$ $s_1 = k^{-1}(h_1 + r_1\frac{s_1(h_2 + r_2x_2) - s_2h_1}{r_1s_2}) $ Ta có hết tất cả giá trị rồi, giờ tìm lại $x_2$ thuiii, mình dựa vào code này để tìm lại được $x_2$ ```python from Crypto.Util.number import* from hashlib import md5 from ecdsa.numbertheory import inverse_mod s1 = 0xe0ad72631b049d0461142c9af0fa605b588d0695be99d76c3320bae3fb3b8dcf s2 = 0xf40567aae8f2a85d7b1c624cb9678a9377753fc4422f6fa0bb81f56de9cb0d5f r = 0x8d3cb76e42b44cb553ade47f54317c1f924cb1f328422a403781e1bd7017d71d m1 = b"trananh" m2 = b"nhatzittt" messageHash1 = int((md5(m1).hexdigest()),16) messageHash2 = int((md5(m2).hexdigest()),16) numerator = (((s2 * messageHash1) % publicKeyOrderInteger) - ((s1 * messageHash2) % publicKeyOrderInteger)) denominator = inverse_mod( r * ((s1 - s2) % publicKeyOrderInteger), publicKeyOrderInteger) privateKey = numerator * denominator % publicKeyOrderInteger print(privateKey) ``` Ta tìm được khóa $d = 103753787388531709442718751260758444024424117994950490803615988887467390909036$ Ta thấy rằng $Encrypted flag = Private Key*Flag$, thế nên, giờ ta chỉ cần inverse(privatekey, G.order()) rồi nhân lại với Encrypt Flag là thu được Flag thôiii ``` Q = E(80287585214899514117739968699898788173171686319245191029720093652663358176191, 78593019850865466334887789419596022034295179434341282152257703613890819344938) P = int(pow(privateKey,-1,publicKeyOrderInteger))*Q print(P) ``` ``` (173877001943961524508797336940865009214794735500137102852359845041518430077 : 105483079702178112911417165737195582105029489466258484095154775234948912280405 : 1) ``` Flag là tọa độ x **Flag: bi0sctf{https://bit.ly/3I0zwtG}** ### LALALA Source code của chall như sau: ```python from random import randint from re import search flag = "bi0sctf{%s}" % f"{randint(2**39, 2**40):x}" p = random_prime(2**1024) unknowns = [randint(0, 2**32) for _ in range(10)] unknowns = [f + i - (i%1000) for i, f in zip(unknowns, search("{(.*)}", flag).group(1).encode())] output = [] for _ in range(100): aa = [randint(0, 2**1024) for _ in range(1000)] bb = [randint(0, 9) for _ in range(1000)] cc = [randint(0, 9) for _ in range(1000)] output.append(aa) output.append(bb) output.append(cc) output.append(sum([a + unknowns[b]^2 * unknowns[c]^3 for a, b, c in zip(aa, bb, cc)]) % p) print(f"{p = }") print(f"{output = }") ``` Ta thu được rất nhiều giá trị output, tận nhìu nhìu MB lận. Phân tích bài này, ta thấy được rằng $Unknown$ gồm có 10 giá trị, ngoài ra còn có 100 vòng for bao gồm: - Vòng for 0: Gồm 100 vòng for - $$aa_0 + unknown_{b_0}^{2}.unknown_{c_0}^{3} \pmod{p}$$ ... - $$aa_{99} + unknown_{b_{99}}^{2}.unknown_{c_{99}}^{3} \pmod{p}$$ ... - Vòng for 99: Gồm 100 vòng for - $$aa_0 + unknown_{b_0}^{2}.unknown_{c_0}^{3} \pmod{p}$$ ... - $$aa_{99} + unknown_{b_{99}}^{2}.unknown_{c_{99}}^{3} \pmod{p}$$ Ta phân tích vòng for 0, ta thấy rằng $b,c \in {[0,9]}$, thế nên vòng for đầu tiên sẽ bằng: $$\text{hệ số}.unknown_{b_0}^{2}.unknown_{c_0}^{3} + \text{hệ số}.unknown_{b_0}^{2}.unknown_{c_1}^{3} + ... + \text{hệ số}.unknown_{b_1}^{2}.unknown_{c_0}^{3} + ... +\text{hệ số}.unknown_{b_9}^{2}.unknown_{c_9}^{3} + sum(aa) = result_0$$ Tương tự như thế, 100 vòng for ta sẽ có ma trận như sau: \begin{equation*} \begin{bmatrix} coeff_0.b_0.c_0 & coeff_0.b_0.c_1 & ... & coeff_0.b_9.c_9 \\ coeff_1.b_0.c_0 & coeff_1.b_0.c_1 & ... & coeff_1.b_9.c_9 \\ \vdots & \vdots \\ coeff_{99}.b_0.c_0 & coeff{99}.b_0.c_1 & ... & coeff{99}.b_9.c_9 \\ \end{bmatrix} = \begin{bmatrix} result_0 - sum(aa_0) \\ result_1 - sum(aa_1) \\ \vdots \\ result_99 - sum(aa_99) \end{bmatrix} \end{equation*} Sau đó ta chỉ cần dùng hàm ``solve_right`` của sage là có thể tìm được 100 nghiệm từ $unknown_{0}^{2}.unknown_{0}^{3}$ tới $unknown_{9}^{2}.unknown_{9}^{3}$ Ta sẽ thu được 10 giá trị là $unknown_{i}^5$ với $i \in {[0,9]}$. Ta chỉ cần căn bậc 5 là thu được 10 giá trị $unknown$ nha. Ta chỉ cần %1000 là sẽ thu được flag nha. Hơi rắc rối tí nhưng mà bạn đọc code rùi sẽ hiểu nha. ```sage= from out import* from gmpy2 import iroot Ma = [] Re = [] for i in range(0,len(output),4): row = [[0 for i in range(10)] for j in range(10)] aa = output[i] bb = output[i+1] cc = output[i+2] result = output[i+3] sum = 0 for a, b, c in zip(aa,bb,cc): sum = (sum + a) % p row[b][c] +=1 real_row = [] for elements in row: for element in elements: real_row.append(element) Ma.append(real_row) Re.append(result - sum) Mat = Matrix(GF(p), Ma) Res = vector(GF(p), Re) X = Mat^-1 *Res # X = Mat.solve_right(Res) data = [] lst = [] for i in range(100): lst.append(X[i]) if len(lst) == 10: data.append(lst) lst = [] unknown = [] for i in range(10): unknown.append(int(str(iroot(int(data[i][i]),5)[0]).replace("mpz(","").replace(")",""))) print(unknown) flag = "" for i in unknown: flag += chr(i%1000) print(i%1000) print("bi0sctf{" + flag + "}") ``` **Flag: bi0sctf{8d522ae1a7}** ## rr ```python from Crypto.Util.number import * flag = b'bi0sctf{https://www.youtube.com/watch?v=soDR-BctVeE___1e9c4e8dba79812bd81ec4c2}' from random import randint flag = bytes_to_long(flag) n = 472993274721871037103726599805149366727531552333249750035977291933239067588481589544777397613192273114354221827196579379954069925604091911249655707080927769808587176515295614018992848517984372306879552247519117116110554431341268358177159108949791969262793325836353834899335531293329721598226413212541536002401507477776699642647348576111445702197483449777741566350285229621935507081895389023444249054515395783080003733803406382744631528246608154546123270319561514117323480441428953306734274538511770278887429407127143049023747710881993279361892937905382946820141513009017756811296722630617325141162244806884220212939955235410280899112731530527048274396186038160728562551536558223235783656985493518204710943916486379681906506757757594165379493317173050550893487151879681122510523721157284728808336110950008840684602353984682117748018347433177541603140491131603068512706893984834735290809952944273565203183330739252949245209529232254867201402656024997949207918675051941911990640248052951780195402390132237903538546705181463959793972284823588987652138458328270662652334799233015314673544813649692428544375538627858921763941533600553536579901589575693816746953261108022490849251974419402753031545629158199093099096735356165044275617408697 rr = 11898141078345200236264081467585899457224809417108457314508072413792599039332439547789237898270544336909458761754683941320649771736625000667170176071314483 ks = [randint(0, rr**(i+1)) for i in range(20)] # k0 = (0,rr) # k1 = (0,rr^2) có dạng là rr*x + y # k2 = (0,rr^3) có dạng là rr^2*x + rr*y + z # ... c1 = pow(sum(k*flag**i for i, k in enumerate(ks)), (1<<7)-1, n) # (k0*flag^0 + k1*flag^1 + k2*flag^2 + ... + k19*flag^19)^ 127 mod n c2 = pow(flag, (1<<16)+1, n) # flag^65537 mod n ks = [pow(69, k, rr**(i+2)) for i, k in enumerate(ks)] # k0 = 69^k0 % p^2, k1 = 69^k1 % p^3, ..., k19 = 69^k19 % p^21 print(f"{ks = }") print(f"{c1 = }") print(f"{c2 = }") ``` Từ source code trên, ta có thể tóm tắt được rằng: $$ \begin{cases} c1 = (\sum_{i=0}^{19} k_i \ flag^i) ^ {127} \mod \ n \\ c2 = flag^{65537} \mod \ n \\ K = [69^{k_{i}} \mod \ p^{i+2}], \ i \in [0, 19] \end{cases} $$ Ta có rằng $K = [69^{k_{i}} \mod \ p^{i+2}], \ i \in [0, 19]$ Với i == 0, ta có được: $K_0 = 69^{k_{0}} \mod \ p^{2}$ Ta mũ hai vế với $p-1$, ta được: $K_0^{p-1} = (69^{p-1})^{k_{0}} \mod \ p^{2}$ Theo định lý Fermat nhỏ, ta có được rằng: $(c_0*p + 1) = (1 + d_0*p)^{k_0} \mod {p^2}$ Phân tích vế phải bằng [**Nhị thức Pascal Binomial theorem**](https://en.wikipedia.org/wiki/Binomial_theorem), ta được: $$ c_{0}*p + 1 = \left( \begin{array}{c} k_{0} \\ 0 \end{array} \right) \ 1^{k_{0}} \ (d_{0}*p)^0 + \left( \begin{array}{c} k_{0} \\ 1 \end{array} \right) \ 1^{k_{0}-1} \ (d_{0}*p)^1 + ... \ mod \ p^2 $$ Hoặc viết đơn giản hơn là $(c_0*p + 1) = [1^{k_0}*(d_0*p)^0] + [1^{k_0-1}*(k_0*d_0*p)^1] + \ ... + [1^1*(k_0*d_0*p)^{k_0-1}] + [1^0*(d_0*p)^{k_0}] \ mod \ p^2$ Từ trên ta có được: $$c_0 * p + 1 = 1 + k_0*d_0*p \ mod \ p^2$$ $$c_0 * p = k_0*d_0*p \ mod \ p^2$$ $$c_0 = k_0*d_0 \ mod \ p$$ Từ đó, ta có thể tìm lại $k_{0} = c_{0} \ (d_{0})^{-1} \mod \ p$ Thế giờ với $p^r$ thì sao Đặt $x = x_{r} \ p^{r} + … + x_{1} \ p + x_{0}$ Ta có được rằng: $y = g^x \mod p^{r+2}, \ x < p^{(r+1)}$ Tương tự như trên, ta mũ hai về với $p-1$, ta được: $y^q = (g^q) ^ {x} \mod p^{r+1}, x < p^{r}$ $$ \iff \underbrace{(c_r p^r + \cdots + c_1 p + 1)}_{c = y^q \mod p^{r+1}} = {\underbrace{(d_r p^r + \cdots + d_1 p + 1)}_{d = g^q \mod p^{r+1}}}^{x_{r-1} p^{r-1} + \cdots + x_1p + x_0} \mod p^{r+1} $$ $\implies c_1 = d_1x_0 \mod p$ Sau khi tìm lại được $x_0$, ta được như sau: $$y^q = (g^q)^x \mod p^{r+2} $$ $$y^q = (g^q)^{({x_{r} \ p^{r} + … + x_{1} \ p + x_{0}})} \mod p^{r+2}$$ $$(y \ g^{-x_{0}})^q = (g^q)^{p \ ({x_{r} \ p^{r} + … + x_{2} \ p + x_{1}})} \mod p^{r+2}$$ Và đặt $y’ = (y \ g^{-x_{0}})$ và $g’ = g^p$, tiếp tục tìm khi hoàn thiện được giá trị $x$. Đọc khó hiểu đúng không, giờ ta ví dụ nhé $p = 65537$ $x = 65537*7 + 123$ $K = 69^x \mod p^3$ $K ^ {p-1} = (69^{p-1})^x \mod p^3$ $38209*p^2 + 62417*p + 1 = (24572*p^2 + 49527*p + 1)^x \mod p^3$ $38209*p^2 + 62417*p + 1 \mod p^3$ $\iff 62417*p + 1 \mod p^2$ $(24572*p^2 + 49527*p + 1)^{x_1*p+x_0} \mod p^3$ $\iff (24572*p^2 + 49527*p + 1)^{x_1*p} \mod p^3$ $* (24572*p^2 + 49527*p + 1)^{x_0} \mod p^3$ $\iff (24572*p^2 + 49527*p + 1)^{x_0} \mod p^3$ $\iff (49527*p + 1)^{x_0} \mod p^2$ $38209*p^2 + 62417*p + 1 = (24572*p^2 + 49527*p + 1)^x \mod p^3$ $\implies 62417*p + 1 = (49527*p + 1)^{x_0} \mod p^2$ Giờ quay lại $p^2$ rồi, ta tiếp tục $$ 62417*p + 1 = 1 + 49527*p*x_0* \mod p^2$$ $$ 62417= 49527*x_0* \mod p$$ $$x_0 = 62417*(49527^{-1}) \mod p = 123$$ Từ đó, ta có được $$K = 69^{x_1*p + 123} \mod p^3$$ $$K^{p-1} = (69^{p-1})^{x_1*p + 123} \mod p^3$$ $$(K*69^{-123})^{p-1} = [(69^{p})^{p-1}]^{x_1} \mod p^3$$ Tiếp tục cho tới khi hoàn thành được $x$ Giờ ta quay lại với 2 phương trình kia đó là $$f_1(x) = (\sum_{i=1}^{10} k_i \ x^i) ^ {127} - c1 \mod \ n$$ $$f_2(x) = x^{65537} - c2 \mod \ n$$ Giờ ta chỉ cần tính gcd của 2 phương trình này là sẽ thu được flag thui hehehe. ```python from Crypto.Util.number import* from sage.all import* from chall import* def find_x(y,g,p,q,r): c = pow(y,q,p**r) d = pow(g,q,p**r) kx = (c-1)//(p**(r-1)) k = (d-1)//(p**(r-1)) x = kx*pow(k,-1,p) % p return x def find_dlog(y,g,p,q,r): xs = [] for i in range(r-1): xi = find_x(y,g,p,q,i+2) xs.append(xi) y = y * pow(g,-xi, p**r) g = pow(g,p,p**r) return xs def pgcd(g1, g2): while g2: g1, g2 = g2, g1 % g2 return g1.monic() p = rr q = rr - 1 rks = [] for rd in range(20): g = 69 y = ks[rd] r = rd + 2 x = find_dlog(y,g,p,q,r) real_x = 0 for i in range(len(x)): real_x += x[i]*(p**(i)) print("[+] rounds",rd, "check", pow(g,real_x,p**r) == y) rks.append(real_x) PR = PolynomialRing(Zmod(n), names='x') f1 = sum(k*PR.gen()**i for i, k in enumerate(rks))**((1 << 7) - 1) - c1 f2 = PR.gen()**(65537) - c2 f0 = pgcd(f1,f2) print(long_to_bytes(int(- f0.constant_coefficient() % n))) ``` **Flag: bi0sctf{https://www.youtube.com/watch?v=soDR-BctVeE___1e9c4e8dba79812bd81ec4c2}**