buuctf re

Java逆向解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import java.io.PrintStream;
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] + '@' ^ 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��");
}
}
}

Exp:

1
2
3
4
5
KEY = [180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65]
flag=""
for i in range(0,len(KEY)):
flag+=chr(KEY[i]-ord('@')^0x20)
print(flag)

findit

png

将这组十六进制数转为字符:
1
2
3
4
5
k1=[0x70,0x76,0x6b,0x71,0x7b,0x6d,0x31,0x36,0x34,0x36,0x37,0x35,0x32,0x36,0x32,0x30,0x33,0x33,0x6c,0x34,0x6d,0x34,0x39,0x6c,0x6e,0x70,0x37,0x70,0x39,0x6d,0x6e,0x6b,0x32,0x38,0x6b,0x37,0x35,0x7d]
flag=""
for i in range(0,len(k1)):
flag+=chr(k1[i])
print(flag)
1
pvkq{m164675262033l4m49lnp7p9mnk28k75}

1

凯撒密码得flag:

1
flag{c164675262033b4c49bdf7f9cda28a75}

简单注册器

用jadx-gui打开

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void onClick(View v) {
int flag = 1;
String xx = editview.getText().toString();
if (!(xx.length() == 32 && xx.charAt(31) == 'a' && xx.charAt(1) == 'b' && (xx.charAt(0) + xx.charAt(2)) - 48 == 56)) {
flag = 0;
}
if (flag == 1) {
char[] x = "dd2940c04462b4dd7c450528835cca15".toCharArray();
x[2] = (char) ((x[2] + x[3]) - 50);
x[4] = (char) ((x[2] + x[5]) - 48);
x[30] = (char) ((x[31] + x[9]) - 48);
x[14] = (char) ((x[27] + x[28]) - 97);
for (int i = 0; i < 16; i++) {
char a = x[31 - i];
x[31 - i] = x[i];
x[i] = a;
}
textview.setText("flag{" + String.valueOf(x) + "}");
return;
}
textview.setText("输入注册码错误");
}

Exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
# -*- coding:utf-8 -*-

flagtrue = "dd2940c04462b4dd7c450528835cca15"
x = [i for i in flagtrue]
x[2] = chr(ord(x[2]) + ord(x[3]) - 0x32)
x[4] = chr(ord(x[2]) + ord(x[5]) - 0x30)
x[0x1e] = chr(ord(x[0x1f]) + ord(x[0x9]) - 0x30)
x[0xe] = chr(ord(x[0x1b]) + ord(x[0x1c]) - 0x61)

for i in range(16):
x[i],x[31-i] = x[31-i],x[i]

print ("flag{"+ ''.join(x) + "}")
flag:
1
flag{59acc538825054c7de4b26440c0999dd}

CrackRTF

拿到个exe文件,二话不说直接丢进ida

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
int __cdecl main_0()
{
DWORD v0; // eax
DWORD v1; // eax
CHAR String; // [esp+4Ch] [ebp-310h]
int v4; // [esp+150h] [ebp-20Ch]
CHAR String1; // [esp+154h] [ebp-208h]
BYTE pbData; // [esp+258h] [ebp-104h]

memset(&pbData, 0, 0x104u);
memset(&String1, 0, 0x104u);
v4 = 0;
printf("pls input the first passwd(1): ");
scanf("%s", &pbData);
if ( strlen((const char *)&pbData) != 6 ) // flag的长度为6
{
printf("Must be 6 characters!\n");
ExitProcess(0);
}
v4 = atoi((const char *)&pbData); // 感觉是转换v4的,具体没细看(感觉不太重要)
if ( v4 < 100000 ) // v4小于100000就退出
ExitProcess(0);
strcat((char *)&pbData, "@DBApp"); // 将@DBApp与pbData连接
v0 = strlen((const char *)&pbData); // v0 == 12
sub_40100A(&pbData, v0, &String1); //连接之后pbData经过处理和下面的字符串进行比较才会继续,进入该函数查看是用何种方式进行加密,可以把前面的6位数爆破出来
if ( !_strcmpi(&String1, "6E32D0943418C2C33385BC35A1470250DD8923A9") )
{
printf("continue...\n\n");
printf("pls input the first passwd(2): ");
memset(&String, 0, 0x104u);
scanf("%s", &String);
if ( strlen(&String) != 6 ) // string == 6
{
printf("Must be 6 characters!\n");
ExitProcess(0);
}
strcat(&String, (const char *)&pbData); // string == 18
memset(&String1, 0, 0x104u);
v1 = strlen(&String); // v1 == 18
sub_401019((BYTE *)&String, v1, &String1);
if ( !_strcmpi("27019e688a4e62a649fd99cadaafdb4e", &String1) )
{
if ( !sub_40100F(&String) )
{
printf("Error!!\n");
ExitProcess(0);
}
printf("bye ~~\n");
}
}
return 0;
}

进sub_40100A

2

最关键的还是这个函数

3

4

函数中第二个为ALG_ID=0x8004u,在https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id中查询,发现是SHA1加密

5

写脚本爆破出password(1)的值:

1
2
3
4
5
6
7
8
9
10
11
import hashlib
partflag = '@DBApp'
flag = ''
for i in range(100000,999999):
flag = str(i) + partflag
flaghex = hashlib.sha1(flag.encode('utf-8'))
flaghex = flaghex.hexdigest()
if "6e32d0943418c2c33385bc35a1470250dd8923a9" == flaghex:
print(flag)
break

1
123321@DBApp

同理进入sub_401019

6

查询ALG_ID=0x8003u,MD5加密

7

最简单的方法就是用网站解密工具https://www.somd5.com/

接下来还是按正常方式解,进入该函数

​ 再进入sub_401005看看,就是将我们从AAA取出的值和第二次密码连接后的字符串进行异或

用ResourceHacker查看文件中的资源

因为要生成一个.rtf的文件,而每个RTF文件都是一个文本文件,显示时由RTF阅读器格式化。文件开始处是{/rtf,它作为RTF文件的标志是必不可少的。随意看个rtf的文件头,{/rtf1/ansi/ansicpg936/deff0/deflang1033/deflangfe2052
所以取前六位,{\rtf1直接与AAA中前六个数据异或(05 7D 41 15 26 01 )。

EXP:

1
2
3
4
5
6
7
8
s = "{\rtf1"
a = [0x05,0x7D,0x41,0x15,0x26,0x01]

flag = ""
for i in range(0,len(s)):
x = ord(s[i]) ^ a[i]
flag += chr(x)
print(flag)
1
~!3a@0

最后在本地查找dbapp.rtf文件,得到flag:flag{N0_M0re_Free_Bugs}

请我喝杯咖啡吧~

支付宝
微信