[buuctf]特殊的base64
首先查壳,发现是一个无壳的,64位的一个文件,那就直接拖入到ida中查看main函数,看到算法。
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rax
__int64 v4; // rax
std::string result; // [rsp+20h] [rbp-60h]
std::string rightFlag; // [rsp+30h] [rbp-50h]
std::string str; // [rsp+40h] [rbp-40h]
char v9; // [rsp+4Fh] [rbp-31h]
std::string v10; // [rsp+50h] [rbp-30h]
_main();
std::string::string(&str);
std::allocator<char>::allocator(&v9);
std::string::string(&rightFlag, "mTyqm7wjODkrNLcWl0eqO8K8gc1BPk1GNLgUpI==", &v9);
std::allocator<char>::~allocator(&v9);
v3 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "Please input your flag!!!!");
std::ostream::operator<<(v3, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
std::operator>><char,std::char_traits<char>,std::allocator<char>>(refptr__ZSt3cin, &str);
std::string::string(&v10, &str);
base64Encode(&result);
std::string::~string(&v10);
if ( std::operator==<char>(&result, &rightFlag) )
v4 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "The flag is right!!!!!!!!!");
else
v4 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "This is a wrong flag!!!!!!!!");
std::ostream::operator<<(v4, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
std::string::~string(&result);
std::string::~string(&rightFlag);
std::string::~string(&str);
return 0;
}
发现,特殊的base给了&rightFlag,之后跟&result比较,之后输出是否正确,那么直接进base64Encode看看编码是怎么编码的。
std::string __cdecl base64Encode(std::string *p_decode)
{
std::string *v1; // rdx
char *v2; // rax
int v3; // eax
int v4; // ebx
char *v5; // rax
int v6; // eax
int v7; // ebx
char *v8; // rax
int v9; // eax
_BYTE *v10; // rax
int v11; // eax
char *v12; // rax
int v13; // eax
_BYTE *v14; // rax
int v15; // eax
char *v16; // rax
int v17; // eax
int v18; // ebx
char *v19; // rax
int v20; // eax
_BYTE *v21; // rax
int v22; // eax
__int64 v24; // [rsp+0h] [rbp-80h]
char v25; // [rsp+2Fh] [rbp-51h]
int pos_0; // [rsp+30h] [rbp-50h]
int pos; // [rsp+34h] [rbp-4Ch]
int len; // [rsp+38h] [rbp-48h]
int i; // [rsp+3Ch] [rbp-44h]
std::string *p_encodeResult; // [rsp+60h] [rbp-20h]
std::string *p_decodea; // [rsp+68h] [rbp-18h]
p_encodeResult = p_decode;
p_decodea = v1;
std::allocator<char>::allocator((char *)&v24 + 47);
std::string::string(p_encodeResult, &unk_489084, &v25);
std::allocator<char>::~allocator(&v25);
len = std::string::length(p_decodea);
for ( i = 0; len / 3 > i; ++i )
{
v2 = (char *)std::string::operator[](p_decodea, 3 * i);
v3 = *(char *)std::string::operator[](&baseKey, *v2 >> 2);
std::string::operator+=(p_encodeResult);
v4 = 16 * (*(_BYTE *)std::string::operator[](p_decodea, 3 * i) & 3);
v5 = (char *)std::string::operator[](p_decodea, 3 * i + 1);
v6 = *(char *)std::string::operator[](&baseKey, v4 | (*v5 >> 4));
std::string::operator+=(p_encodeResult);
v7 = 4 * (*(_BYTE *)std::string::operator[](p_decodea, 3 * i + 1) & 0xF);
v8 = (char *)std::string::operator[](p_decodea, 3 * i + 2);
v9 = *(char *)std::string::operator[](&baseKey, v7 | (*v8 >> 6));
std::string::operator+=(p_encodeResult);
v10 = (_BYTE *)std::string::operator[](p_decodea, 3 * i + 2);
v11 = *(char *)std::string::operator[](&baseKey, *v10 & 0x3F);
std::string::operator+=(p_encodeResult);
}
if ( len % 3 == 1 )
{
pos = 3 * (len / 3);
v12 = (char *)std::string::operator[](p_decodea, 3 * (len / 3));
v13 = *(char *)std::string::operator[](&baseKey, *v12 >> 2);
std::string::operator+=(p_encodeResult);
v14 = (_BYTE *)std::string::operator[](p_decodea, pos);
v15 = *(char *)std::string::operator[](&baseKey, 16 * (*v14 & 3));
std::string::operator+=(p_encodeResult);
std::string::operator+=(p_encodeResult, "==");
}
if ( len % 3 == 2 )
{
pos_0 = 3 * (len / 3);
v16 = (char *)std::string::operator[](p_decodea, 3 * (len / 3));
v17 = *(char *)std::string::operator[](&baseKey, *v16 >> 2);
std::string::operator+=(p_encodeResult);
v18 = 16 * (*(_BYTE *)std::string::operator[](p_decodea, pos_0) & 3);
v19 = (char *)std::string::operator[](p_decodea, pos_0 + 1);
v20 = *(char *)std::string::operator[](&baseKey, v18 | (*v19 >> 4));
std::string::operator+=(p_encodeResult);
v21 = (_BYTE *)std::string::operator[](p_decodea, pos_0 + 1);
v22 = *(char *)std::string::operator[](&baseKey, 4 * (*v21 & 0xF));
std::string::operator+=(p_encodeResult);
std::string::operator+=(p_encodeResult, "=");
}
return (std::string)p_encodeResult;
}
发现,没有对于编码表的动作,咱们再去看看编码表,直接查找字符串。
.rdata:0000000000489090 aAabbccddeeffgg db 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0987654321/+',0
获得了一个编码,没有对于这个编码做什么,那么就直接替换编码表,来获得flag,直接写脚本即可。
import base64
str_1 = "mTyqm7wjODkrNLcWl0eqO8K8gc1BPk1GNLgUpI=="
str_base = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0987654321/+"
str_zh_base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
flag = base64.b64decode(str_1.translate(str.maketrans(str_base,str_zh_base)))
print(flag)#flag{Special_Base64_By_Lich}'
最后获得flag就是flag{Special_Base64_By_Lich}