On your never ending search for flags you stumle into a deep swamp. Suddenly, in front of you, you find a weird little green stanger standing. “I am wondering, why are you here”, the creature asks you. “I am looking flags” you answer. “Looking for flags? Found something else, you have, I would say, hmmm?” “Look, I’m really sorry but I need to get back to solving challenges or I’ll never get my full solve”, you say as you try to push the creature out of your way. “No! No, no! Stay and help you, I will. Find your banner, hmm?”, the creature says and won’t get out of your way. “I’m not looking for a banner, I’m looking for a flag!” you dement. “Oohhh, Flag. Challenge. Solve. You need to solve a challenge”. “Do you have a flag?” “A flag? Perhaps… Hmmm, give you a challenge, I can. Solve it you must” and with that the little creature scurries away and returns after a while with a mysterious little box.

“A communication device, this is. Send me a message you must”. You take a closer look at the box. It has a screen that reads

println("MESSAGE PLACEHOLDER, PLEASE REPLACE")

println("MESSAGE TOKEN: [RANDOM]")

and a keyboard below the screen. “Only append code, you can, yes? Replace the placeholder with your message, you must. But not touch the token or add any lines, you may, hmmm?”, as the seemingly intellijent creature explains the rules to you, it scratches its head, “Hope, an Idea you have, I do”. “Well, not immediately, but I will certainly give it a try!”, you answer, still slightly confused. “No! Try not. Solve. Or solve not. There is no try.”, the creature admonishes you.

Category: rev

Solver: jogius, lukasrad02

Flag: GPNCTF{Well,_you_have_done._Solved_this_challenge_it_appears_you_have}

This challenge has a pretty long description, so I encourage you to read through it - there are a lot of hints hidden in it! The words intellij and Idea are written in cursive, which indicates this has something to do with JetBrains or Java. When combining that with scratches, which is another cursive word in the description, we can find a page on Scratch Files, which are described as

… fully functional, runnable, and debuggable files that support syntax highlighting, code completion, and all other features for the corresponding file type.

Now that we have an idea what this challenge could be based on, let’s connect to our instance and see what happens. The first thing we see is the following prompt: Please enter the continuation of the code below followed by '----' on a new line. After a bit of playing around (entering invalid code throws an error on the file myKotlin.kts) we find that, if we enter valid Kotlin code, it gets executed and the output is returned to us in the following manner

Please enter the continuation of the code below followed by '----' on a new line
println("This is valid Kotlin")
----
Compiling and executing your code now
Not a valid solution. Your output:
Line 0:
MESSAGE PLACEHOLDER, PLEASE REPLACE
  
Line 2:
MESSAGE TOKEN: 94a779c8-dd7e-4ba4-a82f-0dfae1667c90
  
Line 3:
This is valid Kotlin
  
The your output doesn't match the required form
You did not replace the placeholder

However, it seems we are quite limited in what we can do. Trying to open a file with java.io.File("myKotlin.kts") throws the error Exception in thread "main" java.lang.Exception: java.io.File is a Java type. If I want to do Java, have a look at Terminator - and this is error is thrown for all Java types we have tried to use. Things like reflection or c-interop that could be helpful are only accessible via Java classes. At this point, we move to using a local installation of Intellij and Kotlin Scratch Files - even though it’s not quite the same environment, at least we get proper error messages. And it doesn’t shut down every four minutes.

So, what is Kotlin even able to do on its own, without using any Java interop? Turns out it’s not completely useless: we are able to define functions! More importantly, we are able to define a function called println(s: String), which takes precedence over the default implementation in kotlin.io. This is a huge step forward - we can actually modify the output of the first lines!

Please enter the continuation of the code below followed by '----' on a new line
fun println(string: String) {
    if (string.startsWith("MESSAGE TOKEN")) {
        kotlin.io.println(string)
    } else {
        kotlin.io.println("")
    }
}
----
Compiling and executing your code now
Not a valid solution. Your output:
Line 0:


Line 2:
MESSAGE TOKEN: 137292dc-f251-46a5-a39d-5b8b205ab534

Line 3:

fun println(string: String): Unit
The your output doesn't match the required form

Still no flag though … it’s not happy with our output. Let’s go back to the challenge description and what Yod- no, “a weird little green stranger” told us.

“Only append code, you can, yes? Replace the placeholder with your message, you must. But not touch the token or add any lines, you may, hmmm?”

We’ve successfully replaced the placeholder, and the token is being printed just as expected, but there is a third line in our output. When using our local installation of IntelliJ, we can see that the Scratchpad feature prints some function footprint on the corresponding line.

img.png

Luckily, Kotlin is also able to exit the process without (directly) calling any Java methods. So we try executing this code snipped in a local scratch file:

println("MESSAGE PLACEHOLDER, PLEASE REPLACE")

println("MESSAGE TOKEN: [RANDOM]")

kotlin.system.exitProcess(0);
fun println(string: String) {
    if (string.startsWith("MESSAGE TOKEN")) {
        kotlin.io.println(string)
    } else {
        kotlin.io.println("")
    }
}

All we get is this line of text: 'Nothing' return type needs to be specified explicitly. No information on where or how this error occurred, just the message. What does end up working is wrapping the exitProcess call inside another function. Our final interaction looked like this

Please enter the continuation of the code below followed by '----' on a new line
exit()
fun println(string: String) {
    if (string.startsWith("MESSAGE TOKEN")) {
        kotlin.io.println(string)
    } else {
        kotlin.io.println("")
    }
}

fun exit() {
    kotlin.system.exitProcess(0)
}
----
Compiling and executing your code now
GPNCTF{Well,_you_have_done._Solved_this_challenge_it_appears_you_have}

which successfully removed what the function declaration evaluated to before

img.png