Reputation: 3936
After seeing the following code, I started wondering if there was a way to access the full lowercase alphabet without using any letters(conditions to be applied below):
[($=(!0)+'')[0]+$[1]+$[2]+((!1)+'')[3]+$[0],(([]+[])[1]+'')[1]+([]+{})[1],([]+{})[1]+(([]+[])[1]+'')[1]+$[3]].join(' ');
// "trust no one"
Using the various statements below the following letters can be accessed a b c d e f g i j l m n o p r s t u v x y
:
// "true" yeilds: e r t u
!0+'';
// "false" yeilds: a f l s
!1+'';
// "[object Object]" yeilds: b c j o t
[]+{}+'';
// "undefined" yeilds: d i n
[][1]+'';
// "Infinity" yeilds: y
1/0+'';
// Using the above statements "constructor" can be spelled
// It has no value by itself but can be coupled with other statements to get more letters
($=[]+{}+'')[5]+$[1]+(([]+[])[1]+'')[1]+((!1)+'')[3]+($=!0+'')[0]+$[1]+$[2]+($=[]+{}+'')[5]+$[6]+$[1]+((!0)+'')[1];
// "function RegExp() { [native code] }" yeilds: g p v x
(/./)[/*constructor" from above*/]+'';
// "function Number() { [native code] }" yeilds: m
(0)[/*"constructor" from above*/]+'';
What are ways to access to remaining characters h q w z
with the following limits applied:
global
for node, window
for browsers, etcUpvotes: 0
Views: 1488
Reputation: 69
Here's my solution to produce all English letters both in lowercase and uppercase.
This solution is not using unescape
function but do utilize dynamic function generator to implicitly un-escape hex literal string.
((_,$,$$) =>
/* _ = 'abcdefghijklmnopqrstuvwxyz'
$ = code => Function( arg, code )
declare $$ (will be defined later)
*/
_[ // invoke _.toUpperCase() ...
// construct "toUpperCase"...
_[19]+_[14]+ // "to"
($$=( // $$ = hexCode => { return `\x${hexCode}` }
__ => $( // __ as hexCode, invoke the $ function...
[ _[17]+_[4]+_[19]+_[20]+_[17]+_[13], // "return"
' `\\',_[23],__,'`'] // ` \x${hexCode}`
[ _[9]+_[14]+_[8]+_[13] ]('') // .join('')
)()
))(55) // 'U'
+_[15]+_[15]+_[4]+_[17] // "pper"
+$$(43) // '\x43' --> 'C'
+_[0]+_[18]+_[4] // "ase"
]() // --> "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+_ // concatenate with the _
)(...( // call with spread operator...
( (_,$,$$) => [
_[1]+_[28]+_[31]+_[11]+_[4]+_[0] // "abcdef"
+ ( _ += // append following string to _
''[
$=[ // "constructor", saved as $
_[31]+_[27]+_[10]+_[3]+_[5]
+_[6]+_[7]+_[31]+_[5]+_[27]+_[6]
]
] // --> "function String() { [native code] }"
+ ''+/./[$]
// --> "function RegExp() { [native code] }"
)[55] // 'g'
+ (17)[
$$=_[5]+_[27]+_[50]+_[5]+_[6]+_[21]+_[10]+_[55]
// $$ = "toString"
](36) // (17).toString(36) --> 'h'
+_[21]+_[29] // "ij"
+(20)[$$](36) // (20).toString(36) --> 'k'
+_[2] // 'l'
+(0[$]+'')[11] // (Number.toString())[11] --> 'm'
+_[10]+_[27]+_[90] // "nop"
+(26)[$$](36) // (26).toString(36) --> 'q'
+_[6]+_[3]+_[5]+_[9]+_[66] // "rstuv"
+(32)[$$](36) // (32).toString(36) --> 'w'
+_[89]+_[25] // "xy"
+(35)[$$](36) // (35).toString(36) --> 'z'
// code=>Function(arg,code)
, _ => (()=>{})[$]('_',_)
])(
// "falsetrueundefinedInfinity[object Object]"
''+![]+!![]+[][0]+(1/0)+{}
)
));
Returned string: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
.
''+![]+!![]+[][0]+(1/0)+{}
which will produce
"falsetrueundefinedInfinity[object Object]"
Let's name this string as {s1} for this explanation.
Pass string s1 to closure function f1 as first argument (the _
variable)
Grab "abcdef"
from s1 (now stored in _
variable)...
_[1] + _[28] + _[31] + _[11] + _[4] + _[0]
"constructor"
from s1 ... _[31]+_[27]+_[10]+_[3]+_[5]
+_[6]+_[7]+_[31]+_[5]+_[27]+_[6]
and saved it into $
variable ($
is declared as undefined argument in f1 function)
String
function by taking constructor of any string instance (in this case we can just use an empty string)...<string_instance>.constructor
= ''.constructor = ''['constructor']
= ''[$] // $ = "constructor" in previous step
= the String function
Convert it to string by appending it to an empty string to get "function String() { [native code] }"
RegExp
instance..././[$] //--> the RegExp function
Convert it into a string --> "function RegExp() { [native code] }"
Number
instance...0[$] // --> the Number function
Convert it into a string --> "function Number() { [native code] }"
_
variable.
Let's name this new string as s2. Content of s2 now is... "falsetrueundefinedInfinity[object Object]function String() { [native code] }function RegExp() { [native code] }function Number() { [native code] }"
From s2, grab the character 'g'
at index #55
Compose "toString"
from s2 ...
_[5]+_[27]+_[50]+_[5]+_[6]+_[21]+_[10]+_[55]
and store it into the $$
variable (it is also declared as undefined argument in f1 function)
Now we can call toString()
function from any number to get any lower case letter by supplying 36
as its radix argument, thus calling (17).toString(36)
will yield the 'h'
letter. In our code, this accomplished by: (17)[$$](36)
Next take letter 'i'
and 'j'
from s2
Get letter 'k'
using the same toString(36)
method as in step 11, this time with number 20
.
Grab "lmnop"
from s2
Use (26).toString(36)
to get letter 'q'
Grab "rstuv"
from s2
Use (32).toString(36)
to get letter 'w'
Grab "xy"
from s2
Use (35).toString(36)
to get letter 'z'
.
Now we have all lowercase letters. Put it into f1's result array as its first element.
To get the uppercase letters is a little tricky. We'll use function generator (the Function
function) to generate a function which returns character decoded from given argument. As first step, obtain the Function
function by referencing constructor of a function instance...
<function_istance>.constructor
= ( ()=>{} )[ 'constructor' ]
= (()=>{})[$]
= Function
and wrap it into a closure to generate our desired function...
code => Function( argument_name, code )
Because we can't use letters, just reuse the '_'
name for its argument...
_ => Function( '_', _ )
Please don't be confused between the _
(argument of the closure) with the '_'
(argument of the new function generated as the result of calling the closure).
For the sake of clarity, let's name this closure function as f2.
We'll put the f2 as second element in f1's result array.
Now f1 is finished, we'll pass the result (array from the previous two steps) using spread operator as _
and $
argument into function f3. So in f3, our s2 string is in _
variable, and f2 is in $
variable.
Create new function f4, which is to return a character from given argument. We'll need f4 to produce two uppercase letters: 'U'
(char code 0x55) and 'C'
(char code 0x43). This will be accomplished by simple return statement followed by a hex-literal string "return \x??"
where ??
is the argument to be passed on. Because we have all required letters to compose the code (all of them is lowercase letters), we just need to assemble them. Put f4 as variable $$
(it is already defined as undefined argument in f3).
Call f4 with 55
as argument (will be automatically casted into '55'
, prefixed with hard-coded '\x'
become '\x55'
--> letter 'U'
.
Prepend with "pper"
grabbed from s2
Call f4 again with 43
as argument, this will produce letter 'C'
.
Prepend with "ase"
, thus we have "toUpperCase"
Invoke _.toUpperCase()
to get upper case version of s2
Prepend string from step 28 with s2
Return from f3 with result string from step 29: all letters both in lowercase and uppercase forms.
Upvotes: 1
Reputation: 4329
Aha got it. If unescape
is allowed, not encoded for clarity:
[]['constructor']['constructor']['call']('','return unescape' + '("%68%71%77%7' + 'a' +'")')()
This gives us hqwx, and can of course give us anything else.
the only bit that cannot be reached is '("%68%71%77%7<a goes here>")'
, but that satisfies the symbols and numbers rule. The a can be constructed otherwise.
If we want to avoid unescape, we can use (828035)['toString'](36)
-- The "magic" number 828035
was generated by using parseInt('hqwz',36)
.
And encoded -- with large parts broken out for readability:
// From your post
str_constructor = ($=[]+{}+'')[5]+$[1]+(([]+[])[1]+'')[1]+
((!1)+'')[3]+($=!0+'')[0]+$[1]+$[2]+($=[]+{}+'')[5]+
$[6]+$[1]+((!0)+'')[1];
// call
str_call = ([]+{}+'')[5]+($=!1+'')[1]+$[2]+$[2];
// return unescape ( bonus, not using a literal space character )
ret_unescape = ($=!0+'')[1]+$[3]+$[0]+$[2]+$[1]+($=''[1]+'')[1]+
([]+{}+'')[7]+$[0]+$[1]+$[3]+($=!1+'')[3]+([]+{}+'')[5]+$[1]+
((/./)[str_constructor]+'')[14]+(!0+'')[3];
// finally
[][str_constructor][str_constructor][str_call]('',ret_unescape + '("%68%71%77%7' + (!1+'')[1] +'")')() // "hqwz"
// or -- toString
str_toString = (!0+'')[0]+([]+{}+'')[1]+($=(('')[str_constructor]+''))[9]+$[10]+$[11]+$[12]+$[13]+$[14]
(828035)[str_toString](36) // hqwz
Bonus-bonus:
We can even ditch numbers if we are sneaky.
true: !![]
false: ![]
0: ![]+![]
1: !![]+![]
2: !![]+!![]
10: (!![]+![]+'')+(![]+![])
My big nasty magic constant could therefore be:
((!![]+!![])*(!![]+!![])*(!![]+!![])+'')+((!![]+!![])+'')+
((!![]+!![])*(!![]+!![])*(!![]+!![])+'')+
(![]+![]+'')+(!![]+!![]+!![]+'')+((!![]+!![])*(!![]+!![])+!![])-![]
Upvotes: 1
Reputation: 657
([]+{}+'')[5]+([]+{}+'')[1]+(([]+[])[1]+'')[1]+(!1+'')[3]+(!0+'')[0]
+(!0+'')[1]+(!0+'')[2]+([]+{}+'')[5]+(!0+'')[0]+([]+{}+'')[1]+(!0+'')[1]
gives you 'constructor', which you can then use with a string literal like this:
('')[([]+{}+'')[5]+([]+{}+'')[1]+(([]+[])[1]+'')[1]+(!1+'')[3]+(!0+'')[0]
+(!0+'')[1]+(!0+'')[2]+([]+{}+'')[5]+(!0+'')[0]+([]+{}+'')[1]+(!0+'')[1]]+''
which gives you 'function String() { [native code] }'
which gives you 'v' and 'g'
Edit: You found 'constructor' too, it's tricky to get much more without a way to access the global variable.
Here's a way to get the global variable in Node:
('')['constructor']['constructor']('','return global')()
Using the approaches above:
('')[
// 'constructor'
({}+'')[5] + ({}+'')[1] + (([]+[])[1]+'')[1] + (!1+'')[3] +
(!0+'')[0] + (!0+'')[1] + (!0+'')[2] + ({}+'')[5] +
(!0+'')[0] + ({}+'')[1] + (!0+'')[1]
][
// 'constructor'
([]+{}+'')[5] + ([]+{}+'')[1] + (([]+[])[1]+'')[1] + (!1+'')[3] +
(!0+'')[0] + (!0+'')[1] + (!0+'')[2] + ([]+{}+'')[5] +
(!0+'')[0] + ([]+{}+'')[1] + (!0+'')[1]
](
'',
// 'return'
(!0+'')[1] + (!0+'')[3] + (!0+'')[0] + (!0+'')[2] + (!0+'')[1] + (([]+[])[1]+'')[1] +
' ' +
// 'g'
(('')[
([]+{}+'')[5] + ([]+{}+'')[1] + (([]+[])[1]+'')[1] +
(!1+'')[3] + (!0+'')[0] + (!0+'')[1] + (!0+'')[2] +
([]+{}+'')[5] + (!0+'')[0] + ([]+{}+'')[1] + (!0+'')[1]
] + '')[14] +
// 'lobal'
(!1+'')[2] + ({}+'')[1] + ({}+'')[2] + (!1+'')[1] + (!1+'')[2]
)()
From there you could access global.env
and from there it's almost cheating.
Edit: You can also build this:
[]['constructor']['constructor'](
'o',
"var a=[];for(var x in o){a.append(x)};return a")
Which gives you a poor man's Object.keys()
, which you can use to access the names of various objects' methods.
You can also build an eval function & assign it to $
:
$=[]['constructor']['constructor']('s','return eval(s)')
Upvotes: 1