LOADING

加载过慢请开启缓存 浏览器默认开启

2025ZJNUctf re-Writeup(无悬赏)

re1

nop一下

image-20250406124905889

改eip到image-20250406124933513

import re

# 输入文本(假设已经复制到剪贴板或保存在文件中)
text = """
Ooooooooookkkkkkkay, thank you for waiting me for such a long time, here are the 1th char of flag... Z
............................................................
Ooooooooookkkkkkkay, thank you for waiting me for such a long time, here are the 2th char of flag... J
............................................................
Ooooooooookkkkkkkay, thank you for waiting me for such a long time, here are the 3th char of flag... N
............................................................
Ooooooooookkkkkkkay, thank you for waiting me for such a long time, here are the 4th char of flag... U
。。。。。。。。。。。。。。。。。。。。。。。
............................................................
Ooooooooookkkkkkkay, thank you for waiting me for such a long time, here are the 113th char of flag... G
............................................................
Ooooooooookkkkkkkay, thank you for waiting me for such a long time, here are the 114th char of flag... }
............................................................
2025-04-06 12:37:28 [2] Closing connection from 127.0.0.1...
"""

# 使用正则表达式提取所有 flag 字符
pattern = r"here are the \d+th char of flag... (.)"
matches = re.findall(pattern, text)

# 拼接所有字符
flag = "".join(matches)

print("提取的 flag 是:")
print(flag)
#submit ZJNUCTF{wOw_y0u_ARE_tHe_7lme_maSTeR_@Nd_y0u_Wi1I_Kn0w_The_TrUTH_i_H#pE_yoU_GO7_7h1S_Fl4G_wI7h0Ut_wA1Tin6_7o0_L#nG}

re2

改了delta,记得转端序

#include <stdio.h>
#include <stdint.h>

void decrypt(uint32_t* v, uint32_t* k) {
    uint32_t v0 = v[0], v1 = v[1], sum = 0x11451419 *32, i;	//这里的sum是0x9e3779b9*32后截取32位的结果,截取很重要。//这里的数据类型可能会有符号,可以尝试改为int
    uint32_t delta = 0x11451419;
    uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
    for (i = 0; i < 32; i++) {
        v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
        v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
        sum -= delta;
    }
    v[0] = v0; v[1] = v1;
}

int main()
{
    uint32_t v[8] = { 0x25B0D6B1, 0xE4CC934B, 0xB088C228, 0x3B7C4A5F, 0x84C1227A, 0x28A3FF7C },
        k[4] = { 0x736E3161,0x6C65775F,0x656D6F63,0x756F795F };  //若有多组数据,可以每两个进行加密。
    
    for (int i = 0; i < 6; i += 2) {
        decrypt(&v[i], k);
    }
    for (int i = 0; i < 40; i++) {
        printf("%c", *((char*)v + i));
    }

    return 0;
}

re3

程序藏在脱壳代码中,而不是内部程序。

有花指令

image-20250407003724194

image-20250407003801649

push全面的全是花指令全部nop掉,下面有一段smc,data就是上面那段函数,注意只有132位,记得计算。

i =0
data[i++] ^= 0xcc
i>132 -->jmp

image-20250407004113037

解密后恢复函数

v10为我们的输入,从上面的start的rdi寄存器可以看出来

image-20250407004444280

加密逻辑

for ( j = 0LL; *(&word_9B1E + j) == ((((j ^ *(v10 + j) ^ 0x66) >> 4) | (16 * (j ^ *(v10 + j) ^ 0x66))) ^ 0x55); ++j )

解密脚本

#include<stdio.h>
#include<stdint.h>

int main()
{
    unsigned char data[] = {
    0x96, 0x87, 0xF7, 0x56, 0x47, 0x26, 0x37, 0xF4, 0xC6, 0x57, 0xE4, 0x76, 0x66, 0xD1, 0x84, 0x36,
    0x54, 0xE4, 0xF4, 0x46, 0x87, 0xB4, 0x04, 0xB7, 0xE5, 0xA7, 0x17, 0x77, 0x64, 0xD7, 0x27, 0xA6,
    0x66, 0xC5, 0xF7, 0x94, 0x84, 0xA7, 0xA5, 0xD5, 0x44, 0xA5, 0x77, 0xC7, 0x04, 0x67, 0xE3, 0xB6,
    0xC5, 0x64, 0x03, 0x46, 0x85, 0xF5, 0xA6, 0x15, 0x45, 0xC6, 0x56, 0x64, 0xB6, 0x37
    };
    for (int i = 0; i < 62; i++) {
        data[i] ^= 0x55;
        data[i] = (data[i] << 4) | (data[i] >> 4);
        data[i] ^= 0x66;
        data[i] ^= i;
        printf("%c", data[i]);
    }
}

re4

image-20250407004813580

第一处的逻辑

vqtbl1q_s8(*(int8x16_t *)&StringUTFChars_1[16 * i], t)对应汇编代码 TBL V0.16B, {V0.16B}, V1.16B;即以v1为索引,在表v0中查找值,放入v0中,这里是128位为一组进行操作,每次操作都是以byte为单位,逻辑大概是

for i in range(16):
        data[i] = input[table[i]
#逆
for i in range(16):
    res[table[i]] = data[i]

再对表进行异或修改,用修改后的表继续下一组操作,一共3组128位数据共48字节。一起的逻辑是

for j in range(3):
    for i in range(16):
        data[i + j*16] = input[table[i]+ j*16]
        table[i] ^= j

下面有个循环位移,后面还有个换表base64解密就行

#include<stdio.h>
#include<stdint.h>
#include"base64.h"
#include <string.h>

int main()
{
    int table[] = { 0xD, 0xE, 0xF, 0xC, 0xB, 0xA, 9, 8, 6, 7, 5, 4, 2 ,3, 1, 0 };
    //abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ3456780129+/
    unsigned char data[100] = "KJn0QBi+7Zba70HhyITl3Rv1c0K77QrGKIWWI08jStDTK1DLw1fPc1DNk1zRg09P";
    decodeBase64((char*)data, sizeof(data));
    //unsigned char data[] = { 0x92,0x33,0x7a,0xa9,0xb2,0x3e,0xe3,0x30,0x40,0xe3,0xa8,0x47,0x62,0x2b,0x4b,0xd2,0xb5,0x7b,0x0b,0xa9,0x38,0xe2,0xa4,0x60,0x92,0x2c,0x30,0x8b,0xae,0x49,0xb1,0x37,0x6d,0x93,0xb7,0x65,0x5b,0xb1,0x69,0x0b,0xb7,0x67,0x2b,0xb6,0x6b,0x1b,0xaf,0x69 };
    
    unsigned char mm[100],res[100];

    for (int j = 0; j <= 47; j += 3)
    {
        data[j] = ((unsigned __int8)data[j] << 5) | (data[j]>>3);
        data[j + 1] = ((unsigned __int8)data[j + 1] << 1) | (data[j + 1] >> 7);
        data[j + 2] = data[j + 2];
    }

    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 16; j++) {
            data[j+i*16] ^= table[j];
        }
        for (int j = 0; j < 16; j++) {
            res[table[j] + i * 16] = data[j + i * 16];
            table[j] ^= i;
        }
    }
}