由于当天有事没参加,只能拿题看看了,觉得这道题很有意思。
稍微写写。
IDA打开,通过字符串定位到main函数
然后开始动调,到达红色位置出现了神奇的一幕,弹出的窗口不是Exception而是hook,挺有意思的,让后只能F7进去看看了。
hook技术类似于patch,将系统函数的调用执行流程给改掉了,这里似乎用的不是inline hook,用hook来隐藏代码也是绝了
F7
通过动态调试,可以看出来这里有个数组,将原来的大写变小写,小写变大写,点进去看,可以很容易看出这就是base64所用的表
然后代码就到了我们看到的MessageBox这了,但是后面那个注册VEH是干什么呢?继续向下分析。
发现出现了异常,访问了非法内存
所以,我们结合之前注册VEH就可以猜测是出题人故意这样弄得,Handler里肯定藏着不为人知的秘密。必进去看看
本来有个IF,被我patch掉了,问题不大,只是判断是不是由出题人故意设置的异常引起的
这里需要注意的是gen_key函数,看起来是生成密钥
一路点进去,发现这个东西咋这么像SM4?
去查SBox,发现就是Sm4加密
现在看得出那个16位tips数组就是密钥
现在回到Handler,发现里面调用了SetUnhandledExceptionFilter,显然又是和之前一样的套路
点进处理函数
compare最后就是比较Str1和Str2,这个很容易看到,Str2是存在程序数据里的,像是一串base64加密,现在去看看Str1,去查raw_data的交叉引用,发现这个就是输入的数据进行SM4加密
所以,至此逻辑就清楚了
输入->SM4(输入,key)->魔改的base64->前后交换顺序->与Str2比较
注意这里的Str2是经过相邻两个字符反转了的
还有这个base64也和***普通的base64不一样***:
1.base64的表大小写反转了,2.这里的索引index经过(index+24)%64了的
需要注意,下面是EXP
#include<cstdio>
#include<cstring>
using namespace std;
char Str2[]="1UTAOIkpyOSWGv/mOYFY4R!!";
char key[]="where_are_u_now?";
char flag[]={0x53,0x4D,0x34,0x66,0x6F,0x52,0x45,0x78,0x63,0x65,0x70,0x69,0x6F,0x4E,0x3F,0x21,0x0}; //经过SM4解密后的数据
// 输入->SM4(输入,key)->魔改的base64->前后交换顺序->与Str2比较
static const char base64[64] =
{
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F',
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/'
};
static const char _base64[64] = //原版表
{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/'
};
int getIndex(char c)
{
for(int i=0;i<64;i++)
if(base64[i]==c)
return i;
return -1;
}
char data[]={0xbb,0x56,0xad,0x8a,0x83,0xca,0xa1,0x8c,0x2c,0x56,0x03,0x3f,0xca,0x8c,0x9f,0xaf,0x0};
//base64解密后的数据,拿去SM4解密后就是flag
int main()
{
int v2=0;
char v5;
for(int i=0;;i+=2)
{
v2=strlen(Str2);
if(i>=v2)
break;
v5=Str2[i];
Str2[i]=Str2[i + 1];
Str2[i+1]=v5;
}
printf("Base64:");
for(int i=0;i<strlen(Str2);i++)
{
int index=getIndex(Str2[i]);
if(index-24<0)
index+=64;
if(Str2[i]=='!')
printf("=");
else
printf("%c",_base64[index-24]);
}
printf("\nKey:");
for(int i=0;i<=strlen(key);i++)
printf("%X",key[i]);
printf("\nFlag:");
for(int i=0;i<strlen(flag);i++)
printf("%c",flag[i]);
return 0;
}