Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Whatever we input, the binary searches for characters in our input that are the same as a character of the flag in the same position. It prints the number of characters before the first occurrence of this. For example, if the flag was FwordCTF{}, then...
Fgjehrfd -> 0
sws -> 1
gggg -> 4
Using this, we can run a simple byte by byte bruteforce in order to get the data in flag.txt - NuL1_Byt35?15_IT_the_END?Why_i_c4nT_h4ndl3_That!}
Adding the flag format, we get the flag, FwordCTF{NuL1_Byt35?15_IT_the_END?Why_i_c4nT_h4ndl3_That!}
I used backticks for padding since they were pretty much guaranteed not to be in the flag - we can send backtick_padding + char and bruteforce "char" until the number returned equals the number of backticks, the character of the flag in that position would be the char where the server returned number is equal to the number of backticks.
https://github.com/tna0y/Python-random-module-cracker
(title hints at mersenne twister, which is what python random uses)
script below:
We are only allowed to use these characters: $()_[]=+;".
Webserver evals our input.
We also have a 2000 character cap (found by experimenting)
Found a pretty good resource on this:
Main idea is to
use underscores for variables names
use $_=([]."")[([]==[])+([]==[])+([]==[])]
to get a lowercase a
use $_=([]."")[[].[]+[][[]]]
to get an uppercase A
use [varname]++
to increase the ascii value for each of these to get all ascii letters
take a string and join our characters one by one with .=
for other characters, we can just join then with .="char"
, assuming it is allowed.
Our first goal is to get phpinfo, to see if there are any disabled functions:
Payload:
We can see that useful functions which would have allowed us to read from the file like file_get_contents are disabled. However, readfile() is not disabled, so we can use that. We can then use printf() to output that to us.
Our final payload will then eval to: printf(readfile("FLAG.PHP"))
Final payload:
(need to view source to see it)
Numbers
The program is a constant prompt that... 1. Reads a number from us 2. Checks if the number is greater than 60, if so it tells us we're naughty and exits 3. Reads that amount of data into a 64 length buffer 4. Prints the data 5. Asks if we want to try again, just dont type n
There's also some prompts inbetween but those aren't important. At first glance, this seems perfectly secure. But actually, note this code snippet.
It actually uses atoi to convert our input to a number, and atoi allows signed integers.
This means we can enter a negative number, like -1, and atoi will return 0xffffffff
the read function takes a size_t parameter - it wont think we're trying to read -1 bytes of data, but 4294967295
bytes of data. Now that's a lot of overflow.
PIE is on, so we cant just overwrite the return address of the integer reading function, ret2plt and call it a day. Because it prints our input back at us, we can exploit it similarly to skywriting from redpwn.
As a recap, strings are terminated by null bytes. When a function, like printf in this case, attempts to print a string, it will continue reading data until it reaches a null byte, at which it will stop.
If we make our input long enough, overwriting null bytes and nudging itself next to some data, said data can be leaked. Imagine it like this:
(our input is at the beginning, and we wish to leak the 0xdeadbeef data) currently this reads as an empty string let's fill the input with AAAA
Now, the null bytes have been overwritten, so the 0xdeadbeef is part of the string! This reads to be AAAA\xde\ad\be\ef.
8 bytes from the beginning of our buffer is atoi+16, we can leak this using this method and calculate the libc base. Our input is 72 bytes from the return address, so after leaking we will send 72 bytes of padding + poprdi + /bin/sh + retgadget(stack alignment) + system to overwrite the return address of the buffer reading function and pop a shell.
Then, cat flag.txt
to get the flag.
Send size of -1 to gain large buffer overflow
Send 8 bytes to leak libc address(atoi+16)
Use libc-database find to get the remote libc(libc6_2.28-0ubuntu1_amd64)
Use size -1 trick again to overwrite return address and send system("/bin/sh") rop chain to pop a shell
The binary has no protections except Partial RELRO.
The menu has 3 options besides exiting, one of which is secret.
We can read into a shellcode pointer, but only 5 bytes get read. We can execute said shellcode. This is all pretty much useless since 5 bytes of shellcode is not enough to do literally anything useful.
There's a secret option - gomugomunomi. It reads 100 bytes of input(no BOF) and then printfs it, allowing us to execute the classic format string exploit.
I tried to do the simple %p leak, but found no useful addresses on the stack. Instead, I used %s to read my buffer(offset 7, found through pwntools automation) as an address of a string in order to read got entries.
By doing gotaddress + %7$s we can leak got addresses to get a libc leak. We'll use libc-database find yet again to get the remote libc, libc6_2.30-0ubuntu2.2_i386
Then, we'll execute a got overwrite attack by overwriting printf@got with system. Next gomugomunomi, the input will be system'd, so we enter /bin/sh to get dropped into a shell.
But it's not over! On the remote, there is no cat. The solution to read flag.txt is simple - while read line; do echo $line; done < flag.txt
This reveals the flag.
gotaddress+ %7$s to leak libc
Format string overwrite to map printf to system
In gomugomunomi, send /bin/sh
Use while read line; do echo $line; done to read the flag file as cat is nonexistent
If you request the sums of 0 1, 1 2, and 2 0, you can sum them and divide to get the sum of 0, 1 and 2.
Then subtracting one of the above from this lets you find 0, 1 and 2, from which you can ask for 2 3 to get 3, etc.
Script below.
Looking at the script, it scrambles the flag (by using one of the flag's characters as the seed), splits it into blocks of 2 bytes, and then pads them, and then AES encrypts them with a known key.
We start by decrypting each block with the key to get a long string: aaFho_i_aC2b_abfc8edFw!kolae_ngbom_r__f_9T525eg__ihedd}{pmertt
Then, we bruteforce the seed by trying each of the characters of the flag as the seed. We do this by scrambling our own string (I chose ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
) with the seed, and then comparing it to the above string and see if it's in flag format.
Seeing as "w" only appears once, and it is in the flag format, I based my check on this. We check if our output string[21] is equal to "B", since this is its place in the flag format.
We get our seed as "h", and we encrypt our string with it. Last thing to do is to match each character up to its original position. Script below:
Chuck it in ghidra or your favourite decompiler/analyser - we see it prints the system address to us, then uses gets to read an input. This is a classic buffer overflow which we'll attack with ret2libc.
As it prints the libc address of system, we can simply use that to calculate the libc base. The binary is 32-bit, and it reads input into ebp-0x1c, giving 32 bytes of padding until return address overwrite. Then, we just send system + junk + /bin/sh address
Note that we don't know the remote libc - I used libc-database find to get the remote libc binary, which is libc6_2.30-0ubuntu2_i386
So: 1. Receive libc address 2. Calculate libc base 3. Build ret2libc system("/bin/sh") chain 4. Pop shell, cat flag.txt
Here's what the program does
First of all, use a mess function to encode the flag. This mess function is easily byte by byte bruteforceable if we use the printable range of characters.
Let's call this mflag.
Next, it pads the mflag so that it's length is a multiple of 9 using .
Then, it encrypts the mflag using matrix multiplication. Splitting the mflag into bunches of 9, it fills up a 3x3 matrix using the ascii values, multiplies it by a key that we know, transposes the resulting matrix, and turns it into a string result of of form
This is all done using the messig_up function. Then, it takes the output, parses it, and uses an encode function to encode each of the numbers, writing them all to the output file. I didn't reverse the encode function, and instead just did a classic bruteforce to get the numbers which were all less than 2500.
Here's how the solve script operates.
Create a mapping of all possible encodings. Now, decode all the number encodings using this mapping.
Split the numbers into groups of 9, fill up 3x3 matrices, and transpose these matrices to get the pure matrix multiplication outputs.
Calculate the matrix inverse of the matrix key, then multiply the matrices by this inverse to get the original matrices
String together all these matrices back into a string by taking the ascii values(we call round, as the results will be floats) to get mess(flag)
Use our byte by byte bruteforce mess function to decode the messed flag.
Script below:
The start of the challenge links you to a twitter (https://twitter.com/1337bloggs). This brings you to the person of Fred Bloggs.
After looking through the followers of 1337 bloggs, you get a twitter of a team called Eword, mentioned in the challenge description (https://twitter.com/EwordTeam).] We also get a CTFtime page(https://ctftime.org/team/131587), however looking at this brings nothing of interest.
[this is where the guessing picks up]
Maybe there was something on the CTFtime page that they didn't want us to see.
Using the wayback machine ( a group of archived internet pages), we find 2 archived pages.
Clicking on one of these archived pages leads us to here.
https://web.archive.org/web/20200826195056/https://ctftime.org/team/131587
We can see a pastebin link (https://pastebin.com/8bk9qLX1) that leads us to some clues.
The most interesting thing here is the 2nd pastebin link, leading us to some base64.
This base64 can be converted here: (https://base64.guru/converter/decode/file) and is reconstructed to a jpg.
We get 3 pretty big clues here:
The social media platform he uses (instagram, due to the layout resembling an Instagram story)
The line "thanks to the advisor for recommending it for me". This advisor refers to Trip Advisor, a reviw site.
A picture of the hotel he was staying at.
After using google lens, we find out that our target is staying at "Hilton Podgorica Crna Gora" in Macedonia.
After staring at reviews for an hour, I was stuck, until will came in and gave me a s*nity check, realisng that the person who we needed to catch was right in front of us the whole time.
The man we are looking for was found, Wokaihwokomas Kustermann.
He had the username of "check my instagram" on trip advisor, so a simple sherlock search should do the trick.
We found an instagram!
After opening his profile picture fully, you get the flag of:
Each character of the plaintext is encrypted using a known N and unknown e, creating a ciphertext array we're given. Infact, the actual RSA behind it is completely irrelevant. All we need to know is that each character is mapped to a number via a mapping function which we cannot reverse. The ciphertext is 932 numbers long, with 31 unique numbers, making it the equivalent of a simple substitution cipher which we can easily break using frequency analysis.
I used this script(with the values already loaded in enc)
Which prints out:
I'm not sure why the output is wrong, but it can be chucked into a substitution cipher solver(https://www.guballa.de/substitution-solver) to get the real plaintext:
From here we can see the flag is WELLFREQUENCYANALYSISROCKS wrapped in the flag format(you actually had to put it in lowercase too)
Basically, there is an LCG being used to generate the string of numbers. It takes a seed, multiplies it with "a", adds "b", and then takes that mod a prime "p".
We don't know any of these values however. It generates a list of numbers from a starting random seed this way, and then xors each character of the flag to get a new list.
We know the flag format is "FwordCTF{"
, so we can start by XORing these characters to get the actual string of LCG generated numbers: [6680465291011788181, 5100570103593250306, 5906808313299165163, 1965917782737693404, 9056785591048864532, 1829758495155458643, 6790868899161600099, 1596515234863242753, 1542626304251881944]
Now, we do some modular maths stuff:
6680465291011788181 a + b = 5100570103593250306 5906808313299165163 a + b = 1965917782737693404(all of these are taken mod p of course) 1596515234863242753 * a + b = 154262630425188194
We can subtract the equations from each other to get rid of the b: (6680465291011788181 - 5906808313299165163)a = 5100570103593250306 - 1965917782737693404 (5906808313299165163 - 1596515234863242753)a = 1965917782737693404 - 1542626304251881944
Simplifying:
Im using these from now because idk why the others arent working
Solve script:
when connecting to the service i tried most of the common priv esc techniques but none worked however. After being triggered for hours because it wasn't sudo -l i read the briefing again. I then googled the briefing and after quite a bit of endless googling found something called linux capabilities that could be exploited. I ended up finding this website about it:
After running the check to see if this could be exploited on our system:
this shows the same thing as the website so we know it should be able to be exploited.
We see that the binary tar has the privelages to read anything on the file system.
We attempt the example on /etc/shadow just like in the website and then go on to do the same thing on the flag.txt file:
We then go into the /tmp/home/user1
directory and read the flag.txt
file
NULL
First of all, there are a few things in the header we need to fix. The first byte needs to be a 89, not a 69 (nice), and we need to capitalize the IHDR chunk header thing (idk)
Next, if we run a pngcheck, we see that the dimensions are 0x0. Thinking back to dimensionless loading, we can bruteforce the dimensions if the crc32 is intact.
We then change the dimensions using something like GHEX: and then we can open the image as normal to get the flag.