[ctf.show.reverse] re2

签到完了就一个小题,本身不繁杂但是有点长。

先是要求输入一个串然后逐位与0x1f异或后检查密钥是否正确

char __cdecl sub_401A70(char *Str, char *Str1)
{
  char v3; // [esp+0h] [ebp-E4h]
  signed int i; // [esp+D0h] [ebp-14h]
  signed int v5; // [esp+DCh] [ebp-8h]

  __CheckForDebuggerJustMyCode(&unk_40B027);
  v5 = strlen(Str);
  for ( i = 0; i < v5; ++i )
    Str1[i] += Str[i] ^ 0x1F;
  if ( !strcmp(Str1, "DH~mqqvqxB^||zll@Jq~jkwpmvez{") )
    c_printf("充值成功.\n", v3);
  else
    c_printf("Error!\n", v3);
  return *Str1;
}

然后开始处理这个密钥:

先循环密钥到256位长

int __cdecl sub_401800(int a1, int a2, int a3)
{
  int result; // eax
  int j; // [esp+D0h] [ebp-14h]
  int i; // [esp+DCh] [ebp-8h]

  result = __CheckForDebuggerJustMyCode(&unk_40B027);
  if ( a3 <= 256 )
  {
    for ( i = 0; i < 256; ++i )
    {
      *(_BYTE *)(i + a1) = *(_BYTE *)(a2 + i % a3);
      result = i + 1;
    }
  }
  if ( a3 > 256 )    //后边没用,不够256
  {
    for ( j = 0; j < 256; ++j )
    {
      *(_BYTE *)(j + a1) = *(_BYTE *)(j + a2);
      result = j + 1;
    }
  }
  return result;
}

再生成第2个密钥(值为0-255)

int __cdecl sub_401780(int a1)
{
  int result; // eax
  int i; // [esp+D0h] [ebp-8h]

  result = __CheckForDebuggerJustMyCode(&unk_40B027);
  for ( i = 0; i < 256; ++i )
  {
    *(_BYTE *)(i + a1) = i;
    result = i + 1;
  }
  return result;
}

根据第1个密钥将第2个密钥位置交换后作为解密密钥

int __cdecl sub_4018E0(int a1, int a2)
{
  int result; // eax
  int i; // [esp+D0h] [ebp-2Ch]
  char v4; // [esp+EBh] [ebp-11h]
  int v5; // [esp+F4h] [ebp-8h]

  result = __CheckForDebuggerJustMyCode(&unk_40B027);
  v5 = 0;
  for ( i = 0; i < 256; ++i )
  {
    v5 = (*(unsigned __int8 *)(i + a2) + v5 + *(unsigned __int8 *)(i + a1)) % 256;
    v4 = *(_BYTE *)(i + a1);
    *(_BYTE *)(i + a1) = *(_BYTE *)(v5 + a1);
    *(_BYTE *)(v5 + a1) = v4;
    result = i + 1;
  }
  return result;
}

最后次读入的flag用密钥加密后存入enflag.txt文件。由于这里只对处理后的密钥与flag作异或运算,所以加密与解密相同,可直接用来解密

int __cdecl sub_4015E0(int a1, FILE *in_file, FILE *out_file)
{
  int result; // eax
  char v4; // [esp+103h] [ebp-35h]
  char i; // [esp+11Bh] [ebp-1Dh]
  int v6; // [esp+124h] [ebp-14h]
  int v7; // [esp+130h] [ebp-8h]

  __CheckForDebuggerJustMyCode(&unk_40B027);
  v7 = 0;
  v6 = 0;
  for ( i = fgetc(in_file); ; i = fgetc(in_file) )
  {
    result = i;
    if ( i == -1 )
      break;
    v7 = (v7 + 1) % 256;
    v6 = (v6 + *(unsigned __int8 *)(v7 + a1)) % 256;
    v4 = *(_BYTE *)(v7 + a1);
    *(_BYTE *)(v7 + a1) = *(_BYTE *)(v6 + a1);
    *(_BYTE *)(v6 + a1) = v4;
    fputc(*(_BYTE *)((*(unsigned __int8 *)(v6 + a1) + *(unsigned __int8 *)(v7 + a1)) % 256 + a1) ^ i, out_file);
  }
  return result;
}

先求出密钥:

str1 = b"DH~mqqvqxB^||zll@Jq~jkwpmvez{"
str0 = b''
for i in str1:
    str0 +=bytes([i^0x1f])
print(str0)

再将enflag.txt文件更名为flag.txt后运行一次程序即可。

做出你的选择:
1.充钱
2.退出
1

请输入您的密钥:[Warnning]Access_Unauthorized
充值成功.

加密成功!
您的充值金额不足。


C:\ctf.show.reverse\re2>type enflag.txt
flag{RC4&->ENc0d3F1le}

生成的enflag.txt文件即为flag

或者用自己重写一遍程序。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值