BeginCTF2024 RE WP 剩下的复现

12. goforfun(寄)

前面是一些无关紧要的初始化

下面看到疑似rc4

虽然函数支离破碎,但可以看到rc4的结构,异或的部分做了魔改

后面似乎是base64换表,但脚本跑不出来,这里的算法没搞懂,只能贴一下别的dalao的

先逆后面的不明加密

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
unsigned char findPos(const unsigned char* base64_map, unsigned char c)//查找下标所在位置
{
    for (int i = 0; i < strlen((const char*)base64_map); i++)
    {
        if (base64_map[i] == c)
            return i;
    }
}
unsigned char* base64_decode(const unsigned char* code0)
{
    unsigned char* code = (unsigned char*)code0;
    unsigned char base64_map[65] = "8G+cazk2jqb7w01CtoKH4FsrgR3vVmQ9pPhXLAleOd/nB6DfIxMWYiUZ5SEJyNuT";
    long len, str_len, flag = 0;
    unsigned char* res;
    len = strlen((const char*)code);
    if (code[len - 1] == '=')
    {
        if (code[len - 2] == '=')
        {
            flag = 1;
            str_len = len / 4 * 3 - 2;
        }
        else
        {
            flag = 2;
            str_len = len / 4 * 3 - 1;
        }
    }
    else
        str_len = len / 4 * 3;
    res = (unsigned char*)malloc(sizeof(unsigned char) * str_len + 1);
    unsigned char a[4] = { 0 };
    for (int i = 0, j = 0; j < str_len - flag; j += 3, i += 4)
    {
        a[0] = findPos(base64_map, code[i]);		//code[]每一个字符对应base64表中的位置,用位置值反推原始数据值
        a[1] = findPos(base64_map, code[i + 1]);
        a[2] = findPos(base64_map, code[i + 2]);
        a[3] = findPos(base64_map, code[i + 3]);
        res[j] = a[0] | ((a[1] & 0x3) << 6);//第一个字符对应
        res[j + 1] = ((a[1] & 0x3c) >> 2) | ((a[2] & 0xf) << 4);
        res[j + 2] = ((a[3] & 0x3f) << 2) | ((a[2] & 0x30) >> 4);
    }
    switch (flag)
    {
        case 0:break;
        case 1:
            {
                a[0] = findPos(base64_map, code[len - 4]);
                a[1] = findPos(base64_map, code[len - 3]);
                res[str_len - 1] = a[0] | ((a[1] & 0x3) << 6);
                break;
            }
        case 2: {
            a[0] = findPos(base64_map, code[len - 4]);
            a[1] = findPos(base64_map, code[len - 3]);
            a[2] = findPos(base64_map, code[len - 2]);
            res[str_len - 2] = a[0] | ((a[1] & 0x3) << 6);//第一个字符对应
            res[str_len - 1] = ((a[1] & 0x3c) >> 2) | ((a[2] & 0xf) << 4);
            break;
        }
    }
    res[str_len] = '\0';
    return res;
}
int main() {
    unsigned char BaseData[] = "HZ0sMJXqxHgUb2b9RNg+1xw=";
    unsigned char* result = base64_decode(BaseData);//魔改base
    for (int i = 0; i < 17; i++)
        printf("%#x,", result[i]);
    return 0;
}
//0xd3,0xdd,0x58,0xf2,0x3e,0x26,0xf1,0x84,0xd9,0xca,0xa1,0x7c,0x59,0x8f,0x9,0x4e,0xcc,

之后rc4比较好还原一点

#goforfun wp
enc = "HZ0sMJXqxHgUb2b9RNg+1xw"
#enc = [0x48,0x5a,0x30,0x73,0x4d,0x4a,0x58,0x71,0x78,0x48,0x67,0x55,0x62,0x32,0x62,0x39,0x52,0x4e,0x67,0x2b,0x31,0x78,0x77]
key = 'happynewyear'
basemap = "8G+cazk2jqb7w01CtoKH4FsrgR3vVmQ9pPhXLAleOd/nB6DfIxMWYiUZ5SEJyNuT"
enc1=[0xd3,0xdd,0x58,0xf2,0x3e,0x26,0xf1,0x84,0xd9,0xca,0xa1,0x7c,0x59,0x8f,0x9,0x4e,0xcc]
enc2 = enc1[::-1]
#魔改rc4
s_box = [0]*256
for i in range(255,-1,-1):
    s_box[i] = - 1 - i
#print(s_box)
v8 = 0
v9 = 0
while ( v8 < 256 ):
    v10 = s_box[v8]
    v11 = v8
    v12 = v8 - 12 * (((2863311531 * v8) >> 32) >> 3)
    v9 += ord(key[v12%len(key)]) + v10
    v9 %= 256
    s_box[v11] = s_box[v9]
    s_box[v9] = v10                     
    v8 = v11 + 1
#S盒初始化
#print(s_box)
v4 = 0
v5 = 0
v6 = 0 
for i in range(len(enc2)):
    v7 = s_box[v5 + 1]%256
    v8 = (v7 + v6)%256
    s_box[v5 + 1] = s_box[v8]
    s_box[v8] = v7
    enc2[v4] ^= s_box[(v7 + s_box[v5 + 1])%256]  ^ 0x2F
    enc2[v4] &= 0xFF
    v4 += 1
    v5 += 1
    v6 = v8
flag = ''
for i in range(len(enc2)):
    flag += chr(enc2[i])
print(flag)
#go_a_nice_journey
13. 出题人的密码是什么

修花指令得到主逻辑,反调试也patch掉

然后下面有一堆函数需要找加密在哪里,只能慢慢来找,可以把翻过的函数改名字减少重复劳动

中间__rdtsc函数部分是检测时间的函数,调试的时候跳过就行

__rdtsc 是一个在 x86 和 x86-64 架构上的内建函数,它读取当前的时间戳计数器(Time Stamp Counter, TSC)。时间戳计数器是一个由 CPU 提供的 64 位寄存器,它以一种非常高的频率(通常是 CPU 的主频)自增。由于其递增的频率非常高,它常被用作一个高精度的时间源,尤其是在需要测量代码执行时间等场景中。

最后发现两个加密部分

类似CRC的部分需要动调获得key的值,虽然是随机生成的但是其值不变

修改标志寄存器SF的跳过检验

key=0x33077D

从二进制角度理解更容易逆向

和0比较实际上是比较最高位(标志位)是0还是1:

  • 如果是1(负数),就左移一位(*2)与key异或

由于key最后一位是1,v6左移一位最后一位是0,异或结果最后一位必然是1。因此逆向的时候,如果一次加密后最后一位是1,这次加密前它肯定是负数

  • 如果是0(正数),就左移一位,最后一位就变成0。同理,最后一位是0的本次加密前一定是正数。

由此可以构建逆向脚本。

简单的异或

提一下密文就可以逆了

#出题人密码
crypto = [0xB4, 0xBB, 0xD8, 0xEB, 0xD0, 0x6E, 0xAB, 0xCA, 0x65, 0x8E, 
          0x4B, 0xE9, 0x4D, 0xD4, 0x4A, 0xF3, 0x7D, 0x29, 0xC2, 0xF9, 
          0x95, 0x89, 0xA4, 0x85, 0x9D, 0xCD, 0xDF, 0x77, 0xFD, 0x45, 
          0xCB, 0x5D, 0x7D, 0xFD, 0x93, 0x4B, 0xBC, 0xF6, 0x7C, 0xF3, 
          0x24, 0x42, 0xF5, 0xD2, 0xDD, 0xE3, 0x56, 0xAE]
#异或部分逆向
enc2 = [0]*len(crypto)
for i in range(len(crypto)):
    enc2[i] = ((crypto[i] ^ 0x25) - 5) & 0xff #这边要多加括号和限制位数,不然结果会有问题
print(enc2)
key = 0x33077D
#CRC部分逆向
def decrc(value, key):
    for i in range(64):
        if value & 1: #最后一位是1,加密前肯定是负数
            value = (value ^ key) >> 1
            value |= 0x8000000000000000  #还原最高位
        else: #最后一位是0,加密前必为正数
            value = value >> 1
    return value

flag = b''
for i in range(0, len(enc2), 8):
    enc1 = int.from_bytes(enc2[i: i + 8], 'little')
    flag += decrc(enc1, key).to_bytes(8, 'little')
print(flag)
'''
[140, 153, 248, 201, 240, 70, 137, 234, 59, 166, 105, 199, 99, 236, 106, 209, 83, 7, 226, 215, 171, 167, 124, 155, 179, 227, 245, 77, 211, 91, 233, 115, 83, 211, 177, 105, 148, 206, 84, 209, 252, 98, 203, 242, 243, 193, 110, 134]
b'begin{Th1s_reverse_pr0blem_may_t@ke_some_time#!}'
'''

14. ezvm

前面有一堆内存分配也不到有啥用

flag长度为32

34行 进去一大堆数据,猜测是opcode操作码

37行 可以看到最后的密文

35、36行很奇怪,动调后可以发现是虚拟机的初始化和分发函数

似乎是形成一个结构体存储opcode里的内容

修一修数据类型得到dispatcher部分的逻辑

根据不同的操作码调用不同偏移地址的函数(有些我已经改了名字先不管)

然后分析各个函数模拟的操作(我也不会分析……只是对着官方wp稍微理解一下)

提一下opcode打印指令,好在不是所有的函数都被用到了

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
	unsigned char opcode[] =
	{
	  0x70, 0x00, 0x00, 0x00, 0x1E, 0x71, 0x30, 0x73, 0x00, 0x7A,
	  0x73, 0x10, 0x67, 0x01, 0x7B, 0x74, 0x00, 0x7A, 0x75, 0x0B,
	  0x70, 0x00, 0x00, 0x00, 0x1E, 0x71, 0x30, 0x7B, 0x75, 0x01,
	  0x70, 0x00, 0x00, 0x00, 0x1E, 0x71, 0x30, 0x73, 0x10, 0x7A,
	  0x73, 0x00, 0x6D, 0x01, 0x74, 0x00, 0x75, 0x09, 0x66
	};
	for (int i = 0; i < 49; i++)
	{
        if ((opcode[i] >= 0x66 && opcode[i] <= 0x7C) && (opcode[i - 1] >= 0x66 && opcode[i - 1] <= 0x7C))
        {
            printf("\n");
        }
		switch (opcode[i])
		{
        case 0x66:
            printf("nop  ");
            continue;
        case 0x67:
            printf("add  ");
            continue;
        case 0x68:
            printf("sub  ");
            continue;
        case 0x69:
            printf("mul  ");
            continue;
        case 0x6A:
            printf("div  ");
            continue;
        case 0x6B:
            printf("inc  ");
            continue;
        case 0x6C:
            printf("dec  ");
            continue;
        case 0x6D:
            printf("xor  ");
            continue;
        case 0x6E:
            printf("and  ");
            continue;
        case 0x6F:
            printf("push  ");
            continue;
        case 0x70:
            printf("pushd  ");
            continue;
        case 0x71:
            printf("pop  ");
            continue;
        case 0x72:
            printf("mov  ");
            continue;
        case 0x73:
            printf("movd  ");
            continue;
        case 0x74:
            printf("move2d  ");
            continue;
        case 0x75:
            printf("loop  ");
            continue;
        case 0x76:
            printf("cmp  ");
            continue;
        case 0x77:
            printf("jl  ");
            continue;
        case 0x78:
            printf("jg  ");
            continue;
        case 0x79:
            printf("jz  ");
            continue;
        case 0x7A:
            printf("incd  ");
            continue;
        case 0x7B:
            printf("decd  ");
            continue;
        case 0x7C:
            printf("xor_ops  ");
            continue;
        default:
            if (opcode[i + 1] >= 0x66 && opcode[i + 1] <= 0x7C)
            {

                printf("%#x\n", opcode[i]);
            }
            else 
            {
                printf("%#x, ", opcode[i]);
            }
            continue;
		}
	}
    return 0;
}
/*
pushd  0, 0, 0, 0x1e
pop  0x30
movd  0
incd
movd  0x10
add  0x1
decd
move2d  0
incd
loop  0xb
pushd  0, 0, 0, 0x1e
pop  0x30
decd
loop  0x1
pushd  0, 0, 0, 0x1e
pop  0x30
movd  0x10
incd
movd  0
xor  0x1
move2d  0
loop  0x9
nop
*/

然后看不懂一点,贴一下官方wp

PUSHD,  0x00, 0x00, 0x00, 0x1E, //flag length-2
POP,    0x30,         //r3 = 0x2f
MOVD,   0x00,   //loop begin r0=dd
INCD,
// d[i]+=d[i+1]
MOVD,        0x10,   // r1 = d[i]
ADD,        0x01,        // r0 += r1
DECD,        //i--
MOV2D,        0x00,
INCD,        // d[i] = r0
LOOP,        0x0B,        //loop
//i=0
PUSHD,  0x00, 0x00, 0x00, 0x1E,//flag length-2
POP,         0x30,

DECD,                        //loop begin
LOOP,        0x01,

PUSHD,  0x00, 0x00, 0x00, 0x1E,//flag length-2
POP,         0x30,

// d[i]^=d[i-1]
MOVD,        0x10,        //loop begin
INCD,
MOVD,        0x00,
XOR,        0x01,
MOV2D,        0x00,
LOOP,        0x09,        //loop
END
data = [0xC7, 0x0B, 0xDB, 0x0C, 0xE5, 0x08, 0xAD, 0xDE, 0xAF, 0xCD, 0x67, 0xBF, 0x1F, 0xBF, 0x1E, 0x68, 0xFE, 0x25, 0xFD, 0x6F, 0x08, 0x50, 0xCD, 0x15, 0xB0, 0x21, 0x8B, 0x3E, 0xFD, 0x73, 0xED, 0x90]
for i in range(len(data)-1,0,-1):
    data[i]^=data[i-1]
for i in range(len(data)-2,-1,-1):
    data[i]-=data[i+1]
print(bytes(data))
#b'begin{r3@11y_A_B4by_34$y_FK_Vm!}'
15. babyvm(寄)

完全学不懂,存一份脚本吧

opcode=[]
with open('opcode.vm','rb') as file:
    content=file.read()
    for i in range(0,len(content),4):
        opcode1=int.from_bytes(content[i:i+4],byteorder='little',signed=True)
        opcode.append(opcode1)
memory=[]
with open('memory.vm','rb') as file:
    content=file.read()
    for i in range(0,len(content),4):
        memory1=int.from_bytes(content[i:i+4],byteorder='little',signed=True)
        memory.append(memory1)
opcode_key = {
    1:'{} add {} {}',
    2:'{} sub {} {}',
    3:'{} mul {} {}',
    4:'{} div {} {}',
    5:'{} in_pointer 0',
    6:'{} out_pointer 0',
    7:'{} push flag',
    8:'{} pop output',
    9:'{} scanf flag',
    10:'{} show flag',
    11:'{} jmp {}',
    12:'{} njmp ',
    13:'{} len',
}
def get_eip(eip):
  return '_' + str(eip) + ':'
v16=opcode
i=0
disam=''
while i>=0 and i< len(opcode):
    x=v16[i]
    if x == 1:
        disam += opcode_key[x].format(get_eip(i), memory[v16[(i + 2)]], memory[v16[(i + 2 + 1)]]) + '\n'
        memory[v16[i + 1]] = memory[v16[i + 2]] + memory[v16[i + 2 + 1]]
        i += 3 + 1
        continue
    if x == 2:
        disam += opcode_key[x].format(get_eip(i), memory[v16[(i + 2 + 1)]], memory[v16[(i + 2)]]) + '\n'
        memory[v16[i + 1]] =  memory[v16[i + 2]] + memory[v16[i + 2 + 1]]
        #print(memory[v16[i + 1]])+'\n')
        i += 3 + 1
        continue
    if x == 3:
        disam += opcode_key[x].format(get_eip(i), memory[v16[(i + 2)]], memory[v16[(i + 2 + 1)]]) + '\n'
        memory[v16[i + 1]] = memory[v16[i + 2]] * memory[v16[i + 2 + 1]]
        print(memory[v16[i + 1 +2]])
        print(',')
        i += 3 + 1
        continue
    if x == 4:
        disam += opcode_key[x].format(get_eip(i), memory[v16[(i + 2)]], memory[v16[(i + 2 + 1)]]) + '\n'
        memory[v16[i + 1]] = memory[v16[i + 2]] / memory[v16[i + 2 + 1]]
        i += 3 + 1
        continue
    if x == 5:
        disam += opcode_key[x].format(get_eip(i)) + '\n'
        v5 = 0
        i += v5 + 1
        continue
    if x == 6:
        disam += opcode_key[x].format(get_eip(i)) + '\n'
        v6 = 0
        i += v6 + 1
        continue
    if x == 7:
        disam += opcode_key[x].format(get_eip(i)) + '\n'
        v7 = 2
        i += v7 + 1
        continue
    if x == 8:
        disam += opcode_key[x].format(get_eip(i)) + '\n'
        v8 = 2
        i += v8 + 1
        continue
    if x == 9:
        disam += opcode_key[x].format(get_eip(i)) + '\n'
        buf = 1
        i += buf + 1
        continue
    if x == 10:
        disam += opcode_key[x].format(get_eip(i)) + '\n'
        v10 = 1
        i += v10 + 1
        continue
    if x == 11:
        disam += opcode_key[x].format(get_eip(i), memory[v16[(i + 1)]]) + '\n'
        v11 = 2
        i += v11 + 1
        continue
    if x == 12:
        disam += opcode_key[x].format(get_eip(i)) + '\n'
        v12 = 2
        i += v12 + 1
        continue
    if x == 13:
        disam += opcode_key[x].format(get_eip(i)) + '\n'
        v13 = 2
        i += v13 + 1
        continue
    disam+='exit(0)\n'
    i += 1
    continue
#print(disam)
from z3 import *
flag = []
key = [115
,
26
,
128
,
200
,
21
,
234
,
172
,
152
,
39
,
71
,
55
,
28
,
105
,
42
,
75
,
63
,
114
,
205
,
2
,
222
,
212
,
148
,
17
,
74
,
87
,
253
,
250
,
136
,
89
,
211
,
49
,
26
,
115
,
88
,
181
,
195
,
237
,
10
,
119
,
121
,
229
,
172
,
230
,
123
,
245
,
127
,
119
,
157
,
208
,
159
,
37
,
32
,
5
,
207
,
145
,
75
,
251
,
60
,
135
,
125
,
181
,
83
,
66
,
43
,
85
,
198
,
89
,
205
,
114
,
221
,
105
,
145
,
155
,
91
,
123
,
48
,
76
,
64
,
141
,
22
,
211
,
225
,
204
,
55
,
107
,
76
,
7
,
39
,
199
,
84
,
167
,
62
,
219
,
54
,
6
,
144
,
55
,
98
,
186
,
116
,
149
,
163
,
127
,
186
,
46
,
118
,
247
,
194
,
9
,
165
,
169
,
224
,
68
,
129
,
54
,
15
,
134
,
39
,
185
,
248
,
245
,
159
,
64
,
241
,
163
,
116
,
4
,
15
,
126
,
170
,
10
,
110
,
251
,
169
,
252
,
99
,
199
,
188
,
149
,
72
,
233
,
38
,
197
,
105
,
202
,
2
,
22
,
225
,
189
,
166
,
239
,
220
,
70
,
98
,
194
,
129
,
27
,
236
,
159
,
62
,
152
,
67
,
72
,
35
,
12
,
55
,
139
,
4
,
169
,
142
,
135
,
122
,
3
,
166
,
139
,
62
,
23
,
92
,
11
,
136
,
96
,
141
,
38
,
124
,
139
,
43
,
15
,
119
,
30
,
252
,
255
,
123
,
223
,
200
,
21
,
117
,
231
,
9
,
239
,
222
,
249
,
91
,
66
,
21
,
121
,
146
,
5
,
180
,
6
,
80
,
112
,
255
,
239
,
17
,
39
,
254
,
153
,
118
,
47
,
217
,
84
,
96
,
190
,
188
,
255
,
181
,
188
,
124
,
47
,
70
,
201
,
160
,
126
,
210
,
236
,
22
,
120
,
181
,
197
,
69
,
51
,
173
,
216
,
143
,
41
,
174
,
184
,
189
,
111
,
133
,
79
,
36
,
99
,
140
,
120
,
144
,
80
,
231
,
187
,
107
,
173
,
39
,
151
,
161
,
139
,
233
,
143
,
205
,
170
,
125
,
209
,
54
,
128
,
134
,
55
,
246
,
157
,
57
,
42
,
195
,
5
,
49
,
235
,
8
,
84
,
9
,
219
,
90
,
109
,
164
,
38
,
159
,
218
,
214
,
22
,
205
,
7
,
57
,
210
,
131
,
107
,
67
,
107
,
141
,
129
,
250
,
97
,
3
,
26
,
215
,
119
,
213
,
255
,
183
,
229
,
1
,
27
,
9
,
88
,
59
,
57
,
72
,
91
,
96
,
125
,
105
,
94
,
235
,
138
,
39
,
145
,
130
,
126
,
147
,
254
,
179
,
181
,
183
,
216
,
211
,
164
,
205
,
28
,
160
,
233
,
70
,
109
,
51
,
0
,
71
,
99
,
163
,
37
,
98
,
46
,
44
,
138
,
135
,
191
,
144
,
13
,
240
,
143
,
53
,
75
,
23
,
26
,
224
,
31
,
199
,
182
,
220
,
130
,
61
,
170
,
130
,
253
,
240
,
182
,
9
,
245
,
96
,
170
,
79
,
249
,
16
,
121
,
6
,
7
,
69
,
212
,
133
,
52
,
20
,
225
,
102
,
228
,
121
,
56
,
208
]
v = [217114,270581,291585,234325,240502,277604,286168,290450,179355,272487,249816,305636,276217,294166,237236,242008,289929,221788,268459,247407]
for i in range(20):
    flag.append(BitVec('%d' % i, 8))    #char型
s = Solver()
s.add(flag[0]*key[0]+flag[1]*key[1]+flag[2]*key[2]+flag[3]*key[3]+flag[4]*key[4]+flag[5]*key[5]+flag[6]*key[6]+flag[7]*key[7]+flag[8]*key[8]+flag[9]*key[9]+flag[10]*key[10]+flag[11]*key[11]+flag[12]*key[12]+flag[13]*key[13]+flag[14]*key[14]+flag[15]*key[15]+flag[16]*key[16]+flag[17]*key[17]+flag[18]*key[18]+flag[19]*key[19]==v[0])
s.add(flag[0]*key[20]+flag[1]*key[21]+flag[2]*key[22]+flag[3]*key[23]+flag[4]*key[24]+flag[5]*key[25]+flag[6]*key[26]+flag[7]*key[27]+flag[8]*key[28]+flag[9]*key[29]+flag[10]*key[30]+flag[11]*key[31]+flag[12]*key[32]+flag[13]*key[33]+flag[14]*key[34]+flag[15]*key[35]+flag[16]*key[36]+flag[17]*key[37]+flag[18]*key[38]+flag[19]*key[39]==v[1])
s.add(flag[0]*key[40]+flag[1]*key[41]+flag[2]*key[42]+flag[3]*key[43]+flag[4]*key[44]+flag[5]*key[45]+flag[6]*key[46]+flag[7]*key[47]+flag[8]*key[48]+flag[9]*key[49]+flag[10]*key[50]+flag[11]*key[51]+flag[12]*key[52]+flag[13]*key[53]+flag[14]*key[54]+flag[15]*key[55]+flag[16]*key[56]+flag[17]*key[57]+flag[18]*key[58]+flag[19]*key[59]==v[2])
s.add(flag[0]*key[60]+flag[1]*key[61]+flag[2]*key[62]+flag[3]*key[63]+flag[4]*key[64]+flag[5]*key[65]+flag[6]*key[66]+flag[7]*key[67]+flag[8]*key[68]+flag[9]*key[69]+flag[10]*key[70]+flag[11]*key[71]+flag[12]*key[72]+flag[13]*key[73]+flag[14]*key[74]+flag[15]*key[75]+flag[16]*key[76]+flag[17]*key[77]+flag[18]*key[78]+flag[19]*key[79]==v[3])
s.add(flag[0]*key[80]+flag[1]*key[81]+flag[2]*key[82]+flag[3]*key[83]+flag[4]*key[84]+flag[5]*key[85]+flag[6]*key[86]+flag[7]*key[87]+flag[8]*key[88]+flag[9]*key[89]+flag[10]*key[90]+flag[11]*key[91]+flag[12]*key[92]+flag[13]*key[93]+flag[14]*key[94]+flag[15]*key[95]+flag[16]*key[96]+flag[17]*key[97]+flag[18]*key[98]+flag[19]*key[99]==v[4])
s.add(flag[0]*key[100]+flag[1]*key[101]+flag[2]*key[102]+flag[3]*key[103]+flag[4]*key[104]+flag[5]*key[105]+flag[6]*key[106]+flag[7]*key[107]+flag[8]*key[108]+flag[9]*key[109]+flag[10]*key[110]+flag[11]*key[111]+flag[12]*key[112]+flag[13]*key[113]+flag[14]*key[114]+flag[15]*key[115]+flag[16]*key[116]+flag[17]*key[117]+flag[18]*key[118]+flag[19]*key[119]==v[5])
s.add(flag[0]*key[120]+flag[1]*key[121]+flag[2]*key[122]+flag[3]*key[123]+flag[4]*key[124]+flag[5]*key[125]+flag[6]*key[126]+flag[7]*key[127]+flag[8]*key[128]+flag[9]*key[129]+flag[10]*key[130]+flag[11]*key[131]+flag[12]*key[132]+flag[13]*key[133]+flag[14]*key[134]+flag[15]*key[135]+flag[16]*key[136]+flag[17]*key[137]+flag[18]*key[138]+flag[19]*key[139]==v[6])
s.add(flag[0]*key[140]+flag[1]*key[141]+flag[2]*key[142]+flag[3]*key[143]+flag[4]*key[144]+flag[5]*key[145]+flag[6]*key[146]+flag[7]*key[147]+flag[8]*key[148]+flag[9]*key[149]+flag[10]*key[150]+flag[11]*key[151]+flag[12]*key[152]+flag[13]*key[153]+flag[14]*key[154]+flag[15]*key[155]+flag[16]*key[156]+flag[17]*key[157]+flag[18]*key[158]+flag[19]*key[159]==v[7])
s.add(flag[0]*key[160]+flag[1]*key[161]+flag[2]*key[162]+flag[3]*key[163]+flag[4]*key[164]+flag[5]*key[165]+flag[6]*key[166]+flag[7]*key[167]+flag[8]*key[168]+flag[9]*key[169]+flag[10]*key[170]+flag[11]*key[171]+flag[12]*key[172]+flag[13]*key[173]+flag[14]*key[174]+flag[15]*key[175]+flag[16]*key[176]+flag[17]*key[177]+flag[18]*key[178]+flag[19]*key[179]==v[8])
s.add(flag[0]*key[180]+flag[1]*key[181]+flag[2]*key[182]+flag[3]*key[183]+flag[4]*key[184]+flag[5]*key[185]+flag[6]*key[186]+flag[7]*key[187]+flag[8]*key[188]+flag[9]*key[189]+flag[10]*key[190]+flag[11]*key[191]+flag[12]*key[192]+flag[13]*key[193]+flag[14]*key[194]+flag[15]*key[195]+flag[16]*key[196]+flag[17]*key[197]+flag[18]*key[198]+flag[19]*key[199]==v[9])
s.add(flag[0]*key[200]+flag[1]*key[201]+flag[2]*key[202]+flag[3]*key[203]+flag[4]*key[204]+flag[5]*key[205]+flag[6]*key[206]+flag[7]*key[207]+flag[8]*key[208]+flag[9]*key[209]+flag[10]*key[210]+flag[11]*key[211]+flag[12]*key[212]+flag[13]*key[213]+flag[14]*key[214]+flag[15]*key[215]+flag[16]*key[216]+flag[17]*key[217]+flag[18]*key[218]+flag[19]*key[219]==v[10])
s.add(flag[0]*key[220]+flag[1]*key[221]+flag[2]*key[222]+flag[3]*key[223]+flag[4]*key[224]+flag[5]*key[225]+flag[6]*key[226]+flag[7]*key[227]+flag[8]*key[228]+flag[9]*key[229]+flag[10]*key[230]+flag[11]*key[231]+flag[12]*key[232]+flag[13]*key[233]+flag[14]*key[234]+flag[15]*key[235]+flag[16]*key[236]+flag[17]*key[237]+flag[18]*key[238]+flag[19]*key[239]==v[11])
s.add(flag[0]*key[240]+flag[1]*key[241]+flag[2]*key[242]+flag[3]*key[243]+flag[4]*key[244]+flag[5]*key[245]+flag[6]*key[246]+flag[7]*key[247]+flag[8]*key[248]+flag[9]*key[249]+flag[10]*key[250]+flag[11]*key[251]+flag[12]*key[252]+flag[13]*key[253]+flag[14]*key[254]+flag[15]*key[255]+flag[16]*key[256]+flag[17]*key[257]+flag[18]*key[258]+flag[19]*key[259]==v[12])
s.add(flag[0]*key[260]+flag[1]*key[261]+flag[2]*key[262]+flag[3]*key[263]+flag[4]*key[264]+flag[5]*key[265]+flag[6]*key[266]+flag[7]*key[267]+flag[8]*key[268]+flag[9]*key[269]+flag[10]*key[270]+flag[11]*key[271]+flag[12]*key[272]+flag[13]*key[273]+flag[14]*key[274]+flag[15]*key[275]+flag[16]*key[276]+flag[17]*key[277]+flag[18]*key[278]+flag[19]*key[279]==v[13])
s.add(flag[0]*key[280]+flag[1]*key[281]+flag[2]*key[282]+flag[3]*key[283]+flag[4]*key[284]+flag[5]*key[285]+flag[6]*key[286]+flag[7]*key[287]+flag[8]*key[288]+flag[9]*key[289]+flag[10]*key[290]+flag[11]*key[291]+flag[12]*key[292]+flag[13]*key[293]+flag[14]*key[294]+flag[15]*key[295]+flag[16]*key[296]+flag[17]*key[297]+flag[18]*key[298]+flag[19]*key[299]==v[14])
s.add(flag[0]*key[300]+flag[1]*key[301]+flag[2]*key[302]+flag[3]*key[303]+flag[4]*key[304]+flag[5]*key[305]+flag[6]*key[306]+flag[7]*key[307]+flag[8]*key[308]+flag[9]*key[309]+flag[10]*key[310]+flag[11]*key[311]+flag[12]*key[312]+flag[13]*key[313]+flag[14]*key[314]+flag[15]*key[315]+flag[16]*key[316]+flag[17]*key[317]+flag[18]*key[318]+flag[19]*key[319]==v[15])
s.add(flag[0]*key[320]+flag[1]*key[321]+flag[2]*key[322]+flag[3]*key[323]+flag[4]*key[324]+flag[5]*key[325]+flag[6]*key[326]+flag[7]*key[327]+flag[8]*key[328]+flag[9]*key[329]+flag[10]*key[330]+flag[11]*key[331]+flag[12]*key[332]+flag[13]*key[333]+flag[14]*key[334]+flag[15]*key[335]+flag[16]*key[336]+flag[17]*key[337]+flag[18]*key[338]+flag[19]*key[339]==v[16])
s.add(flag[0]*key[340]+flag[1]*key[341]+flag[2]*key[342]+flag[3]*key[343]+flag[4]*key[344]+flag[5]*key[345]+flag[6]*key[346]+flag[7]*key[347]+flag[8]*key[348]+flag[9]*key[349]+flag[10]*key[350]+flag[11]*key[351]+flag[12]*key[352]+flag[13]*key[353]+flag[14]*key[354]+flag[15]*key[355]+flag[16]*key[356]+flag[17]*key[357]+flag[18]*key[358]+flag[19]*key[359]==v[17])
s.add(flag[0]*key[360]+flag[1]*key[361]+flag[2]*key[362]+flag[3]*key[363]+flag[4]*key[364]+flag[5]*key[365]+flag[6]*key[366]+flag[7]*key[367]+flag[8]*key[368]+flag[9]*key[369]+flag[10]*key[370]+flag[11]*key[371]+flag[12]*key[372]+flag[13]*key[373]+flag[14]*key[374]+flag[15]*key[375]+flag[16]*key[376]+flag[17]*key[377]+flag[18]*key[378]+flag[19]*key[379]==v[18])
s.add(flag[0]*key[380]+flag[1]*key[381]+flag[2]*key[382]+flag[3]*key[383]+flag[4]*key[384]+flag[5]*key[385]+flag[6]*key[386]+flag[7]*key[387]+flag[8]*key[388]+flag[9]*key[389]+flag[10]*key[390]+flag[11]*key[391]+flag[12]*key[392]+flag[13]*key[393]+flag[14]*key[394]+flag[15]*key[395]+flag[16]*key[396]+flag[17]*key[397]+flag[18]*key[398]+flag[19]*key[399]==v[19])
if s.check() == sat:
    print(s.model())

end={18 : 97,
 2 : 118, 
 12 : 118,
 13 : 109,
 3 : 101, 
 10 : 110,
 15 : 104,
 17 : 104,
 7 : 110,
 16 : 97,
 5 : 102,
 14 : 95,
 9 : 105,
 6 : 117,
 11 : 95,
 1 : 97,
 19 : 97,
 8 : 95,
 0 : 104,
 4 : 95}
flag=''
for i in range(20):
    flag+=chr(end[i])
print(flag)
16. 真龙之力

尝试安装失败,是因为xml被改了

可以用MT管理器或者AndroidKiller修改AndroidManifest.xml

调用者不被允许测试的测试程序-CSDN博客文章浏览阅读2.3k次。报错:调用者不被允许测试的测试程序原因:未对测试功能加以限制(直接从Android Studio调试运行应该默认是开了调试模式)解决方法: 在application标签里面添加android:testOnly="false"属性即可..._调用者不被允许测试的测试程序https://blog.csdn.net/kicinio/article/details/117232493#:~:text=%E6%8A%A5%E9%94%99%EF%BC%9A%E8%B0%83%E7%94%A8%E8%80%85%E4%B8%8D%E8%A2%AB%E5%85%81%E8%AE%B8%E6%B5%8B%E8%AF%95%E7%9A%84%E6%B5%8B%E8%AF%95%E7%A8%8B%E5%BA%8F%E5%8E%9F%E5%9B%A0%EF%BC%9A%E6%9C%AA%E5%AF%B9%E6%B5%8B%E8%AF%95%E5%8A%9F%E8%83%BD%E5%8A%A0%E4%BB%A5%E9%99%90%E5%88%B6%EF%BC%88%E7%9B%B4%E6%8E%A5%E4%BB%8EAndroid%20Studio%E8%B0%83%E8%AF%95%E8%BF%90%E8%A1%8C%E5%BA%94%E8%AF%A5%E9%BB%98%E8%AE%A4%E6%98%AF%E5%BC%80%E4%BA%86%E8%B0%83%E8%AF%95%E6%A8%A1%E5%BC%8F%EF%BC%89%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95%EF%BC%9A,%3Capplication...%20android%3AtestOnly%3D%22false%22...%20%3C%2Fapplication%3E%E5%9C%A8application%E6%A0%87%E7%AD%BE%E9%87%8C%E9%9D%A2%E6%B7%BB%E5%8A%A0android%3AtestOnly%3D%22false%22%E5%B1%9E%E6%80%A7%E5%8D%B3%E5%8F%AF..._%E8%B0%83%E7%94%A8%E8%80%85%E4%B8%8D%E8%A2%AB%E5%85%81%E8%AE%B8%E6%B5%8B%E8%AF%95%E7%9A%84%E6%B5%8B%E8%AF%95%E7%A8%8B%E5%BA%8F

MT管理器

改一下即可

AndroidKiller方便一点

安装后需要key和ID

jadx看一下源码

第一个按钮做了加密

具体逻辑在lib的libdragon.so里面

第二个按钮也进行了一些加密

进行了类似于RC4初始化的打乱,但没有异或操作,也就是说只是改变了顺序,可以用索引还原。

解压apk用IDA分析libdragon.so

应该是以v43作为xtea的key,把v42加密了,加密后的KEY(v42)应该在这

解一下KEY

#include<stdio.h>
#include<string.h>
int main()
{
	unsigned int __cdecl xtea_decryption(unsigned int* a1, const unsigned int* a2);
	//unsigned int teakey[4] = { 0x76543210 , 0xFEDCBA98 , 0x89ABCDEF, 0x1234567 };
	unsigned int teakey[4] = { 0x1234567, 0x89ABCDEF , 0xFEDCBA98 , 0x76543210 };
	unsigned int enc[4] = { 0x1b253544,0xfcc56bb0 };
	xtea_decryption(enc, teakey);
	printf("%x\n", enc);
	printf("%s", enc);
	return 0;
}
unsigned int __cdecl xtea_decryption(unsigned int* a1, const unsigned int* a2)
{
	unsigned int result; // eax
	int i; // [esp+0h] [ebp-18h]
	unsigned int sum; // [esp+8h] [ebp-10h]
	unsigned int v5; // [esp+Ch] [ebp-Ch]
	unsigned int v6; // [esp+10h] [ebp-8h]

	v6 = *a1;
	v5 = a1[1];
	sum = 0x9E3779B9 *32;
	for (i = 0; i < 32; ++i)
	{
		v5 -= (a2[(sum >> 11) & 3] + sum) ^ (v6 + ((v6 >> 4) ^ (32 * v6)));
		sum -= 0x9E3779B9;
		v6 -= (a2[sum & 3] + sum) ^ (v5 + ((v5 >> 4) ^ (32 * v5)));
	}
	*a1 = v6;
	result = v5;
	a1[1] = v5;
	return result;
}
//e4aff8a8
//4202SDYY

端序问题跑出来是反的 YYDS2024

打乱的密文 i{biecfuialflnlv_eegieo}Ntt

长度为27,我们输入一串长度27的字符串来查索引

输出vfaxnwtidyzulemjrqbckhs0gop

#dragonindex exp
table = "abcdefghijklmnopqrstuvwxyz0"
back = "vfaxnwtidyzulemjrqbckhs0gop"
enc = "i{biecfuialflnlv_eegieo}Ntt"
for i in table:
    print(enc[back.index(i)],end="")
#begin{Neuvillette_official}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/391855.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

layui表格中使用cascader后导致表格滚动条消失

修改前&#xff0c;受影响页面 修改后最终想要的效果 修改方法

智慧校园规划建设方案

校园信息化建设呈现智能化、应用多样化发展趋势&#xff0c;多种技术和应用交叉渗透至校园生活的各个方面&#xff0c;全面的智慧校园时代已经到来。 对智慧校园的四大应用领域分析 智慧的教学 信息共享交互&#xff1a;建立信息发布、共享、传播与交互的公共平台 教学流程…

torch.utils.data

整体架构 平时使用 pytorch 加载数据时大概是这样的&#xff1a; import numpy as np from torch.utils.data import Dataset, DataLoaderclass ExampleDataset(Dataset):def __init__(self):self.data [1, 2, 3, 4, 5]def __getitem__(self, idx):return self.data[idx]def…

Linux: GDB 调试工具

目录 概念&#xff1a; Linux 下 debug 和 release 的区别&#xff1a; GDB 的使用 &#xff1a; 激活和进入工作模式&#xff1a; 查看文件的内容&#xff1a; 运行调试的文件&#xff1a; 打断点&#xff1a; 查看断点&#xff1a; 删除断点&#xff1a; 禁用断点…

17.3.1.3 灰度

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 灰度的算法主要有以下三种&#xff1a; 1、最大值法: 原图像&#xff1a;颜色值color&#xff08;R&#xff0c;G&#xff0c;B&a…

wayland(xdg_wm_base) client 使用 dmabuf 最简实例

文章目录 前言一、zwp_linux_dmabuf_v1 协议二、wayland client 使用 zwp_linux_dmabuf_v1 协议传递dma-buf代码实例1. wayland_dmabuf.c 代码实例2. xdg-shell-protocol.c 和 xdg-shell-client-protocol.h3. linux-dmabuf-unstable-v1-client-protocol.h 和 linux-dmabuf-unst…

如何在JavaScript中使用大于和小于运算符

在你的 JavaScript 程序中&#xff0c;你经常需要比较两个值&#xff0c;以确定一个是否大于另一个或小于另一个。这就是大于和小于运算符派上用场的地方。 在本文中&#xff0c;我们将通过代码示例更详细地介绍如何使用这些运算符。 &#xff08;本文内容参考&#xff1a;ja…

Stable Diffusion 模型下载:Beautiful Realistic Asians(美丽真实的亚洲人)

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十 下载地址 模型介绍 Beautiful Realistic Asians&#xff08;BRA&#xff09;模型是由作者自己训练…

阿里云服务器租用价格 2024年新版活动报价及租用收费标准

2024年最新阿里云服务器租用费用优惠价格表&#xff0c;轻量2核2G3M带宽轻量服务器一年61元&#xff0c;折合5元1个月&#xff0c;新老用户同享99元一年服务器&#xff0c;2核4G5M服务器ECS优惠价199元一年&#xff0c;2核4G4M轻量服务器165元一年&#xff0c;2核4G服务器30元3…

NumPyML 源码解析(四)

numpy-ml\numpy_ml\neural_nets\utils\__init__.py """ 神经网络特定的常见辅助函数。neural_nets.utils 模块包含神经网络特定的辅助函数&#xff0c;主要用于处理 CNNs。 """# 从当前目录下的 utils 模块中导入所有内容 from .utils import *…

天锐绿盾|防泄密系统|计算机文件数据\资料安全管理软件

“天锐绿盾”似乎是一款专注于防泄密和计算机文件数据/资料安全管理的软件。在信息安全日益受到重视的今天&#xff0c;这样的软件对于保护企业的核心数据资产和防止敏感信息泄露至关重要。 通用地址&#xff1a;www.drhchina.com 防泄密系统的主要功能通常包括&#xff1a; 文…

组合数的计算

1.由定义式直接算&#xff1a;n!/m!*(n-m)! #include <iostream> using namespace std; long long combine(long long m,long long n ){long long result1;for(int i1;i<n1;i){//n!result*i;}for(int i1;i<m1;i){//n!/m!result/i;}for(int i1;i<n-m1;i){//n!/(…

红蓝对抗:网络安全领域的模拟实战演练

引言&#xff1a; 随着信息技术的快速发展&#xff0c;网络安全问题日益突出。为了应对这一挑战&#xff0c;企业和组织需要不断提升自身的安全防护能力。红蓝对抗作为一种模拟实战演练方法&#xff0c;在网络安全领域得到了广泛应用。本文将介绍红蓝对抗的概念、目的、过程和…

问卷设计初探:题目类型概览与注意事项梳理

问卷法常被人们应用于社会调查中&#xff0c;它能反馈出最真实的社会信息。所以&#xff0c;很多企业为了最大程度地了解市场&#xff0c;也经常使用问卷调查法进行研究。不过&#xff0c;想要发挥出问卷法的最大用处&#xff0c;前提是要将问卷设计规范并且可量化。 想要设计…

【漏洞复现】企语iFair协同管理系统任意文件读取漏洞

Nx01 产品简介 企语iFair协同管理系统是一款专业的协同办公软件&#xff0c;该管理系统兼容性强&#xff0c;适合多种企业类型。 Nx02 漏洞描述 企语iFair协同管理系统存在任意文件读取漏洞&#xff0c;未经身份认证的攻击者可以通过此漏洞获取服务器敏感信息。 Nx03 产品主页…

租房招聘|在线租房和招聘平台|基于Springboot的在线租房和招聘平台设计与实现(源码+数据库+文档)

在线租房和招聘平台目录 目录 基于Springboot的在线租房和招聘平台设计与实现 一、前言 二、系统功能设计 三、系统实现 1、房屋管理 2、招聘管理 3、平台资讯管理 4、平台资讯类型管理 四、数据库设计 1、实体ER图 六、论文参考 七、最新计算机毕设选题推荐 八、源…

小白必看,总结前端所有主流的构建工具,webpack / vite / roollup / esbuild,包含源码,建议关注+收藏

前言 本篇文章旨在总结前端常见的构建工具&#xff0c;构建工具是前端工程化中的重要的组成部分。 在实际项目中&#xff0c;我们初始化项目&#xff0c;一般是使用脚手架命令一键生成的&#xff0c;比如说使用 create-vue 初始化 vue 项目的时候&#xff0c;就会默认使用 vi…

力扣 123. 买卖股票的最佳时机 III

题目来源&#xff1a;https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iii/description/ C题解&#xff1a;动态规划。至多买卖两次&#xff0c;这意味着可以买卖一次&#xff0c;可以买卖两次&#xff0c;也可以不买卖。 一天一共就有四个状态&#xff1a; 第…

报文鉴别、实体鉴别

目录 鉴别 1 报文鉴别 1.1 用数字签名进行鉴别&#xff08;原理&#xff09; 可保证机密性的数字签名 1.2 密码散列函数 MD5 算法 MD5 算法计算步骤 安全散列算法 SHA-1 1.3 用报文鉴别码实现报文鉴别 用报文鉴别码 MAC 鉴别报文 使用已签名的报文鉴别码 MAC 对报…

论文阅读:MotionNet基于鸟瞰图的自动驾驶联合感知和运动预测

MotionNet: Joint Perception and Motion Prediction for Autonomous Driving Based on Bird’s Eye View Maps MotionNet&#xff1a;基于鸟瞰图的自动驾驶联合感知和运动预测 论文地址&#xff1a;MotionNet: Joint Perception and Motion Prediction for Autonomous Drivi…