2022-01-04

TetCTF——Crypto

Shares

在这里插入图片描述

Description: Yet another secret sharing scheme.
Service: nc 139.162.61.222 13371
Binary: https://drive.google.com/file/d/1sP0zKSKoF6TJZ-gtaUf7rv4dQ-bGr-cp/view?usp=sharing

用nc并没能拿到题目代码,不知道问题出哪了🐷一直显示链接超时
所以比完赛才拿到题目

"""
This is an (incomplete) implement for a new (and experimental) secret/password
sharing scheme.
The idea is simple. Basically, a secret or password is turned into a set of
finite field elements and each share is just a linear combination of these
elements. On the other hand, when enough shares are collected, the finite field
elements are determined, allowing the original secret or password to be
recovered.
"""
from typing import List
from secrets import randbelow
import string

ALLOWED_CHARS = string.ascii_lowercase + string.digits + "_"
P = len(ALLOWED_CHARS)
INT_TO_CHAR = {}
CHAR_TO_INT = {}
for _i, _c in enumerate(ALLOWED_CHARS):
    INT_TO_CHAR[_i] = _c
    CHAR_TO_INT[_c] = _i


def get_shares(password: str, n: int, t: int) -> List[str]:
    """
    Get password shares.
    Args:
        password: the password to be shared.
        n: the number of shares returned.
        t: the minimum number of shares needed to recover the password.
    Returns:
        the shares.
    """
    assert len(password) <= t
    assert n > 0

    ffes = [CHAR_TO_INT[c] for c in password]
    ffes += [randbelow(P) for _ in range(t - len(password))]
    result = []
    for _ in range(n):
        coeffs = [randbelow(P) for _ in range(len(ffes))]
        s = sum([x * y for x, y in zip(coeffs, ffes)]) % P
        coeffs.append(s)
        result.append("".join(INT_TO_CHAR[i] for i in coeffs))

    return result


def combine_shares(shares: List[str]) -> str:
    raise Exception("unimplemented")


def main():
    pw_len = 16
    password = "".join(INT_TO_CHAR[randbelow(P)] for _ in range(pw_len))

    # how about n < t :D
    n = 16
    t = 32

    for _ in range(2022):
        line = input()
        if line == password:
            from secret import FLAG
            print(FLAG)
            return
        else:
            print(get_shares(password, n, t))


if __name__ == '__main__':
    main()

考点依旧在

对整个程序的描述是:
这是一个新的(实验性的)秘密/密码共享方案的(不完整的)实现。
这个想法很简单。基本上,一个秘密或密码被转换成一组有限域元素,每个共享只是这些元素的线性组合。另一方面,当收集到足够多的共享时,确定有限字段元素,允许恢复原始的秘密或密码

对get_shares的描述是:
得到密码的shares.
参数:
password:共享用户的密码。
N:返回的shares数量。
T:找回密码所需的最小shares数量。
返回:shares。

读程序
从这里开始,char表示允许的 37 37 37个字符中的一个,而int表示 0 0 0 36 36 36之间的整数。
正如我们在源代码中看到的,一个1616个字符的密码 c 1 c 2 … c 16 c_1c_2\ldots c_{16} c1c2c16

一开始就确定了,我们的目标是猜测它。还可以获得20212021股get_shares(pwd),其中:
向密码追加 16 16 16个随机字符
P = c 1 c 2 … c 16 r 1 r 2 … r 16 P= c_1c_2\ldots c_{16}r_1r_2\ldots r_{16} P=c1c2c16r1r2r16
生成 ( Z / 37 Z ) 32 v (\mathbb{Z} / 37\mathbb{Z})^{32}v (Z/37Z)32v 16 16 16个32位的随机向量 v 1 , v 2 , l d o t s , v 16 v_1, v_2, ldots, v_{16} v1,v2,ldots,v16



参考代码

from pwn import *
from tqdm import tqdm

# local runs in 30 seconds, remote takes 20 minutes
r = remote('139.162.61.222', 13371)
# r = process('pypy3 shares.py', shell=True)

P = 37
CHARS = "abcdefghijklmnopqrstuvwxyz0123456789_1"
def INT_TO_CHAR(i): return CHARS[i]
def CHAR_TO_INT(c): return CHARS.index(c)


lhs, rhs = [], []
tq = tqdm(range(2000))
cnt = 0
for _ in tq:
    r.sendline(b'a')
    rv = eval(r.recvline())
    # Notice I keep the c1, c2, ..., c16 coefficients as vectors
    rv = [[CHAR_TO_INT(c) for c in r] for r in rv]
    cs = Matrix(GF(P), [r[16:32] for r in rv])
    # Singular?
    if cs.rank() < 16:
        rs = Matrix(GF(P), [r[:16] + [r[-1]] for r in rv])
        res = cs.augment(rs).rref()[-1]
        # first 16 columns are the v_{i, j}
        lhs.append(res[16:32])
        rhs.append(res[32])
        if len(lhs) == 16:
            break
    cnt += 1
    tq.set_description(f"{len(lhs)} / {cnt}")

# solve for password
ref = Matrix(GF(P), lhs).solve_right(vector(GF(P), rhs))
pwd = ''.join((INT_TO_CHAR(r) for r in ref))
r.sendline(pwd.encode())
print("Flag:", r.recvline().decode())


看人家的代码看好几天,虽然没都懂,而且时间过了差不多也不能访问了,但是还是有点收获的,比如: 我太菜了😥

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值