什么是NoChange?可以看一看这篇文章,自己去感受一下 https://bbs.pediy.com/thread-225080.htm
。添加NoChange 根本目的就是使VirtualProtect(ZwProtectVirtualMemory)这个函数失败。
废话少说,直接进入主题,介绍一下我的整体思路。
第一步:调用 ZwCreateSection 告诉我操作系统我要 SizeOfImage大小的物理内存。
第二步:调用 ZwMapViewOfSection映射内存,然后拷贝 RtlCopyMemory(pViewBase, pInfo->lpBaseOfDll, pInfo->SizeOfImage); 此时这个物理页已经有内容了。
第三步:ZwUnmapViewOfSection(NtCurrentProcess(), pInfo->lpBaseOfDll);
第四步:接下来就是最!最!最!最重要的就是 如何把物理内存重新 映射到指定地址并且加你想要的NoChange属性。我将着重说明一下如何映射(不要嫌我啰嗦):
如果 你完全明白 nCanMapSize 的大小是怎么来的,那么你可以跳过。
涉及一点PE的基础基址,直接看图吧
根据图片可以 ntdll.dll的代码段的最大只能是 0x0117000。
那么 nCanMapSize = 0x0117000,可以吗? 答案是肯定不行的。
需要说明一点:ZwMapViewOfSection(BaseAddress=ntdll.base,nSize=0x0117000)这个函数是会成功,但是接下来映射ntdll的其他数据段起始基址是:BaseAddress=(ntdll.base+0x0117000),此时ZwMapViewOfSection会失败。为什么呢,Msdn告诉我们答案:
坑了我很长时间,其实他的是意思就是 当你BaseAddress指定了值,那么他必须是0x10000的倍数而不是0x1000(靠,我也不知道为什么),因此nCanMapSize必须是 0x120000(当你出现了程序崩溃失败的时候,异常的时候,一般都是这个值的问题),自此我们完成了 关键的步骤喽。顺带看一下某pubg他是怎么重新映射ntdll的
需要注意一点:当你映射ntdll的时候,这个时候你已经卸载他 ZwMapViewOfSection已经不存在,你需要做点额外工作,自己去中断进内核。 。
如果喜欢,请给我一键三连。
方便你们C+V测试
DWORD AddDllNoChange::calcTextSize(MODULEINFO* pInfo,vector<sectionData>& pSectionData)
{
}
BOOL __stdcall AddDllNoChange::AddNoChange(MODULEINFO* pInfo)
{
BOOL bRet = FALSE;
if (!pInfo) return bRet;
}
ULONG AddDllNoChange::BBCastSectionProtection( IN ULONG characteristics, IN BOOLEAN noDEP )
{
ULONG dwResult = PAGE_NOACCESS;
}
PIMAGE_NT_HEADERS pNtHeaders
=
NULL;
PIMAGE_DOS_HEADER pDosHdr
=
(PIMAGE_DOS_HEADER)pInfo
-
>lpBaseOfDll;
pNtHeaders
=
(PIMAGE_NT_HEADERS64)((PUCHAR)pInfo
-
>lpBaseOfDll
+
pDosHdr
-
>e_lfanew);
sectionData dwSection;
DWORD nSize
=
0
;
PIMAGE_SECTION_HEADER pFirstSection
=
(PIMAGE_SECTION_HEADER)(pNtHeaders
+
1
);
if
(IMAGE32(pNtHeaders))
pFirstSection
=
(PIMAGE_SECTION_HEADER)((PIMAGE_NT_HEADERS32)pNtHeaders
+
1
);
for
(PIMAGE_SECTION_HEADER pSection
=
pFirstSection;
pSection < pFirstSection
+
pNtHeaders
-
>FileHeader.NumberOfSections;
pSection
+
+
)
{
if
(IMAGE_SCN_MEM_EXECUTE & pSection
-
>Characteristics)
{
nSize
+
=
pSection
-
>Misc.VirtualSize;
}
else
{
dwSection.VirtualAddress
=
pSection
-
>VirtualAddress;
dwSection.VirtualSize
=
pSection
-
>Misc.VirtualSize;
dwSection.nProtection
=
BBCastSectionProtection(pSection
-
>Characteristics, FALSE);
pSectionData.emplace_back(dwSection);
}
}
if
(nSize >
0x10000
)
{
nSize
=
nSize & (~
0xffff
);
nSize
+
=
0x10000
;
if
((pSectionData.at(
0
).VirtualAddress
+
pSectionData.at(
0
).VirtualSize) >
=
nSize)
{
pSectionData.at(
0
).VirtualAddress
=
nSize;
pSectionData.at(
0
).VirtualSize
=
pSectionData.at(
1
).VirtualAddress
-
pSectionData.at(
0
).VirtualAddress ;
}
else
{
pSectionData.~vector();
}
}
else
{
nSize
=
0
;
}
return
nSize;
PIMAGE_NT_HEADERS pNtHeaders
=
NULL;
PIMAGE_DOS_HEADER pDosHdr
=
(PIMAGE_DOS_HEADER)pInfo
-
>lpBaseOfDll;
pNtHeaders
=
(PIMAGE_NT_HEADERS64)((PUCHAR)pInfo
-
>lpBaseOfDll
+
pDosHdr
-
>e_lfanew);
sectionData dwSection;
DWORD nSize
=
0
;
PIMAGE_SECTION_HEADER pFirstSection
=
(PIMAGE_SECTION_HEADER)(pNtHeaders
+
1
);
if
(IMAGE32(pNtHeaders))
pFirstSection
=
(PIMAGE_SECTION_HEADER)((PIMAGE_NT_HEADERS32)pNtHeaders
+
1
);
for
(PIMAGE_SECTION_HEADER pSection
=
pFirstSection;
pSection < pFirstSection
+
pNtHeaders
-
>FileHeader.NumberOfSections;
pSection
+
+
)
{
if
(IMAGE_SCN_MEM_EXECUTE & pSection
-
>Characteristics)
{
nSize
+
=
pSection
-
>Misc.VirtualSize;
}
else
{
dwSection.VirtualAddress
=
pSection
-
>VirtualAddress;
dwSection.VirtualSize
=
pSection
-
>Misc.VirtualSize;
dwSection.nProtection
=
BBCastSectionProtection(pSection
-
>Characteristics, FALSE);
pSectionData.emplace_back(dwSection);
}
}
if
(nSize >
0x10000
)
{
nSize
=
nSize & (~
0xffff
);
nSize
+
=
0x10000
;
if
((pSectionData.at(
0
).VirtualAddress
+
pSectionData.at(
0
).VirtualSize) >
=
nSize)
{
pSectionData.at(
0
).VirtualAddress
=
nSize;
pSectionData.at(
0
).VirtualSize
=
pSectionData.at(
1
).VirtualAddress
-
pSectionData.at(
0
).VirtualAddress ;
}
else
{
pSectionData.~vector();
}
}
else
{
nSize
=
0
;
}
return
nSize;
HANDLE hSection
=
0
;
LARGE_INTEGER cbSectionOffset
=
{};
PVOID pViewBase
=
NULL;
SIZE_T cbViewSize
=
0
;
NTSTATUS ntstatus
=
0
;
vector<sectionData> dwSectionData;
ULONG nCanMapSize
=
0
;
nCanMapSize
=
calcTextSize(pInfo,dwSectionData);
if
(nCanMapSize <
0x10000
) {
return
bRet;
}
ULONG64 nNextMapAddress
=
nCanMapSize
+
(ULONG64)pInfo
-
>lpBaseOfDll;
ULONG nNextMapSize
=
pInfo
-
>SizeOfImage
-
nCanMapSize;
LARGE_INTEGER cbSectionSize
=
{
0
};
cbSectionSize.QuadPart
=
pInfo
-
>SizeOfImage;
ntstatus
=
ZwCreateSection(
&hSection,
SECTION_ALL_ACCESS,
NULL,
&cbSectionSize,
PAGE_EXECUTE_READWRITE,
SEC_COMMIT,
NULL);
pViewBase
=
0
;
cbSectionOffset.QuadPart
=
0
;
cbViewSize
=
0
;
ntstatus
=
ZwMapViewOfSection(
hSection,
NtCurrentProcess(),
&pViewBase,
0
,
0
,
&cbSectionOffset,
&cbViewSize,
ViewUnmap,
0
,
PAGE_EXECUTE_READWRITE);
if
(NT_SUCCESS(ntstatus))
{
RtlCopyMemory(pViewBase, pInfo
-
>lpBaseOfDll, pInfo
-
>SizeOfImage);
/
/
把内容写入section后,就把当前得 地址 卸载
ntstatus
=
ZwUnmapViewOfSection(NtCurrentProcess(), pViewBase);
ntstatus
=
ZwUnmapViewOfSection(NtCurrentProcess(), pInfo
-
>lpBaseOfDll);
if
(NT_SUCCESS(ntstatus))
{
/
/
映射 代码节区 全给他 PAGE_EXECUTE_READ并且加上 SEC_NO_CHANGE
pViewBase
=
pInfo
-
>lpBaseOfDll;
cbSectionOffset.QuadPart
=
0
;
cbViewSize
=
nCanMapSize;
ntstatus
=
ZwMapViewOfSection(
hSection,
NtCurrentProcess(),
&pViewBase,
0
,
0
,
&cbSectionOffset,
&cbViewSize,
ViewUnmap,
SEC_NO_CHANGE,
PAGE_EXECUTE_READ);
if
(NT_SUCCESS(ntstatus))
{
/
/
映射数据节区 给PAGE_READWRITE
pViewBase
=
(PVOID)nNextMapAddress;
cbSectionOffset.QuadPart
=
nCanMapSize;
cbViewSize
=
nNextMapSize;
ntstatus
=
ZwMapViewOfSection(
hSection,
NtCurrentProcess(),
&pViewBase,
0
,
0
,
&cbSectionOffset,
&cbViewSize,
ViewUnmap,
0
,
PAGE_READWRITE);
if
(NT_SUCCESS(ntstatus) && !dwSectionData.empty())
{
/
/
这个只是 还原数据段 的内存属性 你不喜欢可以不执行
vector<sectionData> ::iterator it
=
dwSectionData.begin();
SIZE_T tmpSize
=
0
;
DWORD OldAccessProtection
=
0
;
ULONG prot
=
0
;
PVOID pAddr
=
NULL;
for
(it; it !
=
dwSectionData.end();
+
+
it)
{
if
(it
-
>nProtection
=
=
PAGE_READONLY)
{
prot
=
it
-
>nProtection;
pAddr
=
(PVOID)((ULONG64)pInfo
-
>lpBaseOfDll
+
it
-
>VirtualAddress);
tmpSize
=
it
-
>VirtualSize;
ZwProtectVirtualMemory(NtCurrentProcess(), &pAddr, &tmpSize, prot, &OldAccessProtection);
}
}
}
}
}
}
if
(hSection) {
CloseHandle(hSection);
}
return
bRet;
HANDLE hSection
=
0
;
LARGE_INTEGER cbSectionOffset
=
{};
PVOID pViewBase
=
NULL;
SIZE_T cbViewSize
=
0
;
NTSTATUS ntstatus
=
0
;
vector<sectionData> dwSectionData;
ULONG nCanMapSize
=
0
;
nCanMapSize
=
calcTextSize(pInfo,dwSectionData);
if
(nCanMapSize <
0x10000
) {
return
bRet;
}
ULONG64 nNextMapAddress
=
nCanMapSize
+
(ULONG64)pInfo
-
>lpBaseOfDll;
ULONG nNextMapSize
=
pInfo
-
>SizeOfImage
-
nCanMapSize;
LARGE_INTEGER cbSectionSize
=
{
0
};
cbSectionSize.QuadPart
=
pInfo
-
>SizeOfImage;
ntstatus
=
ZwCreateSection(
&hSection,
SECTION_ALL_ACCESS,
NULL,
&cbSectionSize,
PAGE_EXECUTE_READWRITE,
SEC_COMMIT,
NULL);
pViewBase
=
0
;
cbSectionOffset.QuadPart
=
0
;
cbViewSize
=
0
;
ntstatus
=
ZwMapViewOfSection(
hSection,
NtCurrentProcess(),
&pViewBase,
0
,
0
,
&cbSectionOffset,
&cbViewSize,
ViewUnmap,
0
,
PAGE_EXECUTE_READWRITE);
if
(NT_SUCCESS(ntstatus))
{
RtlCopyMemory(pViewBase, pInfo
-
>lpBaseOfDll, pInfo
-
>SizeOfImage);
/
/
把内容写入section后,就把当前得 地址 卸载
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2022-9-26 11:02
被一夜酒狂编辑
,原因: