kh→@|;@+open(*"ww").write(VAR_)#
Vyxal can't really do anything with external files, which would normally render this challenge impossible. However, in Vyxal 2.5.3 and prior, there was an ACE exploit allowing for arbitrary Python execution. Yep, I found another one.
The ACE:
Vyxal is a transpiled language, so every Vyxal command is translated to some Python code, and then all of the translated commands are executed. Previously, I found that you could escape a string to insert any Python commands you wanted into the transpiled code. It turns out that you can do something similar with function names.
When defining a function in Vyxal, the resulting python looks something like this:
def FN_func(parameter_stack, arity=None):
...setup stuff...
...commands...
...finishing stuff...
return stack
When calling a function in Vyxal, the resulting Python code looks something like this:
stack += FN_func(stack)
The thing is, when parsing the name of a function, the strategy was to just read characters until reaching a :
, |
, or ;
, which are the delimiters of different parts of the function declaration/call. This meant that you could put any characters you wanted into the name, and it would attempt to transpile it the same way.
In this case, I used a +
in the function name when I called it. That results in this transpiled code:
stack += FN_+open(*"ww").write(VAR_)#(stack)
This code will error when ran, because it tries to add together a function and the None that is returned from the open
command. However, even though it errors, the open
command still runs, meaning that we have executed arbitrary Python. If you wanted to write longer sections of Python code, you could replace the +
with ([])
and add a newline after it.
The program:
In this program, the payload (the arbitrary Python code) is the following:
open(*"ww").write(VAR_)
The basis of this code is the open().write()
command, which creates a file named w
if it doesn't exist, then writes the contents of VAR_
to it.
The VAR_
variable is set at the beginning of the Vyxal program with kh→
. This pushes the builtin Hello World
and saves it to the nameless variable. All variable names are prepended with VAR_
internally, so the variable VAR_
is created and contains Hello World
, which is written to the newly created file. Even though this has the overhead of the ACE setup, it ends up being shorter than the Python solutions due to the builtin.
This ACE has not been fixed in the repo, but it had a patch applied server-side for the online interpreter. It was also fixed in the rewrite and subsequent 2.6 release. If you want to try out this program for yourself, you can download the 2.5.3 version here.