安洵杯 RE CrackMe的WP

由于当天有事没参加,只能拿题看看了,觉得这道题很有意思。
稍微写写。
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;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值