如何保护自己的代码?给自己的代码添加NoChange属性
2022-9-27 01:23:13 Author: bbs.pediy.com(查看原文) 阅读量:8 收藏

什么是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;

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

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;


文章来源: https://bbs.pediy.com/thread-274535.htm
如有侵权请联系:admin#unsafe.sh