• PE 通过导入表注入 Dll


    导入表注入,当程序被加载时,系统会根据程序导入表信息来加载需要用到的dll,导入表注入的原理就是修改程序的导入表,将自己的dll添加到程序的导入表中,这样程序运行时可以将自己的DLL加载到程序的进程空间。
    结构图

    1. 将要注入dll的程序写入到内存中,并新增一个节
    2. 拷贝原来的导入表到新节中
    3. 在新节拷贝的导入表后新增一个导入表_IMAGE_IMPORT_DESCRIPTOR
    4. 增加8字节的INT表和8字节的IAT表
    5. 存储要注入的dll的名称
    6. 增加一个_IMAGE_IMPORT_BY_NAME结构,并将函数名称存进结构体第一个变量后的内存中
    7. 将_IMAGE_IMPORT_BY_NAME结构的地址的RVA赋值给INT表和IAT表第一项
    8. 将dll名称所在位置的首地址的RVA赋值给新增导入表的Name
    9. 修改IMAGE_DATA_DIRECTORY结构的VirtualAddress和Size

    提示

    1. 根据IMAGE_DATA_DIRECTORY结构的size去拷贝导入表,将会多拷贝20字节的0,这也是导入表结束的标志,新增导入表的时候应该将此处的0进行覆盖,因为20字节的0,否则系统不会加载新增的导入表代表导入表结束了。
    2. INT表和IAT表的8字节是因为这两张表至少包含一项内容,才会被系统加载,剩余的4字节为0标志着表的结束。
    3. 结构体存储地址的变量存储都是RVA,使用时需要进行转换,有时是FOA转RVA,有时是RVA转FOA 。

    代码

    #include 
    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    
    LPVOID readFile(PTCHAR fileName, size_t &fileSize) {
        FILE *file;
        fopen_s(&file, fileName, "rb");
        if (nullptr == file) {
            cout << "file open fail" << endl;
            return nullptr;
        }
        struct stat fileStat;
        stat(fileName, &fileStat);
        size_t size = fileStat.st_size;
        fileSize = size;
        auto fileBuffer = malloc(size);
        if (nullptr == fileBuffer) {
            cout << "malloc fail" << endl;
            return nullptr;
        }
        memset(fileBuffer, 0, size);
        fread(fileBuffer, size, 1, file);
        fclose(file);
        return fileBuffer;
    }
    
    BOOL writeFile(LPVOID fileBuffer, unsigned long size, PTCHAR newFileName) {
        FILE *file = nullptr;
        fopen_s(&file, newFileName, "wb");
        if (nullptr == file) {
            cout << "file create fail" << endl;
            return FALSE;
        }
        fwrite(fileBuffer, 1, size, file);
        fclose(file);
        return TRUE;
    }
    
    PIMAGE_NT_HEADERS getNtHeader(LPVOID buffer) {
        auto docHeader = (PIMAGE_DOS_HEADER) buffer;
        auto ntHeader = (PIMAGE_NT_HEADERS32) ((PTCHAR) buffer + docHeader->e_lfanew);
        return ntHeader;
    }
    
    PIMAGE_OPTIONAL_HEADER getOptionalHeader(LPVOID buffer) {
        auto ntHeader = getNtHeader(buffer);
        return &ntHeader->OptionalHeader;
    }
    
    PIMAGE_FILE_HEADER getFileHeader(LPVOID buffer) {
        auto ntHeader = getNtHeader(buffer);
        return &ntHeader->FileHeader;
    }
    
    PIMAGE_SECTION_HEADER getFirstSectionHeader(LPVOID buffer) {
        auto optionHeader = getOptionalHeader(buffer);
        auto ntHeader = getNtHeader(buffer);
        return (PIMAGE_SECTION_HEADER) ((PTCHAR) optionHeader + ntHeader->FileHeader.SizeOfOptionalHeader);
    }
    
    PIMAGE_SECTION_HEADER getLatestSectionHeader(LPVOID buffer) {
        return (PIMAGE_SECTION_HEADER) (getFirstSectionHeader(buffer) + getFileHeader(buffer)->NumberOfSections - 1);
    }
    
    size_t align(size_t size, int align) {
        return ((size / align) + 1) * align;
    }
    
    size_t peSize(LPVOID fileBuffer) {
        auto latestSectionHeader = getLatestSectionHeader(
                fileBuffer);
        return latestSectionHeader->PointerToRawData + latestSectionHeader->SizeOfRawData;
    }
    
    LPVOID Rva2Foa(LPVOID buffer, DWORD rva) {
        auto ntHeader = getNtHeader(buffer);
        auto firstSectionHeader = getFirstSectionHeader(buffer);
        for (int i = 0; i < ntHeader->FileHeader.NumberOfSections - 1; i++) {
            auto section = firstSectionHeader + i;
            if (rva >= section->VirtualAddress && rva < (section->VirtualAddress + section->Misc.VirtualSize)) {
                return (LPVOID) (rva - section->VirtualAddress + section->PointerToRawData);
            }
        }
        cout << "Rva2Foa error:" << rva << endl;
        return nullptr;
    }
    
    LPVOID Foa2Rva(LPVOID buffer, DWORD foa) {
        auto ntHeader = getNtHeader(buffer);
        auto firstSectionHeader = getFirstSectionHeader(buffer);
        if (foa <= ntHeader->OptionalHeader.SizeOfHeaders) {
            return (LPVOID) foa;
        }
        for (int i = 0; i < ntHeader->FileHeader.NumberOfSections; i++) {
            auto section = firstSectionHeader + i;
            if (foa >= section->PointerToRawData && foa < (section->PointerToRawData + section->SizeOfRawData)) {
                return (LPVOID) (foa - section->PointerToRawData + section->VirtualAddress);
            }
        }
        cout << "Foa2Rva error:" << foa << endl;
        return nullptr;
    }
    
    LPVOID addSection(LPVOID fileBuffer, PTCHAR sectionName, size_t sectionCodeSize) {
        if (strlen(sectionName) >= 8) {
            cout << "sectionName size < 8" << endl;
            return nullptr;
        }
        auto ntHeader = getNtHeader(fileBuffer);
        size_t fileAlign = ntHeader->OptionalHeader.FileAlignment;
        size_t fileSize = peSize(fileBuffer);
        size_t outFileSize = fileSize + align(sectionCodeSize, fileAlign);
        auto newFileBuffer = malloc(outFileSize);
        memset(newFileBuffer, 0, outFileSize);
        memcpy(newFileBuffer, fileBuffer, fileSize);
        free(fileBuffer);
        auto newFileNtHeader = getNtHeader(newFileBuffer);
        auto newOptionHeader = &newFileNtHeader->OptionalHeader;
        auto newFileSectionHeader =
                (PIMAGE_SECTION_HEADER) ((PTCHAR) newOptionHeader +
                                         sizeof(*newOptionHeader));
    
        if ((newFileSectionHeader->PointerToRawData -
             (DWORD) (newFileSectionHeader + newFileNtHeader->FileHeader.NumberOfSections)) < 0x50) {
            cout << "table space not enought" << endl;
            return nullptr;
        }
    
        size_t sectionAlign = newFileNtHeader->OptionalHeader.SectionAlignment;
        auto newFileLatestSectionHeader =
                (PIMAGE_SECTION_HEADER) (newFileSectionHeader + (newFileNtHeader->FileHeader.NumberOfSections - 1));
        auto addSectionHeader = newFileLatestSectionHeader + 1;
    
    
        memcpy(addSectionHeader->Name, sectionName, 8);
    
        addSectionHeader->Misc.VirtualSize = align(sectionCodeSize, sectionAlign);
        addSectionHeader->VirtualAddress = align(
                newFileLatestSectionHeader->VirtualAddress + newFileLatestSectionHeader->Misc.VirtualSize,
                sectionAlign);
        addSectionHeader->SizeOfRawData = align(sectionCodeSize, fileAlign);
        addSectionHeader->PointerToRawData =
                newFileLatestSectionHeader->PointerToRawData + newFileLatestSectionHeader->SizeOfRawData;
        addSectionHeader->Characteristics = IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
    
        newFileNtHeader->FileHeader.NumberOfSections += 1;
    
        auto firstSection = getFirstSectionHeader(newFileBuffer);
        auto latestSection = (DWORD) (getLatestSectionHeader(newFileBuffer) + 1);
        auto ssize = (DWORD) newFileBuffer + firstSection->PointerToRawData - latestSection;
    
        cout << "space size : " << ssize << " --- " << "code size : " << sectionCodeSize << endl;
        cout << latestSection << ":" << (DWORD) (newFileSectionHeader + newFileNtHeader->FileHeader.NumberOfSections)
             << endl;
    
    //    for (int i = 1; i < newFileNtHeader->FileHeader.NumberOfSections; i++) {
    //        newFileSectionHeader[i - 1].Misc.VirtualSize =
    //                newFileSectionHeader[i].VirtualAddress - newFileSectionHeader[i - 1].VirtualAddress;
    //    }
    
        newFileNtHeader->OptionalHeader.SizeOfImage =
                addSectionHeader->VirtualAddress + addSectionHeader->Misc.VirtualSize;
        newFileNtHeader->OptionalHeader.SizeOfHeaders += sizeof(*addSectionHeader);
        return newFileBuffer;
    }
    
    /**
     * pe文件注入shellcode
     */
    void hackPe() {
        char shellcode[] = "\x31\xd2\xb2\x30\x64\x8b\x12\x8b\x52\x0c\x8b\x52\x1c\x8b\x42"
                           "\x08\x8b\x72\x20\x8b\x12\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03"
                           "\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x31\xed\x8b"
                           "\x34\xaf\x01\xc6\x45\x81\x3e\x46\x61\x74\x61\x75\xf2\x81\x7e"
                           "\x08\x45\x78\x69\x74\x75\xe9\x8b\x7a\x24\x01\xc7\x66\x8b\x2c"
                           "\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf\xfc\x01\xc7\x68\x79\x74"
                           "\x65\x01\x68\x6b\x65\x6e\x42\x68\x20\x42\x72\x6f\x89\xe1\xfe"
                           "\x49\x0b\x31\xc0\x51\x50\xff\xd7";;
        string currentPath = filesystem::current_path().u8string();
        string fileNameStr = currentPath + R"(\..\resources\Demo.exe)";
        PTCHAR fileName = fileNameStr.data();
        string fileNamePeStr = currentPath + R"(\..\resources\DemoPe.exe)";
        PTCHAR fileNamePe = fileNamePeStr.data();
        size_t fileSize;
        LPVOID fileBuffer = readFile(fileName, fileSize);
        LPVOID newFileBuffer = addSection(fileBuffer, (PTCHAR) ".import", sizeof(shellcode));
        auto ntHeader = getNtHeader(newFileBuffer);
        auto latestSectionHeader = getLatestSectionHeader(
                newFileBuffer);
        memcpy((PTCHAR) newFileBuffer + latestSectionHeader->PointerToRawData, shellcode, sizeof(shellcode));
        ntHeader->OptionalHeader.AddressOfEntryPoint = latestSectionHeader->VirtualAddress;
        size_t outFileSize = peSize(newFileBuffer);
        writeFile(newFileBuffer, outFileSize, fileNamePe);
        free(newFileBuffer);
    }
    
    void peInject() {
        PTCHAR sectionName = ".import";
        PTCHAR injectDllName = "Dll2.dll";
        PTCHAR injectFunctionName = "ExportFunction";
        string currentPath = filesystem::current_path().u8string();
        string fileNameStr = currentPath + R"(\..\resources\Demo.exe)";
        string fileNameNewStr = currentPath + R"(\..\resources\DemoNew.exe)";
        PTCHAR fileNameNewPe = fileNameNewStr.data();
        PTCHAR fileName = fileNameStr.data();
        size_t fileSize;
        LPVOID fileBuffer = readFile(fileName, fileSize);
        auto optionHeader = getOptionalHeader(fileBuffer);
        auto importDirectory = &optionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
        size_t inaSize = 0x0;
        size_t iatSize = 0x10;
        size_t dllNameLen = strlen(injectDllName) + 1;
        size_t newDataDirectoryLen = sizeof(IMAGE_IMPORT_DESCRIPTOR);
        size_t emptyDataDirectoryLen = newDataDirectoryLen;
        size_t functionNameLen = strlen(injectFunctionName) + 1;
        size_t spaceLen = 0x2;
        size_t sectionLength =
                importDirectory->Size + newDataDirectoryLen + emptyDataDirectoryLen + inaSize + iatSize + dllNameLen +
                functionNameLen + spaceLen;
    
        auto firstSection = getFirstSectionHeader(fileBuffer);
        auto fileAlign = optionHeader->FileAlignment;
        auto sectionAlign = optionHeader->SectionAlignment;
    
        LPVOID newFileBuffer = addSection(fileBuffer, sectionName, sectionLength);
        auto dataDirectory = &getOptionalHeader(newFileBuffer)->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
        auto latestSection = getLatestSectionHeader(newFileBuffer);
        auto newSectionFoa = (PDWORD) ((DWORD) newFileBuffer + latestSection->PointerToRawData);
        auto dataDirectionFoa = Rva2Foa(newFileBuffer, dataDirectory->VirtualAddress);
    
        auto oldImportDirectionAddr = (PIMAGE_IMPORT_DESCRIPTOR) ((DWORD) newFileBuffer + (DWORD) dataDirectionFoa);
    
        memcpy(newSectionFoa, oldImportDirectionAddr, dataDirectory->Size);
    
        auto newImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR) (
                (DWORD) newSectionFoa + dataDirectory->Size - sizeof(IMAGE_IMPORT_DESCRIPTOR));
        auto pIntTble = (PIMAGE_THUNK_DATA) ((DWORD) newImportDescriptor + 0x28);
        auto originPIntTable = pIntTble;
        //int
        pIntTble++;
        pIntTble->u1.Ordinal = 0x0;
        pIntTble++;
    
        //iat
        auto pIatTable = pIntTble;
        auto originPIatTable = pIatTable;
        pIatTable++;
        pIatTable->u1.Ordinal = 0x0;
        pIatTable++;
    
        //dll name
        auto dllNameAddr = (PDWORD) pIatTable;
        memcpy(dllNameAddr, injectDllName, strlen(injectDllName) + 1);
    
        //image_import_by_name
        auto functionNameAddr = (PIMAGE_IMPORT_BY_NAME) (PDWORD) (dllNameAddr + strlen(injectDllName) + 1);
        auto pFunctionName = (LPVOID) ((DWORD) functionNameAddr + 0x2);
        memcpy(pFunctionName, injectFunctionName, strlen(injectFunctionName) + 1);
    
        //copy image_import_by_name to iat and int
        originPIntTable->u1.AddressOfData = (DWORD) Foa2Rva(newFileBuffer,
                                                            (DWORD) functionNameAddr - (DWORD) newFileBuffer);
        originPIatTable->u1.AddressOfData = originPIntTable->u1.Ordinal;
    
        //revise name OriginFirstThunk , FirstThunk
        newImportDescriptor->Name = (DWORD) Foa2Rva(newFileBuffer,
                                                    (DWORD) dllNameAddr - (DWORD) newFileBuffer);
        newImportDescriptor->OriginalFirstThunk = (DWORD) Foa2Rva(newFileBuffer, (DWORD) originPIntTable -
                                                                                 (DWORD) newFileBuffer);
        newImportDescriptor->FirstThunk = (DWORD) Foa2Rva(newFileBuffer, (DWORD) originPIatTable -
                                                                         (DWORD) newFileBuffer);
    
        //revise image_data_directory.virtualaddress and size
        dataDirectory->VirtualAddress = (DWORD) Foa2Rva(newFileBuffer,
                                                        latestSection->PointerToRawData);
        dataDirectory->Size += sizeof(IMAGE_IMPORT_DESCRIPTOR);
    
        size_t newFileSize = peSize(newFileBuffer);
        writeFile(newFileBuffer, newFileSize, fileNameNewPe);
    }
    
    int main() {
        peInject();
        return 0;
    }
    
    
    • 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
    • 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
  • 相关阅读:
    Vue-管理状态仓库Vuex
    04、Java数组
    值得收藏的30道Python练手题(附详解)
    Please No More Sigma(构造矩阵)
    白细胞膜修饰的紫杉醇靶向缓释脂质体/pH敏感前体阳离子脂质体与红细胞膜融合制备
    能谈一下 CAS 机制吗
    YOLOv8检测obb标注hrsc数据集
    在Windows平台编译OpenJdk8
    勤于奋:国外LEAD找任务方法
    FAT32、exFAT 和 NTFS 之间有什么区别?
  • 原文地址:https://blog.csdn.net/dounine/article/details/126382498