title: [ACTF新生赛2020]fungame
categories: CTF题解——reverse
[ACTF新生赛2020]fungame
-
这个题虽然不难,但出题思路清奇,写个题解
-
查壳,32位无壳,进IDA
-
F5main函数
int __cdecl main(int argc, const char **argv, const char **envp) { void *v4; // [esp+1Ch] [ebp-4h] __main(); v4 = malloc(0x14u); memset(v4, 0, 0x14u); memset(x, 0, 0x18u); sub_401340(v4); sub_4013BA((char *)v4); return 0; }
-
挨个看,第一个函数,有意思,简单异或,提取y2,y1,解密一下
int __cdecl sub_401340(int flag) { char i; // [esp+1Fh] [ebp-9h] printf("Please input:"); scanf("%s", flag); //输入第一段flag for ( i = 0; i <= 15; ++i ) { //异或加密 if ( (*(_BYTE *)(i + flag) ^ *((_BYTE *)y1 + i)) != y2[i] ) exit(0); } return 0; }
提取y1,y2解密flag:
# Re_1s_So0_funny!
提交了,假flag,再探,下一位函数
-
这个就有意思了,16位flag存进了12位的数组,搞溢出哇
int __cdecl sub_4013BA(char *flag) { //12位,溢出 char Destination[12]; // [esp+1Ch] [ebp-Ch] BYREF strcpy(Destination, flag); //传给des,溢出部分作为参数传递 strcpy(x, flag); //又复制一份给x,有问题 return 0; }
-
交叉引用查x
void __noreturn sub_40233D() { char Str2[13]; char Str1[16]; char Str[12]; size_t v3; printf("Please input again:"); strcpy(Str2, "YTFzMF9wV24="); //base64加密结果 memset(Str, 0, sizeof(Str)); memset(Str1, 0, sizeof(Str1)); scanf("%s", Str); //第二段输入 v3 = strlen(Str); sub_402421(Str, v3, Str1); //base64 if ( !strcmp(Str1, Str2) ) { printf("%s%s", x, Str); exit(0); } exit(0); }
-
sub_40233D就是对新的输入进行一个base64加密
-
但是这个函数是怎么被执行的,答案就是上面的溢出,通过溢出调用了这个函数40233D
-
所以真正的flag就是:
x + 溢出(注意大小端序问题) + str
-
解密脚本
#异或解密 list=[0x23,0x61,0x3e,0x69,0x54,0x41,0x18,0x4d,0x6e,0x3b,0x65,0x53,0x30,0x79,0x45,0x5b] list1=[0x71,0x4,0x61,0x58,0x27,0x1e,0x4b,0x22,0x5e,0x64,0x3,0x26,0x5e,0x17,0x3c,0x7a] for i in range(0,len(list)): list[i] = chr(list[i]^list1[i]) list = list[:12] #溢出 yichu = [0x3d,0x23,0x40] for i in yichu: list.append(chr(i)) list = ''.join(list) #base64 s="YTFzMF9wV24=" import base64 s = str(base64.b64decode(s),encoding='utf-8') print('flag{' + list + s + '}')
-
个人博客:woodenmandu.cn