2024年NSSCTF秋季招新赛-Reverse
1633103148444167 发表于 四川 CTF 309浏览 · 2024-10-29 14:20

Reverse

又是签到!?

NSSCTF{mobile_is_so_easy}

怎么才能看见flag呢

NSSCTF{You_Can_Carry_This}

这也是py!?

v = [ord(i) for i in '~hojutfsfuoJ`pt`th^dcnbdsxAzESBRRM'][::-1]
for i in range(17):
    v[33 - i] -= 1
    v[i] += 1
print(bytes(v).decode())
# NSSCTF{Bytecode_is_so_Interesting}

不是,哥们,还有签到?

from ctypes import *

dll = cdll.LoadLibrary("./rand.dll")

csd = lambda x: dll.sd(x)
crd = lambda: dll.rd()

csd(0x1BF52)
v = [0x63, 0x5E, 0x4C, 0x5A, 0x52, 0x15, 0x4A, 0x5A, 0x0D, 0x16, 0x15, 0x12, 0x76, 0x7F, 0x01, 0x33, 0x2D, 0x35, 0x17, 0x7F, 0x61, 0x0F, 0x21, 0x64, 0x3C, 0x31, 0x01, 0x40, 0x20, 0x5C, 0x59,]
for i in range(len(v)):
    v[i] ^= (crd() % 100 + i)
print(bytes(v).decode())
# NSSCTF{Re_Is_Really_Too_Simple}

签到?

v = [0x00000020, 0x00000027, 0x00000026, 0x00000025, 0x0000002C, 0x0000002D, 0x0000000F, 0x00000022, 0x00000014, 0x0000001E, 0x00000021, 0x00000018, 0x00000009, 0x000000DF, 0x000000C8, 0x0000001C, 0x000000E7, 0x00000005, 0x000000E5, 0x000000E2, 0x000000EE, 0x0000001A, 0x000000E6, 0x00000004, 0x000000D9, 0x000000C9, 0x000000E3, 0x0000000A, 0x000000F5, 0x000000F1, 0x000000F8, 0x000000F3, 0x000000FA, 0x000000EA, 0x000000FF, 0x000000E7, 0x000000F5, 0x000000B9, 0x000000E4]
k = [0x00000068, 0x00000075, 0x00000075, 0x00000065, 0x00000072, 0x00000060,]
k = [(i^6) for i in k]
for i in range(len(v)):
    v[i] ^= (k[i%6] + i)
print(bytes(v).decode())
# NSSCTF{Xor_is_Incredibly_Entertaining!}

flower?

自己手搓即可

NSSCTF{T9is_F1ow5r_is_Very_Be4u6if9l}

好像也是py?

def simple_add_sub_reverse(text, shift=3):
    return ''.join(chr(ord(c) - shift) if c.isalpha() else c for c in text)


def case(text):
    return text.swapcase()


v = 'RGtAXV59UXtqTWVbUVd4aWs='
key = b'114514'
v = base64.b64decode(v.encode()).decode()
tmp = simple_add_sub_reverse(v)
tmp = case(tmp)
enc = [ord(i) for i in tmp]
for i in range(len(enc)):
    enc[i] ^= key[i % len(key)]
print(bytes(enc).decode())
# NSSCTF{PythoI_Js_so_Easy}

动态调试

两轮init,直接输入等长flag,改v2 -> v1即可,访问v1得到flag

NSSCTF{0d6f90ac-4b5e-4efb-8502-6349cf798f2e}

这来做点数学题吧

from z3 import *

v1 = [Int('v1[%d]' % i) for i in range(21)]
s = Solver()
s.add(v1[1] == 83,
 v1[4] + 32 * v1[3] + 43 * v1[2] + 81 * v1[0] + 35 * v1[5] == 14565
      , 23 * v1[4] + 13 * v1[5] + 78 * v1[6] == 12436
      , 19 * v1[15]
       + 10 * v1[14]
       + 17 * v1[13]
       + 15 * v1[12]
       + 12 * v1[10]
       + v1[9] / 4
       + v1[7]
       + 32 * v1[6]
       + 23 * v1[8]
       + 10 * v1[16] == 12539
      , 23 * v1[20]
       + 54 * v1[19]
       + 32 * v1[18]
       + 119 * v1[15]
       + 121 * v1[14]
       + 20 * v1[13]
       + 130 * v1[16]
       + 12 * v1[17]
       + 213 * v1[10] == 65168
      , 1412 * v1[12]
       + 139 * v1[16]
       + 199 * v1[7]
       + 324 * v1[14]
       + 165 * v1[12]
       + 19 * v1[11]
       + 193 * v1[6]
       + 144 * v1[5]
       + 143 * v1[20] == 267159
      , 867 * v1[13]
       + 654 * v1[11]
       + 678 * v1[9]
       + 175 * v1[7]
       + 45 * v1[5]
       + 21 * v1[1]
       + 13 * v1[3]
       + 100 * v1[15]
       + 24 * v1[17] == 244923
      , 54 * v1[12]
       + 55 * v1[20]
       + 119 * v1[17]
       + 121 * v1[16]
       + 20 * v1[3]
       + 130 * v1[18]
       + 12 * v1[19]
       + 213 * v1[12] == 69874
      , v1[7] == 90
      , v1[20] == 125
      , 233 * v1[10] + 134 * v1[2] + 378 * v1[4] + 133 * v1[9] + 178 * v1[6] + 443 * v1[5] + 11 * v1[1] + 543 * v1[11] == 188780
      , 194 * v1[16]
       + 643 * v1[15]
       + 131 * v1[14]
       + 131 * v1[12]
       + 21 * v1[13]
       + 204 * v1[17]
       + 24 * v1[18]
       + 214 * v1[19] == 151642
      , 123 * v1[18]
       + 25 * v1[16]
       + 124 * v1[13]
       + 37 * v1[14]
       + 7457 * v1[15]
       + 129 * v1[17]
       + 164 * v1[19]
       + 10 * v1[20] == 772291
      , 132 * v1[16]
       + 807 * v1[15]
       + 756 * v1[14]
       + 163 * v1[13]
       + 633 * v1[12]
       + 423 * v1[11]
       + 42 * v1[10]
       + 534 * v1[17] == 346862
      , 867 * v1[18]
       + 5956 * v1[13]
       + 204 * v1[12]
       + 374 * v1[10]
       + 47 * v1[9]
       + 485 * v1[15]
       + 37 * v1[16]
       + 375 * v1[20] == 740703
      , 37 * v1[12]
       + 35 * v1[19]
       + 856 * v1[18]
       + 375 * v1[17]
       + 3578 * v1[16]
       + 567 * v1[3]
       + 55 * v1[20]
       + 21 * v1[4] == 436075
      , 59 * v1[7] + 52 * v1[2] + 102 * v1[3] + 24 * v1[4] + 204 * v1[5] + 13 * v1[6] + 54 * v1[8] + 13 * v1[9] == 38344
      , 98 * v1[7] + 85 * v1[6] + 13 * v1[4] + 19 * v1[3] + 12 * v1[1] + 166 * v1[2] + 25 * v1[5] + 23 * v1[8] == 39337
      , 52 * v1[0] + 45 * v1[1] + 19 * v1[7] + 76 * v1[20] + 12 * v1[15] == 20141
      , 56 * v1[1] + 34 * v1[0] + 75 * v1[7] + 80 * v1[20] + 16 * v1[15] + 19 * v1[12] == 27375
      , 54 * v1[12] + 76 * v1[7] + 87 * v1[1] + 54 * v1[0] + 16 * v1[20] + 18 * v1[15] + 39 * v1[18] == 31598)

if s.check() == sat:
    m = s.model()
    for i in range(21):
        print(chr(m[v1[i]].as_long()), end='')
# NSSCTF{Z3_Is_So_Easy}

web

v = ''

KEY = 0x4c494e
flag = 'NSSCTF{'
k = (KEY >> 7) | (KEY << 5)
for i in range(len(v) // 16):
    num = int(v[i * 16:i * 16 + 16], 16)
    num ^= k
    num ^= KEY
    flag += libnum.n2s(num).decode()
print(flag)

Reverse_or_Pwn

v = [0x0000007A, 0x00000065, 0x00000077, 0x00000064, 0x0000005C, 0x00000026, 0x0000005F, 0x0000005D, 0x00000013, 0x00000024, 0x00000020, 0x00000032, 0x0000006C, 0x00000057, 0x00000032, 0x0000007B]
k = [0x0000002E, 0x0000000D, 0x0000001E, 0x00000017, 0x00000003, 0x0000004F, 0x0000002C, 0x00000002, 0x00000061, 0x00000041, 0x00000053, 0x00000057, 0x0000001E, 0x00000021, 0x00000057, 0x00000044]
for i in range(len(v)):
    v[i] ^= k[i]
print(bytes(v).decode())
# This_is_reserve?

这里有个知识点,This_is_reserve?长度为16 = 0xc+4,也就是说,在后边再次添加字符的话会修改返回地址,控制程序流走向,找到我们要返回的地址00402463,转为字符串则为c$@,结果没过,恼火

想想打栈溢出的时候出现栈平衡,向下挪一,00402464,转为字符串则为d$@,过了(32位栈平衡,没必要吧哥)

def fun(a, b):
    return (a + 0x1BF52 + 16 * b - 66) & 0xffffffff


for v9 in range(0xffffffff):
    v16 = v9 // 10000
    v15 = v9 % 10000 // 100
    v14 = v9 % 10000 % 100
    v13 = fun(5 * v15, 1)
    v12 = fun(v9, 11 * (v15 + v14 - 3))
    v11 = v12 - 16 * v16 + v14 * v13
    if (v12 & 1) != 0 or v13 <= 99 or v16 <= 999 or v15 <= 9 or v14 > 9 or (
            v12 - 16 * v16 + v14 * v13) & 0xffffffff != 21241824:
        continue
    else:
        print(v9)
        break
# 20241008
alp = [
    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
    '+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
    '6789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345',
    '0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
    'stuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr',
][::-1]


v = '+/1k6wlc+QFy5zN1+BVC3gVDKwx25zMd/CxU+glG4A925QVd+QRY4AQjBQF6+QFW+/J2GB5FASpuIvwb/Clu9AR1KwByCRRW/Qch+ANO+DM='
for i in range(len(alp)):
    model = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    v = (base64.b64decode(v.translate(str.maketrans(alp[i], model))).decode())
    print(v)
# Pwn_and_base_is_so_Easy!

NSSCTF{This_is_reserve?d$@Pwn_and_base_is_so_Easy!}

NSS茶馆!

from ctypes import *
from libnum import *


def decrypt(v, k):
    v0 = c_uint32(v[0])
    v1 = c_uint32(v[1])
    delta = 0x114514
    sum1 = c_uint32(delta * 33)
    for i in range(33):
        v1.value -= ((v0.value << 4) + k[2]) ^ (v0.value + sum1.value) ^ ((v0.value >> 5) + k[3])
        v0.value -= ((v1.value << 4) + k[0]) ^ (v1.value + sum1.value) ^ ((v1.value >> 5) + k[1])
        sum1.value -= delta
    return v0.value, v1.value


flag = []

enc = [0x3A26D265, 0x81D9A0B6, 0x0E5E002A, 0x3907EFE5, 0x71B6BC57, 0xE0AC0DA2]
key = [0x0000000B, 0x00000016, 0x00000021, 0x0000002C]
for i in range(len(enc)//2):
    res = decrypt(enc[i * 2:i * 2 + 2], key)
    for j in res:
        flag += n2s(j).decode()
print(''.join(flag))
print()
# NSSCTF{tea_is_so_easy!!}

md5也能爆破?

这道题主要实现了分块md5(改)加密,除了第一次是正常的md5加密外,其他会因为参数a1的值而改变

我的第一想法是使用idapython实现爆破过程

由于第一块是没有改的,也就是正常的md5加密,那么就可以通过md5解密得到结果

'7fb8ceb3bd59c7956b1df66729296a4c' : 1485

# 基于运行了一次,也就是已经过了第一块加密 :1485
ansflag = ''
# 保留上一次加密所用的参数
ea = 0x001A5A00
ori = [get_wide_byte(ea+i) for i in range(24)]

# 开始尝试
part_add = ea + 0x18
for i in string.printable:
    patch_byte(part_add,ord(i))
    for ii in string.printable:
        patch_byte(part_add+1,ord(ii))
        for iii in string.printable:
            patch_byte(part_add+2,ord(iii))
            for iiii in string.printable:
                patch_byte(part_add+3,ord(iiii))

                # 模拟F8
                step_over()

                # 获取加密后的结果32字符
                ans_add = 0x001A5944
                ans = [get_wide_byte(ans_add+i) for i in range(16)]
                flag = ''
                for i in ans:
                    tmp = hex(i)[2:].zfill(2)
                    flag += tmp
                # print(flag)

                # 比较结果
                v = [
                    '7fb8ceb3bd59c7956b1df66729296a4c',
                    'f182395ed4eaa34bf53fa0507e124c28',
                    '1c2aaf4995574c11dbd2c79024d7df08',
                    'd5945e772e2715ae12ff75818fb0477e',
                    'c3c3dab8e8f8eda9c62ae676cff5b6b9',
                    '75cd9e91d1f4ad1bf88a964f69078d93',
                    '7bc0d87c4ee78bafa9fea6aba4215b89',
                    'c68bfbb9f793b6eeee2b985ffce1e634',
                    '344d233437cc2ff5f6d9f363ca54d81b',
                    'df8b095635311f27e22110085eaff244',
                ]

                if flag in v:
                    # 获取正确的密文
                    for i in range(4):
                        ansflag += chr(get_wide_byte(part_add+i))
                    # 程序运行直到下一次断点 模拟F9
                    continue_process()
                else:
                    # 控制EIP回到加密程序
                    EIP = 0x00198A17
                    set_reg_value(EIP,"EIP")

                    # 还原上一次匹配成功的参数
                    for i in range(24):
                        patch_byte(ea+i,ori[i])

可惜可能是由于IDA的问题,这个方法实现不了,每一次输出的值都是上一次成功的值,不知道是哪里的问题。

将输出错误的提示,改成输出结果

直接实现爆破脚本

v = [
    '7fb8ceb3bd59c7956b1df66729296a4c',
    'f182395ed4eaa34bf53fa0507e124c28',
    '1c2aaf4995574c11dbd2c79024d7df08',
    'd5945e772e2715ae12ff75818fb0477e',
    'c3c3dab8e8f8eda9c62ae676cff5b6b9',
    '75cd9e91d1f4ad1bf88a964f69078d93',
    '7bc0d87c4ee78bafa9fea6aba4215b89',
    'c68bfbb9f793b6eeee2b985ffce1e634',
    '344d233437cc2ff5f6d9f363ca54d81b',
    'df8b095635311f27e22110085eaff244',
]

input_data = "1485{tuFnYbckFWarUpPYUdXGlhOOIaPMeVsxKQ}"
num_segments = len(input_data) // 4
flag = '1485'
for i in range(1, num_segments):

    for chars in itertools.product(string.digits, repeat=4):
        modified_data = (input_data[:i * 4] + ''.join(chars) + input_data[(i + 1) * 4:])

        exe_file_path = r""  #File directory

        process = subprocess.Popen(
            exe_file_path,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True
        )

        stdout, stderr = process.communicate(input=modified_data)

        flag_prompt = "plz input your flag:"
        output_after_flag_prompt = stdout.split(flag_prompt, 1)[-1].strip() if flag_prompt in stdout else ""

        ans = output_after_flag_prompt[i * 32:(i + 1) * 32]
        if v[i] == ans:
            flag += ''.join(chars)
            print(f"[!] Updated flag: {flag}")
            input_data = modified_data
            break
        else:
            continue
# 1485059684930231436754585566745634684261
0 条评论
某人
表情
可输入 255