NSSCTF-reverse-wp

几道reverse基础题目wp

很简单,写的c语言脚本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <string.h>
int main() {
	char Str1[1000];
	strcpy_s(Str1, sizeof(Str1), "{34sy_r3v3rs3}");
	int i;
	for (i = 0; i <= 665; ++i)
	{
		if (Str1[i] == '3')
			Str1[i] = 'e';
	}
	for (i = 0; i <= 665; ++i)
	{
		if (Str1[i] == '4')
			Str1[i] = 'a';
	}
	printf("%s", Str1);
}

Tips:

​ 1.使用strcpy函数要添加#include <string.h>函数头 ​ 2.在比较新的编译器里面,会对strcpy的安全问题报错,需对strcpy进行改进:

strcpy_s(str1,中间参数,str2);

中间参数的意义可以理解为:str2预计需要向str1占用多少空间

所以很显然中间参数的值的大小,必须大于等于str2的空间,但是小于等于str1空间(前提:str1>=str2)

通常情况下可以写为:

strcpy_s(str1,sizeof(str2),str2);

或者strcpy_s(str1,strlen(str2)+1,str2);

image-20230314163509730

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main() {
	char a[] = "d`vxbQd";
	for (int i = 0; i < 7; i++) {
		a[i] = a[i] ^ 2;
		a[i]--;
	}
	printf("%s",a);
}

把原本的python的脚本稍作修改,再跑一遍(xor加密)得到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
import base64,urllib.parse
key = "HereIsFlagggg"
flag = "xxxxxxxxxxxxxxxxxxx"

s_box = list(range(256))
j = 0
for i in range(256):
    j = (j + s_box[i] + ord(key[i % len(key)])) % 256
    s_box[i], s_box[j] = s_box[j], s_box[i]
res = []
i = j = 0
for s in flag:
    i = (i + 1) % 256
    j = (j + s_box[i]) % 256
    s_box[i], s_box[j] = s_box[j], s_box[i]
    t = (s_box[i] + s_box[j]) % 256
    k = s_box[t]
    res.append(chr(ord(s) ^ k))
cipher = "".join(res)
crypt = (str(base64.b64encode(cipher.encode('utf-8')), 'utf-8'))
enc = str(base64.b64decode(crypt),'utf-8')
enc = urllib.parse.quote(enc)
print(enc)
# enc = %C2%A6n%C2%87Y%1Ag%3F%C2%A01.%C2%9C%C3%B7%C3%8A%02%C3%80%C2%92W%C3%8C%C3%BA

下面是修改之后的脚本:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import urllib.parse
key = "HereIsFlagggg"
flag = "%C2%A6n%C2%87Y%1Ag%3F%C2%A01.%C2%9C%C3%B7%C3%8A%02%C3%80%C2%92W%C3%8C%C3%BA"
flag =urllib.parse.unquote(flag)
s_box = list(range(256))
j = 0
for i in range(256):
    j = (j + s_box[i] + ord(key[i % len(key)])) % 256
    s_box[i], s_box[j] = s_box[j], s_box[i]
res = []
i = j = 0
for s in flag:
    i = (i + 1) % 256
    j = (j + s_box[i]) % 256
    s_box[i], s_box[j] = s_box[j], s_box[i]
    t = (s_box[i] + s_box[j]) % 256
    k = s_box[t]
    res.append(chr(ord(s) ^ k))
cipher = "".join(res)

print(cipher)
//NSSCTF{REAL_EZ_RC4}

Tips:python脚本中最下边注释掉的enc就是正确的flag之后加密的,千万不要覆盖掉

反编译,很简单的代码审计,复制改程序的代码进行修改,逆向运算进行解密

image-20230314214225357

下面是C语言写的脚本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <stdio.h>
int main() {
    char Str[] = "ylqq]aycqyp{";
    int v7 = strlen(Str);
    for (int i = 0; i < v7; ++i)
    {
        if ((Str[i] <= 96 || Str[i] > 98) && (Str[i] <= 64 || Str[i] > 66))
            Str[i] += 2;
        else
            Str[i] -= 24;
    }
    printf("%s", Str);
}

但输出的flag好像有点问题,确实怪

1
//{nss_c{es{r},{用a替换,得到{nss_caesar}为正确答案

非预期解:在十六进制数据对应的ASCII中发现了flag

image-20230314221252472

image-20230315093709559

append()函数 ⽤于在列表末尾添加新的对象

random.getrandbits(k) 返回一个不大于K位的Python整数(十进制),比如k=10,则结果是0~2^10之间的整数。

以下是算法逆向脚本:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import random
result = [201, 8, 198, 68, 131, 152, 186, 136, 13, 130, 190, 112, 251, 93, 212, 1, 31, 214, 116, 244]
random.seed(1)
l = []
for i in range(4):
    l.append(random.getrandbits(8))
flag=[]
for i in range(len(l)):
    random.seed(l[i])
    for n in range(5):
        flag.append(chr(result[i*5+n]^random.getrandbits(8)))
print(''.join(flag))
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include <stdio.h>
int main()
{
    srand(0x2766);
    printf("NSSCTF{");
    for (int m = 0; m < 13; ++m )
    {
        printf("%d", rand() % 8 + 1);
    }
    putchar('}');
}

Tips:必须在Linux下运行才正确

非预期解:

image-20230315223812826

预期解: IDA32位,定位到main函数,发现花指令

image-20230315225138572

快捷键D转换成数据

image-20230315225209261

然后nop(90)

image-20230315225300974

随后一路快捷键C将黄色代码转换成数据

image-20230315225406355

整理完成之后,创建函数,之后就可以进行F5反编译,得到flag

image-20230315225544634

根据题目标签可知,UPX脱壳,可以用upx直接进行脱壳

1
upx.exe -d xxxxx.exe

https://github.com/upx/upx/releases

image-20230316161652078

题目代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
flag = 'xxxxxxxxxxxxxxxxxxx'

s_box = 'qwertyuiopasdfghjkzxcvb123456#$'
tmp = ''
for i in flag:
    tmp += str(bin(ord(i)))[2:].zfill(8)
b1 = int(tmp,2)
s = ''
while b1//31 != 0:
    s += s_box[b1%31]
    b1 = b1//31

print(s)

# s = u#k4ggia61egegzjuqz12jhfspfkay

审计注释:

1
2
3
4
5
6
7
ord(i):返回字符 `i`  ASCII 码值。
bin(ord(i))  ASCII 码值转换为二进制数。
str(bin(ord(i))) 将二进制数转换为字符串。
[2:] 从第二个字符开始取,去除字符串开头的 '0b'
  0 补齐字符串的左侧,使其总长度为 8
 tmp += str(bin(ord(i)))[2:].zfill(8) 将处理结果拼接到 tmp 中。
 int(tmp,2)  tmp 解释为二进制数,并转换为整数类型。

本题考察取模逆运算

image-20230316203309224

memcmp函数的原型为 int memcmp(const void *str1, const void *str2, size_t n);其功能是把存储区 str1 和存储区 str2 的前 n 个字节进行比较。该函数是按字节比较的,位于string.h。

  • 如果返回值 < 0,则表示 str1 小于 str2。
  • 如果返回值 > 0,则表示 str1 大于 str2。
  • 如果返回值 = 0,则表示 str1 等于 str2。

通过Shift+F12查看字符串,发现两段类似base64编码的字符串,猜测base64换表,脚本如下:

1
2
3
4
5
import base64
str1 = "5Mc58bPHLiAx7J8ocJIlaVUxaJvMcoYMaoPMaOfg15c475tscHfM/8=="                        #str1是要解密的代码
string1 = "qvEJAfHmUYjBac+u8Ph5n9Od17FrICL/X0gVtM4Qk6T2z3wNSsyoebilxWKGZpRD"             #string1是改过之后的base64表
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
print (base64.b64decode(str1.translate(str.maketrans(string1,string2))))

image-20230319150422156

image-20230319152007526

image-20230319152316646

python脚本:

1
2
3
4
5
6
from base64 import *
enc = "TlJRQFBBdTs4alsrKFI6MjgwNi5p"
str = b64decode(enc).decode()
for i in range(len(str)):
    print(chr(i + ord(str[i])),end='')
NSSCTF{B@se64_HAHAHA}

一个xor加密 使用 npm 包 escodegen 解密

  1. 安装 escodegen
1
npm i escodegen -g

​ 2.将json 文件转换成 js语句

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ esgenerate 附件.json
(function () {
    function bE(str, key) {
        var arr = str.split('');
        return arr.map(i => {
            return String.fromCharCode(i.charCodeAt() ^ key);
        }).join('');
    }
    console.log(bE('EXXH_Mpjx\x7FBxYnjggrM~eerv', 11));
}());

​ 3.执行语句即可获得 flag

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$ node
Welcome to Node.js v14.13.1.
Type ".help" for more information.
> (function () {
...     function bE(str, key) {
.....         var arr = str.split('');
.....         return arr.map(i => {
.......             return String.fromCharCode(i.charCodeAt() ^ key);
.......         }).join('');
.....     }
...     console.log(bE('EXXH_Mpjx\x7FBxYnjggrM~eerv', 11));
... }());

NSSCTF{astIsReallyFunny}