一、前言

  堆对于开发者一般来说是熟悉又陌生的,熟悉是因为我们常常使用new/delete或者malloc/free使用堆,陌生是因为我们基本没有去了解堆的结构。堆在什么地方?怎么申请?怎么释放?系统又是怎么管理堆的呢?

  带着疑问,这两天看了<软件漏洞分析技术>与<漏洞战争>中关于堆的说明,终于对于堆有一点点的了解了。这里记录一下在学习和调试中的一点笔记。

二、关于堆的基本知识

  1).首先了解空闲双向链表和快速单向链表的概念

  1.空闲双向链表(空表)

  空闲堆块的块首中包含一对重要的指针,这对指针用于将空闲堆块组织成双向链表。按照堆块的大小不同,空表总共被分为128条。

  堆区一开始的堆表区中有一个128项的指针数组,被称作空表索引(Freelist array)。该数组的每一项包括两个指针,用于标识一条空表。

  如图所示,空表索引的第二项(free[1])标识了堆中所有大小为8字节的空闲堆块。之后每个索引项指示的空闲堆块递增8字节。例如free[2]为16字节的空闲堆块,free[3]为24字节的空闲堆块,free[127]为1016字节的空闲堆块。
        空闲堆块的大小 = 索引项(ID) x 8(字节)
  把空闲堆块按照大小的不同链入不同的空表,可以方便堆管理系统高效检索指定大小的空闲堆块。需要注意的是,空表索引的第一项(free[0])所标识的空表相对比较特殊。这条双向链表链入了所有大于等于1024字节的堆块(小于512KB),升序排列。

  

  2.快速单项链表(快表)

  快表是Windows用来加速堆块分配而采用的一种堆表。这里之所以叫做"快表"是因为这类单项链表中从来不会发生堆块合并(其中的空闲块块首被设置为占用态,用来防止堆块合并)

  快表也有128条,组织结构与空表类似,只是其中的堆块按照单项链表组织。

  快表总是被初始化为空,而且每条快表最多只有4个结点,故很快就会被填满。

  

  2)堆块的结构

  堆块分为块首和块身,实际上,我们使用函数申请得到的地址指针都会越过8字节(32位系统)的块首,直接指向数据区(块身)。堆块的大小包括块首在内的,如果申请32字节,实际会分配40字节,8字节的块首+32字节的块身。同时堆块的单位是8字节,不足8字节按8字节分配。堆块分为占用态和空闲态。

  其中空闲态结构为:

  占用态结构为

  空闲态将块首后8个字节用于存放空表指针了。

  在64位系统,块首大小为16字节,按16字节对齐。

  

  3)堆块的分配和释放

  1.堆块分配

  堆块分配可以分为三类:快表分配、普通空表分配和零号空表(free[0]分配)。

  从快表中分配堆块比较简单,包括寻找到大小匹配的空闲堆块、将其状态修改为占用态、把它从堆表中"卸下"、最后返回一个指向堆块快身的指针给程序使用。
  普通空表分配时首先寻找最优的空闲块分配,若失败,则寻找次优的空闲块分配,即最小的能满足要求的空闲块。
  零号空表中按照大小升序链着大小不同的空闲块,故在分配时先从free[0]反向查找最后一个块(即最大块),看能否满足要求,如果满足要求,再正向搜索最小能满足要求的空闲堆块进行分配。
  当空表中无法找到匹配的"最优"堆块时,一个稍大些的块会被用于分配,这种次优分配发生时,会先从大块中按请求的大小精确地"割"出一块进行分配,然后给剩下的部分重新标注块首,链入空表。
  由于快表只有在精确匹配才会分配,所以不存在上述现象。

  

  2.堆块的释放
  释放堆块的操作包括将堆块状态改为空闲,链入相应的堆表。所有的释放块都链入堆表的末尾,分配的时候也先从堆表末尾拿。
  另外需要强调,快表最多只有4项。

  3.堆块的分配和释放

  在具体进行堆块分配和释放时,根据操作内存大小不同,Windows采取的策略也会有所不同。可以把内存按照大小分为三类:

      小块:Size < 1KB
      大块:1KB < Size < 512KB
      巨块:Size >= 512KB

                            分配  释放
 小块

首先进行快表分配
   若快表分配失败,进行普通空表分配
   若普通空表分配失败,使用堆缓存分配
   若堆缓存分配失败,尝试零号空表分配(freelist[0])
   若零号空表分配失败,进行内存紧缩后在尝试分配
   若仍无法分配,返回NULL

优先链入快表(只能链入4个空闲块)
如果快表满,则将其链入相应的空表

 大块

首先使用堆缓存进行分配
   若堆缓存分配失败,使用free[0]中的大块进行分配

优先将其放入堆缓存
若堆缓存满,将链入freelist[0]

 巨块

一般来说巨块申请非常罕见,要用到虚分配方法(实际上并不是从堆区分配的)
   这种类型的堆块在堆溢出利用中几乎不会遇到

 直接释放,没有堆表操作

  

  在分配的过程中需要注意的几点是:

  (1)快表中的空闲块被设置为占用态,故不会发生堆块合并操作,且只能精确匹配时才会分配。

  (2)快表是单链表,操作比双链表简单,插入删除都少用很多指令

  (3)快表只有4项,很容易被填满,因此空表也是被频繁使用的

 三、调试堆在PEB中的数据结构

  1)完成C代码,在x64下编译为Release版本,运行

#include "stdafx.h"
#include <Windows.h>
#include <iostream>
using namespace std;extern "C" PVOID64 _cdecl GetPebx64();
int _tmain(int argc, _TCHAR* argv[])
{PVOID64 Peb = 0;Peb = GetPebx64();printf("Peb is 0x%p\r\n",Peb);HANDLE hHeap;char *heap;char str[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";  //0x20
hHeap = HeapCreate(HEAP_GENERATE_EXCEPTIONS,0x1000,0xffff);getchar();   //用于暂停,便于调试器附加
heap = (char*)HeapAlloc(hHeap,0,0x20);printf("Heap addr:0x%08p\r\n",heap);strcpy(heap,str);printf("str is %s\r\n",heap);cin>>Peb;HeapFree(hHeap,0,heap);  //释放
    HeapDestroy(hHeap);cin>>Peb;return 0;
}

  其中GetPebx64()函数为使用.asm文件的汇编,通过gs:[0x60]获得

.CODEGetPebx64 PROC mov rax,gs:[60h]retGetPebx64 ENDP
END

  运行结果为

  我们使用Windbg附加,查看PEB结构

0:001> dt _PEB 0x000007FFFFFDB000
ntdll!_PEB+0x000 InheritedAddressSpace : 0 ''+0x001 ReadImageFileExecOptions : 0 ''+0x002 BeingDebugged    : 0x1 ''+0x003 BitField         : 0x8 ''+0x003 ImageUsesLargePages : 0y0+0x003 IsProtectedProcess : 0y0+0x003 IsLegacyProcess  : 0y0+0x003 IsImageDynamicallyRelocated : 0y1+0x003 SkipPatchingUser32Forwarders : 0y0+0x003 SpareBits        : 0y000+0x008 Mutant           : 0xffffffff`ffffffff Void+0x010 ImageBaseAddress : 0x00000001`3f050000 Void+0x018 Ldr              : 0x00000000`77522640 _PEB_LDR_DATA+0x020 ProcessParameters : 0x00000000`00242170 _RTL_USER_PROCESS_PARAMETERS+0x028 SubSystemData    : (null)  +0x030 ProcessHeap      : 0x00000000`00240000 Void        //进程默认堆的地址+0x038 FastPebLock      : 0x00000000`7752a960 _RTL_CRITICAL_SECTION+0x040 AtlThunkSListPtr : (null) +0x048 IFEOKey          : (null) +0x050 CrossProcessFlags : 0+0x050 ProcessInJob     : 0y0+0x050 ProcessInitializing : 0y0+0x050 ProcessUsingVEH  : 0y0+0x050 ProcessUsingVCH  : 0y0+0x050 ProcessUsingFTH  : 0y0+0x050 ReservedBits0    : 0y000000000000000000000000000 (0)+0x058 KernelCallbackTable : (null) +0x058 UserSharedInfoPtr : (null) +0x060 SystemReserved   : [1] 0+0x064 AtlThunkSListPtr32 : 0+0x068 ApiSetMap        : 0x000007fe`ff710000 Void+0x070 TlsExpansionCounter : 0+0x078 TlsBitmap        : 0x00000000`77522590 Void+0x080 TlsBitmapBits    : [2] 0x11+0x088 ReadOnlySharedMemoryBase : 0x00000000`7efe0000 Void+0x090 HotpatchInformation : (null) +0x098 ReadOnlyStaticServerData : 0x00000000`7efe0a90  -> (null) +0x0a0 AnsiCodePageData : 0x000007ff`fffa0000 Void+0x0a8 OemCodePageData  : 0x000007ff`fffa0000 Void+0x0b0 UnicodeCaseTableData : 0x000007ff`fffd0028 Void+0x0b8 NumberOfProcessors : 4+0x0bc NtGlobalFlag     : 0+0x0c0 CriticalSectionTimeout : _LARGE_INTEGER 0xffffe86d`079b8000+0x0c8 HeapSegmentReserve : 0x100000             //堆的默认保留大小+0x0d0 HeapSegmentCommit : 0x2000                //堆的默认提交大小+0x0d8 HeapDeCommitTotalFreeThreshold : 0x10000  //解除提交的总空闲块阈值+0x0e0 HeapDeCommitFreeBlockThreshold : 0x1000   //解除提交的单块阈值+0x0e8 NumberOfHeaps    : 5                      //进程堆的数量+0x0ec MaximumNumberOfHeaps : 0x10               //ProcessHeaps数组目前的大小  +0x0f0 ProcessHeaps     : 0x00000000`7752a6c0  -> 0x00000000`00240000 Void  //一个数组,记录了每一个堆的地址+0x0f8 GdiSharedHandleTable : (null) +0x100 ProcessStarterHelper : (null) +0x108 GdiDCAttributeList : 0+0x110 LoaderLock       : 0x00000000`77527490 _RTL_CRITICAL_SECTION+0x118 OSMajorVersion   : 6+0x11c OSMinorVersion   : 1+0x120 OSBuildNumber    : 0x1db1+0x122 OSCSDVersion     : 0x100+0x124 OSPlatformId     : 2+0x128 ImageSubsystem   : 3+0x12c ImageSubsystemMajorVersion : 5+0x130 ImageSubsystemMinorVersion : 2+0x138 ActiveProcessAffinityMask : 0xf+0x140 GdiHandleBuffer  : [60] 0+0x230 PostProcessInitRoutine : (null) +0x238 TlsExpansionBitmap : 0x00000000`77522580 Void+0x240 TlsExpansionBitmapBits : [32] 1+0x2c0 SessionId        : 1+0x2c8 AppCompatFlags   : _ULARGE_INTEGER 0x0+0x2d0 AppCompatFlagsUser : _ULARGE_INTEGER 0x0+0x2d8 pShimData        : (null) +0x2e0 AppCompatInfo    : (null) +0x2e8 CSDVersion       : _UNICODE_STRING "Service Pack 1"+0x2f8 ActivationContextData : 0x00000000`00140000 _ACTIVATION_CONTEXT_DATA+0x300 ProcessAssemblyStorageMap : (null) +0x308 SystemDefaultActivationContextData : 0x00000000`00130000 _ACTIVATION_CONTEXT_DATA+0x310 SystemAssemblyStorageMap : (null) +0x318 MinimumStackCommit : 0+0x320 FlsCallback      : 0x00000000`0027fe90 _FLS_CALLBACK_INFO+0x328 FlsListHead      : _LIST_ENTRY [ 0x00000000`0027fa70 - 0x00000000`0027fa70 ]+0x338 FlsBitmap        : 0x00000000`77522570 Void+0x340 FlsBitmapBits    : [4] 3+0x350 FlsHighIndex     : 1+0x358 WerRegistrationData : (null) +0x360 WerShipAssertPtr : (null) +0x368 pContextData     : 0x00000000`00150000 Void+0x370 pImageHeaderHash : (null) +0x378 TracingFlags     : 0+0x378 HeapTracingEnabled : 0y0+0x378 CritSecTracingEnabled : 0y0+0x378 SpareTracingBits : 0y000000000000000000000000000000 (0)

  我们可以使用dd 0x00000000`7752a6c0查看进程堆的地址

  也可以使用!heap -h 命令查看进程堆的地址和分配的大小

  而我们可以看到运行结果中分配的地址4A0A90,正好在段4A0000中。

  2)堆的相关结构

  我们首先了解下面几个结构_HEAP_ENTRY,_HEAP_SEGMENT,_HEAP。

  1._HEAP_ENTRY就是块首,下面是一个64位系统堆块的结构,我们在申请得到的地址减去0x10,就可以得到HEAP_ENTRY的首地址。

                  

   2._HEAP_SEGMENT是段结构,我们可以这么认为,堆申请内存的大小是以段为单位的,当新建一个堆的时候,系统会默认为这个堆分配一个段叫0号段,通过刚开始的new和malloc分配的空间都是在这个段上分配的,当这个段用完的时候,如果当初创建堆的时候指明了HEAP_GROWABLE这个标志,那么系统会为这个堆在再分配一个段,这个时候新分配的段就称为1号段了,以下以此类推。每个段的开始初便是HEAP_SEGMENT结构的首地址,由于这个结构也是申请的一块内存,所以它前面也会有个HEAP_ENTRY结构: 

  我们使用Windbg查看HEAP_SEGMENT结构如下:

ntdll!_HEAP_SEGMENT  +0x000 Entry            : _HEAP_ENTRY+0x010 SegmentSignature : Uint4B+0x014 SegmentFlags     : Uint4B+0x018 SegmentListEntry : _LIST_ENTRY+0x028 Heap             : Ptr64 _HEAP    //段所属的堆+0x030 BaseAddress      : Ptr64 Void      //段的基地址+0x038 NumberOfPages    : Uint4B      //段的内存页数+0x040 FirstEntry       : Ptr64 _HEAP_ENTRY  //第一个堆块(HEAP_ENTRY指针,堆块一般位于HEAP_SEGMENT后面)+0x048 LastValidEntry   : Ptr64 _HEAP_ENTRY  //堆块的边界值+0x050 NumberOfUnCommittedPages : Uint4B    //尚未提交的内存页数+0x054 NumberOfUnCommittedRanges : Uint4B    //UnCommittedRanges数组元素数+0x058 SegmentAllocatorBackTraceIndex : Uint2B+0x05a Reserved         : Uint2B+0x060 UCRSegmentList   : _LIST_ENTRY

  

  3._HEAP结构

  HEAP结构则是记录了这个堆的信息,这个结构可以找到HEAP_SEGMENT链表入口,空闲内存链表的入口,内存分配粒度等等信息。HEAP的首地址便是堆句柄的值,但是堆句柄的值又是0号段的首地址也是堆句柄,何解?其实很简单,0号段的HEAP_SEGMENT就在HEAP结构里面,HEAP结构类定义如这样:

0:001> dt ntdll!_HEAP 4a0000  +0x000 Entry            : _HEAP_ENTRY+0x010 SegmentSignature : 0xffeeffee+0x014 SegmentFlags     : 0+0x018 SegmentListEntry : _LIST_ENTRY [ 0x00000000`004a0128 - 0x00000000`004a0128 ]+0x028 Heap             : 0x00000000`004a0000 _HEAP+0x030 BaseAddress      : 0x00000000`004a0000 Void+0x038 NumberOfPages    : 0x10+0x040 FirstEntry       : 0x00000000`004a0a80 _HEAP_ENTRY+0x048 LastValidEntry   : 0x00000000`004b0000 _HEAP_ENTRY+0x050 NumberOfUnCommittedPages : 0xe+0x054 NumberOfUnCommittedRanges : 1+0x058 SegmentAllocatorBackTraceIndex : 0+0x05a Reserved         : 0+0x060 UCRSegmentList   : _LIST_ENTRY [ 0x00000000`004a1fe0 - 0x00000000`004a1fe0 ]+0x070 Flags            : 0x1004         //堆标志+0x074 ForceFlags       : 4              //强制标志+0x078 CompatibilityFlags : 0            +0x07c EncodeFlagMask   : 0x100000+0x080 Encoding         : _HEAP_ENTRY+0x090 PointerKey       : 0x5c50b3ba`3fc7668b +0x098 Interceptor      : 0+0x09c VirtualMemoryThreshold : 0xff00      //最大堆块大小+0x0a0 Signature        : 0xeeffeeff        //HEAP结构的签名+0x0a8 SegmentReserve   : 0x100000          //段的保留空间大小+0x0b0 SegmentCommit    : 0x2000            //每次提交内存的大小+0x0b8 DeCommitFreeBlockThreshold : 0x100   //解除提交的单块阈值+0x0c0 DeCommitTotalFreeThreshold : 0x1000  //解除提交的总空闲块阈值+0x0c8 TotalFreeSize    : 0x151             //空闲块的总大小+0x0d0 MaximumAllocationSize : 0x000007ff`fffdefff   //可分配的最大值+0x0d8 ProcessHeapsListIndex : 5        //本堆在进程堆列表中的索引+0x0da HeaderValidateLength : 0x208     //头结构的验证长度+0x0e0 HeaderValidateCopy : (null) +0x0e8 NextAvailableTagIndex : 0    //下一个可用的堆块标记索引+0x0ea MaximumTagIndex  : 0         //最大的堆块标记索引+0x0f0 TagEntries       : (null)    //指向用于标记堆块的标记结构+0x0f8 UCRList          : _LIST_ENTRY [ 0x00000000`004a1fd0 - 0x00000000`004a1fd0 ]   //UnCommitedRange Segments+0x108 AlignRound       : 0x1f   +0x110 AlignMask        : 0xffffffff`fffffff0    //用于地址对齐的掩码+0x118 VirtualAllocdBlocks : _LIST_ENTRY [ 0x00000000`004a0118 - 0x00000000`004a0118 ] +0x128 SegmentList      : _LIST_ENTRY [ 0x00000000`004a0018 - 0x00000000`004a0018 ]  //段链表HEAP_SEGMENT+0x138 AllocatorBackTraceIndex : 0+0x13c NonDedicatedListLength : 0    //用于记录回溯信息+0x140 BlocksIndex      : 0x00000000`004a0230 Void+0x148 UCRIndex         : (null) +0x150 PseudoTagEntries : (null)  +0x158 FreeLists        : _LIST_ENTRY [ 0x00000000`004a0ac0 - 0x00000000`004a0ac0 ]  //空闲块链表数组+0x168 LockVariable     : 0x00000000`004a0208 _HEAP_LOCK  //用于串行化控制的同步对象+0x170 CommitRoutine    : 0x5c50b3ba`3fc7668b     long  +5c50b3ba3fc7668b+0x178 FrontEndHeap     : (null)     //用于快速释放堆块的"前端堆"+0x180 FrontHeapLockCount : 0      //"前端堆"的锁定计数+0x182 FrontEndHeapType : 0 ''      //"前端堆"的类型+0x188 Counters         : _HEAP_COUNTERS+0x1f8 TuningParameters : _HEAP_TUNING_PARAMETERS

  对比一下上面HEAP_SEGMENT的结构,可以发现HEAP中就包含一个HEAP_SEGMENT结构。

              

 四、定位申请的内存

  我们知道我们申请的内存地址为4A0A90,根据前面学习的,4A0A90-0x10 = 4A0A80就是_HEAP_ENTRY的地址,而该地址在段4a0000中

  1)我们使用!heap -a 4a0000查该堆的内容

0:001> !heap -a 4a0000
Index   Address  Name      Debugging options enabled5:   004a0000 Segment at 00000000004a0000 to 00000000004b0000 (00002000 bytes committed)Flags:                00001004ForceFlags:           00000004
    Granularity:          16 bytesSegment Reserve:      00100000Segment Commit:       00002000DeCommit Block Thres: 00000100DeCommit Total Thres: 00001000Total Free Size:      00000151Max. Allocation Size: 000007fffffdefffLock Variable at:     00000000004a0208Next TagIndex:        0000Maximum TagIndex:     0000Tag Entries:          00000000PsuedoTag Entries:    00000000Virtual Alloc List:   004a0118Uncommitted ranges:   004a00f8004a2000: 0000e000  (57344 bytes)FreeList[ 00 ] at 00000000004a0158: 00000000004a0ac0 . 00000000004a0ac0  00000000004a0ab0: 00030 . 01510 [100] - freeSegment00 at 004a0000:Flags:           00000000Base:            004a0000First Entry:     004a0a80Last Entry:      004b0000Total Pages:     00000010Total UnCommit:  0000000eLargest UnCommit:00000000UnCommitted Ranges: (1)Heap entries for Segment00 in Heap 00000000004a0000address: psize . size  flags   state (requested size)00000000004a0000: 00000 . 00a80 [101] - busy (a7f)00000000004a0a80: 00a80 . 00030 [101] - busy (20)00000000004a0ab0: 00030 . 01510 [100]00000000004a1fc0: 01510 . 00040 [111] - busy (3d)00000000004a2000:      0000e000      - uncommitted bytes.

  可以看到内存粒度问16字节

 Granularity:          16 bytes

  继续往下看可以发现堆中正好有地址为4a0a80的一项

00000000004a0a80: 00a80 . 00030 [101] - busy (20)

  第一项为地址,第二项a80为上一项的堆块大小,0x30为该堆块的大小,[101]为是这个内存的标志位,最右边的1表示内存块被占用,然后busy(20)表示这块内存被占用,申请的内存为0x20,加上块首的大小为0x10,一共是0x30

  

  2)我们知道了_HEAP_ENTRY的地址为4a0a80,我们查看该结构体

  

  发现这里的Size和我们的0x30完全不符!

  我们可以看上面的_HEAP结构,Win7下面的_HEAP结构比XP多了两项

   +0x07c EncodeFlagMask   : 0x100000+0x080 Encoding         : _HEAP_ENTRY

  相对于XP,Vista之后增加了对堆块的头结构(HEAP_ENTRY)的编码。编码的目的是引入随机性,增加堆的安全性,防止黑客轻易就可以预测堆的数据结构内容而实施攻击。在_HEAP结构中新增了如下两个字段:

  其中的EncodeFlagMask用来指示是否启用编码功能,Encoding字段是用来编码的,编码的方法就是用这个Encoding结构与每个堆块的头结构做亦或(XOR)

  读取_HEAP偏移为0x80的Encoding子结构:注意Size字段是从偏移8开始的两个字节,不是从偏移0开始

  

  我们使用dd查看我们的HEAP_ENTRY信息

  

  做异或解码:

0:001> ?2b552b39^29542b3a
Evaluate expression: 33619971 = 00000000`02010003

  低地址的word是Size字段,所以Size字段是0x3,因为是以0x10为内存粒度的,所以字节大小为

0:001> ?3*0x10
Evaluate expression: 48 = 00000000`00000030

  也就是0x30,与我们显示出的正好一致

  

  3)内存中的数据

  

  

五、总结

  1.在PEB中保存这进程的堆地址和数量。

  2.HEAP结构记录HEAP_SEGMENT的方式采用了链表,这样不再受数组大小的约束,同时将HEAP_SEGMENT字段包含进HEAP,这样各堆段的起始便统一为HEAP_SEGMENT,不再有xp下0号段与其他段那种区别,可以统一进行管理了。

  3.每个HEAP_SEGMENT都有多个堆块,每个堆块包含块首和块身,块身为我们申请得到的地址。

  下一篇会研究堆溢出。

  代码链接:http://pan.baidu.com/s/1bpBm8W3

 参考:

  windbg调试HEAP

  堆和堆的调试

  <软件漏洞分析技术>

  <漏洞战争>

  

转载于:https://www.cnblogs.com/aliflycoris/p/5914663.html

Windows7 x64 了解堆相关推荐

  1. 虚拟机VMware12下安装windows7 x64系统使用教程

    2019独角兽企业重金招聘Python工程师标准>>> 学习编程的童鞋,有的时候在安装一些软件的时候会出现一些问题至失败而导致系统内的残余文件以及注册表残留,那么我们可以在VMwar ...

  2. 如何在Windows7 x64 上安装oracle10g

    如何在Windows7 x64上安装oracle10g 安装Oracle for x64 vista Windows7安装Oracle 10g x64版的时候出现: 解决方案: 1. 直接有效的办法: ...

  3. Windows7 x64在Wampserver上安装memcache

    2019独角兽企业重金招聘Python工程师标准>>> Windows7 x64在Wampserver上安装memcache 放假重装了一下系统,win7 x64的,而我使用的win ...

  4. 2022年安装Windows7 x64 专业版系统更新提示错误代码80072EFE,解决办法【亲测有限】

    2022年安装Windows7 x64 专业版系统更新提示错误代码80072EFE. 系统镜像: 文件名 cn_windows_7_professional_with_sp1_vl_build_x64 ...

  5. windows7 x64系统安装VC++6.0的方法探讨

    破解方法: 运行setup.exe安装程序,会弹出如下的的程序兼容性助手提示:此程序存在已知的兼容性问题,这个是Win7在警告用户VC++6.0存在兼容性问题:此程序存在已知的兼容性问题.如下图,选中 ...

  6. 64位驱动 hp630打印机_HP Deskjet 1280打印机x64驱动下载|HP1280打印机windows7 x64位驱动 - 驱动无忧...

    支持windows7 32位及X64位系统的HP Deskjet 1280打印机驱动程序,解压后需要手动指定驱动位置方式安装.已测试能用. 32位驱动文件: HPF900AL.DLL HPFIMG50 ...

  7. Windows7 X64 虚拟光驱

    本人机器 是6G的内存, 所以不得不用X64的操作系统. 但是X64的系统还真是有不少兼容性的问题. 虚拟光驱先尝试了DAEMON Tools Lite  Version: 4.35.5, 直接报告: ...

  8. 00001、如何在Windows7(x64)上安装 Sharepoint2010 Fundation

    一.修改Config.xml文件 到目录:"C:\Program Files (x86)\MSECache\SharePoint2010\Files\Setup"下去修改confi ...

  9. GPT分区下安装Windows7 x64 完整教程

    关于EFI的介绍,就不赘述了. 大家可以看看维基百科的介绍 http://zh.wikipedia.org/wiki/UEFI 在网上找了EFI安装win7 64位的教程,大多是从光盘启动安装,虽然这 ...

最新文章

  1. 数学知识--Unconstrained Optimization(第二章)
  2. HTML5 Canvas translate与rotate应用
  3. linux下的c socket编程(4)--server端的继续研究
  4. K8S控制器类型:RC/RS、Deployment、DaemonSet、Job和CronJob、StatefulSet、HPA
  5. taskspawn函数 linux,vxworks的启动任务taskSpawn
  6. MYSQL重置ROOT密码
  7. 专家观点:即使在云中 硬件同样至关重要
  8. 数位dp模板 最高位最低位_无纸化办公入门指南(数位板篇)
  9. oracle函数 授权,如何在Oracle中以普通用户身份运行dbms_crypto函数?
  10. oracle服务名连接慢,数据库 – Oracle SID和服务名称;连接问题
  11. java部分_java基础部分
  12. 3.2 Zend_Db_Select
  13. python discover()没有加载测试用例_Python系统学习 - Unittest
  14. (转)在FlashBuilder里的ActionScript工程中使用Flash CS5中的类 fl.controls库
  15. 笔画输入法6.8豪华版 破解版
  16. 验证手机号或座机号的合法性
  17. 用两个半图片来看图片
  18. Char Popp加入PSB担任高级副总裁兼全球定性研究主管
  19. CentOS 7 下 MySQL 5.7环境部署
  20. webrtc丢包率与jitter计算

热门文章

  1. preventExtention、freeze、seal及isExtensible、isFrozen 、isSealed比较
  2. 思维导图怎么画:多方法绘制自己喜欢的思维导图技巧
  3. 误将 “百度”写入公司资料表,B站“抄作业”实锤
  4. IDEA 学生 免费教育许可证 领取教程
  5. iframe简单使用实例
  6. NOIP知识汇总及模板整理
  7. Cocos精品|不毁童年的情怀手游《葫芦娃》
  8. 泰山OFFICE技术讲座:页面空白(页边距)是怎么算的
  9. 深度学习-nlp系列(4):Word2Vec 字词向量的训练和使用
  10. linux压缩包解压安装mysql教程