Niech twój język * w większości * będzie bezużyteczny! (Wątek gliniarzy)


61

Zainspirowany tym komentarzem ...

Dziękujemy użytkownikom Step Hen , Wheat-Wizard i Dennis za pomoc w ugruntowaniu specyfikacji tego wyzwania przed jego opublikowaniem!

To jest wątek gliniarzy. Przejdź do wątku Rabusiów tutaj


W tym wyzwaniu masz za zadanie uruchomić kod, który sprawi, że Twój język nie będzie spełniał naszych kryteriów bycia językiem programowania. W tym wyzwaniu oznacza to, że język nie może już ...

  • Weź numeryczne dane wejściowe i wyjściowe

  • Dodaj dwie liczby razem

  • Sprawdź, czy określona liczba jest liczbą pierwszą, czy nie.

Jest to wyzwanie dla , w którym istnieją dwa różne wyzwania o dwóch różnych celach: gliniarze spróbują napisać kod, który sprawi, że język będzie w większości bezużyteczny, a złodzieje spróbują znaleźć ukryte obejście, które pozwala glinom odzyskać swój język.

Jako policjant musisz napisać dwa fragmenty kodu:

  1. Taki, który sprawia, że ​​twój język jest w większości bezużyteczny, np. Poprzez usunięcie wbudowanych funkcji do pobierania danych wejściowych / wyjściowych i operacji numerycznych. Im więcej funkcji usuniesz, tym lepiej. Ten kod nie może ulec awarii ani wyjść. Powinno być możliwe dodanie kodu na końcu tego fragmentu, a ten kod zostanie poddany ocenie . I...

  2. ... fragment kodu, który przyjmuje dwie nieujemne liczby całkowite jako dane wejściowe, dodaje je do siebie i generuje ich sumę. Ten fragment kodu musi nadal poprawnie działać, nawet po uruchomieniu pierwszego fragmentu kodu. Gdy oba fragmenty zostaną połączone razem, muszą one utworzyć pełny program, który dodaje dwie liczby lub zdefiniować funkcję, która dodaje dwie liczby. W idealnym przypadku ten fragment kodu powinien polegać na bardzo niejasnym zachowaniu, aby był trudniejszy do znalezienia.

Możesz wybrać dowolną standardową metodę wejścia i wyjścia . Musisz jednak ujawnić dokładnie, jakiego formatu (wejścia i wyjścia) używasz. Rabuś nie może złamać twojej odpowiedzi, chyba że użyje tego samego formatu co ty.

Po napisaniu obu tych fragmentów musisz opublikować pierwszy jako odpowiedź, nie ujawniając drugiego. Twoja odpowiedź powinna zawierać wszystkie następujące informacje:

  • Pierwszy fragment (oczywiście nie sekundę).

  • Język (w tym niewielka wersja, ponieważ większość zgłoszeń prawdopodobnie będzie polegać na dziwnych przypadkowych przypadkach)

  • Format IO, w tym czy jest to funkcja czy pełny program. Rabusie muszą używać tego samego formatu, aby ich crack mógł być ważny.

  • Wszelkie dziwne przypadki krawędzi wymagane do odpowiedzi. Na przykład działa tylko na systemie Linux lub wymaga połączenia z Internetem . Oczywiście jest to nieco subiektywne, ale jeśli policjant ma jakiś skrajny przypadek, który zapobiega jego pękaniu, a następnie ujawnia to dopiero po bezpieczeństwie, uważam to za słabe sportowe. Potencjalny złodziej powinien mieć wszystkie informacje niezbędne do złamania odpowiedzi, zanim zostanie ona złamana.

Nie musisz ujawniać liczby bajtów, dopóki odpowiedź nie będzie bezpieczna.

Oto przykład. W przypadku pierwszego fragmentu kodu możesz przesłać następujący program w języku Python 3:

Python 3

print=None

Pobiera dane wejściowe ze STDIN i dane wyjściowe do STDOUT

A jako drugi fragment możesz napisać:

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

Jest to ważne, ponieważ weźmie dwie liczby jako dane wejściowe i wyświetli ich sumę, nawet jeśli połączysz oba fragmenty razem, np.

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

Jednak złodziejowi będzie bardzo łatwo znaleźć rozwiązanie. Ponieważ byłoby to bardzo łatwe do złamania, możesz spróbować załatać to konkretne podejście w następujący sposób:

import sys
sys.stdout=None
print=None

Jednak nawet to ma bardzo łatwe obejście:

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

Jako policjant Twoim celem jest uczynienie ukrytego obejścia tak niejasnym, jak to możliwe, aby uniemożliwić złodziejom znalezienie go.

W rabusie będą patrzeć na jednej z odpowiedzi, i próbować go złamać. Mogą go złamać, pisząc dowolny prawidłowy fragment, który mógłby działać jako fragment 2 (dodanie dwóch liczb razem po tym, jak język stał się w większości bezużyteczny). To nie musi być ten sam fragment, jak pierwotnie zamierzałeś. Jeśli złodziej złamie twoją odpowiedź, pozostawi komentarz do twojej odpowiedzi, a następnie powinieneś ją edytować, aby wskazać, że została złamana. Jeśli Twój post jest pęknięty, edytuj swoją odpowiedź, aby pokazać rozwiązanie (fragment 2), które pierwotnie zamierzałeś. Nie jest to reguła sama w sobie , tylko przyjazna sugestia, aby gra była przyjemna. Nie musisz.

Jeśli przez cały tydzień odpowiedź pozostanie nieprzetarta, możesz edytować w drugim fragmencie i wskazać, że Twoja odpowiedź jest teraz bezpieczna . Jeśli nie edytujesz go po upływie tygodnia, inni użytkownicy mogą go złamać, dopóki tego nie zrobisz. Jeśli nie ujawnisz swojego drugiego fragmentu, nie możesz zdobyć punktów za odpowiedź lub nazwać go bezpiecznym.

Zwycięzca wątku gliniarzy jest najkrótszą bezpieczną odpowiedzią obejmującą oba fragmenty , liczone w bajtach, i ta odpowiedź zostanie zaakceptowana po upływie wystarczającego czasu. Zdajesz nie musisz ujawniać swój licznik bajtów aż twoja odpowiedź jest bezpieczne, ponieważ liczba bajtów ma znaczenia swój wynik aż twoja odpowiedź jest bezpieczny. W przypadku, gdy upłynie wystarczający czas i żadne odpowiedzi nie pozostaną bez krakowania, zwycięzcą zostanie odpowiedź, która pozostanie bez krakowania przez najdłuższy okres czasu.

Baw się dobrze!

Wyjaśnienia zasad

  • Pierwszy fragment kodu musi działać poprawnie bez żadnych danych wejściowych . Może wyświetlać cokolwiek zechcesz, a dane wyjściowe będą ignorowane - tak długo jak snippet zostanie zrobiony, drugi fragment działa poprawnie.

  • Drugi fragment musi zostać faktycznie wykonany, aby odpowiedź była poprawna. Oznacza to odpowiedź typu

    import sys
    sys.exit()
    

    nie jest poprawny, ponieważ nie łamie języka. Po prostu odchodzi. Podobnie, wprowadzenie nieskończonej pętli jest nieprawidłowe, ponieważ drugi fragment kodu nigdy nie zostanie wykonany.

  • Po zapewnieniu bezpieczeństwa twój wynik jest liczbą bajtów obu fragmentów .

  • Wróćmy do Proszę ujawnić wszelkie dziwne przypadki brzegowe wymagane do odpowiedzi na twoje pytanie ... Twoje zgłoszenie musi zawierać wystarczającą ilość informacji, zanim zostanie ujawnione, aby było odtwarzalne po ujawnieniu. Oznacza to, że jeśli Twoja odpowiedź stanie się bezpieczna, a następnie edytujesz: Oto moja odpowiedź. O tak, BTW to działa tylko wtedy, gdy uruchomisz go na Solarisie, żart jest z ciebie! Twoja odpowiedź jest nieprawidłowa i zostanie usunięta i nie zostanie uznana za kwalifikującą się do wygrania.

  • Drugi fragment kodu może ulec awarii po wypisaniu sumy - dopóki dane wyjściowe są nadal poprawne (na przykład, jeśli zdecydujesz się wyprowadzić dane do STDERR, a następnie otrzymasz kilka informacji o awarii, jest to nieprawidłowe).

  • Nie możesz edytować swojego kodu po przesłaniu odpowiedzi.

  • Nie możesz polegać na funkcjach kryptograficznych, takich jak szyfrowanie, funkcje skrótu, CSPRNG itp.

Urywek, aby znaleźć nieskradzione zgłoszenia:


3
Co należy zrobić dla języków takich jak C? Łączenie pozwala tylko na jeden „główny fragment” i każda logika będzie musiała tam przejść. Na przykład, jeśli mam int main(){ do_evil_stuff(); }gdzie powinien iść kod użytkownika? W funkcji? Po wszystkich oświadczeniach w main?
Conor O'Brien

1
Czy drugi fragment można umieścić w dowolnym miejscu pierwszego fragmentu?
LegionMammal978

1
Nic nie wiem o kodowaniu, ale to wyzwanie wygląda niesamowicie
Pritt Balagopal,

2
Edytowałem w niesamowitym fragmencie jimmy23013 . Zapraszam do wycofania się, ale i tak wykorzystałem go do znalezienia zgłoszeń i pomyślałem, że może to pomóc innym.
Dom Hastings,

2
@DomHastings To bardzo pomocne! Dziękuję bardzo :)
DJMcMayhem

Odpowiedzi:


2

Gforth 0.7.3 (TIO) , 231 bajtów [BEZPIECZNY]

Ten kod redefiniuje jako bezużyteczne niektóre niezbędne metody wyjściowe, a także dodawanie i coś kluczowego dla deklarowania funkcji. Powodzenia!

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

Wejściami będą dwie podpisane liczby całkowite pobrane z góry stosu jako parametry funkcji. Wyjście do STDOUT.

Powinieneś więc naprawić zadane obrażenia i zdefiniować funkcję, która pobiera dwie najwyższe wartości ze stosu i wypisuje wynik jako liczbę całkowitą (nie zmiennoprzecinkową) do STDOUT bez dodatkowego wyjścia (brak spacji końcowej).

Oto szablon , jeśli twoja funkcja celu ma nazwę f.

Rozwiązanie:

79 bajtów

Właściwie usunąłem immediatesłowo kluczowe z końca redefinicji ;, więc odpowiedź była niezbędna, aby uwzględnić je na początku. Funkcja, którą zdefiniowałem, jest w większości równoważna z wewnętrzną definicją ., ale nie drukuje spacji na końcu, a dodawanie odbywa się jako pierwsze, poprzez przeniesienie liczb na stos zmiennoprzecinkowy iz powrotem.

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

Wypróbuj online


1
To bardzo miła odpowiedź. Przy takim tempie wygląda na to, że może to być jedyna nie spakowana odpowiedź!
DJMcMayhem

:) Połączyłem kilka różnych przeszkód. W tym momencie zastanawiam się, czy mógłbym zrobić tylko jeden, aby poprawić mój wynik. Ale możliwe jest, że posiadanie więcej niż jednego jest powodem, dla którego nie zostało jeszcze spakowane.
mbomb007

21

Haskell, złamany przez Christiana Sieversa

import Prelude(getLine,print)
a=a

Pełny program, odczytywanie dwóch liczb całkowitych (w tym ujemnych) ze standardowego wejścia i pisanie na standardowe wyjście.

Właśnie wyłączyłem Preludium, więc prawie nic nie wchodzi w zakres, a potem dodałem definicję; dalsze importy są niepoprawne pod względem składniowym. Dałem ci getLinei printchociaż.


Edytowano, aby dodać moje oryginalne rozwiązanie. Crack Christiana był inny, ale wykorzystuje te same podstawowe funkcje (można uzyskać zaskakującą ilość obliczeń, uzyskując dostęp do funkcji, które mają cukier syntaktyczny, nawet jeśli nie można wywołać bezpośrednio żadnego wbudowanego elementu ani nawet nazwać zaangażowanych typów).

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

Co i tak prawdopodobnie nie jest super-golfem, ale tutaj jest bardziej czytelne:

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)


17

Python 2 , Cracked

Implementuje dodawanie jako nazwaną funkcję

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\

Wypróbuj online!

Co to robi?

Aby ci pomóc, wyjaśnię, co to robi. Ten kod otwiera plik źródłowy i sprawdza, czy pozostała część kodu spełnia następujące kryteria:

  • Nie zawiera ciągu import
  • Składa się wyłącznie z postaci &)(,.:[]a`cdfijmonrt~

Jeśli nie spełni którekolwiek z kryteriów, limit rekurencji zostanie ustawiony tak, 1że każdy napisany kod osiągnie limit rekurencji.

Nie ma tu żadnych sztuczek, napisałem rozwiązanie, które używa tylko tych znaków i nie importuje, nie robię nic wywrotowego, ale powiem, że myślę, że będzie to dość trudne do złamania.

Aby zaoszczędzić trochę czasu, oto krótka lista przydatnych rzeczy, których nie możesz zrobić z tym ograniczeniem

  • + no cóż,

  • eval/ execNie pozwoliłbym ci tego uciec

  • Liczby, mogą być bardziej przydatne niż myślisz

  • Literały łańcuchowe

  • len

  • =, Brak przypisywania zmiennych

  • >, <, ==. . . Nie zostawiłem cię bez porównań

  • *, -, /, %, ^, |, >>, << Jedyne operatory dostępne są ~i&

  • __foo__, Żadna z tych fantazyjnych metod podwójnego podkreślenia nie jest dozwolona.


1
Wow, to jest całkiem złe. Miły!
HyperNeutrino,

Fantastyczna odpowiedź na rozpoczęcie :)
DJMcMayhem

Hehe, to mogło być zainspirowane tym głupim wyzwaniem króla wzgórza, które próbowałem sprecyzować na czacie
Stephen

4
Myślę, że to jest poprawny crack: codegolf.stackexchange.com/a/133209/68942
HyperNeutrino

RE pierwszy fragment: This code is not allowed to crash or exit.(patrz czat w celu dyskusji na jego temat)
Stephen

12

Python 2 , Cracked

To czwarta iteracja tej odpowiedzi. Każda z ostatnich odpowiedzi została złamana poprzez zresetowanie głębokości rekurencji.

Implementuje dodawanie jako nazwaną funkcję

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\

Wypróbuj online!

Co to robi?

Aby ci pomóc, wyjaśnię, co to robi. Ten kod otwiera plik źródłowy i sprawdza, czy pozostała część kodu składa się wyłącznie ze znaków &)(,.:[]a`cdfijmonrt~

Jeśli się nie powiedzie, limit rekurencji jest ustawiony tak, 1że każdy napisany kod osiągnie limit rekurencji.

Wyłączyłem również wszystkie moduły, więc nie możesz niczego importować.

Nie ma tu żadnych sztuczek, napisałem rozwiązanie, które używa tylko tych znaków i nie importuje, nie robię nic wywrotowego, ale powiem, że myślę, że będzie to dość trudne do złamania.

Aby zaoszczędzić trochę czasu, oto krótka lista przydatnych rzeczy, których nie możesz zrobić z tym ograniczeniem

  • + no cóż,

  • eval/ execNie pozwoliłbym ci tego uciec

  • Liczby, mogą być bardziej przydatne niż myślisz

  • Literały łańcuchowe

  • len

  • =, Brak przypisywania zmiennych

  • >, <, ==. . . Nie zostawiłem cię bez porównań

  • *, -, /, %, ^, |, >>, << Jedyne operatory dostępne są ~i&

  • __foo__, Żadna z tych fantazyjnych metod podwójnego podkreślenia nie jest dozwolona.

Moje rozwiązanie

Teraz, gdy xnor złamał go w sposób, z którego jestem wystarczająco zadowolony, ujawnię swoje rozwiązanie

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

Niespodzianka, niespodzianka to ogromna kupa bełkotu. Zamiast tego zepsuć, zamierzam przejść przez proces, w jaki sposób to zrobiłem.

Zacząłem od całkiem standardowego algorytmu dodawania

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

Następnie użyłem bitowe trik do reprezentowania ^z |, &, ~.

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

Użyłem innej bitowej sztuczki, aby się pozbyć |

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

Teraz pozostało tylko <<, nie powinno być zbyt trudne, prawda? Przygotuj się na wyboistą jazdę. Aby zastąpić przesunięcie bitów, użyłem ciągów, aby dodać zero na końcu jego reprezentacji binarnej

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

Ma to kilka problemów, ale podstawowy korzysta z dodawania , więc obejrzałem to, używając zamiast tego formatu

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

Nie wolno nam używać bin, więc użyłem formatowania ciągów do konwersji na binarną.

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

Ponieważ dosłowne ciągi znaków są zabronione, muszę zbudować ciąg {0:b}0z części wykonanych za pomocą tyknięć i joinrazem.

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

Pusty ciąg jest dość łatwy, możesz po prostu zrobić

`r`[:0]

Zera były

`0`

i {:}wszystkie zostały zabrane ze słowników.

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

bwydaje się dość trudne, nie ma go w naszym zestawie znaków, więc jak mamy uzyskać obiekt, który ma bw sobie repr? Oto, jak: Kiedy używasz reprwbudowanej funkcji, dostajesz coś, co wygląda

<built-in function name>

I skąd weźmiemy nasze 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

Teraz pozostały tylko liczby, potrzebuję tylko -1, 0, 1 i 2, więc oto jak je przedstawiłem:

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

2 może być o bajt krótszy niż

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

w oparciu o sugestie @ Blender w komentarzach, ale nie pomyślałem o tym aż po fakcie.

Więc podstawiamy te liczby w

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

I to jest crack.


Ten fragment wydaje się sam w sobie błędny.
ATaco,

@ATaco Wierzę, że zostało to omówione na czacie i zdecydowano, że było w porządku.
Wheat Wizard

Reguły wyraźnie stanowią inaczej. „Ten kod nie może ulec awarii ani wyjść.”
ATaco,

@ATaco Oto wiadomość, którą powiedział, że zaktualizuje ją, kiedy będzie miał okazję.
Wheat Wizard


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
}

Wypróbuj online!

Wejście ze STDIN i wyjście do STDOUT.

Działa to bezbłędnie. Hahaha, to jest całkiem złe. Testowałem to tylko na gcc TIO. Zazwyczaj musisz dodać swój kod po tym fragmencie, aby zadziałał :) Komentarz jest złośliwy, nie słuchaj go.

Testowane na gcc (GCC) 6.3.1 20161221 (Red Hat 6.3.1-1) . Powinien działać na każdym systemie Linux.

Oryginalne rozwiązanie

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

@ LegionMammal978 Ah tak
Conor O'Brien

2
Określ swoją platformę!
Joshua

@Joshua Dodałem trochę informacji
Conor O'Brien


No __asm__i masz mnóstwo funkcji do wyboru :) nie myśl, że C i C ++ są tutaj dobrymi wrogami.
edmz

9

Haskell , złamany przez Bena

main=main--

Wypróbuj online! Powinien to być pełny program odczytujący dwie liczby ze standardowego wyjścia i wysyłający sumę do standardowego wyjścia.

Każdy pełny program zaczyna się od uruchomienia mainfunkcji, ale tutaj mainwywołuje się i powoduje nieskończoną pętlę. Co gorsza, komentarz liniowy rozpoczyna się --bezpośrednio za wywołaniem rekurencyjnym, aby zapobiec zmianie go na np. main2A następnie zdefiniowaniu, aby wykonać sumowanie.


Zamierzone rozwiązanie:

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

Wypróbuj online!

--rozpoczyna komentarz linii, chyba że można go również przeanalizować jako część operatora. (Podświetlanie składni wydaje się być nieświadome tego faktu.) --$Jest poprawnym operatorem poprawki, który przyjmuje mainjako pierwszy argument i jakiś fałszywy drugi argument (). Następnie definiuje się, aby zignorować oba argumenty i zamiast tego wykonać wymagane zadanie.



5
możesz po prostu dodać „where main = ...”
michi7x7

+1 za rozwiązanie Haskell, które działa tylko z powodu leniwej oceny Haskell.
Jules

9

C (GCC w systemie Linux) (pęknięty)

Zamiast głupich technik odczytu plików, robimy to we właściwy sposób - z białą listą SECCOMP!

Twoje zadanie: zaimplementuj dodawanie z wejściem STDIN i wyjściem do 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!
}

Wypróbuj online!

Co to do cholery jest!?

Aby pomóc ci w twoim niezwyciężonym zadaniu, wyjaśnię, co robi ten kod.

__attribute__ ((constructor(0)))zapewnia, że sfunkcja zostanie uruchomiona jako pierwsza. Funkcja zamyka wszystkie otwarte deskryptory plików dla STDIN, STDOUT i STDERR. Następnie program ogranicza się do ścisłej białej listy SECCOMP, która ogranicza wywołania systemowe do:

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

Dlatego nie możesz otwierać żadnych nowych plików (ani w zasadzie nic robić). Następnie przechodzimy do main i wywołujemy Twój kod, ładnie zawinięty w sandboxfunkcję.

Na syscall(SYS_exit, EXIT_SUCCESS);końcu jest po prostu zapewnienie, że program exit_group(2)zamknie się poprawnie - domyślnie GCC zakończy działanie, z którym nie jest dozwolona biała lista SECCOMP. Ta funkcja wyjścia jest wywoływana po uruchomieniu kodu.

Więc nie masz otwartych deskryptorów plików i nie możesz otworzyć niczego nowego. Niemożliwe, prawda? ;)



8

16-bitowy tryb rzeczywisty x86, montaż ( pęknięty )

_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

Łatwo, jeśli znasz sztuczkę.


1
Jak bierzesz wkład? Na stosie, czy w rejestrach? (Poza tym wygląda na to, że ma to być 16-bitowy zestaw, ale jeśli tak, or [bp], 256to jest nieprawidłowy. Czy to tak or WORD PTR [bp], 256?)
Cody Gray

1
Ponadto powinieneś określić, którego procesora używasz; istnieje wiele wersji x86 i klonów oraz wiele niezdefiniowanych instrukcji. Gdybym napisał kod dla „niejasnego klonu 80186”, tak się złożyło, że miałam niezdefiniowaną instrukcję, która wymagała kilku argumentów i bla bla bla ... Możemy również potrzebować środowiska. 16-bitowy system Windows dał SS == DS gwarancję, że na przykład inne systemy mogą tego nie zrobić.
Orion,

1
Wystarczy tylko podać która procesora, jeśli rzeczywiście za pomocą jakiś trik, który działa tylko na jednym konkretnym modelu (lub jednej konkretnej generacji). Ten kod nie jest taki, więc myślę, że „x86-16” jest wystarczające. Moim zdaniem im bardziej ogólny, tym lepiej. Uzgodniono, że należy określić tryb rzeczywisty lub chroniony, chociaż obecność hltinstrukcji (pierścień 0) zdecydowanie sugeruje, że nie jest to tryb chroniony.
Cody Gray

3
@Joshua, jeśli to nie działa na każdej platformie, musisz przynajmniej określić platformę, na której będzie działać. Your submission must contain enough information before being revealed to be reproducible after being revealed
Stephen

1
@StepHen: Rozwiązaniem do rozerwania języka jest agnostyk platformy po określeniu trybu rzeczywistego x86-16, ale operacje we / wy nie są agnostyczne dla platformy. Ten, kto go wybucha, może określić system operacyjny, dla którego się wybił. Późno dodałem etykietę _main, aby ktoś mógł teoretycznie zrobić prawie agnostyczną przerwę, łącząc się z libc.
Joshua

4

JavaScript, pęknięty

Wyzwanie to opiera się na rozwiązaniu Granta Davisa , ale naprawia rozwiązanie, które miał na myśli (które tworzy iframe i korzysta z iframe window). Rozwiązanie działa w konsoli javascript na chrome about:blank pagei zajmuje dwa input()s, dodaje je do siebie i console.logjest wynikiem. Wpisz swój kod po:

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

Po pierwsze, sprać prompti consoleoraz ustawić skrót d. Następnie tworzymy obserwatora mutacji z wywołaniem zwrotnym, który usuwa każdy zmutowany cel. Stawiamy, że mutacja obserwator obserwować dokument, a następnie powiadomić o childListi subtreemodyfikacje. Zamiast literału trueużywamy skrótu do prawdziwej wartości document( specyfikacja na to nie pozwala, ale chrome to robi).

Po tym, jak to opublikowałem, zdałem sobie sprawę z dużo bardziej eleganckiego clobbera. Moje zamierzone rozwiązanie nadal działa, ale opublikowany crack nie:

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

Witamy na stronie! Chcę zobaczyć, jakie będzie rozwiązanie :)
DJMcMayhem


4

Perl 5, złamany przez 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__

Dane wejściowe są odbierane w osobnych wierszach, STDINa dane wyjściowe są drukowane STDOUT.

Cały kod podąża za __DATA__znacznikiem. Wykorzystuje metodę podobną do rozwiązania @ WheatWizard, polegającą na tym, że kod jest analizowany, a niepotrzebne znaki są usuwane.

Zostało to przetestowane na wersjach 5.8, 5.10 i 5.16 i nie wymaga żadnych flag wiersza poleceń.

Wypróbuj online!


2
Czy możesz podać metodę i format wejścia / wyjścia?
Ilmari Karonen,

@IlmariKaronen Przeprosiny, to STDINznaki z osobnymi wierszami i STDOUT. Dodam to do głównego ciała.
Dom Hastings,


4

Python 3, cracked przez zbw

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

Wszystkie moduły zostały usunięte, co oznacza, że ​​nie ma żadnych wbudowanych funkcji i niewiele można zrobić. Wyjście do STDOUT, wejście z STDIN. Jest to druga iteracja tej odpowiedzi po tym, jak poprzednia została złamana przez trywialne crack przez dodanie instrukcji break.


Naprawdę ciekawi mnie fragment, który potem działa
NickA

Cóż, musisz poczekać siedem dni lub na trywialny crack, w zależności od tego, co nastąpi wcześniej ...
pppery


Cóż, takie wyzwania są bardzo trudne do zrobienia
pppery

4

APL (ngn-apl) , pęknięty przez ngn

Wykonane we współpracy z moim kolegą Marshallem .

Wprowadź za pomocą lewego i prawego argumentu do +. Tj. Twoim celem jest wstawienie kodu po poniższym, aby ostatni wiersz odczytywał ⎕←3+2i 5wysyłał dane do STDOUT.

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

Wypróbuj online!

Działa poprzez ustawienie wszystkich przydatnych funkcji, do {}których pobiera jeden lub dwa argumenty i zwraca pustą listę liczbową. Ustawia także po prostu komponować funkcje.


Pęknięcie

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

⍺⍵1/0 powtórz 0 przez lewy argument i prawy argument i 1

 pobierz indeksy, które by to posortowały (ponieważ wszystkie elementy są zerowe, daje 0 1 2… (a + b)

⌈/ maksymalna wartość (a + b)


ngn / apl zawiera możliwość wykonania dowolnego JavaScript. Nie uważam takiego rozwiązania za słuszne, ponieważ wtedy chodziłoby o wyłączenie JavaScript zamiast APL. Istnieje rzeczywiście prawidłowy (choć niejasny) sposób resetowania +przy użyciu tylko czystej APL i bez brudnych sztuczek.
Adám

3

Python 2 , Cracked

To druga iteracja odpowiedzi, która została raz złamana przez @HyperNuetrino przy użyciu metody, której się nie spodziewałem. Teraz załatałem to, więc mam nadzieję, że jedyne pozostałe rozwiązania będą musiały przestrzegać ograniczeń, które zamierzałem.

Implementuje dodawanie jako nazwaną funkcję

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\

Wypróbuj online!


Myślę, że mógłbym to zrobić, gdybym miał u, ale utknąłem bez tego.
isaacg

@isaacg Właśnie z ciekawości, z czym byś chciał u?
Wheat Wizard

.count. Mogę uzyskać ciąg tak długo, jak żądany wynik, ale nie mam możliwości, aby wziąć jego długość.
isaacg

__import__('sys').setrecursionlimit(100)... i nic nie zostało załatane. Jednak tak naprawdę nie mam ochoty umieszczać go w wątku rabusia, mam ochotę oszukiwać. Wypróbuj online
Value Ink


3

Java 8, Cracked przez @ OlivierGrégoire

Oto moja próba. W zasadzie chodzi o to, aby po prostu przeciążyć wszystkie przestrzenie nazw, których możesz użyć do wyjścia (i mam nadzieję, że odzwierciedlę). Wyjście jest przeznaczone do 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{}
}

Czarna lista jest zwykle gorszym podejściem niż biała lista, więc jestem pewien, że to kwestia czasu, zanim ktoś zaproponuje podejście, którego nie rozważałem.


1
To nie jest klasa wykonywalna ...
Olivier Grégoire,

1
@ OlivierGrégoire Przykro mi z tego powodu, dodałem class String{}po testach, nie zdając sobie sprawy, że to znokautuje main(String[] ...). Powinno już działać
Lord Farquaad,

1
Tak, to zrobi, dziękuję! :) Nie zmienia to jednak pęknięcia, które zamierzam zrobić: p
Olivier Grégoire,

1
Pęknięty! Naprawdę mi się podobało :)
Olivier Grégoire,

1
Patrzyłem na coś takiego (przepraszam, że trudno sformatować kod w komentarzach), ale myślę, że twoje rozwiązanie jest znacznie czystsze: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

3

cQuents, złamane przez Mayube

#|1,1:A

To powinno być dość łatwe, ale nigdy nie wiadomo.

„Problem” polegał na tym, że bez C kodu wystąpił błąd.

Rozwiązanie Mayube:

#|1,1:A+BC

Każdy element w sekwencji to pierwsze wejście plus drugie razy trzecie (aka 1)

Moje rozwiązania:

#1,1:A+B,C

Sekwencja przełącza się między pierwszym wejściem plus drugim wejściem, a trzecim wejściem (1). Pierwszy element w drugim to A+B.

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

Podobne do rozwiązania Mayube - zamiast pomnożyć B*C, po prostu dodaje, Ca następnie odejmuje.

Wypróbuj online!

Wyjaśnienie

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

Obecnie program ten generuje dane wyjściowe 1, ponieważ bez danych wejściowych użytkownika pierwsze dane wejściowe są pierwsze 1w domyślnej wartości wejściowej ( #).


Dokumenty wydają się naprawdę niezręcznie sformułowane, nie mogę na całe życie zrozumieć, co to znaczy, kiedy mówiDefault 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,

@Mayube, to dziwne, muszę znaleźć sposób, aby powiedzieć to poprawnie. Zasadniczo dane wejściowe do programu mogą być równe najwyższym danym wejściowym zapytanym przez zmienne A,B,C,D,Ew kodzie. Na przykład, jeśli w dowolnym momencie masz zmienną Dw swoim programie, analizator oczekuje, że będą 4 dane wejściowe, ale jeśli istnieje E, analizator oczekuje, że będzie 5 danych wejściowych. Nie może być mniejsza niż oczekiwana kwota. Jednak zawsze jest opcjonalne ostatnie wejście n, które jest używane na różne sposoby w różnych trybach.
Stephen

@Mayube fragment, który opublikowałem powyżej, zawiera A, więc szuka jednego wejścia. Ponieważ są dwa, z #których oba pochodzą z domyślnego wejścia, używa pierwszego jako Awartości, a drugi jako n.
Stephen

Więc jeśli miałbym podać 2 dane wejściowe i dołączyć BC, A byłoby pierwszym wejściem, B byłoby drugim, C byłoby 1, a n byłoby drugim 1?
Skidsdev,

@Mayube, przepraszam za moje kiepskie dokumenty. TMI: jeśli początek wyglądałby #1,1(bez paska), byłby to: A jako pierwszy 1, B jako drugi 1, C jako pierwszy sygnał wejściowy, a n jako drugi sygnał wejściowy. Możesz także zrobić #1|1, gdzie A to pierwsze 1, B to pierwsze wejście, C to drugie wejście, a n to drugie 1.
Stephen

3

Node.JS wersja 7.3.0 (Cracked przez 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)})();

Umieść drugi blok kodu po pierwszym.

Oświadczenie: drugi blok kodu nie będzie działał samodzielnie (bez umieszczania go po pierwszym). Jeśli nie jest to dozwolone, mogę zmodyfikować drugi fragment kodu.

To jest pełny program. Wyjście to process.stdout(STDOUT), wejście toprocess.argv (argumenty wiersza poleceń)

To moi pierwsi gliniarze i rabusie, mam nadzieję, że to dobre wyzwanie :)

Wypróbuj online!


Wyzwanie wyjaśnione

Generuje losową zmienną nod 0 do 1e7. Jeśli zadzwonisz do zapisu z prawidłowym n, nie drukuje niczego, ale ustawia lna 0, co „odblokowuje” funkcję zapisu, umożliwiając wydrukowanie czegokolwiek. Jeśli spróbujesz wywołać write z nie-ciągiem, wyśle ​​cię do nieskończonej pętli. Jeśli spróbujesz zadzwonić, napisz z czymkolwiek innym niż poprawnyn gdy zapis jest „zablokowany”, wyśle ​​cię do nieskończonej pętli, aby zapobiec zgadywaniu.

Zamierzone rozwiązanie

Przekracza obok typu, który pozornie sprawdza ciągi znaków tylko za pomocą symbolu, który również zaczyna się od s. Powoduje to błąd funkcji wynikający z wywołania eval, ponieważ nie można dodać ciągu „f” do symbolu. Łapiemy błąd i używamy wyrażenia regularnego, aby odzyskać dane nze stosu, gdzie jest on w nazwie funkcji. Następnie próbujemy pisać, nktóry niczego nie drukuje, ale ustawia zmienną „lock” lna 0, aby „odblokować” funkcję zapisu. Teraz, gdy funkcja zapisu jest odblokowana, po prostu drukujemy sumę.

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


To genialne ... Początkowo byłem na dobrej drodze! Dzięki za trening mózgu!
Dom Hastings,

3

RProgN2 , Pęknięty przez Arnolda Palmera

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

Zapisuje wszystkie operatory matematyczne, bez możliwości ich przywrócenia. W szczególności zastępuje je funkcją, która usuwa dwa górne elementy ze stosu.

Wypróbuj online!

Oryginalne rozwiązanie

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

Wypróbuj online!


Przeglądam twoją dokumentację i nie mogę znaleźć tego, co ²robi symbol. Chcesz oświecić mnie?
Arnold Palmer,

Ta dokumentacja nie jest niezwykle istotna dla RProgN2, a ten symbol przyjmuje [[w tym przypadku dwie następne koncepcje i otacza je funkcją @ArnoldPalmer
ATaco


Dang, to o wiele lepsze. Nie wiedziałem o operatorach stosów, które z pewnością byłyby przydatne. Również znajomość «»tworzy zmienne lokalne w przeciwieństwie do bałaganu zmiennych globalnych byłaby bardzo pomocna.
Arnold Palmer

3

Haskell, 161 144 bajtów, Cracked przez BlackCap

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

Wejście do STDIN, wyjście do STDERR. Dodaj na końcu programu.

Edycja: Przeznaczony do kompilacji bez dodatkowych argumentów GHC, tylko normalne ghc --make prog.hs .

Edytowane ponownie, aby obniżyć liczbę bajtów.

Baw się dobrze!


Więc nie mogę tego zrobić, ponieważ główna funkcja nie zostanie wywołana? main = do x <- readLn :: IO Integer; y <- readLn; print $ x + y
BlackCap

@ BlackCap Nie, ponieważ GHC oczekuje, że mainfunkcja będzie w module, Maingdy nie -main-iszostanie podana flaga.
zbw

To nie działa, ale i tak chcę się z tym podzielić
BlackCap,

Nazywam to crackowanym. Oto moje zamierzone rozwiązanie, gra w golfa. Nie działa na TIO, ponieważ opakowanie nie wysyła danych wejściowych do kompilatora.
zbw

Jeśli opublikujesz swoje rozwiązanie, oznaczę je jako pęknięte.
zbw

3

Mascarpone , rozbity przez 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<^$

Dane wejściowe to cyfry kościelne na stdio, używane idla przyrostu i zdla zera. Na przykład 2 + 3 to:

iiziiiz

Z końcowym znakiem nowej linii

Wynik powinien być liczbą na stdout, w tym samym formacie, co na stdio. Na przykład, jeśli odpowiedź brzmi pięć, powinieneś wypisać:

iiiiiz

(mascarpone nie ma pojęcia liczb)


Zamierzone rozwiązanie:

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

Z dokumentacji nie wynika to od razu, ale jak stwierdził w swoim crackie @IlmariKaronen, dosłowne napisy w Mascarpone są tak naprawdę syntaktycznym cukrem do wypychania sekwencji znaków.

Celowo napisałem komentarze, [this]$aby wyglądało na to, że pcham ciąg i natychmiast go puszczam. Naiwny cracker mógł spróbować czegoś takiego jak [:,>!]/*pchnięcie sznurka, zamiana go z tłumaczem i interpretacja.

Udaję też, że wstawiłem interpretera, który zostawiłem na stosie $, ale $został już przedefiniowany na NOP. Zostajesz z tym tłumaczem na stosie i musisz go nosić ze sobą przez cały program; przez każdy znak każdego ciągu.


Pęknięty. I nie, nigdy nie słyszałem o Mascarpone przed tym wyzwaniem.
Ilmari Karonen,

@IlmariKaronen Nowy ulubiony język? Dobra robota!
BlackCap

2

C # (.NET Core) Pęknięty przez Ilmari Karonen

Pęknięty także przez Jozuego .

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

Odczytuje dwie wartości ze stdin i zapisuje wynik na stdout. Testowane w systemie Windows z wersją Framework 3, 4.6 i TIO .

Oto pełny program, który zamierzałem.

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

Wypróbuj online!



codegolf.stackexchange.com/a/133412/14306 Zakładam, że nie było to zamierzone rozwiązanie.
Joshua

@IlmariKaronen: +1. To było zamierzone rozwiązanie.
raznagul

@Joshua: +1 za znalezienie innego rozwiązania niż zamierzałem.
raznagul

2

GolfScript , złamany przez Dennisa

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

Wypróbuj online!

To jest wyzwaniem, mimo wszystko, więc dlaczego nie spróbować GolfScript?

Poprawnym rozwiązaniem powinien być fragment kodu, który odczytuje ze stosu dwie liczby całkowite, dodaje je do siebie i zwraca wynik na stosie. Problem polega na tym, że powinien on nadal działać, nawet jeśli powyższy kod przedefiniował prawie wszystkie wbudowane operatory GolfScript, aby nie robić absolutnie nic. Przynajmniej zostawiłem ;nietknięty, abyś mógł nadal usuwać wartości ze stosu. ;-) Twój kod powinien działać na standardowym interpretatorze GolfScript, takim jak zaimplementowanym np. W TIO (patrz link powyżej).


Rozwiązanie Dennisa , podobnie jak moje , opiera się na rzadko używanej funkcji GolfScript, która umożliwia interpolację kodu Ruby w ciągach cudzysłowów. Korzystamy z tej funkcji, aby zdefiniować nowy operator dodawania, który działa dokładnie tak, jak wbudowany +operator, a następnie wywołać go.

(Jednym z powodów, dla których funkcja interpolacji Ruby w GolfScript jest tak rzadko używana, jest to, że niezręcznie interpolowany kod Ruby jest wykonywany podczas analizowania , a jego dane wyjściowe są buforowane przez interpreter GolfScript. Zatem jeśli np. Masz ciąg znaków z interpolowanym kodem Ruby w pętli kod uruchomi się tylko raz przed uruchomieniem rzeczywistego programu, a następnie zawsze będzie zwracał tę samą wartość przy każdej iteracji pętli. Możesz obejść to za pomocą eval ciągu, aby odroczyć parsowanie, ale to sprawia, że ​​i tak niezręczna składnia jest jeszcze większa brzydka i gadatliwa, a w każdym razie dla tego wyzwania wyłączyłem również operatora eval ~. Okazuje się jednak, że definiowanie nowych wbudowanych operatorów GolfScript jest jedna rzecz, którą ta funkcja robi całkiem ładnie i czysto.)



Pęknięty. W końcu zorientowałem się, co robiłem źle.
Dennis,

@Dennis: Tak, tym razem go przybiłeś. FWIW, moim zamierzonym rozwiązaniem było "#{var'_','gpush a+b'.cc2}";_, które działa dokładnie tak jak twoje, z wyjątkiem tego, że jest o kilka bajtów krótszy.
Ilmari Karonen,

2

Node.js v8.2.0, Cracked przez 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) )
                 );
}

Masz zaimplementować tę logicfunkcję. Dane wejściowe to dostarczone argumenty (od standardowego wejścia), dane wyjściowe są tym, co zwraca funkcja (jest wypisywane na standardowe wyjście).


Mój kod kościół koduje liczby z wejścia. Reszta kodu jest po to, aby cię zastraszyć.
Funkcja bałaganu wprowadza pewne sztuczki, aby zaimplementować notację bez punktów ( a . b == dot (a) (b)), której używam głównie do dodawania . id .do losowych miejsc, które nic nie robią, ale dezorientują każdego, kto nie zna programowania funkcjonalnego.
Transformacja zastosowana do liczb przed przekazaniem ich do logicfunkcji wynosi x+1i y-1, co daje w sumie 0, więc jest to kolejny NOP, który dodaje się do niejasności.

Zamierzonym rozwiązaniem było:

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


@DomHastings To nie jest zamierzone rozwiązanie, ale powiem, że możesz, o ile program zatrzymuje się bez wyjątku i nie drukuje dodatkowych znaków na wyjściu
BlackCap

Właśnie opublikowałem alternatywę! (Możesz zobaczyć moje poprzednie rozwiązanie w historii tej odpowiedzi!)
Dom Hastings

Och, łał, byłem daleko ... Wciąż to jest lepsze niż moja pierwsza bardzo podstępna próba! Dzięki za puzzle!
Dom Hastings,

2

Inform 7 , cracked by ppperry

For reading a command: rule fails.

[Your code here.]

Dane wejściowe powinny być wpisywane przez odtwarzacz jako polecenie interaktywne, np . add 17 to 25Lub sum 17 25. Możesz wybrać dokładną formę polecenia, które powinno zostać wprowadzone, o ile zawiera on dwie liczby. Suma liczb (np. 42) Powinna zostać wydrukowana w odpowiedzi na polecenie.

Wyzwanie oczywiście polega na tym, że cała czynność „odczytywania polecenia” jest zastępowana przez brak operacji. Prawdopodobnie istnieje kilka sposobów rozwiązania tego problemu, ale przynajmniej powinno to wymagać znajomości języka. Ten, który wymyśliłem, jest dość prosty, choć nieco nieoczekiwany.

Testowałem swoje rozwiązanie w GNOME Inform 7 IDE, wersja 6L38 , na Ubuntu Linux. Proponowane rozwiązanie działa zarówno na zapleczach Glulx, jak i na maszynie Z. Powinno także działać na innych najnowszych wersjach Inform 7. Zauważ, że (bez odpowiedniego obejścia) powyższy kod spowoduje, że interpreter będzie zapętlony podczas próby odczytania polecenia; interpreter maszyny Z wydaje się zupełnie nie reagować, kiedy to się dzieje, i nie można go zatrzymać z poziomu IDE, więc polecam używanie Glulx do testowania.


pęknięty , a jeśli się zastanawiasz, nigdy nie słyszałem o informowaniu przed tym wyzwaniem
pppery

2

CPython 3 (ponownie), pęknięty przez Syzyfa

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

Możesz zrobić wszystko, co chcesz - o ile nie jest zaimplementowane w C. Oznacza to print, że nie , nie input- wszystkie z nich trafią w _(1)linię i zakończą działanie . Wprowadzanie ze STDIN z liczbami na dwóch oddzielnych liniach, wysyłanie do STDOUT. Zastanawiam się, jak długo to potrwa ... Zajęło mi sporo czasu, aby znaleźć drugi działający fragment po wymyśleniu tej wyłączającej sztuczki. Jawne określenie Cpython, aby uniknąć pękania na podstawie innej alternatywnej implementacji sys.setprofile.


Pęknięty. Nie mam pojęcia, dlaczego to działa.
Syzyf

Chyba mogę teraz zapytać: dlaczego functools?
Dennis

@Dennis Ponieważ sispyphus odkrył lukę, a nie zamierzone rozwiązanie
pppery

@Sisyphus Twój crack został zgłoszony jako błąd w pythonie
pppery

2

Java 8 ( Cracked )

Drugie podejście. Tym razem zainwestowałem dwie minuty w testowanie.

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

    }

}

Większość rzeczy powinna być zakryta.


1
Czy mógłbyś dołączyć to do klasy z odpowiednim importem? Jest to rodzaj wyzwania, w którym te niewielkie zmiany mogą zrobić lub złamać wejście. Mam kilka rozwiązań dla tego, jakie jest, ale to drastycznie zmniejsza się, jeśli po prostu umieścisz to w klasie / interfejsie. Również formatowanie, aby usunąć te wszystkie wiersze, byłoby dla nas całkiem miłe, czytelnicy.
Olivier Grégoire,

Tam pęknięta odpowiedź przy użyciu dokładnie twojego kodu. I +1, bo wygląda na to, że zapomniałem. Przepraszam.
Olivier Grégoire,

Wywołania #setAccessible (false) nic nie robią.
Nevay

1

Python 2 pękł

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

Wypróbuj online!

Przedmówię to, mówiąc, że ta odpowiedź jest palantem, mającym na celu ograniczenie odpowiedzi.


Zainspirowany odpowiedziami Kreatora pszenicy i HyperNeutrino .

Fragment odczytuje plik źródłowy i odmawia kontynuowania, jeśli ostatni fragment kodu oddzielony spacjami nie jest sha256 e6400dd63733d10ec042e3c28033cfa85e1d25fbef80020810c354d7c942e843.

EDYCJA : nieznacznie edytowane w odpowiedzi na ten komentarz . Podstawowy problem się nie zmienia, żadna próba pęknięcia nie jest unieważniona.


1
RE pierwszy fragment:This code is not allowed to crash or exit.
Stephen

Jest to nieprawidłowe, ponieważ kończy działanie, co nie jest dozwolone w przypadku pierwszego fragmentu kodu.
DJMcMayhem


1

Java 8 Cracked przez @ OlivierGrégoire

Starałem się uczynić to tak trudnym, jak to możliwe! :) I, w przeciwieństwie do innych odpowiedzi w języku Java do tej pory, będziesz musiał przestrzegać dokładnych reguł wyzwania, umieszczając go po tym całym fragmencie (więc nie, nie umieszczasz kodu w public static void main(String[] args)metodzie, umieszczasz go po całej klasie. :) Powodzenia!

Dodałem komentarze, aby pokazać, co jest ograniczone.
( Zainspirowany tym postem, który jest mniej restrykcyjny i możliwy do pobicia dzięki temu samemu podejściu, którego mógłbym użyć do mojej odpowiedzi ).

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:

Wypróbuj tutaj. (ideone.com zamiast TIO, ponieważ wydaje się, że tam nie działa. Testy zostały wykonane w środowisku Eclipse IDE, ale moje zamierzone rozwiązanie działa, jeśli używasz ideone.com)



1

Galaretka: PĘKNIĘTA

Będzie to niesamowicie łatwe w porównaniu z niesamowitą odpowiedzią Pythona na Kreatora pszenicy, ale proszę bardzo: P

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

Sha256 hexdigest mojego rozwiązania obejścia, w tym pierwszego fragmentu, to cfeb1e193ad77f66f039c0d6a792a3e4c311490f6412698e019ca1fae10c0e0a .

Uwaga

Możesz nie mieć żadnych nowych wierszy w kodzie, z wyjątkiem ciągów, w przeciwnym razie ten kod nawet nie zostanie uruchomiony, co przeczy celowi tego wyzwania.

Cracked przez DJMcMayhem

Szczerze mówiąc, używa to nowej linii, więc chciałbym zobaczyć rozwiązanie, które nie korzysta z nowej linii.

Także rozwiązanie Jonathana Allana

To nie używa nowej linii, więc zostało złamane. : P

Moje rozwiązanie jest następujące:

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

Pierwszy fragment usuwa tylko atomy jednoznakowe, co oznacza, że ​​eval Python nadal działa :)))


Drugi fragment jest zawsze dołączany na końcu pierwszego fragmentu.
Stephen

@StepHen Tylko określając: P Ale zapomniałem dodać notatkę; to naprawdę ważne.
HyperNeutrino,

3
Nie sądzę, że możesz ograniczyć takich złodziei. Jeśli możesz złamać go za pomocą Newlines, to jest to poprawny crack. Czy istnieje sposób, aby zapobiec dodawaniu Newlines lub wymuszać wykonanie pierwszego wiersza?
DJMcMayhem


1
Podoba mi się twój zamierzony crack. Bardzo podstępny.
Dennis,

1

JavaScript, pęknięty

Wejście: prompt()dwa razy

Wynik: console.log()

Moje rozwiązanie nie działa w jsfiddle. Działa na stronie about: pusta strona z konsolą JS Google Chrome.

prompt=console=0

Moje rozwiązanie:

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

Wyjaśnienie:

Usunąłem monit i konsolę, ustawiając je na 0.

W moim rozwiązaniu tworzę ramkę iframe, która tworzy piaskownicę, i nowe wystąpienie okna, w którym monit i konsola działają poprawnie.



@CRDrost Nie wierzę, że w specyfikacji jest testowanie pierwszeństwa i nie wyświetlasz obu fragmentów.
Stephen

Przepraszam, masz rację, źle odczytałem.
CR Drost

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*/
  }
}

To powinno być bardzo łatwe do złamania.

Zamierzone rozwiązanie

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

Wypróbuj online



Zupełnie zapomniałem o java.io… Ale i tak masz zamierzone rozwiązanie…
Roman Gräf,

Nie widzę tutaj żadnego problemu. Tak naprawdę napisałem drugi fragment, który po prostu zapomniałem go edytować. Według TIO pierwszy fragment kompiluje się bez żadnego ostrzeżenia.
Roman Gräf,

@ OlivierGrégoire Gotowe. Myślę, że każde IDE będzie na mnie krzyczeć, ale przynajmniej kompilator to akceptuje ...
Roman Gräf
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.