题目链接:
这道题整体逻辑就是:
它把你输入的flag来加密,加密完一个比较就行
总体没什么,就是这个加密是对我来说是新东西
不是很了解base64加密的,可以看看这篇文章:
(也是我写的,哈哈)
————————————————————————————
开局,查壳——无壳——32位
这些不用多说吧
这是个EXE可运行程序,运行看看呗 伙计们
好家伙,我输错了,然后终端就关闭了,就来一个
error! Are you happy! 服了
IDA伺候吧
f12就看见了这个东西
来到主函数
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // esi
int v5[3]; // [esp+8h] [ebp-74h] BYREF
__int16 v6; // [esp+14h] [ebp-68h]
char v7; // [esp+16h] [ebp-66h]
char v8[100]; // [esp+18h] [ebp-64h] BYREF
sub_403CF8(&unk_40E140);
scanf("%s", v8);
memset(v5, 0, sizeof(v5));
v6 = 0;
v7 = 0;
sub_401080(v8, strlen(v8), v5);
v3 = 0;
while ( *((_BYTE *)v5 + v3) == byte_40E0E4[v3] )
{
if ( ++v3 > strlen((const char *)v5) )
goto LABEL_6;
}
sub_403CF8(aError);
LABEL_6:
if ( v3 - 1 == strlen(byte_40E0E4) )
return sub_403CF8(aAreYouHappyYes);
else
return sub_403CF8(aAreYouHappyNo);
}
这一部分大家都理解了吧,毕竟前面都写了那么多题了
我们回去看
这个就是一个判断操作嘛,说明和这个Byte什么的要一样
我们去看看这个byte
这里他的格式比较乱,我们按一下A(对这个这个7ah)
就成了这种(IDA牛逼)
再看这一段(我改名成fun1了这个看着舒服)
int __cdecl fun1(int a1, int a2, int a3)
{
int v3; // edi
int v4; // esi
int v5; // edx
int v6; // eax
int v7; // ecx
int v8; // esi
int v9; // esi
int v10; // esi
int v11; // esi
_BYTE *v12; // ecx
int v13; // esi
int v15; // [esp+18h] [ebp+8h]
v3 = 0;
v4 = 0;
sub_401000();
v5 = a2 % 3;
v6 = a1;
v7 = a2 - a2 % 3;
v15 = a2 % 3;
if ( v7 > 0 )
{
do
{
LOBYTE(v5) = *(_BYTE *)(a1 + v3);
v3 += 3;
v8 = v4 + 1;
*(_BYTE *)(v8 + a3 - 1) = byte_40E0A0[(v5 >> 2) & 0x3F];
*(_BYTE *)(++v8 + a3 - 1) = byte_40E0A0[16 * (*(_BYTE *)(a1 + v3 - 3) & 3)
+ (((int)*(unsigned __int8 *)(a1 + v3 - 2) >> 4) & 0xF)];
*(_BYTE *)(++v8 + a3 - 1) = byte_40E0A0[4 * (*(_BYTE *)(a1 + v3 - 2) & 0xF)
+ (((int)*(unsigned __int8 *)(a1 + v3 - 1) >> 6) & 3)];
v5 = *(_BYTE *)(a1 + v3 - 1) & 0x3F;
v4 = v8 + 1;
*(_BYTE *)(v4 + a3 - 1) = byte_40E0A0[v5];
}
while ( v3 < v7 );
v5 = v15;
}
if ( v5 == 1 )
{
LOBYTE(v7) = *(_BYTE *)(v3 + a1);
v9 = v4 + 1;
*(_BYTE *)(v9 + a3 - 1) = byte_40E0A0[(v7 >> 2) & 0x3F];
v10 = v9 + 1;
*(_BYTE *)(v10 + a3 - 1) = byte_40E0A0[16 * (*(_BYTE *)(v3 + a1) & 3)];
*(_BYTE *)(v10 + a3) = 61;
LABEL_8:
v13 = v10 + 1;
*(_BYTE *)(v13 + a3) = 61;
v4 = v13 + 1;
goto LABEL_9;
}
if ( v5 == 2 )
{
v11 = v4 + 1;
*(_BYTE *)(v11 + a3 - 1) = byte_40E0A0[((int)*(unsigned __int8 *)(v3 + a1) >> 2) & 0x3F];
v12 = (_BYTE *)(v3 + a1 + 1);
LOBYTE(v6) = *v12;
v10 = v11 + 1;
*(_BYTE *)(v10 + a3 - 1) = byte_40E0A0[16 * (*(_BYTE *)(v3 + a1) & 3) + ((v6 >> 4) & 0xF)];
*(_BYTE *)(v10 + a3) = byte_40E0A0[4 * (*v12 & 0xF)];
goto LABEL_8;
}
LABEL_9:
*(_BYTE *)(v4 + a3) = 0;
return sub_401030(a3);
}
哎呀妈呀,这逼代码,真长
没办法,看看。
先看这个sub401
发现这个东西就是一个把一个字符串s里面的东西给换掉
我们跟进一些这个byte40e
同理 ,按A
乖宝宝,这不64加密表吗
这小子是对加密表进行更改了
好恶心啊(姿态版)
给他来个fun11的好名字
那下面这一坨就是base64加密了嘛
过
最后这还有个函数
看看先
int __cdecl sub_401030(const char *a1)
{
__int64 v1; // rax
char v2; // al
v1 = 0i64;
if ( strlen(a1) )
{
do
{
v2 = a1[HIDWORD(v1)];
if ( v2 < 97 || v2 > 122 )
{
if ( v2 < 65 || v2 > 90 )
goto LABEL_9;
LOBYTE(v1) = v2 + 32;
}
else
{
LOBYTE(v1) = v2 - 32;
}
a1[HIDWORD(v1)] = v1;
LABEL_9:
LODWORD(v1) = 0;
++HIDWORD(v1);
}
while ( HIDWORD(v1) < strlen(a1) );
}
return v1;
}
ok,兄弟们,这就是个大小写转换。
所以这个函数(fun1)有三个功能:
1.更换base64的base表
2.base64加密
3.大小写转换
那我们知道他转换后是
这个东西
那么直接来脚本
import base64
import string
string='zMXHz3TIgnxLxJhFAdtZn2fFk3lYCrtPC2l9'.swapcase()#大小写转换
tables64='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'#原来的base64表
newtable='ABCDEFQRSTUVWXYPGHIJKLMNOZabcdefghijklmnopqrstuvwxyz0123456789+/'#现在表
maketrans=str.maketrans(newtable,tables64)#不会,记住吧,铁子们
translate=string.translate(maketrans)
flag=base64.b64decode(string.translate(str.maketrans(newtable,tables64)))
print(flag)
最后输出:
最后的最后
【usualcrypt】https://www.bilibili.com/video/BV13S4y1N7Nk?vd_source=d489eb9dd6c53b7b147915e683943a6d
我是看的这个up主的视频,推荐给大家,这种宝藏up主很推荐。
然后我们可以用动态调试直接得到新的base表,视频里面也有讲
顺带一提 zMXH 就是fla的base64的转换哦~