介绍了windows下对Explorer的拷贝动作的精确截获,这个在企业数据安全dlp产品系列中减少审计的噪音很有效,方便运营人员做针对性的审计。

在企业数据安全中我通常需要监测用户的拷贝行为,特别像explorer这样的进程,方法很多比如文件过滤驱动监测文件的打开与读写,但是这样会有很多噪音产生,实现的不好的话也可能会造成用户在桌面操作感受不良好,比如卡,所以我们需要的是一种更精准地方法,下面我们就来分析下如何去更加精准的定位拷贝。

一、            分析

我们都知道windows软件读写的方法很多比如c库一些读写函数,fopen 、fread、fwrite,c++流函数std::stream,但是都会进入windows的底层读写,还有一类文件操作函数就是Shell函数SHFileOperation,不管什么函数最后都会调用windows自己常用的文件操作函数就是CreateFileA、CreateFileW、ReadFile、WriteFile,我们可以使用调试器去在CreateFileW函数设置断点,但是这个一个问题我们必须在explorer进程空间里设断点,但是会阻碍正常的桌面UI操作,为了方便我们操作桌面,写一个文件过滤驱动,去过滤我们需要的信息,比如我们把一个.txt文件从目录A拷贝到目录B,我们可以在过滤驱动的IRP_MJ_CREATE的例程函数里这样写

  1. CErrorStatus PreCreate( CIrp& Irp, zipmbool& IsIrpCompleted)
  2. {
  3. CFileObject FileObject;
  4. CErrorStatus Error = STATUS_SUCCESS;
  5. Irp.UseCurrentStackLocation();
  6. CIoStackLocation Stack = Irp.StackLocation();
  7.  
  8. do
  9. {
  10. if( wcsstr(FileObject.FileName()->Buffer,L".txt"))
  11. {
  12. if (FileObject.RelatedFileObject())
  13. {
  14.  
  15. }
  16. }
  17. } while (FALSE);
  18.  
  19. return Error;
  20. }

这样过滤会减少很多干扰,利用windbg的虚拟机的双机器调试。

加载驱动后,我们可以设置断点在if ( FileObject.RelatedFileObject()),这行代码上。

然后拷贝一个txt的文件从A到B,如下图

这里windbg调试器就会停下,进入刚才设置的断点位置。

输入命令kb

发现堆栈是从user层到内核层在到本驱动的PreCreate函数,这时user层显示的只是地址,是因为符号没加载,继续输入.reload  /user,慢慢就显示了

引起注意的是红色框显示的堆栈:

Nt!NtCreateFile

KernelBase!CreateFile

Kernel32!CreateFileWImplementation

Shell32!CFSTransfer:_OpenSrcFileWithRetry

Shell32! CFSTransfer::OpenItem

Shell32!CDelegatingTansfer:: OpenItem

Shell32! CCopyOperation::Do

Shell32! CCopyWorkItem::_DoOperation

Shell32! CCopyWorkItem::_SetupAndPerformOp

Shell32! CCopyWorkItem::ProcessWorkItem

Shell32!CRecursiveFolderoperation::Do

Shell32!CFileOperation::_EnumRootDo

Shell32!CFileOperation::PrepareAndDoOperation

Shell32!CFileOperation::PreformOperation

Shell32!SHFileOperationEx

由上可以看出最主要的是调用了SHFileOperationEx函数,这好说了,使用IDA打开shell32.dll分析这个函数

IDA显示这个函数调用了SHCreateFileOperation

继续跟进SHCreateFileOperation

它创建的是GUID_947aab5f_0a5c_4c13_b4d6_4bf7836fc9f8这个类的实例,隶属于FileOperaton, 写过com的人都知道947aab5f_0a5c_4c13_b4d6_4bf7836fc9f8这个实例id就是com中的 IFileOperation的com库接口,查看windows的sdk定义如下

  1. MIDL_INTERFACE("947aab5f-0a5c-4c13-b4d6-4bf7836fc9f8")
  2. IFileOperation : public IUnknown
  3. {
  4. public:
  5. virtual HRESULT STDMETHODCALLTYPE Advise(
  6. __RPC__in_opt IFileOperationProgressSink *pfops,
  7. __RPC__out DWORD *pdwCookie) = ;
  8.  
  9. virtual HRESULT STDMETHODCALLTYPE Unadvise(
  10. DWORD dwCookie) = ;
  11.  
  12. virtual HRESULT STDMETHODCALLTYPE SetOperationFlags(
  13. DWORD dwOperationFlags) = ;
  14.  
  15. virtual HRESULT STDMETHODCALLTYPE SetProgressMessage(
  16. __RPC__in_string LPCWSTR pszMessage) = ;
  17.  
  18. virtual HRESULT STDMETHODCALLTYPE SetProgressDialog(
  19. __RPC__in_opt IOperationsProgressDialog *popd) = ;
  20.  
  21. virtual HRESULT STDMETHODCALLTYPE SetProperties(
  22. __RPC__in_opt IPropertyChangeArray *pproparray) = ;
  23.  
  24. virtual HRESULT STDMETHODCALLTYPE SetOwnerWindow(
  25. __RPC__in HWND hwndOwner) = ;
  26.  
  27. virtual HRESULT STDMETHODCALLTYPE ApplyPropertiesToItem(
  28. __RPC__in_opt IShellItem *psiItem) = ;
  29.  
  30. virtual HRESULT STDMETHODCALLTYPE ApplyPropertiesToItems(
  31. __RPC__in_opt IUnknown *punkItems) = ;
  32.  
  33. virtual HRESULT STDMETHODCALLTYPE RenameItem(
  34. __RPC__in_opt IShellItem *psiItem,
  35. __RPC__in_string LPCWSTR pszNewName,
  36. __RPC__in_opt IFileOperationProgressSink *pfopsItem) = ;
  37.  
  38. virtual HRESULT STDMETHODCALLTYPE RenameItems(
  39. __RPC__in_opt IUnknown *pUnkItems,
  40. __RPC__in_string LPCWSTR pszNewName) = ;
  41.  
  42. virtual HRESULT STDMETHODCALLTYPE MoveItem(
  43. __RPC__in_opt IShellItem *psiItem,
  44. __RPC__in_opt IShellItem *psiDestinationFolder,
  45. __RPC__in_opt_string LPCWSTR pszNewName,
  46. __RPC__in_opt IFileOperationProgressSink *pfopsItem) = ;
  47.  
  48. virtual HRESULT STDMETHODCALLTYPE MoveItems(
  49. __RPC__in_opt IUnknown *punkItems,
  50. __RPC__in_opt IShellItem *psiDestinationFolder) = ;
  51.  
  52. virtual HRESULT STDMETHODCALLTYPE CopyItem(
  53. __RPC__in_opt IShellItem *psiItem,
  54. __RPC__in_opt IShellItem *psiDestinationFolder,
  55. __RPC__in_opt_string LPCWSTR pszCopyName,
  56. __RPC__in_opt IFileOperationProgressSink *pfopsItem) = ;
  57.  
  58. virtual HRESULT STDMETHODCALLTYPE CopyItems(
  59. __RPC__in_opt IUnknown *punkItems,
  60. __RPC__in_opt IShellItem *psiDestinationFolder) = ;
  61.  
  62. virtual HRESULT STDMETHODCALLTYPE DeleteItem(
  63. __RPC__in_opt IShellItem *psiItem,
  64. __RPC__in_opt IFileOperationProgressSink *pfopsItem) = ;
  65.  
  66. virtual HRESULT STDMETHODCALLTYPE DeleteItems(
  67. __RPC__in_opt IUnknown *punkItems) = ;
  68.  
  69. virtual HRESULT STDMETHODCALLTYPE NewItem(
  70. __RPC__in_opt IShellItem *psiDestinationFolder,
  71. DWORD dwFileAttributes,
  72. __RPC__in_opt_string LPCWSTR pszName,
  73. __RPC__in_opt_string LPCWSTR pszTemplateName,
  74. __RPC__in_opt IFileOperationProgressSink *pfopsItem) = ;
  75.  
  76. virtual HRESULT STDMETHODCALLTYPE PerformOperations( void) = ;
  77.  
  78. virtual HRESULT STDMETHODCALLTYPE GetAnyOperationsAborted(
  79. __RPC__out BOOL *pfAnyOperationsAborted) = ;
  80.  
  81. };

我们回到之前那个Ex函数,创建完IFileOperation的实例后,就开始调用里面的函数

分别调用了

Call dword ptr[esi+0x20h]

Call dword pre[esi+0x2Ch] 或者Call  dword pre[esi+0x4Ch]

Call dword pre[esi+0x44h] 或者 Call dword pre[esi+0x3Ch]

其他函数都是设置Explorer的拷贝Item的属性的函数,+0×44这个函数对应的是IFileOperation::Copy Items,而+0x3C对应的函数是IFileOperation::Move tems,而我们这次的拷贝动作调用的就是IFileOperation::CopyItems,下面我们有方案了我们可以hook这个IFileOpertion的接口库实现精准截获桌面的拷贝动作。

一、            实现

CopyItems为例子

定义一个CFileOperation

  1. #define QueryInterface_Index 0
  2. #define AddRef_Index (QueryInterface_Index + 1)
  3. #define Release_Index (AddRef_Index + 1)
  4. #define Advice_Index (Release_Index + 1)
  5. #define Unadvise_Index (Advice_Index + 1)
  6. #define SetOperationFlags_Index (Unadvise_Index + 1)
  7. #define SetProgressMessage_Index (SetOperationFlags_Index + 1)
  8. #define SetProgressDialog_Index (SetProgressMessage_Index + 1)
  9. #define SetProperties_Index (SetProgressDialog_Index + 1)
  10. #define SetOwnerWindow_Index (SetProperties_Index + 1)
  11. #define ApplyPropertiesToItem_Index (SetOwnerWindow_Index + 1)
  12. #define ApplyPropertiesToItems_Index (ApplyPropertiesToItem_Index + 1)
  13. #define RenameItem_Index (ApplyPropertiesToItems_Index + 1)
  14. #define RenameItems_Index (RenameItem_Index + 1)
  15. #define MoveItem_Index (RenameItems_Index + 1)
  16. #define MoveItems_Index (MoveItem_Index + 1)
  17. #define CopyItem_Index (MoveItems_Index + 1)
  18. #define CopyItems_Index (CopyItem_Index + 1)
  19. #define DeleteItem_Index (CopyItems_Index + 1)
  20. #define DeleteItems_Index (DeleteItem_Index + 1)
  21. #define NewItem_Index (DeleteItems_Index + 1)
  22. #define PerformOperations_Index (NewItem_Index + 1)
  23. #define GetAnyOperationAborted_Index (PerformOperations_Index + 1)
  24. #define HOOK(a, b) b##_old = (P##b)HookVtbl(a, 0, b##_Index,
  25. (PBYTE)b##_new)
  26.  
  27. class CFileOperation
  28. {
  29.  
  30. public:
  31. CFileOperation(void);
  32. ~CFileOperation(void);
  33.  
  34. int HookVtbl(void* pObject, unsigned int classIdx, unsigned int methodIdx, int newMethod);
  35.  
  36. static HRESULT __stdcall CopyItems_new(IFileOperation *pThis,
  37.  
  38. IUnknown *punkItems,
  39.  
  40. IShellItem *psiDestinationFolder);
  41.  
  42. BOOL Init();
  43. };

在初始化的时候我们需要获取接口并却修改截获CopyItems和MoveItems的指针接口

  1. BOOL CFileOperation::Init()
  2. {
  3. IFileOperation* Pf = NULL;
  4. CoInitialize( NULL );
  5.  
  6. do
  7. {
  8. HRESULT hr = CoCreateInstance(
  9.  
  10. CLSID_FileOperation,
  11. NULL,
  12. CLSCTX_ALL,
  13. IID_IFileOperation,
  14. (PVOID*)&Pf);
  15. HOOK(Pf, CopyItems);
  16.  
  17. } while (FALSE);
  18. }
  19.  
  20. int CFileOperation::HookVtbl(void* pObject, unsigned int classIdx, unsigned int methodIdx, int newMethod)
  21. {
  22.  
  23. int** vtbl = (int**)pObject;
  24. DWORD oldProtect = ;
  25. int oldMethod = vtbl[classIdx][methodIdx];
  26.  
  27. VirtualProtect(vtbl[classIdx] + sizeof(int*) * methodIdx, sizeof(int*), PAGE_READWRITE, &oldProtect);
  28.  
  29. vtbl[classIdx][methodIdx] = newMethod;
  30.  
  31. VirtualProtect(vtbl[classIdx] + sizeof(int*) * methodIdx, sizeof(int*), oldProtect, &oldProtect);
  32.  
  33. return oldMethod;
  34. }
  35.  
  36. HRESULT CFileOperation::CopyItems_new(IFileOperation *pThis,
  37. IUnknown *punkItems,
  38. IShellItem *psiDestinationFolder)
  39. {
  40. HRESULT hr = CopyItems_old(pThis, punkItems, psiDestinationFolder);
  41. return hr;
  42. }

这里生成了dll后我们需要注入到桌面进程中,这样就可以实现截获CopyItems接口,注意这里只是完成了第一步,这个接口传进来的参数只是一个Item内存结构,我们需要获取具体的数据,下面继续。

从上面分析我们得知winvista以后的桌面拷贝操作最终使用的是IFileOperation接口,在shell32.dll里对应的就是CFileOperation类

CopyItems对应的就是

继续进入

CFileOperation::_AddOperationMulti

可以看到首先判断DestFile这个参数是否是Folder文件夹,如果是文件夹就是开始枚举ShellItem这个参数,我们继续进入EnumShellItemsFromUnknown函数

从上面我们看出该函数会QueryInterface各个接口:

_GUID_70629033_e363_4a28_a567_0db78006e6d7

_GUID_b63ea76d_1f85_456f_a19c_48159efa858b

_GUID_d0191542_7954_4908_bc06_b2360bbe45ba

_GUID_0000010e_0000_0000_c000_000000000046

如果以上接口都不存在的话,就调用

SHGetIDListFromObjectSHCreateShellItemArrayFromIDLists来获取接口,

在实际调用中发现以上几个不是所有操作系统都支持,而最后两个函数却支持winvista以后的所有系统,所以我们就用最后两个函数来获取源信息,而这两个函数在shell32.dll都是导出的接口定义如下:

HRESULT SHCreateShellItemArrayFromIDLists(

                                _In_  UINT                   cidl,

                              _In_  PCIDLIST_ABSOLUTE_ARRAY rgpidl,

                             _Out_ IShellItemArray        **ppsiItemArray

);

最后获取的是IShellItemArray接口,接口定义为:

  1. MIDL_INTERFACE("b63ea76d-1f85-456f-a19c-48159efa858b")
  2.  
  3. IShellItemArray : public IUnknown
  4. {
  5.  
  6. public:
  7.  
  8. virtual HRESULT STDMETHODCALLTYPE BindToHandler(
  9. /* [unique][in] */ __RPC__in_opt IBindCtx *pbc,
  10. /* [in] */ __RPC__in REFGUID bhid,
  11. /* [in] */ __RPC__in REFIID riid,
  12. /* [iid_is][out] */ __RPC__deref_out_opt void **ppvOut) = ;
  13.  
  14. virtual HRESULT STDMETHODCALLTYPE GetPropertyStore(
  15. /* [in] */ GETPROPERTYSTOREFLAGS flags,
  16. /* [in] */ __RPC__in REFIID riid,
  17. /* [iid_is][out] */ __RPC__deref_out_opt void **ppv) = ;
  18.  
  19. virtual HRESULT STDMETHODCALLTYPE GetPropertyDescriptionList(
  20. /* [in] */ __RPC__in REFPROPERTYKEY keyType,
  21. /* [in] */ __RPC__in REFIID riid,
  22. /* [iid_is][out] */ __RPC__deref_out_opt void **ppv) = ;
  23.  
  24. virtual HRESULT STDMETHODCALLTYPE GetAttributes(
  25. /* [in] */ SIATTRIBFLAGS AttribFlags,
  26. /* [in] */ SFGAOF sfgaoMask,
  27. /* [out] */ __RPC__out SFGAOF *psfgaoAttribs) = ;
  28.  
  29. virtual HRESULT STDMETHODCALLTYPE GetCount(
  30. /* [out] */ __RPC__out DWORD *pdwNumItems) = ;
  31.  
  32. virtual HRESULT STDMETHODCALLTYPE GetItemAt(
  33. /* [in] */ DWORD dwIndex,
  34. /* [out] */ __RPC__deref_out_opt IShellItem **ppsi) = ;
  35.  
  36. virtual HRESULT STDMETHODCALLTYPE EnumItems(
  37. /* [out] */ __RPC__deref_out_opt IEnumShellItems **ppenumShellItems) = ;
  38. };

大致我们可以写出获取信息的文件的函数

  1. UINT
  2. GetFilesFromDataObjectWin(
  3. IUnknown *iUnknown,
  4. LPWSTR **ppPath)
  5. {
  6. HRESULT hr = E_FAIL;
  7. LPITEMIDLIST Pv = NULL;
  8. int nCount = ;
  9. IShellItemArray* ShellItemArray = NULL;
  10. do
  11. {
  12.  
  13. __try
  14. {
  15. hr = SHGetIDListFromObject(iUnknown,&Pv);
  16. if ( FAILED(hr) )
  17. {
  18. break;
  19. }
  20.  
  21. hr = SHCreateShellItemArrayFromIDLists(
  22. TRUE,
  23. (LPCITEMIDLIST *)&Pv,
  24. &ShellItemArray);
  25.  
  26. if ( FAILED(hr) )
  27. {
  28. break;
  29. }
  30.  
  31. hr = ShellItemArray->GetCount((ULONG*)&nCount);
  32.  
  33. if ( !nCount )
  34. {
  35. break;
  36. }
  37.  
  38. *ppPath = new LPWSTR[nCount];
  39. memset(*ppPath,,sizeof(LPWSTR)*nCount);
  40.  
  41. for ( int Index = ; Index < nCount ; Index++)
  42. {
  43. IShellItem* ShellItem = NULL;
  44.  
  45. if( SUCCEEDED(ShellItemArray->GetItemAt(
  46. Index,
  47. &ShellItem)))
  48. {
  49. if ( ShellItem /*&& ShellItem->GetAttributes(
  50. 0x20000000,
  51. &GAof ) == 0 */)
  52. {
  53. LPWSTR Temp = NULL;
  54. if(SUCCEEDED(ShellItem->GetDisplayName(
  55. SIGDN_FILESYSPATH,
  56. &Temp)))
  57. {
  58. __try
  59. {
  60. if ( Temp )
  61. {
  62. int Length = wcslen(Temp);
  63. *ppPath[Index] = new WCHAR[Length + ];
  64. memset(*ppPath[Index],,sizeof(WCHAR)*(Length + ));
  65. wcsncpy(
  66. *ppPath[Index],
  67. Temp,
  68. Length);
  69. CoTaskMemFree(Temp);
  70. Temp = NULL;
  71.  
  72. }
  73. }
  74. __except(EXCEPTION_EXECUTE_HANDLER)
  75. {
  76. if ( Temp )
  77. {
  78. CoTaskMemFree(Temp);
  79. Temp = NULL;
  80. }
  81. }
  82.  
  83. }
  84. }
  85.  
  86. if ( ShellItem )
  87. {
  88. ShellItem->Release();
  89. }
  90.  
  91. }
  92. }
  93. }
  94. __finally
  95. {
  96.  
  97. if ( ShellItemArray )
  98. {
  99. ShellItemArray->Release();
  100. }
  101.  
  102. if ( Pv)
  103. {
  104. CoTaskMemFree(Pv);
  105. }
  106. }
  107.  
  108. } while (FALSE);
  109.  
  110. return nCount;
  111. }

以上是获取源文件的信息,而拷贝目的的信息获取就很简单了,CopyItem的定义的目的中的参数

IShellItem *psiDestinationFolder,中的IShellItem 定义如下

  1. MIDL_INTERFACE("43826d1e-e718-42ee-bc55-a1e261c37bfe")
  2.  
  3. IShellItem : public IUnknown
  4. {
  5.  
  6. public:
  7.  
  8. virtual HRESULT STDMETHODCALLTYPE BindToHandler(
  9. /* [unique][in] */ __RPC__in_opt IBindCtx *pbc,
  10. /* [in] */ __RPC__in REFGUID bhid,
  11. /* [in] */ __RPC__in REFIID riid,
  12. /* [iid_is][out] */ __RPC__deref_out_opt void **ppv) = ;
  13.  
  14. virtual HRESULT STDMETHODCALLTYPE GetParent(
  15. /* [out] */ __RPC__deref_out_opt IShellItem **ppsi) = ;
  16.  
  17. virtual HRESULT STDMETHODCALLTYPE GetDisplayName(
  18. /* [in] */ SIGDN sigdnName,
  19. /* [string][out] */ __RPC__deref_out_opt_string LPWSTR *ppszName) = ;
  20.  
  21. virtual HRESULT STDMETHODCALLTYPE GetAttributes(
  22. /* [in] */ SFGAOF sfgaoMask,
  23. /* [out] */ __RPC__out SFGAOF *psfgaoAttribs) = ;
  24.  
  25. virtual HRESULT STDMETHODCALLTYPE Compare(
  26. /* [in] */ __RPC__in_opt IShellItem *psi,
  27. /* [in] */ SICHINTF hint,
  28. /* [out] */ __RPC__out int *piOrder) = ;
  29.  
  30. };

根据定义我们就可以通过GetDisplayName去获取目的文件的信息:

  1. BOOL
  2. GetDestFolder(IShellItem* psiDestinationFolder, LPWSTR* lpDst )
  3. {
  4. do
  5. {
  6. HRESULT hr = psiDestinationFolder->GetDisplayName(
  7. SIGDN_FILESYSPATH,
  8. lpDst);
  9.  
  10. if(FAILED(hr))
  11. {
  12. break;
  13. }
  14.  
  15. return TRUE;
  16.  
  17. } while (FALSE);
  18.  
  19. return FALSE;
  20. }

综合起来,我们可以实现如下:

  1. HRESULT CFileOperation::CopyItems_new(IFileOperation *pThis, IUnknown *punkItems, IShellItem *psiDestinationFolder)
  2. {
  3. HRESULT hr = CopyItems_old(pThis, punkItems, psiDestinationFolder);
  4.  
  5. LPWSTR lpDst = NULL;
  6. PWSTR* lpSrc = NULL;
  7.  
  8. //获取目的信息
  9. GetDestFolder(psiDestinationFolder, &lpDst) );
  10. //获取源文件信息
  11. GetFilesFromDataObjectWin(punkItems, &lpSrc);
  12. return hr;
  13. }

至此我们就很就精准地截获了windows桌面程序的拷贝、剪切的具体动作,也获取详细的文件名称,我们甚至还能准确地得知该动作是否成功,更加详细的信息就留给读者去研究,总之shell32.dll是个很值得开发人员去研究的,里面有很多意想不到的东西,甚至能写出很简单的程序实现很复杂有效的功能,可以充分利用windows系统给我们提供的便捷的库。

引用

Win7、win8、win10下实现精准截获Explorer拷贝行为 (freebuf)

Win7、win8、win10下实现精准截获Explorer拷贝行为的更多相关文章

  1. Win7/Win8/Win10下安装Ubuntu14.04双系统 以及常见问题

    整理自网络. 1. 制作镜像 将ubantu镜像刻录到优盘(我使用UltraISO刻录,镜像下载地址:链接: http://pan.baidu.com/s/1bndbcGv 密码: qsmb) 2. ...

  2. 通过修改manifest文件来解决Vista/Win7/Win8/win10下应用程序兼容性问题

    https://www.cnblogs.com/snowbook/p/5363990.html

  3. Tomcat 在win7/win8 系统下tomcat-users.xml.new(拒绝访问)解决方法

    tomcat启动报错No UserDatabase component found under key UserDatabase 也可以这样处理 Tomcat 在win7/win8 系统下tomcat ...

  4. win7/win8/win10 系统

    WIN7/WIN8/WIN10 系统安装 http://www.windows7en.com/Win7/18572.html

  5. SQL Server 2000 绿色精简版gsql适用于xp/win7/win8/win10

    老的程序员肯定都用过sql2000数据库,我在2006-2010年之间,做的不少网站也都是sql2000数据库的,但是后来随着mysql的兴起,就逐渐不再使用sql数据库了.但是最近有个客户的网站要修 ...

  6. Win8/Win10下程序经常无响应的解决办法

    如果你使用Win8/Win10系统时经常出现程序无响应的问题不仿试下如下解决办法. 表现症状: 任何程序都有可能出现无响应(记事本.Visual Studio.QQ.视频播放器等) 一旦一个程序出现未 ...

  7. UEFI+GPT安装WIN7,WIN8/WIN10下安装WIN7双系统

    一.BIOS更改 首先来bios更改:我们知道,uefi+gpt引导虽然出来的时间比较长,但是win7还不能完全的支持,所以在使用uefi+gpt安装win7的时候就会出现各种错误!所以我们在安装Wi ...

  8. 最新32位和64位xp,win7,win8,win10系统大全(电脑装机版)

    一.系统主要特点 1.安装维护方便快速 - 全自动无人值守安装,采用万能GHOST技术,安装系统过程只需3-5分钟,适 合新旧各种机型. - 集成常见硬件驱动,智能识别+预解压技术,绝大多数硬件可以快 ...

  9. 2015年度精品 最新力作32位和64位xp,win7,win8,win10系统下载(电脑城专用版)

    一.系统主要特点 1.安装维护方便快速 - 全自动无人值守安装,采用万能GHOST技术,安装系统过程只需3-5分钟,适 合新旧各种机型. - 集成常见硬件驱动,智能识别+预解压技术,绝大多数硬件可以快 ...

随机推荐

  1. 多线程之实现Runnable接口及其优点

    多线程之实现Runnable接口: 1.创建一个Runnable接口的实现类 2.在实现类中重写Runnable接口的run方法 3.创建一个Runnable接口实现类的对象 4.创建Thread类对 ...

  2. shell 里面的计算

    ---恢复内容开始--- 关于shell里面的计算其实早在接触LINUX的时候就已经接触到了.每次在运用的时候却是在网上到处找,所以觉得花点时间好好研究下. 首先了解下常用的算数运算符号: +  - ...

  3. window.location.href 与 window.location.href 的区别

  4. ldap搭建

    yum install openldap openldap-servers openldap-clients -y #检查是否安装成功 slapd -VVopenldap的配置文件都在/etc/ope ...

  5. maven 学习之路之二(1)

    上次我简单讲了maven的安装和构建生命周期. 这一篇博客我将用实际项目来分享下maven整个构建生命周期的具体使用: 这次我将用maven做一个自己写程序的一个模版程序. 自己实现一个简单的页面登录 ...

  6. springboot中使用servlet通过配置类

    在servlet目录下创建个servlet类,示例代码如下: package com.bjpowernode.springboot.servlet; import javax.servlet.Serv ...

  7. npoi c#

    没有安装excel docx的情况下 操作excel docx

  8. SpringBoot 在IDEA中实现热部署(实用版)(引入)

    SpringBoot 在IDEA中实现热部署(实用版) 引用:https://www.jianshu.com/p/f658fed35786 好的热部署让开发调试事半功倍,这样的“神技能”怎么能错过呢, ...

  9. HTML5日期时间输入类型注意事项(time,date)

    原文链接:http://www.webhek.com/post/html5-date.html 1.HTML5规范里只规定date新型input输入类型,并没有规定日历弹出框的实现和样式.所以,各浏览 ...

  10. vue中前进刷新、后退缓存方案收集

    来源掘金: https://juejin.im/post/5b2ce07ce51d45588a7dbf76 来源博客园 https://www.cnblogs.com/wonyun/p/8763314 ...