Make your language *mostly* unusable! (Cops' thread)

62

10

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>

James

Posted 2017-07-18T23:57:26.807

Reputation: 54 537

3What 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? – Conor O'Brien – 2017-07-19T00:34:56.683

@ConorO'Brien could employ some trick like commenting out the last } and inserting your own (in fact, that could be part of the challenge :P) – Stephen – 2017-07-19T01:41:42.093

@StepHen You can't modify your own code in C, it's a compiled language – Conor O'Brien – 2017-07-19T01:47:30.767

What constitutes "run correctly"? – Conor O'Brien – 2017-07-19T01:51:24.750

1Can the second snippet be placed anywhere in the first snippet? – LegionMammal978 – 2017-07-19T02:51:31.470

1I know nothing about coding, but this challenge looks amazing, – Pritt Balagopal – 2017-07-19T14:04:57.977

@DJMcMayhem this answer was edited but to correct an issue that was unforeseen (the program was made... not a program). In the end I cracked it anyways and without that change having any effect. Does it still count?

– Olivier Grégoire – 2017-07-19T15:07:39.863

This is essentially what I was going for in this sandbox proposal. I'll delete my proposal, since it was never posted.

– mbomb007 – 2017-07-19T21:25:28.657

2

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.

– Dom Hastings – 2017-07-20T18:13:46.733

2@DomHastings That's extremely helpful! Thank you very much :) – James – 2017-07-20T18:14:35.920

This challenge has a suprisingly high percentage of answers being cracked ... – pppery – 2017-07-21T13:17:10.287

Answers

2

Gforth 0.7.3 (TIO), 231 bytes [SAFE]

This code redefines as useless some necessary output methods, as well as addition and something crucial for declaring functions. Good luck!

: . ;
: dec. ;
: u. ;
: .r ;
: u.r ;
: d. ;
: ud. ;
: d.r ;
: ud.r ;
: emit ;
: type ;
: + postpone 2drop ;
: ; + + + postpone exit reveal postpone [ ;

Input will be two signed integers taken from the top of the stack as function parameters. Output to STDOUT.

So you should fix the damage done, and define a function that takes the top two values from the stack and prints the result as an integer (not a float) to STDOUT without additional output (no trailing space).

Here's a template, if your goal function is named f.

Solution:

79 bytes

I actually removed the immediate keyword from the end of the redefinition of ;, so it was necessary for an answer to include it at the start. The function I defined is mostly equivalent to the internal definition of ., but it doesn't print the space at the end, and the addition is performed first, by moving the numbers to the floating point stack and back.

immediate : f s>f s>f f+ f>d swap over dabs <<# #s rot sign #> (type) #>> 0 0 ;

Try it online

mbomb007

Posted 2017-07-18T23:57:26.807

Reputation: 21 944

1This is a very nice answer. At this rate, it looks like it might end up being the only uncracked answer! – James – 2017-07-25T16:24:58.487

:) I combined a couple of different obstacles. At this point, I'm wondering if I could've done just a single one to make my score better. But it's possible that having more than one is why it's uncracked yet. – mbomb007 – 2017-07-25T18:08:29.013

21

Haskell, cracked by Christian Sievers

import Prelude(getLine,print)
a=a

Full program, reading two integers (including negative ones) from stdin and writing to stdout.

I've just disabled the Prelude so almost nothing is in scope, and then added a definition; further imports are syntactically invalid. I gave you getLine and print though.


Edited to add my original solution. Christian's crack was different, but exploits the same basic features (you can get a surprising amount of computation done by accessing functions that have syntactic sugar, even when you can't call anything builtin directly or even name the types involved).

import Prelude(getLine,print)
a=a
(x:l)!0=x
(x:l)!n=l!d[0..n]
d[x,y]=x
d(x:l)=d l
x^y=[x..]!y
x+y=f[0..y](x^y)(-((-x)^(-y)))
f[]x y=y
f _ x y=x
f.g= \x->f(g x)
f&0= \x->x
f&n=f.(f&d[0..n])
x*y=((+x)&y)0
x%[]=x
x%('-':s)= -(x%s)
x%(c:s)=x*10+i c%s
i c=l['1'..c]
l[]=0
l(x:s)=1+l s
main=do
 x<-getLine
 y<-getLine
 print((0%x)+(0%y))

Which probably isn't super-golfed anyway, but here it is more readibly:

import Prelude(getLine,print)
a=a

-- List indexing
(x : _) !! 0 = x
(_ : xs) !! n = xs !! (sndLast [0..n])

-- sndLast [0..n] lets us decrement a positive integer
sndLast [x, _] = x
sndLast (_ : xs) = sndLast xs

-- Pseudo-addition: right-operator must be non-negative
x +~ y = [x..] !! y

-- Generalised addition by sign-flipping if y is negative
x + y = switch [0..y] (x +~ y) (-((-x) +~ (-y)))
  where switch [] _ empty = empty   -- [0..y] is null if y is negative
        switch _ nonempty _ = nonempty

f . g = \x -> f (g x)

-- compose a function with itself N times
composeN f 0 = \x -> x
composeN f n = f . (composeN f (sndLast [0..n]))

-- multiplication is chained addition
x * y = composeN (+x) y 0

strToNat acc [] = acc
strToNat acc ('-' : cs) = -(strToNat acc cs)
strToNat acc (c : cs) = strToNat (acc * 10 + charToDigit c) cs

charToDigit c = length ['1'..c]

length [] = 0
length (_ : xs) = 1 + length xs

main = do
  x <- getLine
  y <- getLine
  print (strToNat 0 x + strToNat 0 y)

Ben

Posted 2017-07-18T23:57:26.807

Reputation: 381

2cracked – Christian Sievers – 2017-07-19T12:36:26.263

17

Python 2, Cracked

Implements addition as a named function

import sys
c="".join(open(__file__).read().split('\n')[4:])
if set(c)-set(' &)(,.:[]a`cdfijmonrt~')or"import"in c:sys.setrecursionlimit(1)
f=lambda\

Try it online!

What does this do?

For the purposes of helping you out a bit I'll explain what this does. This code opens the source file and checks if the remainder of the code fits the following criteria:

  • Does not contain the string import
  • Is made solely of the characters &)(,.:[]a`cdfijmonrt~

If it fails either criterion the recursion limit is set to 1 meaning that any code you write will hit the recursion limit.

There are no tricks here, I have written a solution that uses only these characters and no imports, I'm not doing anything subversive, but I will say that I think this will be pretty hard to crack.

To save you some time here is a short list of useful things you cannot do with this restriction

  • + well duh,

  • eval/exec Wasn't going to let you get away with that

  • Numbers, They might be more useful than you think

  • String literals

  • len

  • =, No assigning variables

  • >,<,==. . . I have left you with no comparisons

  • *,-,/,%,^,|,>>,<< The only operators available are ~ and &

  • __foo__, None of those fancy double underscore methods are allowed.

Post Rock Garf Hunter

Posted 2017-07-18T23:57:26.807

Reputation: 55 382

1Wow this is quite evil. Nice! – HyperNeutrino – 2017-07-19T01:24:51.017

Fantastic answer to kick things off :) – James – 2017-07-19T01:33:15.113

Hehe, this just might have been inspired by that dumb [tag:king-of-the-hill] challenge I tried to spec out in chat that one time – Stephen – 2017-07-19T01:37:45.657

4

I think this is a valid crack: https://codegolf.stackexchange.com/a/133209/68942

– HyperNeutrino – 2017-07-19T02:03:12.023

RE the first snippet: This code is not allowed to crash or exit. (see chat for discussion on it) – Stephen – 2017-07-19T02:18:15.627

Hmm while you assure us you have used only those characters, wouldn't just setting the recursion limit to three or more after assigning some normal code to f be valid?

– Jonathan Allan – 2017-07-19T02:31:48.353

@JonathanAllan See HyperNeutrino's crack – Conor O'Brien – 2017-07-19T02:32:34.887

@ConorO'Brien ah, poor connection. – Jonathan Allan – 2017-07-19T02:35:44.297

Did you need to check for "import" separately, given that 'p' is not an allowed character? – aschepler – 2017-07-19T23:32:02.163

12

Python 2, Cracked

This is the fourth iteration of this answer. Each of the last answers has was cracked via reseting the recursion depth.

Implements addition as a named function

import sys
if set("".join(open(__file__).read().split('\n')[4:]))-set(' &)(,.:[]a`cdfijmonrt~'):sys.setrecursionlimit(1)
for m in sys.modules:sys.modules[m]=None
del sys;f=lambda\

Try it online!

What does this do?

For the purposes of helping you out a bit I'll explain what this does. This code opens the source file and checks if the remainder of the code is made solely of the characters &)(,.:[]a`cdfijmonrt~

If it fails the recursion limit is set to 1 meaning that any code you write will hit the recursion limit.

I've also disabled all of the modules, so you can't import anything.

There are no tricks here, I have written a solution that uses only these characters and no imports, I'm not doing anything subversive, but I will say that I think this will be pretty hard to crack.

To save you some time here is a short list of useful things you cannot do with this restriction

  • + well duh,

  • eval/exec Wasn't going to let you get away with that

  • Numbers, They might be more useful than you think

  • String literals

  • len

  • =, No assigning variables

  • >,<,==. . . I have left you with no comparisons

  • *,-,/,%,^,|,>>,<< The only operators available are ~ and &

  • __foo__, None of those fancy double underscore methods are allowed.

My solution

So now that xnor has cracked it in a way I am sufficiently satisfied with I am going to reveal my solution

r,o:(o and f(~(~r&~o)&~(r&o),int(`r`[:r&~r].join([`dict()`[r&~r],`r&~r`,`dict([(r&~r,r&~r)])`[int(`~([]in[[]])`[[]in[[]]:])],`min`[[]in[[]]],`dict()`[~(r&~r)],`r&~r`]).format(r&o),int(`~([]in[[]])`[[]in[[]]:]))))or r

Surprise, surprise its a hulking pile of gibberish. Rather than break this down I'm going to go through the process of how I made this.

I started with a pretty standard addition algorithm

r,o:(o and f(r^o,r&o<<1))or r

Then I used a bitwise trick for representing ^ with |,&,~.

r,o:(o and f((r|o)&~(r&o),r&o<<1))or r

I used another bitwise trick to get rid of the |

r,o:(o and f(~(~r&~o)&~(r&o),r&o<<1))or r

Now all thats left is the <<, shouldn't be too hard, right? Well get ready for a bumpy ride. To replace the bitshift I used strings to append a zero to the end of its binary representation

r,o:(o and f(~(~r&~o)&~(r&o),int(bin(r&o)[2:]+"0",2)))or r

This has a few problems but the primary one is using addition, so I worked around this by using a format instead

r,o:(o and f(~(~r&~o)&~(r&o),int("{}0".format(bin(r&o)[2:]),2)))or r

We are not allowed to use bin, so I used string formatting to convert to binary.

r,o:(o and f(~(~r&~o)&~(r&o),int("{0:b}0".format(r&o),2)))or r

Since string literals are forbidden I have to build the string {0:b}0 out of parts made with back ticks and join them together.

r,o:(o and f(~(~r&~o)&~(r&o),int("".join(["{","0",":","b","}","0"]).format(r&o),2)))or r

The empty string is pretty easy, you can just do

`r`[:0]

The zeros were

`0`

and the {:} were all grabbed from dictionaries.

r,o:(o and f(~(~r&~o)&~(r&o),int("".join([`dict()`[0],`0`,`dict([(0,0)])`[2],"b",`dict()`[-1],`0`]).format(r&o),2)))or r

b seems pretty hard to get, its not in our character set, so how are we supposed to get an object that has a b in its repr? Well here's how: When you use repr on a builtin function you get something that looks like

<built-in function name>

And thats from where we'll get our b.

r,o:(o and f(~(~r&~o)&~(r&o),int("".join([`dict()`[0],`0`,`dict([(0,0)])`[2],`min`[1],`dict()`[-1],`0`]).format(r&o),2)))or r

Now all thats left are numbers, I only need -1, 0, 1, and 2 so here's how I represented them:

-1 = ~(r&~r)
 0 = r&~r
 1 = []in[[]]
 2 = `~([]in[[]])`[[]in[[]]:]

2 could actually be a byte shorter as

```r&~r```.find(`r&~r`)

based on @Blender's suggestions in the comments, but I didn't think of this until after the fact.

So we substitute these numbers in

r,o:(o and f(~(~r&~o)&~(r&o),int(`r`[:r&~r].join([`dict()`[r&~r],`r&~r`,`dict([(r&~r,r&~r)])`[int(`~([]in[[]])`[[]in[[]]:])],`min`[[]in[[]]],`dict()`[~(r&~r)],`r&~r`]).format(r&o),int(`~([]in[[]])`[[]in[[]]:]))))or r

And thats the crack.

Post Rock Garf Hunter

Posted 2017-07-18T23:57:26.807

Reputation: 55 382

This snippet seems to error on its own. – ATaco – 2017-07-19T05:22:25.363

@ATaco I believe this was discussed in chat and it was decided that this was ok. – Post Rock Garf Hunter – 2017-07-19T05:23:18.320

Rules explicitly state otherwise. "This code is not allowed to crash or exit." – ATaco – 2017-07-19T05:24:23.397

@ATaco Here's the message he said he would update it when he got the chance.

– Post Rock Garf Hunter – 2017-07-19T05:26:38.733

I was going to try to crack but I don't even know how to make it not crash ;-; – ATaco – 2017-07-19T05:27:27.343

@ATaco Its the beginning of a lambda definition, add some arguments and a colon, r,rr: followed by the code will do the trick. The \\ is just a line continuation character. – Post Rock Garf Hunter – 2017-07-19T05:29:02.053

All right, we've got find, min, ord, int, repr backticks, argument separators, method calls... we can get a lot of numbers by putting together repr backticks, ord, &, and ~... we can add individual digits by slicing the right strings... – user2357112 supports Monica – 2017-07-19T06:20:34.550

We've got for and in, so we have list comprehensions and genexps. No next or iter, though. I wonder how many of these characters are red herrings. I haven't come up with a use for the j... – user2357112 supports Monica – 2017-07-19T06:28:14.680

@user2357112 I will tell you that my intended solution uses all of these characters, no red herrings. Perhaps not all of them are needed but I've tried to minimize the character set to the best of my abilities. However not all the functions you have mentioned are used in my solution, for example I don't use ord. Hope thats not too much of a hint, but I want to keep it fun. – Post Rock Garf Hunter – 2017-07-19T06:31:40.020

oh, whoops, I forgot I'd already come up with a use for the j - join, which is a usable substitute for + for string concatenation. – user2357112 supports Monica – 2017-07-19T06:44:32.257

I'm going to bed. Here are some notes that might be useful for other people who want to crack this.

– user2357112 supports Monica – 2017-07-19T07:35:32.740

@user2357112 those are some really nice notes but - is disallowed... – Value Ink – 2017-07-19T08:10:39.060

The length of any string can be achieved with (your string).rfind(\()`[int():int()])` – Value Ink – 2017-07-19T09:16:02.153

Here are all the digits 0-9: https://pastebin.com/aaUd42fc

– Blender – 2017-07-19T09:24:42.100

You can construct arbitrary numbers by obtaining the string representations of any of those digits and then concatenating them: -275 == int(`()`[int():int()].join(['-', '2', '7', '5'])) – Blender – 2017-07-19T09:42:31.650

5Cracked? – xnor – 2017-07-19T10:03:41.417

@ValueInk: Ah, crap. Oh well. I only really used it to get 0, which could be produced other ways. (Nice len workaround.) – user2357112 supports Monica – 2017-07-19T15:02:47.080

10

C (gcc) Cracked!

#define D(f)void f(void);
D(printf)D(fprintf)D(putc)D(puts)D(getchar)D(putc)D(fputc)D(ferror)D(feof)D(read)D(fclose)D(fread)D(wr1te)D(fgets)D(fgetc)D(popem)D(gets)D(read)D(scanf)D(setbuf)D(execl)D(execlp)D(putchar)D(execle)D(execv)D(malloc)D(execvp)D(execvpe)D(exec)D(system)D(close)D(fwrite)D(open)D(free)
int stdin;
int main(){
//your code goes here...hehe
}

Try it online!

Input from STDIN and output to STDOUT.

This runs without error. Hahaha this is quite evil. I've only tested it on TIO's gcc. Per usual, you must append your code after this snippet in order for it to work :) The comment is a mean one, don't listen to it.

Tested on gcc (GCC) 6.3.1 20161221 (Red Hat 6.3.1-1). Should work on any linux system.

Original solution

#define D(f)void f(void);
D(printf)D(fprintf)D(putc)D(puts)D(getchar)D(putc)D(fputc)D(ferror)D(feof)D(read)D(fclose)D(fread)D(wr1te)D(fgets)D(fgetc)D(popem)D(gets)D(read)D(scanf)D(setbuf)D(execl)D(execlp)D(putchar)D(execle)D(execv)D(malloc)D(execvp)D(execvpe)D(exec)D(system)D(close)D(fwrite)D(open)D(free)
int stdin;
int main(){
//your code goes here...hehe
}
void __attribute__ ((destructor)) dtor() {
    int a,b,c,d;a=b=c=0;
    struct FILE* z = popen("cat", "r");
#define q(x)for(;(c=getc(z))^32&&c^-1;)x=10*x+c-48;
q(a);q(b);
    char*y=calloc(c=a+b,1);
    for(a=0;c;){y[a++]=(48+(c%10));c=c/10;}
    for(b=0;b<a/2;b++){d=y[b];y[b]=y[a-b-1];y[a-b-1]=d;}
    write(1,y,a);
}

Conor O'Brien

Posted 2017-07-18T23:57:26.807

Reputation: 36 228

@LegionMammal978 Ah yes – Conor O'Brien – 2017-07-19T02:38:22.823

2Specify your platform! – Joshua – 2017-07-19T02:48:33.860

@Joshua I have added some information – Conor O'Brien – 2017-07-19T03:02:45.427

4cracked – Dennis – 2017-07-19T03:23:49.337

Well, __asm__ and you have plenty of functions to choose from :) don't think C and C++ are good enemies here. – edmz – 2017-07-19T13:07:34.900

__asm__ implies platform specificity. If the cop writes portable code, I don't think the robber is allowed to limit his workaround to a particular platform. But that's just the rules I'd want; maybe I'm wrong. @black – Cody Gray – 2017-07-19T14:04:12.623

@CodyGray: same can be said for read(2), technically. Still, I see Python answers here, which, truth to be told, might call C too. But that's really an edge-case, I guess we shall agree to say :) – edmz – 2017-07-19T14:18:39.957

well once somebody recalls attribute ((destructor)) it's only a matter of time before this goes down. Take the address of printf, cast it to the right type, and call it that way. – Joshua – 2017-07-19T15:35:13.427

10

C (GCC on Linux) (cracked)

Instead of using silly file-reading sandboxing techniques, we do it the proper way - with SECCOMP whitelisting!

Your task: implement addition with input from STDIN and output to STDOUT.

#include <stdlib.h>
#include <unistd.h>
#include <sys/prctl.h>
#include <linux/seccomp.h>
#include <syscall.h>
#include <stdio.h>
void sandbox();
__attribute__ ((constructor(0))) int s() {
    close(0);
    close(1);
    close(2);
    prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT);
}
int main() {
    sandbox();
    syscall(SYS_exit, EXIT_SUCCESS);
}
void sandbox() {
    // Your code here!
}

Try it online!

WTF is this!?

To help you in your insurmountable task I'll explain what this code does.

__attribute__ ((constructor(0))) ensures the s function is run first. The function closes all open file descriptors for STDIN, STDOUT and STDERR. Then the program restricts itself with a strict SECCOMP whitelist, which limits your system calls to the following:

read(2)
write(2)
_exit(2)
sigreturn(2)

Therefore you cannot open any new files (or basically do anything). We then come to main and call your code, nicely wrapped in the sandbox function.

The syscall(SYS_exit, EXIT_SUCCESS); at the end is just to ensure the program exits cleanly - by default GCC will exit with exit_group(2) which is not allowed by the SECCOMP whitelist. This exiting function is called after your code is run.

So you have no open file descriptors, and you can't open anything new. Impossible, right? ;)

Sisyphus

Posted 2017-07-18T23:57:26.807

Reputation: 1 521

3cracked – 2012rcampion – 2017-07-19T15:40:21.160

9

Haskell, cracked by Ben

main=main--

Try it online! This should be a full program reading two numbers from stdin and outputting the sum to stdout.

Each full program starts by running the main function, but here main calls itself and causes an infinite loop. To make matters worse, a line comment is started with -- directly behind the recursive call to prevent changing it to e.g. main2 and then defining that to do the summation.


Intended solution:

main=main--$()
_ --$ _ = do
     x <- readLn
     y <- readLn
     print $ x+y

Try it online!

-- starts a line comment unless it can also be parsed as part of an operator. (The syntax highlighting seems to be unaware of this fact.) --$ is a valid infix operator which takes main as first argument and some dummy second argument (). It is then defined to ignore both arguments and to perform the required task instead.

Laikoni

Posted 2017-07-18T23:57:26.807

Reputation: 23 676

2

Cracked it: https://codegolf.stackexchange.com/a/133244/17061

– Ben – 2017-07-19T06:42:40.320

5you can just add "where main = ..." – michi7x7 – 2017-07-19T07:20:31.303

+1 for a Haskell solution that only works because of Haskell's lazy evaluation. – Jules – 2017-07-20T17:38:01.903

8

x86 16 bit real mode Assembly (Cracked)

_main:
    call l
    cli
    hlt
l:  pop si
    xor ax, ax
    mov bp, cs
    mov es, ax
    mov di, 12
    mov [di], si
    mov [di + 2], bp
    pushf
    mov bp, sp
    or word [bp], 256
    popf

Easy if you know the trick.

Joshua

Posted 2017-07-18T23:57:26.807

Reputation: 3 043

1How are you taking the input? On the stack, or in registers? (Also, it looks like this is supposed to be 16-bit assembly, but if so, or [bp], 256 is invalid. Is that supposed to be or WORD PTR [bp], 256?) – Cody Gray – 2017-07-19T08:10:58.393

1Also, you should specify which processor you're using; there's lots of x86 versions and clones out there, and lots of undefined instructions. If I wrote code for an "obscure 80186 clone" that just so happened to have an undefined instruction that took a few arguments and blah blah blah... We also might need environment. 16 bit Windows gave an SS==DS guarantee that other systems might not, for example. – Orion – 2017-07-19T09:06:00.633

At least give us operating mode. Is this real mode, protected mode, or long mode? – Orion – 2017-07-19T09:07:05.927

1You only need to specify which processor if you actually are using some trick that works only on one particular model (or one particular generation). This code isn't like that, so I think "x86-16" is sufficient. In my opinion, the more general the better. Agreed that real or protected mode should be specified, although the presence of the hlt instruction (ring 0) strongly implies that this is not protected mode. – Cody Gray – 2017-07-19T12:30:12.483

@CodyGray: I deliberately didn't specify the OS. It will suffice to defeat this if you manage to un-break the the breakage this code introduced and from that point I don't care what the I/O is. – Joshua – 2017-07-19T15:14:22.973

3@Joshua if it doesn't work on every platform, you have to at least specify a platform it will work on, I believe. Your submission must contain enough information before being revealed to be reproducible after being revealed – Stephen – 2017-07-19T21:08:13.810

1@StepHen: The solution to unbreak the language is platform agnostic once specified x86-16 real mode, but I/O is not platform agnostic. He who breaks out it may specify the OS for which he broke out. I added the _main label late so that someone could in theory make a nearly agnostic break by linking against libc. – Joshua – 2017-07-19T21:11:28.327

1I think I see how to do it, and yes, it's pretty much processor-agnostic. – Mark – 2017-07-19T22:30:16.630

Cracked – Mark – 2017-07-20T22:38:07.690

@Mark: Nope! You need to be able to perform I/O somehow or nobody's ever going to see the result in register. – Joshua – 2017-07-21T03:51:45.883

Actually cracked :-) I was driving myself crazy with this, because I thought I knew the trick, but I couldn't seem to make it work. I was using DOS Debug to assemble/test the code, but it turns out that Debug doesn't interpret the operand to the CALL instruction as a relative offset. So here I was typing CALL 5, and it was interpreting that as a relative call to CS:0005, which obviously was not what I wanted. Ironically, I had to turn on single-stepping to debug my mistake! – Cody Gray – 2017-07-21T09:57:59.280

4

Perl 5, cracked by Ilmari Karonen

$_=<DATA>;
s/[+'{dPz|K.UD!_ iJ;o}e6tjWb7253k@%&Iq4l0AN:?\$8B`Yywn9^pfmZQTF"M#-]//g;
eval;
print@_,$!,pop,shift,<>,eval"@>",$\,@ARGV,eval"@$",$@,eval"@@",$,,eval"@,",$/
__DATA__

Input is received on separate lines of STDIN and output is printed to STDOUT.

All code goes after the __DATA__ marker. This uses a similar method to @WheatWizard's solution in that the code is parsed and unusable chars are removed.

This has been tested on versions 5.8, 5.10 and 5.16, and requires no command-line flags.

Try it online!

Dom Hastings

Posted 2017-07-18T23:57:26.807

Reputation: 16 415

2Could you please specify the input/output method and format? – Ilmari Karonen – 2017-07-19T21:44:18.200

@IlmariKaronen Apologies, it's STDIN with chars on separate lines and STDOUT. I'll add this to the main body. – Dom Hastings – 2017-07-20T04:37:24.853

Cracked, I think. – Ilmari Karonen – 2017-07-20T23:22:32.883

4

APL (ngn-apl), cracked by ngn

Made in cooperation with my colleague Marshall.

Input through left and right arguments to +. I.e. your goal is to insert code after the the following, so that your last line reads ⎕←3+2 and outputs 5 to STDOUT.

+←-←−←⍴←≢←≡←⊥←⊤←⍟←○←⍳←⌹←~←∈←∊←⍷←<←≤←=←≥←>←≠←,←⍪←⌷←⌽←⍉←⊖←{}⋄⍣←∘

Try it online!

Works by setting all useful functions to {} which takes one or two arguments and returns an empty numeric list. Also sets to just compose functions.


Crack

+←{⌈/⍋⍺⍵1/0}

⍺⍵1/0 replicate 0 by the left argument and the right argument and 1

 get the indices that would sort that (since all elements are zero, it gives 0 1 2…(a+b)

⌈/ the maximum value (a+b)

Adám

Posted 2017-07-18T23:57:26.807

Reputation: 37 779

ngn/apl includes the ability to execute arbitrary JavaScript. I do not consider such a solution valid, as it would then be about disabling JavaScript rather than APL. There is indeed a valid (albeit obscure) way to reset + using only pure APL and no dirty tricks. – Adám – 2017-07-19T20:51:23.963

4

Javascript, Cracked

This challenge builds off of Grant Davis's, but fixes the solution he had in mind (which creates an iframe and uses the iframe's window). The solution runs in the javascript console on chrome's about:blank page, and takes two input()s, adds them together, and console.logs the result. Put your code after:

d=prompt=console=document;new MutationObserver(s=>s.forEach(e=>{t=e.target;t.parentNode.removeChild(t)})).observe(d,{"childList":d, "subtree":d})

First, we clobber prompt and console and set the shortcut d. Then, we create a mutation observer with a callback which removes every target mutated. We set that mutation observer to observe the document, and notify on childList and subtree modifications. Instead of the literal true, we use our shortcut to the truthy value document (the spec doesn't allow this, but chrome does).

After I posted this, I realized a much more elegant clobber. My intended solution still works, but the crack posted does not:

 h=document.querySelector("html");h.parentNode.removeChild(h);

Daniel Franklin

Posted 2017-07-18T23:57:26.807

Reputation: 73

Welcome to the site! I'm interested to see what the solution will be :) – James – 2017-07-19T21:17:58.507

I think this counts as a crack. – Ilmari Karonen – 2017-07-19T22:31:34.723

4

Python 3, cracked by zbw

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

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. This is the second iteration of this answer after the previous one was broken by a trivial crack by adding a break statement.

pppery

Posted 2017-07-18T23:57:26.807

Reputation: 3 987

I'm really curious to see the snippet that works after this – None – 2017-07-21T01:50:10.213

Well, you have to wait seven days or for a non-trivial crack, whichever comes first ... – pppery – 2017-07-21T02:19:45.183

Cracked! – zbw – 2017-07-21T17:55:48.233

Well, well, challenges like these are very difficult to do well – pppery – 2017-07-21T19:23:41.283

3

cQuents, cracked by Mayube

#|1,1:A

This should be fairly easy, but you never know.

The "problem" was that without C in your code, you got an error.

Mayube's solution:

#|1,1:A+BC

Each item in the sequence is the first input plus the second times the third (aka 1)

My solutions:

#1,1:A+B,C

The sequence cycles between the first input plus the second input, and the third input (1). The first item in the second is A+B.

#1,1:A+B+C-C

Similar to Mayube's solution - instead of multiplying B*C, just adds C and then subtracts it.

Try it online!

Explanation

#|1,1      Append 1 and 1 to the end of the user's input
     :     Set mode to : (sequence 1: if given n, output nth term in sequence; if given no n, output whole sequence)
      A    Each item in the sequence equals the first input

Currently, this program outputs 1, since with no user input, the first input is the first 1 in the default input (#).

Stephen

Posted 2017-07-18T23:57:26.807

Reputation: 12 293

The docs seem really awkwardly worded, I can't for the life of me figure out what it means when it says Default input is combined with user input to form the total input, which must align with the expected input (which is based on the highest input requested by the Sequence Definition) – Skidsdev – 2017-07-19T14:49:33.587

@Mayube it's weird, I need to find a way to say it correctly. Basically, your input to the program can be equal to the highest input queried by variables A,B,C,D,E in the code. For example, if at any point you have the variable D in your program, the parser expects there to be 4 inputs, but if there is also an E, the parser expects there to be 5 inputs. There cannot be less than the expected amount. However, there is always an optional last input, n, which is used in different ways by different modes. – Stephen – 2017-07-19T14:55:42.003

@Mayube the snippet I posted above contains an A, so it looks for one input. Since there are two, both coming from # which specifies default input, it uses the first one as A's value and the second one as n. – Stephen – 2017-07-19T14:56:24.463

So if I were to give 2 inputs, and append BC, A would be the first input, B would be the second, C would be 1, and n would be the second 1? – Skidsdev – 2017-07-19T15:12:44.357

@Mayube exactly, sorry for my crappy docs. TMI: if the beginning looked like #1,1 (no bar), it would be: A as the first 1, B as the second 1, C as the first input, and n as the second input. You can also do #1|1, where A is the first 1, B is is the first input, C is the second input, and n is the second 1. – Stephen – 2017-07-19T15:15:05.640

Hmm okay, and what does the : do? Docs say output the nth term, but in what order is the code run? – Skidsdev – 2017-07-19T15:19:26.083

@Mayube : sets the mode. Information before the mode is parameters for the program, information after the mode is the sequence. I'll edit in an explanation for this snippet. Program format is <literals><parameters><mode><sequence> (dunno why that's not in docs, I'll put it in next commit) – Stephen – 2017-07-19T15:22:30.853

Looks like this should do

– Skidsdev – 2017-07-19T15:53:08.790

3

Python 2, Cracked

This is the second iteration of an answer that has been cracked once by @HyperNuetrino using a method I had not expected. I've now patched it so hopefully the only solutions left will have to abide by the restrictions I intended.

Implements addition as a named function

import sys
c="".join(open(__file__).read().split('\n')[4:])
if set(c)-set(' &)(,.:[]a`cdfijmonrt~')or"import"in c:sys.setrecursionlimit(1)
sys.modules['sys'],sys.modules['os']=None,None;del sys;f=lambda\

Try it online!

Post Rock Garf Hunter

Posted 2017-07-18T23:57:26.807

Reputation: 55 382

I think I could do this if I had a u, but I'm stuck without it. – isaacg – 2017-07-19T03:21:02.870

@isaacg Just out of curiosity, what would you to with u? – Post Rock Garf Hunter – 2017-07-19T03:21:52.460

.count. I can get a string as long as the desired output, but I have no way to take its length. – isaacg – 2017-07-19T03:22:56.087

__import__('sys').setrecursionlimit(100)... and nothing actually got patched. I don't really feel like posting it in the robber's thread though, feels like cheating. Try it online – Value Ink – 2017-07-19T03:27:03.437

¯\(ツ)/¯ I put a TIO link in my comment that works, so I'd assume it works. – Value Ink – 2017-07-19T03:32:06.157

__import__=None :P – Conor O'Brien – 2017-07-19T03:51:52.940

@ConorO'Brien Good point, I thought the use might be able to use del __import__ to reset it, but it looks like that fails. I'm going to leave as is in case someone is trying to crack it right now. – Post Rock Garf Hunter – 2017-07-19T03:56:10.787

2Cracked, I think? – Sisyphus – 2017-07-19T04:13:42.820

3

RProgN2, Cracked by Arnold Palmer

"+-/*÷^"{²[[\=};

Writes over all the math operators, with no way to restore them. In particular, it replaces them with a function that removes the top two items on the stack.

Try it online!

Original Solution

{S]‘[L}`d={0RL}`i=«x=y=x{xd`x=yi`y=x}:y»`+=

{S]‘[L}`d={0RL}`i=«x=y=x{xd`x=yi`y=x}:y»`+=
{     }`d=                                  #Define a function, "d", which returns n-1
 S                                          #Convert the input to a stack, which, as a number, makes a stack of 1 - n.
  ]‘                                        #Duplicate the stack, and pop the top value off it.
    [                                       #Discard the popped'd value.
     L                                      #Get the length of the stack, which now is n-1.
          {   }`i=                          #Define a function, "i", which returns n+1
           0R                               #Get the range of numbers between 0 and n.
             L                              #Get the length of that stack, which is n+1
                  «                    »`+= #Define a function, "+", which takes two numbers, and outputs their sum. We use «» here, because it localises references, instead of globalising them.
                   x=                       #Set the first input to the value of "x", which by default, is x.
                     y=                     #Ditto for y.
                       x{          x}:      #While x is truthy, which in this case, is non-zero.
                         xd                 #Get x - 1
                           `x=              #Set x to it.
                              yi`y=         #And set y to y + 1
                                      y     #Push y to the output. And we're done.

Try it online!

ATaco

Posted 2017-07-18T23:57:26.807

Reputation: 7 898

I'm going through your documentation and I can't seem to find what the ² symbol does. Care to enlighten me?

– Arnold Palmer – 2017-07-19T17:31:02.637

That documentation is not incredibly relevant for RProgN2, and that symbol takes the next two concepts [[ in this case, and wraps them in a function @ArnoldPalmer – ATaco – 2017-07-19T21:25:21.700

Cracked – Arnold Palmer – 2017-07-20T13:03:42.637

Dang, that's much better. I didn't know about the stack operators, which sure would've been handy. Also, knowing «» creates local variables as opposed to messing up global ones would've been super helpful. – Arnold Palmer – 2017-07-21T10:32:39.230

3

Java 8, Cracked by @OlivierGrégoire

Here's my attempt. Pretty much, the idea is to just overload all the namespaces you can use to output (and reflect, I hope). Output is intended to sdout (System.out).

class java {
    public static void main(String[]s){
       //there is no executable code in snippet one.
       //your code here.
    }
    class Class{}
    class Method{}
    class System{}
    class FileDescriptor{}
    class Logger{}
    class Runtime{}
    class Scanner{}
}

Blacklisting is typically a worse approach than whitelisting, so I'm sure it's just a matter of time before someone comes up with an approach I didn't consider.

Lord Farquaad

Posted 2017-07-18T23:57:26.807

Reputation: 1 513

1This is not an executable class... – Olivier Grégoire – 2017-07-19T14:26:20.070

Weird, I swear I just had it working a minute ago. Give me a second... – Lord Farquaad – 2017-07-19T14:27:21.017

1@OlivierGrégoire Sorry about that, I added class String{} after testing without realizing it would knock out main(String[] ...). It should work now – Lord Farquaad – 2017-07-19T14:30:48.540

1Yep, that'll do it, thank you! :) It doesn't change the crack I'm about to do, though :p – Olivier Grégoire – 2017-07-19T14:33:58.203

@OlivierGrégoire your confidence is discouraging – Lord Farquaad – 2017-07-19T14:37:07.460

Well I'm currently blocked by an unforeseen exception, but I'm nearly through. – Olivier Grégoire – 2017-07-19T14:41:10.663

1Cracked! I really enjoyed this one :) – Olivier Grégoire – 2017-07-19T14:57:11.380

Thanks! That's a very clever solution! The blacklist fails after all – Lord Farquaad – 2017-07-19T15:00:37.130

Was my solution the intended solution, or did you expect another one? – Olivier Grégoire – 2017-07-19T15:12:23.020

1I was looking at something like this (sorry it's hard to format code in comments), but I think your solution is much cleaner: int sum = 0; new Exception("" + sum) { public void printStackTrace() { ClassLoader cl = ClassLoader.getSystemClassLoader(); try { printStackTrace(new PrintStream((PrintStream)cl.loadClass("java.lang.System").getDeclaredField("out").get(null))); } catch (Exception e){} } }.printStackTrace(); – Lord Farquaad – 2017-07-19T15:24:26.867

probable better place overload classes first, or it will too easy to crack with something like System.out.println(a+b); }} class a{{ – user1516873 – 2017-07-20T14:49:27.317

@user1516873 couldn't they do that either way? new A(); }} class A{{public A() { /* add numbers */ I think snippet 2 has to be valid on it's own though, so I'm not sure these approaches would count – Lord Farquaad – 2017-07-21T21:23:33.210

3

Node.JS version 7.3.0 (Cracked by Dom Hastings)

var p=process,f;(_=>{var w=p.stdout.write,n='f'+(Math.random()*1e7|0),l=1
f=p.stdout.write=a=>eval(`(function ${n}(a){while(l&&((typeof a)[0]!='s'||'f'+a!=n));a=l?l="":a;w.apply(p.stdout,arguments);})`)(a)})();

Place the second code block after the first.

Disclaimer: the second code block will not function on its own (without being placed after the first). If this is not allowed however I can modify the second snippet.

This is a full program. Output is process.stdout (STDOUT), input is process.argv (command line arguments)

This is my first cops and robbers, hopefully this is a good challenge :)

Try it online!


The challenge explained

Generates a random variable n from 0 to 1e7. If you call write with the correct n, doesn't print anything but sets l to 0 which "unlocks" the write function, allowing you to print anything. If you try to call write with a non-string, sends you into an infinite loop. If you try to call write with anything other than the correct n while write is "locked", sends you into an infinite loop to prevent guessing.

The intended solution

Sneaks past the typeof that seemingly checks for strings only by using a Symbol, which also starts with s. This throws an error in the function resulting from the eval call because you can't add the string "f" to a Symbol. We catch the error and use regex to recover n from the stack trace, where it is in the function's name. Then we try to write n which doesn't print anything, but sets the "lock" variable l to 0 to "unlock" the write function. Now that the write function is unlocked we just print the sum.

try{f(Symbol())}catch(e){f(e.stack.match(/f(\d+)/)[1])
f(+p.argv[2]+ +p.argv[3]+"")}

jrich

Posted 2017-07-18T23:57:26.807

Reputation: 3 898

Cracked! – Dom Hastings – 2017-07-20T17:00:20.247

That's genius... I was on the right track originally then! Thanks for the brain training! – Dom Hastings – 2017-07-20T18:06:23.330

3

Mascarpone, cracked by Ilmari Karonen

[ Make 'i' and 'z' print 'q' ]$
v ['q.]v* 'i<^
v ['q.]v* 'z<^

[ Disable some standard commands ]$
v[]v*   '1<^
v[]v*   '$<^
v[]v*   '@<^
v[]v*   '{<^
v[]v*   '}<^
v[<:]v* '<<^
v[]v*   'v<^$

Input is church numerals on stdio, using i for increment and z for zero. For instance, 2+3 would be:

iiziiiz

With a trailing newline

Output should be a number on stdout, in the same format as on stdio. For example, if the answer is five you should output:

iiiiiz

(mascarpone has no concept of numbers)


Intended solution:

: '[/''/'i/'./' /':/',/'>/'!/']/* 'i<^
: '[/':/',/'>/'!/']/* 'z<^
: ,>!
'z.

It is not immediately apparent from the documentation, but as @IlmariKaronen stated in his crack, string literals in Mascarpone are actually syntactic sugar for pushing a sequence of characters.

I deliberately wrote comments like [this]$ to make it look like I am pushing a string and popping it immediately afterwards. A naive cracker might have tried something like [:,>!]/* to push a string, swap it with the interpreter, and interpret it.

I also pretend to pop the interpreter I left on the stack with $, but $ has already been redefined to a NOP. You are left with this interpreter on the stack, and you have to carry it with you trough the entire program; trough each character of every string.

BlackCap

Posted 2017-07-18T23:57:26.807

Reputation: 3 576

Cracked. And no, I'd never heard of Mascarpone before this challenge. – Ilmari Karonen – 2017-07-25T22:14:10.760

@IlmariKaronen New favorite language? Good job! – BlackCap – 2017-07-25T23:16:23.600

3

Haskell, 161 144 bytes, Cracked by BlackCap

{-#OPTIONS_GHC -fth -w#-}
module M where

Input to STDIN, output to STDERR. Add to the end of the program.

Edit: Intended to be compiled with no extra GHC arguments, just the normal ghc --make prog.hs.

Edited again to lower the byte count.

Have fun!

zbw

Posted 2017-07-18T23:57:26.807

Reputation: 171

So I cannot do this, because the main function won't be called? main = do x <- readLn :: IO Integer; y <- readLn; print $ x + y – BlackCap – 2017-07-22T00:11:10.240

@BlackCap No, because GHC expects the main function to be in the module Main when no -main-is flag is provided. – zbw – 2017-07-22T17:18:23.750

This does not work, but I want to share the idea anyways – BlackCap – 2017-07-23T23:49:06.770

I'll call that cracked. Here was my intended solution, golfed down. It doesn't work on TIO, because the wrapper doesn't send the input to the compiler.

– zbw – 2017-07-24T01:54:28.877

If you post your solution, I'll mark it cracked. – zbw – 2017-07-24T01:55:20.753

Cracked! – BlackCap – 2017-07-24T10:06:13.757

2

C# (.NET Core) Cracked by Ilmari Karonen

Also cracked by Joshua.

namespace System
{
    class Console
    {
        static void Main()
        {
            //Your code goes here
        }
    }
}

Reads the two values from stdin and writes the result to stdout. Tested on Windows with Framework Version 3, 4.6 and on TIO.

Here is the full program I had intended.

namespace System
{
    class Console
    {
        static void Main()
        {
            var t = Reflection.Assembly.Load("mscorlib").GetType("System.Console");
            var r = t.GetMethod("ReadLine");
            int a = int.Parse((string)r.Invoke(null, null));
            int b = int.Parse((string)r.Invoke(null, null));
            var w = t.GetMethod("WriteLine", new[] { typeof(int) });
            w.Invoke(null, new object[] { a + b });
        }
    }
}

Try it online!

raznagul

Posted 2017-07-18T23:57:26.807

Reputation: 424

Cracked. – Ilmari Karonen – 2017-07-19T17:44:30.970

https://codegolf.stackexchange.com/a/133412/14306 I assume this wasn't the intended solution. – Joshua – 2017-07-19T17:54:54.847

@IlmariKaronen: +1. This was the intended solution. – raznagul – 2017-07-20T07:35:41.703

@Joshua: +1 for finding a different solution than I had intended. – raznagul – 2017-07-20T07:38:08.380

2

Java 8 (Cracked)

Second attempt. This time I invested two minutes of testing.

static {

    try {

        System.setIn(null);
        System.setOut(null);
        System.setErr(null);

        for (Method m : System.class.getMethods()) {

            m.setAccessible(false);

        }

        System.class.getMethod("getSecurityManager", new Class[0]).setAccessible(false);

        for (Method m : Class.class.getMethods()) {

            m.setAccessible(false);

        }

        SecurityManager mngr = new SecurityManager() {

            @Override
            public void checkPermission(Permission p) {

                if (p.getName().equals("createSecurityManager")) throw new SecurityException();
                if (p.getActions().startsWith("read")) throw new SecurityException();

            }

        };

        System.setSecurityManager(mngr);

        // Your code goes here.

    } catch (Throwable t) {

    }

}

Most things shouuuld be covered.

racer290

Posted 2017-07-18T23:57:26.807

Reputation: 1 043

1Would you please enclose this in a class with appropriate imports? It's the kind of challenge where this small changes can make or break an entry. I got several solutions for this one as is, but that reduces drastically if you simply enclose this in a class / interface. Also, format to remove all those while lines would be pretty nice for us, readers. – Olivier Grégoire – 2017-07-19T13:47:01.997

There, a cracked answer using exactly your code. And a +1 because it seems I forgot it. Sorry.

– Olivier Grégoire – 2017-07-19T15:23:21.320

The #setAccessible(false) calls do nothing. – Nevay – 2017-07-19T21:48:03.817

2

GolfScript, cracked by Dennis

{}' !$%&()*+,-./<=>?@[\]^`|~'':'*~;

Try it online!

This is a challenge, after all, so why not try GolfScript?

A valid solution should be a snippet that reads two integers off the stack, adds them together and returns the result on the stack. The catch is that it should still work even after the code above has redefined almost all of the built-in GolfScript operators to do abolutely nothing. At least I left ; untouched, so you can still pop values off the stack. ;-) Your code should work on the standard GolfScript interpreter, as implemented e.g. on TIO (see link above).


Dennis' solution, like my own, relies on the rarely used feature of GolfScript that allows interpolated Ruby code in double quoted strings. We use this feature to define a new addition operator that works exactly like the built-in + operator, and then call it.

(One reason why the Ruby interpolation feature in GolfScript is so rarely used is that, awkwardly, the interpolated Ruby code is executed during parsing, and its output is cached by the GolfScript interpreter. Thus, if you e.g. have a string with interpolated Ruby code in a loop, the code will run only once before the actual program starts and thereafter always return the same value on every iteration of the loop. You can work around that using string eval to defer parsing, but that makes the already awkward syntax even more ugly and verbose, and in any case, for this challenge I disabled the eval operator ~, too. However, it turns out that defining new built-in GolfScript operators is one thing this feature actually does quite nicely and cleanly.)

Ilmari Karonen

Posted 2017-07-18T23:57:26.807

Reputation: 19 513

Hint – CalculatorFeline – 2017-07-19T17:32:56.217

Cracked. Finally figured out what I was doing wrong. – Dennis – 2017-07-20T03:14:27.943

@Dennis: Yeah, you nailed it this time. FWIW, my intended solution was "#{var'_','gpush a+b'.cc2}";_, which works exactly like yours except for being a few bytes shorter.

– Ilmari Karonen – 2017-07-20T10:37:54.377

2

Node.js v8.2.0, Cracked by Dom Hastings

let mess = ctx => f => new Proxy (f, {
  has: (t, p) => p in t || p in ctx
, get: (t, p) => {
    let k = p in t? t[p]: ctx[p];

    if (k instanceof Function) return (
      function fetch (_k) {
        return mess (ctx) ( x => ( q => q instanceof Function
                                      ? fetch (q)
                                      : t (q)
                                  ) ( _k(x) )
                          )
      })(k);

    return k;
  }
});

with (mess (global) (x => x)) {
  dot   = f => a => b => f(a(b))
  ap    = f => g => x => f (x) (g (x))
  flip  = f => x => y => f (y) (x)
  Const = a => b => a
  id    = x => x
  num   = n => n (x => x + 1) (0)
  log   = console.log

  let x = flip (Const . id . id)
    , y = flip (Const . id . id . id)
  for (let i = 0; i < process.argv[2]; i++) x = ap (dot) (x)
  for (let i = 0; i < process.argv[3]; i++) y = ap (dot) (y)
  process.argv = [];

  logic = x => y => /* Your code here */;

  log . id . num ( logic (ap (dot) (x))
                         (f => z => (( y(flip (id) . id . flip (dot (id)) (f)) ) (Const (z))) (id) )
                 );
}

You are to implement the logic function. Input is the arguments provided (from stdin), output is whatever your function returns (is printed to stdout).


My code church encodes the numbers from the input. The rest of the code is just there to intimidate you.
The mess function does some trickery to implement point-free notation (a . b == dot (a) (b)), which I primarely use to add . id . to random places, which doesn't do anything, but will confuse anyone unfamiliar with functional programming.
The transformation applied to the numbers before I pass them to the logic function is x+1 and y-1, which adds up to 0, so it's another NOP to add to the obscurity.

The intended solution was:

logic = x => y => f => z => x (f) (y (f) (z))

BlackCap

Posted 2017-07-18T23:57:26.807

Reputation: 3 576

1Cracked! – Dom Hastings – 2017-07-20T17:36:04.530

@DomHastings That's not the intended solution, but I'm gonna say that you can, as long as the program halts without an exception, and doesn't print additional characters to the output – BlackCap – 2017-07-20T17:37:06.837

I've just posted an alternative! (You can see my previous solution in the history of that answer though!) – Dom Hastings – 2017-07-20T17:37:56.140

Oh wow, I was a way off... Still that's better than my first very cheaty attempt! Thanks for the puzzle! – Dom Hastings – 2017-07-20T17:43:31.103

2

Inform 7, cracked by ppperry

For reading a command: rule fails.

[Your code here.]

The input should be typed by the player as an interactive command, e.g. add 17 to 25 or sum 17 25. You're free to choose the exact form of the command that should be entered, as long as it includes two numbers. The sum of the numbers (e.g. 42) should be printed in response to the command.

The challenge, of course, is doing that while the entire "reading a command" activity is replaced by a no-op. There are probably several ways to solve this problem, but at least it should require some familiarity with the language. The one I came up with is actually quite simple, if a bit unexpected.

I've tested my solution in the GNOME Inform 7 IDE, version 6L38, on Ubuntu Linux. The intended solution works on both the Glulx and the Z-machine back-ends, and should work on other recent versions of Inform 7, too. Note that (without a suitable work-around) the code above will cause the interpreter to busy-loop when it tries to read a command; the Z-machine interpreter seems to become completely unresponsive when this happens, and can't be stopped from within the IDE, so I recommend using Glulx for testing.

Ilmari Karonen

Posted 2017-07-18T23:57:26.807

Reputation: 19 513

cracked, and in case you were wondering, I had never heard of inform before this challenge – pppery – 2017-07-21T22:30:35.053

2

CPython 3 (again), cracked by Sisyphus

import sys,os,functools
def p(f,e,a,_=os._exit):
 if e == "c_call":_(1)
sys.setprofile(p)

You can do anything you want -- as long as it isn't implemented in C. This means no print, no input -- all of those will hit the _(1) line and terminate. Input from STDIN with the numbers on two seperate lines, output to STDOUT. I wonder how long this is going to last ... Took me quite a while to find the second working snippet after coming up with this disabling trick. Explicitly specifying Cpython to avoid being cracked based non some alternative implementation of sys.setprofile.

pppery

Posted 2017-07-18T23:57:26.807

Reputation: 3 987

Cracked. I have very little idea why this works. – Sisyphus – 2017-07-22T06:24:59.887

I guess I can ask now: why functools? – Dennis – 2017-07-22T06:29:26.020

@Dennis Because sispyphus discovered a loophole, not the intended solution – pppery – 2017-07-22T12:14:45.530

@Sisyphus Your crack has been reported as a bug in python

– pppery – 2017-07-22T12:52:55.357

1

Jelly: CRACKED

This will be insanely easy compared to Wheat Wizard's awesome Python answer, but here we go :P

“for c in code_page:
 if c in atoms:atoms[c].call=None”ŒVø<insert code snippet here>

The sha256 hexdigest of my workaround solution, including the first snippet, is cfeb1e193ad77f66f039c0d6a792a3e4c311490f6412698e019ca1fae10c0e0a.

Note

You may not have any newlines in the code except for strings otherwise this code will not even be run, which defeats the purpose of this challenge.

Cracked by DJMcMayhem

To be fair, this uses a newline, so I'd like to see a solution that doesn't use a newline.

Also a solution by Jonathan Allan

This doesn't use a newline, so it's been cracked. :P

My solution is this:

“for c in code_page:
 if c in atoms:atoms[c].call=None”ŒVø“print(int(input())+int(input()))”ŒV

The first snippet only deletes single character atoms which means that Python eval still works :)))

HyperNeutrino

Posted 2017-07-18T23:57:26.807

Reputation: 26 575

The second snippet is always appended to the end of the first snippet. – Stephen – 2017-07-19T01:38:55.133

@StepHen Just specifying :P But I forgot to add the note; that's really important. – HyperNeutrino – 2017-07-19T01:42:20.820

3I don't think you can restrict the robbers like that. If you can crack it with Newlines, that's a valid crack. Is there anyway to prevent Newlines from being added, or forcing the first line to be executed? – James – 2017-07-19T01:49:13.107

@DJMcMayhem Based on the way Jelly works, newlines will just make more links and unless you call previous links, a newline appended will ignore everything before it. Is that fine, or should I delete this? There is theoretically a way involving modifying the source code of Jelly itself, but that's seriously a pain lol – HyperNeutrino – 2017-07-19T02:01:59.263

2https://codegolf.stackexchange.com/a/133213/31716 – James – 2017-07-19T02:49:21.923

@DJMcMayhem Okay :P (: – HyperNeutrino – 2017-07-19T15:46:49.407

1I like your intended crack. Very sneaky. – Dennis – 2017-07-20T03:21:29.593

1

Python 2 cracked

import sys,hashlib
c=open(__file__).read().split()[-1]
if c!='#'and hashlib.sha256(c).hexdigest()!='e6400dd63733d10ec042e3c28033cfa85e1d25fbef80020810c354d7c942e843':sys.exit() #

Try it online!

I'll preface this by saying this answer is a jerk move, intended as a lower-bound answer.


Inspired by Wheat Wizard's and HyperNeutrino's answers.

The snippet reads the source file and refuses to continue if the last whitespace-separated chunk of code does not sha256 into e6400dd63733d10ec042e3c28033cfa85e1d25fbef80020810c354d7c942e843.

EDIT: Edited slightly in response to this comment. The core problem does not change, any crack attempt is not invalidated.

TwiNight

Posted 2017-07-18T23:57:26.807

Reputation: 4 187

1RE the first snippet: This code is not allowed to crash or exit. – Stephen – 2017-07-19T02:19:22.817

This is invalid because it exits, which is not allowed for the first snippet. – James – 2017-07-19T02:40:05.490

1cracked – Dennis – 2017-07-19T02:48:08.730

1

Java, Cracked

import java.lang.reflect.*;
public class Main{
  public static void main(String... args){
    System.setOut(null);
    System.setErr(null);
    /*Your code here*/
  }
}

This should be was very easy to crack.

Intended solution

import java.lang.reflect.*;
public class Main{
public static void main(String... args){
  System.setOut(null);
  System.setErr(null);
  try{
    Class<?> cistream = Class.forName("java.io.InputStream");
    Class<?> cfostream = Class.forName("java.io.FileOutputStream");
    Class<?> costream = Class.forName("java.io.OutputStream");
    Class<?> cfdescriptor = Class.forName("java.io.FileDescriptor");
    Object sout = cfostream.getConstructor(cfdescriptor).newInstance(cfdescriptor.getField("out").get(null));
    Class<?> csys = Class.forName("java.lang.System");
    Field mod = Field.class.getDeclaredField("modifiers");
    mod.setAccessible(true);
    Field stdout = csys.getField("out");
    mod.set(stdout,Integer.class.cast(mod.get(stdout) )&~ Modifier.FINAL);
    stdout.set(null,Class.forName("java.io.PrintStream").getConstructor(costream).newInstance(sout));
    Class<?> cscanner = Class.forName("java.util.Scanner");
    Object scanner = cscanner.getConstructor(cistream).newInstance(System.in);
    Method nextInt = cscanner.getMethod("nextInt");
    int f = Integer.class.cast(nextInt.invoke(scanner));
    int s = Integer.class.cast(nextInt.invoke(scanner));
    int sum = s + f;
    System.out.println(sum);
  }catch(Throwable t){t.printStackTrace();}
  }
}

Try it online

Roman Gräf

Posted 2017-07-18T23:57:26.807

Reputation: 2 915

I think this is valid – Moira – 2017-07-19T09:17:50.893

I totally forgot about java.io.. But you got the intended solution anyways.. – Roman Gräf – 2017-07-19T09:35:50.310

I don't see any problem here. I actually wrote the second snipet just forgot to edit it on. According to TIO the first snipppet compiles without any warning.

– Roman Gräf – 2017-07-19T13:12:30.560

@OlivierGrégoire Done. I think any IDE will yell at me for this but I at least the compiler accepts it... – Roman Gräf – 2017-07-19T16:15:55.027

1

Java 8 Cracked by @OlivierGrégoire

I tried to make it as hard as possible! :) And, unlike the other Java answer so far, you'll have to follow the exact rules of the challenge, by placing it after this entire snippet (so no, you don't put your code in the public static void main(String[] args) method, you put it after the entire class. :) Good luck!

I've added comments to show what is being restricted.
(Inspired by this post, which is less restrictive and beatiable with the same approach I could use for my answer.)

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.io.FilePermission;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class Main {

  // Put everything in a static block so it is run before the static main method 
  // and any trailing (static) initializer-blocks:
  static {
    try {
      initializing();
    } catch (final Exception e) {
    }
  }

  static void initializing() throws Exception {
    // Overwrite System.out, System.err and System.in:
    System.setOut(new PrintStream(new ByteArrayOutputStream()));
    System.setErr(new PrintStream(new ByteArrayOutputStream()));
    System.setIn(new ByteArrayInputStream(new byte[0]));

    // Enable reflection for System.out, System.err and System.in:
    final Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    final Class<?> fdClass = java.io.FileDescriptor.class;
    final Field outField = fdClass.getDeclaredField("out");
    outField.setAccessible(true);
    modifiersField.setInt(outField, outField.getModifiers() & ~Modifier.FINAL);
    final Field errField = fdClass.getDeclaredField("err");
    errField.setAccessible(true);
    modifiersField.setInt(errField, errField.getModifiers() & ~Modifier.FINAL);
    final Field inField = fdClass.getDeclaredField("in");
    inField.setAccessible(true);
    modifiersField.setInt(inField, inField.getModifiers() & ~Modifier.FINAL);

    // Replace existing System.out FileDescriptor with a new (useless) one:
    outField.set(null, new FileDescriptor());
    // Replace existing System.err FileDescriptor with a new (useless) one:
    errField.set(null, new FileDescriptor());
    // Replace existing System.in FileDescriptor with a new (useless) one:
    inField.set(null, new FileDescriptor());

    // Disable reflection for System.out, System.err, System.in again:
    modifiersField.setInt(outField, outField.getModifiers() & ~Modifier.FINAL);
    modifiersField.setInt(errField, errField.getModifiers() & ~Modifier.FINAL);
    modifiersField.setInt(inField, inField.getModifiers() & ~Modifier.FINAL);
    inField.setAccessible(false);
    errField.setAccessible(false);
    outField.setAccessible(false);
    modifiersField.setAccessible(false);

    // Overwrite the SecurityManager:
    System.setSecurityManager(new SecurityManager() {

      private boolean exitAllowed = false;

      @Override
      public void checkExec(final String cmd) {
        throw new SecurityException();
      }

      @Override
      public void checkPermission(final java.security.Permission perm) {
        final String name = perm.getName();
        // You're not allowed to read/write files:
        if (name.equals("setIO") || name.equals("writeFileDescriptor")
            || name.equals("readFileDescriptor")
            || ((perm instanceof FilePermission) && name.startsWith("/proc/self/fd/"))) {
          throw new SecurityException();
        }
        // You're not allowed to overwrite the Security settings:
        if (name.equals("setSecurityManager") || name.equals("suppressAccessChecks")) {
          throw new SecurityException();
        }
        // You're not allowed to use reflection anymore:
        if (name.equals("getModifiers") || name.equals("get") || name.equals("set")
            || name.equals("setBoolean") || name.equals("setByte")
            || name.equals("setChar") || name.equals("setShort") || name.equals("setInt")
            || name.equals("setLong") || name.equals("setFloat") || name.equals("setDouble")
            || name.equals("setFieldAccessor") || name.equals("setFieldAccessor")) {
          throw new SecurityException();
        }
        // When you try to leave the current VM it will stop the program:
        if (name.startsWith("exitVM") && !this.exitAllowed) {
          this.exitAllowed = true;
          System.exit(0);
        }

        // You know what, nothing is allowed!
        throw new SecurityException("Mhuahahahaha!");
      }
    });
  }

  public static void main(String[] args) {
    // Overwritting all given arguments:
    args = new String[0];

    // Exit the program before you can do anything!
    System.exit(0);
  }
}

// Your code goes below:

Try it here. (ideone.com instead of TIO, since it doesn't seem to work there.. Testing has been done in the Eclipse IDE, but my intended solution does work if you use ideone.com)

Kevin Cruijssen

Posted 2017-07-18T23:57:26.807

Reputation: 67 575

1Cracked! – Olivier Grégoire – 2017-07-19T14:11:34.203

1

JavaScript, Cracked

Input: prompt() twice

Output: console.log()

My solution does not work in jsfiddle. Works on the about:blank page with Google chrome's JS console.

prompt=console=0

My solution:

x=document.createElement("iframe")
x.src="data:text/html,<script>console.log(prompt()-0+(prompt()-0))</script>"
document.body.appendChild(x)

Explanation:

I removed prompt and console by setting them equal to 0.

In my solution I create an iframe, which creates a sandbox, and a new instance of window where prompt and console work properly.

Grant Davis

Posted 2017-07-18T23:57:26.807

Reputation: 693

1Cracked? – Ilmari Karonen – 2017-07-19T15:49:14.830

@CRDrost I don't believe there is primality testing in the spec, and you don't show both snippets. – Stephen – 2017-07-19T21:21:15.263

Sorry, you're right, I misread. – CR Drost – 2017-07-19T21:45:46.917

1

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!

James

Posted 2017-07-18T23:57:26.807

Reputation: 54 537

^Zread a;read b; echo $((a+b)) – Joshua – 2017-07-19T18:13:25.777

@Joshua isn't + disabled though? – Skidsdev – 2017-07-19T18:19:49.140

@joshua I don't think exiting vim and doing it in bash counts as cracking a vim answer. – James – 2017-07-19T18:24:17.823

@DJMcMayhem Cracked?

– ბიმო – 2017-07-19T18:55:48.583

1

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!

James

Posted 2017-07-18T23:57:26.807

Reputation: 54 537

Cracked. – ბიმო – 2017-07-19T20:43:30.220

It seems to me that yours is quite different from mine (keystrokes-wise). Would you mind including your solution, I'm very curioius? – ბიმო – 2017-07-20T16:36:28.487

1

Ruby (cracked by Dennis)

END{exit 0}

Input through STDIN, output through exit code. Example:

 $ ruby mostly_unusable.rb
3
4
 $ echo $?
7

histocrat

Posted 2017-07-18T23:57:26.807

Reputation: 20 600

cracked – Dennis – 2017-07-19T22:15:14.183

1

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

pppery

Posted 2017-07-18T23:57:26.807

Reputation: 3 987

As is, this is just a syntax error. for needs to go on its own line. – Dennis – 2017-07-20T03:18:21.023

Didn't delroth write a blog post about this one? – Kevin – 2017-07-20T06:20:28.007

@Dennis fixed. I don't know how I managed to miss that – pppery – 2017-07-20T12:19:29.320

Cracked – Arnold Palmer – 2017-07-20T18:47:47.317

1

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.

Olivier Grégoire

Posted 2017-07-18T23:57:26.807

Reputation: 10 647

You had to go and specify the input method, didn't you? Gah!

– Ilmari Karonen – 2017-07-20T15:34:24.063

@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. ;) – Olivier Grégoire – 2017-07-20T15:36:49.720

@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! ;)

– Olivier Grégoire – 2017-07-20T15:53:34.347

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.

– Ilmari Karonen – 2017-07-20T15:56:27.217

@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. – Olivier Grégoire – 2017-07-20T16:06:29.213

1

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

Rohan Jhunjhunwala

Posted 2017-07-18T23:57:26.807

Reputation: 2 569

Does the code end with a trailing newline? – pppery – 2017-07-22T12:30:42.980

no @pperry it does not – Rohan Jhunjhunwala – 2017-07-22T20:31:04.837

I think this counts as a crack, then – pppery – 2017-07-22T21:10:44.717

@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 – Rohan Jhunjhunwala – 2017-07-23T03:43:29.340

1

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 ;)

Olivier Grégoire

Posted 2017-07-18T23:57:26.807

Reputation: 10 647

You found a crack, an oversight from me, but not the answer: that is a platform dependant answer, which is explicitly forbidden. – Olivier Grégoire – 2017-07-20T22:20:06.997

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.

– Olivier Grégoire – 2017-07-20T22:28:00.047

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." :( – Ilmari Karonen – 2017-07-20T23:34:33.473

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? – Ilmari Karonen – 2017-07-21T00:00:56.147

@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.

– Olivier Grégoire – 2017-07-21T09:54:15.660

OK, how's this for a crack, then?

– Ilmari Karonen – 2017-07-21T10:45:42.380

1

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.

pppery

Posted 2017-07-18T23:57:26.807

Reputation: 3 987

2Cracked! – James – 2017-07-20T19:55:22.573

I never knew that function even existed ... (although I did expect this one to be cracked fairly quickly) – pppery – 2017-07-20T20:06:38.760

1

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 ...

pppery

Posted 2017-07-18T23:57:26.807

Reputation: 3 987

cracked – Dennis – 2017-07-21T06:46:11.227

1

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

pppery

Posted 2017-07-18T23:57:26.807

Reputation: 3 987

Cracked. – Veedrac – 2017-07-31T01:34:39.693

@Veedrac Ready for the next stage?

– pppery – 2017-07-31T01:50:56.573

0

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.

racer290

Posted 2017-07-18T23:57:26.807

Reputation: 1 043

You don't show the code to execute, and you don't show that the whole code you execute produces nothing. – Olivier Grégoire – 2017-07-19T13:09:12.867

Well, as I stated above, it's not really more than a guess. – racer290 – 2017-07-19T13:18:07.417

Also, cracked!

– Olivier Grégoire – 2017-07-19T13:18:26.797

Well, that was not inteded. – racer290 – 2017-07-19T13:20:44.697

May I edit my answer to fix it or will I have to open a new one? – racer290 – 2017-07-19T13:21:15.643

I'm afraid that's a new one... Also, make sure to make a complete class, not only a main method and friends. And take my first comment in account: add a code that must run correctly without your block and incorrectly, but produce nothing with your block. – Olivier Grégoire – 2017-07-19T13:21:37.677

@racer290 I'm liking this challenge more and more, as people make complicated ways to block I/O and addition and others are like "well... I can just do that, and it works." – Stephen – 2017-07-19T13:22:12.660

0

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.

Poke

Posted 2017-07-18T23:57:26.807

Reputation: 3 075

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. :/ – Ilmari Karonen – 2017-07-20T01:42:51.283

@IlmariKaronen You had the correct output method but you did input in a clever manner that I actually like better :] Nice job – Poke – 2017-07-20T04:21:02.493

0

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.

Mega Man

Posted 2017-07-18T23:57:26.807

Reputation: 1 379

1Cracked! – Sisyphus – 2017-07-23T10:12:21.363

0

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?

pppery

Posted 2017-07-18T23:57:26.807

Reputation: 3 987

Sorry. – Veedrac – 2017-07-31T01:58:11.323

@Veedrac and fixed yet again I'm tired of all these double-underscore loopholes.

– pppery – 2017-07-31T02:03:49.023

0

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)

pppery

Posted 2017-07-18T23:57:26.807

Reputation: 3 987

Cracked. – Veedrac – 2017-07-31T02:52:55.360

0

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 ...

pppery

Posted 2017-07-18T23:57:26.807

Reputation: 3 987

Is someone going to crack this? – pppery – 2017-08-05T12:42:12.030