什么是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后,就把当前得 地址 卸载
[培训]科锐软件逆向54期预科班、正式班开始火爆招生报名啦!!!
最后于 2022-9-26 11:02
被一夜酒狂编辑
,原因: