easyre

先看一下,64位无壳

用IDA64位打开,搜索main函数(在逆向工程中,main 函数通常是程序的入口点(Entry Point),也是分析的起点和核心。)

flag就出来了

reverse1

64位无壳

老样子搜索main函数按tab查看伪代码

这里遍历了str2 并且将所有字符o替换成0 (ASCII码)

跟进一下str2

flag{hell0_w0rld}

reverse2

查壳,64位无壳直接分析

这里将flag遍历并且将i和r替换成1

跟进flag看看是多少然后修改

少了个大括号就是前面的7Bh,按r解码就行了

flag{hack1ng_fo1_fun}

内涵的软件

无壳打开

直接把他提交了

新年快乐

加壳了,upx.exe,直接到kali里用自带的工具脱壳。

新的文件在桌面

放ida里

将HappyNewYear!复制到str2里,然后用户输入str1,对比,所以这就是答案

XOR

文件解压后有一个xor有一个文件夹_MACOSX,这个文件夹不用管,就是缓存(没有用的垃圾文件)

MAC OS系统的,无壳64位。

放入IDA64

这里的get_line是自定义输入读取函数,类似于上面的scanf,但是比scanf好,可以防止缓冲区溢出和方便处理换行符。

_b就是我们输入的内容,在下面的strncmp的比较重global就是key,也就等于上面的key

这里有个if判断,如果你输入的值不等于(!=)33就会报错,如果等于那么就进行异或。

但是这个异或不影响,这里的意思是把你输入的值进行异或然后变成一个新的字符串与global进行比对,那么我们直接查看global就行了。(其实我也对异或也不咋了解)

这里还看不到,因为globa只是保存的后面这一字符串的内存地址,我们要继续跟进。

利用快捷键shift+e提取,选项的意思是:

将程序内存中找到的原始数据,以 “C 语言的无符号字符数组” 的形式,并使用 “十进制” 来表示每个元素,导出或显示出来。

然后写一个脚本。

reverse3

无壳32位

打开搜索main函数,查看伪代码

简述一下过程:

int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  size_t v3; // eax
  const char *v4; // eax
  size_t v5; // eax
  char v7; // [esp+0h] [ebp-188h]
  char v8; // [esp+0h] [ebp-188h]
  signed int j; // [esp+DCh] [ebp-ACh]
  int i; // [esp+E8h] [ebp-A0h]
  signed int v11; // [esp+E8h] [ebp-A0h]
  char Destination[108]; // [esp+F4h] [ebp-94h] BYREF
  char Str[28]; // [esp+160h] [ebp-28h] BYREF
  char v14[8]; // [esp+17Ch] [ebp-Ch] BYREF

  for ( i = 0; i < 100; ++i )
  {
    if ( (unsigned int)i >= 0x64 )
      j____report_rangecheckfailure();
    Destination[i] = 0;
  }
  sub_41132F("please enter the flag:", v7);    #相当于printf提示用户输入
  sub_411375("%20s", (char)Str);               #相当于scanf,最多读取20个字符存入Str    
  v3 = j_strlen(Str);                          #读取Str长度存入v3
  v4 = (const char *)sub_4110BE(Str, v3, v14); #调用新函数,将Str和v3和v14作为参数得到字符串
  strncpy(Destination, v4, 0x28u);             #复制v4到Destination最多40个字符
  v11 = j_strlen(Destination);                 #读取Destination长度到v11
  for ( j = 0; j < v11; ++j )                  
    Destination[j] += j;                       #为Destination加索引
  v5 = j_strlen(Destination);                  #再次获得新的destination长度到v5
  if ( !strncmp(Destination, Str2, v5) )       #如果Str2的前五个字符等于Destination的前五个
    sub_41132F("rigth flag!\n", v8);           #输出flag
  else
    sub_41132F("wrong flag!\n", v8);
  return 0;
}

跟踪上面的计算 sub_4110BE

发现有比较敏感的数组

点进去看一下

明显的base64,如果你不确定,你可以点编辑——插件

就会自动显示包含的加密有什么。

打开str2发现字符串

直接写脚本对str2进行字符偏移处理(将加密后的字符串每个字符的ASCII码值减去其所在位置的索引)也是逆向偏移。

helloword

下载完是APK文件,打开apk文件分析软件,改之理

访问开始文件

flag就在里面

不一样的flag

无壳32位

读取源代码

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  _BYTE v3[29]; // [esp+17h] [ebp-35h] BYREF
  int v4; // [esp+34h] [ebp-18h]
  int v5; // [esp+38h] [ebp-14h] BYREF
  int i; // [esp+3Ch] [ebp-10h]
  _BYTE v7[12]; // [esp+40h] [ebp-Ch] BYREF

  __main();
  v3[26] = 0;
  *(_WORD *)&v3[27] = 0;
  v4 = 0;
  strcpy(v3, "*11110100001010000101111#");
  while ( 1 )
  {
    puts("you can choose one action to execute");
    puts("1 up");
    puts("2 down");
    puts("3 left");
    printf("4 right\n:");
    scanf("%d", &v5);
    if ( v5 == 2 )
    {
      ++*(_DWORD *)&v3[25];
    }
    else if ( v5 > 2 )
    {
      if ( v5 == 3 )
      {
        --v4;
      }
      else
      {
        if ( v5 != 4 )
LABEL_13:
          exit(1);
        ++v4;
      }
    }
    else
    {
      if ( v5 != 1 )
        goto LABEL_13;
      --*(_DWORD *)&v3[25];
    }
    for ( i = 0; i <= 1; ++i )
    {
      if ( *(_DWORD *)&v3[4 * i + 25] >= 5u )
        exit(1);
    }
    if ( v7[5 * *(_DWORD *)&v3[25] - 41 + v4] == 49 )
      exit(1);
    if ( v7[5 * *(_DWORD *)&v3[25] - 41 + v4] == 35 )
    {
      puts("\nok, the order you enter is the flag!");
      exit(0);
    }
  }
}

其实你打开这个程序之后你就会发现他是让你选1234来决定你走上下左右,这是一种迷宫形题目

我们需要从根据题目从哪里走到哪里就可以得出flag

看这里当v7的元素等于#的时候会输出flag,但是等于1的时候就会exit 退出

所以我们要避开1去到#,所以我么可以判断*号是开始,#是结束

迷宫型都是方形的区域

我们只需要走0到#

所以flag就是222441144222

SimpleRev

无壳64位,但是是ELF文件,小端序,并且是linux的x86-64

好了打开mian函数查看,就是说你选d或者q,d就继续,q就退出,选别的就会重复,除了有个Decry()函数没啥有用的,跟踪

unsigned __int64 Decry()
{
  char v1; // [rsp+Fh] [rbp-51h]
  int v2; // [rsp+10h] [rbp-50h]
  int v3; // [rsp+14h] [rbp-4Ch]
  int i; // [rsp+18h] [rbp-48h]
  int v5; // [rsp+1Ch] [rbp-44h]
  char src[8]; // [rsp+20h] [rbp-40h] BYREF
  __int64 v7; // [rsp+28h] [rbp-38h]
  int v8; // [rsp+30h] [rbp-30h]
  __int64 v9[2]; // [rsp+40h] [rbp-20h] BYREF
  int v10; // [rsp+50h] [rbp-10h]
  unsigned __int64 v11; // [rsp+58h] [rbp-8h]

  v11 = __readfsqword(0x28u);
  *(_QWORD *)src = 0x534C43444ELL;
  v7 = 0LL;
  v8 = 0;
  v9[0] = 0x776F646168LL;            \\这里转码之后是wodah所以我们要编程hadow
  v9[1] = 0LL;
  v10 = 0;
  text = (char *)join(key3, v9);    \\key3是kills,join函数也是拼接所以,killshadow
  strcpy(key, key1);                \\将key1赋值给key,跟进是ADSFK
  strcat(key, src);                 \\将src和key拼接,在上面,转码之后是SLCDN,因为是小端,
                                    \\所以我们要将SLCDN反转,为什么ADSFK不呢,
                                    \\因为在伪代码界面的是小端,二进制页面就是自动变为大端
                                    \\所以拼接后是ADSFKNDCLS
  v2 = 0;
  v3 = 0;
  getchar();                        \\缓冲回车
  v5 = strlen(key);                 \\v5等于key的长度10
  for ( i = 0; i < v5; ++i )        \\对v5处理
  {
    if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
      key[i] = key[v3 % v5] + 32;   \\这里呢就是对A-Z之间的加32,也就是转换为小写
    ++v3;
  }
  printf("Please input your flag:");
  while ( 1 )            \\无限循环    
  {
    v1 = getchar();      \\读取一个字符存入v1
    if ( v1 == 10 )      \\如果是换行符
      break;             \\退出
    if ( v1 == 32 )      \\如果是空格
    {
      ++v2;              \\不做转换,仅将v2(str2的下标)自增,等于跳过
    }
    else
    {
      if ( v1 <= 96 || v1 > 122 )   \\判断是不是大写字母,用来表示v1不是小写
      {
        if ( v1 > 64 && v1 <= 90 )  \\判断是不是小写,表示v1是大写
        {
          str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97; \\v1原始的字符
          ++v3;   \\自增,移动到key数组的下一个元素     \\v3 % v5表示是在key数组的范围内循环
        }                          \\% 26确保是英文字母,+97表示让他成为小写字母
      }
      else
      {
        str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97; \\转换位小写 
        ++v3;
      }
      if ( !(v3 % v5) )
        putchar(32);   \\这里是当v3是v5的整数倍时,条件成立,然后这里的是输出一个空格
      ++v2;       \\这里是将str2下标向后移一位。
    }
  }
  if ( !strcmp(text, str2) )        //判断str2和text是否相等,相等就会返回恭喜
    puts("Congratulation!\n");
  else
    puts("Try again!\n");
  return __readfsqword(0x28u) ^ v11;
}

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐