Reverse Begin(BUUCTF)

本文介绍了一系列逆向工程挑战的解决方法,包括利用不同工具和技术来分析各种类型的文件,如EXE、APK等,通过反编译、字符串查找等方式获取隐藏的flag。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.easyre

下载后得到,首先拖入exeinfope中查壳。

用ida64打开,左侧找到main函数打开,F5进入查看伪代码,可得flag

emmm。。。

正解为flag{                   }

2.reverse1

 下载后得到,首先拖入exeinfope中查壳。

 用ida64打开

 按下shift+F12查看所有字符串

发现类似于flag的字符{   }  双击打开

和right flag中相同,都有sub_1400118C函数

 查看sub_1400118C函数

F5查看伪代码,附上ascii码对照表一张,将111“o”,替换为了48“0”。

 解出flag

3.reverse2

 先用ida x64打开

 发现main函数,打开,F5查看伪代码

 分析发现有替换,将“i”和“r”替换成“1”。

shift+F12查看字符串,发现类似flag的字符串

 打开后发现类似flag:hacking_for_fun和刚才的main函数有关

 经过替换后解出flag

4.内涵的软件

本次下载得到了一个.exe先打开一试(期待ing。。。)

 。。。。。上exeinfope查壳。32的

对应的ida打开,反汇编。打开main函数。

 发现其跳转至main_0函数,打开main_0函数

 发现可疑flag

正确

5.新年快乐

老规矩,上exeinfope查壳。32的

ida打开有壳!!

OllyDBG脱壳失败,需要脱壳机一台。。。

ida打开脱壳后的exe

 打开main函数,F5查看伪代码

 分析可知Str2,为TrueFlag

6.xor

首先查壳,是64

用ida打开,F5查看伪代码。

打开global

转化为数据后是16进制

导出为十进制

xor运算为a[i]^a[i-1] ,写一个程序处理数据,得到flag

 

7.helloword

 首先下载文件,拖入exeinfo查,发现是.apk安卓格式

用安卓的反编译工具apkide打开

到smail/com/文件名/MainActivity.smali目录下

就可以看到flag ,正确

8.reverse 3

下载后得.exe放入查壳,是32位

用IDE32打开,查看主函数

 输入数据经过sub_4110BE处理后与Str2对比

 查看sub_4110BE函数

猜测为Base64加密

 查看字符串Str2

很明显 ,并不是正确flag

查看主函数。发现第25行将v4赋值给Destination

27和28行将Destination的每一位都加上其对应位的数字

整理思路编写解flag代码

9.不一样的flag

首先下载文件,拖入exeinfo查,可以判断是32位

 用IDA32打开

找到main函数,通过反编译得C伪代码

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 ( *(int *)&v3[4 * i + 25] < 0 || *(int *)&v3[4 * i + 25] > 4 )
        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);
    }
  }
}

分析51行和53行,49对应Ascii值是,35对应的Ascii值为#

分析代码,本题为迷宫题,迷宫为11110100001010000101111#进行5*5排列,迷宫出口最后结果为#

由55行可得过程的移动方向就是最后flag,下下下右右上上右右下下下,即222441144222

10.SimpleRev

下载后得到一个无拓展名文件,放入Exeinfo查得,用IDA64打开

打开main函数,反编译为C伪代码

 在第14行有发现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;
  v9[1] = 0LL;
  v10 = 0;
  text = (char *)join(key3, v9);
  strcpy(key, key1);
  strcat(key, src);
  v2 = 0;
  v3 = 0;
  getchar();
  v5 = strlen(key);
  for ( i = 0; i < v5; ++i )
  {
    if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
      key[i] = key[v3 % v5] + 32;
    ++v3;
  }
  printf("Please input your flag:");
  while ( 1 )
  {
    v1 = getchar();
    if ( v1 == 10 )
      break;
    if ( v1 == 32 )
    {
      ++v2;
    }
    else
    {
      if ( v1 <= 96 || v1 > 122 )
      {
        if ( v1 > 64 && v1 <= 90 )
        {
          str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
          ++v3;
        }
      }
      else
      {
        str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
        ++v3;
      }
      if ( !(v3 % v5) )
        putchar(32);
      ++v2;
    }
  }
  if ( !strcmp(text, str2) )
    puts("Congratulation!\n");
  else
    puts("Try again!\n");
  return __readfsqword(0x28u) ^ v11;
}

打开key3可知key3为kills

22行有join函数

char *__fastcall join(const char *a1, const char *a2)
{
  size_t v2; // rbx
  size_t v3; // rax
  char *dest; // [rsp+18h] [rbp-18h]

  v2 = strlen(a1);
  v3 = strlen(a2);
  dest = (char *)malloc(v2 + v3 + 1);
  if ( !dest )
    exit(1);
  strcpy(dest, a1);
  strcat(dest, a2);
  return dest;
}

分析join,其实就是一个拼接函数,text为killshadow

 key1为ADSFKstrcpy(key, key1) strcat(key, src);key为ADSFKNDCLS

29~34行将key转化为adsfkndcls,

由比较函数可知,flag要经历遍历后str2[2]**********那一串********运算,不难猜测flag也是10位

 编写解题本解出flag

11.Java逆向解密

下载得到.clsas文件,用Java Dec打开

import java.util.ArrayList;
import java.util.Scanner;

public class Reverse {
  public static void main(String[] args) {
    Scanner s = new Scanner(System.in);
    System.out.println("Please input the flag );
    String str = s.next();
    System.out.println("Your input is );
    System.out.println(str);
    char[] stringArr = str.toCharArray();
    Encrypt(stringArr);
  }
  
  public static void Encrypt(char[] arr) {
    ArrayList<Integer> Resultlist = new ArrayList<>();
    for (int i = 0; i < arr.length; i++) {
      int result = arr[i] + 64 ^ 0x20;
      Resultlist.add(Integer.valueOf(result));
    } 
    int[] KEY = { 
        180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 
        133, 191, 134, 140, 129, 135, 191, 65 };
    ArrayList<Integer> KEYList = new ArrayList<>();
    for (int j = 0; j < KEY.length; j++)
      KEYList.add(Integer.valueOf(KEY[j])); 
    System.out.println("Result:");
    if (Resultlist.equals(KEYList)) {
      System.out.println("Congratulations);
    } else {
      System.err.println("Error);
    } 
  }
}

 第一段将我们输入的input送入Encrypt处理,即

 result = arr[i] + 64 ^ 0x20

写flag脚本

 即flag{This_is_the_flag_!}

12.luck_guy

下载后首先拖入exeinfope中查壳

 用ida64打开main函数

 so???patch_me

emmm...get_flag( )

unsigned __int64 get_flag()
{
  unsigned int v0; // eax
  int i; // [rsp+4h] [rbp-3Ch]
  int j; // [rsp+8h] [rbp-38h]
  __int64 s; // [rsp+10h] [rbp-30h] BYREF
  char v5; // [rsp+18h] [rbp-28h]
  unsigned __int64 v6; // [rsp+38h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  v0 = time(0LL);
  srand(v0);
  for ( i = 0; i <= 4; ++i )
  {
    switch ( rand() % 200 )
    {
      case 1:
        puts("OK, it's flag:");
        memset(&s, 0, 0x28uLL);
        strcat((char *)&s, f1);
        strcat((char *)&s, &f2);
        printf("%s", (const char *)&s);
        break;
      case 2:
        printf("Solar not like you");
        break;
      case 3:
        printf("Solar want a girlfriend");
        break;
      case 4:
        s = 0x7F666F6067756369LL;
        v5 = 0;
        strcat(&f2, (const char *)&s);
        break;
      case 5:
        for ( j = 0; j <= 7; ++j )
        {
          if ( j % 2 == 1 )
            *(&f2 + j) -= 2;
          else
            --*(&f2 + j);
        }
        break;
      default:
        puts("emmm,you can't find flag 23333");
        break;
    }
  }
  return __readfsqword(0x28u) ^ v6;
}
v0 = time(0LL);
  srand(v0);
  for ( i = 0; i <= 4; ++i )
  {
    switch ( rand() % 200 )
//luck guy??
//case 2,case 3还是废的。。。
雀实

继续分析case1中使用f1,f2,case4中给f2赋值,case5中对f2进行修改

 即s=icug`of

按照case4——case5——case1的顺序写解题脚本

 可得flag

13.刮开有奖

下载后首先拖入exeinfope中查壳,无壳,32位

 用ida32打开,找到关键函数(WinMain(x,x,x,x)-DialogBoxParamaA)打开反编译

 查看DialogFunc函数

INT_PTR __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
  const char *v4; // esi
  const char *v5; // edi
  int v7[2]; // [esp+8h] [ebp-20030h] BYREF
  int v8; // [esp+10h] [ebp-20028h]
  int v9; // [esp+14h] [ebp-20024h]
  int v10; // [esp+18h] [ebp-20020h]
  int v11; // [esp+1Ch] [ebp-2001Ch]
  int v12; // [esp+20h] [ebp-20018h]
  int v13; // [esp+24h] [ebp-20014h]
  int v14; // [esp+28h] [ebp-20010h]
  int v15; // [esp+2Ch] [ebp-2000Ch]
  int v16; // [esp+30h] [ebp-20008h]
  CHAR String[65536]; // [esp+34h] [ebp-20004h] BYREF
  char v18[65536]; // [esp+10034h] [ebp-10004h] BYREF

  if ( a2 == 272 )
    return 1;
  if ( a2 != 273 )
    return 0;
  if ( (_WORD)a3 == 1001 )
  {
    memset(String, 0, 0xFFFFu);
    GetDlgItemTextA(hDlg, 1000, String, 0xFFFF);
    if ( strlen(String) == 8 )
    {
      v7[0] = 90;
      v7[1] = 74;
      v8 = 83;
      v9 = 69;
      v10 = 67;
      v11 = 97;
      v12 = 78;
      v13 = 72;
      v14 = 51;
      v15 = 110;
      v16 = 103;
      sub_4010F0((int)v7, 0, 10);
      memset(v18, 0, 0xFFFFu);
      v18[0] = String[5];
      v18[2] = String[7];
      v18[1] = String[6];
      v4 = (const char *)sub_401000(v18, strlen(v18));
      memset(v18, 0, 0xFFFFu);
      v18[1] = String[3];
      v18[0] = String[2];
      v18[2] = String[4];
      v5 = (const char *)sub_401000(v18, strlen(v18));
      if ( String[0] == v7[0] + 34
        && String[1] == v10
        && 4 * String[2] - 141 == 3 * v8
        && String[3] / 4 == 2 * (v13 / 9)
        && !strcmp(v4, "ak1w")
        && !strcmp(v5, "V1Ax") )
      {
        MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
      }
    }
    return 0;
  }
  if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 )
    return 0;
  EndDialog(hDlg, (unsigned __int16)a3);
  return 1;
}

26-39行中进行计算,查看sub_4010F0函数

 编写c代码得解

即得到3CEHJNSZagn

将678位进行sub_401000处理,345也进行sub_401000处理

v4 = “ak1w”;v5 = “V1Ax”

string[2] = ‘W’
string[3] = ‘P’
string[4] = ‘1’ 
string[5] = ‘j’
string[6] = ‘M'
string[7] = ‘p 

所以,string = “UJWP1jMp” 

14.justRE

按照套路,先查壳,32位无壳,用ida32打开

反编译主函数看看好像没有什么头绪  

 shift+12看看有没有长得像flag得字符,或者靠积累的感觉看看DialogFunc

有两个%d %d要对应两个数字,尝试后面得19999,0

即flag{1999902069a45792d233ac}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值