PE:AddNewSection

DWORD AddNewSection(IN PVOID pFileBuffer, OUT PVOID* pNewFileBuffer)
{
    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;

    if(!pFileBuffer)
    {
        printf("FileBuffer無效!\n");
        free(pFileBuffer);
        return;
    }
    if(*(PWORD)pFileBuffer != IMAGE_DOS_SIGNATURE)
    {
        printf("不是有效的PE文件\n");
        free(pFileBuffer);
        return;
    }
    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    pNTHeader = (PIMAGE_NT_HEADERS)(pDosHeader + pDosHeader->e_lfanew);
    pPEHeader = (PIMAGE_FILE_HEADER)(pNTHeader + 4);
    pOptionHeader = (PIMAGE_OPTIONAL_HEADER)(pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
    pSectionHeader = (PIMAGE_SECTION_HEADER)(pOptionHeader + pPEHeader->SizeOfOptionalHeader);
    //判斷是否有足夠的空間添加一個節表
    if((pOptionHeader->SizeOfHeaders - (pDosHeader->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER + pPEHeader->SizeOfOptionalHeader + IMAGE_SIZEOF_SECTION_HEADER * pPEHeader->NumberOfSections)) < IMAGE_SIZEOF_SECTION_HEADER * 2)
    {
       printf("添加節表空間不足\n");
       free(pFileBuffer);
       return;
    }
    //計算添加節後的大小sizeOfFileBuffer
    DWORD sizeOfNewFileBuffer = 0;
    DWORD sizeOfSections = 0;
    DWORD sizeOfFileBuffer = 0;
    PIMAGE_SECTION_HEADER pTemOfSectionHeader = pSectionHeader;
    for(int i=0;i<pPEHeader->NumberOfSections;pTemOfSectionHeader++,i++)
    {
        sizeOfSections += pTemOfSectionHeader->PointerToRawData;
    }
    sizeOfFileBuffer = sizeOfSections + pOptionHeader->SizeOfHeaders;
    sizeOfNewFileBuffer = sizeOfFileBuffer + pOptionHeader->FileAlignment;//增加一個文件對齊長度的大小的節
    //分配新的緩衝區
    PVOID pTemOfNewFileBuffer = NULL;
    pTemOfNewFileBuffer = malloc(sizeOfNewFileBuffer);
    if(!pTemOfNewFileBuffer)
    {
        printf("pTemOfNewFileBuffer分配失敗!\n");
        free(pFileBuffer);
        return;
    }
    //複製PE文件到新的緩衝區
    memset(pTemOfNewFileBuffer,0,sizeOfNewFileBuffer);
    memcpy(pTemOfNewFileBuffer,pFileBuffer,sizeOfFileBuffer);
    //添加新節表並修改屬性
    //通過上面的循環後,pTemOfSectionHeader是新節表的RVA
    PIMAGE_SECTION_HEADER pNewSectionHeader = (PIMAGE_SECTION_HEADER)(((DWORD)pTemOfSectionHeader - (DWORD)pFileBuffer) + (DWORD)pNewFileBuffer);
    memset(pNewSectionHeader,0,0x80);//填充兩個節表大小的0
    memcpy(pNewSectionHeader->Name,"new",sizeof("new"));
    pNewSectionHeader->Misc.VirtualSize = pOptionHeader->FileAlignment;
    pNewSectionHeader->VirtualAddress = (pNewSectionHeader - 1)->VirtualAddress + pOptionHeader->SectionAlignment;
    pNewSectionHeader->SizeOfRawData = pOptionHeader->FileAlignment;
    pNewSectionHeader->PointerToRawData = (pNewSectionHeader - 1)->PointerToRawData + (pNewSectionHeader - 1)->SizeOfRawData;
    pNewSectionHeader->Characteristics = pNewSectionHeader->Characteristics||0x60000020;
    //修改NumberOfSections和sizeofimage
    pPEHeader->NumberOfSections += 1;
    pOptionHeader->SizeOfImage += pOptionHeader->FileAlignment;

    *pNewFileBuffer = pTemOfNewFileBuffer;
    pTemOfNewFileBuffer = NULL;
    free(pFileBuffer);
    return sizeOfNewFileBuffer;
}
1、判斷是否有足夠的空間,可以添加一個節表.
判斷條件:
SizeOfHeader - (DOS + 垃圾數據 + PE標記 + 標準PE頭 + 可選PE頭 + 已存在節表)
>= 2個節表的大小
2、需要修改的數據
1) 添加一個新的節(可以copy一份)
2) 在新增節表後面 填充一個節大小的0;
3) 修改PE頭中節的數量
4) 修改sizeOfImage的大小
5) 再原有數據的最後,新增一個節的數據(內存對齊的整數倍).
6)修正新增節表的屬性
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章