开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 2521|回复: 4
收起左侧

[Windows逆向] PE输入表DLL注入,只看这篇干货就够了(分享源码)

[复制链接]
发表于 2023-8-16 01:54:45 | 显示全部楼层 |阅读模式   湖南省常德市
本帖最后由 小希啊 于 2023-8-16 02:26 编辑

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


下面逐步讲解并附带源码
二.编写DLL
自行编写DLL,导出一个函数,弹出对话框
[C++] 纯文本查看 复制代码
// 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基本结构体都不懂,那还是建议先系统学习下,精易逆向安全培训就挺不错,主讲老师根哥真的是我遇到过的线上最好的培训老师,零基础的也不用担心,我就是零基础开始学的.
[C++] 纯文本查看 复制代码
// 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注入确实成功啦




在逆向三期中有一个作业就是自己写一个LordPE工具,跟着老师的课程来,这个作业一点不难,本来想上传视频分享下我写的,发现好像发不了视频,就此作罢
大家果有任何不明白的地方欢迎与我交流,我必定知无不言,也欢迎大家报名逆向四期!






本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
发表于 2024-1-19 23:56:41 | 显示全部楼层   广东省潮州市
感谢分享,很给力!
回复 支持 反对

使用道具 举报

发表于 2023-8-16 12:55:54 | 显示全部楼层   广东省梅州市
小星星是我的。
回复 支持 反对

使用道具 举报

结帖率:0% (0/1)
发表于 2023-8-16 09:21:05 | 显示全部楼层   吉林省延边朝鲜族自治州
写的真棒,不亏是,三期扛大旗的存在~@!
回复 支持 反对

使用道具 举报

发表于 2023-8-16 09:12:44 | 显示全部楼层   河南省郑州市
非常棒
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

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