首页 > 其他分享 >2020羊城杯easyre

2020羊城杯easyre

时间:2023-06-19 09:02:00浏览次数:41  
标签:a1 int a3 easyre char v12 羊城 2020 encode

2020羊城杯easyre

  • 无壳64位程序
  • GCC编译

回显如下所示:

放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();
  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;
  }
}

程序逻辑如下所示:

  • 输入字符串到Str数组里
  • strlen(Str) != 38可得知flag长度必须为38
  • 字符串经过了3次加密分别是,encode_one、encode_two、encode_three
  • 经过3次加密后与Str2进行比较.

算法分析:

Encode_one

encode_one

__int64 __fastcall cmove_bits(unsigned __int8 a1, char a2, char a3)
{
  return (unsigned __int8)((int)(unsigned __int8)(a1 << a2) >> a3);
}

void __fastcall encode_one(char *a1, int a2, char *a3, int *a4)
{
  int v4; // esi
  int v5; // esi
  int v6; // esi
  int v7; // [rsp+34h] [rbp-1Ch]
  int v8; // [rsp+38h] [rbp-18h]
  int v10; // [rsp+48h] [rbp-8h]
  int i; // [rsp+4Ch] [rbp-4h]
  unsigned __int8 *v12; // [rsp+70h] [rbp+20h]

  v12 = (unsigned __int8 *)a1;
  if ( a1 && a2 )
  {
    v10 = 0;
    if ( a2 % 3 )
      v10 = 3 - a2 % 3;
    v8 = a2 + v10;
    v7 = 8 * (a2 + v10) / 6;
    for ( i = 0; i < v8; i += 3 )
    {
      *a3 = alphabet[(char)*v12 >> 2];
      if ( a2 + v10 - 3 == i && v10 )
      {
        if ( v10 == 1 )
        {
          v4 = (char)cmove_bits(*v12, 6u, 2u);
          a3[1] = alphabet[v4 + (char)cmove_bits(v12[1], 0, 4u)];
          a3[2] = alphabet[(char)cmove_bits(v12[1], 4u, 2u)];
          a3[3] = 61;
        }
        else if ( v10 == 2 )
        {
          a3[1] = alphabet[(char)cmove_bits(*v12, 6u, 2u)];
          a3[2] = 61;
          a3[3] = 61;
        }
      }
      else
      {
        v5 = (char)cmove_bits(*v12, 6u, 2u);
        a3[1] = alphabet[v5 + (char)cmove_bits(v12[1], 0, 4u)];
        v6 = (char)cmove_bits(v12[1], 4u, 2u);
        a3[2] = alphabet[v6 + (char)cmove_bits(v12[2], 0, 6u)];
        a3[3] = alphabet[v12[2] & 0x3F];
      }
      a3 += 4;
      v12 += 3;
    }
    if ( a4 )
      *a4 = v7;
  }
}

alphabet_table:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

这里的alphabet_table是一个标准的base64表,按理base64加密算法来说,base64最常见的操作是移位,这里的移位去哪了呢?在cmove_bits函数中,是存在着((a1 << a2) >> a3)这种移位.我们看一下传入的参数分别为v12[1],0,4u.

  • 也就是对v12[1]向左移动0位,向右移动4位。

这很明显是一个base64算法的特征,所以我们大致可以判断encode_one实际上是对于输入的明文进行第一层的Base64加密。

Encode_two

encode_two

void __fastcall encode_two(const char *a1, int a2, char *a3, int *a4)
{
  if ( a1 )
  {
    if ( a2 )
    {
      strncpy(a3, a1 + 26, 0xDui64);
      strncpy(a3 + 13, a1, 0xDui64);
      strncpy(a3 + 26, a1 + 39, 0xDui64);
      strncpy(a3 + 39, a1 + 13, 0xDui64);
    }
  }
}

encode_two传入的参数分别是a3,v5,v10,&v4

  • a3代表的是第一次经过Base64加密后的数据
  • v10代表是经过第二次加密后的数据

所以这里的encode_two函数,实际上就是一个对原数据进行了一个分组.

我们把a3代表1,a3+13代表2,a3+26代表3,a3+39代表4,可以得知以下结论

  • 1 - 3
  • 2 - 1
  • 3 - 4
  • 4 - 2
  • 左边代表原数据的位置,右边代表分组过后的数据所在位置.

Encode_three

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

可以看出这个函数是一个自定义逻辑算法。

对于在ASCII码在65-90之间的字符,进行以下运算

*a3 = (v5 - 65 + 3) % 26 + 65;

对于在ASCII码在97-122之间的字符,进行以下运算

*a3 = (v5 - 97 + 3) % 26 + 97;

对于在ASCII码在48-57之间的字符,进行以下运算

*a3 = (v5 - 48 + 3) % 10 + 48;

这里如果对于恺撒加密有涉及的人,是比较熟悉的。恺撒加密的算法,我在另外一篇博客提到过,

恺撒加密实际上,是一种替换加密的技术,是基于明文在字母表上的偏移的一种加密技术。要注意的是,字母表不一定要为26个字母,只是根据密码设计的需求而已。而恺撒加密中最常见的加密方法就是同余了,即:

$En(x) = (x + n) mod 26$

明文+偏移量要控制在26之内,因为字母表是26个。

所以这里的encode_three函数,实际上是对65-90,97-122,48-57的字符做一个偏移量为3的恺撒加密。

同时在main函数里面,最后的Str1经过三次加密后,必须要和Str2相等,所以Str2相当于最后的密文,Str1相当于我们要求的明文,即flag.

Str2:"EmBmP5Pmn7QcPU4gLYKv5QcMmB3PWHcP5YkPq3=cT6QckkPckoRG"

解密流程:

既然我们已经知道了程序的整个加密逻辑,如下所示:

  1. encode_one(Base64标准加密)
  2. encode_two(切片分组)
  3. encode_three(恺撒加密,key=3)

decode_one

所以我们要先写一个恺撒解密的Python脚本,脚本如下:

def decrypt_caesar(str,key=3):#根据key的不同可以改变
    test = ""
    for i in str:
        if ord(i) >= 65 and ord(i) <= 90:
            test += chr(65 + ((ord(i) - 65 -3) % 26))#这个是从A到Z
        elif ord(i) >= 97 and ord(i) <= 122:
            test += chr(97 + ((ord(i) - 97 -3) % 26))#这个是从a到z一共有26个字母,要控制在表里面
        elif ord(i) >= 48 and ord(i) <= 57:#这里可以根据题目中的字母表进行改变
            test += chr(48 + ((ord(i) - 48 - 3) % 10))
        else:
            test += i
    return test
b = "EmBmP5Pmn7QcPU4gLYKv5QcMmB3PWHcP5YkPq3=cT6QckkPckoRG"
a = decrypt_caesar(b)
print(a)

#BjYjM2Mjk4NzMR1dIVHs2NzJjY0MTEzM2VhMn0=zQ3NzhhMzhlOD

decode_two

我们知道在encode_two里面,分组所对应的逻辑如下所示:

1(分组前的排序) - 3(分组后的排序)
2 - 1
3 - 4
4 - 2
strncpy(a3, a1 + 26, 0xDui64);
strncpy(a3 + 13, a1, 0xDui64);
strncpy(a3 + 26, a1 + 39, 0xDui64);
strncpy(a3 + 39, a1 + 13, 0xDui64);

所以对应的脚本如下所示:

a = "BjYjM2Mjk4NzMR1dIVHs2NzJjY0MTEzM2VhMn0=zQ3NzhhMzhlOD"

for i in range(0,len(a),13):
    print(a[i:i+13])
"""
BjYjM2Mjk4NzM #3
R1dIVHs2NzJjY #1
0MTEzM2VhMn0= #4
zQ3NzhhMzhlOD #2
"""


我们再手动拼接一下即可."R1dIVHs2NzJjYzQ3NzhhMzhlODBjYjM2Mjk4NzM0MTEzM2VhMn0="

decode_three

直接上Base64解密脚本即可:

import base64
a = "R1dIVHs2NzJjYzQ3NzhhMzhlODBjYjM2Mjk4NzM0MTEzM2VhMn0="
b = base64.b64decode(a)
print(b)
#b'GWHT{672cc4778a38e80cb362987341133ea2}'

标签:a1,int,a3,easyre,char,v12,羊城,2020,encode
From: https://www.cnblogs.com/qsons/p/17490223.html

相关文章

  • [NOIP2020] 移球游戏 解题报告
    题目描述给定\(n+1\)个栈,栈的高度限制为\(m\)。初始时前\(n\)个上每个有\(m\)个球,最后一个为空。球分为\(n\)种颜色,每种恰好\(m\)个。一次操作可以把一个栈顶的元素弹出放到一个另一个栈顶,但是不可以使栈溢出或下溢。现要把同种颜色的球移动到同一个栈上,你需要构造一......
  • JOI Final 2020 题解
    JOI2020JustLongNeckties首先一定是贪心将两个从小到大排。然后考虑维护\(a_i-b_i\)的前缀max与\(a_{i+1}-b_i\)的后缀max即可。https://qoj.ac/submission/113106JOI2020JJOOII2考虑维护出每个点往前跳\(k\)个J/O/I跳到哪里。于是枚举右端点,然后往前跳找......
  • 靶机2020web隐藏信息探索
     个人感觉这套做题法是非常快的,本文可能有点啰嗦,请各位务必耐心看完,相信看完的各位一定会有所学成! #绿色字体代表解析,红色字体是答案,橙色代表方法一,通过本地PC中渗透测试平台Kali对服务器场景Web20200529中的网站进行访问,找到登录界面中的FLAG,并将FLAG提交直接在url里面输入靶机I......
  • PHPSTORM 2020中文版下载 软件大全
    PhpStorm和ZendStudio一样,依然是Java内核开发的一款功能强大的PHPIDE代码编辑器,支持windows和linux平台。PhpStorm7开始支持PHP5.5了,改进PHP代码高亮颜色等。PhpStorm常适合于PHP开发人员及前端工程师。提供诸于:智能HTML/CSS/JavaScript/PHP编辑、代码质量分析、版本控制集成(SVN......
  • [ACTF2020 新生赛]Exec 1
    查看源代码,发现并没有什么东西有一个可以输入的框框,想到命令执行ls可以在linux查看文件由于不知道在哪个文件下,用../../进行判断--注意执行前面要有|看到文件再次执行|cat../../../../flag得到flag......
  • [ACTF2020新生赛]Include
    >[ACTF2020新生赛**]Include**由于是file伪协议打开flag.php文件可能存在文件漏洞进入发现没有flag进行猜测flag存在flag.php源代码中可以利用php://filter伪协议来查看flag.php的源代码,构造payload:?file=php://filter/convert.base64-encode/resource=flag.php看到文件......
  • CMU15445 (Fall 2020) 数据库系统 Project#3 - Query Execution 详解
    前言经过前两个实验的铺垫,终于到了执行SQL语句的时候了。这篇博客将会介绍SQL执行计划实验的实现过程,下面进入正题。总体架构一条SQL查询的处理流程如下为:SQL被Parser解析为抽象语法树ASTBinber将AST转换为Bustub可以理解的更高级的ASTTreerewriter将语法......
  • NOIP2020 T2 字符串匹配【题解】
    NOIP2020T2字符串匹配首先声明这篇题解存在大多数让我这种人看懂的废话,如果想要速通,请另寻他解题目简化定义字符串乘法为\(AB\)为把两个字符串拼起来,定义阶乘\(A^i\)表示\(\prod_{1}^iA\)再定义\(F(S)\)为\(S\)中出现奇数次字符的数量现给定一个字符串\(S\),求......
  • mmhmm重塑视频会议、2020新款emoji可爱来袭、微软将推云游戏服务xCloud等| Decode the
    Social MediaSucks.DecodetheWeek≠音视频技术周刊 NewsBriefing1. Evernote前CEO推出虚拟摄影棚应用mmhmm重塑视频会议PhilLibin带领Evernote创造辉煌后,再次回到消费与企业应用的交界,推出虚拟相机云服务mmhmm(中文发音是“嗯哼”)。mmhmm可在Zoom、GoogleMeet、YouTube以......
  • LiveVideoStackCon 2020上海 6月见
    自强不息,否极泰来。当你在2020年底总结这一年的得失时,LiveVideoStackCon可能保留了难忘的瞬间——我们等待他太久了。原本计划于4月举行的LiveVideoStackCon2020上海由于COVID-19不得不推迟到6月13-14日,LiveVideoStack团队全体远程办公,线下活动全面停摆,并被每周四/周日晚间线上公......