2023 The 7th Henan Higher Education Information Security Competition-Yuwang Cup-ISCC2023 Offline Competition-(misc+cryoto) (detailed-ideas-script)

Wuhu~

Is it really tiring? I spent a day and a half in the original day, and I still don’t comment on that sentence. All fellow Taoists have their own opinions.

My misc found another small unexpected thing. I didn’t expect this to happen offline too.

The following are some of my own ideas and analysis. If you have any questions or suggestions, you can contact me at any time.

2023 The 7th Henan Higher Education Information Security Competition-Yuwang Cup-ISCC2023 Offline Competition

Below I am the insights and ideas of misc and cryoto

download attachment

Link: https://pan.baidu.com/s/1qaIl_ZJVaBY4Kpnkl3NFMw?pwd=lulu 
Extraction code: lulu 
--share from Baidu Netdisk super member V3

Table of contents

Misc

Color

code explanation

Each other

What is the first step to see the audio

Replenish

Badimages

Cryoto

choir4

script analysis

upper script

insecure public key

one character only

code explanation

Come on everyone ( •̀ ω •́ )y look forward to seeing you again


Misc

Color

 only one txt file

 Wow when the file opens and the files inside are exposed before our eyes

I believe that many veterans will understand how to do it immediately

This is a very simple RGB to picture problem, not to mention the file name is still a hint

(Of course novices must accumulate more)

Here we go to the script (with parsing)

We need to write a script to create a blank RGB image, then read the color information from the specified file "color.txt", and apply the color information to each pixel of the image one by one. Finally, the image is displayed by the im.show() method.

from PIL import Image

# 定义图像的宽度和高度

x = 500

y = 500

# 创建一个新的RGB图像

im = Image.new("RGB", (x, y))

# 打开并读取颜色文件

file = open("./color.txt", "r")

# 遍历图像的每个像素for i in range(x):

    for j in range(y):

        # 从文件中读取一行颜色信息,并去除换行符

        line = file.readline().strip("\n")

        

        # 去除括号并分割RGB值

        line = line.replace("(", "").replace(")", "")

        rgb = list(line.split(","))

        

        # 将颜色值转换为整数,并将RGB值应用到当前像素

        im.putpixel((i, j), (int(rgb[0]), int(rgb[1].strip(" ")), int(rgb[2].strip(" "))))

        # 显示图像

im.show()

code explanation

In the above code, we use the PIL (Python Imaging Library) library for image processing. Specific steps are as follows:

  • Importing the Image class: We import the Image module from the PIL library so we can use its functions and methods.
  • Define the image size: We use the variables x and y to specify the width and height of the image respectively, which is set to 500 here.
  • Create a blank image: Create a new RGB image object through the Image.new() function, use the parameter "RGB" to specify the color mode of the image as red, green and blue (RGB), and pass in the width and height as parameters.
  • Open the color file: Open the file named "color.txt" through the open() function, and specify it as read-only mode. The file should contain a series of RGB color values, one color value per line.
  • Traversing image pixels: Use nested for loops to traverse each pixel of the image, the outer loop controls the number of rows, and the inner loop controls the number of columns.
  • Read color information: Use the file.readline() function to read the color information in the file line by line, and use the .strip("\n") method to remove the newline character at the end of each line.
  • Parse the color information: remove the parentheses through string operations, and use the .split(",") method to split the RGB value into a list of strings.
  • Convert the color value: Use the int() function to convert the RGB string to an integer and assign it to the red, green and blue variables respectively.
  • Apply color information: apply the RGB value to the currently traversed pixel through the im.putpixel() method, and pass the parameters as the coordinates (i, j) and color value (red, green, blue) of the current pixel.
  • Display image: Display the generated image by im.show() method.
  • Please make sure that you have prepared a file named "color.txt" before running the code, and store it in the format of one color value per line, for example: (255, 0, 0) means red.

Run directly to get the flag

flag{fb8c67f9-712b-4f3d-9cb2-9219685421a9}

Each other

There's still only one file but this time it's an audio

the song is nice 

What is the first step to see the audio

A: Then it is the first step of audio, you must look at the waveform diagram

B: Hey, misc doesn’t matter what type, the first step must be to look at the source code of the file

Me: Shouldn't the first step to get the audio be to enjoy the song ? The most beautiful flower in the grassland is the fiery red Sarilang

OK, back to the topic

In fact, I also looked at the waveform diagram at the beginning, but it was of no use.

Then let's look at 010 from the source code and start

 We found an obvious hint at the end of the file

AES encryption password is 12345678

But this is offline and disconnected

Let's think about what steganography software is encrypted with AES

Silent Eye (silenteye) Don’t ask me how I know (it’s all about trial and error with tools on the computer) But this tool is quite unpopular

 We choose the file and choose to decrypt

Run to get a txt file (decompressed)

Inside is a dense code composed of 012

My god this is the most annoying thing

ok ok now let's think about it

What code is composed of three characters

I really can't remember a few at this moment.

However, we are carefully observing if we have to convert a character

0 is not the most frequently changed .

And 1 long thought !

This 2 is that ?

Then we directly replace

I don’t know if I don’t know what to do, this is not a variant code of brainfuck coding

You can use scripts or use offline toolboxes for disconnection. Fortunately, I have both. I am indeed a misc hand.

python2 ook.py -o 2.txt

 save to notepad

run again

python2 ook.py -b 3.txt

Get the flag, hey, the topic of this topic is unpopular

Replenish

Add some knowledge here

Ook! Ook! is a code expressed by imitating the language of orangutans. It is a variant encoding derived from Brainfuck. Ook! Ook! consists of three characters, "Ook.", "Ook?", and "Ook!".

Each "Ook!" represents an instruction. The following are the correspondences:

  • "Ook. Ook?": Equivalent to "<" in Brainfuck
  • "Ook? Ook.": Equivalent to ">" in Brainfuck
  • "Ook. Ook.": Equivalent to "+" in Brainfuck
  • "Ook! Ook!": Equivalent to "-" in Brainfuck
  • "Ook! Ook.": Equivalent to "." in Brainfuck
  • "Ook. Ook!": Equivalent to "," in Brainfuck
  • "Ook! Ook?": Equivalent to "[" in Brainfuck
  • "Ook? Ook!": Equivalent to "]" in Brainfuck

The Ook! Ook! code is similar in usage and meaning to Brainfuck, just described in a different language

Brainfuck is an encoding consisting of eight characters. This encoding is a minimalist programming language consisting of eight instruction symbols, including ">", "<", "+", "-", ".", ",", "[" and " ]".

Badimages

 Look at the name probably means broken mirror

The idea of ​​blind guessing this question is to restore a file or data inside

But this question has an unexpected solution,  if it is online, it will give me extra points

 I just cat him haha

 At the end we found the flag and ended directly

The normal solution is what I said at the beginning

If you are interested, you can try it

I will upload later when I need time

Cryoto

choir4

 

Only one source file and script

I should have guessed the idea by looking at this.

Flag runs task.py to get cipher

All we need to do is reverse the cipher in the parsing script to get the flag

The following is task.py Let's analyze it first

script analysis

 Of course, I will dissect each part of this script in detail:

from secret import flag

This line of code imports a variable flag from a module named  "secret" . Based on the information provided by the code snippet, we can assume that flag is a string containing the secret flag.

import random

This line of code imports Python's built-in module  random , which provides functions for generating random numbers.

k = random.randint( 0 , 255 )

This line of code uses the random.randint()  function to generate a random integer in the interval  [0, 255] (inclusive), and assigns it to the variable k. This random integer will be used as the key for the XOR operation.

cipher = “”

for c in flag:

    cipher += chr(ord(c) ^ k)

This part of the code uses a loop to iterate over each character in the flag string and does the following:

  • ord(c)  Gets the ASCII value of the character  c  .
  • XOR the ASCII value with the key k: ord(c) ^ k .
  • The chr()  function converts the result back to the corresponding character.
  • Finally, the resulting characters are appended to the cipher  string.

In this way, the loop is executed until the entire flag string is traversed, and the ciphertext string cipher  after the XOR operation is generated .

with open("cipher", "w") as f:

    f.write(cipher)

This part of the code creates a file named "cipher" using  the open()  function and opens it in write mode. Then,  write the ciphertext string  cipher  into the file through the write() method. Finally, use  the with  statement to ensure that file operations are properly closed.

The goal of the script is to encrypt a secret token using an XOR operation with a randomly generated key and save the resulting ciphertext to a file called "cipher"  .

Each character in the flag is XORed with the same number k for encryption.

All characters in the plaintext are XORed with the same key k.

Therefore, it is only necessary to enumerate 256 possible k, and then try to XOR decryption. If the decrypted string contains "flag", it means that the decryption is successful.

upper script

with open("cipher", "r") as f:

    cipher = f.read()

    #打开名为 "cipher" 的文件,并以只读模式打开它





for k in range(0, 256):

    msg = ""

    #外层循环使用 range(0, 256) 遍历从 0 到 255 的所有可能的密钥

    for c in cipher:

    #内层循环遍历 cipher 字符串中的每个字符

        msg += chr(ord(c) ^ k)

        #chr() 函数将结果转换回相应的字符。

-       #最后,将得到的字符追加到 msg 字符串中,以构建解密后的消息

    if "flag" in msg:

        print(msg)

        break

        #解密后的消息中包含字符串 "flag",则输出该消息并跳出循环

Run to get the flag

flag{c30dd6b0-38a3-5f88-830c-52ed3b67c81f}

insecure public key

 one public key one ciphertext

Obviously RSA decryption

The pem public key file can extract n and e

And if there is n, we need fermat decomposition to get p and q for rsa decryption

Of course, Feng Erxi 's tool should be the most convenient tool for offline rsa solution as far as I know.

But the script still needs to

# -*- coding: utf-8 -*-



from Crypto.PublicKey import RSA

from gmpy2 import *



def Pollard_rho_func_2(a,n):

    return (pow(a,n-1,n)+3)%n

with open('pub.pem', 'r') as f:

    key = RSA.importKey(f)

    print('n:'+str(key.n))

    print('e:'+str(key.e))

    n = key.n

    e = key.e



# 费get p,q



ori=2

a=Pollard_rho_func_2(ori,n)

b=Pollard_rho_func_2(a,n)

p=1

i=1

while (a!=b):

    if (gcd(abs(a-b),n)>1):

        p=gcd(abs(a-b),n)

        break

    else:

        a = Pollard_rho_func_2(a,n)

        b = Pollard_rho_func_2(b,n)

        b = Pollard_rho_func_2(b,n)

    i+=1

    if (i%100==0):

        print(i)

if (p!=1):

    print('p:'+str(p))

    q = n/p

    print('q:'+str(q))

# p= 189749484366449861630736482622030204229600074936733397229668738586605895979811823994029500725448581332746860468289540041125768726148614579255062994177531727784605194094836998282676712435286273497842956368997116036170165393912022560935791934662695453870846024312915604049805219410140420469163797779129644454583

# q= 177993461816075408240866752227210319316825574291000376727523991315086097605063837563342286560819823849610146713383370383386260295565108973920944593141677024612114517119831676665456754235233172344362610684938542774386956894066675103840244633202469661725050948177995671009070311486253646420435061175078660441183



d = invert(e,(p-1)*(q-1))

print('d:'+str(d))

#c = 0xc1bb8cbb9581abf710cab1908a04772f6cc972756e161a5a0615eaf1505d6928e545e626a508abd8c008d43c4eab5ee751c2b5e297891784dc851d8ba887907278142bc70649b503fdec092b143f3afc4508e1671f503c8e38d624befdeeea2bfd3e947289000568a2e409d0f955e19ebb9dccb798543c6435247a8d6b05facddb7f270fce1cecf92994beb7f3119d7f09caa4cff46c9e8db119e41726d0a0ce02ab2b5ae42c3e64c17746a29a32bd642a6045d73078ae8bd1f54a869760474b395c493ffc69cd8020647dcb0610779296a7c18aa984c5b74414e45bdf5d44000888765e457fb84e1ba3b6f60f7ab4f3b9047614f36adf49eac5d662c5916fb8

c = 0x2093fdefa37b3b4ef0d45f42e32f98aa3f1495f06ef6a24250



origin = pow(c,d,n)

print('*'*20)

print(hex(origin)[2:].decode('hex'))

get gkce~ow]dDyYsg|]{<}jtcsq

It looks like it's either Caesar or a fence because there are two brackets

There are tools that can be used, but script writing still needs to be known

a = "gkce~ow]dDyYsg|]{<}jtcsq"

b = ''

# 遍历字符串 'a' 中的每个字符for i in range(len(a)):

    j = i / 2 + 1



    # 如果索引 'i' 是偶数,则从字符的 ASCII 值中减去 'j'

    if i % 2 == 0:

        b += chr(ord(a[i]) - j)

    else:

        # 如果索引 'i' 是奇数,则将 'j' 添加到字符的 ASCII 值中

        b += chr(ord(a[i]) + j)

# 打印转换后的字符串 'b'print(b)

In this code, you use a loop to go through each character of the string a and perform some arithmetic operations to encrypt or decrypt the characters.

Specifically, during encryption, you get the encrypted character by taking the character's ASCII code minus the index, dividing by 2 and adding 1. And during decryption, you divide the ASCII code of the character plus the index by 2 to get the original character.

Based on the string "a" you provided,

flag{we_l0v3_encrYpti0n}

one character only

 The moment the file is opened

is this one character is this a bunch of characters

so annoying

But when I saw this, I suddenly thought of the big question of AL, a misc question on the ISCC online this year.

At the end of that question, I got a text similar to the above. Only one of the lines is true after encoding and decoding.

Other lines are full of noise information

Feeling over, let's continue to look at this question

All text is in hexadecimal representation

You can convert all characters to ascii to see the content

But found that the output after the conversion is garbled

 The name of the topic is only one character 

Combining previous experience and similar questions online to guess that it is XOR encryption  and the correct answer is the result of one line using a certain character XOR 

The idea should be this, but if you really try to solve them one by one, I am afraid that the entire offline time will not be enough.

Since you don't know whether the secret key is a visible character, you can use 0, 255 loop to decrypt all content

 Because the file has a total of 500 lines , each line is decrypted using 255 lines, and the final output result is 500 *255=127500 lines . Even if the correct result is among them, it is difficult for us to view line by line with our eyes.

Because the final flag must be readable ascii code, we filter out the results of combinations of numbers, letters, and spaces in all results

This is a general idea

A detailed explanation of the script will be given later

#coding:utf-8

import binascii



# 将16进制转换为ASCII

def hex2char(data):

    output = binascii.unhexlify(data)

    return output



# 异或解密函数,tips为加密字符串,key为秘钥,长度可变

def xor_encrypt(tips, key):

    lkey = len(key)

    secret = []

    num = 0



    for each in tips:

        if num >= lkey:

            num = num % lkey



        # 将每个字符与秘钥进行异或运算,并将结果转换为ASCII字符

        secret.append(chr(ord(each) ^ ord(key[num])))

        num += 1



    # 将解密后的字符列表连接成字符串并返回

    return "".join(secret)



# 打开文件并读取所有行的内容

txt = open('enc.txt', 'r').readlines()



# 遍历文件中的每一行

for line in txt:

    # 尝试使用0到255之间的不同整数作为秘钥进行解密操作

    for i in range(0, 255):

        a = 1

        result = xor_encrypt(hex2char(line.strip('\n')), chr(i))



        # 筛选出只包含数字、字母和空格的解密结果

        for j in result.strip('\n'):

            k = ord(j)



            # 如果字符不是数字、字母或空格,则将标志a设置为0

            if k < ord('z') + 1 and k > ord('0') - 1:

                pass

            elif k == 32:

                pass

            else:

                a = 0

                break



        # 如果解密结果只包含数字、字母和空格,则打印该结果

        if a == 1:

            print(result)

        # python2

code explanation

When you run this code, it tries to decrypt every line in an input file called 'enc.txt'.

First, the code defines two functions:

1. The hex2char(data) function uses the binascii module to convert hexadecimal data to an ASCII string.

  • It accepts a parameter data, which represents the hexadecimal data to be converted.
  • The function internally calls the binascii.unhexlify() function to perform the conversion operation.
  • Finally, the converted ASCII string is returned as the result. 2.

2. The xor_encrypt(tips, key) function performs XOR encryption and decryption operations.

  • It accepts two parameters: tips indicates the string to be encrypted or decrypted, and key indicates the key.
  • Some variables are defined inside the function: lkey indicates the length of the key, secret is used to store the result of encryption or decryption, and num is used to track the character position in the key.
  • The function encrypts or decrypts by XORing the key and the input string character by character. If the key is not long enough, the characters in the key are recycled.
  • The XOR operation works by converting the characters to ASCII codes, performing the XOR operation, and then converting the result back to character form.
  • Finally, the function concatenates all the resulting characters into a string and returns it.

Next, let's analyze the main code logic:

  1. txt = open('enc.txt', 'r').readlines(): Open the file named 'enc.txt' and read all the lines, storing each line as a string in the txt list.
  2. for line in txt:: traverse each line in the txt list (that is, each line in the file).
  3. for i in range(0, 255): Loop for integer values ​​from 0 to 254 (ASCII code range), which represent possible key characters.
  4. a = 1: Initialize the variable a to 1, which is used to mark whether the decryption result meets the filtering conditions.
  5. result = xor_encrypt(hex2char(line.strip('\n')), chr(i)): Remove the newline character from the current line content and convert it to an ASCII string. Then, call the xor_encrypt() function using the key character in the current loop to decrypt the current line content, and store the decrypted result in the result variable.
  6. Next, filter the decryption results through the following steps:
  • for j in result.strip('\n'):: Loop through each character in the decryption result.
  • k = ord(j): Get the ASCII code of character j and store it in the k variable.
  • Checks if the ASCII code of a character satisfies the following conditions:
  • if k < ord('z') + 1 and k > ord('0') - 1: pass: The character is the ASCII code range between numbers or letters, and the loop continues.
  • elif k==32: pass: The character is the ASCII code of a space, and the loop continues.
  • else: a = 0; break: If the character is neither a number nor a letter, nor a space, then set the variable a to 0 and break out of the inner loop.

7.if a == 1: print(result): After completing the inner loop, check whether the value of variable a is 1. If yes, it means that the decryption result meets the filtering conditions, and it will be printed out. \ 

Run to get the flag, preferably in python2 environment

flag{leKwFMfjcEitrqoTmdkIZSPRVLYxWsQU}

Come on everyone ( •̀ ω •́ )y look forward to seeing you again

Guess you like

Origin blog.csdn.net/m0_68012373/article/details/131585500