buu刷题日记1

文章讲述了在解决CTF挑战时,如何使用ida进行反编译分析,理解加密函数并编写脚本进行解密,涉及到的技术包括z3方程组解密、异或操作、Base64编码等。通过对不同题目案例的解析,展示了逆向工程在解题过程中的重要性。
摘要由CSDN通过智能技术生成

[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}

收获

太难搞了,再继续加油加油加油吧,奥里给!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值