BaseCTF RE W3(c-c-c)

ezAndroid

用GDA打开,快速定位到MainActivity

关键部分在onConfirmButtonClick内

可以看到在按下按钮(存疑,我没跑)后,会从一个名字为flag的文件里读取flagBytes,再将输入的字符串用Base64encode方法加密后与其进行比较,若匹配则输出yess。

众所周知,apk本质上就是zip包

将其后缀修改为zip,可在其中的assets文件夹内找到flag文件

可以确认是hex数据,密文找到

接下来就是加密部分,使用cyberchef尝试后可以确认这里的”Base64encode“只是个幌子,实际上并不是base64

在zip内定位到该apk的so库,使用IDA进行分析

定位到Base64encode

这显然不是base64,再省去头尾一大段的地址操作,看do while循环内的加密部分

v5 = (*(__int64 (__fastcall **)(__int64, __int64))(*(_QWORD *)a1 + 0x558LL))(a1, a3);
 v6 = (*(__int64 (__fastcall **)(__int64, __int64, _QWORD))(*(_QWORD *)a1 + 0x5C0LL))(a1, a3, 0LL);
 v7 = operator new[](v5);
 v8 = (void *)v7;
 if ( v5 >= 1 )
{
   v9 = 0LL;
   v10 = (unsigned int)v5;
   v11 = (char *)v6;
   v12 = (_BYTE *)v7;
   v13 = (char *)&unk_E2D9;
   do
  {
     v14 = v9++;
     v15 = *v11++;
     --v10;
     v16 = v13[4294967284 * (v14 / 12)];
     ++v13;
     *v12++ = v16 ^ v15;
  }
   while ( v10 );
}

这里嗯看其实很难得看出来,直接凭直觉从异或开始分析比较容易,

*v12++ =v16^v15

一路往上推可以发现*v12最终指向v5,而v5操作地址,因此大概率是加密结果

同理v15可以猜测与明文有关,剩下v16。

v16是由从v13中元素按照索引每12个就回到开头来组成的,继续往上可以定位到&unk_E2D9

再rodata段找到unk_E2D9的内容,长度为12,侧面证明猜测

那么这就是密钥了

cyberchef一下即可解出

世界上最简单的题目

没什么可说的,把抽象变量名替换掉后看,就是一个简单的异或加密,添加了一个a1表。

题目:

# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
a1 =[1 ,1 ,1 ,3 ,1 ,1 ,1 ,3 ,1 ,1 ,1 ,3 ,1 ,1 ,3 ,1 ,1 ,3 ,1 ,1 ,3 ,1 ,3 ,1 ,3 ,1 ,3 ]#line:6
f1 =[101 ,102 ,117 ,120 ,119 ,108 ,102 ,124 ,100 ,109 ]#line:7
def o1 ():#line:13
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   return input ("please input your flag: ")#line:14
def p1 (O0O0OOOOO00OOOOO0 ):#line:20
   return list (O0O0OOOOO00OOOOO0 )#line:21
def main ():#line:27
   OO0O0O00O00O00OO0 =o1 ()#line:28
   O0OOOO0O0O0O0OOOO =1 #line:29
   # #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   O00OOO0OO0000OO00 =0 #line:30
   if len (OO0O0O00O00O00OO0 )!=len (f1 ):#line:36
       print ("Input length does not match.")#line:37
       exit ()#line:38
   OOO00OOO0000OO0O0 =p1 (OO0O0O00O00O00OO0 )#line:44
   # #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   for O0O0OOO00O000000O in range (len (a1 )):#line:50
       if a1 [O0O0OOO00O000000O ]==1 :#line:51
           OOO00OOO0000OO0O0 [O00OOO0OO0000OO00 ]=chr (ord (OOO00OOO0000OO0O0 [O00OOO0OO0000OO00 ])^O0OOOO0O0O0O0OOOO )#line:57
           O0OOOO0O0O0O0OOOO +=1 #line:58
       elif a1 [O0O0OOO00O000000O ]==3 :#line:59
           O00OOO0OO0000OO00 +=1 #line:60
   for O0OOOOOO000000OOO in range (len (f1 )):#line:66
       if f1 [O0OOOOOO000000OOO ]!=ord (OOO00OOO0000OO0O0 [O0OOOOOO000000OOO ]):#line:67
           print ("nooooo")#line:68
           # #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# #免费的50分,复制粘贴直接秒杀!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
           exit ()#line:69
   print ("yes, your flag is")#line:75
   print ("BaseCTF{"+''.join (OO0O0O00O00O00OO0 )+"}")#line:76
if __name__ =="__main__":#line:82
   main ()#line:83

exp(上):

#include<stdio.h>

int main()
{
int enc[10]={101 ,102 ,117 ,120 ,119 ,108 ,102 ,124 ,100 ,109};
for(int i=0;i<=9;i++)
{
printf("%c",enc[i]);
}
return 0;
}

我也不知道为什么我要用C++写一半换Python..大概是因为原题能直接用吧?

exp(下):


a1 =[1 ,1 ,1 ,3 ,1 ,1 ,1 ,3 ,1 ,1 ,1 ,3 ,1 ,1 ,3 ,1 ,1 ,3 ,1 ,1 ,3 ,1 ,3 ,1 ,3 ,1 ,3 ]#line:6
f1 =[101 ,102 ,117 ,120 ,119 ,108 ,102 ,124 ,100 ,109 ]
def o1 ():#line:13
   return input ("please input your flag: ")#line:14
def p1 (samp ):#line:20
   return list (samp )#line:21
def main ():#line:27
   src =o1 ()#line:28
   one =1 #line:29
   zero =0 #line:30
   ####长度检查##########
   if len (src )!=len (f1 ):#line:36
       print ("Input length does not match.")#line:37
       exit ()#line:38
   #########加密函数########
   enc =p1 (src )#line:44
   for i in range (len (a1 )):#line:50
       if a1 [i ]==1 :#line:51
           enc [zero ]=chr (ord (enc [zero ])^one )#line:57
           one +=1 #line:58
       elif a1 [i ]==3 :#line:59
           zero +=1 #line:60
   print(enc)
if __name__ =="__main__":#line:82
   main ()#line:83

密文转成字符串后直接输入即可获得flag

出题人已疯

.Net逆向

用dnSpy打开,快速定位到MainWindow

关键部分:

private void Btn_Submit_Click(object sender, RoutedEventArgs e)
{
char[] array = this.Tb_Input.Text.ToCharArray();
char[] array2 = string.Join("", this.sentences).ToCharArray();
for (int i = 0; i < array.Length; i++)
{
array[i] *= array[i];
array[i] = (char)((int)array[i] ^ i ^ (int)array2[i % array2.Length]);
}
uint[] source = new uint[]
{
24164U,
27173U,
32145U,
17867U,
40533U,
21647U,
17418U,
30032U,
27950U,
62998U,
60750U,
64870U,
52680U,
61797U,
49234U,
59762U,
16704U,
19200U,
32132U,
24038U,
21764U,
30130U,
28113U,
23070U,
27413U,
27917U,
28938U,
50207U,
64834U,
60132U,
64832U,
63334U,
55103U,
22176U,
21991U,
20073U,
22281U,
19476U,
28302U,
24336U,
24720U,
19544U,
23018U,
43976U
};
bool flag = new string(array) != new string((from c in source
select (char)c).ToArray<char>());
if (flag)
{
MessageBox.Show("\ud83d\ude2d我有异或症!");
}
else
{
MessageBox.Show("\ud83d\ude0b异或症好了!");
}
}
    // Token: 0x04000001 RID: 1
public string[] sentences = new string[]
{
"你以为我还会在乎吗?\ud83d\ude2c\ud83d\ude2c\ud83d\ude2c我在昆仑山练了六年的剑\ud83d\ude1f\ud83d\ude1f\ud83d\ude1f我的心早就和昆仑山的雪一样冷了\ud83d\ude10\ud83d\ude10\ud83d\ude10我在大润发杀了十年的鱼\ud83d\ude2b\ud83d\ude2b\ud83d\ude2b我以为我的心早已跟我的刀一样冷了\ud83d\ude29\ud83d\ude29\ud83d\ude29",
"我早上坐公交滴卡的时候和司机大叔说“两个人”,司机惊讶地看着我“你明明就是一个人,为什么要滴两个人的卡?”我回他,“我心中还有一个叫Kengwang的。”司机回我说,“天使是不用收钱的。”",
"(尖叫)(扭曲)(阴暗的爬行)(扭动)(阴暗地蠕动)(翻滚)(激烈地爬动)(痉挛)(嘶吼)(蠕动)(阴森的低吼)(爬行)(分裂)(走上岸)(扭曲的行走)(不分对象攻击)",
"地球没我照样转?硬撑罢了!地球没我照样转?硬撑罢了!地球没我照样转?硬撑罢了!地球没我照样转?硬撑罢了!地球没我照样转?硬撑罢了!地球没我照样转?硬撑罢了!",
"扭曲上勾拳!阴暗的下勾拳!尖叫左勾拳!右勾拳爬行!扭动扫堂腿!分裂回旋踢!这是蜘蛛阴暗的吃耳屎,这是龙卷风翻滚停车场!乌鸦痉挛!老鼠嘶吼!大象蠕动!愤怒的章鱼!无差别攻击!无差别攻击!无差别攻击!"
};

// Token: 0x04000002 RID: 2
public byte[] title = new byte[]
{
250,
81,
152,
152,
186,
78,
242,
93,
175,
117,
27,
103,
104,
84,
229,
119
};

// Token: 0x04000003 RID: 3
internal Label Lb_Title;

// Token: 0x04000004 RID: 4
internal TextBlock Tb_Description;

// Token: 0x04000005 RID: 5
internal TextBox Tb_Input;

// Token: 0x04000006 RID: 6
internal Button Btn_Submit;

// Token: 0x04000007 RID: 7
private bool _contentLoaded;
}

看逻辑很简单,就是从sentences中取索引为i取余其长度的元素与明文和i进行异或,再与source中进行比较,因此source即为密文,sentences即为key表,依次逻辑编写exp:

#include<bits/stdc++.h>

int main()
{
   uint32_t enc[44] = {
               24164U,
               27173U,
               32145U,
               17867U,
               40533U,
               21647U,
               17418U,
               30032U,
               27950U,
               62998U,
               60750U,
               64870U,
               52680U,
               61797U,
               49234U,
               59762U,
               16704U,
               19200U,
               32132U,
               24038U,
               21764U,
               30130U,
               28113U,
               23070U,
               27413U,
               27917U,
               28938U,
               50207U,
               64834U,
               60132U,
               64832U,
               63334U,
               55103U,
               22176U,
               21991U,
               20073U,
               22281U,
               19476U,
               28302U,
               24336U,
               24720U,
               19544U,
               23018U,
               43976U
  };
   long long int counter=0;
   unsigned char sentences[2000] ="你以为我还会在乎吗?😬😬😬我在昆仑山练了六年的剑😟😟😟我的心早就和昆仑山的雪一样冷了😐😐😐我在大润发杀了十年的鱼😫😫😫我以为我的心早已跟我的刀一样冷了😩😩😩我早上坐公交滴卡的时候和司机大叔说“两个人”,司机惊讶地看着我“你明明就是一个人,为什么要滴两个人的卡?”我回他,“我心中还有一个叫Kengwang的。”司机回我说,“天使是不用收钱的。”(尖叫)(扭曲)(阴暗的爬行)(扭动)(阴暗地蠕动)(翻滚)(激烈地爬动)(痉挛)(嘶吼)(蠕动)(阴森的低吼)(爬行)(分裂)(走上岸)(扭曲的行走)(不分对象攻击)地球没我照样转?硬撑罢了!地球没我照样转?硬撑罢了!地球没我照样转?硬撑罢了!地球没我照样转?硬撑罢了!地球没我照样转?硬撑罢了!地球没我照样转?硬撑罢了!扭曲上勾拳!阴暗的下勾拳!尖叫左勾拳!右勾拳爬行!扭动扫堂腿!分裂回旋踢!这是蜘蛛阴暗的吃耳屎,这是龙卷风翻滚停车场!乌鸦痉挛!老鼠嘶吼!大象蠕动!愤怒的章鱼!无差别攻击!无差别攻击!无差别攻击!";
   while (sentences[counter]!='\0') {
       counter++;
  }
   printf("%lld\n",counter);
   for(int i = 0; i < 44; i++)
  {
       enc[i] =char(int(enc[i])^ i ^ int(sentences[i % counter]));
      // enc[i]/=enc[i];
       printf("%c", enc[i]);
  }
   return 0;
}

不知道哪里出问题了,猜测是中文编码读入问题导致sentences索引&长度不对

Dont-Debug-Me

反调试,nop掉两处if即可

image-20240904055840953

![image-20240904060550695]