links:
simple_attack
F***:
THEY DIDN'T WORK AT ALL!!
*append: THE ONLY WORKING WAY is that repack the 103223779_p0.jpg
with bandizip, even failed by specifying src.zip
.
Greeting
123456
as passphrase.Hill
I **BRUTEFORE the cipher with ChatGPT:
ezPYC
ezUPX
We can use IDA as a debugger to find the restored entry point by tracing the stack changes. After that, we will be able to analyze it in-place to figure out the flag.
Set a HW breakpoint at the stack:
Continue running until suspicious function prologue show up after HW breakpoint interrupted:
(Interrupts at here. After reanalyzing (Options - Gerneral - Analysis - Reanalyze program
) we can clearly see a standard prologue, which differ from UPX unpacking routine a lot.)
Also there is a pop up warning that RIP
has jumped to somewhere not defined as code, which indicates that the execution flow has migrated from unpacking codes to the main procedure.
Toggle decompile from here we'll be able to find the main function call:
The main function is simple, a single byte XOR loop:
Then the flag can be retrieved with IDAPython:
Elden Random
The buffer storing the first read() will overflow by 8 bytes, which overrides the seed
local variable.
By reproducing overflow with constant value, the rand() results will be deterministic. We can generate a sequence by taking advantage of Compiler Explorer.
Once reaching the final myread()
function, remaining steps could have been totally automatic (refer to this trick previously discussed), as long as a working leak
method is provided.
A fun thing is that the iterator i
is a static variable, so it's unnecessary to resend the rand() sequence
as shown above, since i
stay the same after re-execution from _start
.
And the final payload is structured exactly the same to what has been shown in the reference link:
Elden Ring I
seccomp
calls:
So, the purpose of these calls is to restrict the process from making execve and execveat system calls. If the process tries to make either of these calls, it will be killed. This could be part of a security measure to prevent the process from executing other programs.
As the explaination says the execve
syscall is forbidden. We have to construct an open - read - write
chain to read flag from remote filesystem. Since the read()
and puts()
(which acts as the writer function) have been imported, the only trouble that need to get over is to program an open()
call, requiring its entry address to be leaked.
Back to the vulnerable, since the first overflow only provid 48 bytes of space, it's necessary to perform a stack-pivot, where the actual cat
payload will be hold.
Luckily, this function provides an all-in-one gadget, which let us put the cat
payload as well as migrate the stack at once:
The available stack address can be retrieved by DynELF.stack()
:
Then perform a read() call to read the cat
payload into the chosen address:
ezfmt
fmtstr
problems usually requires a read-write loop so that you leak out the essential address, then write something back to a calculated address to hijack the routine. Another common way is to overide the offsets stored in .got
, then call the modified dynamic-resolved function to jump to arbitary address/procedures.
But in this challenge, both of the techniques mentioned above failed.
As the disassembly shows there is nothing more than a trivial return from after the vulnerable printf
:
Since the target vulnerable has embeded a backdoor function sys
, we have to catch the only chance and control the execution flow returning to sys
.
My first idea was to hijack the stack checker, which was soon proven impossible, since the stack never overflows:
Next I turned to the finish hook .fini_array
, which has a static address, and it seems to be writable:
However it's just an illusion. When loaded into memory, it turned to be immutable, locked by ld
:
So the only key left to us remained the rbp
chain.
xBP
chain in Format String challengesWe know the %n
specifier requires an address of a variable. printf("%n",&v)
writes the number of printed characters into v
. So the behavior on the given value to %n
will be:
addr
, the number will be written to addr
;addr
, in which case we notice that:
%n
, e.g. the return address of current subprocedure, there must be a cross-reference(xref) to the address of the target value, inside the stack area, which can be discovered by searching the memory.printf
specifiers are able to refer to the string itself, we can write arbitary address by giving the address within the format string.Now take a look at *bp
(i.e. rbp
/64, ebp
/32).
bp
is saved to the stack whenever diving into the next call, and each bp
of the stack frame
is chained, pointing to its caller's.bp
. When the current subprocedure ends, the epilogue will do some job equivalent to mov bp => sp; pop bp;
Consider the two points, we found that the bp
chain perfectly meet the requirement of the stack layout towards the format string exploit. If we manage to get the %n
referencing to the bp
of current stack frame, it is possible to change the saved bp
of its caller, which is taken as new bp
value when the caller returns, and finally redirect the sp
and *ip
when the caller of caller returns.
In a word: If %n
references to a stack frame of a function, we take control when the caller of caller of that function returns.
However in this challenge, the caller of vulnerable function is main()
. The caller of main()
never returns, the process end up with calling exit()
directly.
bp
chains rather than the
current?
rbp
:
.
Wow! There it is! It lands on the %18$
position, just take it as the payload!bp
value saved in current frame, so it takes effect when the main()
is returning. We want the forged bp
to point to the tail of the payload, so that the returning address is completely specified by us.bp
is quite near to original legal bp
address, only the lowest byte is needed as the %n
argument. To struggle against randomized address, we need some luck to get the payload working. I end up with this:
sp
must be aligned to 16 bytes before calling system()
, so the payload set the sp
to 0xxxxx78
. Inside sys()
there is another push
adjusting the stack to be aligned.… or, is it?
If you can't find any clue in this challenge, you might be suffering this:
Huh?! There isn't any available rbp chain at all!!!
After research around, I notice that the solution relies on a very specific condition. If you are interested, pleas refer to this post for more details.
ezshellcode
Courses
Bypass It
Seems nothing responded:
What about fetch it manually?
It actually did return a page, in which we can see the form to be posted with in registeration.
Follow the form to make registeration request:
Then login will be available, after that the flag is presented.
32768
Mute out debugger breakpoints:
_debugger
(e.g. function _debugger(){}) to make the statement meaningful.Examine the obfuscated code, it shows that the string literals and identifier/names are likely to be plain text. So we can directly search the keywords such as game over
, which leads us to this function:
Think about the game procedure, the "game over" message must follow up with stepping actions. So here the breakpoint should take us into a judement deciding whether we have won the game, where were likely to let us capture the flag.
Play the game, we found that the breakpoint is imediately taken. Check the call stack, where we can find some suspicious judgements:
Also we can see some data structure very likely to be for holding number blocks.
Break here and modify the cells to generate 2 16384
block, merge them into 32768
, then the flag will be presented.
jhat
nashorn
manual and learn to use the Java Interface from inside the script.PRNG
ezMath
Pell's Equation
section.ezRSA
d = gmpy2.invert(e,(leak1-1)*(leak2-1))
Pictures
Key Image
wipes out the solid glyph and Xor
-ed into every image.1.
2.
we can conclude that:
Xor
between any 2 images will erase the background since their original background and Key
is totally the same. (clue 1)3.
and clue 1
we can conclude that:
Xor
-ed from A
and B
, and the image shows only one glyph, it indicates that A
and B
are generated one by another. (clue 2)4.
and clue 2
we can conclude that:
A
and B
is linked to each other, we get the image generation order, which indicates the letter order of flag.To operate with image and pixiel caculation, always remember of the old friend numpy
:
Next we generate all Xor
combinations to find the images containing one glyph:
I strongly recommand that put all the chosen image into an image editor. Some images may be very similar, and you definitely need to overlap them together to make sure you catch different pieces.
Rename the layers so that we know both the content and the source numbers
, which is very helpful while adjusting the order.
We know the flag starts from hgame{
and end with}
, so let it be.
And the remaining order should be able to reveal.