[FlareOn4]IgniteMe
逆向题吗老规矩先查壳查壳后发现无壳是32位程序
打开ida查看分析一波f5反编译后是这玩意我也没看明白啥写的
然后打开sub_401050函数看一看哦原来是要用到动调,因为是exe文件所以是本地Windows进行调试,如果是elf文件则需要在虚拟机用gdb调试或者远程调试,动调完发现v4是4
然后得出v4的值了在进行下一步解密操作,就是获取完字符串的长度然后在进行数组倒序,紧跟着是异或,但要注意异或这里是与最后一位进行的异或,最后再进行一个数组比较操作,分析完后直接上脚本解flag,这里脚本是写着写着卡壳了没搞粗来网上找的
byte_403000=[0x0D,0x26,0x49, 0x45, 0x2A, 0x17, 0x78, 0x44, 0x2B, 0x6C, 0x5D,0x5E, 0x45, 0x12, 0x2F, 0x17, 0x2B, 0x44, 0x6F, 0x6E, 0x56, 0x9,0x5F, 0x45, 0x47, 0x73, 0x26, 0x0A, 0x0D, 0x13, 0x17, 0x48, 0x42,0x1, 0x40, 0x4D, 0x0C, 0x2, 0x69, 0x0]
flag=""
L=len(byte_403000)-1
for i in range(len(byte_403000)):
if i==0:
byte_403000[L-i]= byte_403000[L-i]^0x4
byte_403000[L-i-1] = byte_403000[L-i-1]^byte_403000[L-i]
flag+=chr(byte_403000[L-i])
print(byte_403000)
print(flag[::-1])
运行结果为
flag为:flag{R_y0u_H0t_3n0ugH_t0_1gn1t3@flare-on.com}
[GWCTF 2019]xxor
还是查壳先发现无壳是64位程序,因为用不着动调所以ida64也可以做
打开ida64后直接反编译查看主函数
看着这么多看着也不想看,但还是要大致分析一波,确定加密函数分别为sub_400770函数和sub_400686函数,大致就是一个z3方程组解密和异或操作解密,首先看sub_400770函数,他就是用z3方程组解密
这里可以直接通过python脚本的z3约束法进行解密,脚本如下
from z3 import *
a1,a2,a3,a4,a5,a6=Ints('a1 a2 a3 a4 a5 a6')
s = Solver()
s.add(a3-a4==2225223423)
s.add(a4+a5==4201428739)
s.add(a3-a5==1121399208)
s.add(a1==-548868226)
s.add(a6==-2064448480)
s.add(a2==550153460)
if(s.check()==sat):
print(s.model())
else:
print("false")
解密的结果为
[a3 = 3774025685,
a2 = 550153460,
a6 = -2064448480,
a1 = -548868226,
a4 = 1548802262,
a5 = 2652626477]
解出来后再查看sub_400686函数
大致就是里面涉及一个a2,传进去的data3是数据,然后在根据z3方程组求解的结果进行异或操作来编写解密脚本一番操作后得知a2数组的值是2,2,3,4,然后最后用c编写脚本如下:
#include <stdio.h>
int main()
{
int a1[6] = { 3746099070,550153460,3774025685,1548802262,2652626477,2230518816 };
unsigned int a2[4] = { 2,2,3,4 };
unsigned int v3;
unsigned int v4;
int v5;
for (unsigned int j = 0; j < 5; j += 2)
{
v3 = a1[j];
v4 = a1[j + 1];
v5 = 1166789954 * 64;
for (unsigned int i = 0; i < 64; i++)
{
v4 -= (v3 + v5 + 20) ^ ((v3 << 6) + a2[2]) ^ ((v3 >> 9) + a2[3]) ^ 0x10;
v3 -= (v4 + v5 + 11) ^ ((v4 << 6) + *a2) ^ ((v4 >> 9) + a2[1]) ^ 0x20;
v5 -= 1166789954;
}
a1[j] = v3;
a1[j + 1] = v4;
}
for (unsigned int i = 0; i < 6; i++)
printf("%c%c%c", *((char*)&a1[i] + 2), *((char*)&a1[i] + 1), *(char*)&a1[i]);
}
最后运行结果得到flag为:flag{re_is_great!}
[WUSTCTF2020]Cr0ssfun
查壳发现无壳且是64位程序,直接用对应ida打开,发现程序在进行一个比较后结束,所以关键在于check函数,反编译的主函数
然后接下来重点便是check函数,发现是数组的所有值,所以推测将其汇总进行输出发现思路正确,而数组值如图
最后编写脚本如下
#include<stdio.h>
int main()
{
int a1[50]={0};
int i;
a1[10] =112;
a1[13]=64;
a1[3]=102;
a1[26]=114;
a1[20]=101;
a1[7]=48;
a1[16]=95;
a1[11]=112;
a1[23]=101;
a1[30]=117;
a1[0]=119;
a1[6]=50;
a1[22]=115;
a1[31]=110;
a1[12]=95;
a1[15]=100;
a1[8]=123;
a1[18]=51;
a1[28]=95;
a1[21]=114;
a1[2]=116;
a1[9]=99;
a1[32]=125;
a1[19]=118;
a1[5]=48;
a1[14]=110;
a1[4]=50;
a1[17]=114;
a1[29]=102;
a1[17]=114;
a1[24]=95;
a1[1]=99;
a1[25]=64;
a1[27]=101;
for(i=0;i<50&&a1[i]!=0;i++)
printf("%c",a1[i]);
}
运行结果为
flag为:flag{cpp_@nd_r3verse_@re_fun}
[FlareOn6]Overlong
例行查壳发现无壳是32位程序
运行了一下也啥也没有然后直接拖ida看吧
可以看出来加密函数为sub_401160函数,加密长度为28,然后打开此函数进一步查看
unsigned int __cdecl sub_401160(char *a1, int a2, unsigned int a3)
{
unsigned int i; // [esp+4h] [ebp-4h]
for ( i = 0; i < a3; ++i )
{
a2 += sub_401000(a1, a2);
if ( !*a1++ )
break;
}
return i;
}
int __cdecl sub_401000(_BYTE *a1, char *a2)
{
int v3; // [esp+0h] [ebp-8h]
char v4; // [esp+4h] [ebp-4h]
if ( (int)(unsigned __int8)*a2 >> 3 == 30 )
{
v4 = a2[3] & 0x3F | ((a2[2] & 0x3F) << 6);
v3 = 4;
}
else if ( (int)(unsigned __int8)*a2 >> 4 == 14 )
{
v4 = a2[2] & 0x3F | ((a2[1] & 0x3F) << 6);
v3 = 3;
}
else if ( (int)(unsigned __int8)*a2 >> 5 == 6 )
{
v4 = a2[1] & 0x3F | ((*a2 & 0x1F) << 6);
v3 = 2;
}
else
{
v4 = *a2;
v3 = 1;
}
*a1 = v4;
return v3;
}
这里直接找到对应源字符串地址然后加密,原字段为下图的绿色部分
提取出来后再根据加密逻辑编写脚本解出flag,脚本为:
#include <stdio.h>
#include <string.h>
unsigned char dword_402008[]={
0xE0,0x81,0x89,0xC0,0xA0,0xC1,0xAE,0xE0,0x81,0xA5,
0xC1,0xB6,0xF0,0x80,0x81,0xA5,0xE0,0x81,0xB2,0xF0,
0x80,0x80,0xA0,0xE0,0x81,0xA2,0x72,0x6F,0xC1,0xAB,
0x65,0xE0,0x80,0xA0,0xE0,0x81,0xB4,0xE0,0x81,0xA8,
0xC1,0xA5,0x20,0xC1,0xA5,0xE0,0x81,0xAE,0x63,0xC1,
0xAF,0xE0,0x81,0xA4,0xF0,0x80,0x81,0xA9,0x6E,0xC1,
0xA7,0xC0,0xBA,0x20,0x49,0xF0,0x80,0x81,0x9F,0xC1,
0xA1,0xC1,0x9F,0xC1,0x8D,0xE0,0x81,0x9F,0xC1,0xB4,
0xF0,0x80,0x81,0x9F,0xF0,0x80,0x81,0xA8,0xC1,0x9F,
0xF0,0x80,0x81,0xA5,0xE0,0x81,0x9F,0xC1,0xA5,0xE0,
0x81,0x9F,0xF0,0x80,0x81,0xAE,0xC1,0x9F,0xF0,0x80,
0x81,0x83,0xC1,0x9F,0xE0,0x81,0xAF,0xE0,0x81,0x9F,
0xC1,0x84,0x5F,0xE0,0x81,0xA9,0xF0,0x80,0x81,0x9F,
0x6E,0xE0,0x81,0x9F,0xE0,0x81,0xA7,0xE0,0x81,0x80,
0xF0,0x80,0x81,0xA6,0xF0,0x80,0x81,0xAC,0xE0,0x81,
0xA1,0xC1,0xB2,0xC1,0xA5,0xF0,0x80,0x80,0xAD,0xF0,
0x80,0x81,0xAF,0x6E,0xC0,0xAE,0xF0,0x80,0x81,0xA3,
0x6F,0xF0,0x80,0x81,0xAD,0x0};
int sub_401000(unsigned char* a1, unsigned char *a2)
{
int v3; // [esp+0h] [ebp-8h]
char v4; // [esp+4h] [ebp-4h]
if ( (signed int)*a2 >> 3 == 30 )
{
v4 = a2[3] & 0x3F | ((a2[2] & 0x3F) << 6) | ((a2[1] & 0x3F) << 12) | ((*a2 & 7) << 18);
v3 = 4;
}
else if ( (signed int)*a2 >> 4 == 14 )
{
v4 = a2[2] & 0x3F | ((a2[1] & 0x3F) << 6) | ((*a2 & 0xF) << 12);
v3 = 3;
}
else if ( (signed int)*a2 >> 5 == 6 )
{
v4 = a2[1] & 0x3F | ((*a2 & 0x1F) << 6);
v3 = 2;
}
else
{
v4 = a2[0];
v3 = 1;
}
*a1 = v4;
return v3;
}
int sub_401160(unsigned char *a1,unsigned char *a2, unsigned int a3)
{
int v3; // ST08_4
int i; // [esp+4h] [ebp-4h]
for ( i = 0; i < a3; ++i )
{
a2 += sub_401000(a1, a2);
v3 = *a1++;
if ( !v3 )
break;
}
return i;
}
int main(){
int i;
unsigned int v4; // eax
unsigned int v7; // [esp+80h] [ebp-4h]
int len=strlen((char *)dword_402008);
unsigned char Text[174]={0};
unsigned char *s=dword_402008;
v4 = sub_401160(Text, s, len);
v7 = v4;
Text[v4] = 0;
printf("%s \n",Text);
return 0;
}
运行结果为
所以flag为:flag{I_a_M_t_h_e_e_n_C_o_D_i_n_g@flare-on.com}
[UTCTF2020]basic-re
例行查壳无壳是64位程序,直接拖入ida进行查看分析,先反编译查看主函数发现没撒乱用,然后直接查找字符串发现flag
flag为:flag{str1ngs_1s_y0ur_fr13nd}
只能说是简简单单的一道题
[FlareOn3]Challenge1
查壳发现无壳且是32位程序直接拖入ida打开
主函数为:
int __cdecl main(int argc, const char **argv, const char **envp)
{
char Buffer[128]; // [esp+0h] [ebp-94h] BYREF
char *Str1; // [esp+80h] [ebp-14h]
char *Str2; // [esp+84h] [ebp-10h]
HANDLE StdHandle; // [esp+88h] [ebp-Ch]
HANDLE hFile; // [esp+8Ch] [ebp-8h]
DWORD NumberOfBytesWritten; // [esp+90h] [ebp-4h] BYREF
hFile = GetStdHandle(0xFFFFFFF5);
StdHandle = GetStdHandle(0xFFFFFFF6);
Str2 = "x2dtJEOmyjacxDemx2eczT5cVS9fVUGvWTuZWjuexjRqy24rV29q";
WriteFile(hFile, "Enter password:\r\n", 0x12u, &NumberOfBytesWritten, 0);
ReadFile(StdHandle, Buffer, 0x80u, &NumberOfBytesWritten, 0);
Str1 = (char *)sub_401260(Buffer, NumberOfBytesWritten - 2);
if ( !strcmp(Str1, Str2) )
WriteFile(hFile, "Correct!\r\n", 0xBu, &NumberOfBytesWritten, 0);
else
WriteFile(hFile, "Wrong password\r\n", 0x11u, &NumberOfBytesWritten, 0);
return 0;
}
这里可以看出str2很像是base64加密
再根据此函数里面的可以确定它是base64加密,只不过是变种的base字母表顺序不一样,然后再找其字母表顺序
如上图其字母替换表为:ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/
找在线网站进行解密的到
flag为:flag{sh00ting_phish_in_a_barrel@flare-on.com}
特殊的 BASE64
查壳无壳是64位,直接用ida打开,根据题目直接查找字符串
但是这里发现它并不是正常的base64那样的加密,而更像是base64的变种常见的base64的密码表应该是ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
而这题的看到的类似密码表的字符串是AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0987654321/+
所以可以看出我们的猜想正确
然后再看主函数:
int __cdecl main(int argc, const char **argv, const char **envp)
{
std::ostream *v3; // rax
std::ostream *v4; // rax
char v6[16]; // [rsp+20h] [rbp-60h] BYREF
char v7[16]; // [rsp+30h] [rbp-50h] BYREF
char v8[15]; // [rsp+40h] [rbp-40h] BYREF
char v9; // [rsp+4Fh] [rbp-31h] BYREF
char v10[32]; // [rsp+50h] [rbp-30h] BYREF
_main(argc, argv, envp);
std::string::string((std::string *)v8);
std::allocator<char>::allocator(&v9);
std::string::string(v7, "mTyqm7wjODkrNLcWl0eqO8K8gc1BPk1GNLgUpI==", &v9);
std::allocator<char>::~allocator(&v9);
v3 = (std::ostream *)std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "Please input your flag!!!!");
refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(v3);
std::operator>><char>(refptr__ZSt3cin, (std::string *)v8);
std::string::string((std::string *)v10, (const std::string *)v8);
base64Encode(v6, v10);
std::string::~string((std::string *)v10);
if ( (unsigned __int8)std::operator==<char>(v6, v7) )
v4 = (std::ostream *)std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "The flag is right!!!!!!!!!");
else
v4 = (std::ostream *)std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "This is a wrong flag!!!!!!!!");
refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(v4);
std::string::~string((std::string *)v6);
std::string::~string((std::string *)v7);
std::string::~string((std::string *)v8);
return 0;
}
大致就是先将v7初始化为mTyqm7wjODkrNLcWl0eqO8K8gc1BPk1GNLgUpI==,然后输入flag字符串,在对输入的字符串进行base64编码,最后将编码的结果与v7进行比较,而初始化a1密码表的时候用的是unk_489084的地址
说明猜想也是正确的,所以直接写脚本如下
import base64
import string
str1 = "mTyqm7wjODkrNLcWl0eqO8K8gc1BPk1GNLgUpI=="
string1 = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0987654321/+"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
a=str1.translate(str.maketrans(string1,string2))
print(base64.b64decode(a).decode())#base64解码
上述脚本利用密码表还原成正常base64编码后的字符串结果为
flag为flag{Special_Base64_By_Lich}
[ACTF新生赛2020]Universe_final_answer
查壳无壳是64位的直接拖ida打开直接反编译查看主函数
__int64 __fastcall main(int a1, char **a2, char **a3)
{
__int64 v4; // [rsp+0h] [rbp-A8h] BYREF
char v5[104]; // [rsp+20h] [rbp-88h] BYREF
unsigned __int64 v6; // [rsp+88h] [rbp-20h]
v6 = __readfsqword(0x28u);
__printf_chk(1LL, "Please give me the key string:", a3);
scanf("%s", v5);
if ( (unsigned __int8)sub_860(v5) )
{
sub_C50(v5, &v4);
__printf_chk(1LL, "Judgement pass! flag is actf{%s_%s}\n", v5);
}
else
{
puts("False key!");
}
return 0LL;
}
其加密应该是在sub_860函数中,点开后进一步查看函数发现是z3方程组加密
bool __fastcall sub_860(char *a1)
{
int v1; // ecx
int v2; // esi
int v3; // edx
int v4; // r9d
int v5; // r11d
int v6; // ebp
int v7; // ebx
int v8; // r8d
int v9; // r10d
bool result; // al
int v11; // [rsp+0h] [rbp-38h]
v1 = a1[1];
v2 = *a1;
v3 = a1[2];
v4 = a1[3];
v5 = a1[4];
v6 = a1[6];
v7 = a1[5];
v8 = a1[7];
v9 = a1[8];
result = 0;
if ( -85 * v9 + 58 * v8 + 97 * v6 + v7 + -45 * v5 + 84 * v4 + 95 * v2 - 20 * v1 + 12 * v3 == 12613 )
{
v11 = a1[9];
if ( 30 * v11 + -70 * v9 + -122 * v6 + -81 * v7 + -66 * v5 + -115 * v4 + -41 * v3 + -86 * v1 - 15 * v2 - 30 * v8 == -54400
&& -103 * v11 + 120 * v8 + 108 * v7 + 48 * v4 + -89 * v3 + 78 * v1 - 41 * v2 + 31 * v5 - (v6 << 6) - 120 * v9 == -10283
&& 71 * v6 + (v7 << 7) + 99 * v5 + -111 * v3 + 85 * v1 + 79 * v2 - 30 * v4 - 119 * v8 + 48 * v9 - 16 * v11 == 22855
&& 5 * v11 + 23 * v9 + 122 * v8 + -19 * v6 + 99 * v7 + -117 * v5 + -69 * v3 + 22 * v1 - 98 * v2 + 10 * v4 == -2944
&& -54 * v11 + -23 * v8 + -82 * v3 + -85 * v2 + 124 * v1 - 11 * v4 - 8 * v5 - 60 * v7 + 95 * v6 + 100 * v9 == -2222
&& -83 * v11 + -111 * v7 + -57 * v2 + 41 * v1 + 73 * v3 - 18 * v4 + 26 * v5 + 16 * v6 + 77 * v8 - 63 * v9 == -13258
&& 81 * v11 + -48 * v9 + 66 * v8 + -104 * v6 + -121 * v7 + 95 * v5 + 85 * v4 + 60 * v3 + -85 * v2 + 80 * v1 == -1559
&& 101 * v11 + -85 * v9 + 7 * v6 + 117 * v7 + -83 * v5 + -101 * v4 + 90 * v3 + -28 * v1 + 18 * v2 - v8 == 6308 )
{
return 99 * v11 + -28 * v9 + 5 * v8 + 93 * v6 + -18 * v7 + -127 * v5 + 6 * v4 + -9 * v3 + -93 * v1 + 58 * v2 == -1697;
}
}
return result;
}
但是需要注意的是此方程解出来后要v2和v1互换,v7和v6互换。然后在对应其ascll码兑换成字符串,其解密脚本为:
from z3 import *
s = Solver()
v1 = Int('v1')
v2 = Int('v2')
v3 = Int('v3')
v4 = Int('v4')
v5 = Int('v5')
v6 = Int('v6')
v7 = Int('v7')
v8 = Int('v8')
v9 = Int('v9')
v11 = Int('v11')
s.add(-85 * v9 + 58 * v8 + 97 * v6 + v7 + -45 * v5 + 84 * v4 + 95 * v2 - 20 * v1 + 12 * v3 == 12613)
s.add(
30 * v11 + -70 * v9 + -122 * v6 + -81 * v7 + -66 * v5 + -115 * v4 + -41 * v3 + -86 * v1 - 15 * v2 - 30 * v8 == -54400)
s.add(-103 * v11 + 120 * v8 + 108 * v7 + 48 * v4 + -89 * v3 + 78 * v1 - 41 * v2 + 31 * v5 - (
v6 * 64) - 120 * v9 == -10283)
s.add(71 * v6 + (v7 * 128) + 99 * v5 + -111 * v3 + 85 * v1 + 79 * v2 - 30 * v4 - 119 * v8 + 48 * v9 - 16 * v11 == 22855)
s.add(5 * v11 + 23 * v9 + 122 * v8 + -19 * v6 + 99 * v7 + -117 * v5 + -69 * v3 + 22 * v1 - 98 * v2 + 10 * v4 == -2944)
s.add(-54 * v11 + -23 * v8 + -82 * v3 + -85 * v2 + 124 * v1 - 11 * v4 - 8 * v5 - 60 * v7 + 95 * v6 + 100 * v9 == -2222)
s.add(-83 * v11 + -111 * v7 + -57 * v2 + 41 * v1 + 73 * v3 - 18 * v4 + 26 * v5 + 16 * v6 + 77 * v8 - 63 * v9 == -13258)
s.add(81 * v11 + -48 * v9 + 66 * v8 + -104 * v6 + -121 * v7 + 95 * v5 + 85 * v4 + 60 * v3 + -85 * v2 + 80 * v1 == -1559)
s.add(101 * v11 + -85 * v9 + 7 * v6 + 117 * v7 + -83 * v5 + -101 * v4 + 90 * v3 + -28 * v1 + 18 * v2 - v8 == 6308)
s.add(99 * v11 + -28 * v9 + 5 * v8 + 93 * v6 + -18 * v7 + -127 * v5 + 6 * v4 + -9 * v3 + -93 * v1 + 58 * v2 == -1697)
if s.check() == sat:
result = s.model()
print(result)
解出来为[v1 = 48, v6 = 95, v2 = 70, v4 = 82, v11 = 64, v3 = 117, v5 = 84, v9 = 119, v8 = 55, v7 = 121]
将其顺序调完以后转成对应字符,最终得出flag为:flag{F0uRTy_7w@_42}
[羊城杯 2020]easyre
查壳发现无壳且是64位程序
用ida打开查看反编译的主函数
主函数为:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // eax
int v4; // eax
int v5; // eax
char Str[48]; // [rsp+20h] [rbp-60h] BYREF
char Str1[64]; // [rsp+50h] [rbp-30h] BYREF
char v9[64]; // [rsp+90h] [rbp+10h] BYREF
char v10[64]; // [rsp+D0h] [rbp+50h] BYREF
char Str2[60]; // [rsp+110h] [rbp+90h] BYREF
int v12; // [rsp+14Ch] [rbp+CCh] BYREF
_main(argc, argv, envp);
strcpy(Str2, "EmBmP5Pmn7QcPU4gLYKv5QcMmB3PWHcP5YkPq3=cT6QckkPckoRG");
puts("Hello, please input your flag and I will tell you whether it is right or not.");
scanf("%38s", Str);
if ( strlen(Str) != 38
|| (v3 = strlen(Str), (unsigned int)encode_one(Str, v3, v10, &v12))
|| (v4 = strlen(v10), (unsigned int)encode_two(v10, v4, v9, &v12))
|| (v5 = strlen(v9), (unsigned int)encode_three(v9, v5, Str1, &v12))
|| strcmp(Str1, Str2) )
{
printf("Something wrong. Keep going.");
return 0;
}
else
{
puts("you are right!");
return 0;
}
}
简单来看就是给定字符串进行了三次加密最后得到结果
encode_one为base64加密
__int64 __fastcall encode_one(char *a1, int a2, char *a3, int *a4)
{
int v5; // esi
int v6; // esi
int v7; // esi
int v8; // [rsp+34h] [rbp-1Ch]
int v9; // [rsp+38h] [rbp-18h]
int v11; // [rsp+48h] [rbp-8h]
int i; // [rsp+4Ch] [rbp-4h]
unsigned __int8 *v13; // [rsp+70h] [rbp+20h]
v13 = (unsigned __int8 *)a1;
if ( !a1 || !a2 )
return 0xFFFFFFFFi64;
v11 = 0;
if ( a2 % 3 )
v11 = 3 - a2 % 3;
v9 = a2 + v11;
v8 = 8 * (a2 + v11) / 6;
for ( i = 0; i < v9; i += 3 )
{
*a3 = alphabet[(char)*v13 >> 2];
if ( a2 + v11 - 3 == i && v11 )
{
if ( v11 == 1 )
{
v5 = (char)cmove_bits(*v13, 6u, 2u);
a3[1] = alphabet[v5 + (char)cmove_bits(v13[1], 0, 4u)];
a3[2] = alphabet[(char)cmove_bits(v13[1], 4u, 2u)];
a3[3] = 61;
}
else if ( v11 == 2 )
{
a3[1] = alphabet[(char)cmove_bits(*v13, 6u, 2u)];
a3[2] = 61;
a3[3] = 61;
}
}
else
{
v6 = (char)cmove_bits(*v13, 6u, 2u);
a3[1] = alphabet[v6 + (char)cmove_bits(v13[1], 0, 4u)];
v7 = (char)cmove_bits(v13[1], 4u, 2u);
a3[2] = alphabet[v7 + (char)cmove_bits(v13[2], 0, 6u)];
a3[3] = alphabet[v13[2] & 0x3F];
}
a3 += 4;
v13 += 3;
}
if ( a4 )
*a4 = v8;
return 0i64;
}
encode_two为把编码后的字符串以13个为一组顺序换一下
__int64 __fastcall encode_two(const char *a1, int a2, char *a3, int *a4)
{
if ( !a1 || !a2 )
return 0xFFFFFFFFi64;
strncpy(a3, a1 + 26, 0xDui64);
strncpy(a3 + 13, a1, 0xDui64);
strncpy(a3 + 26, a1 + 39, 0xDui64);
strncpy(a3 + 39, a1 + 13, 0xDui64);
return 0i64;
}
encode_three开始没看明白,后来经过一番搜索发现是凯撒加密
__int64 __fastcall encode_three(const char *a1, int a2, char *a3, int *a4)
{
char v5; // [rsp+Fh] [rbp-11h]
int i; // [rsp+14h] [rbp-Ch]
const char *v8; // [rsp+30h] [rbp+10h]
v8 = a1;
if ( !a1 || !a2 )
return 0xFFFFFFFFi64;
for ( i = 0; i < a2; ++i )
{
v5 = *v8;
if ( *v8 <= 64 || v5 > 90 )
{
if ( v5 <= 96 || v5 > 122 )
{
if ( v5 <= 47 || v5 > 57 )
*a3 = v5;
else
*a3 = (v5 - 48 + 3) % 10 + 48;
}
else
{
*a3 = (v5 - 97 + 3) % 26 + 97;
}
}
else
{
*a3 = (v5 - 65 + 3) % 26 + 65;
}
++a3;
++v8;
}
return 0i64;
}
把上述加密逻辑弄明白后开始进行脚本的编写,脚本如下
import base64
data='EmBmP5Pmn7QcPU4gLYKv5QcMmB3PWHcP5YkPq3=cT6QckkPckoRG'
data1=''
for i in data:
if ord(i)>=48 and ord(i)<=57:
data1 += chr((ord(i)-3-48)%10+48)
elif ord(i)>=65 and ord(i)<=90:
data1 += chr((ord(i)-3-65)%26+65)
elif ord(i)>=97 and ord(i)<=122:
data1 += chr((ord(i)-3-97)%26+97)
else:
data1 += i
flag = data1[13:26] + data1[39:] + data1[:13] + data1[26:39]
print(base64.b64decode(flag))
运行得到的结果为:
flag为:flag{672cc4778a38e80cb362987341133ea2}
收获
太难搞了,再继续加油加油加油吧,奥里给!