From c2de294d1c79ac1d3144113b79fbddf9bf0ebf78 Mon Sep 17 00:00:00 2001 From: sangge <2251250136@qq.com> Date: Sun, 15 Oct 2023 19:42:16 +0800 Subject: [PATCH] feat: finish xiaosai --- xiaosai/Claude_Shannon/crack.py | 46 ++++++ xiaosai/Claude_Shannon/crack.sage | 195 ++++++++++++++++++++++++++ xiaosai/Claude_Shannon/main_local.py | 57 ++++++++ xiaosai/Claude_Shannon/main_remote.py | 100 +++++++++++++ xiaosai/ecb_padding/crack.py | 37 +++++ xiaosai/ecb_padding/flag.py | 1 + xiaosai/ecb_padding/main.py | 73 ++++++++++ xiaosai/factor_2048bits/crack.py | 11 ++ xiaosai/factor_2048bits/flag.py | 1 + xiaosai/factor_2048bits/main.py | 19 +++ xiaosai/factor_n/crack.py | 14 ++ xiaosai/factor_n/flag.py | 1 + xiaosai/factor_n/main.py | 16 +++ 13 files changed, 571 insertions(+) create mode 100644 xiaosai/Claude_Shannon/crack.py create mode 100644 xiaosai/Claude_Shannon/crack.sage create mode 100644 xiaosai/Claude_Shannon/main_local.py create mode 100644 xiaosai/Claude_Shannon/main_remote.py create mode 100644 xiaosai/ecb_padding/crack.py create mode 100644 xiaosai/ecb_padding/flag.py create mode 100644 xiaosai/ecb_padding/main.py create mode 100644 xiaosai/factor_2048bits/crack.py create mode 100644 xiaosai/factor_2048bits/flag.py create mode 100644 xiaosai/factor_2048bits/main.py create mode 100644 xiaosai/factor_n/crack.py create mode 100644 xiaosai/factor_n/flag.py create mode 100644 xiaosai/factor_n/main.py diff --git a/xiaosai/Claude_Shannon/crack.py b/xiaosai/Claude_Shannon/crack.py new file mode 100644 index 0000000..819ead6 --- /dev/null +++ b/xiaosai/Claude_Shannon/crack.py @@ -0,0 +1,46 @@ +from pwn import * # type: ignore +# context.log_level = 'debug' + +""" +(这题小小的放了水) +因为只有一轮,而最终的答案有128种情况,那我们不妨直接猜一个答案 +根据条件概率公式算一下 + +for i in range(0,1000,100): + print(i,":", 1 - (127/128) ** i) + +0 : 0.0 +100 : 0.5435690025908804 +200 : 0.7916707446041162 +300 : 0.9049120701701576 +400 : 0.9565989213461966 +500 : 0.9801904023814129 +600 : 0.990958285600675 +700 : 0.9958730812784277 +800 : 0.9981163463716863 +900 : 0.9991402420956556 +大概300次以内都出结果了 +""" + + + +for i in range(300): + try: + r = remote("localhost", 10011) + # r = process(['python3', 'main.py']) + for i in range(15): + r.sendlineafter(b":", b"1") + r.recvuntil(b"!") + + r.sendlineafter(b"chests:", b"0 0 1 0 0 1 0") + r.recvline() + flag = r.recvline() + if b"flag" in flag: + end_time = time.time() + print(flag) + break + else: + r.close() + + except EOFError: + pass diff --git a/xiaosai/Claude_Shannon/crack.sage b/xiaosai/Claude_Shannon/crack.sage new file mode 100644 index 0000000..ba7ecb9 --- /dev/null +++ b/xiaosai/Claude_Shannon/crack.sage @@ -0,0 +1,195 @@ +""" +前置知识(建议要看,非常自信可以不看) +https://zhuanlan.zhihu.com/p/448198789 + +信息论的一些基础 +可以结合这份ppt来看 +https://web.xidian.edu.cn/jwliu/files/20190521_003040.pdf + +同时b站上的国防科技大学-信息论与编码基础也可以学习一下 +https://www.bilibili.com/video/BV1pJ411U7G8?p=61 + + +读题可知,我们需要获取一个7bit的有效信息,每次返回的信息可以看作1bit,共15bit。 +而其中1-2次的说谎我们可以视为1-2bit的传输错误。 +因此我们需要一种最少可以纠正2bit的编码,也就是循环冗余校验 + +根据题目描述,我们需要构造一个(15,7)循环码,也就是15bit的编码数,7bit的有效信息数 +""" +# 首先定义伽罗瓦域 +R. = PolynomialRing(GF(2)) + +""" +然后寻找生成元g +根据定理,(n,k)循环码的生成元g一定是x^n+1的n-k次因子 +(ppt中说是x^n-1,这里因为是GF(2),所以+1和-1是等价的) +带入计算得知,g应当为x^15+1的8次因子 +""" +ff = x^15+1 +g = factor(ff) +# (x + 1) * (x^2 + x + 1) * (x^4 + x + 1) * (x^4 + x^3 + 1) * (x^4 + x^3 + x^2 + x + 1) +factors = [] +for i in range(len(g)): + factors.append(g[i][0]) + +possible_g = [] + +# x + 2 * y + 4 * z == 8 +# root = [(8,0,0),(6,1,0),(4,2,0),(4,0,1),(2,3,0),(2,1,1),(0,4,0),(0,2,1),(0,0,2)] + + +possible_g.append(factors[0]^8) + +possible_g.append(factors[0]^6 * factors[1]) + +possible_g.append(factors[0]^4 * factors[1]^2) + +possible_g.append(factors[0]^4 * factors[2]) +possible_g.append(factors[0]^4 * factors[3]) +possible_g.append(factors[0]^4 * factors[4]) + +possible_g.append(factors[0]^2 * factors[1]^3) + +possible_g.append(factors[0]^2 * factors[1] * factors[2]) +possible_g.append(factors[0]^2 * factors[1] * factors[3]) +possible_g.append(factors[0]^2 * factors[1] * factors[4]) + +possible_g.append(factors[1]^4) + +possible_g.append(factors[1]^2 * factors[2]) +possible_g.append(factors[1]^2 * factors[3]) +possible_g.append(factors[1]^2 * factors[4]) + +possible_g.append(factors[2] * factors[2]) +possible_g.append(factors[2] * factors[3]) +possible_g.append(factors[2] * factors[4]) +possible_g.append(factors[3] * factors[3]) +possible_g.append(factors[3] * factors[4]) +possible_g.append(factors[4] * factors[4]) + +""" +至此我们已经找出所有的生成元了,但是不要忘了还有纠错的要求。 +纠正2bit的要求则是: 假设用d表示码组的最小汉明距离,纠正错误时,设可纠正t位的错误,则d >= 2t+1 +(也就是保证任一点A的错误状态不落到其余点B,并且A的错误状态离A更近) +带入公式则是d >= 5 +""" + +# 定义函数 n2p,将二进制数转换为多项式的形式 +def n2p(a): + a = bin(a)[2:] + p = 0 + for i in range(len(a)): + if a[len(a) - i - 1] == '1': + p += x^i + return p + +# 定义函数enc,将7bit的信息编码成循环码 +def enc(i): + m = n2p(i) + c = (x^8) * m + (((x^8) * m) % g) + return "".join([str(int(i in c.exponents())) for i in range(15)])[::-1] + +# 定义函数dif,计算ab之间的汉明距离 +def dif(a, b): + cnt = 0 + for i in range(len(a)): + if a[i] != b[i]: + cnt += 1 + return cnt + +""" +通过构造校验表来检查所有的生成元是否满足条件 +""" +for g in possible_g: + # 创建一个列表 dic,存储不同输入值的编码 + dic = [] + + for i in range(2**7): + dic.append(enc(i)) + + minHD = 15 + for i in dic: + for j in dic: + if i == j: + continue + if dif(i,j) <= minHD: + minHD = dif(i,j) + + #if minHD >= 5: + #print(g) + # x^8 + x^7 + x^6 + x^4 + 1 + # x^8 + x^4 + x^2 + x + 1 + + +# 下面两个随便挑一个作为生成元就好了 +# g = x^8 + x^7 + x^6 + x^4 + 1 +g = x^8 + x^4 + x^2 + x + 1 +dic = [] + +for i in range(2^7): + dic.append(enc(i)) + +""" +构造问题这个地方有点巧妙。 +我们可以发现系统码是一个对称互补的码,也就是说0和127,1和126的系统码每一位都相反。 + +那么对于所有系统码来说0和1就是平均分布的。(因为成对来看,30个bit中必有15bit的0和15bit的1) +对于系统码的任意一位为0的概率就是0.5,为1的概率也是0.5 + +因此我们可以把questions[i]和j[i]等价来看, +我们可以找出所有令j[i]==1的信息码情况,共64种,把这些进行or运算。 +把这个问题发送出去,如果返回true,那么证明j[i]就是1。 +以此类推,我们就可以得到一串15bit的返回值。 + +但是因为存在最多2bit的错误,我们需要跟码表进行对比,找出汉明距离小于等于2的系统码。 +然后这个系统码对应的信息码就是正确的信息码 +""" + +# 定义字符串模板 part,用于后面构造问题 +part = "( C0 == {} and C1 == {} and C2 == {} and C3 == {} and C4 == {} and C5 == {} and C6 == {} ) " + +# 创建问题列表 questions,用于存储构造的问题模板 +questions = [] +for i in range(15): + question = "" + nums = [j[:7] for j in dic if j[i] == '1'] + for j in range(64): + n = nums[j] + question += part.format(n[0], n[1], n[2], n[3], n[4], n[5], n[6]) + "or " + questions.append(question[:-4]) + + + +# 导入 pwn 模块,用于与远程或本地进程进行交互 +from pwn import * + +# 设置日志级别为 debug,以便在执行过程中输出详细日志信息 +#context.log_level = 'debug' + +r = process(['python3', 'main_local.py']) +#r = remote("localhost", "10011") + +for i in range(1): + msg = '' + # 逐个发送问题并接收答案 + for j in range(15): + r.sendlineafter(b"Shannon:", questions[j].encode()) + r.recvuntil(b"answers:") + if b'True' in r.recvuntil(b"!"): + msg += '1' + else: + msg += '0' + # 查找与收到的答案最接近的编码,这里答案肯定只会有一个 + for j in range(128): + if (dif(msg, dic[j]) <= 2): + break + ans = "" + for k in dic[j][:7]: + ans += k + " " + # 发送解码后的答案 + r.sendlineafter(b"chests:", ans.encode()) + +flag = r.recvall() +print(flag) +r.close() + diff --git a/xiaosai/Claude_Shannon/main_local.py b/xiaosai/Claude_Shannon/main_local.py new file mode 100644 index 0000000..6c0dd40 --- /dev/null +++ b/xiaosai/Claude_Shannon/main_local.py @@ -0,0 +1,57 @@ +from random import choice as c +from random import randint, shuffle +from Crypto.Util.number import * # type: ignore + +flag = b"flag{this_is_a_test_flag}" + +# 白名单列表,包含允许在问题中使用的关键词和符号 +white_list = ['==', '(', ')', 'C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', '0', '1', 'and', 'or', 'not'] + +# 定义一个函数 calc,用于计算问题的结果 +def calc(ans, chests, expr): + try: + C0, C1, C2, C3, C4, C5, C6 = chests + r = eval(expr) + except Exception as e: + print("Shannon fails to understand your words.\n", e) + exit(0) + return ans(r) + +# 定义一个游戏回合函数 do_round +def do_round(): + # 定义两个函数 truth 和 lie,用于判断 Shannon 的回答是否为真或假 + truth = lambda r: not not r + lie = lambda r: not r + chests = [] + for i in range(7): + # 随机生成 7 个 True 或 False,表示每个箱子是宝藏还是怪物 + chests.append(c((True, False))) + print("Seven chests lie here, with mimics or treasure hidden inside.\nBut don't worry. Trusty Shannon knows what to do.") + # 随机选择 Shannon 的回答策略,包括多少次 lie + lie_count = c((1, 2)) + Shannon = [truth] * (15 - lie_count) + [lie] * lie_count + # 猜猜第几次是在说谎 :-) + shuffle(Shannon) + for i in range(15): + print("Ask Shannon:") + question = input().strip() # 输入问题 + for word in question.split(" "): + if word not in white_list: # 检查问题中是否包含白名单以外的关键词或符号 + print("({}) No treasure for dirty hacker!".format(word)) + exit(0) + res = str(calc(Shannon[i], chests, question)) # 计算问题的结果 + print('Shannon answers: {}!\n'.format(res)) + print("Now open the chests:") + # 输入0或1表示每个宝箱的真假,用空格隔开 + chests_string = input() + return chests == list(map(int, chests_string.strip().split(" "))) + +# 游戏开始 +print("The Unbreakable Shannon has returned, with some suspicious chests and a far more complicated strategy -- he MAY LIE ONCE OR TWICE! Can you still get all the treasure without losing your head?") + +for i in range(50): + if not do_round(): # 执行游戏回合 + print("A chest suddenly comes alive and BITE YOUR HEAD OFF.\n") + exit(0) +print("You've found all the treasure! {}\n".format(flag)) # 赢得游戏,获得flag + diff --git a/xiaosai/Claude_Shannon/main_remote.py b/xiaosai/Claude_Shannon/main_remote.py new file mode 100644 index 0000000..1df6f16 --- /dev/null +++ b/xiaosai/Claude_Shannon/main_remote.py @@ -0,0 +1,100 @@ +from random import choice as c +from random import randint, shuffle +import socketserver +import signal +import string +import random +import os + +class Task(socketserver.BaseRequestHandler): + def _recvall(self): + BUFF_SIZE = 2048 + data = b'' + while True: + part = self.request.recv(BUFF_SIZE) + data += part + if len(part) < BUFF_SIZE: + break + return data.strip() + + def send(self, msg, newline=True): + try: + if newline: + msg += b'\n' + self.request.sendall(msg) + except: + pass + + def recv(self, prompt=b'[-] '): + self.send(prompt, newline=False) + return self._recvall() + + # 定义一个函数 calc,用于计算问题的结果 + def calc(self, ans, chests, expr): + try: + C0, C1, C2, C3, C4, C5, C6 = chests + r = eval(expr) + except Exception as e: + self.send(b"Shannon fails to understand your words.\n") + self.send(e) + exit(0) + return ans(r) + + # 定义一个游戏回合函数 do_round + def do_round(self): + # 定义两个函数 truth 和 lie,用于判断 Shannon 的回答是否为真或假 + truth = lambda r: not not r + lie = lambda r: not r + chests = [] + for i in range(7): + # 随机生成 7 个 True 或 False,表示每个箱子是宝藏还是怪物 + chests.append(c((True, False))) + self.send(b"Seven chests lie here, with mimics or treasure hidden inside.\nBut don't worry. Trusty Shannon knows what to do.") + # 随机选择 Shannon 的回答策略,包括多少次 lie + lie_count = c((1, 2)) + Shannon = [truth] * (15 - lie_count) + [lie] * lie_count + # 猜猜第几次是在说谎 :-) + shuffle(Shannon) + for i in range(15): + self.send(b"Ask Shannon:") + question = self.recv().decode().strip() # 输入问题 + for word in question.split(" "): + if word not in white_list: # 检查问题中是否包含白名单以外的关键词或符号 + self.send("({}) No treasure for dirty hacker!".format(word).encode()) + exit(0) + res = str(self.calc(Shannon[i], chests, question)) # 计算问题的结果 + self.send('Shannon answers: {}!\n'.format(res).encode()) + self.send(b"Now open the chests:") + # 输入0或1表示每个宝箱的真假,用空格隔开 + chests_string = self.recv().decode() + return chests == list(map(int, chests_string.strip().split(" "))) + + def handle(self): + signal.alarm(60) + + # 游戏开始 + self.send(b"The Unbreakable Shannon has returned, with some suspicious chests and a far more complicated strategy -- he MAY LIE ONCE OR TWICE! Can you still get all the treasure without losing your head?") + for i in range(50): + if not self.do_round(): # 执行游戏回合 + self.send(b"A chest suddenly comes alive and BITE YOUR HEAD OFF.\n") + return + self.send("You've found all the treasure! {}\n".format(flag).encode()) # 赢得游戏,获得flag + + +class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer): + pass + + +class ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer): + pass + + +if __name__ == "__main__": + flag = bytes(os.getenv("FLAG"),"utf-8") # type: ignore + # 白名单列表,包含允许在问题中使用的关键词和符号 + white_list = ['==', '(', ')', 'C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', '0', '1', 'and', 'or', 'not'] + HOST, PORT = '0.0.0.0', 10011 + server = ForkedServer((HOST, PORT), Task) + server.allow_reuse_address = True + print(HOST, PORT) + server.serve_forever() diff --git a/xiaosai/ecb_padding/crack.py b/xiaosai/ecb_padding/crack.py new file mode 100644 index 0000000..da72a61 --- /dev/null +++ b/xiaosai/ecb_padding/crack.py @@ -0,0 +1,37 @@ +from pwn import * +from flag import flag +from Crypto.Cipher import AES +from hashlib import sha256 +import base64 + +flag = b'' +first_flag = b'' +wordlist = b'123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM{}_' +for i in range(16): + for j in wordlist: + r = remote("127.0.0.1", 10002) + payload = b'0'*(16-5) + b'0' * (15 - i)\ + + first_flag + j.to_bytes() + \ + b'0' * (15 - i) + r.sendline(payload) + cipher = r.recvline() + cipher = base64.b64decode(cipher) + if cipher[16:32] == cipher[32:48]: + first_flag = first_flag + j.to_bytes() + break + +last_flag = b'' +for i in range(21-16): + for j in wordlist: + r = remote("127.0.0.1", 10002) + payload = b'0' * 11 + j.to_bytes() + \ + last_flag + b'0' * 27 + r.sendline(payload) + cipher = r.recvline() + cipher= base64.b64decode(cipher) + if cipher[16:32] == cipher[64:80]: + last_flag = j.to_bytes() + last_flag + break + + +print(first_flag + last_flag) \ No newline at end of file diff --git a/xiaosai/ecb_padding/flag.py b/xiaosai/ecb_padding/flag.py new file mode 100644 index 0000000..abfa7cd --- /dev/null +++ b/xiaosai/ecb_padding/flag.py @@ -0,0 +1 @@ +flag = b'flag{eCb_is_not_SafE}' \ No newline at end of file diff --git a/xiaosai/ecb_padding/main.py b/xiaosai/ecb_padding/main.py new file mode 100644 index 0000000..0869208 --- /dev/null +++ b/xiaosai/ecb_padding/main.py @@ -0,0 +1,73 @@ +from hashlib import sha256 +import socketserver +import signal +from flag import flag +from Crypto.Cipher import AES +import base64 + + + + +class Task(socketserver.BaseRequestHandler): + def _recvall(self): + BUFF_SIZE = 2048 + data = b'' + while True: + part = self.request.recv(BUFF_SIZE) + data += part + if len(part) < BUFF_SIZE: + break + return data.strip() + + def send(self, msg, newline=True): + try: + if newline: + msg += b'\n' + self.request.sendall(msg) + except: + pass + + def recv(self, prompt=b'[-] '): + self.send(prompt, newline=False) + return self._recvall() + + def task(self): + key = sha256(flag).digest() + key = key[:16] + aes = AES.new(key, AES.MODE_ECB) + data = self.recv(prompt=b'') + data = b'cqupt'+ data + flag + # len(flag) == 21 + # wordlist = b'123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM{}_' + if len(data)%16 != 0: + pad = b'0' * (16 - len(data)%16) + data = data + pad + cipher = aes.encrypt(data) + print(aes.decrypt(cipher)) + cipher = base64.b64encode(cipher) + self.send(cipher) + + + + def handle(self): + signal.alarm(60) + self.task() + + return + + +class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer): + pass + + +class ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer): + pass + + +if __name__ == "__main__": + #flag = bytes(os.getenv("FLAG"),"utf-8") + HOST, PORT = '0.0.0.0', 10002 + server = ForkedServer((HOST, PORT), Task) + server.allow_reuse_address = True + print(HOST, PORT) + server.serve_forever() \ No newline at end of file diff --git a/xiaosai/factor_2048bits/crack.py b/xiaosai/factor_2048bits/crack.py new file mode 100644 index 0000000..3f5da3a --- /dev/null +++ b/xiaosai/factor_2048bits/crack.py @@ -0,0 +1,11 @@ +from Crypto.Util.number import * + +p = 170021659067442061523756541191993539248601165314725269340063885026090819928194021233489114706002869522375199940625136026822330472394573193982550217044532146962203411567638298486561460035048451998397915884861905155825573014911356931131393751111816934458614898785910805905358218404703141056982153504282962094549 +q = 156289115230564684236869282390677373336412812898135298853785374595122098483952732832928286906302804608150589957073534308140034369315958525768786913022949461790625449368299077456798653080889386800523502656112132648850626018430482876211766660346216029055456596647573751654709671998718949348538504201995353414849 +n = p * q +cipher = 15315994859113745140937150782850225701835894977924847828178261709106790713756481438851906169833437205680746393379892960895453635059199072504132009117455118252801524117640663250753749247480223306967637814097656959416506419849108127590869410005001001319682678605925584319221815990695423909010895701674831442387195906671891136861712786777889185580869108974742614564867198257449323144696618681193168712805318310217437715668293800077584570491524233826384775049353844578873853868493454822838612576965182892687235411858595304846022012252673457313575555164210208501163855569260816910756715565420825070869972114502924134935227 +phi = (p - 1) * (q - 1) +e = 65537 +d = inverse(e, phi) +plaintext = pow(cipher, d, n) +print(long2str(plaintext)) \ No newline at end of file diff --git a/xiaosai/factor_2048bits/flag.py b/xiaosai/factor_2048bits/flag.py new file mode 100644 index 0000000..7389edc --- /dev/null +++ b/xiaosai/factor_2048bits/flag.py @@ -0,0 +1 @@ +flag = b'flag{W0W_you_cAn_factor_2048bits_prime}' \ No newline at end of file diff --git a/xiaosai/factor_2048bits/main.py b/xiaosai/factor_2048bits/main.py new file mode 100644 index 0000000..24f1d81 --- /dev/null +++ b/xiaosai/factor_2048bits/main.py @@ -0,0 +1,19 @@ +from flag import flag +from Crypto.Util.number import * + +# Is it possible to factor 2048 bits RSA???? + +p = getStrongPrime(1024) +q = getStrongPrime(1024) +n = p * q +e = 65537 +message = bytes_to_long(flag) +cipher = pow(message, e, n) +print(p) +print(q) +print('n = ', n) +print('cipher = ', cipher) +''' +n = 26572534665683235245636883276068606612246011683144885473463339711820331993493357279285848391008791322234296406608539840620252625886064149394162998948970494176467317183311068211754639508369506106626167584042532674048767021259563143175030276397301094824563794971045331643148544039656526615133318494601670688100830427083371422333448416345157657081894568628680132969792458721329931299527818220689347292610785587787837487603664368727957712489422350366840751269348100479824826707549651813948243868760028344290958809882314383956517334878930614926458454637703779278161529934602431923391507121553686269628353968327172758558101 +cipher = 15315994859113745140937150782850225701835894977924847828178261709106790713756481438851906169833437205680746393379892960895453635059199072504132009117455118252801524117640663250753749247480223306967637814097656959416506419849108127590869410005001001319682678605925584319221815990695423909010895701674831442387195906671891136861712786777889185580869108974742614564867198257449323144696618681193168712805318310217437715668293800077584570491524233826384775049353844578873853868493454822838612576965182892687235411858595304846022012252673457313575555164210208501163855569260816910756715565420825070869972114502924134935227 +''' \ No newline at end of file diff --git a/xiaosai/factor_n/crack.py b/xiaosai/factor_n/crack.py new file mode 100644 index 0000000..d066be9 --- /dev/null +++ b/xiaosai/factor_n/crack.py @@ -0,0 +1,14 @@ +import gmpy2 +from sympy import nextprime +from Crypto.Util.number import * +n = 119089874014927074688341672884508166875005676500322264758691717600758737133958853429775347698400246542956663932584349274109281162512900740554148968627493442686180696496512753102593837838697028745592258709705875168834908314583594102947493349091661801379830005354833653565157987808629144151353148601181998243399 +cipher = 117095409962662175082351896808794751507022710425611245694723238077959955609489552866653772250169627679450018400780468195080203740614508425379908667955368095074633690882446901510961333353751345467769557765781287285368700648236247094896521401160296460446518097963846290488354458277094831166588801569124630935182 +e = 65537 +root = gmpy2.iroot(n,2)[0] +q = nextprime(root) +print(n % q) +p = n // q +phi = (p - 1) * (q - 1) +d = inverse(e, phi) +plaintext = pow(cipher, d, n) +print(long2str(plaintext)) \ No newline at end of file diff --git a/xiaosai/factor_n/flag.py b/xiaosai/factor_n/flag.py new file mode 100644 index 0000000..d8e179f --- /dev/null +++ b/xiaosai/factor_n/flag.py @@ -0,0 +1 @@ +flag = b'flag{You_can_do_this}' \ No newline at end of file diff --git a/xiaosai/factor_n/main.py b/xiaosai/factor_n/main.py new file mode 100644 index 0000000..5281b70 --- /dev/null +++ b/xiaosai/factor_n/main.py @@ -0,0 +1,16 @@ +from flag import flag +from Crypto.Util.number import * +from sympy import nextprime + +p = getStrongPrime(512) +q = nextprime(p) +n = p * q +e = 65537 +message = bytes_to_long(flag) +cipher = pow(message, e, n) +print('n = ', n) +print('cipher = ', cipher) +''' +n = 119089874014927074688341672884508166875005676500322264758691717600758737133958853429775347698400246542956663932584349274109281162512900740554148968627493442686180696496512753102593837838697028745592258709705875168834908314583594102947493349091661801379830005354833653565157987808629144151353148601181998243399 +cipher = 117095409962662175082351896808794751507022710425611245694723238077959955609489552866653772250169627679450018400780468195080203740614508425379908667955368095074633690882446901510961333353751345467769557765781287285368700648236247094896521401160296460446518097963846290488354458277094831166588801569124630935182 +''' \ No newline at end of file