工具
IDA+虚拟机(kali)
思路展开
1.查壳,无壳,64位,放到虚拟机运行
灵魂三连问
2.iDA(64-bit)启动
先从下往上找,找关键比较,再从上往下,找用户输入与函数关系
找关键函数的原则:用户的输入变量,第一个过程判断输入符合条件,第二个过程实现算法(输入字符串+算法=结果字符串)
stringMod关键函数
__int64 __fastcall stringMod(__int64 *a1)
{
__int64 len; // r9
__int64 c_str; // r10
__int64 i; // rcx
signed int v4; // er8
int *temp_2; // rdi
int *temp_3; // rsi
signed int t; // ecx
signed int j; // er9
int g; // er10
unsigned int h; // eax
int sign; // esi
int v12; // esi
int temp[24]; // [rsp+0h] [rbp-60h]
memset(temp, 0, 0x48uLL);
len = a1[1];
if ( len )
{
c_str = *a1;
i = 0LL;
v4 = 0;
do
{
v12 = *(char *)(c_str + i);
temp[i] = v12; // temp=a1
if ( 3 * ((unsigned int)i / 3) == (_DWORD)i && v12 != firstchar[(unsigned int)i / 3] )// 当i是3的倍数时,str=first[i/3]
v4 = -1;
++i;
}
while ( i != len );
}
else
{
v4 = 0;
} // 将正确的a1赋值给temp
temp_2 = temp;
temp_3 = temp;
t = 666;
do
{ // 将temp里的每个字符与v7异或,v7变化
*temp_3 = t ^ *(unsigned __int8 *)temp_3;
t += t % 5;
++temp_3;
}
while ( &temp[18] != temp_3 );
j = 1;
g = 0;
h = 1;
sign = 0;
do
{
if ( sign == 2 )
{
if ( *temp_2 != thirdchar[g] ) // 2 5 8 11 15 17
v4 = -1;
if ( h % *temp_2 != masterArray[g] ) // 1 4 7 10 14 16
v4 = -1;
++g;
h = 1;
sign = 0;
}
else
{
h *= *temp_2;
if ( ++sign == 3 )
sign = 0;
}
++j;
++temp_2;
}
while ( j != 19 );
return (unsigned int)(t * v4);
}
看了一圈,函数分三层,第一层赋值操作,当i是3的倍数时,对字符有规定(确定0 3 6 9 12 15 18六个字符),第二层异或操作,异或的值变化,第三层对异或后的值循环,0 1 2 三个为一组
3.脚本
firstchar=[65, 105, 110, 69, 111, 97]
thirdchar=[751, 708, 732, 711, 734, 764]
masterArray=[471, 12, 580, 606, 147, 108 ]
t=[]
x=666
for i in range(18):
t.append(x)
x+=x%5
flag=[0 for i in range(18)]
index=0
for i in range(0,18,3):
flag[i]=firstchar[index] #0,3,6,9,12,15
index+=1
index=0
for i in range(2,18,3):
flag[i]=thirdchar[index]^t[i] #2 5,8,11,14,17
index+=1
index=0
for i in range(1,18,3):
for f in range(32,126): #常用可输入字符,符合条件的留下来
if (flag[i-1]^t[i-1])*(f^t[i])%(flag[i+1]^t[i+1])==masterArray[index]:
flag[i]=f
index+=1
break;
print('tuctf{'+''.join(map(chr,flag))+'}')
tuctf{AfricanOrEuropean?}