大家好,我是武汉科锐逆向CR49期的一名学员,我写这篇文章的目的是想帮助刚开始或者准备开始研究windows系统的人员,此篇文章仅作为经验分享,是我在逆向还原windows10堆API CreateHeap
和AllocateHeap
以及AllocateHeapInternal
源代码时总结的一些经验,如有错误请各位前辈斧正。我们仅分享其windows10 ntdll中常见的一些汇编特征优化,如若不涉及的优化请各位自行翻阅资料学习。
对于windows的逆向需要熟悉其内部编译器的汇编代码优化特征才能更好的进行还原,我仅PO出我逆向还原的CreateHeap API代码,而AllocateHeap等其他API代码就不发了。注意:此代码仅作学习用途,且由于是项目原因,所以我给出粗糙版的代码,某些结构体就不发出来了(偏移还在),如果各位感兴趣可以自己进行逆向 还原
typedef struct _SYSTEM_BASIC_INFORMATION {
ULONG Reserved;
/
/
保留字段,通常为
0
ULONG TimerResolution;
/
/
系统定时器的分辨率(以微秒为单位)
ULONG PageSize;
/
/
页面大小(以字节为单位)
ULONG NumberOfPhysicalPages;
/
/
物理页面的数量
ULONG LowestPhysicalPageNumber;
/
/
物理页面的最低编号
ULONG HighestPhysicalPageNumber;
/
/
物理页面的最高编号
ULONG AllocationGranularity;
/
/
内存分配粒度
ULONG MinimumUserModeAddress;
/
/
用户模式下的最小地址
ULONG MaximumUserModeAddress;
/
/
用户模式下的最大地址
ULONG ActiveProcessorsAffinityMask;
/
/
活动处理器的亲和性掩码
UCHAR NumberOfProcessors;
/
/
处理器的数量
} SYSTEM_BASIC_INFORMATION;
/
*
*
Flags : 指定堆的可选属性的标志。
这些选项会影响通过调用堆函数(RtlAllocateHeap和RtlFreeHeap)对新堆的后续访问。
一共有
3
个值
1.
HEAP_GENERATE_EXCEPTIONS 指定系统引发异常而不是通过返回空值即异常堆
2.
HEAP_GROWABLE 可增长堆如果HeapBase为空必须指定
3.
HEAP_NO_SERIALIZE 指定当堆函数从此堆分配和释放内存时不使用互斥。
当未指定 HEAP_NO_SERIALIZE 时,默认是序列化对堆的访问。
序列化堆访问允许两个或多个线程同时从同一堆分配和释放内存。
*
HeapBase: 非空情况下就是将指定分配的地址,如果空的情况下则会在进程空间随机分配
*
ReserveSize:
*
*
*
/
ULONG g_initVar1ByInitalizeProccess
=
0
;
ULONG g_initVar2ByAvrfLoadDll
=
0
;
typedef
int
(__thiscall
*
PFN_4B3A32F4)(DWORD, DWORD, DWORD, DWORD, DWORD, PVOID);
PFN_4B3A32F4 g_4B3A32F4;
PVOID
RtlCreateHeap(
[
in
] ULONG Flags,
[
in
, optional] PVOID HeapBase,
[
in
, optional] SIZE_T ReserveSize,
[
in
, optional] SIZE_T CommitSize,
[
in
, optional] PVOID Lock,
[
in
, optional] PRTL_HEAP_PARAMETERS Parameters
)
{
DWORD var_12C;
DWORD var_120;
DWORD var_110[
10
];
PVOID pLock
=
Lock;
ULONG ulFlags
=
Flags;
PVOID pBase
=
HeapBase;
PVOID pBase2
=
HeapBase;
SIZE_T stReserver
=
ReserveSize;
DWORD var_BC;
SIZE_T stCommit
=
CommitSize;
PVOID pLock2
=
Lock;
DWORD var_CC;
DWORD CriticalSectionFlag;
DWORD var_D8;
DWORD BaseAddress;
BOOL
ntGlobalFlag
=
((PPEB)__readfsdword(
0x30
))
-
>NtGlobalFlag;
ULONG ulUnknow1
=
0
;
DWORD dwRegionSize
=
0
;
ULONG ulUnknow2
=
0
;
ULONG ulUnknow3
=
0
;
DWORD pHeapHandle2;
BYTE var_A8[
0x30
];
DWORD dwCommiteSize;
SYSTEM_BASIC_INFORMATION SystemInformation;
DWORD var_58;
CPPEH_RECORD ms_exc;
/
/
模拟组
DWORD eax
=
0
;
DWORD ecx
=
0
;
DWORD edx
=
(DWORD)Flags;
DWORD ebx
=
0
;
DWORD esi
=
0
;
DWORD edi
=
(DWORD)Parameters;
/
/
进程默认堆
if
(g_initVar1ByInitalizeProccess !
=
NULL
&& pBase
=
=
NULL
&& pLock
=
=
NULL)
{
/
/
不允许应用程序更改策略
RtlpHpAppCompatDontChangePolicy();
/
/
如果用户设置了Commit指针则通过Commit指针来获取堆结果
esi
=
g_4B3A32F4(ulFlags,
0
, stReserver, stCommit,
0
, Parameters);
if
(esi !
=
0
)
{
goto RELEASE_SRC;
}
if
(edi !
=
0xFFFFFFFF
)
{
edi
=
(DWORD)pBase;
esi
=
0
;
goto RELEASE_SRC;
}
}
else
{
if
(g_initVar2ByAvrfLoadDll !
=
0
&& (DWORD)Parameters
=
=
1
)
{
/
*
mov eax, edx
and
eax,
100h
;
if
((eax &
100h
) !
=
0
)
; eax
=
100h
;
if
((eax &
100h
)
=
=
0
)
; eax
=
0
neg eax ;
if
((eax &
100h
) !
=
0
)
; eax
=
100h
-
> FFFF FEFF
;
if
((eax &
100h
)
=
=
0
)
; eax
=
0
-
>
0
sbb eax, eax ;
if
((eax &
100h
) !
=
0
)
; eax
=
100h
-
> FFFF FEFF
-
>
-
1
;
if
((eax &
100h
)
=
=
0
)
; eax
=
0
-
>
0
-
>
0
not
eax ;
if
((eax &
100h
) !
=
0
)
; eax
=
100h
-
> FFFF FEFF
-
>
-
1
-
>
0
;
if
((eax &
100h
)
=
=
0
)
; eax
=
0
-
>
0
-
>
0
-
>
-
1
and
edi, eax ;
if
((eax &
100h
) !
=
0
)
; eax
=
100h
-
> FFFF FEFF
-
>
-
1
-
>
0
-
>
0
;
if
((eax &
100h
)
=
=
0
)
; eax
=
0
-
>
0
-
>
0
-
>
-
1
-
> edi
*
/
edi
=
(edx &
100
)
=
=
0
?
0
: edi;
}
}
/
/
edx
=
edx &
0xF1FFFFFF
;
ulFlags
=
ulFlags &
0xF1FFFFFF
;
if
((ulFlags &
0x100
) !
=
0
)
{
if
(!(LOWORD(ulFlags) &
2
)
|| (DWORD)pBase !
=
ebx
|| ecx
|| stCommit !
=
ebx
|| (DWORD)pLock !
=
ebx)
{
goto RELEASE_SRC;
}
if
(edi
=
=
0xFFFFFFFF
)
{
edi
=
!g_initVar2ByAvrfLoadDll ?
0
: edi;
}
if
(edi !
=
0
)
{
esi
=
edi;
/
/
参数的验证
if
(!RtlpHpParametersVerify(edi))
{
/
/
goto
}
edx
=
ulFlags;
}
else
{
esi
=
pHeapHandle2;
}
}
else
if
(_RtlpHpHeapFeatures !
=
1
)
{
if
(((((LOWORD(edx) &
2
)
&& (DWORD)pBase
=
=
ebx))
/
/
判断堆参数是否支持
&& RtlpHpParametersSupported(edi))
|| edi
=
=
0
)
{
eax
=
2
;
if
((DWORD)pLock2
=
=
ebx)
{
esi
=
(DWORD)&pHeapHandle2;
}
}
}
if
(esi !
=
0
)
{
eax
=
(DWORD)&pHeapHandle2;
if
(esi
=
=
eax)
{
memset((PBYTE)esi,
0
,
0x30u
);
*
(WORD
*
)esi
=
2
;
*
(WORD
*
)((BYTE
*
)esi
+
2
)
=
0x30
;
*
(DWORD
*
)((BYTE
*
)esi
+
0xC
)
=
1
;
*
(DWORD
*
)((BYTE
*
)esi
+
0x10
) |
=
0xFFFFFFFF
;
}
if
((
*
((BYTE
*
)(esi
+
0x4
)) &
1
))
{
if
(g_initVar2ByAvrfLoadDll
=
=
0
)
{
esi
=
0
;
goto RELEASE_SRC;
}
RtlpHpAppCompatDontChangePolicy();
esi
=
g_4B3A32F4(ulFlags,
0
, stReserver, stCommit,
0
, Parameters);
goto RELEASE_SRC;
}
else
{
eax
=
(DWORD)RtlpHpEnvGetEnvHandleFromParams(esi);
edi
=
(DWORD)stReserver;
if
(edi
=
=
0
)
/
/
如果Reserver 是
0
则给出Commit的大小
{
edi
=
stCommit;
}
if
(eax > edi)
{
eax
=
edi;
}
/
/
通过RtlpHpHeapCreate创建堆然后将堆移动到堆链表中去
if
(!RtlpHpHeapCreate(
RtlpHpConvertCreationFlags(ulFlags,
ntGlobalFlag),
edi,
eax,
ecx,
edx))
{
goto RELEASE_SRC;
}
/
/
移动链表
RtlpMoveHeapBetweenLists(esi, edx,
1
, ebx);
if
(
*
(WORD
*
)(esi
+
0x14
)
=
=
LOWORD(ebx))
{
goto RELEASE_SRC;
}
RtlpHpHeapDestroy(esi);
esi
=
ebx;
goto RELEASE_SRC;
}
}
if
(!(ulFlags &
0x10000000
))
{
if
(_RtlpHeapErrorHandlerThreshold >
=
2
&& (ulFlags &
0xFFF80C00
))
{
if
(((PPEB)__readfsdword(
0x30
))
-
>Ldr)
{
/
/
_DbgPrint();
/
/
这里正常来讲应该是一个结构体而不是强转
+
偏移
/
/
但是为了赶项目进度暂时翻译为偏移的形式
printf(
"HEAP[%wZ]: "
,
*
(DWORD
*
)(
*
(DWORD
*
)(__readfsdword(
0x30
)
+
0xc
)
+
0xc
)
+
0x2c
);
}
else
{
/
/
dbg p
printf(
"HEAP: "
);
}
/
/
dbg p
printf(
"!(CheckedFlags & ~HEAP_CREATE_VALID_MASK)"
);
/
/
if
(byte_4B3A5DA8
=
=
0
)
{
RtlpReportHeapFailure(
2
);
}
/
/
edx
=
ulFlags;
}
/
*
if
(edx &
0xFFF80C00
)
{
edx &
=
0x7F3FF
;
}
*
/
if
(ulFlags &
0xFFF80C00
)
{
ulFlags &
=
0x7F3FF
;
}
}
/
/
ebx 万年老
0
, 这里推断var_A8是个结构体
/
/
或许初始化为 STRUCT var_A8 {
0
};
/
/
不过考虑到WINDOWS是C语言开发的
/
/
也不清楚微软内部编译器支持的语言规范版本
/
/
暂时设置为memset
memset(var_A8,
0
,
0x30
);
if
(edi !
=
0
)
{
/
/
这里对SEH进行一些设置
ms_exc.registration.TryLevel
=
0
;
if
(edi
=
=
esi)
{
memcpy((PBYTE)edi, var_A8,
0xc
);
}
ms_exc.registration.TryLevel
=
0xFFFFFFFE
;
}
/
/
这里的汇编为test cl,
20h
但是ntGlobalFlag
/
/
为
4
字节我不想翻译为强转只能祈祷编译器对取低位有优化
if
(ntGlobalFlag &
0xff
&
0x10
)
{
ulFlags |
=
0x20
;
}
if
(ntGlobalFlag &
0xff
&
0x20
)
{
ulFlags |
=
0x40
;
}
if
(ntGlobalFlag &
0x200000
)
{
ulFlags |
=
0x80
;
}
if
(ntGlobalFlag &
0xff
&
0x40
)
{
ulFlags |
=
0x40000000
;
}
if
(ntGlobalFlag &
0xff
&
0x80
)
{
ulFlags |
=
0x20000000
;
}
if
(ntGlobalFlag &
0x1000
)
{
ulFlags |
=
0x8000000
;
}
ecx
=
__readfsdword(
0x30
);
/
/
这里的var_a8应该是个结构体之后要改一下可以通过PEB的成员反推
/
/
var_a8的成员
if
(!var_A8[
1
])
{
var_A8[
1
]
=
*
(DWORD
*
)(ecx
+
0x78
);
}
if
(!var_A8[
2
])
{
var_A8[
2
]
=
*
(DWORD
*
)(ecx
+
0x7c
);
}
if
(!var_A8[
3
])
{
var_A8[
3
]
=
*
(DWORD
*
)(ecx
+
0x84
);
}
if
(!var_A8[
4
])
{
var_A8[
4
]
=
*
(DWORD
*
)(ecx
+
0x80
);
}
if
(!dword_4B3A6940)
{
dword_4B3A6944
=
0x10000
;
/
/
首先是查询系统信息
if
(NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS::SystemBasicInformation,
&SystemInformation,
0x2c
,
0
) <
0
)
{
goto RELEASE_SRC;
}
dword_4B3A6940
=
var_58;
edx
=
0x1000
;
}
/
/
接下来是对页段的操作
/
/
貌似这里是在对页进行处理
-
0x1000
的操作正是在将
/
/
前面的设置为页首
if
(!var_A8[
5
])
{
var_A8[
5
]
=
dword_4B3A6940
-
dword_4B3A6944
-
0x1000
;
}
/
/
最大值为
0x7F000
if
(!var_A8[
6
] || var_A8[
6
] >
0x7F000
)
{
var_A8[
6
]
=
0x7F000
;
}
/
/
加了一些什么值
if
(stCommit)
{
stCommit
=
(stCommit
+
0xFFF
) &
0xFFFFF000
;
}
/
*
edi
=
stReserver;
if
(edi !
=
0
)
{
ecx
=
edi
+
0XFFF
;
ecx &
=
0xFFFFF000
;
var_BC
=
ecx;
}
*
/
if
(stReserver)
{
var_BC
=
(stReserver
+
0xFFF
) &
0xFFFFF000
;
}
else
{
var_BC
=
(stCommit
+
0xFFFF
) &
0xFFFF0000
;
}
/
*
mov [ebp
+
var_BC], ecx ; ecx
=
var_BC
mov esi, edx ; edx
=
dwCommiteSize
; esi
=
dwCommiteSize
cmp
edx, ecx
ja markif19
*
/
/
/
计算得到最大堆块大小:最大堆块大小实际上是
0x7f000
,即
0x80000
减去一个页面。
/
/
最大块大小为
0xfe00
,粒度偏移为
3
if
(stCommit > var_BC)
{
stCommit
=
var_BC;
esi
=
var_BC;
}
/
/
获取传入的堆参数块,根据PEB设置堆参数块的值,
/
/
根据PEB
-
>NtGlobalFlag设置堆块的标志
/
/
ebx
=
0
if
(!(ulFlags &
0xff
&
2
) && pBase !
=
NULL)
{
ntGlobalFlag
=
0
;
}
else
{
ntGlobalFlag
=
0x1000
;
ulUnknow1
=
2
;
/
/
eax
=
var_BC
-
0x1000
;
if
(stCommit < var_BC
-
0x1000
)
{
var_BC
=
(var_BC
+
0x10fff
) &
0xffff0000
;
}
}
if
(!stCommit || !var_BC)
{
esi
=
0
;
goto RELEASE_SRC;
}
/
/
返回调试堆
if
(ulFlags &
0x61000000
)
{
if
(!(ulFlags &
0x10000000
))
{
return
(PVOID)RtlDebugCreateHeap(ulFlags, pBase, var_BC, stCommit, pLock2, &var_A8);
}
}
stReserver
=
0x258
;
if
(!(ulFlags &
0xff
&
1
))
{
if
(pLock2)
{
ulFlags |
=
0x80000000
;
}
CriticalSectionFlag
=
(DWORD)(pLock2 ? pLock2 :
0
);
stReserver
=
!pLock2 ?
0x270
:
0x252
;
}
else
{
if
(pLock2 !
=
0
)
{
esi
=
0
;
goto RELEASE_SRC;
}
}
/
/
如果调用者提供的堆基地址为
0
,调用ZwAllocateVirtualMemory从内存管理器分配内存
if
(pBase
=
=
0
)
{
BaseAddress
=
0
;
if
(var_A8[
9
] !
=
(DWORD)pBase)
{
esi
=
0
;
goto RELEASE_SRC;
}
pLock
=
(PVOID)RtlpHeapGenerateRandomValue32();
var_BC
=
ebx;
/
/
eax
=
RtlpSecMemFreeVirtualMemory(ecx, edx, &var_BC,
0x8000
)
/
/
| BaseAddress &
0x1f
<<
0x10
;
var_D8
=
RtlpHeapGenerateRandomValue32()
| BaseAddress &
0x1f
<<
0x10
;
dwRegionSize
=
var_D8
+
var_BC;
if
(dwRegionSize < var_BC)
{
dwRegionSize
=
var_BC;
var_D8
=
BaseAddress;
}
if
(NtAllocateVirtualMemory(
-
1
,
&BaseAddress,
0
,
&dwRegionSize,
0x2000
,
(ulFlags &
0x40000
)
=
=
0
?
4
:
64
) <
0
)
{
esi
=
0
;
goto RELEASE_SRC;
}
pHeapHandle2
=
BaseAddress;
var_BC
=
dwRegionSize;
if
(var_D8 !
=
0
)
{
RtlpSecMemFreeVirtualMemory(var_BC, &BaseAddress, &var_D8,
0x8000
);
pHeapHandle2
=
BaseAddress
+
var_D8;
var_BC
=
dwRegionSize
-
var_D8;
}
var_CC
=
BaseAddress
+
var_D8;
stCommit
=
BaseAddress
+
var_D8;
}
else
{
if
(var_A8[
0
] !
=
0
)
{
if
(var_A8[
6
]
=
=
0
|| var_A8[
7
]
=
=
0
|| var_A8[
6
] > var_A8[
7
] || ulFlags &
0xff
!
=
2
)
{
esi
=
0
;
goto RELEASE_SRC;
}
var_CC
=
(DWORD)pBase;
stCommit
=
(DWORD)pBase
+
(DWORD)pLock2;
var_BC
=
var_A8[
7
];
memset(pBase,
0
,
0x1000
);
esi
=
ulFlags;
}
else
{
/
/
pBase2需要切换为结构体
if
(NtQueryVirtualMemory(
-
1
, pBase,
0
, &var_110,
0x1c
,
0
) <
0
|| var_110[
0
] !
=
stCommit
|| var_110[
3
]
=
=
0x10000
)
{
esi
=
0
;
goto RELEASE_SRC;
}
/
/
根据传入的ReserveSize和CommitSize设置堆块的保留页面和提交页面
var_CC
=
(DWORD)var_110;
if
(var_110[
3
]
=
=
0x1000
)
{
var_BC
=
var_110[
2
];
if
(stCommit > var_BC)
{
stCommit
=
var_BC;
}
if
(stCommit <
0x1000
)
{
esi
=
0
;
goto RELEASE_SRC;
}
esi
=
ulFlags;
}
else
{
if
((ulFlags &
0x40000
))
{
if
(var_110[
4
] &
0x40
)
{
goto RELEASE_SRC;
}
}
/
/
此时,已获得一个堆指针、已提交的基址、未提交的基址、段标志、
/
/
提交大小和保留大小。
/
/
如果已提交和未提交的基地址相同,那么我们需要调用ZwAllocateVirtualMemory提交由ComitSize指定的数量
memset(var_110,
0
,
0x1000
);
if
(NtQueryVirtualMemory(
-
1
, pBase,
3
, &var_12C,
0x1c
,
0
) <
0
)
{
esi
=
0
;
goto RELEASE_SRC;
}
var_BC
=
var_120;
stCommit
=
var_110[
2
];
dwCommiteSize
=
stCommit
+
var_CC;
}
}
var_110[
10
] |
=
1
;
pHeapHandle2
=
(DWORD)pBase;
ulFlags &
=
0x40000
;
ecx
=
stCommit;
eax
=
var_CC;
}
/
/
edi
=
pBase
if
(var_CC
=
=
stCommit)
{
if
(NtAllocateVirtualMemory(
-
1
, &var_CC,
0
, &dwCommiteSize,
0x1000
, (ulFlags &
40000
)
=
=
0
?
4
:
64
) <
0
)
{
esi
=
0
;
goto RELEASE_SRC;
}
if
(RtlGetCurrentServiceSessionId())
{
eax
=
__readfsdword(
0x30
);
ecx
=
*
(DWORD
*
)(eax
+
0x50
);
ecx
+
=
0x226
;
}
else
{
/
/
从这里进入
0
环
ecx
=
0x7FFE0380
;
}
if
(
*
(BYTE
*
)ecx !
=
0
)
{
if
(
*
(BYTE
*
)(__readfsdword(
0x30
)
+
0x240
) !
=
1
)
{
RtlpLogHeapCommit(pHeapHandle2, var_CC, dwCommiteSize,
1
);
}
}
stCommit
=
stCommit
+
dwCommiteSize;
}
/
/
edi
=
HeapHandle
+
258h
if
(
*
(DWORD
*
)(__readfsdword(
0x30
)
+
0x68
) !
=
0x800
)
{
/
*
;ecx
=
*
(DWORD
*
)(pHeapHandle2
+
0x258
+
0x7
) &
0xFFFFFFF8
;
*
(DWORD
*
)(pHeapHandle2
+
0xBC
)
=
ecx;
stReserver
=
ecx;
edi
=
*
(DWORD
*
)(pHeapHandle2
+
0xBC
)
+
ecx;
ulFlags |
=
0x4000000
;
esi
=
ulFlags;
*
/
*
(DWORD
*
)(pHeapHandle2
+
0xBC
)
=
*
(DWORD
*
)(pHeapHandle2
+
0x258
+
0x7
) &
0xFFFFFFF8
;
stReserver
=
*
(DWORD
*
)(pHeapHandle2
+
0x258
+
0x7
) &
0xFFFFFFF8
;
edi
=
*
(DWORD
*
)(pHeapHandle2
+
0xBC
)
+
*
(DWORD
*
)(pHeapHandle2
+
0x258
+
0x7
) &
0xFFFFFFF8
;;
ulFlags |
=
0x4000000
;
esi
=
ulFlags;
}
var_110[
9
]
=
(stReserver
+
7
) &
0xFFFFFFF8
;
/
/
ecx
=
var_110[
9
]
/
8
;
*
(WORD
*
)pHeapHandle2
=
var_110[
9
]
/
8
;
*
(WORD
*
)(pHeapHandle2
+
2
)
=
1
;
*
(WORD
*
)(pHeapHandle2
+
7
)
=
1
;
*
(DWORD
*
)(pHeapHandle2
+
0x60
)
=
0xEEFFEEFF
;
*
(DWORD
*
)(pHeapHandle2
+
0x40
)
=
ulFlags &
0xEFFFFFFF
;
*
(DWORD
*
)(pHeapHandle2
+
0x58
)
=
0
;
memset((BYTE
*
)pHeapHandle2
+
0x1F4
,
0
,
0x5C
);
/
/
实际上这里的参数应该为
*
_HEAP_HANDLE
/
/
这里是对堆头进行加密
RtlpCreateHeapEncoding((PVOID)pHeapHandle2);
*
(DWORD
*
)(pHeapHandle2
+
0x234
)
=
1
;
if
(
*
(DWORD
*
)(pHeapHandle2
+
0x40
) &
0x8000000
)
{
/
/
这里或许是获取拦截器索引
/
*
基于此猜测我们给出如下的一些定义
typedef DWORD(__stdcall
*
INTERCEPTOR_PFN)(DWORD, DWORD, DWORD, DWORD);
DWORD
NTAPI
RtlpGetHeapInterceptorIndex(INTERCEPTOR_PFN);
INTERCEPTOR_PFN RtlpStackTraceDatabaseLogPrefix;
*
/
/
*
mov ecx, offset _RtlpStackTraceDatabaseLogPrefix@
16
; RtlpStackTraceDatabaseLogPrefix(x,x,x,x)
call _RtlpGetHeapInterceptorIndex@
4
; RtlpGetHeapInterceptorIndex(x)
movzx eax, ax 值得注意的是这里用了movzx但是对于movzx来讲是取用了低位所以我们有必要考虑
/
/
返回的是一个
4
字节的结构体而非一个DWORD,但是我们不知道语义所以这里给出LOWORD来取代结构体
mov [esi
+
58h
], eax
*
/
*
(DWORD
*
)(pHeapHandle2
+
0x58
)
=
(DWORD)LOWORD(RtlpGetHeapInterceptorIndex(RtlpStackTraceDatabaseLogPrefix));
*
(DWORD
*
)(pHeapHandle2
+
0x40
)
=
0xFFFFFFBF
;
}
*
(DWORD
*
)(pHeapHandle2
+
0x44
)
=
ulFlags &
0x6001007D
;
/
/
这里的还原存疑
/
*
edi 来源
lea edi, [edx
+
258h
] ; edx
=
heapHandle
...
mov ecx, edi ; edi
=
heapHandle
+
0x258
mov eax, [ebp
+
HeapHandle]
sub ecx, eax ; ecx
=
0x258
mov [eax
+
7Eh
], cx
mov eax, [ebp
+
HeapHandle]
*
/
*
(WORD
*
)(pHeapHandle2
+
0x7E
)
=
LOWORD(
0x258
);
/
/
ebx 万年老
0
*
(DWORD
*
)(pHeapHandle2
+
0x80
)
=
0
;
/
/
eax
=
pHeapHandle2
+
0xc0
;
/
/
*
(DWORD
*
)(eax
+
4
)
=
eax;
*
(DWORD
*
)(pHeapHandle2
+
0xc4
)
=
pHeapHandle2
+
0xc0
;
*
(DWORD
*
)(pHeapHandle2
+
0xc0
)
=
pHeapHandle2
+
0xc0
;
/
/
eax
=
pHeapHandle2
+
0x9c
;
/
/
*
(DWORD
*
)(eax
+
4
)
=
eax;
/
/
*
(DWORD
*
)(eax)
=
eax;
*
(DWORD
*
)(pHeapHandle2
+
0x9c
+
4
)
=
pHeapHandle2
+
0x9c
;
*
(DWORD
*
)(pHeapHandle2
+
0x9c
)
=
pHeapHandle2
+
0x9c
;
*
(DWORD
*
)(pHeapHandle2
+
0xA4
+
4
)
=
pHeapHandle2
+
0xA4
;
*
(DWORD
*
)(pHeapHandle2
+
0xA4
)
=
pHeapHandle2
+
0xA4
;
*
(DWORD
*
)(pHeapHandle2
+
0x8C
+
4
)
=
pHeapHandle2
+
0x8C
;
*
(DWORD
*
)(pHeapHandle2
+
0x8C
)
=
pHeapHandle2
+
0x8C
;
if
(!CriticalSectionFlag && !(ulFlags &
0xff
&
1
))
{
/
/
CriticalSectionFlag
=
edi;
CriticalSectionFlag
=
pHeapHandle2
+
0x258
;
if
(RtlInitializeCriticalSectionEx(CriticalSectionFlag,
0
,
0x10000000
) <
0
)
{
/
/
return
0
;
esi
=
0
;
goto RELEASE_SRC;
}
edi
+
=
0x18
;
ecx
=
CriticalSectionFlag;
}
*
(DWORD
*
)(pHeapHandle2
+
0xC8
)
=
CriticalSectionFlag;
*
(DWORD
*
)(pHeapHandle2
+
0x48
) |
=
0x80000000
;
if
(!(RtlpInitializeHeapSegment(pHeapHandle2,
pHeapHandle2,
var_110[
9
]
+
0x238
,
CriticalSectionFlag,
var_110[
0xA
],
var_CC,
stCommit,
var_CC
-
var_110[
0xE
]
+
var_BC) &
0xff
))
{
esi
=
0
;
goto RELEASE_SRC;
}
esi
=
0x80
;
if
(pBase !
=
0
)
{
memset((BYTE
*
)pHeapHandle2
+
0x258
+
0x18
,
0
,
0x80
);
}
*
(DWORD
*
)(pHeapHandle2
+
0x258
+
0x4
)
=
0x80
;
*
(DWORD
*
)(pHeapHandle2
+
0x258
+
0x1c
)
=
pHeapHandle2
+
0x258
+
0x24
;
*
(DWORD
*
)(pHeapHandle2
+
0x258
+
0x18
)
=
pHeapHandle2
+
0xc0
;
*
(DWORD
*
)(pHeapHandle2
+
0x258
+
0x20
)
=
pHeapHandle2
+
0x258
+
0x24
+
0x10
;
RtlpPopulateListIndex(pHeapHandle2, pHeapHandle2
+
0x258
);
*
(WORD
*
)(pHeapHandle2
+
0x7c
)
=
0
;
*
(DWORD
*
)(pHeapHandle2
+
0x64
)
=
var_A8[
0
];
*
(DWORD
*
)(pHeapHandle2
+
0x68
)
=
var_A8[
1
];
*
(DWORD
*
)(pHeapHandle2
+
0x6c
)
=
var_A8[
2
]
/
8
;
*
(DWORD
*
)(pHeapHandle2
+
0x70
)
=
var_A8[
3
]
/
8
;
*
(DWORD
*
)(pHeapHandle2
+
0x78
)
=
var_A8[
4
]
/
8
;
*
(DWORD
*
)(pHeapHandle2
+
0x5c
)
=
(var_A8[
5
]
+
7
)
/
8
;
*
(DWORD
*
)(pHeapHandle2
+
0xcc
)
=
(var_A8[
8
] ^ _RtlpHeapKey);
*
(DWORD
*
)(pHeapHandle2
+
0x250
)
=
4
;
*
(DWORD
*
)(pHeapHandle2
+
0x254
)
=
0xFE000
;
if
(_RtlpDisableHeapLookaside !
=
1
)
{
/
/
test byte ptr _RtlpDisableHeapLookaside, dl
*
(DWORD
*
)(pHeapHandle2
+
0x48
)
=
1
;
}
if
(!(ulFlags &
0x10000
))
{
*
(DWORD
*
)(pHeapHandle2
+
0x94
)
=
0xf
;
*
(DWORD
*
)(pHeapHandle2
+
0x98
)
=
0xFFFFFFF8
;
}
if
(
*
(DWORD
*
)(pHeapHandle2
+
0x40
) &
0x20
)
{
*
(DWORD
*
)(pHeapHandle2
+
0x94
)
+
=
8
;
}
*
(DWORD
*
)(pHeapHandle2
+
0xE4
)
=
0
;
*
(WORD
*
)(pHeapHandle2
+
0xE8
)
=
0
;
*
(WORD
*
)(pHeapHandle2
+
0xEA
)
=
0
;
*
(WORD
*
)(pHeapHandle2
+
0xEB
)
=
0
;
*
(DWORD
*
)(pHeapHandle2
+
0xE8
)
=
0
;
/
/
根据快表的标志初始化块表
if
(((ulFlags &
3
)
=
=
2
) && ((_RtlpDisableHeapLookaside &
1
)
=
=
0
))
{
*
(DWORD
*
)(pHeapHandle2
+
0xEC
)
=
RtlAllocateHeap((PMY_HEAPSTRUCT)pHeapHandle2,
0x80000A
,
0x100
);
if
(!(
*
(DWORD
*
)(pHeapHandle2
+
0xEC
)))
{
goto RELEASE_SRC;
}
*
(BYTE
*
)(pHeapHandle2
-
1
)
=
1
;
*
(BYTE
*
)(pHeapHandle2
+
0xf0
)
=
0x80
;
}
/
/
函数指针传入
/
*
*
暂时给出如下定义
typedef DWORD(__stdcall
*
RtlpProcessHeapsListLock_PFN)();
DWORD
NTAPI
RtlEnterCriticalSection(RtlpProcessHeapsListLock_PFN);
RtlpProcessHeapsListLock_PFN _RtlpProcessHeapsListLock;
*
/
RtlEnterCriticalSection(_RtlpProcessHeapsListLock);
/
/
添加堆到链表
RtlpAddHeapToUnprotectedList(pHeapHandle2);
/
/
离开临界区
RtlLeaveCriticalSection(_RtlpProcessHeapsListLock);
if
(!
*
(DWORD
*
)(pHeapHandle2
+
0x7c
))
{
esi
=
0
;
goto RELEASE_SRC;
}
if
(RtlGetCurrentServiceSessionId())
{
eax
=
__readfsdword(
0x30
);
eax
=
*
(DWORD
*
)(eax
+
0x50
);
eax
+
=
0x226
;
}
else
{
eax
=
0x7FFE0380
;
}
if
(
*
(BYTE
*
)eax !
=
0
&& (
*
(BYTE
*
)(__readfsdword(
0x30
)
+
0x240
) &
1
))
{
if
(RtlGetCurrentServiceSessionId())
{
esi
=
*
(DWORD
*
)(__readfsdword(
0x30
)
+
0x50
)
+
0x226
;
}
RtlpLogHeapCreateEvent(pHeapHandle2, ulFlags, var_BC, dwCommiteSize, (DWORD)
*
(BYTE
*
)esi);
}
else
{
esi
=
ulFlags;
}
if
(RtlGetCurrentServiceSessionId())
{
eax
=
__readfsdword(
0x30
);
eax
=
*
(DWORD
*
)(eax
+
0x50
);
eax
+
=
0x230
;
}
else
{
eax
=
0x7FFE0388
;
}
if
(
*
(BYTE
*
)eax !
=
0
)
{
/
/
记录创建的堆范围
RtlpHeapLogRangeCreate(pHeapHandle2, var_BC, ulFlags);
}
*
(DWORD
*
)(pHeapHandle2
+
0x48
) &
=
0x7FFFFFFF
;
*
(DWORD
*
)(pHeapHandle2
+
0xd0
)
=
0
;
esi
=
pHeapHandle2;
/
/
返回值
pHeapHandle2
=
0
;
CriticalSectionFlag
=
0
;
/
*
*
这里为统一出口用于释放资源与返回值
此函数返回值为HeapHandle
*
/
RELEASE_SRC:
/
/
todo
edi
=
(DWORD)pBase;
edx
=
(DWORD)pLock2;
eax
=
ulUnknow3;
if
(eax !
=
0
&& eax !
=
edx)
{
RtlDeleteCriticalSection(eax);
}
if
(ulUnknow2 !
=
0
&& edi
=
=
0
)
{
var_BC
=
0
;
/
/
eax
=
RtlpSecMemFreeVirtualMemory(ecx, edx, &var_BC,
0x8000
)
/
/
| BaseAddress &
0x1f
<<
0x10
;
var_D8
=
RtlpSecMemFreeVirtualMemory(ecx, (PVOID)edx, &var_BC,
0x8000
)
| BaseAddress &
0x1f
<<
0x10
;
}
RET:
return
(PVOID)esi;
}