BUUCTF-RE-0x02


title: BUUCTF-RE-0x02
date: 2021-04-25 13:13:52
tags:


主要是在BUUCTF上进行刷题,不过感觉难度较大的汇编无法完成,Crack不了,其次在看算法的时候也感觉挺难理解的。有的时候的函数调用有点奇特。所以加油吧。

CrackMe 5

(看不懂汇编,虽然有别人的flag,所以能复现了在自己把flag找出来吧)

查壳:

查壳

看出是一个64位的无壳程序,所以运行它。然后结果如下。所以下一步决定放进IDA。

运行试试

分析下代码:

分析

然后就不是很懂了,后面的那个函数感觉好难啊。

然后自己静态调剂,动态调试,发现好像都不行。

所以看别人的WP:

看雪WP

看着人家对于汇编的看,我好像还不是特别行,然后只将第一个函数搞明白了一点。

Java逆向解密

题目及描述

题目

逆向分析

下载好文件,发现是个==.class==文件

在这里插入图片描述

然后上网搜索,如何打开这个文件。应该是Python 的class类文件。

所以使用的是 jd-gui ,因为其他的几个jar包打不开。

在这里插入图片描述

然后打开就看见了源码了,所以就是一个简单的程序的逆向。所以需要解出那个输入的字符串就好了。

在这里插入图片描述

题目源码如下:

Reverse.class

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);
    } 
  }
}

而在我写逆向算法的过程中,需要注意到符号的允许顺序。

+ 号的运算在 ==^==之前,所以这里需要注意,其他的就很好做了。

在这里插入图片描述

逆向的源码如下:

key = [
        180, 136, 137, 147, 191, 137, 147, 191, 148, 136,
        133, 191, 134, 140, 129, 135, 191, 65]
flag = ""
for j in range(0,len(key)):
    temp = ((key[j])^32)-64
    flag+=chr(temp);

print("flag{"+flag+"}")

flag

flag{This_is_the_flag_!}

好了,本题考察的就是工具的使用以及简单的算法了。而其中注意运算符的顺序还是很必要的。

在这里插入图片描述

BUUCTF-RE

SimpleRev

在这里插入图片描述

然后使用IDA64打开,如下图所示:

image-20210420232240041

然后发现没啥有用的信息,然后注意到第一个判断那里有个函数,不过没在意。所以先按住 Shift+F12 然后看字符串里面有什么有用的信息没。

image-20210420232523560

图片是这样的,所以就点击第二个框,切换到反编译的代码。

截图如下:

image-20210420232718602

image-20210420232740367

代码如下:

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 = 'SLCDN';
  v7 = 0LL;
  v8 = 0;
  v9[0] = 'wodah';
  v9[1] = '\0';
  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 > 'z' )
      {
        if ( v1 > 64 && v1 <= 'Z' )
        {
          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;
}

初步分析

看见最后面的比较所以就看这两个字符串了,所以就先找得是text 把光标移到上面,就可以看见这个函数里哪里有相关的函数。

image-20210420233520036

然后看见上面同样的地方有东西标黄了。

http://qiniu.angelsnow.site/image-20210420233642357.png

双击join()函数,点进去看看是什么。这些都已经被我简单的标记了一点了。

所以Join()函数就是将两个字符串连接在一起。

接下来返回,去查看的text里的key3V9

双击TEXT image-20210420234018413

所以

key3 = kills 
src = SLCDN

所以key 就知道了

key = ADSFKSLCDN

然后是 v9

v9 = wodah

key1:

key1 = ADSFK

然后接下来就是算法的逆向了。去我们找到我们输入的就可了。

开始写 Python 的payload 。

注:这里要跟大家普及一个知识了,即大端与小端(虽然看了这个知识点,但是还是不知道在哪里需要进行区别)

假设一个十六进制数0x12345678

大端的存储方式是:12,34,56,78,然后读取的时候也是从前往后读

小端的存储方式是:78,56,34,12,然后读取的时候是从后往前读取

而PC机一般是小端模式。

博客:小端存储与大端存储的区别

然后写了一会儿的逆向的算法,不过运行不出来。

感觉没啥问题啊。

然后继续写代码,然后。。:

好像得到了flag:KFTGIEDBXU

所以flag =flag{KFTGIEDBXU}

flag{KFTGIEDBXU}

发现不对,接下来看看别人怎么做的吧。

第一眼看见 text不对。。所以那个就是传说中的小端存储。。

我先往回去看看,所以里面的v9是小端存储,不过为啥呢。。感觉看不出来啊,电脑是Intel的CPU可是怎么知道什么是小端哪个是大端呢。

有点迷糊,看了好多文章之后更加迷惑了。

Mark一下

下面吧那个顺序改变一下。

运行结果如下:

flag{KFTGIPPBLJ}

然后去提交。。。。发现还是错的。。

所以再次去查看我的问题在哪里。

然后是下面的也是小端排序,需要更改次序。

所以flag

flag{KFTGIUXBDE}
发现算法有点问题,修改算法,可是出现了一个@这什么情况
flag{KLDQCUDF@O}

算法如下

key3 = "kills"
v9 = "wodah"
v9_1 =""
for i in v9[::-1]:
    v9_1 +=i
# print(v9_1)
# text = "killswodah"
text = key3 + v9_1
str2 = text
print(str2)

key1 = "ADSFK"
src = "SLCDN"
src_1=""
for i in src[::-1]:
    src_1+=i
# key = "ADSFKSLCDN"

key = key1+src_1

key=key.lower()
print(key)
flag = ""
for i in range(0,len(key)):
    for j in range(0,10):
        v1 = ord(str2[i]) - 97 +j*26 + (ord(key[i]) +39-97)
        if(v1<65 or (v1>90 and v1<96) or v1>122):
            continue;
        else:
            flag += chr(v1)
            break;

print(flag)
print("flag{"+flag+"}")

所以最后的flag

flag

flag{KLDQCUDFZO}

对了

总结

这个题目的思路还是挺简单的,就是算法的逆向,也没有加上壳,所以就逆向算法,但是没注意到算法的写的过程中还是有小的问题在出现。所以吧,对于每一步都做了一下笔记还是有帮助的,因为总共花的时间零零散散,不过注释之后就好很多了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值