by Super Guesser
A simple stack bof challenge.
There is a libc-related value on the stack (specifically, same address with name
)
Just send a blank line then we can get libc leak.
After we can build ROP chain.
We can forge the length of table by setting malicious metatable.
I did not know about function collectgarbage
and light C function.
Hence, I built a heap fengshui payload to read binary(lua
)'s GOT and to write a win
function pointer into libc's GOT.
Following the below two code,
The maxmium parameterLimit
is 1000. So, If the depth is big enough, the last parameter will be ignored.
The first step is writing an html file with the delete endpoint with .html
extension.
It's not easy to execute that file as a html page. The trick to do this is using history.back()
. history API uses the cached page if it's available.
to get XSS, we should use the replace function after DOMPurify.sanitze
and DOMPurify.removed
holdes the removed elements during sanitization process. the emoji param has to be wrong to avoid overwriting DOMPurify.removed
.
We can get xss easily. But cookie has httponly flag, so we can't get flag.
In bff/app.py, proxy function has crlf injection vulnerability. Because it uses tcp raw socket, request smugling is possible.
So if we use CRLF injection + HTTP Request Splitting + Content-Length well, we can leak cookies using 400 error messages.
curl
accepts special syntaxes, {one,two,three}
for requesting multiple files at once. Thus, we can bypass the filter ..
and make path traversal like this {.}.
. In addition, when we request multiple files at once, output will be like following.
Now the only left thing is bypassing SECCON
filter.
When we look up templating function, there is a mistake that tmeplate key accepts a single character {
. Thus, we are able to think replace {
to }
, then SECCON{flag}
will be converted to SECCON}flag}
. Now, if we can write some strings contains {
in front of SECCON}flag}
using multiple requests, e.g. asdfasdf{asdzxv... SECCON}flag}
, we can change {asdzxcv... SECCON}
to other string using templating, which can bypass SECCON
filtering.
Also, curl
accepts url fragmentation for file scheme, we can use this to insert any arbitrary string.
which is same as
this will result in
SECCON{i_lik3_fe4ture_of_copy_aS_cur1_in_br0wser}
We are presented with three files: araiguma.DMP
a dump file containing a snapshot of a live run of the main executable araiguma.exe.bin
. And a PCAP file containing the communication between a server and the executable with the name network.pcap
.
I put the executable into IDA and started analyzing. The binary is rather small and is not stripped, thus it is easy to navigate. In the main a Diffie Hellman key is created with static G and P values. The public key is then exported and sent to "192.168.3.6" which answers with a public key of its own. Afterwards the received public key is used to derive a session key that is used for RC4 decryption. So we are looking at a DH handshake to create a shared secret.
Analyzing the binary and the pcap file, we see that a simple protocol is used. First a 4 byte value with the necessary buffer size is sent, and then the actual message follows. Furthermore we can see two messages being sent after the DH handshake which are of length 102 and 103 respectively. The flag is very likely being hidden in one of the two.
I implemented a server that could be used to communicate with the binary in C++. But it had one catch, i would print out the shared secret key, so i could search for it in the running binary (see snippet below). Note that the actual RC4 key is 0x10 bytes long and starts at offset 0xC in the exported struct.
With this server running on localhost i used a hex editor to change the ip "192.168.3.6" to "127.0.0.1" so it would connect to my local server. With all this prepared, i loaded araiguma_patched.exe
into WinDBG and put a breakpoint at the exact same offset as in the dump file: 0x401995. When breaking there, my server would display the following.
This enabled me to search the memory of the local araiguma_patched.exe
for this value and identify patterns that might be useful for searching them in the DMP file.
The latter seemed to be most promising.
There were some contents in the immediate proximity that could be kinda static. Take the "RUUU" or "KSSM" strings for example. I chose the "RUUU" one and added the 4 bytes before it aswell to my search pattern. And would you believe it, i got two hits in the provided DMP file! The latter looked exactly like the struct i saw in the local process and contained the secret shared key at 00163a6c
.
Now it was just a matter of decrypting the RC4. I used python for that.
The ciphertext was taken from the first of the two longer messages in the pcap file. I did not check what the second one contained.
The binary is old school style crackme written by rust.
In eguite::Crackme::onclick::hb69201652eb2ef3b
, there is the flag check routine.
First, this function checks the input starts with SECCON{
and ends with }
and length of input is 43.
And, it checks there are the letter -
at 19th
and 26th
, 33rd
index.
e.g.)
SECCON{aaaaaaaaaaaa-bbbbbb-cccccc-dddddddd}
Next, it decode each parts as big-endian hex string.
Lastly, it checks parts by sum of some parts and xor result of some parts.
We got the flag using z3 solver.
We can see the flag.cbc's IR by clamcb ./flag.cbc --printbcir
. Note that I'll not post the output of this.
F.1 bb.3
checks whether flag.txt end's with "}".
Important part is F.1 bb.5
which transform our input with function F.2
and F.1 bb.6
which compare between transformed input and constant.
So, implementing reverse of F.2
is the solution.
For PQPQ, insufficient, BBB, and witch's symmetric exam, check
We are given, with ,
It can be easily shown that and .
With this, we can calculate . Now with and , we can compute .
To compute , we divide the equation into three, (each with mod ) solve each one, then combine with CRT. This gives us all candidates for the flag.
We are given 4 data with a 512 bit prime such that
where each are all fixed unknowns in and is in .
We rewrite this as
and use lattice methods to solve for .
Now we can find all .
Since we simply know .
Since is a divisor of , GCD can be used to find .
Since , we can simply take .
There can be more possible candidates for , but we didn't have to deal with it.
The idea is to make , which gives us what to send.
Then, we can solve for such that , then solve for such that , then , and so on. This is continued until we have found 5 such values, which works with a decent portion of the prime numbers. Essentially we are just solving for or something like that.
These seeds will give us datasets with , so solving for via CRT works.
This can be easily seen by computing the bounds for and .
In textbook RSA, when ciphertext is given, ciphertext for can be easily calculated without knowing .
When we send , we can check whether or not.
Once we find appropriate satisfies 2^{1022} - 2^{1024} \leq flag \cdot a$, then set as lower bound and possible to recover maximum such that using binary search.
First, note that OFB cipher is practically a stream cipher. Therefore, combined with a padding oracle attack gives us an ECB encryption oracle. Indeed, sending for an OFB decryption gives error at OFB side when is not padded appropriately. In conclusion, we have an ECB encryption oracle.
Since OFB's decryption is same as encryption, this also means that we have an OFB decryption oracle as well. We have OFB encryption/decryption at hand.
Also, note that AES-GCM is also a stream cipher at heart. If we look into AES-GCM's internals, it's easy to see that having an ECB encryption oracle is enough to both encrypt/decrypt (alongside the calculation of tag) so the challenge is solved.
It is well-known that python random module is not cryptophically secure. All we need is to find a integer seed which generates 666 target values.
I first tried to analyze the exact logic for the random module in python but it is too boring. Luckily I find this repository and it contains almost everything I want.
Since the whole code is too long, I will introduce a handmade method in Breaker class.
I find a candidate mersenne state using state_recovery_rand_partial
method then find a corresponding seed.
We send for . In that case, the decimal part of the offsetX, offsetY will be [flag hex] / 16
. We'll find this value to solve the chall.
To do so, we will brute force all 16 possibilities and see if the colors make sense.
In each possibility, we can take a 20 x 20 grid of the picture that is decided by four gradient values. This is equivalent to [flag hex] / 16 + i / 20
having the same integer part for 20 consecutive . We will brute force all possibilities for the four (2D) gradients. Then, since we already know the decimal part of each grid (as we already fixed the value for the flag hex) we can compute the color of it and see if it matches the picture returned from the server. If there one of the candidates for the gradients work, then the flag hex value we guessed is the correct one.
Linux command file
is abused with arbitrary parameter values to provoke time-based inference of the content from the other end. In our case, we used the crafted magic file, read through the /dev/stdin
, where we chained the non-delayed match (based on current string match) along with the delayed one (regex DoS alike).
we are given following code
Since the code does not check for valueError (i.e sending \x00) or exit syscall (control+d) we can just run the program , hit control+d and it will print the flag since the the condition if check
here check will point to function check .