吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 7741|回复: 6
收起左侧

[C&C++ 原创] [vc] dll永久注入exe文件

  [复制链接]
舒默哦 发表于 2020-5-22 18:45
本帖最后由 舒默哦 于 2020-5-22 20:07 编辑




说明:
就是把dll文件拉伸贴在exe文件后面,先执行dll,然后跳回主程序入口继续执行。(其实,dll想什么时候执行就什么时候执行,具体看需求)



遇到的问题:
这儿修复IAT表,不能是静态修复,因为计算机每次重启,系统dll映射到exe程序所在的地址都会变,IAT表必须动态修复。
修复IAT表需要用到"LoadLibraryA"和GetProcAddress两个函数,这两个函数存在于KERNEL32这个DLL中,
可以通过FS寄存器找到进程环境块PEB,得到kernel32的地址,找到GetProcAddress函数所在地址,再通过GetProcAddress找到LoadLibraryA的地址。




具体步骤:
1、分别加载exe和dll到内存
2、给exe添加新节
3、处理dll(拉伸dll和以及修复重定位表)
4、申请新内存(大小=exe文件大小+新节大小)
5、获取dll的入口函数的指针
6、构造ShellCode
7、修改程序入口,跳到ShellCode地址处执行
8、保存文件




实验测试文件用到了LoadPE.exe和test_dll.dll,最后输出的文件是newfile.exe。

test_dll.dll
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
CString str = "\t注入成功!!!!!\r\n\r\n";
str = str + "\tDLL模块在进程空间中的起始地址:" + (DWORD)hModule;
MessageBox(NULL, str.GetString(), "恭喜", MB_OK);
 
 
}
 
case DLL_THREAD_ATTACH:
//MessageBox(NULL, "DLL_THREAD_ATTACH", "", MB_OK);
case DLL_THREAD_DETACH:
//MessageBox(NULL, "DLL_THREAD_DETACH", "", MB_OK);
case DLL_PROCESS_DETACH:
//MessageBox(NULL, "DLL_PROCESS_DETACH", "", MB_OK);
break;
}
return TRUE;
}


main.cpp
[C] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
#include <iostream>
#include <Windows.h>
#include "CString.h"
#include "Shellcode.h"
#define path_exe "c:\\LoadPE.exe"
#define out_path "c:\\newfile.exe"
#define path_dll "C:\\Users\\daddy\\Desktop\\软件代码区\\dll库\\test_dll\\Release\\test_dll.dll"
 
#define GET_HEADER_DICTIONARY(module, idx)        &(module)->headers->OptionalHeader.DataDirectory[idx]
 
#ifdef _WIN64
#define POINTER_TYPE ULONGLONG
#else
#define POINTER_TYPE DWORD
#endif
 
//获取文件的在内存的地址和大小
int GetBuffAddrAndSizeofFile(char* FilePath, _Out_  DWORD* buff, _Out_ DWORD* FileSize, _Out_ DWORD* FileSize1);
//修复重定位表
void PerformBaseRelocation(char* buff, DWORD Value);
//处理dll的函数
DWORD StretchDLL(DWORD pFileBuff,DWORD FileSize,DWORD BaseAddress);
//拉伸文件
DWORD StretchEXE(DWORD pFileBuff, DWORD FileSize);
//文件对齐,返回对齐后的大小
DWORD FileAlignment(DWORD pFileBuf, DWORD FileSize);
//保存文件
void SaveFile(DWORD buffer,DWORD nLength);
//添加新节
void addSeciton(DWORD pFileBuff,DWORD AddSize);
 
 
void File_Forever_Inject()
 {
     //1.0 把exe文件加载到内存
     DWORD pFileBuf_exe = 0;//exe在内存中的地址
     DWORD FileSize_exe = 0;//exe的内存大小
     DWORD FileSize_exe_1 = 0;//exe的文件大小
     if (GetBuffAddrAndSizeofFile((char*)path_exe, &pFileBuf_exe, &FileSize_exe, &FileSize_exe_1) == 0)
     {
         return;
     }
 
     //1.1 把dll文件加载到内存
     DWORD pFileBuf_dll = 0;//dll在内存中的地址
     DWORD FileSize_dll = 0;//dll的内存大小
     DWORD FileSize_dll_1 = 0;//dll的文件大小
     if (GetBuffAddrAndSizeofFile((char*)path_dll, &pFileBuf_dll, &FileSize_dll, &FileSize_dll_1) == 0)
     {
         return;
     }
 
 
     //计算添加新节需要的大小
     DWORD NewSectionSize = FileSize_dll + sizeof(Getkernel32Addr) + sizeof(GetprocessAddress) + sizeof(RebuildimportTable) + 0x100;
 
     //2.添加新节
     addSeciton(pFileBuf_exe, NewSectionSize);
 
 
     //3.处理dll(拉伸dll和修复重定位表)
     PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuf_exe;
     PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pFileBuf_exe + pDosHeader->e_lfanew);
 
     DWORD New_Filesize_dll = StretchDLL(pFileBuf_dll, FileSize_dll, pNtHeader->OptionalHeader.ImageBase + FileSize_exe);
   
      //4.申请新内存 = exe文件大小 + 新节大小
     DWORD nLength = FileSize_exe_1 + NewSectionSize;
     char* TotalBuff = new char[nLength];
     memset(TotalBuff, 0, nLength);
     memcpy(TotalBuff, (void*)pFileBuf_exe, FileSize_exe_1);
     memcpy(TotalBuff + FileSize_exe_1, (char*)New_Filesize_dll, FileSize_dll);
     memcpy(TotalBuff + FileSize_exe_1 + FileSize_dll, Getkernel32Addr, sizeof(Getkernel32Addr));
     memcpy(TotalBuff + FileSize_exe_1 + FileSize_dll + sizeof(Getkernel32Addr), GetprocessAddress, sizeof(GetprocessAddress));
     memcpy(TotalBuff + FileSize_exe_1 + FileSize_dll + sizeof(Getkernel32Addr) + sizeof(GetprocessAddress), RebuildimportTable, sizeof(RebuildimportTable));
 
     char GetProcAddress_Code[] = {
            0x47 ,0x65 ,0x74 ,0x50 ,0x72 ,0x6F ,0x63 ,0x41 ,0x64 ,0x64 ,0x72 ,0x65 ,0x73 ,0x73
     };
 
     char LoadLibraryA_Code[] = {
           0x4C ,0x6F  ,0x61  ,0x64  ,0x4C  ,0x69  ,0x62  ,0x72  ,0x61  ,0x72  ,0x79 ,0x41
     };
 
     memcpy(TotalBuff + nLength - 0x40, GetProcAddress_Code, sizeof(GetProcAddress_Code));
     memcpy(TotalBuff + nLength - 0x30, LoadLibraryA_Code, sizeof(LoadLibraryA_Code));
 
    
     // 5.获取DLL的入口函数的指针 = exe的基址 + exe添加新节前的内存对齐后的大小 + dll入口
 
     PIMAGE_DOS_HEADER pDosHeader_dll = (PIMAGE_DOS_HEADER)pFileBuf_dll;
     PIMAGE_NT_HEADERS pNtHeader_dll = (PIMAGE_NT_HEADERS)(pFileBuf_dll + pDosHeader_dll->e_lfanew);
     DWORD OEP_dll = pNtHeader_dll->OptionalHeader.AddressOfEntryPoint;
     DWORD DllEntry = pNtHeader->OptionalHeader.ImageBase + FileSize_exe + OEP_dll;
 
            
  
     //6.构造shellcode
 
     //call GetKernel32Addr
     //E8 XXXXXXXX = 要跳转的地址-E8所在的地址-5
     DWORD temp = pNtHeader->OptionalHeader.ImageBase + FileSize_exe + FileSize_dll;
     DWORD temp_1 = sizeof(Getkernel32Addr) + sizeof(GetprocessAddress) + sizeof(RebuildimportTable);
     DWORD s_GetKernel32Addr = temp - (temp + temp_1+6) - 5;
 
     //call MyGetProcessAddress
     //E8 XXXXXXXX = 要跳转的地址-E8所在的地址-5
     DWORD s_MyGetProcessAddress = temp + sizeof(Getkernel32Addr) - (temp + temp_1 + 0x14) - 5;
 
     //call RebuildImportTable
     //E8 XXXXXXXX = 要跳转的地址-E8所在的地址-5
     DWORD s_RebuildImportTable = temp + sizeof(Getkernel32Addr) + sizeof(GetprocessAddress) -
         (temp + temp_1 + 0x38) - 5;
 
     //call DllFunc   调用dll
     //E8 XXXXXXXX = 要跳转的地址-E8所在的地址-5
     DWORD DllFunc = DllEntry - (temp + temp_1 + 0x49) - 5;
 
     //"GetProcAddress"字符串所在的地址
     DWORD GPA = pNtHeader->OptionalHeader.ImageBase + FileSize_exe + NewSectionSize - 0x40;
 
     //"LoadLibraryA"字符串所在的地址
     DWORD LLA= pNtHeader->OptionalHeader.ImageBase + FileSize_exe + NewSectionSize - 0x30;
 
     //DLL模块在进程虚拟空间中的起始地址
     DWORD DLLAddr = pNtHeader->OptionalHeader.ImageBase + FileSize_exe;
 
     //主程序的入口
     DWORD jmp_orig = pNtHeader->OptionalHeader.AddressOfEntryPoint + pNtHeader->OptionalHeader.ImageBase;
 
     char ShellCode[] = {
         0x55,
         0x8B,0xEC,
         0x83,0xEC,0x50,
         //0xE8,0x2F,0x7C,0xCE,0xFF,
         0xE8,
         s_GetKernel32Addr & 0xFF,(s_GetKernel32Addr & 0xFF00) >> 8,(s_GetKernel32Addr & 0xFF0000) >> 16,s_GetKernel32Addr >> 24,
         0x89,0x45,0xFC,
         0x68,//0x00,0x00,0x89,0x00,
         GPA & 0xFF,(GPA & 0xFF00) >> 8,(GPA & 0xFF0000) >> 16,GPA >> 24,
         0x50,
         //0xE8,0x21,0x7C,0xFE,0xFF,
         0xE8,
         s_MyGetProcessAddress & 0xFF,(s_MyGetProcessAddress & 0xFF00) >> 8,(s_MyGetProcessAddress & 0xFF0000) >> 16,s_MyGetProcessAddress >> 24,
         0x83,0xC4,0x08,
         0x89,0x45,0xF8,
         0x68,//0x00,0x00,0x45,0x00,
         LLA & 0xFF,(LLA & 0xFF00) >> 8,(LLA & 0xFF0000) >> 16,LLA >> 24,
         0x8B,0x5D,0xFC,
         0x53,
         0xFF,0xD0,
         0x89,0x45,0xF4,
                  
         0x8B,0x5D,0xF8,
         0x53,
         0x8b,0xD0,
         0xB9,
          DLLAddr & 0xFF,(DLLAddr & 0xFF00) >> 8,(DLLAddr & 0xFF0000) >> 16,DLLAddr >> 24,
         //0xE8,0xFB,0x7B,0xC3,0xFF,
         0xE8,
         s_RebuildImportTable & 0xFF,(s_RebuildImportTable & 0xFF00) >> 8,(s_RebuildImportTable & 0xFF0000) >> 16,s_RebuildImportTable >> 24,
         0x83,0xC4,0x04,
         0x6A,0x00,
         0x6A,0x01,
         0x68,//0x00,0x00,0x40,0x00,
         DLLAddr & 0xFF,(DLLAddr & 0xFF00) >> 8,(DLLAddr & 0xFF0000) >> 16,DLLAddr >> 24,
         //0xE8,0xEA,0x7B,0xBE,0x04,
         0xE8,
         DllFunc & 0xFF,(DllFunc & 0xFF00) >> 8,(DllFunc & 0xFF0000) >> 16,DllFunc >> 24,
         0x68,
         //0x00,0x00,0x04,0x00,
         jmp_orig & 0xFF,(jmp_orig & 0xFF00) >> 8,(jmp_orig & 0xFF0000) >> 16,jmp_orig >> 24,
         0xC3
     };
   
     //计算shellcode存放的地址
     DWORD Addr = (DWORD)TotalBuff + FileSize_exe_1 + NewSectionSize - 0x100;
 
     for (int i = 0; i < sizeof(ShellCode); i++)
     {
         ((char*)Addr)[i] = ShellCode[i];
     }
      
 
     //7.修改入口
     PIMAGE_DOS_HEADER pDosHeader_New = (PIMAGE_DOS_HEADER)TotalBuff;
     PIMAGE_NT_HEADERS pNtHeader_New = (PIMAGE_NT_HEADERS)(TotalBuff + pDosHeader_New->e_lfanew);
     DWORD New_OEP = FileSize_exe+ NewSectionSize-0x100;
     *&(pNtHeader_New->OptionalHeader.AddressOfEntryPoint) = New_OEP;
 
 
     //8.保存文件
     SaveFile((DWORD)TotalBuff, nLength);
 }
 
 
int main()
{
    File_Forever_Inject();
    system("pause");
    return 0;
}
 
 
 
//处理dll的函数
DWORD StretchDLL(DWORD pFileBuff,DWORD FileSize,DWORD BaseAddress)
{
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuff;
    PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pFileBuff + pDosHeader->e_lfanew);
 
    //1.1 根据内存大小 申请内存
    char* NewFileBuff = new char[FileSize];
    if (NewFileBuff==NULL)
    {
        printf("内存申请失败!");
        return 0;
    }
    memset(NewFileBuff, 0, FileSize);
 
    //1.2 拉伸文件
     // 拷贝DOS头 + DOS STUB + PE头到headers地址处
    memcpy(NewFileBuff, pDosHeader, pNtHeader->OptionalHeader.SizeOfHeaders);
 
    // 从dll文件内容中拷贝每个section(节)的数据到新的内存区域
    PIMAGE_OPTIONAL_HEADER32 OptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileBuff + pDosHeader->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER);
    PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)OptionalHeader + pNtHeader->FileHeader.SizeOfOptionalHeader);
 
    for (int i = 0; i < pNtHeader->FileHeader.NumberOfSections; i++, pSectionHeader++)
    {
        char* x = (char*)NewFileBuff + pSectionHeader->VirtualAddress;
        char* y = (char*)pFileBuff + pSectionHeader->PointerToRawData;
        memcpy(x ,y, pSectionHeader->SizeOfRawData);
    }
 
    //1.3 修复重定位表
    // 检查加载到进程地址空间的位置和之前PE文件中指定的基地址是否一致,如果不一致,则需要重定位
    int locationDelta = (SIZE_T)((DWORD)BaseAddress - pNtHeader->OptionalHeader.ImageBase);
    if (locationDelta != 0)
    {
        //修复重定位表
        PerformBaseRelocation((char*)NewFileBuff, locationDelta);
 
    }
 
    //1.4 修复IAT表
    // 加载依赖dll,并构建"PEHeader.OptionalHeader.DataDirectory.Image_directory_entry_import"导入表
    /*if (!RebuildImportTable((char*)NewFileBuff, myLoadLibrary, myGetProcAddress))
    {
        printf("修复失败!");
        return 0;
    }*/
 
    return (DWORD)NewFileBuff;
 
}
 
//拉伸文件
DWORD StretchEXE(DWORD pFileBuff, DWORD FileSize)
{
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuff;
    PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pFileBuff + pDosHeader->e_lfanew);
 
    //1.1 根据内存大小 申请内存
    char* NewFileBuff = new char[FileSize];
    if (NewFileBuff == NULL)
    {
        printf("内存申请失败!");
        return 0;
    }
    memset(NewFileBuff, 0, FileSize);
 
    //1.2 拉伸文件
     // 拷贝DOS头 + DOS STUB + PE头到headers地址处
    memcpy(NewFileBuff, pDosHeader, pNtHeader->OptionalHeader.SizeOfHeaders);
 
    // 从dll文件内容中拷贝每个section(节)的数据到新的内存区域
    PIMAGE_OPTIONAL_HEADER32 OptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileBuff + pDosHeader->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER);
    PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)OptionalHeader + pNtHeader->FileHeader.SizeOfOptionalHeader);
 
    for (int i = 0; i < pNtHeader->FileHeader.NumberOfSections; i++, pSectionHeader++)
    {
        char* x = (char*)NewFileBuff + pSectionHeader->VirtualAddress;
        char* y = (char*)pFileBuff + pSectionHeader->PointerToRawData;
        memcpy(x, y, pSectionHeader->SizeOfRawData);
    }
 
    return (DWORD)NewFileBuff;
}
 
 
 
//获取文件的在内存的地址和大小
int GetBuffAddrAndSizeofFile(char* FilePath, _Out_ DWORD* buff, _Out_ DWORD* FileSize ,_Out_ DWORD* FileSize1)
{
    //1.1 获取文件句柄
    HANDLE hFile = CreateFile(
        FilePath,
        GENERIC_READ,
        0,
        NULL,
        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 
    //1.2 获取文件大小
    DWORD dwFileSize = GetFileSize(hFile, NULL);
    CHAR *pFileBuf = new CHAR[dwFileSize];
    memset(pFileBuf, 0, dwFileSize);
 
    //1.3 将文件读取到内存
    DWORD ReadSize = 0;
    ReadFile(hFile, pFileBuf, dwFileSize, &ReadSize, NULL);
 
    //1.4 关闭句柄
    CloseHandle(hFile);
 
 
    //2.1 判断是否为PE文件
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuf;
    if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
    {
        printf("不是MZ开头\n");
        return 0;
    }
    PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pFileBuf + pDosHeader->e_lfanew);
    if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
    {
        printf("不是PE文件\n");
        return 0;
    }
 
    //2.2 把文件的在内存中的地址和大小分别赋值输出参数
    *buff = (DWORD)pFileBuf;
    *FileSize = (pNtHeader->OptionalHeader.SizeOfImage % pNtHeader->OptionalHeader.SectionAlignment==0) ?
        (pNtHeader->OptionalHeader.SizeOfImage) :
        (pNtHeader->OptionalHeader.SizeOfImage- (pNtHeader->OptionalHeader.SizeOfImage % pNtHeader->OptionalHeader.SectionAlignment)+ pNtHeader->OptionalHeader.SectionAlignment);
    *FileSize1 = dwFileSize;
    return 1;
}
 
//文件对齐,返回对齐后的大小
DWORD FileAlignment(DWORD pFileBuf, DWORD FileSize)
{
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuf;
    PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pFileBuf + pDosHeader->e_lfanew);
    DWORD filealign = pNtHeader->OptionalHeader.FileAlignment;
    if (FileSize % filealign==0)
    {
        return FileSize;
    }
    else
    {
        return FileSize - FileSize % filealign + filealign;
    }
}
 
//保存文件
void SaveFile(DWORD buffer,DWORD nLength)
{
    FILE* fp;
    errno_t err = 0;
    err = fopen_s(&fp,(char*)out_path, "wb");
    if (err!=0)
    {
        printf("file cannot open\n");
        return;
    }
 
    if (fwrite((char*)buffer, nLength, 1, fp))
        printf("存盘成功!\n");
    else
        printf("存盘失败!\n");
 
    if (fclose(fp))
        printf("\nfile cannot be closed\n");
}
 
//添加新节
void addSeciton(DWORD pFileBuff,DWORD AddSize)
{
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuff;
    PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pFileBuff + pDosHeader->e_lfanew);
 
    PIMAGE_OPTIONAL_HEADER32 OptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileBuff + pDosHeader->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER);
    PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)OptionalHeader + pNtHeader->FileHeader.SizeOfOptionalHeader);
 
    //判断节表尾部是否有80个字节的空闲区域
    PIMAGE_SECTION_HEADER pse_temp = pSectionHeader + pNtHeader->FileHeader.NumberOfSections;//节表新增节的首地址
    PIMAGE_SECTION_HEADER pse_temp_b = pSectionHeader + pNtHeader->FileHeader.NumberOfSections - 1;//节表最后一节的首地址
    int space = OptionalHeader->SizeOfHeaders - ((DWORD)pse_temp - pFileBuff);
 
    //space空间指的是节表最后都是0,没有其他数据,如果有其他数据,则即使满足了有80个字节的空间,也不能添加数据,这样会破坏其他数据
    //如果空间不够,那么,doc头下面的垃圾数据不要了,后面的PE头 标准PE头 和节表上提;
    //并且要判断pDosHeader->e_lfanew-64这段距离是否大于80,否则上提没有意义
    if (pDosHeader->e_lfanew - 64 > 80 && space < 80)
    {
        int len = ((DWORD*)pse_temp - &(pNtHeader->Signature)) * 4;
        for (int i = 0; i < len; i++)
        {
            *((char*)pFileBuff + 64 + i) = *((char*)pFileBuff + i + pDosHeader->e_lfanew);
        }
        pDosHeader->e_lfanew = 0x40;
         
        pse_temp = pSectionHeader + pNtHeader->FileHeader.NumberOfSections;
        pse_temp_b = pSectionHeader + pNtHeader->FileHeader.NumberOfSections - 1;
        for (int i = 0; i < 80; i++)//把节表尾部80个字节格式化
            *((char*)pFileBuff + 64 + i + len) = 0;
        space = pDosHeader->e_lfanew - 64;//更新space空间
    }
    if (space > 80)
    {
        BYTE(*p)[8] = &(pse_temp->Name);
        int name[8] = { 0x2E,0x74,0x74,0x74,0x74 };
        for (int i = 0; i < 8; i++)
            p[0][i] = name[i];
 
        pse_temp->Misc.VirtualSize = AddSize;
 
        if (pse_temp_b->Misc.VirtualSize > pse_temp_b->SizeOfRawData)//比较内存大小和文件大小
        {
            //检测内存大小是否对齐
            pse_temp->VirtualAddress =
                ((pse_temp_b->Misc.VirtualSize % OptionalHeader->SectionAlignment)==0)? pse_temp_b->Misc.VirtualSize :
                (pse_temp_b->Misc.VirtualSize - pse_temp_b->Misc.VirtualSize % OptionalHeader->SectionAlignment + OptionalHeader->SectionAlignment )+
                pse_temp_b->VirtualAddress;
            printf("%X\n", *&(pse_temp->VirtualAddress));
        }
        else
        {
            pse_temp->VirtualAddress =
                ((pse_temp_b->SizeOfRawData % OptionalHeader->SectionAlignment) == 0) ? pse_temp_b->SizeOfRawData :
                (pse_temp_b->SizeOfRawData - pse_temp_b->SizeOfRawData % OptionalHeader->SectionAlignment + OptionalHeader->SectionAlignment) +
                pse_temp_b->VirtualAddress;
        }
 
        pse_temp->SizeOfRawData = AddSize;
        pse_temp->PointerToRawData = pse_temp_b->SizeOfRawData + pse_temp_b->PointerToRawData;
        pse_temp->Characteristics = 0xE0000020;
        pNtHeader->FileHeader.NumberOfSections = pNtHeader->FileHeader.NumberOfSections + 1;
        pNtHeader->OptionalHeader.SizeOfImage = pNtHeader->OptionalHeader.SizeOfImage + AddSize;       
    }
    else
        printf("添加节失败,没有空间添加新的节!");
}
 
//修复重定位表
void PerformBaseRelocation(char* buff, DWORD Value)
{
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)buff;
    PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(buff + pDosHeader->e_lfanew);
 
    //获取目录表头指针
    PIMAGE_DATA_DIRECTORY pDataDirectory = pNtHeader->OptionalHeader.DataDirectory;
    if (pDataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size > 0)
    {
        PIMAGE_BASE_RELOCATION relocation = (PIMAGE_BASE_RELOCATION)((DWORD)buff + pDataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
        while (relocation->VirtualAddress > 0)
        {
            BYTE* dest = (PBYTE)((DWORD)buff + relocation->VirtualAddress);
            WORD* relInfo = (PWORD)((DWORD)relocation + sizeof(IMAGE_BASE_RELOCATION));
            for (int i = 0; i < ((relocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / 2); ++i, ++relInfo)
            {
                DWORD *patchAddrHL;
                int type, offset;
 
                //the upper 4 bits define the type of relocation
                type = *relInfo >> 12;
                //the lower 12 bits define the offset
                offset = *relInfo & 0xFFF;
 
                switch (type)
                {
                case IMAGE_REL_BASED_ABSOLUTE:
                    //skip relocation
                    break;
                case IMAGE_REL_BASED_HIGHLOW:
                    //change comlete 32 bit address
                    patchAddrHL = (PDWORD)(dest + offset);
                    *patchAddrHL += Value;
                    break;
                default:
                    break;
                }
            }
            //advance to next relocation block
            relocation = PIMAGE_BASE_RELOCATION((DWORD)relocation + relocation->SizeOfBlock);
        }
    }
 
}






结语:
newfile.exe能够在win10上运行,不能在win7上跑(32位和64位都失败)。
有低版本的编译器的老铁可以试一下,在支持win7的编译器上编译,然后在win7上跑看能不能跑得动


clipboard.png
clipboard1.png
clipboard2.png
clipboard3.png

LoadPE.7z

21.58 KB, 下载次数: 208, 下载积分: 吾爱币 -1 CB

PE解析器

Shellcode.7z

2.88 KB, 下载次数: 146, 下载积分: 吾爱币 -1 CB

Shellcode.h

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

gaobb 发表于 2021-9-11 10:26
这是来骗C币的吗?
hj170520 发表于 2020-5-22 19:10
 楼主| 舒默哦 发表于 2020-5-22 19:13
 楼主| 舒默哦 发表于 2020-5-22 19:17
奇安信要拦截这个dll
clipboard5.png
不名物 发表于 2020-5-23 10:49
纯学习一下吧,包装exe,典型的shellcode模式啊
 楼主| 舒默哦 发表于 2020-5-23 17:20
不名物 发表于 2020-5-23 10:49
纯学习一下吧,包装exe,典型的shellcode模式啊

我只想到这种,还有其他方式吗?还有种方法是把dll分离出exe,放到一个临时文件加载后删掉,这样可以不用修复重定位和IAT表
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-4-16 10:15

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表