如何保护自己的代码?给自己的代码添加NoChange属性

admin 2022年10月7日22:57:21评论30 views字数 5368阅读17分53秒阅读模式

如何保护自己的代码?给自己的代码添加NoChange属性

本文为看雪论坛优秀文章

看雪论坛作者ID:一夜酒狂


什么是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属性。我将着重说明一下如何映射:
如何保护自己的代码?给自己的代码添加NoChange属性
如果你完全明白 nCanMapSize 的大小是怎么来的,那么你可以跳过。

涉及一点PE的基础基址,直接看图吧。
如何保护自己的代码?给自己的代码添加NoChange属性
根据图片可以 ntdll.dll的代码段的最大只能是 0x0117000。
那么 nCanMapSize = 0x0117000,可以吗?答案是肯定不行的。

需要说明一点:ZwMapViewOfSection(BaseAddress=ntdll.base,nSize=0x0117000)这个函数是会成功,但是接下来映射ntdll的其他数据段起始基址是:BaseAddress=(ntdll.base+0x0117000),此时ZwMapViewOfSection会失败。为什么呢,Msdn告诉我们答案:
如何保护自己的代码?给自己的代码添加NoChange属性
坑了我很长时间,其实他的是意思就是:当你BaseAddress指定了值,那么他必须是0x10000的倍数而不是0x1000(其实我也不知道为什么),因此nCanMapSize必须是 0x120000(当你出现了程序崩溃失败的时候,异常的时候,一般都是这个值的问题),自此我们完成了 关键的步骤。顺带看一下某pubg他是怎么重新映射ntdll的。
如何保护自己的代码?给自己的代码添加NoChange属性
需要注意一点:当你映射ntdll的时候,这个时候你已经卸载他 ZwMapViewOfSection已经不存在,你需要做点额外工作,自己去中断进内核。 如何保护自己的代码?给自己的代码添加NoChange属性 如何保护自己的代码?给自己的代码添加NoChange属性
如果喜欢,请给我一键三连。
如何保护自己的代码?给自己的代码添加NoChange属性
方便你们C+V测试
DWORD AddDllNoChange::calcTextSize(MODULEINFO* pInfo,vector<sectionData>& pSectionData)
{
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;
}
BOOL __stdcall AddDllNoChange::AddNoChange(MODULEINFO* pInfo)
{
BOOL bRet = FALSE;
if (!pInfo) 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后,就把当前得 地址 卸载    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;
}
ULONG AddDllNoChange::BBCastSectionProtection( IN ULONG characteristics, IN BOOLEAN noDEP )
{
ULONG dwResult = PAGE_NOACCESS;
if (characteristics & IMAGE_SCN_MEM_DISCARDABLE){    dwResult = PAGE_NOACCESS;}else if (characteristics & IMAGE_SCN_MEM_EXECUTE){    if (characteristics & IMAGE_SCN_MEM_WRITE)        dwResult = noDEP ? PAGE_READWRITE : PAGE_EXECUTE_READWRITE;    else if (characteristics & IMAGE_SCN_MEM_READ)        dwResult = noDEP ? PAGE_READONLY : PAGE_EXECUTE_READ;    else        dwResult = noDEP ? PAGE_READONLY : PAGE_EXECUTE;}else{    if (characteristics & IMAGE_SCN_MEM_WRITE)        dwResult = PAGE_READWRITE;    else if (characteristics & IMAGE_SCN_MEM_READ)        dwResult = PAGE_READONLY;    else        dwResult = PAGE_NOACCESS;} return dwResult;
}



如何保护自己的代码?给自己的代码添加NoChange属性


看雪ID:一夜酒狂

https://bbs.pediy.com/user-home-877765.htm

*本文由看雪论坛 一夜酒狂 原创,转载请注明来自看雪社区

如何保护自己的代码?给自己的代码添加NoChange属性

2.5折门票限时抢购如何保护自己的代码?给自己的代码添加NoChange属性

峰会官网:https://meet.kanxue.com/kxmeet-6.htm



# 往期推荐

1.CVE-2022-21882提权漏洞学习笔记

2.wibu证书 - 初探

3.win10 1909逆向之APIC中断和实验

4.EMET下EAF机制分析以及模拟实现

5.sql注入学习分享

6.V8 Array.prototype.concat函数出现过的issues和他们的POC们



如何保护自己的代码?给自己的代码添加NoChange属性



如何保护自己的代码?给自己的代码添加NoChange属性

球分享

如何保护自己的代码?给自己的代码添加NoChange属性

球点赞

如何保护自己的代码?给自己的代码添加NoChange属性

球在看



如何保护自己的代码?给自己的代码添加NoChange属性

点击“阅读原文”,了解更多!

原文始发于微信公众号(看雪学苑):如何保护自己的代码?给自己的代码添加NoChange属性

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年10月7日22:57:21
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   如何保护自己的代码?给自己的代码添加NoChange属性http://cn-sec.com/archives/1333675.html

发表评论

匿名网友 填写信息