【Rev】2021 极客大挑战(部分)

1、调试

0x1

image-20211101211928342

image-20211101211937636

什么?得安装linux虚拟机?像我这种直接用ubuntu系统的根本不虚!

0x2

尝试直接运行,未果

image-20211101212033495

拖入ida中分析,先看main

image-20211101212537439

上来就比较字符串,然后返回,v4是栈里的变量,初始化为0,必然不等于后面的字符串

看看汇编,发现了端倪

image-20211101212748531

如果不相等就去loc_14A0这个函数,发现这个函数直接退出了,没啥用

image-20211101212828980

我们看看如果想等跳转的函数loc_14551。怎么说都比上面退出的函数正常吧。

image-20211101212918624

0x3

到这里我们想直接调用到loc_1455这个函数其实也可以,改汇编的jnz为jz就可以了

image-20211101213059321

image-20211101213104489

保存为ts1,退出,运行,一气呵成!

get flag

image-20211101213135620

2、Re1

0x1

image-20211101214435940

image-20211101214442031

逆向人必备技能了属于是

0x2

拖入ida中分析

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4[256]; // [rsp+20h] [rbp-60h] BYREF
  char Str[40]; // [rsp+120h] [rbp+A0h] BYREF
  int v6; // [rsp+148h] [rbp+C8h]
  char v7; // [rsp+14Ch] [rbp+CCh]
  char v8[58]; // [rsp+150h] [rbp+D0h]
  char v9[2]; // [rsp+18Ah] [rbp+10Ah] BYREF
  int v10; // [rsp+198h] [rbp+118h]
  int i; // [rsp+19Ch] [rbp+11Ch]

  _main(argc, argv, envp);
  v8[0] = 21;
  v8[1] = 113;
  v8[2] = 44;
  v8[3] = 4;
  v8[4] = 37;
  v8[5] = 113;
  v8[6] = 40;
  v8[7] = 16;
  v8[8] = 21;
  v8[9] = 44;
  v8[10] = 121;
  v8[11] = 40;
  v8[12] = 34;
  v8[13] = 45;
  v8[14] = 18;
  v8[15] = 38;
  v8[16] = 25;
  v8[17] = 45;
  v8[18] = 6;
  v8[19] = 58;
  v8[20] = 26;
  v8[21] = 20;
  v8[22] = 25;
  v8[23] = 112;
  v8[24] = 24;
  v8[25] = 114;
  v8[26] = 6;
  v8[27] = 57;
  v8[28] = 26;
  v8[29] = 22;
  v8[30] = 121;
  v8[31] = 112;
  v8[32] = 33;
  v8[33] = 7;
  v8[34] = 22;
  v8[35] = 38;
  v8[36] = 25;
  v8[37] = 45;
  v8[38] = 6;
  v8[39] = 58;
  v8[40] = 33;
  v8[41] = 24;
  v8[42] = 14;
  v8[43] = 38;
  v8[44] = 34;
  v8[45] = 114;
  v8[46] = 26;
  v8[47] = 38;
  v8[48] = 35;
  v8[49] = 45;
  v8[50] = 22;
  v8[51] = 114;
  v8[52] = 26;
  v8[53] = 24;
  v8[54] = 10;
  v8[55] = 58;
  v8[56] = 26;
  v8[57] = 24;
  qmemcpy(v9, "p}", sizeof(v9));
  memset(Str, 0, sizeof(Str));
  v6 = 0;
  v7 = 0;
  memset(v4, 0, sizeof(v4));
  puts("please input your flag:");
  scanf("%s", Str);
  v10 = strlen(Str);
  if ( v10 != 44 )
  {
    puts("flag length is wrong");
    exit(0);
  }
  enc0(Str, v4, 44i64);
  enc1(v4);
  for ( i = 0; i < strlen(v4); ++i )
  {
    if ( v8[i] != v4[i] )
    {
      puts("sorry,your flag is incorrect");
      exit(0);
    }
  }
  printf("congradulations!your flag is: %s", Str);
  return 0;
}

直接给了flag加密后的数据,flag长度为44,经过两个加密

image-20211101214619423

那么我们逆回去先dec1再dec0

0x3

enc1就是简单的异或,直接异或回去就好了

image-20211101214743871

enc0就是base64,都没改表

image-20211101214817345

image-20211101214807265

那么我们直接写exp

#include<stdio.h>

int main() {
    int v8[100] = {0};
    v8[0] = 21;
    v8[1] = 113;
    v8[2] = 44;
    v8[3] = 4;
    v8[4] = 37;
    v8[5] = 113;
    v8[6] = 40;
    v8[7] = 16;
    v8[8] = 21;
    v8[9] = 44;
    v8[10] = 121;
    v8[11] = 40;
    v8[12] = 34;
    v8[13] = 45;
    v8[14] = 18;
    v8[15] = 38;
    v8[16] = 25;
    v8[17] = 45;
    v8[18] = 6;
    v8[19] = 58;
    v8[20] = 26;
    v8[21] = 20;
    v8[22] = 25;
    v8[23] = 112;
    v8[24] = 24;
    v8[25] = 114;
    v8[26] = 6;
    v8[27] = 57;
    v8[28] = 26;
    v8[29] = 22;
    v8[30] = 121;
    v8[31] = 112;
    v8[32] = 33;
    v8[33] = 7;
    v8[34] = 22;
    v8[35] = 38;
    v8[36] = 25;
    v8[37] = 45;
    v8[38] = 6;
    v8[39] = 58;
    v8[40] = 33;
    v8[41] = 24;
    v8[42] = 14;
    v8[43] = 38;
    v8[44] = 34;
    v8[45] = 114;
    v8[46] = 26;
    v8[47] = 38;
    v8[48] = 35;
    v8[49] = 45;
    v8[50] = 22;
    v8[51] = 114;
    v8[52] = 26;
    v8[53] = 24;
    v8[54] = 10;
    v8[55] = 58;
    v8[56] = 26;
    v8[57] = 24;
    for(int i = 0; i < 58; i++) {
        v8[i] ^= 0x40;
        printf("%c",(char)v8[i]);
    }
}

image-20211101214900431

image-20211101214927799

3、win32

0x1

image-20211101215932600

image-20211101215940289

0x2

拖入ida中分析,只有一片区域,被加壳了,首先尝试upx脱壳

image-20211101220011914

image-20211101220801610

0x3

再次拖入ida中分析,直接shift+f12看字符

直接是没换表的base64和一个加密结果,我们直接base64 decode

image-20211101220938453

image-20211101220946876

get flag

image-20211101221022555

3、wasm

0x1

image-20211101194906631

image-20211101194917915

这道题下载下来是一个html+js+wasm文件的一个web页面,如果flag输入正确就给你flag

之前的re没做过这种,在网上搜了搜,解法分为两种——动调和静态分析

0x2

先分享两个学习链接

一种Wasm逆向静态分析方法

Reversing Web Assembly (WASM)(chrom动调)

我先看了看chrom动调,体验极差,之后看了这个静态的,觉得不错,也是直接穿了。

我们来看看如何解题

首先是三个附件,我这里用tomcat运行打开前端,就仅仅是一个输入flag的输入框,提交表单之后会反馈是否输入正确。(直接打开无法运行,建议使用tomcat打开)

image-20211101195636302

根据静态调试的博客,我们先来搞出ida可以分析的elf文件!

按照博文中的方法搞出.o文件

image-20211101200007780

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S6lm94gj-1638161601772)(https://gitee.com/Awoodwhale/blogimg/raw/master/img/image-20211101200033076.png)]

0x3

我们可以把o文件放入ida中进行分析

首先是mian函数

image-20211101200151210

我们可以发现,result是f11函数的返回值,其他没什么需要注意的,粉色的应该是wasm的动态链接之类的东西,我们直接步入f11

image-20211101200307772

image-20211101200405166

仍然是粉色的函数不看,直接看到关键判断,这里是说我们load进入的参数是否等于22,如果不等于就f96

如果等于就去f10。

之后看这些东西直接昏了头,大概就是f96是失败,f10会进入下一步。

0x4

其实到上面那里我就看不下去了,就算是wasm可以进入ida反编译,也确实难看

我们注意到上面静态分析的博文中,可以在wasm.c中找常量,我们直接开始!

找到一个非常大的数组

image-20211101201847724

我尝试性的试一试,因为题目是xorwasm,肯定和异或有关

image-20211101202132123

由于flag格式是SYC{xxxx},我们尝试一下第一个字母,发现第一个数据异或上102就可以得到S,带入第二个数组值,惊奇的得到了Y,那么是不是直接异或一下102就可以了呢?

答案是肯定的,我们先得到}字符异或102的hex,是0x1b,到数组中找到0x1b的位置

image-20211101202318115

找到位置之后就是数据处理了

image-20211101202339508

image-20211101202350652

这题出了只能说是运气好-w-

4、Brute_force

0x1

image-20211101210756786

image-20211101210947643

go的逆向,这题纯靠看

0x2

托人ida分析,直接看main

这里直接猜测是判断长度,flag的长度为24

image-20211101211053011

然后分析下面的main_unnamed函数

看到两个关键字,main_encode肯定是加密算法,下面那个&main_cipher1肯定是flag加密后的

image-20211101211157591

进入main_encode函数,发现是md5加密

image-20211101211327357

然后去到刚刚的flag密文那里,看到3个md5值

image-20211101211404865

并且在下面又看到类似md5加密后的值

image-20211101211428003

之后就去在线网页解密,得到解密结果如下

image-20211101211455843

然后就硬看,首先和go相关,那这个g0就很有用,p可以跟着rogarm,然后就拼出了

image-20211101211612232

用程序验证一下:

image-20211101211639793

得到flag

SYC{7h3_g0_pr0g@rm_13_slgned}