Tags: programming polyglot
Rating:
Description
solve cats first
http://cats.2018.teamrois.cn:1337
Solution
Using the hint from the solution to cats
, we need another list of 15 commands, but they must include at least 4 of python3
, bash
, php
, node
, ruby
.
Script interpreters like these are generally happy to just do nothing when given an empty input file, but our food
file must be at least 2 bytes in size! This immediately meant one thing: polyglot quine, or polyquine for short.
A "polyglot" in a programming context is a piece of code that is valid (and preferably does the same thing) in multiple languages. A lot of simple Python scripts are technically polyglots, since they work in both Python 2 and Python 3. The less similar the syntax of two languages is, the more difficult it is to make a polyglot with them, naturally.
And a "quine" in a programming context is a program which produces its own source code when executed. Generally, if this is accomplished by actually opening and reading the source file the program is considered a "cheating quine", since a lot of the difficulty of this problem is in crafting a string which somehow expands into the full program when formatted in a particular way. Fortunately, there is no restriction in this challenge, and a cheating quine is completely fine.
At first I looked online for similar challenges, and this answer seemed the closest to what I needed. Unfortunately, perl
was not on the list of possible languages, and the challenge asked for Python 3, not Python 2. I spent some time trying to adapt this to work better, but I could only ever make it work for 3 languages at a time.
Then I decided to write my own polyquine, and solve the challenge the hard way. There was no particular method to my development, just writing some code and seeing which interpreter complains about the changes and why, then fixing it and so on. Of the 5 languages I chose python3
, bash
, php
, and node
, since I knew their syntax well enough. ruby
not so much.
The script I came up with during the CTF was:
a=0;food=1;exit=0;cat=2;echo=3;x=5;int=6
cat <food
echo
exit <food
int; 1//5 # <?php die(substr(file_get_contents("food"),79)."\n"); ?>
int; 2//5 or __import__("sys").stdout.write(open("food").read() + "\n") and quit() and """
x ;console.log(require("fs").readFileSync("food", "utf8"));
x//"""
I made no effort to clean it up (mostly a waste of time if it works), but for this write-up I will describe a smaller version. The core functionality is the same.
a=0;cat=0;echo=0;exit=0;food=0;i=0
cat<food
echo;exit
i//1#<?die(substr(file_get_contents("food"),59)."\n");?>
i//2;print(open("food").read());quit();"""
x =0;console.log(require("fs").readFileSync("food","utf8"))
x//"""
Some things could still be removed, but I kept them to make sure sort
prints the file out as-is, i.e. the lines need to be sorted already. Let's see how each language interprets this code.
PHP is the simplest to understand. By default, PHP just copies file contents to standard output. Any actual scripting capability is possible only in PHP mode, which is entered when a <?php
tag is encountered, or the short version <?
. So PHP first prints out everything from a=0;cat= ...
all the way until i//1#
. Then it executes this code:
die(substr(file_get_contents("food"),59)."\n");
file_get_contents("food")
returns the entire food
file contents as a string. substr(..., 59)
removes the first 59 characters (to account for the first part of the file that has already been printed). A "\n"
newline is added for consistency with cat
and the other interpreters. die(...)
outputs the string to stdout and stops execution.
a=0
is a variable assignment in Bash. Multiple statements can be combined into one line by joining them with a ;
semicolon. cat<food
redirects the file food
into cat
, which then outputs it. echo
puts an extra newline and exit
stops execution. After exit
, the lines no longer have to make sense to Bash, since it interprets the file line by line.
JS is unhappy about statements using variables that haven't been declared yet, e.g. a + b
can throw an error if either a
or b
are not variables. Usually, variables are declared as var a = "value";
, i.e. using the var
keyword (or let
or const
in more modern JS). However, an assignment without the var
keyboard is still valid, but it creates a global variable (in the global window
object). So the first line is just creating a bunch of variables. Statements in JS can be terminated with a semicolon, but the semicolon can usually be omitted at the end of the line. This hurts my eyes but here it is convenient for a smaller file.
cat<food
is a less-than comparison to JS. echo
and exit
use the previously declared variables, but the statements don't actually do anything.
The i//1...
and i//2...
lines are also just using the i
variable. Everything after //
is ignored as a comment. Same for the last line x//"""
.
So the most important statement is console.log(require("fs").readFileSync("food","utf8"));
, which requires / imports the fs
API from NodeJS standard libary, then calls its readFileSync
function, which synchronously reads the file food
and decodes it as a UTF-8 string. Finally, console.log(...)
outputs this string to stdout (along with a trailing newline).
The first three lines are interpreted similarly to JS. Some variables are declared and values are assigned to them, then some no-op expressions are evaluated.
But, i//1
in Python means integer division of i
by 1
. The rest of line 4 is ignored, because #
starts a line comment.
print(open("food").read())
does the actual source code output (and a trailing newline). quit()
then stops execution. Finally """
starts a multiline string, which carries on till the end of the file, so the last two lines are not considered code and hence don't have to make sense to Python.
And with that, I fulfilled the requirement of using 4 out of the 5 specified languages. I considered adding ruby
, but again, I don't know much about its syntax so I made due with what I had. The 11 other commands I used were:
sh
, dash
, rbash
- other Bash-like shells which have some differences but interpret this script the same wayhead
, tail
, uniq
, more
, paste
- same as in cats
zmore
- views compressed files directly on terminal, but also shows uncompressed files verbatimsort
- this is why I made sure the lines of code are sorted alreadypython3m
- equivalent to python3 --with-pymalloc
which does not affect Python's functionality.And with that:
Wew, you've found 15 cats! Here is your flag: RCTF{you_love_cats_dont_you}. You are so lihai! RCTF{did_you_make_a_polyglot}
I did indeed.
Active Directory Domain developed by microsoft,this is a directly service,you can easily to solve this issue,just one a single click here this visit <a href="https://fixforwindows.com/directory">Active Directory Domain Services Unavailable</a> sometimes users try the different option and ways to find solve this problem.