usualCrypt

环境

  • IDA pro
  • windows10

题目

[ACTF新生赛2020]usualCrypt

先查壳

发现是32位程序,无壳,拖入IDA
IDA反编译后

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // esi
  int result; // eax
  int v5[3]; // [esp+8h] [ebp-74h] BYREF
  __int16 v6; // [esp+14h] [ebp-68h]
  char v7; // [esp+16h] [ebp-66h]
  char v8[100]; // [esp+18h] [ebp-64h] BYREF

  sub_403CF8(&unk_40E140);
  scanf("%s", v8);
  v5[0] = 0;
  v5[1] = 0;
  v5[2] = 0;
  v6 = 0;
  v7 = 0;
  sub_401080(v8, strlen(v8), v5);
  v3 = 0;
  while ( *((_BYTE *)v5 + v3) == byte_40E0E4[v3] )
  {
    if ( ++v3 > strlen((const char *)v5) )
      goto LABEL_6;
  }
  sub_403CF8(aError);
LABEL_6:
  if ( v3 - 1 == strlen(byte_40E0E4) )
    result = sub_403CF8(aAreYouHappyYes);
  else
    result = sub_403CF8(aAreYouHappyNo);
  return result;
}

注意几个关键的地方,一行行分析

sub_403CF8(&unk_40E140);   //点入unk_40E140,发现是字符串
.data:0040E148                 db  47h ; G
.data:0040E149                 db  69h ; i
.data:0040E14A                 db  76h ; v
.data:0040E14B                 db  65h ; e
.data:0040E14C                 db  20h
.data:0040E14D                 db  6Dh ; m
.data:0040E14E                 db  65h ; e
.data:0040E14F                 db  20h
.data:0040E150                 db  79h ; y
.data:0040E151                 db  6Fh ; o
.data:0040E152                 db  75h ; u
.data:0040E153                 db  72h ; r
.data:0040E154                 db  20h
.data:0040E155                 db  66h ; f
.data:0040E156                 db  6Ch ; l
.data:0040E157                 db  61h ; a
.data:0040E158                 db  67h ; g
.data:0040E159                 db  3Ah ; :
估计sub_403CF8是输出函数,同时注意到 24行的sub_403CF8(aError),估计是输出错误信息的,果然
.data:0040E134 aError          db 'error!',0Ah,0       ; DATA XREF: _main:loc_40122B↑o

看下一行

  scanf("%s", v8);
  v5[0] = 0;
  v5[1] = 0;
  v5[2] = 0;
  v6 = 0;
  v7 = 0;

输入的字符串放到v8这个char数组那里,v5是int数组,长度为3,并全部置零

继续

sub_401080(v8, strlen(v8), v5);
点入这个函数


注意该函数声明许多参数,并发现函数 sub_401000(),点入查看,内容如下

int sub_401000()
{
  int result; // eax
  char v1; // cl

  for ( result = 6; result < 15; ++result )
  {
    v1 = byte_40E0AA[result];
    byte_40E0AA[result] = byte_40E0A0[result];
    byte_40E0A0[result] = v1;
  }
  return result;
}

注意到是对byte_40E0AA和byte_40E0A0进行操作,点击查看,查看如下

.data:0040E0A0 byte_40E0A0     db 41h                  ; DATA XREF: sub_401000:loc_401005↑r
.data:0040E0A0                                         ; sub_401000+17↑w ...
.data:0040E0A1                 db  42h ; B
.data:0040E0A2                 db  43h ; C
.data:0040E0A3                 db  44h ; D
.data:0040E0A4                 db  45h ; E
.data:0040E0A5                 db  46h ; F
.data:0040E0A6                 db  47h ; G
.data:0040E0A7                 db  48h ; H
.data:0040E0A8                 db  49h ; I
.data:0040E0A9                 db  4Ah ; J
.data:0040E0AA ; char byte_40E0AA[]
.data:0040E0AA byte_40E0AA     db 4Bh                  ; DATA XREF: sub_401000+B↑r
.data:0040E0AA                                         ; sub_401000+11↑w
.data:0040E0AB aLmnopqrstuvwxy db 'LMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',0
.data:0040E0E1                 align 4

估计两者应该是字符串数组,返回sub_401080函数,在经过sub_401000函数后,是一段很长的操作,发现都是对byte_40E0A0进行操作,但是好像byte_40E0A0只有10位,好吧,居然是40E0A0到40E0AA连起来的,然后继续看对其的操作,一开始并不知道是什么,经过查阅发现是base64加密,估计是对base的密钥表串进行了魔改,看到最后,发现sub_401030函数

int __cdecl sub_401030(const char *a1)
{
  __int64 v1; // rax
  char v2; // al

  v1 = 0i64;
  if ( strlen(a1) )
  {
    do
    {
      v2 = a1[HIDWORD(v1)];
      if ( v2 < 97 || v2 > 122 )
      {
        if ( v2 < 65 || v2 > 90 )
          goto LABEL_9;
        LOBYTE(v1) = v2 + 32;
      }
      else
      {
        LOBYTE(v1) = v2 - 32;
      }
      a1[HIDWORD(v1)] = v1;
LABEL_9:
      LODWORD(v1) = 0;
      ++HIDWORD(v1);
    }
    while ( HIDWORD(v1) < strlen(a1) );
  }
  return v1;
}

该函数把字符串每个英文字符进行了大小写转换,回到main,发现byte_40E0E4,查看发现是字符串MXHz3TIgnxLxJhFAdtZn2fFk3lYCrtPC2l9,是输入的数据进行了base64加密后的状态,整个拿到flag的过程就是对该程序执行逆向的过程

import base64

flag=''  #保存flag
crypto='zMXHz3TIgnxLxJhFAdtZn2fFk3lYCrtPC2l9'.swapcase()  #转换大小写,对sub_401030的逆向
base='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'  #base64加密的索引表
# byte_40E0AA和byte_40E0A0字符数组的逆操作
dict={}  #
for i in range(len(base)):
    dict[base[i]] = base[i]
'''
  for ( result = 6; result < 15; ++result )
  {
    v1 = byte_40E0AA[result];
    byte_40E0AA[result] = byte_40E0A0[result];
    byte_40E0A0[result] = v1;
  }
'''
for i in range(6,15):  #构造魔改后的索引表,10指的是byte_40E0A0长度
    temp = dict[base[i]]
    dict[base[i]] = dict[base[i+10]]
    dict[base[i+10]] = temp
for i in range(len(crypto)):
    flag += dict[crypto[i]]
flag = base64.b64decode(flag)
print(flag)
#b'flag{bAse64_h2s_a_Surprise}'

参考

base大家族详解:https://www.cnblogs.com/ntestoc/p/10673669.html

posted @ 2021-09-25 22:21  超级想睡觉  阅读(98)  评论(0)    收藏  举报