PE输入表DLL注入

PE输入表DLL注入

一.实现效果
启动notepad.exe时能够加载自己编写的dll.
最终效果如图所示

PE输入表DLL注入_第1张图片


下面逐步讲解并附带源码
二.编写DLL
自行编写DLL,导出一个函数,弹出对话框
// MsgDLL66.cpp : Defines the entry point for the DLL application.
//
 
#include "stdafx.h"
#include 
#include 
 
extern "C"
{
        __declspec(dllexport) int Msg() ;
}
 
DWORD WINAPI ThreadShow(LPVOID LpParameter)
{
        char szPath[MAX_PATH]={0};
        char szBuf[1024]={0};
        GetModuleFileName(NULL,szPath,MAX_PATH);
        sprintf(szBuf,"DLL 已注入到进程 %s [pid=%d]\n",szPath,GetCurrentProcessId());
        //以3种方式显示自己的存在
        //1.Msgbox
        MessageBox(NULL,szBuf,"DLL Inject",MB_OK);
        //2.控制台
        printf("%s",szBuf);
        //3.调试器
        OutputDebugString(szBuf);
        return 0;
}
 
__declspec(dllexport) int Msg()
{
        char szPath[MAX_PATH]={0};
        char szBuf[1024]={0};
        GetModuleFileName(NULL,szPath,MAX_PATH);
        sprintf(szBuf,"DLL 已注入到进程 %s [pid=%d]\n",szPath,GetCurrentProcessId());
        MessageBoxA(NULL, szBuf, "小星星", MB_OK);
        return 0;
}
 
BOOL APIENTRY DllMain( HANDLE hModule,
                                          DWORD  ul_reason_for_call,
                                          LPVOID lpReserved
                                          )
{
    switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
                CreateThread(NULL,0,ThreadShow,NULL,0,NULL);
                Msg();
                break;
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
                break;
    }
    return TRUE;
}

 上面的源码编译后得到dll文件
 

PE输入表DLL注入_第2张图片


三.修改PE输入表实现DLL注入
新建一个工程,把上面得到的dll文件放在工程目录下
 

PE输入表DLL注入_第3张图片


代码如下,关键地方都做了注释,如果PE基本结构体都不懂,那还是建议先系统学习下

// PEImportDllInject.cpp : Defines the entry point for the console application.
//
 
#include "stdafx.h"
#include 
 
#define FilePath "c:\\NOTEPAD.EXE"
#define NewFilePath "c:\\NOTEPAD_new1.EXE"
 
// 把文件读到Buffer里面
LPVOID FileToBuffer()
{
        HANDLE hFile;
        DWORD lpFileSizeHigh;
        DWORD dwFileSize;
        LPVOID  FileBuffer;
        DWORD lpNumberOfBytesRead;
        BOOL bRead;
         
        hFile = CreateFile(FilePath, GENERIC_ALL,FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
         
        if ( hFile == NULL)
        {
                printf("CreateFile error %d\n", GetLastError());
        }
         
    dwFileSize = GetFileSize(hFile,&lpFileSizeHigh);
         
        if ( dwFileSize == NULL)
        {
                printf("GetFileSize error %d\n", GetLastError());
        }
         
        FileBuffer = VirtualAlloc(0,dwFileSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
         
        if ( FileBuffer == NULL)
        {
                printf("VirtualAlloc error %d\n", GetLastError());
        }
         
        bRead = ReadFile(hFile,FileBuffer,dwFileSize,&lpNumberOfBytesRead,NULL);
         
        if ( bRead == FALSE)
        {
                printf("ReadFile error %d\n", GetLastError());
        }
         
        CloseHandle(hFile);
         
        return  FileBuffer;
}
 
// 从文件拷贝到内存
LPVOID FileToMemory(LPVOID FileBuffer)
{
        PIMAGE_DOS_HEADER pImageDosHeader;
        PIMAGE_NT_HEADERS  pImageNtHeaders;
        PIMAGE_FILE_HEADER  pImageFileHeader;
        PIMAGE_OPTIONAL_HEADER pImageOptionalHeader;
        PIMAGE_SECTION_HEADER  pImageSectionHeader;
         
         
        pImageDosHeader = (PIMAGE_DOS_HEADER)FileBuffer;
        pImageNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pImageDosHeader+pImageDosHeader->e_lfanew);
        pImageFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pImageNtHeaders+0x4);
        pImageOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pImageFileHeader+sizeof(IMAGE_FILE_HEADER));
        pImageSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader+pImageFileHeader->SizeOfOptionalHeader);
         
        DWORD dwSizeofImage = pImageOptionalHeader->SizeOfImage;
        DWORD dwSizeofHeader = pImageOptionalHeader->SizeOfHeaders;
        LPVOID MemoryBuffer;
        int i;
         
         
        MemoryBuffer = VirtualAlloc(0,dwSizeofImage*0x10,MEM_COMMIT,PAGE_READWRITE);
         
        if ( MemoryBuffer == NULL)
        {
                printf("VirtualAlloc error %d\n", GetLastError());
        }
         
        memcpy(MemoryBuffer,FileBuffer,dwSizeofHeader);
         
        for ( i = 0; i < pImageFileHeader->NumberOfSections; i++)
        {
                memcpy(  (BYTE*)((DWORD)MemoryBuffer+ pImageSectionHeader.VirtualAddress),
                        (BYTE*)((DWORD)FileBuffer+ pImageSectionHeader.PointerToRawData),
                        pImageSectionHeader.SizeOfRawData);
        }
         
        return MemoryBuffer;
}
 
// 从内存拷贝到新的文件
LPVOID MemoryToNewFile(LPVOID MemoryBuffer)
{
        PIMAGE_DOS_HEADER pImageDosHeader;
        PIMAGE_NT_HEADERS  pImageNtHeaders;
        PIMAGE_FILE_HEADER  pImageFileHeader;
        PIMAGE_OPTIONAL_HEADER pImageOptionalHeader;
        PIMAGE_SECTION_HEADER  pImageSectionHeader;
         
         
        pImageDosHeader = (PIMAGE_DOS_HEADER)MemoryBuffer;
        pImageNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pImageDosHeader+pImageDosHeader->e_lfanew);
        pImageFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pImageNtHeaders+0x4);
        pImageOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pImageFileHeader+sizeof(IMAGE_FILE_HEADER));
        pImageSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader+pImageFileHeader->SizeOfOptionalHeader);
         
        DWORD dwSizeofImage = pImageOptionalHeader->SizeOfImage;
        DWORD dwSizeofHeader = pImageOptionalHeader->SizeOfHeaders;
        LPVOID NewFileBuffer;
        int i;
         
         
        NewFileBuffer = VirtualAlloc(0,dwSizeofImage,MEM_COMMIT,PAGE_READWRITE);
         
        if ( NewFileBuffer == NULL)
        {
                printf("VirtualAlloc error %d\n", GetLastError());
        }
         
        memcpy(NewFileBuffer,MemoryBuffer,dwSizeofHeader);
         
        for ( i = 0; i < pImageFileHeader->NumberOfSections; i++)
        {
                
                memcpy(  (BYTE*)((DWORD)NewFileBuffer+ pImageSectionHeader.PointerToRawData),
                        (BYTE*)((DWORD)MemoryBuffer+ pImageSectionHeader.VirtualAddress),
                        pImageSectionHeader.Misc.VirtualSize);
        }
         
        return NewFileBuffer;
         
}
 
// 存盘写文件
void WriteToFile(LPVOID NewFileBuffer)
{
         
        PIMAGE_DOS_HEADER pImageDosHeader;
        PIMAGE_NT_HEADERS  pImageNtHeaders;
        PIMAGE_FILE_HEADER  pImageFileHeader;
        PIMAGE_OPTIONAL_HEADER pImageOptionalHeader;
        PIMAGE_SECTION_HEADER  pImageSectionHeader;
         
        pImageDosHeader = (PIMAGE_DOS_HEADER)NewFileBuffer;
        pImageNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pImageDosHeader+pImageDosHeader->e_lfanew);
        pImageFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pImageNtHeaders+0x4);
        pImageOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pImageFileHeader+sizeof(IMAGE_FILE_HEADER));
        pImageSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader+pImageFileHeader->SizeOfOptionalHeader);
         
        HANDLE hNewFile;
        DWORD dwFileSize;
        DWORD lpNumberOfBytesWritten;
        BOOL bWrite;
         
        hNewFile = CreateFile(NewFilePath, GENERIC_ALL,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
         
        if ( hNewFile == NULL)
        {
                printf("CreateFile error %d\n", GetLastError());
        }
         
        int k = pImageFileHeader->NumberOfSections-1;
         
        dwFileSize = pImageSectionHeader[k].PointerToRawData + pImageSectionHeader[k].SizeOfRawData;
         
         
        bWrite = WriteFile(hNewFile,NewFileBuffer, dwFileSize,&lpNumberOfBytesWritten,NULL);
         
        if ( bWrite == FALSE)
        {
                printf("WriteFile error %d\n", GetLastError());
        }
         
    CloseHandle(hNewFile);
}
 
//增加节表
DWORD  AddSection(LPVOID MemoryBuffer, char* SectionName, DWORD SectionSize)
{
         
        PIMAGE_DOS_HEADER pImageDosHeader;
        PIMAGE_NT_HEADERS  pImageNtHeaders;
        PIMAGE_FILE_HEADER  pImageFileHeader;
        PIMAGE_OPTIONAL_HEADER pImageOptionalHeader;
        PIMAGE_SECTION_HEADER  pImageSectionHeader;
         
        pImageDosHeader = (PIMAGE_DOS_HEADER)MemoryBuffer;
        pImageNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pImageDosHeader+pImageDosHeader->e_lfanew);
        pImageFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pImageNtHeaders+0x4);
        pImageOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pImageFileHeader+sizeof(IMAGE_FILE_HEADER));
        pImageSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader+pImageFileHeader->SizeOfOptionalHeader);
         
        pImageOptionalHeader->DataDirectory[0xb].Size = 0;
        pImageOptionalHeader->DataDirectory[0xb].VirtualAddress = 0;
         
        DWORD AddFileAddress;
        DWORD AddMemAddress;
         
    int i = pImageFileHeader->NumberOfSections;
         
        pImageFileHeader->NumberOfSections += 0x1;
         
        AddFileAddress = pImageSectionHeader[i-1].PointerToRawData + pImageSectionHeader[i-1].SizeOfRawData;
        AddMemAddress = pImageSectionHeader[i-1].VirtualAddress+ pImageSectionHeader[i-1].Misc.VirtualSize;
         
        if ( AddFileAddress % 0x1000 )
        {
        AddFileAddress = (AddFileAddress+0x1000)&0xFFFFF000;
        }
         
        if ( AddMemAddress % 0x1000 )
        {
        AddMemAddress = (AddMemAddress+0x1000)&0xFFFFF000;
        }
         
        strcpy( (char*)pImageSectionHeader.Name, SectionName);
        pImageSectionHeader.PointerToRawData = AddFileAddress;
        pImageSectionHeader.VirtualAddress = AddMemAddress;
        pImageSectionHeader.SizeOfRawData = SectionSize;
        pImageSectionHeader.Misc.VirtualSize = SectionSize;
        pImageSectionHeader.Characteristics = 0xFFFFFFFF;
         
        pImageOptionalHeader->SizeOfImage = pImageSectionHeader.VirtualAddress+pImageSectionHeader.Misc.VirtualSize;
         
        DWORD AddSectionBuffer;
         
        AddSectionBuffer = (DWORD)MemoryBuffer+AddMemAddress;
         
         
        return AddSectionBuffer;
}
 
//输入表dll注入
int DLLInject(LPVOID MemoryBuffer,DWORD AddSectionBuffer)
{
        PIMAGE_DOS_HEADER pImageDosHeader;
        PIMAGE_NT_HEADERS  pImageNtHeaders;
        PIMAGE_FILE_HEADER  pImageFileHeader;
        PIMAGE_OPTIONAL_HEADER pImageOptionalHeader;
        PIMAGE_SECTION_HEADER  pImageSectionHeader;
        PIMAGE_IMPORT_DESCRIPTOR pImport;
         
        pImageDosHeader = (PIMAGE_DOS_HEADER)MemoryBuffer;
        pImageNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pImageDosHeader+pImageDosHeader->e_lfanew);
        pImageFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pImageNtHeaders+0x4);
        pImageOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pImageFileHeader+sizeof(IMAGE_FILE_HEADER));
        pImageSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader+pImageFileHeader->SizeOfOptionalHeader);        
        pImport=(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)MemoryBuffer+pImageOptionalHeader->DataDirectory[1].VirtualAddress);
        DWORD TotalSize;
        DWORD* NewAddr=(DWORD*)AddSectionBuffer;
         
         
        //1.备份原IID结构
        memcpy(NewAddr,pImport,pImageOptionalHeader->DataDirectory[1].Size);
         
        //结束标记 以0结束
        memset((void*)((DWORD)NewAddr+pImageOptionalHeader->DataDirectory[1].Size),0,sizeof(_IMAGE_IMPORT_DESCRIPTOR));
         
        //2.在原IID 区域构造新的IID的OFT Name FT结构
        DWORD DLLNameRVA=(DWORD)pImport+0x16;
        char*DLLName="MsgDLL66.dll";
        DWORD DLLNameSize=(strlen(DLLName)+1+1)&0xe;
        memcpy((void*)DLLNameRVA,DLLName,DLLNameSize);
        DWORD ByNameRVA=DLLNameRVA+DLLNameSize;
        memset((void*)ByNameRVA,0,2);//hint填充为0
        char*FunName="Msg";
        DWORD FunNameSize=(strlen(FunName)+1+1)&0xe;
        memcpy((void*)(ByNameRVA+2),FunName,FunNameSize);
        *(DWORD*)pImport=ByNameRVA-(DWORD)MemoryBuffer;
        *(DWORD*)((DWORD)pImport+0x4)=0x0;
        *(DWORD*)((DWORD)pImport+0x8)=ByNameRVA-(DWORD)MemoryBuffer;
        *(DWORD*)((DWORD)pImport+0xc)=0x0;
         
        //3.填充新输入表项的IID结构
        PIMAGE_IMPORT_DESCRIPTOR NewIID=(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)NewAddr+pImageOptionalHeader->DataDirectory[1].Size-sizeof(_IMAGE_IMPORT_DESCRIPTOR));
        NewIID->OriginalFirstThunk=(DWORD)pImport-(DWORD)MemoryBuffer;
        NewIID->Name=DLLNameRVA-(DWORD)MemoryBuffer;
        NewIID->FirstThunk=(DWORD)pImport+0x8-(DWORD)MemoryBuffer;
         
        //4.修正PE文件头的信息
        //修改.txt属性
        pImageSectionHeader[0].Characteristics=0xE0000020;
        //修改新节表的属性为0xFFFFFFFF 以及数据目录第B项改为00 (新增节时已经改了)
        //更正输入表的地址以及大小
        pImageOptionalHeader->DataDirectory[1].VirtualAddress=(DWORD)NewAddr-(DWORD)MemoryBuffer;
        pImageOptionalHeader->DataDirectory[1].Size+=sizeof(_IMAGE_IMPORT_DESCRIPTOR);
         
        return 0;
}
 
int main(int argc, char* argv[])
{
        LPVOID  FileBuffer;
        LPVOID  MemoryBuffer;
        LPVOID  NewFileBuffer;
        DWORD AddSectionBuffer;
        // 把文件读到Buffer里面
        FileBuffer = FileToBuffer();
         
        // 从文件拷贝到内存
        MemoryBuffer = FileToMemory(FileBuffer);
 
        //增加节表
        AddSectionBuffer = AddSection(MemoryBuffer, ".111", 0x1000);
 
        //DLL注入
        DLLInject(MemoryBuffer,AddSectionBuffer);
         
        // 从内存拷贝到新的文件
        NewFileBuffer = MemoryToNewFile(MemoryBuffer);
 
        // 存盘写文件
         WriteToFile(NewFileBuffer);
 
 
        printf("Hello World!\n");
        return 0;
}

四.测试效果
运行后在C盘生成了如下新文件
 

PE输入表DLL注入_第4张图片


双击后在打开记事本之前首先弹出了我们注入的dll弹框
 

PE输入表DLL注入_第5张图片


注入成功;;;;
我们再用od加载:
 

PE输入表DLL注入_第6张图片


可以看到,我们的dll也在其中
用LordPE工具加载在输入表里也看到了我们自己写的dll
 

PE输入表DLL注入_第7张图片


由此可见,dll注入确实成功啦


点击下载完整源码

你可能感兴趣的:(单片机,stm32,嵌入式硬件)