ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

脱壳与加壳-加壳-1-手工实现添加区段

2021-04-07 23:04:32  阅读:256  来源: 互联网

标签:脱壳 LastSection pOptionHeader 加壳 PE 区段 DWORD FileBuff


脱壳与加壳-加壳-1-手工实现添加区段

给壳代码开辟空间来存放壳代码

方法1:在空白的区段头到区段的位置添加区段头

在区段的最后一个后面开辟新的区段

步骤

1 读取文件

2 创建buff存放PE文件镜像

3 解析PE(DOS头、NT头、可选PE头、标准PE头)

4 添加区段、修改相关PE某些字段值

5 将壳代码写入新区段

6 保存文件

 

 

代码实现

1 读取文件

    //打开文件,获得文件句柄
HANDLE hFile = CreateFileA(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
//获得文件大小
FileSize = GetFileSize(hFile,0);
//给FileBuff开辟空间来存储文件内容
FileBuff = new char[FileSize];
//读取文件到缓冲区
DWORD RealRead = 0;
BOOL IfSuccess = ReadFile(hFile, FileBuff, FileSize, &RealRead, NULL);
if (IfSuccess == FALSE)
{
MessageBoxA(0, "打开文件失败", "报错", MB_OK);
return FALSE;
}
CloseHandle(hFile);
return TRUE;

2 存放Buff

New一个buff来存放原来的文件

3 解析PE头

存放PE头的一些属性

    pDosHeader = (PIMAGE_DOS_HEADER)FileBuff;
pNtHeader = (PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew + FileBuff);
pFileHeader = &pNtHeader->FileHeader;
pOptionHeader = &pNtHeader->OptionalHeader;
return 0;

4 添加区段修改相关属性

 

    //1 先要判断区段表后面 是否足够存放两个区段头的地址
DWORD k = pFileHeader->NumberOfSections;
k *= sizeof(IMAGE_SECTION_HEADER);//区段数*每个区段头的大小=整个区段头有多大
k = k + 504; //总的区段头的大小+可选PE头的结尾位置的地址
//利用文件对齐来计算剩余的值
DWORD FileAlignment = pOptionHeader->FileAlignment;
DWORD Surplus = FileAlignment - k % FileAlignment;
//Surplus就是剩下的内容了
if (Surplus < 2 * sizeof(IMAGE_SECTION_HEADER))
{
MessageBoxA(0, "区段剩余内存不够", "报错", MB_OK);
return 0;
}
//2 创建新的缓冲区来存放新的PE文件,因为这里假设添加了ShellCode进去
//这里需要注意的是需要注意对齐值的应用,获取对齐后的PE文件大小
DWORD newFileSize = GetAlignSize(FileSize+ ShellCodeSize,pOptionHeader->FileAlignment);
//3 创建新的缓冲区来存放PE文件
char* newFileBuff = new char[newFileSize];
memcpy_s(newFileBuff, newFileSize, FileBuff, FileSize);
FileSize = newFileSize;
delete[] FileBuff;
FileBuff = newFileBuff;
//4更新PE文件信息
InitFileInfo();
//5给新增的区段添加区段头
PIMAGE_SECTION_HEADER LastSection = GetLastSection();
LastSection++;//也就是新添加的区段的首个区段
//给新区段头设置属性
//设置区段内存大小,省事直接安装内存大小对齐
LastSection->Misc.VirtualSize = GetAlignSize(ShellCodeSize, pOptionHeader->SectionAlignment);
//设置名称
strcpy_s((char*)LastSection->Name, 8, SectionName);
//设置区段文件大小
LastSection->SizeOfRawData = GetAlignSize(ShellCodeSize, pOptionHeader->FileAlignment);
//设置偏移值,在内存中的偏移值
PIMAGE_SECTION_HEADER PreLastSectionHeader = GetLastSection();
//新加的区段的内存中的偏移=上一个区段内存中的偏移+内存中的大小对齐后的值
LastSection->VirtualAddress = PreLastSectionHeader->VirtualAddress
+ GetAlignSize(PreLastSectionHeader->Misc.VirtualSize, pOptionHeader->SectionAlignment);
//设置文件中的偏移
LastSection->PointerToRawData = PreLastSectionHeader->PointerToRawData +
+PreLastSectionHeader->SizeOfRawData;
LastSection->Characteristics = dwAttribute;
//将壳代码放到新区段
return 0;

5 保存Buff到文件里面

 

代码实现

//.h文件
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<Windows.h>
#include<iostream>
#include<string>
class CPeUtil
{
public:
CPeUtil();
~CPeUtil();
BOOL LoadFile(const char*path);//加载PE文件
BOOL InitFileInfo();//初始化
BOOL InsertSection(const char*SectionName,DWORD ShellCodeSize,char* ShellCodeBuff,DWORD dwAttribute);//添加区段函数,分别是区段名字,壳代码大小,壳代码指针,区段属性
DWORD GetAlignSize(DWORD RealSize,DWORD AlignSize);
PIMAGE_SECTION_HEADER GetLastSection();
private:
char *FileBuff;
DWORD FileSize;
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS pNtHeader;
PIMAGE_OPTIONAL_HEADER pOptionHeader;
PIMAGE_FILE_HEADER pFileHeader;
};
#include"main.h"
CPeUtil::CPeUtil()
{
FileBuff = NULL;
pDosHeader = NULL;
pNtHeader = NULL;
pOptionHeader = NULL;
pFileHeader = NULL;
}
CPeUtil::~CPeUtil()
{
if (FileBuff)
{
delete[] FileBuff;
}
}
BOOL CPeUtil::LoadFile(const char* path)
{
//打开文件,获得文件句柄
HANDLE hFile = CreateFileA(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
//获得文件大小
FileSize = GetFileSize(hFile,0);
//给FileBuff开辟空间来存储文件内容
FileBuff = new char[FileSize];
//读取文件到缓冲区
DWORD RealRead = 0;
BOOL IfSuccess = ReadFile(hFile, FileBuff, FileSize, &RealRead, NULL);
if (IfSuccess == FALSE)
{
MessageBoxA(0, "打开文件失败", "报错", MB_OK);
return FALSE;
}
CloseHandle(hFile);
return TRUE;
}
BOOL CPeUtil::InitFileInfo()
{
pDosHeader = (PIMAGE_DOS_HEADER)FileBuff;
pNtHeader = (PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew + FileBuff);
pFileHeader = &pNtHeader->FileHeader;
pOptionHeader = &pNtHeader->OptionalHeader;
return 0;
}
DWORD CPeUtil::GetAlignSize(DWORD RealSize, DWORD AlignSize)
{
if (RealSize % AlignSize == 0)
{
return RealSize;
}
else
{
return (RealSize / AlignSize + 1) * AlignSize;
}
}
PIMAGE_SECTION_HEADER CPeUtil::GetLastSection()
{
PIMAGE_SECTION_HEADER FirstSection = IMAGE_FIRST_SECTION(pNtHeader);
FirstSection =FirstSection+ pFileHeader->NumberOfSections - 1;
return FirstSection;
}
BOOL CPeUtil::SaveFile(const char* path)
{
HANDLE hFile = CreateFileA(path,GENERIC_WRITE,0,NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL);
DWORD RealInput = 0;
BOOL ret =WriteFile(hFile, FileBuff, FileSize,&RealInput , NULL);
CloseHandle(hFile);
return TRUE;
}
BOOL CPeUtil::InsertSection(const char* SectionName, DWORD ShellCodeSize, char* ShellCodeBuff, DWORD dwAttribute)
{
//1 先要判断区段表后面 是否足够存放两个区段头的地址
DWORD k = pFileHeader->NumberOfSections;
k *= sizeof(IMAGE_SECTION_HEADER);//区段数*每个区段头的大小=整个区段头有多大
k = k + 504; //总的区段头的大小+可选PE头的结尾位置的地址
//利用文件对齐来计算剩余的值
DWORD FileAlignment = pOptionHeader->FileAlignment;
DWORD Surplus = FileAlignment - k % FileAlignment;
//Surplus就是剩下的内容了
if (Surplus < 2 * sizeof(IMAGE_SECTION_HEADER))
{
MessageBoxA(0, "区段剩余内存不够", "报错", MB_OK);
return 0;
}
//2 创建新的缓冲区来存放新的PE文件,因为这里假设添加了ShellCode进去
//这里需要注意的是需要注意对齐值的应用,获取对齐后的PE文件大小
DWORD newFileSize = GetAlignSize(FileSize+ ShellCodeSize,pOptionHeader->FileAlignment);
//3 创建新的缓冲区来存放PE文件
char* newFileBuff = new char[newFileSize];
memcpy_s(newFileBuff, newFileSize, FileBuff, FileSize);
FileSize = newFileSize;
delete[] FileBuff;
FileBuff = newFileBuff;
//4更新PE文件信息
InitFileInfo();
//5给新增的区段添加区段头
PIMAGE_SECTION_HEADER LastSection = GetLastSection();
LastSection++;//也就是新添加的区段的首个区段
//给新区段头设置属性
//设置区段内存大小,省事直接安装内存大小对齐
LastSection->Misc.VirtualSize = GetAlignSize(ShellCodeSize, pOptionHeader->SectionAlignment);
//设置名称
strcpy_s((char*)LastSection->Name, 8, SectionName);
//设置区段文件大小
LastSection->SizeOfRawData = GetAlignSize(ShellCodeSize, pOptionHeader->FileAlignment);
//设置偏移值,在内存中的偏移值
PIMAGE_SECTION_HEADER PreLastSectionHeader = GetLastSection();
//新加的区段的内存中的偏移=上一个区段内存中的偏移+内存中的大小对齐后的值
LastSection->VirtualAddress = PreLastSectionHeader->VirtualAddress
+ GetAlignSize(PreLastSectionHeader->Misc.VirtualSize, pOptionHeader->SectionAlignment);
//设置文件中的偏移
LastSection->PointerToRawData = PreLastSectionHeader->PointerToRawData +
+PreLastSectionHeader->SizeOfRawData;
LastSection->Characteristics = dwAttribute;
//修改Section数量
pFileHeader->NumberOfSections++;
//修改整个PE文件在内存中的大小
pOptionHeader->SizeOfImage += GetAlignSize(ShellCodeSize, pOptionHeader->SectionAlignment);

//将壳代码放到新区段


//保存Buff到PE里面
SaveFile("a");
return 0;
}

 

标签:脱壳,LastSection,pOptionHeader,加壳,PE,区段,DWORD,FileBuff
来源: https://www.cnblogs.com/Sna1lGo/p/14630005.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有