前言

因为国护, 去不了,只打了逆向区就溜了。

另外的题目是后来复现的

Android - sm4

打开,apk名字app-release_10_jiagu_sign , 以为是要去加固,然后也确实有加固,刚开始没敢写。

image-20230717100625085

写题的话,应该先看程序是干嘛的,就是说,运行看题,然后的话,发现有两个字符串

进入 – 159762dr7vh438sa

image-20230717104522000

点击按钮 – 1313131313131313

image-20230717104532258

可以使用,frida-dex脱掉加固的dex壳,好像是整壳

法一:静态分析

主要逻辑在so层中,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
int __fastcall Java_com_ctf_jniex_MainActivity2_decrypt(int a1, int a2, int a3, int a4)
{
char *v7; // r0
char *v8; // r0
_BYTE *v9; // r1
int v10; // r4
char v12[8]; // [sp+0h] [bp-40h] BYREF
void *v13; // [sp+8h] [bp-38h]
char v14[8]; // [sp+Ch] [bp-34h] BYREF
void *v15; // [sp+14h] [bp-2Ch]
unsigned __int8 v16; // [sp+18h] [bp-28h] BYREF
_BYTE v17[3]; // [sp+19h] [bp-27h] BYREF
void *p; // [sp+20h] [bp-20h]

sm4::setType(&s, 1);
v7 = (char *)(*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)a1 + 676))(a1, a3, 0);
std::string::basic_string<decltype(nullptr)>((int)&v16, v7);
sm4::setIv(&s, &v16);
if ( v16 << 31 )
operator delete(p);
v8 = (char *)(*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)a1 + 676))(a1, a4, 0);
std::string::basic_string<decltype(nullptr)>((int)&v16, v8);
sm4::setKey(&s, &v16);
if ( v16 << 31 )
operator delete(p);
std::string::basic_string<decltype(nullptr)>(
(int)v12,
"663630067D8CD8A2D819CCE0996A2FC49AEA6B31CCCC2EEE5BE59BFA0B56597CCECA2F502A4D1F92E3BC731D915E9CE4");
HexToStr(v14, v12);
sm4::decrypt(&v16, &s, v14);
if ( (unsigned __int8)v14[0] << 31 )
operator delete(v15);
if ( (unsigned __int8)v12[0] << 31 )
operator delete(v13);
v9 = p;
if ( !(v16 << 31) )
v9 = v17;
v10 = (*(int (__fastcall **)(int, _BYTE *))(*(_DWORD *)a1 + 668))(a1, v9);
if ( v16 << 31 )
operator delete(p);
return v10;
}

发现了密文663630067D8CD8A2D819CCE0996A2FC49AEA6B31CCCC2EEE5BE59BFA0B56597CCECA2F502A4D1F92E3BC731D915E9CE4

3个显眼函数sm4::setKey和sm4::setIv还有sm4::decrypt

根据函数传参的顺序,进行sm4解密

cyberchef得到答案

flag{just!_enjoy!_the_match!_zyc_2022}

image-20230717102318579

法二:frida hook

hookJava_com_ctf_jniex_MainActivity2_decrypt函数

其实点击按钮是setiv

那么刚开始的界面里面呢是setkey,不过呢,那个字符串是传不进去了

应该出题人就是让你将之传进去然后调用Decrypt解密

那么编写hook,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function hook() {
var base = Module.findBaseAddress("libjniex.so")
var sub_31388 = base.add(0x31388 + 0x1);
Interceptor.attach(sub_31388, {
onEnter: function(args) {
console.log('[*] sub_31388 (sm4_decrypt) called');
var env = Java.vm.getEnv();
args[3] = env.newStringUtf('159762dr7vh438sa');
console.log('[*] iv: ' + hexdump(env.getStringUtfChars(args[2], 0)));
console.log('[*] key: ' + hexdump(env.getStringUtfChars(args[3], 0)));
},
OnLeave:function(retval){
console.log('ret == ' + retval);
}

});


}

setImmediate(hook);
image-20230717104759462

Animals - 花指令+魔改md5+混淆

运行程序,交互九次

image-20230717105222369

ida64分析,定位main函数,显然发现花指令,好几处,nop掉即可

image-20230717101137493

使用插件快速nop掉

当然也可以写个脚本自动去除

1
2
3
4
5
6
7
8
9
10
import idc
start_add = 0x400800
end_add = 0x406e22
for i in range(start_add,end_add):
if idc.get_wide_dword(i) == 0x08750a74:
for mm in range(9):
ida_bytes.patch_byte(i+mm,0x90)
elif idc.get_wide_dword(i) == 0x13751574:
for m in range(23):
ida_bytes.patch_byte(i+m,0x90)

image-20230717101305555

修复完成后,发现了混淆,使用插件d810去除

去除后代码

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
size_t v3; // rax
size_t v4; // rax
size_t v5; // rax
size_t v6; // rax
size_t v7; // rax
size_t v8; // rax
unsigned int anms_len; // eax
const char *v11; // [rsp+68h] [rbp-2C8h]
const char *v12; // [rsp+80h] [rbp-2B0h]
const char *v13; // [rsp+98h] [rbp-298h]
const char *v14; // [rsp+B0h] [rbp-280h]
const char *v15; // [rsp+C8h] [rbp-268h]
char *src; // [rsp+E0h] [rbp-250h]
int j; // [rsp+144h] [rbp-1ECh]
int data[22]; // [rsp+148h] [rbp-1E8h] BYREF
char output[24]; // [rsp+1A0h] [rbp-190h] BYREF
int input; // [rsp+1B8h] [rbp-178h] BYREF
int i; // [rsp+1BCh] [rbp-174h]
char animals[256]; // [rsp+1C0h] [rbp-170h] BYREF
char *s; // [rsp+2C0h] [rbp-70h] BYREF
char *v24; // [rsp+2C8h] [rbp-68h]
char *v25; // [rsp+2D0h] [rbp-60h]
char *v26; // [rsp+2D8h] [rbp-58h]
char *v27; // [rsp+2E0h] [rbp-50h]
char *v28; // [rsp+2E8h] [rbp-48h]
pthread_t newthread[2]; // [rsp+2F0h] [rbp-40h] BYREF
int v30; // [rsp+300h] [rbp-30h]
int v31; // [rsp+304h] [rbp-2Ch]

v31 = 0;
v30 = a1;
newthread[1] = (pthread_t)a2;
check_debugger();
memset(&s, 0, 0x30uLL);
s = (_BYTE *)("0. cat" + 3);
v24 = (_BYTE *)("1. dog" + 3);
v25 = (_BYTE *)("2. fox" + 3);
v26 = (_BYTE *)("3. panda" + 3);
v27 = (_BYTE *)("4. dragon" + 3);
v28 = (_BYTE *)("5. monkey" + 3);
memset(animals, 0, sizeof(animals));
for ( i = 0; i < 9; ++i )
{
input = 0;
puts("Welcome Animal shop");
sub_400900();
printf("Please input my favorite animal: ");
__isoc99_scanf("%d", &input);
switch ( input )
{
case 0:
src = s;
v3 = strlen(s);
strncat(animals, src, v3);
break;
case 1:
v15 = v24;
v4 = strlen(v24);
strncat(animals, v15, v4);
break;
case 2:
v14 = v25;
v5 = strlen(v25);
strncat(animals, v14, v5);
break;
case 3:
v13 = v26;
v6 = strlen(v26);
strncat(animals, v13, v6);
break;
case 4:
v12 = v27;
v7 = strlen(v27);
strncat(animals, v12, v7);
break;
case 5:
v11 = v28;
v8 = strlen(v28);
strncat(animals, v11, v8);
break;
default:
puts("Input Err.");
exit(0);
}
}
pthread_create(newthread, 0LL, start_routine, 0LL);
pthread_join(newthread[0], 0LL);
puts("done.");
init_data((__int64)data);
anms_len = strlen(animals);

sub_400B30(data, animals, anms_len);

sub_4059A0(data, (__int64)output);

for ( j = 0; j < 16; ++j )
{
if ( enc[j] != output[j] )
{
puts("Wrong.");
exit(0);
}
}
puts("Win! , flag is flag{md5(input)}");
return 0LL;
}

主要函数

1
2
3
4
5
6
7
8
9
pthread_create(newthread, 0LL, start_routine, 0LL);
pthread_join(newthread[0], 0LL);
puts("done.");
init_data((__int64)data);
anms_len = strlen(animals);

sub_400B30(data, animals, anms_len);

sub_4059A0(data, (__int64)output);

使用插件findCrypt发现是魔改md5,魔改了常量值

image-20230717101555609

密文 CBA47BE5F01CD1955C8546A2B24FBD18

image-20230717102751322

根据密文爆破即可

1
2
3
4
5
6
7
8
9
10
11
void __fastcall sub_406140()
{
int i; // [rsp+8h] [rbp-18h]
int v1; // [rsp+Ch] [rbp-14h]

v1 = strlen((const char *)(unsigned int)enc);
check_debugger();
for ( i = 0; i < v1; ++i )
enc[i] = enc[i] & 0xE9 | ~enc[i] & 0x16;
}

md5解密脚本如下

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
###头文件
#ifndef MD5_H
#define MD5_H
typedef struct
{
unsigned int count[2];
unsigned int state[4];
unsigned char buffer[64];
}MD5_CTX;
#define F(x,y,z) ((x & y) | (~x & z))
#define G(x,y,z) ((x & z) | (y & ~z))
#define H(x,y,z) (x^y^z)
#define I(x,y,z) (y ^ (x | ~z))
#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))
#define FF(a,b,c,d,x,s,ac) { \
a += F(b, c, d) + x + ac; \
a = ROTATE_LEFT(a, s); \
a += b; \
}
#define GG(a,b,c,d,x,s,ac) { \
a += G(b, c, d) + x + ac; \
a = ROTATE_LEFT(a, s); \
a += b; \
}
#define HH(a,b,c,d,x,s,ac) { \
a += H(b, c, d) + x + ac; \
a = ROTATE_LEFT(a, s); \
a += b; \
}
#define II(a,b,c,d,x,s,ac) { \
a += I(b, c, d) + x + ac; \
a = ROTATE_LEFT(a, s); \
a += b; \
}
void MD5Init(MD5_CTX* context);
void MD5Update(MD5_CTX* context, unsigned char* input, unsigned int inputlen);
void MD5Final(MD5_CTX* context, unsigned char digest[16]);
void MD5Transform(unsigned int state[4], unsigned char block[64]);
void MD5Encode(unsigned char* output, unsigned int* input, unsigned int len);
void MD5Decode(unsigned int* output, unsigned char* input, unsigned int len);
#endif

###

#define _CRT_SECURE_NO_WARNINGS
#include "MD5.h"
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
#define _TCHAR char
unsigned char PADDING[] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
//魔改了
void MD5Init(MD5_CTX* context)
{
context->count[0] = 0;
context->count[1] = 0;
context->state[0] = 0xEFCDAB89;
context->state[1] = 0x67452301;
context->state[2] = 0x10325476;
context->state[3] = 0x98BADCFE;
}
void MD5Update(MD5_CTX* context, unsigned char* input, unsigned int inputlen)
{
unsigned int i = 0, index = 0, partlen = 0;
index = (context->count[0] >> 3) & 0x3F;
partlen = 64 - index;
context->count[0] += inputlen << 3;
if (context->count[0] < (inputlen << 3))
context->count[1]++;
context->count[1] += inputlen >> 29;
if (inputlen >= partlen)
{
memcpy(&context->buffer[index], input, partlen);
MD5Transform(context->state, context->buffer);
for (i = partlen; i + 64 <= inputlen; i += 64)
MD5Transform(context->state, &input[i]);
index = 0;
}
else
{
i = 0;
}
memcpy(&context->buffer[index], &input[i], inputlen - i);
}
void MD5Final(MD5_CTX* context, unsigned char digest[16])
{
unsigned int index = 0, padlen = 0;
unsigned char bits[8];
index = (context->count[0] >> 3) & 0x3F;
padlen = (index < 56) ? (56 - index) : (120 - index);
MD5Encode(bits, context->count, 8);
MD5Update(context, PADDING, padlen);
MD5Update(context, bits, 8);
MD5Encode(digest, context->state, 16);
}
void MD5Encode(unsigned char* output, unsigned int* input, unsigned int len)
{
unsigned int i = 0, j = 0;
while (j < len)
{
output[j] = input[i] & 0xFF;
output[j + 1] = (input[i] >> 8) & 0xFF;
output[j + 2] = (input[i] >> 16) & 0xFF;
output[j + 3] = (input[i] >> 24) & 0xFF;
i++;
j += 4;
}
}
void MD5Decode(unsigned int* output, unsigned char* input, unsigned int len)
{
unsigned int i = 0, j = 0;
while (j < len)
{
output[i] = (input[j]) |
(input[j + 1] << 8) |
(input[j + 2] << 16) |
(input[j + 3] << 24);
i++;
j += 4;
}
}
void MD5Transform(unsigned int state[4], unsigned char block[64])
{
unsigned int a = state[0];
unsigned int b = state[1];
unsigned int c = state[2];
unsigned int d = state[3];
unsigned int x[64];
MD5Decode(x, block, 64);
FF(a, b, c, d, x[0], 7, 0xd76aa478);
FF(d, a, b, c, x[1], 12, 0xe8c7b756);
FF(c, d, a, b, x[2], 17, 0x242070db);
FF(b, c, d, a, x[3], 22, 0xc1bdceee);
FF(a, b, c, d, x[4], 7, 0xf57c0faf);
FF(d, a, b, c, x[5], 12, 0x4787c62a);
FF(c, d, a, b, x[6], 17, 0xa8304613);
FF(b, c, d, a, x[7], 22, 0xfd469501);
FF(a, b, c, d, x[8], 7, 0x698098d8);
FF(d, a, b, c, x[9], 12, 0x8b44f7af);
FF(c, d, a, b, x[10], 17, 0xffff5bb1);
FF(b, c, d, a, x[11], 22, 0x895cd7be);
FF(a, b, c, d, x[12], 7, 0x6b901122);
FF(d, a, b, c, x[13], 12, 0xfd987193);
FF(c, d, a, b, x[14], 17, 0xa679438e);
FF(b, c, d, a, x[15], 22, 0x49b40821);
GG(a, b, c, d, x[1], 5, 0xf61e2562);
GG(d, a, b, c, x[6], 9, 0xc040b340);
GG(c, d, a, b, x[11], 14, 0x265e5a51);
GG(b, c, d, a, x[0], 20, 0xe9b6c7aa);
GG(a, b, c, d, x[5], 5, 0xd62f105d);
GG(d, a, b, c, x[10], 9, 0x2441453);
GG(c, d, a, b, x[15], 14, 0xd8a1e681);
GG(b, c, d, a, x[4], 20, 0xe7d3fbc8);
GG(a, b, c, d, x[9], 5, 0x21e1cde6);
GG(d, a, b, c, x[14], 9, 0xc33707d6);
GG(c, d, a, b, x[3], 14, 0xf4d50d87);
GG(b, c, d, a, x[8], 20, 0x455a14ed);
GG(a, b, c, d, x[13], 5, 0xa9e3e905);
GG(d, a, b, c, x[2], 9, 0xfcefa3f8);
GG(c, d, a, b, x[7], 14, 0x676f02d9);
GG(b, c, d, a, x[12], 20, 0x8d2a4c8a);
HH(a, b, c, d, x[5], 4, 0xfffa3942);
HH(d, a, b, c, x[8], 11, 0x8771f681);
HH(c, d, a, b, x[11], 16, 0x6d9d6122);
HH(b, c, d, a, x[14], 23, 0xfde5380c);
HH(a, b, c, d, x[1], 4, 0xa4beea44);
HH(d, a, b, c, x[4], 11, 0x4bdecfa9);
HH(c, d, a, b, x[7], 16, 0xf6bb4b60);
HH(b, c, d, a, x[10], 23, 0xbebfbc70);
HH(a, b, c, d, x[13], 4, 0x289b7ec6);
HH(d, a, b, c, x[0], 11, 0xeaa127fa);
HH(c, d, a, b, x[3], 16, 0xd4ef3085);
HH(b, c, d, a, x[6], 23, 0x4881d05);
HH(a, b, c, d, x[9], 4, 0xd9d4d039);
HH(d, a, b, c, x[12], 11, 0xe6db99e5);
HH(c, d, a, b, x[15], 16, 0x1fa27cf8);
HH(b, c, d, a, x[2], 23, 0xc4ac5665);
II(a, b, c, d, x[0], 6, 0xf4292244);
II(d, a, b, c, x[7], 10, 0x432aff97);
II(c, d, a, b, x[14], 15, 0xab9423a7);
II(b, c, d, a, x[5], 21, 0xfc93a039);
II(a, b, c, d, x[12], 6, 0x655b59c3);
II(d, a, b, c, x[3], 10, 0x8f0ccc92);
II(c, d, a, b, x[10], 15, 0xffeff47d);
II(b, c, d, a, x[1], 21, 0x85845dd1);
II(a, b, c, d, x[8], 6, 0x6fa87e4f);
II(d, a, b, c, x[15], 10, 0xfe2ce6e0);
II(c, d, a, b, x[6], 15, 0xa3014314);
II(b, c, d, a, x[13], 21, 0x4e0811a1);
II(a, b, c, d, x[4], 6, 0xf7537e82);
II(d, a, b, c, x[11], 10, 0xbd3af235);
II(c, d, a, b, x[2], 15, 0x2ad7d2bb);
II(b, c, d, a, x[9], 21, 0xeb86d391);
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
}
int main(int argc, _TCHAR* argv[])
{
int i;
unsigned char encrypt[] =
"catmonkeydogdragondogcatfoxpandapanda";//21232f297a57a5a743894a0e4a801fc3
char my[][10] = { "cat","dog","fox","panda","dragon","monkey" };
char animals[256] = { 0 };
//memset(animals, 0, sizeof(animals));
//051410233
for (int i1 = 0; i1 < 6; i1++) {
for (int i2 = 0; i2 < 6; i2++) {
for (int i3 = 0; i3 < 6; i3++) {
for (int i4 = 0; i4 < 6; i4++) {
for (int i5 = 0; i5 < 6; i5++) {
for (int i6 = 0; i6 < 6; i6++) {
for (int i7 = 0; i7 < 6; i7++) {
for (int i8 = 0; i8 < 6; i8++) {
for (int i9 = 0; i9 < 6; i9++) {
char mycrpyo[255] = { 0 };
strcat(mycrpyo, my[i1]);
strcat(mycrpyo, my[i2]);
strcat(mycrpyo, my[i3]);
strcat(mycrpyo, my[i4]);
strcat(mycrpyo, my[i5]);
strcat(mycrpyo, my[i6]);
strcat(mycrpyo, my[i7]);
strcat(mycrpyo, my[i8]);
strcat(mycrpyo, my[i9]);
const char* my =
"catmonkeydogdragondogcatfoxpandapanda";
unsigned char decrypt[16] = { 0 };
MD5_CTX md5;
MD5Init(&md5);
MD5Update(&md5, (unsigned char*)mycrpyo,
strlen((char*)mycrpyo));
MD5Final(&md5, decrypt);
if (((decrypt[0] & 0xE9 | ~decrypt[0] &
0x16) == 0xcb) && ((decrypt[1] & 0xE9 | ~decrypt[1] & 0x16) == 0xa4) &&
((decrypt[2] & 0xE9 | ~decrypt[2] & 0x16) == 0x7B)) {
printf("%d%d%d%d%d%d%d%d%d\n", i1,
i2, i3, i4, i5, i6, i7, i8, i9);
}
}
}
}
}
}
}
}
}
}
return 0;
}

image-20230720104609934

misc - usb+base85

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import sys, argparse, os


class kbpaser:

def __init__(self):
# tshark 导出文件
self.datafile = "kbdatafile.txt"
self.presses = []

# Keyboard Traffic Dictionary
self.normalKeys = {"04": "a", "05": "b", "06": "c", "07": "d", "08": "e", "09": "f", "0a": "g", "0b": "h",
"0c": "i", "0d": "j", "0e": "k", "0f": "l", "10": "m", "11": "n", "12": "o", "13": "p",
"14": "q", "15": "r", "16": "s", "17": "t", "18": "u", "19": "v", "1a": "w", "1b": "x",
"1c": "y", "1d": "z", "1e": "1", "1f": "2", "20": "3", "21": "4", "22": "5", "23": "6",
"24": "7", "25": "8", "26": "9", "27": "0", "28": "<RET>", "29": "<ESC>", "2a": "<DEL>",
"2b": "\t", "2c": "<SPACE>", "2d": "-", "2e": "=", "2f": "[", "30": "]", "31": "\\",
"32": "<NON>", "33": ";", "34": "'", "35": "<GA>", "36": ",", "37": ".", "38": "/",
"39": "<CAP>", "3a": "<F1>", "3b": "<F2>", "3c": "<F3>", "3d": "<F4>", "3e": "<F5>",
"3f": "<F6>", "40": "<F7>", "41": "<F8>", "42": "<F9>", "43": "<F10>", "44": "<F11>",
"45": "<F12>"}

# Press shift
self.shiftKeys = {"04": "A", "05": "B", "06": "C", "07": "D", "08": "E", "09": "F", "0a": "G", "0b": "H",
"0c": "I", "0d": "J", "0e": "K", "0f": "L", "10": "M", "11": "N", "12": "O", "13": "P",
"14": "Q", "15": "R", "16": "S", "17": "T", "18": "U", "19": "V", "1a": "W", "1b": "X",
"1c": "Y", "1d": "Z", "1e": "!", "1f": "@", "20": "#", "21": "$", "22": "%", "23": "^",
"24": "&", "25": "*", "26": "(", "27": ")", "28": "<RET>", "29": "<ESC>", "2a": "<DEL>",
"2b": "\t", "2c": "<SPACE>", "2d": "_", "2e": "+", "2f": "{", "30": "}", "31": "|",
"32": "<NON>", "33": "\"", "34": ":", "35": "<GA>", "36": "<", "37": ">", "38": "?",
"39": "<CAP>", "3a": "<F1>", "3b": "<F2>", "3c": "<F3>", "3d": "<F4>", "3e": "<F5>",
"3f": "<F6>", "40": "<F7>", "41": "<F8>", "42": "<F9>", "43": "<F10>", "44": "<F11>",
"45": "<F12>"}

def tshark_do(self, pcapfile, filterfield, fieldvalue):
if os.name == "nt":
if filterfield is not None:
command = f"tshark -r {pcapfile} -Y {filterfield} -T fields -e {fieldvalue} > {self.datafile}"
else:
command = f"tshark -r {pcapfile} -T fields -e {fieldvalue} > {self.datafile}"
try:
os.system(command)
print("tshark执行语句:" + command)
print("[+] Found : tshark导出数据成功")
except:
print("tshark执行语句:" + command)
print("[+] Found : tshark导出数据失败")

elif os.name == "posix":
# sed '/^\s*$/d' 主要是去掉空行
if filterfield not in None:
command = f"tshark -r {pcapfile} -Y {filterfield} -T fields -e {fieldvalue} | sed '/^\s*$/d' > {self.datafile}"
else:
command = f"tshark -r {pcapfile} -T fields -e {fieldvalue} | sed '/^\s*$/d' > {self.datafile}"

try:
os.system(command)
print("tshark执行语句:" + command)
print("[+] Found : tshark导出数据成功")
except:
print("tshark执行语句:" + command)
print("[+] Found : tshark导出数据失败")

# 筛掉无用数据,改变数据格式
def formatkbdata(self):
formatfile = open("formatKbdatafile.txt", "w")

with open(self.datafile, "r") as f:
for i in f:
# if len(i.strip("\n")) == 8:
# Bytes = [i[j:j+2] for j in range(0, len(i.strip("\n")), 2)]
# data = ":".join(Bytes)
# formatfile.writelines(data+"\n")
if len(i.strip("\n")) == 16:
Bytes = [i[j:j + 2] for j in range(0, len(i.strip("\n")), 2)]
data = ":".join(Bytes)
formatfile.writelines(data + "\n")

formatfile.close()

def jiemi(self):
print("\n-----开始解密Tshark导出的键盘数据-----\n")
# 读取数据 z
with open("formatKbdatafile.txt", "r") as f:
for line in f:
self.presses.append(line[0:-1]) # 去掉末尾的 \n
# 开始处理
result = []
for press in self.presses:
if press == '':
continue
# thark 版本原因,导出数据格式不同
if ':' in press:
Bytes = press.split(":")
else:
# 两两分组
Bytes = [press[i:i + 2] for i in range(0, len(press), 2)]
print(Bytes)
if Bytes[0] == "00":
if Bytes[2] != "00" and self.normalKeys.get(Bytes[2]):
result.append(self.normalKeys[Bytes[2]])
# print(result)
elif int(Bytes[0], 16) & 0b10 or int(Bytes[0], 16) & 0b100000: # shift key is pressed.
if Bytes[2] != "00" and self.normalKeys.get(Bytes[2]):
# result.append(self.normalKeys[Bytes[2]])
result.append(self.shiftKeys[Bytes[2]])
else:
print("[-] Unknow Key : %s" % (Bytes[0]))
print("[+] USB_Found : %s" % (result))
# print(type(result))

flag = 0
for i in range(len(result)):
try:
a = result.index('<DEL>')
del result[a]
del result[a - 1]
except:
pass

for i in range(len(result)):
try:
if result[i] == "<CAP>":
flag += 1
result.pop(i)
if flag == 2:
flag = 0
if flag != 0:
result[i] = result[i].upper()
except:
pass

# print ('\n [+] 键盘数据 output :' + "".join (result))

# 删除提取数据文件
rm_stat = eval(input(f"-----是否删除tshark导出的文件 \"{self.datafile}\", 1 or 0-----\n"))
if rm_stat == 1:
os.remove(self.datafile)


if __name__ == "__main__":
# 我的 vscode 工作区的原因,需要切换到当前目录
pwd = os.path.dirname(__file__)
os.chdir(pwd)

BANNER = r"""
// / / // ) ) // ) )
// / / (( //___/ / ___ __ ___ ___ / ___
// / / \\ / __ ( // ) ) // ) ) // ) ) // ) ) //\ \
// / / ) ) // ) ) // // // / / // // \ \
((___/ / ((___ / / //____/ / ((____ // ((___( ( ((____ // \ \

@MAY1AS
"""
print(BANNER)

argobject = argparse.ArgumentParser(prog="UsbKbCracker", description="""This is a script for decrypt UsbKeyboardData
""")

argobject.add_argument('-f', "--pcapfile", required=True, help="here is your capturedata file")
argobject.add_argument('-e', "--fieldvalue", required=True, help="here is your output_format")
argobject.add_argument('-Y', "--filterfield", help="here is your filter")

arg = argobject.parse_args()

kbparser = kbpaser()

# tshark 导出数据,存储在 usbdatafile.txt 内
kbparser.tshark_do(pcapfile=arg.pcapfile, fieldvalue=arg.fieldvalue, filterfield=arg.filterfield)
kbparser.formatkbdata()
kbparser.jiemi()

使用脚本 - 进行解密,得出Ao(mgHY$\A@Q7gW2D$dE@6#oO0f<Gm1hAI'/N#4<AN;MS@PfrQ149K

image-20230720104155672

使用随波逐流,base85解密得解

image-20230717184002034

flag{ec1b8b96-56a9-f15c-4e39-503e92ab45d2}

crypto - rsa

这题和 AntCTF x D^3CTF 2022 的 d3factor 长的很像

使用脚本解密

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
# sagemath
from Crypto.Util.number import *
import gmpy2,hashlib

N=26989781630503676259502221325791347584607522857769579575297691973258919576768826427059198152035415835627885162613470528107575781277590981314410130242259476764500731263549070841939946410404214950861916808234008589966849302830389937977667872854316531408288338541977868568209278283760692866116947597445559763998608870359453835826711179703215320653445704522573070650642347871171425399227090705774976383452533375854187754721093890020986550939103071021619840797519979671188117673303672023522910200606134989916541289908538417562640981839074992935652363458747488201289997240226553340491203815779083605965873519144351105635977
c=15608493359172313429111250362547316415137342033261379619116685637094829328864086722267534755459655689598026363165606700718051739433022581810982230521098576597484850535770518552787220173105513426779515790426303985414120033452747683669501078476628404455341179818932159581239994489678323564587149645006231756392148052557984581049067156468083162932334692086321511063682574943502393749684556026493316348892705114791740287823927634401828970155725090197482067045119003108806888768161101755244340832271562849138340706213702438667804460812804485276133545408754720942940596865774516864097546006862891145251661268265204662316437
e=65537
e1=8334176273377687778925968652923982846998724107624538105654894737480608040787164942908664678429487595866375466955578536932646638608374859799560790357357355475153852315429988251406716837806949387421402107779526648346112857245251481791000156326311794515247012084479404963628187413781724893173183595037984078029706687141452980915897613598715166764006079337996939237831127877822777298891345240992224457502307777453813403723860370336259768714433691700008761598135158249554720239480856332237245140606893060889458298812027643186014638882487288529484407249417947342798261233371859439003556025622531286607093086262182961900221
e2=22291783101991466901669802811072286361463259096412523019927956845014956726984633944311563809077545336731345629003968417408385538540199052480763352937138063001691494078141034164060073208592072783644252721127901996835233091410441838546235477819239598146496144359952946239328842198897348830164467799618269341456666825968971193729838026760012332020223490546511437879465268118749332615890600046622926159177680882780495663448654527562370133394251859961739946007037825763819500955365636946510343942994301809125029616066868596044885547005547390446468651797783520279531291808102209463733268922901056842903640261702268483580079


r = 7
a = (e2 - e1) * gmpy2.invert(e1*e2,N) % N
# assert a < N
P.<x> = PolynomialRing(Zmod(N))
f = x - a
x = f.small_roots(X = 2^1000,beta = 0.4)
x = x[0]
k_phi = e1*e2*x - (e2 - e1)
p_ = gcd(k_phi,N)

p = gmpy2.iroot(int(p_),r - 1)[0]
# print(p)
q = N // (p**r)
# print(q)
n = p * q
phi_n = (p - 1) * (q - 1)
d = gmpy2.invert(e,phi_n)
# print(n)
m = pow(c,d,n)

print(bytes.decode(long_to_bytes(int(m))))
# flag{RSA_1s_s0_ez_4nd_hwser_c4n_bre4k_1t!}