吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 776|回复: 1
收起左侧

[求助] 为什么这个程序向notepad第二个节后面加入shellcode代码会失败

[复制链接]
d173220523 发表于 2020-7-2 17:25
本帖最后由 d173220523 于 2020-7-2 17:29 编辑

[C] 纯文本查看 复制代码
#include "iostream"
#include <windows.h>

#define size_shellcode 0x12
#define messagebox_add 0x77d507ea
BYTE shellcode[] = {
        0x6A,00,0x6A,00,0x6A,00,0x6A,00,
        0XE8,00,00,00,00,
        0XE9,00,00,00,00
};

char file_path[] = "C:\\WINDOWS\\system32\\notepad.exe";
char write_file_path[] = "C:\\notepad1.exe";

// exe->filebuffer  返回值为计算所得文件大小
int ReadPEFile(char* file_path,PVOID* pFileBuffer)
{
        FILE* pfile = NULL;  // 文件指针
        DWORD file_size = 0;
        LPVOID pTempFilebuffer = NULL;
        
        // 打开文件
        pfile = fopen(file_path,"rb");  // 如果有新的指针,就要进行判断
        if(!pfile)
        {
                printf("打开exe文件失败!\n");//如果分配失败就要关闭文件、释放动态内存、指针指向NULL
                return 0;
        }        
        // 读取文件大小
        fseek(pfile,0,SEEK_END);
        file_size = ftell(pfile);
        fseek(pfile,0,SEEK_SET);
        // 分配空间
        pTempFilebuffer = malloc(file_size);  // 如果有新的指针,就要进行判断
        if(!pTempFilebuffer)
        {
                printf("分配空间失败!\n");//如果分配失败就要关闭文件、释放动态内存、指针指向NULL
                fclose(pfile);
                return 0 ;
        }
        // 将数据读取到内存中
        size_t n = fread(pTempFilebuffer,file_size,1,pfile);
        if(!n)
        {
                printf("数据读取到内存中失败!\n"); //如果分配失败就要关闭文件、释放动态内存、指针指向NULL
                fclose(pfile);
                free(pTempFilebuffer);
                return 0 ;
        }
        // 关闭文件(已经读取到内存了)
        *pFileBuffer = pTempFilebuffer;
        pTempFilebuffer = NULL;
        fclose(pfile); 
        return file_size;
}

// filebuffer -> imagebuffer
DWORD CopyFileBufferToImageBuffer(PVOID pFileBuffer,PVOID* pImageBuffer)
{
        // 初始化PE头部结构体
        PIMAGE_DOS_HEADER pDosHeader = NULL;        
        PIMAGE_NT_HEADERS pNTHeader = NULL;        
        PIMAGE_FILE_HEADER pPEHeader = NULL;        
        PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
        PIMAGE_SECTION_HEADER pSectionHeader = NULL;
        // 初始化IMAGE_BUFFER指针(temparay)
        LPVOID pTempImagebuffer = NULL;

        if(!pFileBuffer)
        {
                printf("(2pimagebuffer阶段)读取到内存的pfilebuffer无效!\n");
                return 0 ;
        }
        // 判断是否是可执行文件
        if(*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE)  // IMAGE_DOS_SIGNATURE是4字节,将pFileBuffer强制类型转换为4字节指针类型(PWORD)
        {
                printf("(2pimagebuffer阶段)不含MZ标志,不是exe文件!\n");
                return 0;
        }
        //强制结构体类型转换pDosHeader
        pDosHeader = PIMAGE_DOS_HEADER(pFileBuffer);
        //判断是否含有PE标志       
        if(*((PDWORD)((DWORD)pFileBuffer+pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE) // 注意指针的加法是:去掉一个*后的类型相加。必须转换为DWORD类型再加减。
        {                                                                                                                                                          //相加后的和 强制类型转换为4字节指针类型(PWORD) IMAGE_NT_SIGNATURE 4BYTES
                printf("(2pimagebuffer阶段)不是有效的PE标志!\n");        
                return 0;
        }
        // 强制结构体类型转换
        pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew);
        pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader+4);
        pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);
        pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader);

        // 分配动态内存
        pTempImagebuffer = malloc(pOptionHeader->SizeOfImage);
        if(!pTempImagebuffer)
        {
                printf("分配动态内存失败!\n");
                free(pTempImagebuffer);
                return 0;
        }
        // 初始化动态内存
        memset(pTempImagebuffer,0,pOptionHeader->SizeOfImage);
        // 拷贝头部
        memcpy(pTempImagebuffer,pDosHeader,pOptionHeader->SizeOfHeaders);
        // 循环拷贝节表
        PIMAGE_SECTION_HEADER pTempSectionHeader = pSectionHeader;
        for(DWORD i = 0;i<pPEHeader->NumberOfSections;i++,pTempSectionHeader++)
        {
                memcpy((void*)((DWORD)pTempImagebuffer+pTempSectionHeader->VirtualAddress),(void*)((DWORD)pFileBuffer+pTempSectionHeader->PointerToRawData),pTempSectionHeader->SizeOfRawData);
        }
        // 返回数据
        *pImageBuffer = pTempImagebuffer;
        pTempImagebuffer = NULL;
        return pOptionHeader->SizeOfImage;
}

//imagebuffer->newbuffer
DWORD CopyImageBufferToNewBuffer(PVOID pImageBuffer,PVOID* pNewBuffer)
{
        // 初始化PE头部结构体
        PIMAGE_DOS_HEADER pDosHeader = NULL;        
        PIMAGE_NT_HEADERS pNTHeader = NULL;        
        PIMAGE_FILE_HEADER pPEHeader = NULL;        
        PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
        PIMAGE_SECTION_HEADER pSectionHeader = NULL;

        // 初始化NEW_BUFFER指针(temparay)
        LPVOID pTempNewbuffer = NULL;

        // 判断pImageBuffer是否有效
        if(!pImageBuffer)
        {
                printf("(2pnewbuffer阶段)读取到内存的pimagebuffer无效!\n");
                return 0;
        }
        //判断是不是exe文件
        if(*((PWORD)pImageBuffer) != IMAGE_DOS_SIGNATURE)
        {
                printf("(2pnewbuffer阶段)不含MZ标志,不是exe文件!\n");
                return 0;
        }
        // 强制结构体类型转换
        pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
        if(*((PDWORD)((DWORD)pImageBuffer+pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
        {
                printf("(2pnewbuffer阶段)不是有效的PE标志!\n");        
                return 0;
        }
        // 强制结构体类型转换
        pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pImageBuffer+pDosHeader->e_lfanew);
        pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader+4); // 这里必须强制类型转换
        pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);
        pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader);

        //获取new_buffer的大小
        int new_buffer_size = pOptionHeader->SizeOfHeaders;
        for(DWORD i = 0;i<pPEHeader->NumberOfSections;i++)
        {
                new_buffer_size += pSectionHeader[i].SizeOfRawData;  // pSectionHeader[i]另一种加法
        }
        // 分配内存(newbuffer)
        pTempNewbuffer = malloc(new_buffer_size);
        if(!pTempNewbuffer)
        {
                printf("(2pnewbuffer阶段)分配Newbuffer失败!\n");
                return 0;
        }
        memset(pTempNewbuffer,0,new_buffer_size);
        // 拷贝头部
        memcpy(pTempNewbuffer,pDosHeader,pOptionHeader->SizeOfHeaders);
        // 循环拷贝节区
        PIMAGE_SECTION_HEADER pTempSectionHeader = pSectionHeader;
        for(DWORD j = 0;j<pPEHeader->NumberOfSections;j++,pTempSectionHeader++)
        {        //PointerToRawData节区在文件中的偏移,VirtualAddress节区在内存中的偏移地址,SizeOfRawData节在文件中对齐后的尺寸
                memcpy((PDWORD)((DWORD)pTempNewbuffer+pTempSectionHeader->PointerToRawData),(PDWORD)((DWORD)pImageBuffer+pTempSectionHeader->VirtualAddress),pTempSectionHeader->SizeOfRawData);
        }
        //返回数据
        *pNewBuffer = pTempNewbuffer; //暂存的数据传给参数后释放
        pTempNewbuffer = NULL;
        return new_buffer_size;  // 返回计算得到的分配内存的大小
}

//newbuffer->存盘
int newbuffer_write2_exe(PVOID NewFileBuffer,DWORD FileSize, char* FilePath)
{
        FILE* fp1 = fopen(FilePath,"wb");
        if(fp1 != NULL)
        {
                fwrite(NewFileBuffer,FileSize,1,fp1);
        }
        fclose(fp1);
        return 1;
}

int add_section(PVOID* pNewFileBuffer,PVOID pImageBuffer,DWORD FileSize)
{
        // 初始化PE头部结构体
        PIMAGE_DOS_HEADER pDosHeader = NULL;        
        PIMAGE_NT_HEADERS pNTHeader = NULL;        
        PIMAGE_FILE_HEADER pPEHeader = NULL;        
        PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
        PIMAGE_SECTION_HEADER pSectionHeader = NULL;

        // 判断pImageBuffer是否有效
        if(!pImageBuffer)
        {
                printf("读取到内存的pfilebuffer无效!\n");
                return 0;
        }
        //判断是不是exe文件
        if(*((PWORD)pImageBuffer) != IMAGE_DOS_SIGNATURE)
        {
                printf("不含MZ标志,不是exe文件!\n");
                return 0;
        }
        // 强制结构体类型转换
        pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
        if(*((PDWORD)((DWORD)pImageBuffer+pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
        {
                printf("不是有效的PE标志!\n");        
                return 0;
        }
        // 强制结构体类型转换
        pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pImageBuffer+pDosHeader->e_lfanew);
        pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader+4); // 这里必须强制类型转换
        pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);
        pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader);
pSectionHeader++;
        // 判断代码区大小够不够
        if(size_shellcode>(pSectionHeader->SizeOfRawData-pSectionHeader->Misc.VirtualSize))
        {
                printf("代码区空间不足!\n"); 
                free(pImageBuffer);
                return 0;
        }
        printf("pSectionHeader->PointerToRawData:%#x  pSectionHeader->Misc.VirtualSize:%#x\n",pSectionHeader->PointerToRawData,pSectionHeader->Misc.VirtualSize);
        printf("pImageBuffer:%#x\n",pImageBuffer);
        // 将代码复制到空白区
        PBYTE code_begin = (PBYTE)((DWORD)pImageBuffer+pSectionHeader->VirtualAddress+pSectionHeader->Misc.VirtualSize);
        printf("pSectionHeader->VirtualAddress:%#X\n",pSectionHeader->VirtualAddress);
        printf("code_begin:%#x\n",code_begin);
        memcpy(code_begin,shellcode,size_shellcode);
        // 修改E8 跳到messagebox
        DWORD callAddr = (messagebox_add-(pOptionHeader->ImageBase+((DWORD)(code_begin+0xD)-(DWORD)pImageBuffer)));  //(DWORD)code_begin+0xoD-(DWORD)pImageBuffer是E8下一条指令的地址的相对偏移
        printf("callAddr:%#X\n",callAddr);
        *(PDWORD)(code_begin+0x09) = callAddr; //填充数据
        // 修改E9 跳回程序开始
        DWORD jmpAddr = ((pOptionHeader->ImageBase + pOptionHeader->AddressOfEntryPoint)-(pOptionHeader->ImageBase+((DWORD)code_begin+size_shellcode-(DWORD)pImageBuffer)));
        *(PDWORD)(code_begin+0x0E) = jmpAddr;
        // 修改OEP
        pOptionHeader->AddressOfEntryPoint = (DWORD)code_begin - (DWORD)pImageBuffer;
        // imagebuffer->newfilebuffer
        int size = CopyImageBufferToNewBuffer(pImageBuffer,pNewFileBuffer);

        if(size = 0 || !pNewFileBuffer)
        {
                printf("imagebuffer->newfilebuffer失败!\n");
                free(pImageBuffer);
                free(pNewFileBuffer);
        }
        // 存盘
        int ret4 = newbuffer_write2_exe(*pNewFileBuffer,FileSize, write_file_path);
        if(!ret4)
        {
                printf("存盘失败!\n");
                return 0;
        }
        return 1;

}

void operate_pe()
{   
        // 初始化操作
        PVOID pFileBuffer = NULL;
        PVOID pNewFileBuffer = NULL;
        PVOID pImageBuffer = NULL;
        DWORD NewFileBufferSize = 0;
        // exe->filebuffer
        int ret1 = ReadPEFile(file_path,&pFileBuffer);  // &pFileBuffer(void**类型) 传递地址对其值可以进行修改
        printf("exe->filebuffer  返回值为计算所得文件大小:%#x\n",ret1);

        // filebuffer -> imagebuffer
        int ret2 = CopyFileBufferToImageBuffer(pFileBuffer,&pImageBuffer);
        printf("filebuffer -> imagebuffer返回值为计算所得文件大小:%#x\n",ret2);
        
        // add_section
        int ret3 = add_section(&pNewFileBuffer,pImageBuffer,ret1);
        printf("%d",ret3);

        free(pFileBuffer);
        free(pNewFileBuffer);
        free(pImageBuffer);
}

int main()
{        
        operate_pe();
        return 0;
}

但第229行我改成+=2程序可以运行也能弹出窗口,但是在uedit里面我找不到6a00在哪里
Windows XP By 52PoJie-2020-07-02-17-29-04.png

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

cube 发表于 2020-7-3 03:21
用"数据与其所在对应段的偏移地址"在uedit中找.
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-26 15:32

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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