63
\$\begingroup\$

Inspired by this comment...

Thanks to users Step Hen, Wheat-Wizard, and Dennis for helping my solidify the specification of this challenge before posting it!

This is the Cops' thread. For the Robbers' thread, go here


In this challenge, you are tasked with running some code that makes it so that your language no longer satisfies our criteria of being a programming language. In that challenge, that means making it so that the language can no longer...

  • Take numerical input and output

  • Add two numbers together

  • Test if a certain number is a prime or not.

This is a challenge, where there are two different challenges with two different objectives: the Cops will try to write some code that makes the language mostly unusable, and the robbers will try to find the hidden workaround that allows the cops to recover their language.

As a cop, you must write two snippets of code:

  1. One that makes your language mostly unusable, e.g. by removing built-in functions for taking input/output and numerical operations. The more features you remove, the better. This code is not allowed to crash or exit. It should be possible to add code to the end of this snippet, and that code will get evaluated. And...

  2. ...a snippet of code that takes two non-negative integers as input, adds them together, and outputs their sum. This snippet must still correctly function even after running the first snippet. When the two snippets are combined together, they must form a full program that adds two numbers, or define a function that adds two numbers. Ideally, this snippet should rely upon very obscure behavior, so as to be more difficult to find.

You may choose any standard method of input and output. However, you must reveal exactly which format (input and output) you are using. A robber cannot crack your answer unless they use the same format as you.

After writing both of these snippets, you must post the first one as an answer, without revealing the second one. Your answer should contain all of the following information:

  • The first snippet (obviously not the second).

  • Language (including minor version, since most submissions will probably rely on strange edge-cases)

  • IO format, including whether it's a function or full program. Robbers must use the same format for their crack to be valid.

  • Any strange edge cases required for your answer to work. For example, only runs on linux, or requires an Internet connection. Obviously, this is slightly subjective, but if a cop has some extreme edge case that prevents it from being cracked, and then only reveals this after being safe, I consider this poor sportsmanship. A potential robber should have all information necessary to crack your answer before it is cracked.

You do not need to reveal your byte count until your answer is safe.

Here's an example. For the first snippet, you could submit the following Python 3 program:

Python 3

print=None

Takes input from STDIN and output to STDOUT

And then as your second snippet, you could write:

import sys
a,b=int(input()),int(input())
sys.stdout.write(a+b)

This is valid because it will take two numbers as input, and output their sum even if you join the two snippets together, e.g.

print=None
import sys
a,b=int(input()),int(input())
sys.stdout.write(a+b)

However, this will be extremely easy for a robber to find a solution to. Since this would be very easy to crack, you could attempt to patch this particular approach like so:

import sys
sys.stdout=None
print=None

However, even this has a very easy workaround:

del print
a,b=int(input()),int(input())
print(a+b)

As a cop, your goal is to make the hidden workaround as obscure as possible, to prevent the robbers from finding it.

The robbers will look at one of your answers, and attempt to crack it. They may crack it by writing any valid snippet that could work as snippet 2 (adding two numbers together after the language is made mostly unusable). This does not have to be the same snippet as you originally intended. If a robber cracks your answer, they will leave a comment on your answer, and then you should edit it to indicate that it has been cracked. If your post is cracked, you should edit your answer to show the solution (snippet 2) that you originally intended. This isn't a rule per se, just a friendly suggestion to keep the game fun. You do not have to.

If an answer remains uncracked for one whole week, you can edit in your second snippet, and indicate that your answer is now safe. If you do not edit it after the week is up, other users can still crack it until you do. If you do not reveal your second snippet, you cannot claim points for your answer, or call it safe.

The winner of the cops' thread is the shortest safe answer including both snippets, counted in bytes, and this answer will be accepted after sufficient time has passed. You do not need to reveal your byte count until your answer is safe, since byte count is irrelevant to your score until your answer is safe. In the event that sufficient time has passed and no answers remain uncracked, the winner will be the answer that remained uncracked for the longest period of time.

Have fun!

Rule clarifications

  • The first snippet must run correctly without taking any input. It may output whatever you like, and this output will be ignored - as long as after the snippet is done, the second snippet runs correctly.

  • The second snippet must actually be executed for your answer to be valid. This means an answer like

    import sys
    sys.exit()
    

    is not valid because it doesn't break the language. It simply quits. Similarly, entering an infinite loop is not valid, since the second snippet will never be executed.

  • After being safe, your score is the byte count of both snippets.

  • This goes back to Please reveal any strange edge cases required for your answer to work... Your submission must contain enough information before being revealed to be reproducible after being revealed. This means that if your answer becomes safe, and then you edit in: Here's my answer. Oh ya, BTW this only works if you run it on Solaris, joke's on you! your answer is invalid and will be deleted and not considered eligible for winning.

  • The second snippet is allowed to crash after outputting the sum - as long as the output is still correct (for example, if you choose to output to STDERR, and then you get a bunch of crash information, this is invalid).

  • You may not edit your code after submitting an answer.

  • You may not rely on cryptographic functions like encryption, hash functions, CSPRNGs etc.

Snippet to find uncracked submissions:

<script>site='meta.codegolf';postID=5686;isAnswer=false;QUESTION_ID=133174;</script><script src='//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js'></script><script>jQuery(function(){var u='//api.stackexchange.com/2.2/';if(isAnswer)u+='answers/'+postID+'?order=asc&sort=creation&site='+site+'&filter=!GeEyUcJFJeRCD';else u+='questions/'+postID+'?order=asc&sort=creation&site='+site+'&filter=!GeEyUcJFJO6t)';jQuery.get(u,function(b){function d(s){return jQuery('<textarea>').html(s).text()};function r(l){return new RegExp('<pre class="snippet-code-'+l+'\\b[^>]*><code>([\\s\\S]*?)</code></pre>')};b=b.items[0].body;var j=r('js').exec(b),c=r('css').exec(b),h=r('html').exec(b);if(c!==null)jQuery('head').append(jQuery('<style>').text(d(c[1])));if (h!==null)jQuery('body').append(d(h[1]));if(j!==null)jQuery('body').append(jQuery('<script>').text(d(j[1])))})})</script>

\$\endgroup\$
11
  • 3
    \$\begingroup\$ What should be done for languages like C? Concatenation only allows for one "main snippet", and any logic is going to have to go there. E.g., if I have int main(){ do_evil_stuff(); } where should the users code go? In a function? After all the statements in main? \$\endgroup\$ Jul 19, 2017 at 0:34
  • 1
    \$\begingroup\$ Can the second snippet be placed anywhere in the first snippet? \$\endgroup\$ Jul 19, 2017 at 2:51
  • 1
    \$\begingroup\$ I know nothing about coding, but this challenge looks amazing, \$\endgroup\$ Jul 19, 2017 at 14:04
  • 2
    \$\begingroup\$ I edited in jimmy23013's awesome snippet. Feel free to revert, but I was using it myself anyway to find submissions and thought it might help others. \$\endgroup\$ Jul 20, 2017 at 18:13
  • 2
    \$\begingroup\$ @DomHastings That's extremely helpful! Thank you very much :) \$\endgroup\$
    – DJMcMayhem
    Jul 20, 2017 at 18:14

46 Answers 46

1
2
1
\$\begingroup\$

Vim (Cracked by Bruce Forte)

This answer is patched here

:for i in split('Qq@:=+','\zs')
exe 'map '.i.' <nop>'
exe 'map! '.i.' <nop>'
endfo

Try it online!

This actually has a fairly easy solution. I'm just trying to get the ball rolling with some vim obfuscation. Depending on how quickly this is cracked, I'll crank up the difficulty later >:D

Input is to the buffer like this:

3
4

And output is to the buffer.

What's evil about it?

This makes it so that the following characters cannot be used:

Qq@:=+

Disabling Q and : prevents you from running ex commands. Disabling q prevents a workaround for q: entering ex mode, and removes your ability to create/run macros. Disabling @ prevents you from deleting text, and running that as a macro (the shortest way to add two numbers). And lastly, removing = and + makes it so you can't use the evaluation register.

For reference, my solution is 23 keystrokes long. Have fun cracking!

\$\endgroup\$
4
  • \$\begingroup\$ ^Zread a;read b; echo $((a+b)) \$\endgroup\$
    – Joshua
    Jul 19, 2017 at 18:13
  • \$\begingroup\$ @Joshua isn't + disabled though? \$\endgroup\$
    – Mayube
    Jul 19, 2017 at 18:19
  • \$\begingroup\$ @joshua I don't think exiting vim and doing it in bash counts as cracking a vim answer. \$\endgroup\$
    – DJMcMayhem
    Jul 19, 2017 at 18:24
  • \$\begingroup\$ @DJMcMayhem Cracked? \$\endgroup\$ Jul 19, 2017 at 18:55
1
\$\begingroup\$

Vim (Cracked by Bruce Forte)

This is a patched version of my previous approach

:for i in split('Qq@:=+!','\zs')
exe 'map '.i.' <nop>'
exe 'map! '.i.' <nop>'
endfo

Plus 3 bytes for the -Z flag.

You can Try it online!, but keep in mind that some things are slightly different online, since this is a V interpreter, not a vim interpreter. Most notably, the -Z flag in vim is translated to the --safe flag in V. Of course, your crack may not rely on any V-specific features.

Input is to the buffer like this:

3
4

And output is to the buffer.

What's evil about it?

First off, the -Z flag prevents you from running any external commands (such as bash, python, awk, etc.). Any cracks must run in pure vim. Also, to clarify, an answer like :q<cr>read a;read b; echo $((a+b)) is not valid, because that is no longer a vim answer. The input and output must happen inside of one vim session

Then it makes it so that the following characters cannot be used:

Qq@:=+!
  • Disabling Q and : prevents you from running ex commands.

  • Disabling q prevents a workaround for q: entering ex mode, and removes your ability to create/run macros.

  • Disabling @ prevents you from deleting text, and running that as a macro (the shortest way to add two numbers).

  • Disabling ! prevents you from using filters.

  • And lastly, disabling = and + makes it so you can't use the evaluation register.

For reference, my solution is 23 keystrokes long. Have fun cracking!

\$\endgroup\$
2
  • \$\begingroup\$ Cracked. \$\endgroup\$ Jul 19, 2017 at 20:43
  • \$\begingroup\$ It seems to me that yours is quite different from mine (keystrokes-wise). Would you mind including your solution, I'm very curioius? \$\endgroup\$ Jul 20, 2017 at 16:36
1
\$\begingroup\$

Ruby (cracked by Dennis)

END{exit 0}

Input through STDIN, output through exit code. Example:

 $ ruby mostly_unusable.rb
3
4
 $ echo $?
7
\$\endgroup\$
1
  • \$\begingroup\$ cracked \$\endgroup\$
    – Dennis
    Jul 19, 2017 at 22:15
1
\$\begingroup\$

Java 8, too many bytes! (cracked on Linux (only) by Ilmari Karonen)

import java.io.FilePermission;
import java.io.InputStream;
import java.net.SocketPermission;
import java.security.Permission;
class Boolean {}
class Byte {}
class Character {}
class Double {}
class Enum {}
class Float {}
class Integer {}
class Long {}
class Math {}
class Number {}
class Package {}
class Short {}
class StrictMath {}
class System {} // tried to redefine System? Good try.
class Thread {}
class Void {}
class java {} // do NOT create a String class that is not java.lang.String (or do, but you won't be able to reuse java.lang.String)
interface Main { // No static block for you! Also, Java 8 only!
  static ClassLoader C = ClassLoader.getSystemClassLoader();
  static void main(String[] a) throws Throwable {
    a = new String[0];
    SecurityManager sm = new SecurityManager() {
      @Override public void checkPermission(Permission perm) {
        String n = perm.getName();
        if (   n.startsWith("set")                  // hey, that's my security, not yours!
            || n.startsWith("read")                 // don't read stuff
            || n.startsWith("get")                  // various thingies including getenv.
            || perm instanceof FilePermission       // no files
            || perm instanceof SocketPermission) {  // no network
          throw new SecurityException("Nope!");
        }
      }
      @Override public void checkPropertyAccess(String key) {
        throw new SecurityException("No property for you!"); // Hey, I've thought about it too! :)
      }
    };
    Object in = C.loadClass("java.lang.System").getDeclaredField("in").get(null);
    InputStream.class.getMethod("close").invoke(in); // No input!
    C.loadClass("java.lang.System").getMethod("setSecurityManager", SecurityManager.class).invoke(null, sm);
    otherMethod();
  }
  static void otherMethod(){
    // Your code here
  }
}

Input method: arguments on the command line.

I'm a nice guy, I let you use System.out, but not directly: security first.

Hint: the intended, hidden 2nd snippet doesn't use the } character, even though there are other, more standard, ways to break it.

\$\endgroup\$
5
  • \$\begingroup\$ You had to go and specify the input method, didn't you? Gah! \$\endgroup\$ Jul 20, 2017 at 15:34
  • \$\begingroup\$ @IlmariKaronen Sorry for that... The rules said I have to provide an input method :s When I realized it, I just fixed that. I didn't modify the code, though. Also, one of my hints say that you should be able to do it without the } character, so it's possible without doing so. Next time I just add Class to the list: I don't need it. ;) \$\endgroup\$ Jul 20, 2017 at 15:36
  • \$\begingroup\$ @IlmariKaronen I asked on chat if you effectively cracked it and the answer is that I made a mistake, but I fixed it before any robber was posted, so this challenge is still safe, sorry. While your effort is laudable and very impressive, we're not there yet! ;) \$\endgroup\$ Jul 20, 2017 at 15:53
  • \$\begingroup\$ Oh well, I rewrote my crack to take input on the command line. Unfortunately that makes it Linux-only, but at least it works on TIO. \$\endgroup\$ Jul 20, 2017 at 15:56
  • \$\begingroup\$ @IlmariKaronen Ok, I'll consider cracked, even though my intended solution works doesn't rely on the OS. Be ready a fixed challenge will be up soon. \$\endgroup\$ Jul 20, 2017 at 16:06
1
\$\begingroup\$

Python 3, Cracked

import sys
for mod in sys.modules.values():mod.__dict__.clear()

All modlues have been deleted, which means there are no builtins available and not much else can be done. Output to STDOUT, input from STDIN

\$\endgroup\$
4
  • \$\begingroup\$ As is, this is just a syntax error. for needs to go on its own line. \$\endgroup\$
    – Dennis
    Jul 20, 2017 at 3:18
  • \$\begingroup\$ Didn't delroth write a blog post about this one? \$\endgroup\$
    – Kevin
    Jul 20, 2017 at 6:20
  • \$\begingroup\$ @Dennis fixed. I don't know how I managed to miss that \$\endgroup\$ Jul 20, 2017 at 12:19
  • \$\begingroup\$ Cracked \$\endgroup\$ Jul 20, 2017 at 18:47
1
\$\begingroup\$

Python 3, cracked by Dennis

import ctypes, sys
if "\n".join(open(__file__).readlines()[2:]):ctypes.pythonapi.Py_AtExit(ctypes.pythonapi.Py_FatalError);del ctypes; sys.modules["ctypes"] = None

(trailing newline at end of code)

Shall we try again ... Uses the ctypes module the force a fatal error (with a nonsensical error message). Input from STDIN, output to STDERR, as before ...

\$\endgroup\$
1
  • \$\begingroup\$ cracked \$\endgroup\$
    – Dennis
    Jul 21, 2017 at 6:46
1
\$\begingroup\$

Java 8, OS-agnostic, cracked by Ilmari Karonen

import java.io.FilePermission;
import java.lang.Class;             // No trying redefining Class.
import java.lang.ClassLoader;       // or ClassLoader
import java.lang.String;            // or String
import java.lang.System;            // And don't think I forgot System!
import java.lang.SecurityException; // You won't mind, will you?
import java.lang.Runtime;           // Just for good measure.
import java.lang.Throwable;         // I'd hate to forget one.
import java.net.SocketPermission;
import java.security.Permission;
class java {}                       // just so you don't mess my own imports  I carefully protected.
interface Main {                    // No static block for you!
                                    // Also, Java 8 only!
                                    // Yep, TIO friendly
  static void main(String[] a) throws Throwable {
    a = new String[0];              // Just in case
    try {
      SecurityManager sm = new SecurityManager() {
        @Override public void checkPermission(Permission perm) {
          String n = perm.getName();
          if (   n.startsWith("set")                  // hey, that's my security, not yours!
              || n.startsWith("read")                 // don't read stuff
              || n.startsWith("get")                  // various thingies including getenv.
              || perm instanceof FilePermission       // no files
              || perm instanceof SocketPermission) {  // no network
            throw new SecurityException("Nope!");
          }
        }
        @Override public void checkPropertyAccess(String key) {
          throw new SecurityException("No property for you!"); // Hey, I've thought about it too! :)
        }
        @Override public void checkExec(String cmd) {
          throw new SecurityException("Muhahaha! No.");
        }
      };
      System.in.close(); // No input
      try{ClassLoader.getSystemClassLoader().loadClass("A");}catch(Throwable e){}       // I load your class, but I don't initialize it!
      System.setSecurityManager(sm);
      ClassLoader.getSystemClassLoader().loadClass("A").newInstance();
    } catch (ClassNotFoundException e) {
      // Do nothing, but don't crash.
    } catch (Throwable e) {
      throw e;
    }
  }
}
// Your code here!
// Hint: create a class A with a public constructor. Not an enum or an interface.

Intended solution:

class A {
  public A() {
    // The access restriction is on System.getProperty(String), not System.getProperties().
    // It's an irk of Java, but is consistent through its history, and is clearly documented as such
    int a = Integer.parseInt(System.getProperties().get("a"));
    int b = Integer.parseInt(System.getProperties().get("b"));
    System.out.println(a+b);
  }
}

Input method: command line arguments

Notes:

  • Don't limit to a single OS, the solution is OS-agnostic as it doesn't rely on anything the OS has to offer. I won't accept an answer that works only on a subset of systems where Java runs.
  • You have to create a class named A with a public no-param constructor (or a static block) to get your code running. That's your entry point. You may declare that the constructor throws something, if you want.
  • You don't need to create any other class + method than A and it's constructor. At least the intended solution doesn't.
  • It's not because I import something that it's used, even in the solution. Don't think I "forgot to remove it" before posting.
  • Don't overthink it, a first year student can solve it. Actually, he/she has a better shot than you to solve it ;)
\$\endgroup\$
6
  • \$\begingroup\$ You found a crack, an oversight from me, but not the answer: that is a platform dependant answer, which is explicitly forbidden. \$\endgroup\$ Jul 20, 2017 at 22:20
  • \$\begingroup\$ Just for the sake of saying it, I'm not closed against actual cracks that I didn't intend. I intended for instance to block the access to SecurityManager and I failed at that. Okay, that's my mistake, but the rest stays the same: "I won't accept an answer that works only on a subset of systems where Java runs." All the answers exist here. \$\endgroup\$ Jul 20, 2017 at 22:28
  • \$\begingroup\$ Well, it is OS-agnostic, although not necessarily JVM-agnostic. But you're right, it probably doesn't work on every system "where Java runs." :( \$\endgroup\$ Jul 20, 2017 at 23:34
  • \$\begingroup\$ Just to check a potential loophole, when you write "command line arguments", I assume you're specifically talking about the program arguments (i.e. those that come after the class name on the command line), not VM arguments (i.e. those that come before the class name). That is, I can't say that the program should be invoked as, say, java -Dnumbers=3,4 Main, right? \$\endgroup\$ Jul 21, 2017 at 0:00
  • \$\begingroup\$ @IlmariKaronen To be clear: when I write command-line arguments, these are arguments I type on the command line to startup the application. You specifically ask about properties (-D...), so let's answer that directly: if you post a solution that can reliably bypass my checkPropertyAccess and pass arguments reliably that way (RuntimeMXBean, for instance is not reliable since explicitly platform dependant), I would have to consider such a solution valid. \$\endgroup\$ Jul 21, 2017 at 9:54
1
\$\begingroup\$

S.I.L.O.S, 12 bytes Cracked!


def print z

Here we essentially duct tape the mouth of your program. We redefine the print keyword to the letter z. Enjoy!
My intended solution outputs to stdout, and receives input via stdin (on TIO it takes in the two integers on separate CLA, but locally use two integers on separate lines)


The intended solution sneakily redefines z back to print, pperry found a golfier method that defines p as print and then works as expected.

Intended solution


def print z z print
readIO 
j=i
readIO
j+i
printInt j
\$\endgroup\$
4
  • \$\begingroup\$ Does the code end with a trailing newline? \$\endgroup\$ Jul 22, 2017 at 12:30
  • \$\begingroup\$ no @pperry it does not \$\endgroup\$ Jul 22, 2017 at 20:31
  • \$\begingroup\$ I think this counts as a crack, then \$\endgroup\$ Jul 22, 2017 at 21:10
  • \$\begingroup\$ @ppperry good job, don't overthink it. That was the intended solution. Although I'm going to try again with a slightly more restrictive security system \$\endgroup\$ Jul 23, 2017 at 3:43
1
\$\begingroup\$

Python 3, cracked by DJMcMayhem

import atexit
if "\n".join(open(__file__).readlines()[2:]):atexit.register(1..__truediv__, 0)

(trailing newline at end of code block). Input from STDIN, output to STDERR. Abuses the rule about correct output even after crashes by registering an atexit handler that raises a ZeroDivisionError, which would normally get output to STDERR, polluting the output.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Cracked! \$\endgroup\$
    – DJMcMayhem
    Jul 20, 2017 at 19:55
  • \$\begingroup\$ I never knew that function even existed ... (although I did expect this one to be cracked fairly quickly) \$\endgroup\$ Jul 20, 2017 at 20:06
1
\$\begingroup\$

CPython 3, cracked by Veedrac

import sys,os,functools
if open(__file__).read().count("__""call__"):sys.exit()
def p(f,e,a,_=os._exit):
     if e == "c_call":_(1)
sys.setprofile(p)
del sys.setprofile

(trailing newline at end)

A patch of my previous answer that used the profile hack. First, prematurely exits if the user's code contains __call__ (which can't be constructed dynamically, as getattr would itself trigger the profile hook madness). Also, deletes sys.setprofile for thoroughness. Generally same idea; you can do everything in Python, but nothing in C. Input to STDIN, output to STDOUT

\$\endgroup\$
2
0
\$\begingroup\$

Java, cracked

It's more of a guess..

public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, NoSuchMethodException {
    
    try {
        
        System.class.getField("in").set(null, null);
        System.class.getField("out").set(null, null);
        System.class.getField("err").set(null, null);
        
        System.class.getMethod("getSecurityManager", new Class[0]).setAccessible(false);
        
        File.class.getField("fs").set(null, null);
        
        for (Method m : Class.class.getMethods()) {
            
            m.setAccessible(false);
            
        }
        
        SecurityManager mngr = new SecurityManager() {
            
            @Override
            public void checkPermission(Permission p) {
                
                throw new Error("Muahaha!");
                
            }
            
            @Override
            public void checkLink(String s) {
                
                throw new Error("Not this way, my friend!");
                
            }
            
        };
        
        System.setSecurityManager(mngr);
        
    } catch (Throwable t) {
        
    }
    
}

This blocks all ways of I/O that I know of, and also blocks undoing my work by construction a custom security manager that does not permit anything (not even linking native libraries). I don't see a way to remove Javas arithmetic stuff,but if someone does, feel free to leave a comment. Hope you enjoy the challenge.

\$\endgroup\$
7
  • \$\begingroup\$ You don't show the code to execute, and you don't show that the whole code you execute produces nothing. \$\endgroup\$ Jul 19, 2017 at 13:09
  • \$\begingroup\$ Well, as I stated above, it's not really more than a guess. \$\endgroup\$
    – racer290
    Jul 19, 2017 at 13:18
  • \$\begingroup\$ Also, cracked! \$\endgroup\$ Jul 19, 2017 at 13:18
  • \$\begingroup\$ Well, that was not inteded. \$\endgroup\$
    – racer290
    Jul 19, 2017 at 13:20
  • \$\begingroup\$ May I edit my answer to fix it or will I have to open a new one? \$\endgroup\$
    – racer290
    Jul 19, 2017 at 13:21
0
\$\begingroup\$

Java 7 (cracked by Ilmari Karonen)

class Main {
  static {
    // I see a lot of java answers where folks are using a Scanner in a static
    // initializer block so let's beat them to the punch and read the first parameter
    // before they have a chance to. The intended solution uses program arguments for input
    // anyway...
    java.util.Scanner s = new java.util.Scanner(System.in);
    if (s.hasNext()) {
      s.next();
    }

    try {
      System.out.close();
      System.in.close();
      System.err.close();
      System.setProperties(null);
    } catch (Exception e) {
      // Nothing
    }
  }
  public static void main(String[]a) throws Exception {
    a = new String[0];
    // Code goes here
  }
}

Try it online!

The intended solution runs on Linux and will work on TIO. It takes input as program arguments and outputs to stdout. Hopefully I didn't forget something really easy. I don't think reflection helps the same way as it does in other answers. Good luck.

\$\endgroup\$
2
  • \$\begingroup\$ Cracked. I suspect my solution counts as "something really easy", but I'm not sure how to get around the System.out.close() without tricks like that, since it seems to close the entire underlying file descriptor. :/ \$\endgroup\$ Jul 20, 2017 at 1:42
  • \$\begingroup\$ @IlmariKaronen You had the correct output method but you did input in a clever manner that I actually like better :] Nice job \$\endgroup\$
    – Poke
    Jul 20, 2017 at 4:21
0
\$\begingroup\$

Python 3.4, 241 bytes, cracked by Sisyphus

sys=__import__("sys")
sуs=__import__("os")
del sуs.system, sуs.open, sуs.write, sуs.writev
del __builtins__ 
del sys.__stdout__,sys.__stderr__,sys.__stdin__ 
sys.stdout=sys.stdin
sys.stderr=sys.stdout
sys.stdin.write=sys.stderr
del sys

Input on true STDIN and with Ctrl-D, output with STDOUT.

\$\endgroup\$
1
0
\$\begingroup\$

CPython 3.6, cracked by veedrac

import sys,os
if open(__file__).read().count("__""call__"):sys.exit()
def p(f,e,a):
 if e == "c_call":1(2)
c=p.__code__
c=type(c)(3, 0, c.co_nlocals, c.co_stacksize, c.co_flags, c.co_code,
                   c.co_consts[:-2]+(os._exit,1), c.co_names, c.co_varnames,
                   c.co_filename, c.co_name, c.co_firstlineno, c.co_lnotab)
p=type(p)(c, {})
sys.setprofile(p)
del c, sys.setprofile

Shall we try yet again?

\$\endgroup\$
2
0
\$\begingroup\$

CPython 3.6, cracked by veedrac

import sys,os
if open(__file__).read().count("__")>5:sys.exit()
def p(f,e,a):
 if e == "c_call":1(2)
c=p.__code__
c=type(c)(3, 0, c.co_nlocals, c.co_stacksize, c.co_flags, c.co_code,
                   c.co_consts[:-2]+(os._exit,1), c.co_names, c.co_varnames,
                   c.co_filename, c.co_name, c.co_firstlineno, c.co_lnotab)
p=type(p)(c, {})
sys.setprofile(p)
del c, sys.setprofile

(trailing newline at end)

There is a non-overwriting solution to all of this madness ... (Input to STDIN, output to STDOUT)

\$\endgroup\$
1
0
\$\begingroup\$

CPython 3.6

import sys,os, ctypes, __main__
f = open(__file__).read()
if f.count("__call__") > 1: sys.exit()
if len(f.splitlines()) != 21:ctypes.pythonapi.Py_AtExit(ctypes.pythonapi.Py_FatalError)
type(ctypes.pythonapi).repr = repr(ctypes.pythonapi)
def p(f,e,a):
 if e == 1 and a is not 2:
    try:3(f,e,a)
    finally:3(f,e,a)
wipe = __main__.__dict__.clear
c=p.__code__
c=type(c)(3, 0, c.co_nlocals, c.co_stacksize, c.co_flags, c.co_code,
                    (None, "c_call",wipe, p), c.co_names, c.co_varnames,
                    c.co_filename, c.co_name, c.co_firstlineno, c.co_lnotab)
p.__code__ = c
g=getattr
s=sys.setprofile
for mod in sys.modules.values():
    if g(mod,"__name__",None) != "__main__":mod.__dict__.clear()
s(p)
wipe()

(trailing newline at end)

Congratulations, Veedrac, zbw, and Dennis! You've cracked all three of my Python solutions. but now, can you crack them all together?! Input from STDIN, output to STDERR (which, per the rules, needs to be clean and not contain a Fatal Python error:, which the ctypes handler will print). The profile hook crashes by causing a recursion error handling a recursion error in order to make sure it isn't abused as an exit method. I wonder how long this will take to be cracked ...

\$\endgroup\$
1
  • \$\begingroup\$ Is someone going to crack this? \$\endgroup\$ Aug 5, 2017 at 12:42
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.