JavaScript (ECMAScript6), 2 byte mỗi dòng
'\
'[
'\
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\
'\
`)
()
Giải thích dài
Cách chúng ta có thể làm cho các dòng ngắn hơn là chuyển đổi mã thành một chuỗi và thoát khỏi các đầu dòng, điều này sẽ áp đặt giới hạn 2byte trên mỗi dòng.
Vì vậy, alert(1)
trở thành
"\
a\
l\
e\
r\
(\
1\
)"
Nhưng bây giờ mã của bạn là một chuỗi vì vậy chúng ta cần thực thi chuỗi dưới dạng mã. Tôi biết ít nhất 4 cách bạn có thể thực thi chuỗi dưới dạng mã:
- eval (mã) . Mất ít nhất 5 byte để gọi
eval(
- setTimeout (mã, thời gian chờ) . Chạy chức năng không đồng bộ, nhưng tùy chọn nếu bạn vượt qua một chuỗi, nó sẽ gọi eval bên trong.
- Bạn có thể tận dụng DOM và đặt mã của bạn vào trong một
onclick=""
thuộc tính, nhưng tôi không thể quản lý để làm cho phần tạo phần tử ngắn lại.
- Gọi hàm tạo Hàm mới Hàm mới () sẽ phân tích mã của bạn thành một hàm ẩn danh mà bạn có thể gọi sau (tôi đã sử dụng hàm này).
Tất cả các chức năng có nguồn gốc cuộc sống bên trong cửa sổ đối tượng và trong javascript bạn có thể truy cập vào thuộc tính đối tượng bằng cách sử dụng ký hiệu dấu chấm để eval()
trở thành window.eval()
, hoặc bạn có thể truy cập vào các thuộc tính bằng cách sử dụng ký hiệu khung window['eval']()
. Bạn có thể tận dụng điều này để phá vỡ eval
nhiều dòng bằng phương pháp được mô tả trước đó. Nhưng bạn vẫn phải gõ cửa sổ , một mẹo nhỏ là nếu bạn không ở trong khung, biến trên cùng cũng là cửa sổ, vì vậy window.eval trở thành top.eval (giảm 3 byte).
w=top
w['eval']
You can shorten the assignment using parenthesis
w=(
top
)
w[
'e\
av\
al'
](
/*string*/
)
Vì vậy, điều này sẽ làm cho mã tối thiểu là 3 byte. Để tạo mã 2 byte tôi đã sử dụng hàm new Function(/*string*/);
tạo, nhưng tôi phải sáng tạo để truy cập nó mà không phải gõ nó.
Đầu tiên, hàm tạo cho phép bạn gọi nó là hàm bỏ qua từ khóa mới, điều này làm giảm 4 byte nhưng nó cũng quan trọng vì một lý do khác. Gọi hàm tạo như một hàm vẫn trả về một thể hiện, điều này cho phép chúng ta chuyển new Function(code)
sangFunction(code)
. Một điều quan trọng khác là hàm tạo Hàm có một call
phương thức cho phép bạn gọi bất kỳ hàm nào nhưng ghi đè tham chiếu này và chính hàm tạo Hàm là hàm mà bạn có thể gọi một phương thức trên đó Function.call(null, code)
.
Tất cả các hàm riêng là các thể hiện của hàm tạo Hàm và tất cả các đối tượng trong javascript đều có thuộc tính hàm tạo . Vì vậy, bạn có thể có quyền truy cập Hàm tạo trên bất kỳ hàm riêng nào như alert.constructor
và sử dụng phương thức gọi chúng ta có thể thực thi hàm tạo như một hàm. Bây giờ chúng ta có alert.constructor.call (null, code) trả về một hàm.
kết hợp những thứ trước đây chúng ta có thể biến nó thành alert['constructor']['call'](null, code)
Bây giờ chúng ta chỉ cần tìm một hàm hoặc phương thức có tên ngắn, vì vậy tôi chọn phương thức big () bên trong hàm tạo String. Vì vậy, tôi có thể truy cập nó trực tiếp từ một chuỗi trống"".big
"".big.constructor.call(null, "code")();
''['big']['constructor']['call'](0,'/* code */')()
Sau đó, tôi chỉ phá vỡ mọi thứ trong 2 byte
Ngắn erGiải thích (TLDR)
Tôi đang truy cập hàm tạo Hàm (mã) mới để phân tích chuỗi thay vì eval (mã) . Hàm tạo này có sẵn ở mọi hàm riêng bằng cách thực hiện bất kỳ Hàm nào. nhà xây dựng , thích alert.constructor===Function
. Tôi đang sử dụng một hàm / phương thức bên trong String.prototype.big String.prototype.big.constructor.call(null, /*string*/)
Nhưng truy cập trực tiếp từ một chuỗi ký tự "".big
và chuyển nó thành ký hiệu ngoặc . ""['big']['constructor']['call'](0, CODE)
để có thể phá vỡ nó bằng cách sử dụng \
.