add exterminated writeup and fix diplodocus typos
Signed-off-by: Julien CLEMENT <julien.clement@epita.fr>
This commit is contained in:
parent
3e9261a7c8
commit
55075855bb
288
jujure/content/writeups/fcsc_2022/EXTerminated.md
Normal file
288
jujure/content/writeups/fcsc_2022/EXTerminated.md
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
---
|
||||||
|
title: "Decrypting cryptolocked partition | EXTerminated @ FCSC 2022"
|
||||||
|
date: "2022-05-08 19:00:00"
|
||||||
|
author: "Juju"
|
||||||
|
tags: ["Reverse", "Writeup", "fcsc"]
|
||||||
|
toc: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Intro
|
||||||
|
|
||||||
|
EXTerminated is a malware reversing challenge. You are handed an EXT4 partition
|
||||||
|
that has been encrypted by a malware, your goal is to recover the original
|
||||||
|
unencrypted files.
|
||||||
|
|
||||||
|
The description of the challenge tells us that the malware does not use any
|
||||||
|
known cryptosystem to encrypt data, let's find this out.
|
||||||
|
|
||||||
|
{{< image src="/EXTerminated/panik.png" style="border-radius: 8px;" >}}
|
||||||
|
|
||||||
|
## Challenge description
|
||||||
|
`reverse` | `472 pts` `12 solves` `:star::star:`
|
||||||
|
```
|
||||||
|
Un client a détecté un seveur compromis sur son parc. Ce serveur semble avoir
|
||||||
|
perdu l'ensemble de ses données suite à une infection. Il nous indique que les
|
||||||
|
attaquants exigent une rançon et affirment pouvoir récupérer les fichiers
|
||||||
|
disparus.
|
||||||
|
|
||||||
|
Une analyse rapide du virus indique que ce dernier ne disposerait à première
|
||||||
|
vue d'aucun algorithme cryptographique connu.
|
||||||
|
|
||||||
|
On vous demande d'analyser ce disque, et de récupérer les fichiers originaux.
|
||||||
|
|
||||||
|
SHA256(disk.img) = a9e7891224868af43e2aa134152beaa2a83f43cde21af8038d138001377157dc.
|
||||||
|
```
|
||||||
|
|
||||||
|
Author: `Nofix`
|
||||||
|
|
||||||
|
## Given files
|
||||||
|
|
||||||
|
[disk.img](/EXTerminated/disk.img)
|
||||||
|
|
||||||
|
# Writeup
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
So we can see we are given an EXT4 partition.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ file disk.img
|
||||||
|
disk.img: Linux rev 1.0 ext4 filesystem data,
|
||||||
|
UUID=c26167b3-e0b9-441d-ab4d-a5f4b5b1fcd0 (extents) (64bit) (large files)
|
||||||
|
(huge files)
|
||||||
|
```
|
||||||
|
|
||||||
|
Let's try to mount it.
|
||||||
|
|
||||||
|
We can see that there are multiple pictures, a pdf and an executable called
|
||||||
|
`wannaweep`, which is probably our malware.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ sudo mount -o loop ./disk.img mnt/
|
||||||
|
$ tree mnt/
|
||||||
|
mnt/
|
||||||
|
├── Documents
|
||||||
|
│ └── anssi-guide-ransomware_attacks_all_concerned-v1.0.pdf
|
||||||
|
├── Images
|
||||||
|
│ ├── accident.png
|
||||||
|
│ ├── disk.jpg
|
||||||
|
│ ├── flag.jpg
|
||||||
|
│ ├── martine.jpg
|
||||||
|
│ ├── smile.png
|
||||||
|
│ ├── tintin.jpeg
|
||||||
|
│ └── valide.png
|
||||||
|
├── lost+found [error opening dir]
|
||||||
|
└── wannaweep
|
||||||
|
|
||||||
|
3 directories, 9 files
|
||||||
|
```
|
||||||
|
|
||||||
|
By further investigating we can see that all data of the files have been erased
|
||||||
|
except for wannaweep, which definitely is the malware, an x64 stripped and
|
||||||
|
dinamically linked ELF.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ file mnt/Images/flag.jpg
|
||||||
|
mnt/Images/flag.jpg: data
|
||||||
|
$ xxd mnt/Images/flag.jpg | head
|
||||||
|
00000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................
|
||||||
|
00000010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
|
||||||
|
00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
|
||||||
|
00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................
|
||||||
|
00000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
|
||||||
|
00000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
|
||||||
|
00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
|
||||||
|
00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
|
||||||
|
00000080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
|
||||||
|
00000090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
|
||||||
|
$ file mnt/wannaweep
|
||||||
|
mnt/wannaweep: ELF 64-bit LSB executable, x86-64, version 1 (SYSV),
|
||||||
|
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2,
|
||||||
|
BuildID[sha1]=590a9f68cde37ffceb8e7441db343742e4032f47, for GNU/Linux
|
||||||
|
3.2.0, stripped
|
||||||
|
```
|
||||||
|
|
||||||
|
We can see that the binary links to `libext2fs.so.2`, a library for EXT file
|
||||||
|
system parsing and manipulation. Since it is dinamically linked we will still
|
||||||
|
have the corresponding symbols so I'm guessing I won't have too much trouble
|
||||||
|
understanding what the malware does even though I do not know the EXT
|
||||||
|
specification.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ ldd mnt/wannaweep
|
||||||
|
linux-vdso.so.1 (0x00007ffccb2b3000)
|
||||||
|
libext2fs.so.2 => /usr/lib/libext2fs.so.2 (0x00007f8059117000)
|
||||||
|
libcom_err.so.2 => /usr/lib/libcom_err.so.2 (0x00007f8059111000)
|
||||||
|
libc.so.6 => /usr/lib/libc.so.6 (0x00007f8058f07000)
|
||||||
|
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f80591ad000)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Main
|
||||||
|
|
||||||
|
It is now the perfect time for me to absolutely not launch this program, I
|
||||||
|
could have setup a sandboxed environment but it turned out it wasn't necessary,
|
||||||
|
the code was really straight forward.
|
||||||
|
|
||||||
|
So I start my favorite decompiler and I download the source code of libext2fs.
|
||||||
|
|
||||||
|
A small fast forward in time as the main function is really straight forward,
|
||||||
|
|
||||||
|
The program takes the path to the device to encrypt as argument, calls a bunch
|
||||||
|
of function that are mostly wrappers around libext2fs functions to initialize
|
||||||
|
some global variables holding structures of the EXT filesystem. It alsos checks
|
||||||
|
that some flags are set in the structures of libext2fs, I do not know if these
|
||||||
|
flags are implementation specific or are standard EXT flags but I did not
|
||||||
|
bother too much with this.
|
||||||
|
|
||||||
|
The intersting stuff is at the end, I can see that it calls a function that
|
||||||
|
I called `encrypt_folder` after reversing it. It then flushes the filesystem to
|
||||||
|
disk and write the inode bitmap.
|
||||||
|
|
||||||
|
{{< code file="/static/EXTerminated/main.c" language="c" >}}
|
||||||
|
|
||||||
|
## Encrypt folder
|
||||||
|
|
||||||
|
Alright so let's take a look at the `encrypt_folder` to understand why I called
|
||||||
|
it this way.
|
||||||
|
|
||||||
|
I could clearly see from `main` that function was called with the string `.`
|
||||||
|
to reference the current directory, and a function pointer that was still
|
||||||
|
unkown to me at the time but that I renamed `encrypt_file`.
|
||||||
|
|
||||||
|
How I knew that the function was encrypting folders and that the parameter was
|
||||||
|
a callback to encrypt files is really simple, you can clearly see the libc
|
||||||
|
symbols calling `opendir` on the path given as argument (`.`), reading all the
|
||||||
|
entries of the directory and calling the callback if the entry is a file.
|
||||||
|
|
||||||
|
If it is not a file, it will `chdir` in the said directory, before recursively
|
||||||
|
calling itself with the same arguments.
|
||||||
|
|
||||||
|
{{< code file="/static/EXTerminated/encrypt_folder.c" language="c" >}}
|
||||||
|
|
||||||
|
|
||||||
|
## Encrypt file
|
||||||
|
|
||||||
|
Let's now look at the `encrypt_file` we guessed. Again, mostly wrapper
|
||||||
|
functions so I did not bother to show you why I named them this way, the code
|
||||||
|
basically reads the content of the file to encrypt, encrypts it in a dedicated
|
||||||
|
block, puts it in the file system before deleting the original content of the
|
||||||
|
file.
|
||||||
|
|
||||||
|
{{< code file="/static/EXTerminated/encrypt_file.c" language="c" >}}
|
||||||
|
|
||||||
|
## Encrypt block
|
||||||
|
|
||||||
|
Well, I was scared of custom cryptography but this seems simple enough for me.
|
||||||
|
To encrypt a plain text block, the malware starts at the last byte of the block
|
||||||
|
and xor it with the previous one until it reaches the start.
|
||||||
|
Actually this function does a heap buffer underflow when xoring the first byte
|
||||||
|
of the block, since it will xor it with the byte right before the block in the
|
||||||
|
heap.
|
||||||
|
|
||||||
|
Reversing the encryption is trivial, the only undefined behaviours is with the
|
||||||
|
underflow because we cannot know the value of the byte preceding the block.
|
||||||
|
However, I assumed it would really likely be 0.
|
||||||
|
|
||||||
|
{{< code file="/static/EXTerminated/encrypt_block.c" language="c" >}}
|
||||||
|
|
||||||
|
## Decrypting
|
||||||
|
|
||||||
|
So to decrypt a block, we simply need to know the value of the byte preceding
|
||||||
|
the buffer. Let's assume it is 0 since it is the most likely.
|
||||||
|
|
||||||
|
I will xor this byte with the first byte of cipher text and that will give
|
||||||
|
me the first byte of plain text, I then repeat the operation, xoring the
|
||||||
|
first byte of plain text with the second byte of cipher text and I do this
|
||||||
|
for the whole block to recover the entire block.
|
||||||
|
|
||||||
|
|
||||||
|
## Solve
|
||||||
|
|
||||||
|
So know I know how to decrypt a block, let's decrypt the whole filesystem.
|
||||||
|
|
||||||
|
I could do something really smart and overengineered to recover a valid
|
||||||
|
decrypted EXT filesystem that I could mount to recover the original files.
|
||||||
|
|
||||||
|
However I'm not familiar with the EXT specification and their are still small
|
||||||
|
shadow zones in the malware code for me, so I try a naive solution.
|
||||||
|
|
||||||
|
I'm guessing that data blocks of files or all alligned on `0x1000`, it would be
|
||||||
|
kind of weird otherwise for me. So if I just cut the whole filesystem in
|
||||||
|
`0x1000` sized blocks without any consideration of the semantic of those blocks
|
||||||
|
in the EXT structure, I could just decrypt each of these blocks individually,
|
||||||
|
and prey that I recover some files whose blocks were contiguous in the EXT
|
||||||
|
structure.
|
||||||
|
|
||||||
|
Obviously that will corrupt all the EXT metadata but it doesn't really matter
|
||||||
|
as long as I can recover the files.
|
||||||
|
|
||||||
|
{{< code file="/static/EXTerminated/decrypt.py" language="py" >}}
|
||||||
|
|
||||||
|
Now let's try to output the result and see if we find any file signatures:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ ./decrypt.py > decrypted.img
|
||||||
|
$ binwalk decrypted.img
|
||||||
|
|
||||||
|
DECIMAL HEXADECIMAL DESCRIPTION
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
9289728 0x8DC000 PNG image, 473 x 306, 8-bit/color RGB, non-interlaced
|
||||||
|
9531392 0x917000 JPEG image data, JFIF standard 1.01
|
||||||
|
9625600 0x92E000 PNG image, 500 x 564, 8-bit/color RGBA, non-interlaced
|
||||||
|
10125312 0x9A8000 JPEG image data, JFIF standard 1.01
|
||||||
|
10212833 0x9BD5E1 bix header, header size: 64 bytes, header CRC: 0x6003083D, created: 2004-01-10 13:39:36, image size: 2097152 bytes, Data Address: 0x22120000, Entry Point: 0x1E040003, data CRC: 0xD2100008, CPU: IA64, image name: ""
|
||||||
|
10231808 0x9C2000 JPEG image data, EXIF standard
|
||||||
|
10231820 0x9C200C TIFF image data, big-endian, offset of first image directory: 8
|
||||||
|
10330112 0x9DA000 JPEG image data, EXIF standard
|
||||||
|
10330124 0x9DA00C TIFF image data, big-endian, offset of first image directory: 8
|
||||||
|
10403840 0x9EC000 PNG image, 482 x 367, 8-bit/color RGB, non-interlaced
|
||||||
|
10403902 0x9EC03E Zlib compressed data, default compression
|
||||||
|
34263365 0x20AD145 Cisco IOS experimental microcode, for ""
|
||||||
|
46640306 0x2C7ACB2 MySQL ISAM compressed data file Version 9
|
||||||
|
46691658 0x2C8754A GIF image data 15531 x
|
||||||
|
```
|
||||||
|
|
||||||
|
We do! So let's try to extract them
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ binwalk --dd='.*' decrypted.img
|
||||||
|
|
||||||
|
DECIMAL HEXADECIMAL DESCRIPTION
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
9289728 0x8DC000 PNG image, 473 x 306, 8-bit/color RGB, non-interlaced
|
||||||
|
9531392 0x917000 JPEG image data, JFIF standard 1.01
|
||||||
|
9625600 0x92E000 PNG image, 500 x 564, 8-bit/color RGBA, non-interlaced
|
||||||
|
10125312 0x9A8000 JPEG image data, JFIF standard 1.01
|
||||||
|
10212833 0x9BD5E1 bix header, header size: 64 bytes, header CRC: 0x6003083D, created: 2004-01-10 13:39:36, image size: 2097152 bytes, Data Address: 0x22120000, Entry Point: 0x1E040003, data CRC: 0xD2100008, CPU: IA64, image name: ""
|
||||||
|
10231808 0x9C2000 JPEG image data, EXIF standard
|
||||||
|
10231820 0x9C200C TIFF image data, big-endian, offset of first image directory: 8
|
||||||
|
10330112 0x9DA000 JPEG image data, EXIF standard
|
||||||
|
10330124 0x9DA00C TIFF image data, big-endian, offset of first image directory: 8
|
||||||
|
10403840 0x9EC000 PNG image, 482 x 367, 8-bit/color RGB, non-interlaced
|
||||||
|
10403902 0x9EC03E Zlib compressed data, default compression
|
||||||
|
34263365 0x20AD145 Cisco IOS experimental microcode, for ""
|
||||||
|
46640306 0x2C7ACB2 MySQL ISAM compressed data file Version 9
|
||||||
|
46691658 0x2C8754A GIF image data 15531 x
|
||||||
|
|
||||||
|
$ file _decrypted.img.extracted/*
|
||||||
|
_decrypted.img.extracted/2C7ACB2: MySQL ISAM compressed data file Version 9
|
||||||
|
_decrypted.img.extracted/2C8754A: GIF image data 15531 x
|
||||||
|
_decrypted.img.extracted/8DC000: PNG image data, 473 x 306, 8-bit/color RGB, non-interlaced
|
||||||
|
_decrypted.img.extracted/9A8000: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, progressive, precision 8, 660x424, components 3
|
||||||
|
_decrypted.img.extracted/9BD5E1: data
|
||||||
|
_decrypted.img.extracted/9C200C: TIFF image data, big-endian, direntries=0
|
||||||
|
_decrypted.img.extracted/9C2000: JPEG image data, Exif standard: [TIFF image data, big-endian, direntries=0], comment: "CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 90", baseline, precision 8, 481x600, components 3
|
||||||
|
_decrypted.img.extracted/9DA000: JPEG image data, Exif standard: [TIFF image data, big-endian, direntries=0], baseline, precision 8, 683x500, components 3
|
||||||
|
_decrypted.img.extracted/9DA00C: TIFF image data, big-endian, direntries=0
|
||||||
|
_decrypted.img.extracted/9EC000: PNG image data, 482 x 367, 8-bit/color RGB, non-interlaced
|
||||||
|
_decrypted.img.extracted/9EC03E: empty
|
||||||
|
_decrypted.img.extracted/9EC03E-0: zlib compressed data
|
||||||
|
_decrypted.img.extracted/20AD145: cisco IOS experimental microcode for ''
|
||||||
|
_decrypted.img.extracted/92E000: PNG image data, 500 x 564, 8-bit/color RGBA, non-interlaced
|
||||||
|
_decrypted.img.extracted/917000: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, baseline, precision 8, 495x669, components 3
|
||||||
|
```
|
||||||
|
|
||||||
|
Displaying the images we just extracted, we find the following one, giving us
|
||||||
|
the flag.
|
||||||
|
|
||||||
|
{{< image src="/EXTerminated/flag.png" style="border-radius: 8px;" >}}
|
@ -139,7 +139,7 @@ enum describing possible movements in this array. I therefore name them `move`,
|
|||||||
|
|
||||||
Next we notice that we check that the `jth` bit of the `ith` row of the array,
|
Next we notice that we check that the `jth` bit of the `ith` row of the array,
|
||||||
if is not set, it sets the said bit and update the coordinates in the context.
|
if is not set, it sets the said bit and update the coordinates in the context.
|
||||||
If however it is already set, the program set the error flag that we already
|
If however it is already set, the program sets the error flag that we already
|
||||||
identified earlier.
|
identified earlier.
|
||||||
|
|
||||||
Clearly this is some sort of 12 * 12 bitboard implementation, the first thing
|
Clearly this is some sort of 12 * 12 bitboard implementation, the first thing
|
||||||
@ -175,9 +175,9 @@ to place the said bit on a different bitboard than case 2 but with the same
|
|||||||
coordinates. If the bit queue is empty then we output an error.
|
coordinates. If the bit queue is empty then we output an error.
|
||||||
|
|
||||||
So I understand here that we must place 24 bits on another board while
|
So I understand here that we must place 24 bits on another board while
|
||||||
simultaneously moving on the first one that tracks the tile we already visited.
|
simultaneously moving on the first one that tracks the tiles we already visited.
|
||||||
|
|
||||||
Seems easy enough, however, the instruction does not end here, it call a
|
Seems easy enough, however, the instruction does not end here, it calls a
|
||||||
function passing the row of the bitboard as parameter, if the return value of
|
function passing the row of the bitboard as parameter, if the return value of
|
||||||
this function is more than `2` we output an error.
|
this function is more than `2` we output an error.
|
||||||
|
|
||||||
@ -267,15 +267,15 @@ traversal of the board, we did not encounter more than 2 bits.
|
|||||||
|
|
||||||
Here I was really scared because I started to think that this was maybe `\J`
|
Here I was really scared because I started to think that this was maybe `\J`
|
||||||
trolling me with again a cryptography problem modelised using bitboards are
|
trolling me with again a cryptography problem modelised using bitboards are
|
||||||
something. And everyone who checks my results of the FCSC know how bad I am
|
something. And everyone who checks my results of the FCSC know how bad I am at
|
||||||
cryptography.
|
cryptography.
|
||||||
|
|
||||||
{{< code file="/static/diplodocus/check_align.c" language="c" >}}
|
{{< code file="/static/diplodocus/check_align.c" language="c" >}}
|
||||||
|
|
||||||
#### Alignement count
|
#### Alignement count
|
||||||
|
|
||||||
So now I am really unhappy, I was having finding out puzzle and placing bits on
|
So now I am really unhappy, I was having fun finding out puzzle and placing
|
||||||
boards but now `\J` is throwing modular arithmetic at me.
|
bits on boards but now `\J` is throwing modular arithmetic at me.
|
||||||
|
|
||||||
I take a break crying in my bed after these findings before actually thinking.
|
I take a break crying in my bed after these findings before actually thinking.
|
||||||
|
|
||||||
@ -356,8 +356,8 @@ the point if you remember well.
|
|||||||
However the only columns check is in case 0 where it simply checks that there
|
However the only columns check is in case 0 where it simply checks that there
|
||||||
is an even number of point per column.
|
is an even number of point per column.
|
||||||
|
|
||||||
Nothing forbid us to put 12 points on the first and last column, which
|
Nothing forbids us to put 12 points on the first and last column, which
|
||||||
validates all our constraints
|
validates all our constraints.
|
||||||
|
|
||||||
```
|
```
|
||||||
|X| | | | | | | | | | |X|
|
|X| | | | | | | | | | |X|
|
||||||
@ -374,6 +374,8 @@ validates all our constraints
|
|||||||
|X| | | | | | | | | | |X|
|
|X| | | | | | | | | | |X|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
{{< image src="/diplodocus/stop_the_count.png" style="border-radius: 8px;" >}}
|
||||||
|
|
||||||
## Solve
|
## Solve
|
||||||
|
|
||||||
We now simply need to write the input that will give instructions to the
|
We now simply need to write the input that will give instructions to the
|
||||||
|
19
jujure/static/EXTerminated/decrypt.py
Executable file
19
jujure/static/EXTerminated/decrypt.py
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
with open('./disk.img', 'rb') as f:
|
||||||
|
data = f.read()
|
||||||
|
blocks = [data[i * 0x1000:(i * 0x1000) + 0x1000] for i in range(len(data) // 0x1000)]
|
||||||
|
|
||||||
|
clear = bytearray()
|
||||||
|
|
||||||
|
for block in blocks:
|
||||||
|
x = 0
|
||||||
|
for b in block:
|
||||||
|
c = x ^ b
|
||||||
|
clear.append(c)
|
||||||
|
x = c
|
||||||
|
|
||||||
|
os.write(1, clear)
|
BIN
jujure/static/EXTerminated/disk.img
Normal file
BIN
jujure/static/EXTerminated/disk.img
Normal file
Binary file not shown.
9
jujure/static/EXTerminated/encrypt_block.c
Normal file
9
jujure/static/EXTerminated/encrypt_block.c
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
int64_t encrypt_block(char* block, int64_t len)
|
||||||
|
{
|
||||||
|
int64_t i;
|
||||||
|
for (i = 0; i < len; i = (i + 1))
|
||||||
|
{
|
||||||
|
block[((len - i) - 1)] = (block[((len - i) - 1)] ^ block[((len - i) - 2)]);
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
73
jujure/static/EXTerminated/encrypt_file.c
Normal file
73
jujure/static/EXTerminated/encrypt_file.c
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
int64_t encrypt_file(char* name)
|
||||||
|
{
|
||||||
|
return encrypt_file2(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t encrypt_file2(char* name)
|
||||||
|
{
|
||||||
|
int32_t inode = 0;
|
||||||
|
int32_t len_read = 0;
|
||||||
|
uint64_t blocksize = ((uint64_t)fs->blocksize);
|
||||||
|
void* block = xcalloc(1, blocksize); // Allocate data for encrypted block
|
||||||
|
int64_t fd = get_size(name); // Get the file size
|
||||||
|
if (fd != 0)
|
||||||
|
{
|
||||||
|
fd = open(name, 2); // Open the file
|
||||||
|
int32_t fd = fd;
|
||||||
|
if (fd != 0xffffffff)
|
||||||
|
{
|
||||||
|
if (inode == 0)
|
||||||
|
// Create an inode for the encrypted file
|
||||||
|
ext2fs_new_inode(fs, 0, 0x41ed, 0, &inode);
|
||||||
|
|
||||||
|
ext2fs_inode_alloc_stats2(fs, ((uint64_t)inode), 1, 1);
|
||||||
|
char stop = 0;
|
||||||
|
int64_t nb_blocks = 1;
|
||||||
|
uint64_t* blocks = xcalloc(1, 0x10);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// Fill the block with file data
|
||||||
|
if (fill_block(fd, block, blocksize, &len_read) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Determine if another block is needed to encrypt the file
|
||||||
|
int32_t n_blocks = len_read / 0x1000;
|
||||||
|
int32_t len_read;
|
||||||
|
if (len_read % 0x1000 != 0)
|
||||||
|
stop = 1;
|
||||||
|
|
||||||
|
// Encrypt the block
|
||||||
|
encrypt_block(block, ((int64_t)len_read));
|
||||||
|
|
||||||
|
// Write encrypted block to the filesystem
|
||||||
|
int64_t new_block = write_block(block, ((uint64_t)fs->blocksize), inode);
|
||||||
|
|
||||||
|
// Some stuff I did not bother to understand
|
||||||
|
// probably setting up recursive blocks for big files
|
||||||
|
// or preparing new empty blocks for the file that must be
|
||||||
|
// emptied
|
||||||
|
// but I do not know nor does it really matter for now
|
||||||
|
if (blocks[((nb_blocks - 1) * 2)] == 0)
|
||||||
|
{
|
||||||
|
blocks[((nb_blocks - 1) * 2)] = new_block;
|
||||||
|
blocks[(((nb_blocks - 1) * 2) + 1)] = new_block;
|
||||||
|
}
|
||||||
|
else if ((blocks[(((nb_blocks - 1) * 2) + 1)] + 1) != new_block)
|
||||||
|
{
|
||||||
|
nb_blocks = (nb_blocks + 1);
|
||||||
|
realloc(blocks, (nb_blocks << 4));
|
||||||
|
blocks[((nb_blocks - 1) * 2)] = new_block;
|
||||||
|
blocks[(((nb_blocks - 1) * 2) + 1)] = new_block;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
blocks[(((nb_blocks - 1) * 2) + 1)] = new_block;
|
||||||
|
|
||||||
|
memset(block, 0, ((uint64_t)fs->blocksize));
|
||||||
|
} while ((stop & 1) == 0);
|
||||||
|
// Remove data from the original file
|
||||||
|
fd = delete_data(name, nb_blocks, blocks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
28
jujure/static/EXTerminated/encrypt_folder.c
Normal file
28
jujure/static/EXTerminated/encrypt_folder.c
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
DIR* encrypt_folder(char* path, void* callback)
|
||||||
|
{
|
||||||
|
DIR* dir = opendir(path);
|
||||||
|
if (dir != 0)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
struct dirent64* dirent = readdir(dir);
|
||||||
|
if (dirent == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (((uint32_t)dirent->d_type) != 4)
|
||||||
|
{
|
||||||
|
callback(&dirent->d_name);
|
||||||
|
}
|
||||||
|
else if ((strcmp(&dirent->d_name, ".") != 0 && strcmp(&dirent->d_name, "..") != 0))
|
||||||
|
{
|
||||||
|
chdir(&dirent->d_name);
|
||||||
|
encrypt_folder(".", callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chdir("..");
|
||||||
|
dir = closedir(dir);
|
||||||
|
}
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
BIN
jujure/static/EXTerminated/flag.png
Normal file
BIN
jujure/static/EXTerminated/flag.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 90 MiB |
43
jujure/static/EXTerminated/main.c
Normal file
43
jujure/static/EXTerminated/main.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
int32_t main(int32_t argc, char** argv, char** envp)
|
||||||
|
{
|
||||||
|
int32_t res;
|
||||||
|
if (argc != 2)
|
||||||
|
{
|
||||||
|
char** rax;
|
||||||
|
rax = 0;
|
||||||
|
printf("Usage %s <device> \n", *(int64_t*)argv);
|
||||||
|
res = 1;
|
||||||
|
}
|
||||||
|
else if (check_fs_opened() != 0)
|
||||||
|
{
|
||||||
|
res = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
open_and_read(argv[1]);
|
||||||
|
if (fs == 0)
|
||||||
|
{
|
||||||
|
perror("Could not get handle on FS");
|
||||||
|
exit(1);
|
||||||
|
/* no return */
|
||||||
|
}
|
||||||
|
if (check_flag_clear() != 0)
|
||||||
|
{
|
||||||
|
res = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fs->blocksize != 0x1000)
|
||||||
|
{
|
||||||
|
perror("FS blocksize is invalid");
|
||||||
|
exit(1);
|
||||||
|
/* no return */
|
||||||
|
}
|
||||||
|
encrypt_folder(".", encrypt_file);
|
||||||
|
ext2fs_flush(fs);
|
||||||
|
write_inode_bitmap();
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
BIN
jujure/static/EXTerminated/panik.png
Executable file
BIN
jujure/static/EXTerminated/panik.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 191 KiB |
@ -16,7 +16,7 @@ case 0:
|
|||||||
zmm0 = (zmm0 & _mm_bsrli_si128(zmm0, 4));
|
zmm0 = (zmm0 & _mm_bsrli_si128(zmm0, 4));
|
||||||
|
|
||||||
int32_t all_set = (zmm0 & 0xfff) != 0xfff;// Check that context.third_board
|
int32_t all_set = (zmm0 & 0xfff) != 0xfff;// Check that context.third_board
|
||||||
err = all_set | err; // Is all set to 1
|
err = all_set | err; // is all set to 1
|
||||||
context.err = err;
|
context.err = err;
|
||||||
|
|
||||||
uint32_t flag = 1; // Set error flag
|
uint32_t flag = 1; // Set error flag
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
uint64_t sub_1570(int32_t j, int32_t i, struct context context)
|
uint64_t sub_1570(int32_t j, int32_t i, struct context context)
|
||||||
{
|
{
|
||||||
int32_t res = 0;
|
int32_t res = 0;
|
||||||
int32_t *board = context.board;;
|
int32_t *board = context.board;
|
||||||
int32_t res_flag = 0;
|
int32_t res_flag = 0;
|
||||||
if ((j <= 0xb && i <= 0xb))
|
if ((j <= 0xb && i <= 0xb))
|
||||||
{
|
{
|
||||||
@ -17,13 +17,13 @@
|
|||||||
int32_t x = -0xb; // Second increment
|
int32_t x = -0xb; // Second increment
|
||||||
int32_t neg = (y >> 0x1f); // Probably interesting
|
int32_t neg = (y >> 0x1f); // Probably interesting
|
||||||
int32_t r11_2 = ((y_cpy * -0xb) + rbp_1); // but I can't seem
|
int32_t r11_2 = ((y_cpy * -0xb) + rbp_1); // but I can't seem
|
||||||
int32_t y_cpy_cpy = ((neg ^ y) - osef); // to care enough
|
int32_t y_cpy_cpy = ((neg ^ y) - neg); // to care enough
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (x != 0)
|
if (x != 0)
|
||||||
{
|
{
|
||||||
int32_t neg = (x >> 0x1f); // Abs value again or
|
int32_t neg = (x >> 0x1f); // Abs value again or
|
||||||
int32_t x_cpy = ((neg ^ x) - osef); // something
|
int32_t x_cpy = ((neg ^ x) - neg); // something
|
||||||
int32_t y_cpy_cpy_cpy = y_cpy_cpy;
|
int32_t y_cpy_cpy_cpy = y_cpy_cpy;
|
||||||
int32_t count;
|
int32_t count;
|
||||||
while (true) // Euclidean algorithm
|
while (true) // Euclidean algorithm
|
||||||
@ -63,7 +63,7 @@
|
|||||||
|
|
||||||
// STOP THE COUNT
|
// STOP THE COUNT
|
||||||
int32_t too_much = count > 2;
|
int32_t too_much = count > 2;
|
||||||
res_flag = (res_flag | count>2);
|
res_flag = (res_flag | too_much);
|
||||||
}
|
}
|
||||||
if (x == 0xb) // End the while true loops and iterate
|
if (x == 0xb) // End the while true loops and iterate
|
||||||
{
|
{
|
||||||
|
BIN
jujure/static/diplodocus/stop_the_count.png
Normal file
BIN
jujure/static/diplodocus/stop_the_count.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 197 KiB |
Loading…
Reference in New Issue
Block a user