CISCN re 部分wp
glass
jeb打开,发现加密过程在so文件里面
ida看so文件
查看自己的加密函数
解密1
unsigned char flag[39]={ 0xA3, 0x1A, 0xE3, 0x69, 0x2F, 0xBB, 0x1A, 0x84, 0x65, 0xC2,
0xAD, 0xAD, 0x9E, 0x96, 0x05, 0x02, 0x1F, 0x8E, 0x36, 0x4F,
0xE1, 0xEB, 0xAF, 0xF0, 0xEA, 0xC4, 0xA8, 0x2D, 0x42, 0xC7,
0x6E, 0x3F, 0xB0, 0xD3, 0xCC, 0x78, 0xF9, 0x98, 0x3F,};
char key[]="12345678";
#include<stdio.h>
int main()
{
int i,j,k,a,b,c;
int len_key=8,len_flag=39;
unsigned char *p=flag;
for ( j = 0; j < len_flag; j += len_key )
{
for ( k = 0; (len_key & ~(len_key >> 31)) != k && j + k < len_flag; ++k )
p[k]^=key[k];
p += len_key;
}
for(i=0;i<len_flag;i+=3)
{
a = flag[i];
b = flag[i+1];
c = flag[i+2];
// flag[i] = a ^ c;
// flag[i+1] = b ^ a ^ c;
// flag[i+2] = c ^ b;
flag[i+1] = b ^ a;
flag[i+2]=flag[i+2] ^ flag[i+1];
flag[i] = flag[i]^flag[i+2];
}
for(i=0;i<39;i++)
{
printf("0x%02x,",flag[i]);
}
}
//0xf8,0xba,0x6a,0x97,0x47,0xca,0xe8,0x91,0xc5,0x07,0x6e,0xf7,0x92,0x0b,0x39,0x92,0x14,0xa8,0xaf,0x7e,0xaa,0x50,0x45,0x8d,0x6d,0x2d,0xb6,0x86,0x6e,0x9f,0x86,0x5e,0xdf,0xb3,0x1e,0x52,0xa6,0x62,0x6a
rc4解密,也可以动调出要异或的对应值,回头学学怎么动调so文件
#include<stdio.h>
#include<string.h>
typedef unsigned longULONG;
void rc4_init(unsigned char*s, unsigned char*key, unsigned long Len)
{
int i = 0, j = 0;
char k[256] = { 0 };
unsigned char tmp = 0;
for (i = 0; i<256; i++)
{
s[i] = i;
k[i] = key[i%Len];
}
for (i = 0; i<256; i++)
{
j = (j + s[i] + k[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}
void rc4_crypt(unsigned char*s, unsigned char*Data, unsigned long Len)
{
int i = 0, j = 0, t = 0;
unsigned long k = 0;
unsigned char tmp;
for (k = 0; k<Len; k++)
{
i = (i + 1) % 256;
j = (j + s[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
t = (s[i] + s[j]) % 256;
Data[k] ^= s[t];
}
}
int main()
{
unsigned char s[256] = { 0 }, s2[256] = { 0 };//S-box
char key[256] = { "12345678" };
char pData[512] = {0xf8, 0xba, 0x6a, 0x97, 0x47, 0xca, 0xe8, 0x91, 0xc5, 0x07, 0x6e, 0xf7, 0x92, 0x0b, 0x39, 0x92, 0x14, 0xa8, 0xaf, 0x7e, 0xaa, 0x50, 0x45, 0x8d, 0x6d, 0x2d, 0xb6, 0x86, 0x6e, 0x9f, 0x86, 0x5e, 0xdf, 0xb3, 0x1e, 0x52, 0xa6, 0x62, 0x6a};
unsigned long len = strlen(pData);
int i;
rc4_init(s, (unsigned char*)key, strlen(key));
for (i = 0; i<256; i++)
{
s2[i] = s[i];
}
rc4_crypt(s2, (unsigned char*)pData, len);
printf("pData=%s", pData);
return 0;
}
//CISCN{6654d84617f627c88846c172e0f4d46c}
baby_bc
bc文件为llvm字节码的二进制形式。
通过下面的指令转为elf
clang -S -fobj-arc xxx.bc -o xxx.s
clang xxx.s -o xxx
然后动调分析流程,发现是一个5*5的数独数组来作为flag,要满check里面的条件。
fill_number()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tx3NDpNx-1621353964787)(https://i.loli.net/2021/05/18/KqyRZPi4L1XMVsb.png)]
docheck(),这个函数就是限制函数,行列的数必须满足一些大小关系
__int64 docheck()
{
char v1; // [rsp+2Eh] [rbp-9Ah]
__int64 v2; // [rsp+30h] [rbp-98h]
__int64 v3; // [rsp+40h] [rbp-88h]
__int64 v4; // [rsp+50h] [rbp-78h]
__int64 v5; // [rsp+58h] [rbp-70h]
char *v6; // [rsp+68h] [rbp-60h]
__int64 v7; // [rsp+70h] [rbp-58h]
char v8; // [rsp+7Fh] [rbp-49h]
char *v9; // [rsp+88h] [rbp-40h]
__int64 v10; // [rsp+90h] [rbp-38h]
__int64 v11; // [rsp+98h] [rbp-30h]
__int64 v12; // [rsp+A8h] [rbp-20h]
char v13[6]; // [rsp+BCh] [rbp-Ch] BYREF
char v14[6]; // [rsp+C2h] [rbp-6h] BYREF
v12 = 0LL;
do
{
v10 = v12;
sub_401050(v14, 0LL, 6LL);
v9 = &v14[(unsigned __int8)map[5 * v12]];
if ( *v9
|| (*v9 = 1, v14[(unsigned __int8)map[5 * v12 + 1]])
|| (v14[(unsigned __int8)map[5 * v12 + 1]] = 1, v14[(unsigned __int8)map[5 * v12 + 2]])
|| (v14[(unsigned __int8)map[5 * v12 + 2]] = 1, v14[(unsigned __int8)map[5 * v12 + 3]])
|| (v14[(unsigned __int8)map[5 * v12 + 3]] = 1, v14[(unsigned __int8)map[5 * v12 + 4]]) )
{
v8 = 0;
return v8 & 1;
}
++v12;
}
while ( v10 + 1 < 5 );
v11 = 0LL;
while ( 1 )
{
v7 = v11;
sub_401050(v13, 0LL, 6LL);
v6 = &v13[(unsigned __int8)map[v11]];
if ( *v6 )
break;
*v6 = 1;
if ( v13[(unsigned __int8)byte_404055[v11]] )
break;
v13[(unsigned __int8)byte_404055[v11]] = 1;
if ( v13[(unsigned __int8)byte_40405A[v11]] )
break;
v13[(unsigned __int8)byte_40405A[v11]] = 1;
if ( v13[(unsigned __int8)byte_40405F[v11]] )
break;
v13[(unsigned __int8)byte_40405F[v11]] = 1;
if ( v13[(unsigned __int8)byte_404064[v11]] )
break;
++v11;
if ( v7 + 1 >= 5 )
{
v5 = 0LL;
while ( 1 )
{
v4 = v5;
if ( row[4 * v5] == 1 ) // v5=1 v5=4
{
if ( (unsigned __int8)map[5 * v5] < (unsigned __int8)map[5 * v5 + 1] )
goto LABEL_27;
}
else if ( row[4 * v5] == 2 && (unsigned __int8)map[5 * v5] > (unsigned __int8)map[5 * v5 + 1] )// v5=2
{
LABEL_27:
v8 = 0;
return v8 & 1;
}
if ( byte_404071[4 * v5] == 1 ) // no
{
if ( (unsigned __int8)map[5 * v5 + 1] < (unsigned __int8)map[5 * v5 + 2] )
goto LABEL_27;
}
else if ( byte_404071[4 * v5] == 2 && (unsigned __int8)map[5 * v5 + 1] > (unsigned __int8)map[5 * v5 + 2] )// no
{
goto LABEL_27;
}
if ( byte_404072[4 * v5] == 1 ) // v5=4
{
if ( (unsigned __int8)map[5 * v5 + 2] < (unsigned __int8)map[5 * v5 + 3] )
goto LABEL_27;
}
else if ( byte_404072[4 * v5] == 2 && (unsigned __int8)map[5 * v5 + 2] > (unsigned __int8)map[5 * v5 + 3] )// no
{
goto LABEL_27;
}
if ( byte_404073[4 * v5] == 1 ) // v5=2 v5=0
{
if ( (unsigned __int8)map[5 * v5 + 3] < (unsigned __int8)map[5 * v5 + 4] )
goto LABEL_27;
}
else if ( byte_404073[4 * v5] == 2 && (unsigned __int8)map[5 * v5 + 3] > (unsigned __int8)map[5 * v5 + 4] )// no
{
goto LABEL_27;
}
++v5;
if ( v4 + 1 >= 5 )
{
v3 = 0LL;
while ( 1 )
{
v2 = v3 + 1;
if ( col[5 * v3] == 1 ) // no
{
v1 = 0;
if ( (unsigned __int8)map[5 * v3] > (unsigned __int8)map[5 * v2] )
goto LABEL_26;
}
else if ( col[5 * v3] == 2 ) // no
{
v1 = 0;
if ( (unsigned __int8)map[5 * v3] < (unsigned __int8)map[5 * v2] )
{
LABEL_26:
v8 = v1;
return v8 & 1;
}
}
if ( byte_404091[5 * v3] == 1 ) // v3=3
{
v1 = 0;
if ( (unsigned __int8)map[5 * v3 + 1] > (unsigned __int8)map[5 * v2 + 1] )
goto LABEL_26;
}
else if ( byte_404091[5 * v3] == 2 )// no
{
v1 = 0;
if ( (unsigned __int8)map[5 * v3 + 1] < (unsigned __int8)map[5 * v2 + 1] )
goto LABEL_26;
}
if ( byte_404092[5 * v3] == 1 ) // no
{
v1 = 0;
if ( (unsigned __int8)map[5 * v3 + 2] > (unsigned __int8)map[5 * v2 + 2] )
goto LABEL_26;
}
else if ( byte_404092[5 * v3] == 2 )// v3=0 v2=1
{
v1 = 0;
if ( (unsigned __int8)map[5 * v3 + 2] < (unsigned __int8)map[5 * v2 + 2] )
goto LABEL_26;
}
if ( byte_404093[5 * v3] == 1 ) // v3=2
{
v1 = 0;
if ( (unsigned __int8)map[5 * v3 + 3] > (unsigned __int8)map[5 * v2 + 3] )
goto LABEL_26;
}
else if ( byte_404093[5 * v3] == 2 )// no
{
v1 = 0;
if ( (unsigned __int8)map[5 * v3 + 3] < (unsigned __int8)map[5 * v2 + 3] )
goto LABEL_26;
}
if ( byte_404094[5 * v3] == 1 ) // v3=3
{
v1 = 0;
if ( (unsigned __int8)map[5 * v3 + 4] > (unsigned __int8)map[5 * v2 + 4] )
goto LABEL_26;
}
else if ( byte_404094[5 * v3] == 2 )// v3=0
{
v1 = 0;
if ( (unsigned __int8)map[5 * v3 + 4] < (unsigned __int8)map[5 * v2 + 4] )
goto LABEL_26;
}
++v3;
v1 = 1;
if ( v2 >= 4 )
goto LABEL_26;
}
}
}
}
}
v8 = 0;
return v8 & 1;
}
分析前面的一部分应该是判断,每一行,每一列都是1~5构成,后面的if判断就是大小比较,我注释的v2,v3,v5的值可以找到5*5数独表中相应数字的位置,然后进行大小关系限制,no就代表这个if没什么用。
大概判断限定如下
用z3来解
from z3 import *
s = Solver()
flag=[0]*36
for i in range(25):
flag[i] = Int('flag['+str(i)+']')
for i in range(25):
s.add(flag[i]>=1)
s.add(flag[i]<=5)
s.add(flag[12]==4)
s.add(flag[18]==3)
s.add(flag[2]>flag[7])
s.add(flag[3]>flag[4])
s.add(flag[4]>flag[9])
s.add(flag[5]>flag[6])
s.add(flag[11]>flag[10])
s.add(flag[13]>flag[14])
s.add(flag[18]>flag[13])
s.add(flag[21]>flag[16])
s.add(flag[24]>flag[19])
s.add(flag[20]>flag[21])
for i in range(5):
s.add(flag[i * 5] != flag[i * 5 + 1])
s.add(flag[i * 5] != flag[i * 5 + 2])
s.add(flag[i * 5] != flag[i * 5 + 3])
s.add(flag[i * 5] != flag[i * 5 + 4])
s.add(flag[i * 5 + 1] != flag[i * 5 + 2])
s.add(flag[i * 5 + 1] != flag[i * 5 + 3])
s.add(flag[i * 5 + 1] != flag[i * 5 + 4])
s.add(flag[i * 5 + 2] != flag[i * 5 + 3])
s.add(flag[i * 5 + 2] != flag[i * 5 + 4])
s.add(flag[i * 5 + 3] != flag[i * 5 + 4])
i=0
for j in range(5):
s.add(flag[j] != flag[1 * 5 + j])
s.add(flag[j] != flag[2 * 5 + j])
s.add(flag[j] != flag[3 * 5 + j])
s.add(flag[j] != flag[4 * 5 + j])
s.add(flag[5 + j] != flag[4 * 5 + j])
s.add(flag[5 + j] != flag[3 * 5 + j])
s.add(flag[5 + j] != flag[4 * 5 + j])
s.add(flag[10 + j] != flag[3 * 5 + j])
s.add(flag[10 + j] != flag[4 * 5 + j])
s.add(flag[15 + j] != flag[4 * 5 + j])
if s.check() == sat:
model = s.model()
str = [model[flag[i]].as_long().real for i in range(25)]
for i in range(25):
print(str[i],end='')
else:
print("no_sat")
#CISCN{MD5(1425353142350212150442315)}
CISCN_gift
涉及到了没学过的知识点,后面学了来补