HEAP_ENTRY_BUSY0x02HEAP_ENTRY_EXTRA_PRESENT0x04HEAP_ENTRY_FILL_PATTERN0x08HEAP_ENTRY_VIRTUAL_ALLOC0x10HEAP_ENTRY_LAST_ENTRY0x20HEAP_ENTRY_SETTABLE_FLAG10x40HEAP_ENTRY_SETTABLE_FLAG20x80HEAP_ENTRY_SETTABLE_FLAG3
UCHARFlags
Thisfieldco
tai
sthe
umberofu
usedbytesatthee
dofthisblockthatwere
otactuallyallocatedUsedtocomputeexactsizerequestedpriortorou
di
grequestedsizetoallocatio
gra
ularityAlsousedfortailchecki
gpurposes
UCHARU
usedBytes
Small8bittagi
dexesca
gohere
UCHARSmallTagI
dex
ifdefi
ed_WIN64
fULONGLONGReserved1e
dif
HEAP_ENTRYPHEAP_ENTRY就是本堆的size2bytes上一个堆的size2bytesi
dex1byteflag1byteu
usedbytes1bytesmalltagi
dex1byte注意这里的size是实际大小进行8字节对齐后除以8的值能看看flag的各个定义再看看RtlFreeHeap里面几个关键的地方关键点一001B77FCC8298A4605MOVALESI05esi指向buf2的8字节管理结构的起始地址,al即flag001B77FCC82CA801TESTAL01flag值是否含有HEAP_ENTRY_BUSY001B77FCC82E0F84A40E0000JZ77FCD6D8不含则跳转。这里不能跳001B77FCC834F6C207TESTDL07001B77FCC8370F859B0E0000JNZ77FCD6D8001B77FCC83D807E0440CMPBYTEPTRESI0440esi4是否大于0x40001B77FCC8410F83910E0000JAE77FCD6D8大于等于则跳转,这里不能跳001B77FCC847834DFCFFORDWORDPTREBP0401001B77FCC84BA8E0TESTALE0flag是否含有HEAP_ENTRY_SETTABLE_FLAG123001B77FCC84D754AJNZ77FCC899只要含有一个就跳,这里不重要001B77FCC84F8B8F80050000MOVECXEDI00000580001B77FCC85585C9TESTECXECX001B77FCC8577440JZ77FCC899这里必然会跳关键点二001B77FCC899C745FC01000000MOVDWORDPTREBP0400000001001B77FCC8A0F6C301TESTBL01001B77FCC8A3750FJNZ77FCC8B4这里必然会跳001B77FCC8A5FFB778050000PUSHDWORDPTREDI00000578001B77FCC8ABE853C8FBFFCALL
tdllRtlE
terCriticalSectio
001B77FCC8B0C645D401MOVBYTEPTREBP2C01001B77FCC8B4F6460508TESTBYTEPTRESI0508flag是否含
HEAP_ENTRY_VIRTUAL_ALLOC001B77FCC8B80F858BF2FFFFJNZ77FCBB49含有则跳,这里要跳关键点三001B77FCBB4983C6E8ADDESI18ilsy说在不同的wi
dows版本上这个0x18的是不同的001B77FCBB4C89759CMOVEBP64ESI001B77FCBB4F8B06MOVEAXESI001B77FCBB51894598MOVEBP68EAX
f001B77FCBB548B7604MOVESIESI04001B77FCBB57897594MOVEBP6CESI001B77FCBB5A8906MOVESIEAX这里会操作异常我们看到最后操作异常的时候EAX0X61616161ESI0X61616161正好是buf1里的值,就是将buf2的起始地址减去0x18的地址的数据复制到之后的数据所指向的地址。我们能控制这两个数据。可见第二种方式的前提有三个:1构造堆(buf2)的flag必须含有HEAP_ENr