PE输入表DLL注入
一.实现效果
启动notepad.exe时能够加载自己编写的dll.
最终效果如图所示
下面逐步讲解并附带源码
二.编写DLL
自行编写DLL,导出一个函数,弹出对话框
- // MsgDLL66.cpp : Defines the entry point for the DLL application.
- //
- #include “stdafx.h”
- #include <windows.h>
- #include <stdio.h>
- 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注入
新建一个工程,把上面得到的dll文件放在工程目录下
代码如下,关键地方都做了注释,如果PE基本结构体都不懂,那还是建议先系统学习下
- // PEImportDllInject.cpp : Defines the entry point for the console application.
- //
- #include “stdafx.h”
- #include <windows.h>
- #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盘生成了如下新文件
双击后在打开记事本之前首先弹出了我们注入的dll弹框
注入成功;;;;
我们再用od加载:
可以看到,我们的dll也在其中
用LordPE工具加载在输入表里也看到了我们自己写的dll
由此可见,dll注入确实成功啦 |