You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We need to find out how to do this for the function provided by the challenge.
I think use strict is the core of this challenge because it's much easier without strict mode. In non-strict mode, arguments.calle returns it self for IIFE(Immediately Invoked Function Expression).
(function(){returnarguments.callee+'';/* flag */})()
In strict mode it's not working and result in this error:
Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
I took some times to think about if there is another way to access an anonymous function without arguments.callee, finally I realized it's a dead end.
What if we change our direction? If we can access process, we can require('./flag') ourself to get the flag, without dumping the function body.
By googling vm nodejs escape or vm nodejs bypass I read some articles, but it seems none of them works, it's a dead end as well.
A few minutes later, I started to notice what makes it a dead end: function name. Because we can't get the function body without function name in strict mode.
We need to think outside the box, we can actually named the function. Or more specifically, create the named function ourself by close the current one and start a new one.
// originalusestrict';(function(){return${code};/* ${FLAG} */})()// we can close the current one and start a new onevarcode=`});(function a(){return a+''`// becomeusestrict';(function(){return});(functiona(){returna+'';/* ${FLAG} */})()
Cool, it works! It returns the whole function body including flag.
But it's 28 in length already, we can't bypass if (output.includes('zer0pts')){} because adding replace exceeds the limitation.
We need to shorten our exploit code, it seems the arrow function can help.
The length is 27, we are trying so hard to cut one character 😂.
Noticed that I use this.a=()=> here because (var a=()=>)() will raise an error: Uncaught SyntaxError: Unexpected token 'var', there is no such syntax. So I assign the arrow function to existing object to make it work.
When I reached here I feel I was so close, it's almost there. We don't need replace because it's too long. All we need is [0], we can extract the flag one by one to bypass the check.
But });(this.a=()=>{return (a+'')[0] is 32 in length, so sad. How to reduce more characters?
Let's start with the long one: return. Arrow function needs no return if it returns value directly.
The length is 28, so replace [0] with [10] is 29, just fit the limitation perfectly!
Right now we can exfiltrate the function body by characters, I wrote a simple script to help us see what is the full flag.
varaxios=require('axios')// flag start from index 23varpat=`});(this.a=()=>(a+'')[23]+{/*`varans=''asyncfunctionrun(){varlen=23;// 100 is a random guess, I guess 70 at first and it's too short lolwhile(len<100){payload=pat.replace(23,len);varresult=awaitaxios('http://web.ctf.zer0pts.com:8002/?code='+encodeURIComponent(payload))varf=result.data.split('<output>')[1]console.log(f)ans+=f[0]console.log(ans)len++}console.log(ans)}run()
Finally, awesome challenge!
The text was updated successfully, but these errors were encountered:
Kantan Calc
Description
"Kantan" means simple or easy in Japanese.
source code:
Writeup
This one is interesting because the flag is part of comment inside the function.
In JavaScript, you can get function body by casting it to a string:
We need to find out how to do this for the function provided by the challenge.
I think
use strict
is the core of this challenge because it's much easier without strict mode. In non-strict mode,arguments.calle
returns it self for IIFE(Immediately Invoked Function Expression).In strict mode it's not working and result in this error:
I took some times to think about if there is another way to access an anonymous function without arguments.callee, finally I realized it's a dead end.
What if we change our direction? If we can access
process
, we canrequire('./flag')
ourself to get the flag, without dumping the function body.By googling
vm nodejs escape
orvm nodejs bypass
I read some articles, but it seems none of them works, it's a dead end as well.A few minutes later, I started to notice what makes it a dead end: function name. Because we can't get the function body without function name in strict mode.
We need to think outside the box, we can actually named the function. Or more specifically, create the named function ourself by close the current one and start a new one.
Cool, it works! It returns the whole function body including flag.
But it's 28 in length already, we can't bypass
if (output.includes('zer0pts')){}
because addingreplace
exceeds the limitation.We need to shorten our exploit code, it seems the arrow function can help.
The length is 27, we are trying so hard to cut one character 😂.
Noticed that I use
this.a=()=>
here because(var a=()=>)()
will raise an error:Uncaught SyntaxError: Unexpected token 'var'
, there is no such syntax. So I assign the arrow function to existing object to make it work.When I reached here I feel I was so close, it's almost there. We don't need
replace
because it's too long. All we need is[0]
, we can extract the flag one by one to bypass the check.But
});(this.a=()=>{return (a+'')[0]
is 32 in length, so sad. How to reduce more characters?Let's start with the long one:
return
. Arrow function needs no return if it returns value directly.We are getting closer, although it doesn't work because of the annoying
;
and}
, the length is 24.After 10~15 minutes, I figure out how to bypass it. Use
/*
to comment out;
and use+{
to make it an empty object!The length is 28, so replace
[0]
with[10]
is 29, just fit the limitation perfectly!Right now we can exfiltrate the function body by characters, I wrote a simple script to help us see what is the full flag.
Finally, awesome challenge!
The text was updated successfully, but these errors were encountered: