BUUCTF逆向题rome

一、工具:

1、IDA

二、解题过程

①、将程序载入32位IDA

②、函数窗口找到 main函数,生成伪代码

 

 发现调用func,那么猜测,解题的关键是这个函数。

③、双击查看该函数的伪代码

int func()
{
  int result; // eax
  int v1; // [esp+14h] [ebp-44h]
  int v2; // [esp+18h] [ebp-40h]
  int v3; // [esp+1Ch] [ebp-3Ch]
  int v4; // [esp+20h] [ebp-38h]
  unsigned __int8 v5; // [esp+24h] [ebp-34h]
  unsigned __int8 v6; // [esp+25h] [ebp-33h]
  unsigned __int8 v7; // [esp+26h] [ebp-32h]
  unsigned __int8 v8; // [esp+27h] [ebp-31h]
  unsigned __int8 v9; // [esp+28h] [ebp-30h]
  int v10; // [esp+29h] [ebp-2Fh]
  int v11; // [esp+2Dh] [ebp-2Bh]
  int v12; // [esp+31h] [ebp-27h]
  int v13; // [esp+35h] [ebp-23h]
  unsigned __int8 v14; // [esp+39h] [ebp-1Fh]
  char v15; // [esp+3Bh] [ebp-1Dh]
  char v16; // [esp+3Ch] [ebp-1Ch]
  char v17; // [esp+3Dh] [ebp-1Bh]
  char v18; // [esp+3Eh] [ebp-1Ah]
  char v19; // [esp+3Fh] [ebp-19h]
  char v20; // [esp+40h] [ebp-18h]
  char v21; // [esp+41h] [ebp-17h]
  char v22; // [esp+42h] [ebp-16h]
  char v23; // [esp+43h] [ebp-15h]
  char v24; // [esp+44h] [ebp-14h]
  char v25; // [esp+45h] [ebp-13h]
  char v26; // [esp+46h] [ebp-12h]
  char v27; // [esp+47h] [ebp-11h]
  char v28; // [esp+48h] [ebp-10h]
  char v29; // [esp+49h] [ebp-Fh]
  char v30; // [esp+4Ah] [ebp-Eh]
  char v31; // [esp+4Bh] [ebp-Dh]
  int i; // [esp+4Ch] [ebp-Ch]

  v15 = 81;
  v16 = 115;
  v17 = 119;
  v18 = 51;
  v19 = 115;
  v20 = 106;
  v21 = 95;
  v22 = 108;
  v23 = 122;
  v24 = 52;
  v25 = 95;
  v26 = 85;
  v27 = 106;
  v28 = 119;
  v29 = 64;
  v30 = 108;
  v31 = 0;
  printf("Please input:");
  scanf("%s", &v5);
  result = v5;
  if ( v5 == 65 )
  {
    result = v6;
    if ( v6 == 67 )
    {
      result = v7;
      if ( v7 == 84 )
      {
        result = v8;
        if ( v8 == 70 )
        {
          result = v9;
          if ( v9 == 123 )
          {
            result = v14;
            if ( v14 == 125 )
            {
              v1 = v10;
              v2 = v11;
              v3 = v12;
              v4 = v13;
              for ( i = 0; i <= 15; ++i )
              {
                if ( *((_BYTE *)&v1 + i) > 64 && *((_BYTE *)&v1 + i) <= 90 )
                  *((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 51) % 26 + 'A';
                if ( *((_BYTE *)&v1 + i) > 96 && *((_BYTE *)&v1 + i) <= 122 )
                  *((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 79) % 26 + 97;
              }
              for ( i = 0; i <= 15; ++i )
              {
                result = (unsigned __int8)*(&v15 + i);
                if ( *((_BYTE *)&v1 + i) != (_BYTE)result )
                  return result;
              }
              result = printf("You are correct!");
            }
          }
        }
      }
    }
  }
  return result;
}

 这个地方引起了我的注意,一个一个选中按 r 键转成字符

 猜测,flag应该和这字符串有关(Qsw3sj_lz4_Ujw@l),带着猜测继续往下阅读代码

 解读这段代码发现是字符位移的操作,格式像极了凯撒加密的过程,猜测应该就是凯撒加密了

读完代码大致明白,该代码就是把flag中的每个字符(字母)进行了凯撒加密,最终得到:Qsw3sj_lz4_Ujw@l   既然这样我们就只需要把过程逆一下就可以得到正确的 flag 了

④、代码详细解读

依for循环的代码得知:

当字符为大写字母时,执行 =>  *((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 51) % 26 + 65; 

        令ch = C;,大写字母 C 对应的 ASCII 码是 67 ,带入表达式中 => (67 - 51) % 26 + 65 = 81,ASCII码 81 对应的字符为大写 Q ,诶,发现和所给的字符串第一个字符对应上了,他们的 ASCII 码相差 14 ,我们大胆的猜测,所给字符串中的大写字母减去 14 就可以得到flag中对应的字符

当字符为小写字母时,执行 =>  *((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 79) % 26 + 97;

        同理分析得,所给字符串中的小写字母减去 18 得到flag中对应的字符

⑤、写脚本思路:

#include <stdio.h>
#include <string.h>

int main()
{
	char ch[] = "Qsw3sj_lz4_Ujw@l";
	
	for(int i = 0;i < strlen(ch);i++)
	{
		if(ch[i] > 64 && ch[i] < 91)
		{
			ch[i] = ch[i] - 14;
			if(ch[i] < 65)
				ch[i] = ch[i] + 26;
		}
		else if(ch[i] > 96 && ch[i] < 123)
		{
			ch[i] = ch[i] - 18;
			if(ch[i] < 97)
				ch[i] = ch[i] + 26;
		}
		else
			ch[i] = ch[i];
	}
	
	printf("%s",ch);
	
	return 0;
}

遍历已知的字符串(Qsw3sj_lz4_Ujw@l)

条件:字符为字母,大小写区分开

ch[i] = ch[i] + 26 这里是确保字符始终为字母,应为执行了 ch[i] = ch[i] - 14 或 ch[i] = ch[i] - 18 语句后,得到的字符可能不是字母,而凯撒加密是针对字母进行加密的,加 26 可以确保得到的字符在字母的范围内(其实这段我也不是太理解,也希望能得到大佬的指点

ch[i] = ch[i],表示如果遍历到的字符不为字母则照常输出。

 最终的答案:flag{Cae3ar_th4_Gre@t}

三、收获

1、凯撒加密解密的C语言实现

2、凯撒加密代码的大概格式

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值