首页
社区
课程
招聘
[求助] 模块加载回调中使用导入表注入DLL问题
2021-2-28 13:27 7503

[求助] 模块加载回调中使用导入表注入DLL问题

2021-2-28 13:27
7503

第一次程序能正常运行,dll也注入成功.第二次运行程序发现导入表的地址变成不可读,保存导入表那一句代码失败,程序运行不起来了.

 

问题就出在这一句代码
//拷贝原始数据
RtlCopyMemory(pImportNew, pImportDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR) * nImportDllCount);

 

百思不得骑姐啊.

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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
VOID StartInject(
    IN PUNICODE_STRING    FullImageName,
    IN HANDLE    ProcessId, // where image is mapped
    IN PIMAGE_INFO    ImageInfo
    )
{
    NTSTATUS ntStatus;
    PIMAGE_IMPORT_DESCRIPTOR pImportNew;
    HANDLE hProcessHandle=NULL;
    ULONG nImportDllCount = 0;
    SIZE_T size;
    IMAGE_IMPORT_DESCRIPTOR Add_ImportDesc;
    PULONG ulAddress;
    ULONG oldCr0;
    ULONG Func;
    PIMAGE_IMPORT_BY_NAME ptmp;
    IMAGE_THUNK_DATA *pOriginalThunkData;
    IMAGE_THUNK_DATA *pFirstThunkData;
    PIMAGE_BOUND_IMPORT_DESCRIPTOR pBoundImport;
 
    PVOID lpBuffer = NULL;
    PVOID lpDllName = NULL;
    PVOID lpExportApi = NULL;
    PVOID lpTemp = NULL;
    PVOID lpTemp2 = NULL;
 
    do
    {
        PEPROCESS g_eprocess = IoGetCurrentProcess();
 
        //基地址
        ULONG ulBaseImage = (ULONG)ImageInfo->ImageBase;// 进程基地址
        PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)ulBaseImage;
 
        //32位进程的NT头 是PIMAGE_NT_HEADERS32   64位的需要另外定义
        PIMAGE_NT_HEADERS32 pHeader = (PIMAGE_NT_HEADERS32)(ulBaseImage + (ULONG)pDos->e_lfanew);
        IMAGE_OPTIONAL_HEADER32 opt = pHeader->OptionalHeader;
 
        if (opt.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
        {
            WriteErrorLogFile("32位程序 PE可选头解析错误");
            break;
        }
 
        //这里可能出问题  32位程序和64位程序的可选PE头是不一样的
 
        PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)(pHeader->OptionalHeader.DataDirectory[1].VirtualAddress + ulBaseImage);
 
 
 
        //获取导入表的个数
        nImportDllCount = opt.DataDirectory[1].Size / sizeof(IMAGE_IMPORT_DESCRIPTOR);
 
        //打开被注入进程的进程对象
        ntStatus = ObOpenObjectByPointer(g_eprocess, OBJ_KERNEL_HANDLE, NULL, PROCESS_ALL_ACCESS, //PROCESS_WRITECOPY
            NULL, KernelMode, &hProcessHandle);
        if (!NT_SUCCESS(ntStatus))
        {
            WriteErrorLogFile("模块回调中 ObOpenObjectByPointer失败");
            break;
        }
 
        // 数据目录表中的导入表大小增加一个  IMAGE_IMPORT_DESCRIPTOR 结构
        size = sizeof(IMAGE_IMPORT_DESCRIPTOR) * (nImportDllCount + 1);
 
        //  重新分配导入表
        ntStatus = ZwAllocateVirtualMemory(hProcessHandle, &lpBuffer, 0, &size,
            MEM_COMMIT | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
        if (!NT_SUCCESS(ntStatus))
        {
 
            WriteErrorLogFile("模块回调中 重新分配导入表失败");
            break;
        }
 
        RtlZeroMemory(lpBuffer, sizeof(IMAGE_IMPORT_DESCRIPTOR) * (nImportDllCount + 1));
        size = 20;
        // 分配当前进程空间。
        ntStatus = ZwAllocateVirtualMemory(hProcessHandle, &lpDllName, 0, &size,
            MEM_COMMIT | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
        if (!NT_SUCCESS(ntStatus))
        {
 
            WriteErrorLogFile("模块回调中 分配当前进程空间失败");
            break;
        }
        RtlZeroMemory(lpDllName, 20);
 
        size = 20;
        ntStatus = ZwAllocateVirtualMemory(hProcessHandle, &lpExportApi, 0, &size,
            MEM_COMMIT | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
        if (!NT_SUCCESS(ntStatus))
        {
            WriteErrorLogFile("模块回调中 lpExportApi分配失败");
            break;
        }
        RtlZeroMemory(lpExportApi, 20);
 
        // 分配当前进程空间。
        size = 20;
        ntStatus = ZwAllocateVirtualMemory(hProcessHandle, &lpTemp, 0, &size,
            MEM_COMMIT | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
        if (!NT_SUCCESS(ntStatus))
        {
            WriteErrorLogFile("模块回调中 lpExportApi分配失败");
            break;
        }
        RtlZeroMemory(lpTemp, 20);
        // 分配当前进程空间。
        size = 20;
        ntStatus = ZwAllocateVirtualMemory(hProcessHandle, &lpTemp2, 0, &size,
            MEM_COMMIT | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
        if (!NT_SUCCESS(ntStatus))
        {
            break;
        }
        RtlZeroMemory(lpTemp2, 20);
 
        pImportNew = lpBuffer;
 
        //拷贝原始数据
        RtlCopyMemory(pImportNew, pImportDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR) * nImportDllCount);
 
        // 构造自己的DLL    IMAGE_IMPORT_DESCRIPTOR结构
 
 
        pOriginalThunkData = (PIMAGE_THUNK_DATA)lpTemp;
        pFirstThunkData = (PIMAGE_THUNK_DATA)lpTemp2;
 
        ptmp = (PIMAGE_IMPORT_BY_NAME)lpExportApi;
 
        ptmp->Hint = 0;
        // 至少要一个导出API  Inj
        RtlCopyMemory(ptmp->Name, "Inj", strlen("Inj"));
        pOriginalThunkData[0].u1.AddressOfData = (ULONG)ptmp - ulBaseImage;
        pFirstThunkData[0].u1.AddressOfData = (ULONG)ptmp - ulBaseImage;
 
        Add_ImportDesc.FirstThunk = (ULONG)pFirstThunkData - ulBaseImage;
        Add_ImportDesc.TimeDateStamp = 0;
        Add_ImportDesc.ForwarderChain = 0;
        //
        // DLL名字的RVA
        //32位DLL的名字  64位另外设置
        RtlCopyMemory(lpDllName, "jbndakb17.dll", strlen("jbndakb17.dll"));
        Add_ImportDesc.Name = (ULONG)lpDllName - ulBaseImage;
        Add_ImportDesc.Characteristics = (ULONG)pOriginalThunkData - ulBaseImage;
 
        pImportNew += (nImportDllCount - 1);
        RtlCopyMemory(pImportNew, &Add_ImportDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR));
 
        pImportNew += 1;
        RtlZeroMemory(pImportNew, sizeof(IMAGE_IMPORT_DESCRIPTOR));
 
        //关闭写保护
        KIRQL oldIrql = WPOFF();
 
        // 改导出表
 
        pHeader->OptionalHeader.DataDirectory[1].VirtualAddress = (ULONG)(pImportNew - nImportDllCount) - ulBaseImage;
        pHeader->OptionalHeader.DataDirectory[1].Size += sizeof(IMAGE_IMPORT_DESCRIPTOR);
 
        pBoundImport = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)((ULONG)opt.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress
            + ulBaseImage);
 
        if ((ULONG)pBoundImport != ulBaseImage)
        {
            //取消绑定输入表里的所有东西
            opt.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
            opt.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
        }
        WPON(oldIrql);
 
        DbgPrint("注入32位模块完成\n");
    } while (FALSE);
 
    if (NULL != hProcessHandle)
    {
        ZwClose(hProcessHandle);
        hProcessHandle = NULL;
    }
 
 
}

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞0
打赏
分享
最新回复 (1)
雪    币: 887
活跃值: (1260)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Hbruce 2022-11-18 17:04
2
0
PIMAGE_DOS_HEADER 可以得到数据,PIMAGE_NT_HEADERS32 pHeader = (PIMAGE_NT_HEADERS32)(ulBaseImage + (ULONG)pDos->e_lfanew) 得到的 pHeader 数据全是0啊,不管32还是64都是0
游客
登录 | 注册 方可回帖
返回