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]