> For the complete documentation index, see [llms.txt](https://arne-ctf.gitbook.io/ctf/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://arne-ctf.gitbook.io/ctf/2025/san-diego-ctf/misc-triglot.md).

# Misc - Triglot

## Description

<div align="left"><figure><img src="/files/8SssBwx4zmReg6aHO2BD" alt=""><figcaption></figcaption></figure></div>

## Downloads

{% file src="/files/zvh5LbRQCH87idOMETPz" %}

## Solution

This is a tough one with very little solves but I still attempted it because I did a similar challenge in HTB last year [here](/ctf/2024/htb-cyber-apocalypse/misc-multidigilingual.md). I thought I could breeze past this real quick but it turned out to be more challenging than I thought.&#x20;

The challenge is straight forward - write a **Perl-Python-JavaScript** file-read polyglot. Firstly, let's write the file-read code for each language:

#### Python

```python
print(open('flag.txt').read())
```

#### Perl

```perl
open(my $file, 'flag.txt');print(<$file>);
```

#### JavaScript

```javascript
console.log(require('fs').readFileSync('flag.txt','utf8'))
```

Combining **Perl+Python:**

```perl
q="""=;open(my $file, 'flag.txt');print(<$file>);#""";print(open('flag.txt').read())
```

This is simple, put the python code behind the '#' symbol and it will be treated as a comment by Perl. Similarly in python, the Perl code is treated as comment when put between the triple double quotes. Here's the hard part - that is invalid JavaScript.

<figure><img src="/files/1CpaFi8sa8BxKAqr715r" alt=""><figcaption><p>Node error</p></figcaption></figure>

Anyway, I modified the validation script slightly such that it prints the individual interpreter's output:

```bash
#!/usr/bin/env bash
set -eo pipefail

wrong() {
  printf "EXTREMELY LOUD INCORRECT BUZZER!!!\n"
}
trap wrong ERR

code=$(cat)

printf '%s' "$code" | perl -c
printf '%s' "$code" | python3 -c 'import sys,ast; ast.parse(sys.stdin.read())'
printf '%s' "$code" | node -e "const fs=require('fs'), src=fs.readFileSync(0,'utf8'); require('vm').createScript(src)"

perl_out=$(printf '%s' "$code" | perl -)
py_out=$(printf '%s' "$code" | python3 -)
js_out=$(printf '%s' "$code" | node -)

printf 'Perl output:\n%s\n\n' "$perl_out"
printf 'Python output\n%s\n\n' "$py_out"
printf 'JS output\n%s\n\n' "$js_out"

if [[ "$perl_out" == "$py_out" && "$perl_out" == "$js_out" ]]; then
  printf "Your triglot compiles!! Here's your output:\n"
  printf '%s\n' "$py_out"
else
  exit 1
fi
```

I spent a good maybe 5 hours going nowhere until I found this post, <https://codegolf.stackexchange.com/questions/209420/inspired-by-hq9-4-behavior-polyglot/209521#209521>.

My final script is:

```javascript
0//1;q=0;print(open('flag.txt').read());'''=;open(my $file, 'flag.txt');print(<$file>);q[
for(x=1,z=(a='')=>a;x;)console.log(require('fs').readFileSync('flag.txt','utf8')+(x--,z()))//]#'''
```

As you can see from the syntax highlighting, it mostly made use of **'//'** in JavaScript to comment most of the other code out. Other thing worth mentioning is the odd **for** loop. To be honest, I still don't quite understand how this loop works. There are only 2 expressions (notice there's only 2 semicolons) and I'd expect the 2nd expression to be a condition in a typical loop but it's not. The decrement is also done in the function itself rather than the '**for'** statement. If anyone could explain to me how this works do reach out to me :)

<div align="left"><figure><img src="/files/o1JZhNB34MxtCFLQuRzy" alt=""><figcaption></figcaption></figure></div>
