目录

NepCTF 2021

开始时间:2021-03-20 10:00:00
结束时间:2021-03-22 00:00:00

misc

签到

sharun:这题有很多解啊

附件是一个txt,里面看起来是python,给flag变量赋了一个装满16进制数的list misc-sign-flag-txt 写脚本转换成二进制字符串并输出(为了更清晰把1替换成了空格并使用Consolas等宽字体查看记事本)

1
2
3
4
5
6
flag = [...]
flag = [bin(x).replace("0b", "").replace("1", " ") for x in flag]
f = open("out.txt", "w")
for line in flag:
    f.write(line + "\n")
f.close()

打开out.txt即可看到flag
sign-flag-ver
Nep{Y0u_ar3_50_cl3ver!}

冰峰历险记

冒险者小张在迷宫里意外发现了坏女人留下的宝箱,你能帮他解开秘密么?

附件是一个exe文件,打开发现是一个electron做的游戏
icepeak-surface
尝试操作了一下,拿到宝箱后怪物移动速度极快,手残秒死:(
放弃正常游戏通关的思路,开始解包。
exe后缀改为zip,打开解压出Adventure-1.0.0-full.nukpg
icepeak-zip1
nupkg后缀同样改为zip,继续解压出Adventure-1.0.0-full.zip\lib\net45\resources\app
icepeak-zip2
app/index.html中找到这么一段js

1
2
3
4
5
6
7
//go ahead and reverse it!
function onButtonClick () {

var _0x3771=['\x62\x6c\x65','\x72\x61\x74\x75','\x33\x39\x46\x32','\x31\x4c\x49\x4a\x76\x65\x68','\x32\x33\x6e\x79\x4f\x53\x75\x6d','\x31\x36\x4d\x42\x73\x69\x7a\x6d','\x34\x64\x4d\x50\x73\x48\x53','\x2d\x31\x44\x45','\x37\x33\x32\x39\x34\x56\x55\x4d\x52\x78\x52','\x34\x41\x45\x31','\x31\x31\x36\x31\x38\x38\x37\x55\x50\x47\x44\x6c\x68','\x33\x36\x30\x39','\x66\x6f\x6e\x74','\x38\x44\x43\x33','\x53\x69\x7a\x65','\x36\x44\x36\x2d','\x43\x6f\x6e\x67','\x32\x33\x6b\x63\x4d\x7a\x4b\x65','\x45\x35\x35\x38','\x31\x35\x36\x35\x32\x35\x64\x50\x66\x52\x45\x49','\x73\x74\x79\x6c','\x6c\x61\x74\x69','\x35\x63\x42\x4c\x49\x4e\x5a','\x35\x35\x37\x33\x39\x68\x72\x6d\x41\x73\x6c','\x4e\x65\x70\x7b','\x36\x38\x38\x35\x38\x68\x6e\x55\x50\x43\x74','\x31\x30\x39\x39\x36\x31\x68\x43\x6f\x45\x6e\x79','\x76\x69\x73\x69','\x6f\x6e\x73\x21','\x34\x36\x30\x35\x31\x46\x66\x61\x70\x4f\x49','\x74\x65\x78\x74'];var _0x336e=function(_0x8710fc,_0xbfc9ff){_0x8710fc=_0x8710fc-0xa9;var _0x377162=_0x3771[_0x8710fc];return _0x377162;};var _0x422051=_0x336e;(function(_0x5ea0a5,_0x23a2f6){var _0x4b1718=_0x336e;while(!![]){try{var _0x13718d=parseInt(_0x4b1718(0xb3))*-parseInt(_0x4b1718(0xbb))+-parseInt(_0x4b1718(0xb9))*parseInt(_0x4b1718(0xc4))+-parseInt(_0x4b1718(0xac))+-parseInt(_0x4b1718(0xc7))*-parseInt(_0x4b1718(0xbc))+parseInt(_0x4b1718(0xaa))*parseInt(_0x4b1718(0xc5))+parseInt(_0x4b1718(0xbf))*parseInt(_0x4b1718(0xc6))+parseInt(_0x4b1718(0xb5))*parseInt(_0x4b1718(0xb8));if(_0x13718d===_0x23a2f6)break;else _0x5ea0a5['push'](_0x5ea0a5['shift']());}catch(_0x2f82a9){_0x5ea0a5['push'](_0x5ea0a5['shift']());}}}(_0x3771,0xcdfa7));if(input[_0x422051(0xc0)]==_0x422051(0xba)+_0x422051(0xc3)+_0x422051(0xab)+_0x422051(0xa9)+'\x42\x2d\x34\x39'+'\x33\x31\x2d\x41'+_0x422051(0xb1)+_0x422051(0xad)+_0x422051(0xaf)+_0x422051(0xb4)+'\x7d'){chest_lock[_0x422051(0xbd)+'\x62\x6c\x65']=!![],chest_unlock[_0x422051(0xbd)+'\x62\x6c\x65']=![],input[_0x422051(0xbd)+'\x62\x6c\x65']=![],balloon['\x76\x69\x73\x69'+'\x62\x6c\x65']=![],dialog[_0x422051(0xc0)]=_0x422051(0xb2)+_0x422051(0xc2)+_0x422051(0xb7)+_0x422051(0xbe),dialog[_0x422051(0xb6)+'\x65'][_0x422051(0xae)+_0x422051(0xb0)]=0x40,dialog['\x78']=0xa,dialog['\x79']=0x32,this[_0x422051(0xbd)+_0x422051(0xc1)]=![];return;}timeoutid!=null&&clearTimeout(timeoutid);prompts[_0x422051(0xbd)+_0x422051(0xc1)]=!![],balloon[_0x422051(0xbd)+_0x422051(0xc1)]=!![],timeoutid=setTimeout(disappear,0x1388);


}

格式化并替换难看的变量名

 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
var first_str = [
    '\x62\x6c\x65', 
    '\x72\x61\x74\x75', 
    '\x33\x39\x46\x32', 
    '\x31\x4c\x49\x4a\x76\x65\x68', 
    '\x32\x33\x6e\x79\x4f\x53\x75\x6d', 
    '\x31\x36\x4d\x42\x73\x69\x7a\x6d', 
    '\x34\x64\x4d\x50\x73\x48\x53', 
    '\x2d\x31\x44\x45', 
    '\x37\x33\x32\x39\x34\x56\x55\x4d\x52\x78\x52', 
    '\x34\x41\x45\x31', 
    '\x31\x31\x36\x31\x38\x38\x37\x55\x50\x47\x44\x6c\x68', 
    '\x33\x36\x30\x39', 
    '\x66\x6f\x6e\x74', 
    '\x38\x44\x43\x33', 
    '\x53\x69\x7a\x65', 
    '\x36\x44\x36\x2d', 
    '\x43\x6f\x6e\x67', 
    '\x32\x33\x6b\x63\x4d\x7a\x4b\x65', 
    '\x45\x35\x35\x38', 
    '\x31\x35\x36\x35\x32\x35\x64\x50\x66\x52\x45\x49', 
    '\x73\x74\x79\x6c', 
    '\x6c\x61\x74\x69', 
    '\x35\x63\x42\x4c\x49\x4e\x5a', 
    '\x35\x35\x37\x33\x39\x68\x72\x6d\x41\x73\x6c', 
    '\x4e\x65\x70\x7b', 
    '\x36\x38\x38\x35\x38\x68\x6e\x55\x50\x43\x74', 
    '\x31\x30\x39\x39\x36\x31\x68\x43\x6f\x45\x6e\x79', 
    '\x76\x69\x73\x69', 
    '\x6f\x6e\x73\x21', 
    '\x34\x36\x30\x35\x31\x46\x66\x61\x70\x4f\x49', 
    '\x74\x65\x78\x74']; 
var util_func = function (arg1, _0xbfc9ff) { 
    arg1 = arg1 - 0xa9;
    var output = first_str[arg1]; 
    return output; 
}; 
var func1 = util_func; 
(function (arg1, arg2) { 
    var func2 = util_func; 
    while (true) { 
        try { 
            var num1 = parseInt(func2(0xb3)) * 
            -parseInt(func2(0xbb)) + 
            -parseInt(func2(0xb9)) * 
            parseInt(func2(0xc4)) + 
            -parseInt(func2(0xac)) + 
            -parseInt(func2(0xc7)) * 
            -parseInt(func2(0xbc)) + 
            parseInt(func2(0xaa)) * 
            parseInt(func2(0xc5)) + 
            parseInt(func2(0xbf)) * 
            parseInt(func2(0xc6)) + 
            parseInt(func2(0xb5)) * 
            parseInt(func2(0xb8)); 
            if (num1 === arg2) break; 
            else arg1['push'](arg1['shift']()); 
        } catch (e) { 
            arg1['push'](arg1['shift']()); 
        } 
    } 
    console.log(arg1);
}(first_str, 0xcdfa7)); 
if (input[func1(0xc0)] == func1(0xba) + func1(0xc3) + func1(0xab) + func1(0xa9) + '\x42\x2d\x34\x39' + '\x33\x31\x2d\x41' + func1(0xb1) + func1(0xad) + func1(0xaf) + func1(0xb4) + '\x7d') 
{ 
    chest_lock[func1(0xbd) + '\x62\x6c\x65'] = true, 
    chest_unlock[func1(0xbd) + '\x62\x6c\x65'] = ![], 
    input[func1(0xbd) + '\x62\x6c\x65'] = ![], 
    balloon['\x76\x69\x73\x69' + '\x62\x6c\x65'] = ![], 
    dialog[func1(0xc0)] = func1(0xb2) + func1(0xc2) + func1(0xb7) + func1(0xbe), 
    dialog[func1(0xb6) + '\x65'][func1(0xae) + func1(0xb0)] = 0x40, 
    dialog['\x78'] = 0xa, 
    dialog['\x79'] = 0x32, this[func1(0xbd) + func1(0xc1)] = ![]; 
    return; 
} 
timeoutid != null && clearTimeout(timeoutid); 
prompts[func1(0xbd) + func1(0xc1)] = true, 
balloon[func1(0xbd) + func1(0xc1)] = true, 
timeoutid = setTimeout(disappear, 0x1388);

可看出在64行前都是在对first_str做操作,64行对输入数据进行了比较,猜测是输入了flag,等号后表达式eval得到flag。
icepeak-flag
Nep{39F24AE1-1DEB-4931-A6D6-36098DC3E558}

re

hardcsharp

我觉得很hard,你觉得呢(doge

附件是一个压缩包,内有一个exe,直接运行。
hardsharp-run
那没事了,用dnSpy打开
hardsharp-dnSpy

 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
// hardcsharp.Program
// Token: 0x06000001 RID: 1 RVA: 0x00002050 File Offset: 0x00000250
private static void Main(string[] args)
{
	AesClass aesClass = new AesClass();
	string text = "";
	string strB = "1Umgm5LG6lNPyRCd0LktJhJtyBN7ivpq+EKGmTAcXUM+0ikYZL4h4QTHGqH/3Wh0";
	byte[] array = new byte[]
	{
		81,
		82,
		87,
		81,
		82,
		87,
		68,
		92,
		94,
		86,
		93,
		18,
		18,
		18,
		18,
		18,
		18,
		18,
		18,
		18,
		18,
		18,
		18,
		18,
		18,
		18,
		18,
		18,
		18,
		18,
		18,
		18
	};
	Console.WriteLine("Welcome to nepnep csharp test! plz input the magical code:");
	string text2 = Console.ReadLine();
	if (text2.Length != 37)
	{
		Console.WriteLine("Nope!");
		Console.ReadKey();
		return;
	}
	if (text2.Substring(0, 4) != "Nep{" || text2[36] != '}')
	{
		Console.WriteLine("Nope!");
		Console.ReadKey();
		return;
	}
	for (int i = 0; i < 32; i++)
	{
		text += Convert.ToChar((int)(array[i] ^ 51)).ToString();
	}
	if (string.Compare(aesClass.AesEncrypt(text2, text), strB) == 0)
	{
		Console.WriteLine("wow, you pass it!");
		Console.ReadKey();
		return;
	}
	Console.WriteLine("Nope!");
	Console.ReadKey();
}

array已知,异或51求得text

1
2
3
4
array = [81,82,87,81,82,87,68,92,94,86,93,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18]
text = "".join(chr(x ^ 51) for x in array)
print(text) 
# "badbadwomen!!!!!!!!!!!!!!!!!!!!!"

使用badbadwomen!!!!!!!!!!!!!!!!!!!!!作为密码AES解密strB得到flag。
hardsharp-aes
Nep{up_up_down_down_B_a_b_A_Nep_nep~}

crypto

Real_Base

base64?林北不太确定

附件是一个python文件

 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
#py2
import string
import random
from secret import flag,b_char

def encode(s):
    res=''
    binstr=[ bin(ord(s[i])).replace('0b','').zfill(8) for i in range(len(s))]
    p1=len(binstr) // 3
    p2=len(binstr) % 3
    part1 = binstr[0:3*p1]
    
    for i in range(p1):
        str_p1=binstr[i*3]+binstr[i*3+1]+binstr[i*3+2]
        tmp_str = [str_p1[x: x + 6] for x in [0, 6, 12, 18]]
        tmp_res = [b_char[int(x,2)]for x in tmp_str]
        res+=''.join(tmp_res)

    if p2:
        part2 = binstr[3*p1:]
        str_p2 = ''.join(part2)+(3-p2)*'0'*8
        tmp_str = [str_p2[x: x + 6] for x in [0, 6, 12, 18]][:p2+1]
        tmp_res = [b_char[int(x,2)]for x in tmp_str]
        res+=''.join(tmp_res)
        res +='='*(3-p2)
    return res
 
m1=random.sample(list(b_char),50)
print ''.join(m1)
print encode(m1)
print encode(flag)
# rTcb1BR8YVW2EOUjweXpIiLt5QCNg7ZAsD9muq3ylMhvofnx/P
# 2Br9y9fcu97zvB2OruZv0D3Bwhbj0uNQnvfdtC2TwAfPrdBJ3xeP4wNn0hzLzCVUlRa=
# tCvM4R3TzvZ7nhjBxSiNyxmP28e7qCjVxQn91SRM3gBKzxQ=

给出了m1的原文和密文,以及flag的密文。
要求出flag原文,需要求得b_char
修改encode函数用m1的密文和原文对照得出部分b_char

 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
import string
import random
# from secret import flag,b_char

b_char = {}
encoded = "2Br9y9fcu97zvB2OruZv0D3Bwhbj0uNQnvfdtC2TwAfPrdBJ3xeP4wNn0hzLzCVUlRa="

def encode(s):
    res=''
    binstr=[ bin(ord(s[i])).replace('0b','').zfill(8) for i in range(len(s))]
    p1=len(binstr) // 3
    p2=len(binstr) % 3
    part1 = binstr[0:3*p1]
    index = 0
    
    for i in range(p1):
        str_p1=binstr[i*3]+binstr[i*3+1]+binstr[i*3+2]
        tmp_str = [str_p1[x: x + 6] for x in [0, 6, 12, 18]]
        for x in tmp_str:
            b_char[int(x, 2)] = encoded[index]
            index += 1
        # tmp_res = [b_char[int(x,2)]for x in tmp_str]
        # res+=''.join(tmp_res)

    if p2:
        part2 = binstr[3*p1:]
        str_p2 = ''.join(part2)+(3-p2)*'0'*8
        tmp_str = [str_p2[x: x + 6] for x in [0, 6, 12, 18]][:p2+1]
        for x in tmp_str:
            b_char[int(x, 2)] = encoded[index]
            index += 1
        # tmp_res = [b_char[int(x,2)]for x in tmp_str]
        # res+=''.join(tmp_res)
        # res +='='*(3-p2)
    return res


encode("rTcb1BR8YVW2EOUjweXpIiLt5QCNg7ZAsD9muq3ylMhvofnx/P")
print(b_char)
# b_char = {28: '2', 37: 'B', 17: 'r', 35: '9', 24: 'y', 5: 'f', 2: 'c', 20: 'u', 33: '7', 25: 'z', 21: 'v', 50: 'O', 61: 'Z', 26: '0', 39: 'D', 29: '3', 22: 'w', 7: 'h', 1: 'b', 9: 'j', 49: 'N', 52: 'Q', 13: 'n', 3: 'd', 19: 't', 38: 'C', 55: 'T', 36: 'A', 51: 'P', 45: 'J', 23: 'x', 4: 'e', 30: '4', 47: 'L', 57: 'V', 56: 'U', 11: 'l', 53: 'R', 0: 'a'}

flag密文遍历得到的b_char检测是否所有字符都有对应值来验证b_char的完整性。

1
2
3
4
5
6
7
c_char = {}
for k, v in b_char.items():
    c_char[v] = k
flag = "tCvM4R3TzvZ7nhjBxSiNyxmP28e7qCjVxQn91SRM3gBKzxQ"
for c in flag:
    if c not in c_char:
        print("oh f**k")

realbase-oh
可知b_char不完整。
寻找规律补全b_char,可发现0-25是字母a-z26-35是数字0-936-61是大写字母A-Z
得到完整的b_char,编写decode函数解密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
import string

b_char = {}
for x in range(0, 26):
    b_char[x] = string.ascii_lowercase[x]
index = 0
for x in range(26, 36):
    b_char[x] = str(index)
    index += 1
index = 0
for x in range(36, 62):
    b_char[x] = string.ascii_uppercase[index]
    index += 1

c_char = {}
for k, v in b_char.items():
    c_char[v] = k

def decode(s):
    res = ''
    s = s.replace("=", "")
    binstr = []
    for x in s:
        binstr.append(c_char[x])
    binstr = [bin(num).replace("0b", "").zfill(6) for num in binstr]
    p1 = len(binstr) // 4
    p2 = len(binstr) % 4
    part1 = binstr[0:4*p1]

    for i in range(p1):
        str_p1=binstr[i*4]+binstr[i*4+1]+binstr[i*4+2]+binstr[i*4+3]
        tmp_str = [str_p1[x: x + 8] for x in [0, 8, 16]]
        tmp_res = [chr(int(x, 2)) for x in tmp_str]
        res+=''.join(tmp_res)

    if p2:
        part2 = binstr[4*p1:]
        str_p2 = ''.join(part2)+(4-p2)*'0'*6
        tmp_str = [str_p2[x: x + 8] for x in [0, 8, 16]]
        tmp_res = [chr(int(x, 2)) for x in tmp_str]
        res+=''.join(tmp_res)

    return res


flag = "tCvM4R3TzvZ7nhjBxSiNyxmP28e7qCjVxQn91SRM3gBKzxQ="
print(decode(flag))

得到flag
realbase-result
Nep{Wwe_a4re_b1as3r!!Bby_Ccomptine}