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打开,如下图所示:
然后发现没啥有用的信息,然后注意到第一个判断那里有个函数,不过没在意。所以先按住 Shift+F12 然后看字符串里面有什么有用的信息没。

图片是这样的,所以就点击第二个框,切换到反编译的代码。
截图如下:
代码如下:
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 把光标移到上面,就可以看见这个函数里哪里有相关的函数。
然后看见上面同样的地方有东西标黄了。
双击join()函数,点进去看看是什么。这些都已经被我简单的标记了一点了。
所以Join()函数就是将两个字符串连接在一起。
接下来返回,去查看的text里的key3与V9。
双击TEXT
所以
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}
对了
总结
这个题目的思路还是挺简单的,就是算法的逆向,也没有加上壳,所以就逆向算法,但是没注意到算法的写的过程中还是有小的问题在出现。所以吧,对于每一步都做了一下笔记还是有帮助的,因为总共花的时间零零散散,不过注释之后就好很多了。