发现关键函数
直接base64没解出来,题目说动态调试,就试一下
调试后再次进入,base表变了,试一下,还是不对,只好再仔细分析一下。
*a3 = 4 * ((len + 2) / 3); // 计算编码后的字符长度
v13 = malloc(*a3);
if ( !v13 )
return 0i64;
v15 = 0i64;
v14 = 0i64;
while ( v15 < len )
{
v4 = v15++;
v12 = *(unsigned __int8 *)(str + v4); // str[1]
if ( v15 >= len )
{
v6 = 0;
}
else
{
v5 = v15++;
v6 = *(unsigned __int8 *)(str + v5); // str[2]
}
v11 = v6;
if ( v15 >= len )
{
v8 = 0;
}
else
{
v7 = v15++;
v8 = *(unsigned __int8 *)(str + v7); // str[3]
}
v10 = (v11 << 8) + (v12 << 16) + v8; // v10=(str[2]<<8)+(str[1]<<16)+str[3]
// 数组中第 4 个字节左移 8 位,第 3 个字节左移 16 位,第 2 个字节左移 24 位,然后将它们相加,得到一个 24 位整数的值
v13[v14] = base64_table[v8 & 0x3F]; // &0x3f保留v8的低 6 位
v13[v14 + 1] = base64_table[(v10 >> 6) & 0x3F];
v13[v14 + 2] = base64_table[(v10 >> 12) & 0x3F];// 向右移动12位,从而将v10的第12位移动到第0位
// 得到了v10中第12到第23位(共 12 位)所代表的整数值
v9 = v14 + 3;
v14 += 4i64;
v13[v9] = base64_table[(v10 >> 18) & 0x3F]; // 变成4字节
if ( !setjmp(env) )
exception_handler();
}
if ( len % 3 == 1 )
{
v13[*a3 - 1] = '=';
}
else if ( len % 3 != 2 )
{
goto LABEL_18; // 不足3位补'='
}
v13[*a3 - 2] = '=';
LABEL_18:
v13[*a3] = 0;
return v13;
}
这3个字符取的位置跟正常的相反,没发现什么特别的,只好看wp了
还是看漏了 ,唉
每处理完3个字符后会进行exception_handler()
所以enc36个字符,有9个base表,调九次。
找到一个脚本的
from pwn import u32
from ctypes import *
clibc = cdll.LoadLibrary("msvcrt.dll")
enc = b'YkLYv1Xj23X7N0E5eoFgUveKeos1XS8K9r4g'
tab = b'+86420ywusqomkigecaYWUSQOMKIGECABDFHJLNPRTVXZbdfhjlnprtvxz13579/'
flag = b''
for i in range(0,len(enc),4):
v = [tab.index(enc[i+j]) for j in range(4)]
k3 = ((v[1]&3)<<6) + v[0]
k2 = ((v[2]&0xf)<<4) + (v[1]>>2)
k1 = (v[3]<<2)|(v[2]>>4)
flag += bytes([k1,k2,k3])
#change tab
seed = tab[0] #取第1个字符为种子
clibc.srand(seed)
ttab = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
v = [_ for _ in ttab]
for j in range(63,0,-1):
v3 = clibc.rand()
v[v3%(j+1)],v[j] = v[j],v[v3%(j+1)]
tab = bytes(v)
print(flag, tab)
print(flag)
#NSSCTF{Welc0me_T0_Re_World}
感谢[NSSCTF 2nd] NSS两周年纪念赛。_hint1 = (2019-2023*m) % mod-CSDN博客
不太会写,所以只能生撕,搞9次base64
得到flag