JavaScript (ECMAScript6), 2 bajty na linię
'\
'[
'\
b\
i\
g'
][
'\
c\
o\
n\
s\
t\
r\
u\
c\
t\
o\
r'
][
'\
c\
a\
l\
l'
](
0,
`\
n\
=\
p\
r\
o\
m\
p\
t\
(\
'\
'\
)\
;\
i\
=\
0\
;\
f\
o\
r\
(\
;\
+\
+\
i\
<\
=\
n\
;\
c\
o\
n\
s\
o\
l\
e\
.\
l\
o\
g\
(\
i\
%\
5\
?\
f\
|\
|\
i\
:\
f\
+\
'\
P\
i\
e\
'\
)\
)\
f\
=\
i\
%\
3\
?\
'\
'\
:\
'\
A\
p\
p\
l\
e\
'\
`)
()
Długie wyjaśnienie
Sposób, w jaki możemy skrócić linie, polega na przekształceniu kodu w łańcuch i ucieczce od końca linii, co spowoduje ograniczenie 2 bajtów na linię.
Tak się alert(1)
staje
"\
a\
l\
e\
r\
(\
1\
)"
Ale teraz twój kod jest ciągiem, więc musimy go wykonać jako kod. Znam co najmniej 4 sposoby wykonywania łańcucha jako kodu:
- eval (kod) . Do wywołania potrzeba co najmniej 5 bajtów
eval(
- setTimeout (kod, limit czasu) . Uruchamia funkcję asynchronicznie, ale opcjonalnie, jeśli przekażesz ciąg, wywoła eval wewnętrznie.
- Możesz skorzystać z DOM i wstawić kod do
onclick=""
atrybutu, ale nie udało mi się skrócić tworzenia elementu.
- Wywołanie konstruktora funkcji new Function () parsuje twój kod w anonimową funkcję, którą możesz wywołać później (użyłem tego).
Wszystkie natywne funkcje mieszka wewnątrz okna obiektu w javascript i można uzyskać dostęp do właściwości obiektu za pomocą notacji kropki więc eval()
staje się window.eval()
, czy można uzyskać dostęp do właściwości za pomocą notacji nawiasu window['eval']()
. Możesz skorzystać z tego, aby rozbić eval
wiele linii przy użyciu metody opisanej wcześniej. Ale nadal musisz wpisać okno , jedną sztuczką jest to, że jeśli nie znajdujesz się w ramce, górną zmienną jest również okno, więc window.eval staje się top.eval (3 bajty mniej).
w=top
w['eval']
You can shorten the assignment using parenthesis
w=(
top
)
w[
'e\
av\
al'
](
/*string*/
)
Czyni to kod minimum 3 bajtów. Aby utworzyć 2 bajty kodu, użyłem new Function(/*string*/);
konstruktora, ale musiałem być kreatywny, aby uzyskać do niego dostęp bez konieczności wpisywania go.
Po pierwsze, konstruktor funkcji umożliwia wywołanie go jako funkcji pomijającej nowe słowo kluczowe, co zmniejsza 4 bajty, ale jest również ważne z innego powodu. Wywołanie konstruktora jako funkcja nadal zwraca instancję To pozwala nam włączyć new Function(code)
doFunction(code)
. Inną ważną rzeczą jest to, że konstruktor funkcji ma call
metodę, która pozwala wywoływać dowolną funkcję, ale zastępuje to odwołanie, a sam konstruktor funkcji jest funkcją, którą można wywołać na niejFunction.call(null, code)
.
Wszystkie funkcje rodzime są instancjami konstruktora funkcji, a wszystkie obiekty w javascript mają właściwość konstruktora . Możesz więc mieć dostęp do konstruktora funkcji do dowolnej funkcji natywnej alert.constructor
, a za pomocą metody wywołania możemy wykonać konstruktor jako funkcję. Teraz mamy alert.constructor.call (null, kod) zwraca funkcję.
łącząc poprzednie thechiniques możemy to zmienić alert['constructor']['call'](null, code)
Teraz musimy tylko znaleźć krótką nazwaną funkcję lub metodę, więc wybieram metodę big () wewnątrz konstruktora String. Więc mogę uzyskać do niego bezpośredni dostęp z pustego ciągu"".big
"".big.constructor.call(null, "code")();
''['big']['constructor']['call'](0,'/* code */')()
Potem po prostu wszystko zepsułem na 2 bajty
Krótki er wyjaśnienie (TLDR)
Uzyskuję dostęp do nowego konstruktora funkcji (kod), aby przeanalizować ciąg zamiast eval (kod) . Ten konstruktor jest dostępny dla każdej funkcji natywnej poprzez wykonanie dowolnej funkcji. konstruktor , jak alert.constructor===Function
. Używam funkcji / metody wewnątrz String.prototype.big String.prototype.big.constructor.call(null, /*string*/)
Ale dostęp do niej bezpośrednio z literału ciągu "".big
i zamieniłem go na notację w nawiasie . ""['big']['constructor']['call'](0, CODE)
aby móc go złamać za pomocą \
.