After smashing my head for hours over the polyglot chall at the defcon qualifiers this year, this was the challenge I had to solve. Besides that, PoC||GTFO 0x5 was released a few days ago, which happens to be a very cool pdf/swf/zip polyglot - check it out.

Enough pretalk, lets get to the beef. The challenge was it to create a program which cats the flag. So far, so easy, but the interesting part is that it has to run/compile in 5 different languages: Python2.7, Python3, Ruby, C and haskell.

It is not hard to write a program which does this for every single of this languages, the hard part is to combine it into one file without syntax errors. Since Haskell has by far the strongest rules, it makes sense to start the program with haskell. It took a while before I discovered that I can cat the flag in haskell even without importing additional functions, the solution here is the readFile function, which is loaded by the haskell prelude.

The first line of the polyglot “a = {-” does nothing else besides creating a haskell function named a and opening a comment tag.

The second line just opens a code area, which gets ignored by the c preprocessor, so we are free to do there whatever we want. “Whatever we want” is in this case to complement the  “a= {-"-code to be valid in both ruby and python. In py, this statement creates a dictionary a, while in ruby a hash is created.  Line 3 does the required magic and nurfed helped to come up with this.

The rest of the polyglot is rather self exemplatory. The only additional interesting point is the ending clause, which happens  via a “#define” and is therefore, for both Ruby and Py already a comment. Here is finally the polyglot code:

a = {-
#ifdef trasha
#1};
0+""" ".to_i + 1  => """.isdigit()}#"}
""" "
=begin
#endif 

1};
int main(){
system("cat flag");
}

#ifdef B
-} putStrLn "AAAA"
main = do
s <- readFile "flag"
putStr s
{-
"""
import os

os.system("cat flag");
"""
=end 

system("cat flag")
" """ 
#endif
#define s 'abcd'-}

Last, but not least, I also provide the abstract structure of the polyglot for better understanding:

  1. HS/RUBY/PY/C
  2. HS-COMMENT_BEGIN
  3. C-IGNORE
  4. MAGIC_RUBY/PY
  5. PYCOMMENT_BEGIN
  6. RUBYCOMMENT_BEGIN
  7. CIGNORE_END
  8. CPAYLOAD
  9. CIGNORE_BEGIN
  10. HSCOMMENT_END
  11. HSPAYLOAD
  12. HSCOMMEND_END
  13. PYCOMMENT_END
  14. PYPAYLOAD
  15. PYCOMMENT_BEGIN
  16. RUBYCOMMENT_END
  17. RUBYPAYLOAD
  18. PYTHON_UNCOMMENT
  19. CIGNORE_END
  20. ENDING_CLAUSE

Cheers,

nsr