fromECCimportCurve,Coordfromsecretsimportrandbelowflag="uctf{test_flag}"signatures={}valid_hosts={'uctf.ir'}a=0x0b=0x7p=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fGx=0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798Gy=0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ecc=Curve(a,b,p)G=Coord(Gx,Gy)assertecc.is_on_curve(G)forhostinvalid_hosts:d=randbelow(p)Q=ecc.sign(G,d)signatures[host]=[hex(Q.x),hex(Q.y)]print(signatures)print("Give me your generator and private key for verification process")data0=input("G(x,y) in hex format: ")data1=input("d in hex format: ")try:Coordinates=data0.split(',')PrivateKey=data1G1=Coord(int(Coordinates[0],16),int(Coordinates[1],16))d1=int(PrivateKey,16)exceptExceptionase:print('Wrong format! try again.')exit()ifnotecc.is_on_curve(G1):print('Point is not on the curve!')exit()ifd1<2:print("Security Issues Discovered!")exit()sig=ecc.sign(G1,d1)ifsig.x==int(signatures['uctf.ir'][0],16)andsig.y==int(signatures['uctf.ir'][1],16):print(f"Access granted. Here is your reward : {flag}".encode())else:print("Verficication process failed!")
اگر نگاهی به محتویات دو فایل داده شده کنیم متوجه می شویم که با Elliptic Curve Digital Signature Algorithm یا ECDSA سر و کار داریم.
در رمزنگاری، الگوریتم امضای دیجیتال منحنی بیضوی ECDSA گونه ای از الگوریتم امضای دیجیتال (DSA) را ارائه می دهد که از Elliptic Curve Cryptography استفاده می کند.
در این چالش، وظیفه ما بهرهبرداری از CVE-2020-0601 بود که به عنوان آسیبپذیری CurveBall شناخته میشود. این آسیبپذیری در CryptoAPI ویندوز Crypt32.dll وجود دارد و بر نحوه اعتبارسنجی گواهیهای رمزنگاری منحنی بیضوی ECC تأثیر میگذارد.
این نقص به مهاجم اجازه میدهد تا گواهیهای ECC را جعل کند، که میتواند منجر به حملات Man In The Middle (MITM) یا امکان امضای کدی شود که به نظر میرسد از طرف مراجع معتبر است. این آسیبپذیری عمدتاً بر سیستمهای ویندوز 10 و ویندوز سرور 2016/2019 تأثیر میگذارد.
خب بیاید با تعریف منحنی مورد نظر روی فیلد متناهی \mathbb{F}_p شروع کنیم (p,a,b,G,n):
خب بریم ببینیم که دقیقا این چالش چیکار میکنه و چه چیزی از ما میخواد!؟
توی فایل ECC.py کلاس های مربوط به Coord و Curve و عملیاتی که روی منحنی انجام میشه رو میبینیم.
توی فایل challenge.py در واقع در ابتدا مشخصات منحنی و generator رو میبینیم و در ادامه به ازای هر valid host اومده عملیات مربوط به امضا رو انجام داده و در دیکشنری signatures ذخیره کرده و بعدش میاد اونو چاپ میکنه.
در واقع میاد یک نقطه Q به این صورت تولید میکنه :
Q = kG
که k < p هست.
و اینکه از ما یک نقطه پایه G و یک عدد صحیح k میخواد که نتیجه ضرب اسکالرش برابر با متخصات امضایی باشه که خودش برای یک valid host تولید کرده یعنی Q.
اگه دقت کنید میبیند در واقع جایی چک نکرده که نقطه پایه ما همون G ای باشه که خودش اول کار تعریف کرده و این کارمون رو راحت میکنه.
در واقع میایم و یک عدد صحیح تصادفی مانند k' انتخاب میکنیم و معکوسشو نسبت به مرتبه منحنی حساب میکنیم و با استفاده از این عدد و امضایی که تولید شده یک نقطه پایه مثل G' تعریف میکنیم:
G' = [1/k']Q
خب خیلی پر واضح هست که اگر k' و نقطه G' رو به عنوان ورودی بدیم نتیجه نقطه Q خواهد بود.
solve.sage
1 2 3 4 5 6 7 8 91011121314151617181920
a=0x0b=0x7p=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fGx=0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798Gy=0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8# define elliptic curveE=EllipticCurve(GF(p),[a,b])# related signature Q=E("...","...")CG=Zmod(E.order())# k'kprime=CG.random_element()kprimeinv=kprime.inverse_of_unit()# G'Gprime=ZZ(kprimeinv)*Q