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