新增节代码
Posted cspecialr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了新增节代码相关的知识,希望对你有一定的参考价值。
#include "stdafx.h" #include<stdio.h> #include<windows.h> #include<malloc.h> #define ShellCodeIen 0x12 #define MessageBoxAdder 0x77D507EA BYTE ShellCode[]= 0x6A,00,0x6A,00,0x6A,00,0x6A,00, 0xE8,00,00,00,00, 0xE9,00,00,00,00 ; // //FileBuffer函数 DWORD ReadPEFile(LPVOID* ppFileBuffer) FILE* pFile=NULL; DWORD SizeFileBuffer=0; pFile=fopen("C://Documents and Settings//ma_lic//桌面//IISPutScanner.exe","rb"); if(!pFile) printf("打开notepad失败\\n"); return 0; //获取文件大小 fseek(pFile,0,SEEK_END); SizeFileBuffer=ftell(pFile); fseek(pFile,0,SEEK_SET); if(!SizeFileBuffer) printf("读取文件大小失败\\n"); return 0; //开辟空间 *ppFileBuffer=malloc(SizeFileBuffer); if(!*ppFileBuffer) printf("开辟空间失败\\n"); fclose(pFile); return 0; //复制数据 size_t n=fread(*ppFileBuffer,SizeFileBuffer,1,pFile); if(!n) printf("复制数据失败\\n"); free(*ppFileBuffer); fclose(pFile); return 0; fclose(pFile); return SizeFileBuffer; /// //FileBuffer--->ImgaeBuffer DWORD FileBufferToImageBuffer(LPVOID pFileBuffer,LPVOID* ppImageBuffer) PIMAGE_DOS_HEADER pDosHeader=NULL; PIMAGE_NT_HEADERS pNTHeader=NULL; PIMAGE_FILE_HEADER pFileHeader=NULL; PIMAGE_OPTIONAL_HEADER pOptionalHeader=NULL; PIMAGE_SECTION_HEADER pSectionHeader=NULL; if(!pFileBuffer) printf("FileBuffer函数调用失败\\n"); return 0; printf("%x\\n",pFileBuffer); //判断是否是PE文件 pDosHeader=(PIMAGE_DOS_HEADER)pFileBuffer; if(pDosHeader->e_magic!=IMAGE_DOS_SIGNATURE) printf("不是有效的MZ标志\\n"); return 0; pNTHeader=(PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew); if(pNTHeader->Signature!=IMAGE_NT_SIGNATURE) printf("不是有效的PE标志\\n"); return 0; pFileHeader=(PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4); pOptionalHeader=(PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader+20); //开辟ImageBuffer空间 *ppImageBuffer=malloc(pOptionalHeader->SizeOfImage+pOptionalHeader->SectionAlignment);//增加节才加上SectionAligement if(!*ppImageBuffer) printf("开辟ImageBuffer空间失败"); return 0; printf("SizeOfImage%x\\n",pOptionalHeader->SizeOfImage); //malloc清零 memset(*ppImageBuffer,0,pOptionalHeader->SizeOfImage); //复制Headers printf("SizeOfHeader%x\\n",pOptionalHeader->SizeOfHeaders); memcpy(*ppImageBuffer,pDosHeader,pOptionalHeader->SizeOfHeaders); //循环复制节表 pSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader+pFileHeader->SizeOfOptionalHeader); for(int i=1;i<=pFileHeader->NumberOfSections;i++,pSectionHeader++) memcpy((LPVOID)((DWORD)*ppImageBuffer+pSectionHeader->VirtualAddress),(LPVOID)((DWORD)pFileBuffer+pSectionHeader->PointerToRawData),pSectionHeader->SizeOfRawData); printf("%d\\n",i); printf("拷贝完成\\n"); return pOptionalHeader->SizeOfImage; //AddSection // LPVOID AddSection(LPVOID pImageBuffer) if(!pImageBuffer) printf("pImageBuffer参数传入失败\\n"); return 0; PIMAGE_DOS_HEADER pDosHeader=NULL; PIMAGE_NT_HEADERS pNTHeader=NULL; PIMAGE_FILE_HEADER pFileHeader=NULL; PIMAGE_OPTIONAL_HEADER pOptionalHeader=NULL; PIMAGE_SECTION_HEADER pSectionHeader=NULL; PIMAGE_SECTION_HEADER pNewSectionTable=NULL; pDosHeader=(PIMAGE_DOS_HEADER)pImageBuffer; pNTHeader=(PIMAGE_NT_HEADERS)((DWORD)pImageBuffer+pDosHeader->e_lfanew); pFileHeader=(PIMAGE_FILE_HEADER)((DWORD)pNTHeader+4); pOptionalHeader=(PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader+20); pSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader+pFileHeader->SizeOfOptionalHeader); //判断文件对齐和内存对齐 if(pOptionalHeader->FileAlignment==pOptionalHeader->SectionAlignment) printf("文件对齐和内存对齐相等\\n"); // 判断是否有足够的空间新增节表 DWORD SizeOfSectionTable=0x28; DWORD FreeBase=((DWORD)pOptionalHeader->SizeOfHeaders-((DWORD)pSectionHeader+pFileHeader->NumberOfSections*SizeOfSectionTable-(DWORD)pImageBuffer)); if(FreeBase<SizeOfSectionTable*2) printf("没有足够的空间新增节表!!!\\n"); free(pImageBuffer); return 0; printf("有足够的空间新增节表!!!\\n"); //修改NumberOfSection pFileHeader->NumberOfSections=pFileHeader->NumberOfSections+1; printf("NumberOfSection=%d\\n",pFileHeader->NumberOfSections); //修改SizeOfImage printf("SizeOfImage=%x\\n",pOptionalHeader->SizeOfImage); pOptionalHeader->SizeOfImage=pOptionalHeader->SizeOfImage+pOptionalHeader->SectionAlignment; printf("SizeOfImage=%x\\n",pOptionalHeader->SizeOfImage); //这里就不同扩大ImageBuffer了,上面已经增加了 //填写新的节表(复制.txt节表然后再修正) pNewSectionTable=(PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader+(pFileHeader->NumberOfSections-1)*SizeOfSectionTable); //开始复制.text memcpy(pNewSectionTable,pSectionHeader,SizeOfSectionTable); //修正新的节表 //循环到倒数第二个节表 for(int i=1;i<pFileHeader->NumberOfSections-1;i++,pSectionHeader++) printf("%d\\n",i); pNewSectionTable->Misc.VirtualSize=pOptionalHeader->SectionAlignment; printf("%x\\n",pNewSectionTable->Misc.VirtualSize); pNewSectionTable->VirtualAddress=pSectionHeader->VirtualAddress+pSectionHeader->SizeOfRawData; printf("%x\\n",pNewSectionTable->VirtualAddress); pNewSectionTable->SizeOfRawData=pOptionalHeader->SectionAlignment; printf("%x\\n",pNewSectionTable->SizeOfRawData); pNewSectionTable->PointerToRawData=pSectionHeader->PointerToRawData+pSectionHeader->SizeOfRawData; printf("%x\\n",pNewSectionTable->PointerToRawData); printf("新的节表修正完成!!!\\n"); return pImageBuffer; else printf("内存对齐和文件对齐不相等\\n"); printf("文件对齐和内存对齐相等\\n"); // 判断是否有足够的空间新增节表 DWORD SizeOfSectionTable=0x28; DWORD FreeBase=((DWORD)pOptionalHeader->SizeOfHeaders-((DWORD)pSectionHeader+pFileHeader->NumberOfSections*SizeOfSectionTable-(DWORD)pImageBuffer)); if(FreeBase<SizeOfSectionTable*2) printf("没有足够的空间新增节表!!!\\n"); free(pImageBuffer); return 0; printf("有足够的空间新增节表!!!\\n"); //修改NumberOfSection pFileHeader->NumberOfSections=pFileHeader->NumberOfSections+1; printf("NumberOfSection=%d\\n",pFileHeader->NumberOfSections); //修改SizeOfImage printf("SizeOfImage=%x\\n",pOptionalHeader->SizeOfImage); pOptionalHeader->SizeOfImage=pOptionalHeader->SizeOfImage+pOptionalHeader->SectionAlignment; printf("SizeOfImage=%x\\n",pOptionalHeader->SizeOfImage); //这里就不用扩大ImageBuffer了,上面已经增加了 //填写新的节表(复制.txt节表然后再修正) pNewSectionTable=(PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader+(pFileHeader->NumberOfSections-1)*SizeOfSectionTable); //开始复制.text memcpy(pNewSectionTable,pSectionHeader,SizeOfSectionTable); //修正新的节表 //循环到倒数第二个节表 for(int i=1;i<pFileHeader->NumberOfSections-1;i++,pSectionHeader++) printf("%d\\n",i); pNewSectionTable->Misc.VirtualSize=pOptionalHeader->SectionAlignment; printf("%x\\n",pNewSectionTable->Misc.VirtualSize); DWORD RawSize=pSectionHeader->SizeOfRawData; printf("%x????\\n",RawSize); //这里因为文件对齐和内存对齐不一样,所以需要对齐 while(RawSize%pOptionalHeader->SectionAlignment!=0) RawSize++; //printf("RawSize=%x\\n",RawSize); pNewSectionTable->VirtualAddress=pSectionHeader->VirtualAddress+RawSize; printf("%x\\n",pNewSectionTable->VirtualAddress); pNewSectionTable->SizeOfRawData=pOptionalHeader->SectionAlignment; printf("%x\\n",pNewSectionTable->SizeOfRawData); pNewSectionTable->PointerToRawData=pSectionHeader->PointerToRawData+pSectionHeader->SizeOfRawData; printf("%x\\n",pNewSectionTable->PointerToRawData); printf("新的节表修正完成!!!\\n"); return pImageBuffer; //ImageBufferToFileBuffer DWORD ImageBufferToFileBuffer(LPVOID pImageBuffer,LPVOID* ppBuffer) PIMAGE_DOS_HEADER pDosHeader=NULL; PIMAGE_NT_HEADERS pNTHeader=NULL; PIMAGE_FILE_HEADER pFileHeader=NULL; PIMAGE_OPTIONAL_HEADER pOptionalHeader=NULL; PIMAGE_SECTION_HEADER pSectionHeader=NULL; if(!pImageBuffer) printf("error"); return 0; pDosHeader=(PIMAGE_DOS_HEADER)pImageBuffer; pNTHeader=(PIMAGE_NT_HEADERS)((DWORD)pImageBuffer+pDosHeader->e_lfanew); pFileHeader=(PIMAGE_FILE_HEADER)((DWORD)pNTHeader+4); pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + 20); pSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader+pFileHeader->SizeOfOptionalHeader); //得到FileBuffer的大小 for(int i=1;i<pFileHeader->NumberOfSections;i++,pSectionHeader++) printf("%d\\n",i); printf("numberofsection=%d\\n",pFileHeader->NumberOfSections); printf("%x\\n",pSectionHeader->Misc.VirtualSize); printf("%x\\n",pSectionHeader->VirtualAddress); printf("%x\\n",pSectionHeader->SizeOfRawData); printf("%x\\n",pSectionHeader->PointerToRawData); //循环到最后一个节表 DWORD SizeOfBuffer=pSectionHeader->PointerToRawData+pSectionHeader->SizeOfRawData; printf("SizeOfBuffer=%x\\n",SizeOfBuffer); //开辟空间 *ppBuffer=malloc(SizeOfBuffer); if(!*ppBuffer) printf("开辟Buffer空间失败\\n"); return 0; memset(*ppBuffer,0,SizeOfBuffer); //复制头 memcpy(*ppBuffer,pImageBuffer,pOptionalHeader->SizeOfHeaders); //复制节表 pSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader+pFileHeader->SizeOfOptionalHeader); printf("woc\\n"); for(int j=1;j<=pFileHeader->NumberOfSections;j++,pSectionHeader++) printf("%d\\n",j); memcpy((LPVOID)((DWORD)*ppBuffer+pSectionHeader->PointerToRawData),(LPVOID)((DWORD)pImageBuffer+pSectionHeader->VirtualAddress),pSectionHeader->SizeOfRawData); printf("拷贝完成\\n"); return SizeOfBuffer; //存贮到新的exe BOOL MemeryToFile(LPVOID pBuffer,DWORD SizeOfBuffer) FILE* fpw=fopen("C://Documents and Settings//ma_lic//桌面//NEWSECIISPutScanner.exe","wb"); if(!fpw) printf("fpw error"); return false; if (fwrite(pBuffer, 1, SizeOfBuffer, fpw) == 0) printf("fpw fwrite fail"); return false; fclose(fpw); fpw = NULL; printf("success\\n"); return true; int main() LPVOID pFileBuffer=NULL; LPVOID* ppFileBuffer=&pFileBuffer; LPVOID pImageBuffer=NULL; LPVOID* ppImageBuffer=&pImageBuffer; DWORD SizeOfFileBuffer=0; DWORD SizeOfImageBuffer=0; DWORD SizeOfBuffer=0; LPVOID pBuffer=NULL; LPVOID* ppBuffer=&pBuffer; //调用filebuffer函数 SizeOfFileBuffer=ReadPEFile(ppFileBuffer); if(!SizeOfFileBuffer) printf("FileBuffer函数调用失败 \\n"); return 0; pFileBuffer=*ppFileBuffer; //调用FileBufferToImageBuffer函数 SizeOfBuffer=FileBufferToImageBuffer(pFileBuffer,ppImageBuffer); if(!SizeOfBuffer) printf("调用FileBufferToImageBuffer函数失败"); return 0; //调用AddSection函数 pImageBuffer=AddSection(pImageBuffer); //调用ImageBufferToBuffer SizeOfBuffer=ImageBufferToFileBuffer(pImageBuffer,ppBuffer); pBuffer=*ppBuffer; if(!SizeOfBuffer) printf("SizeOfBuffer error"); return 0; //调用MemeryToFile if(MemeryToFile(pBuffer,SizeOfBuffer)==false) printf("end"); return 0; return 0;
PE知识复习之PE新增节
一丶为什么新增节.以及新增节的步骤
例如前几讲.我们的PE文件在空白区可以添加代码.但是这样是由一个弊端的.因为你的空白区节属性可能是只读的不能执行.如果你修改了属性.那么程序就可能出现问题.所以新增一个节可以实现我们的代码.
等等.
1.新增节的步骤
1.在最后一个节位置添加一个节.如果没有空白位置.自己需要给扩展头扩大.并且自己修正节的偏移.
2.修改文件头中节表个数.
3.添加的新节表修改节表的属性. 节.VirtualAddress .这个成员指定了这个节在内存哪里展开.所以需要修改.
4.修改节表文件偏移 节.PointerToRawData 我们指定了内存中从哪里展开节.那么也需要指定这个节在文件中在哪里展开
5.修改节表中的 节数据对齐后的大小. 节.SizeofRawData. 我们新增的节.自己需要在PE文件添加一段节数据.数据的大小按照文件对齐添加. 并且填写到这个成员中.
6.修改扩展头的PE镜像大小. sizeofImage. 这个成员才是关键.如果不按照内存对齐修改镜像大小.那么我们的节就不会映射到内存中.或者PE文件根本无法执行.
二丶根据新增节步骤.实战手工添加一个节.
1.添加一个节表
添加节表的时候.需要在最后一个节后面添加.随便哪一个PE文件举例
因为扩展头中的SizeofHeaders 标明了 DOS头+NT头 +节表的大小.按照文件对齐存放.所以在400开始才是节数据.那么我们上图所示.最后一个节表为.rsrc. 我们下面有足够的空间添加一个新的节表.所以我们复制这个节表.在他后面粘贴.粘贴了一个新的.rsrc节表.
我们为这个节重命名为 AAAA
2.修改节表个数.在文件头属性中.
文件头中有一个属性记录了我们节表的个数.我们新增了一个节.那么就需要在原有的个数上加1.找到文件头记录节表个数位置.并加一即可.
原为7,现在改为8即可.
3.修正节表中的偏移.
我们新增了一个节表.那么我们就要为这个节表指明内存中开始展开的位置. 文件中展开的位置. 以及节数据的大小.
对应的三个成员分别是:
节.VirtualAddress
节.SizeOfRawData
节.PointerToRawData
3.1 节.VirtuallAddress修改
首先第一个成员. 节.virtuallAddress .我们按照文件对齐.与上一个节表对齐存放即可.
例如上一个节表对齐后的展开位置为 0x1c000 那么我们就修改为 0x1d000
3.2 节.sizeofRawData修改
这个成员就是节数据按照文件对齐后的大小.取决于我们给这个节添加多少数据.我们可以在PE文件后面添加 0x1000个字节.
新增的节开始位置改成FFFFF方便我们查看.
我们添加了0x1000的节数据.那么这个成员就修改为0x1000
3.3 节.PointerRawToData 文件偏移修改
最后修改的就是节在文件中哪里展开的. 这个我们需要看上一个节的文件偏移.以及节数据大小. 算出来的.
例如上一个节 偏移位置为10. 那么节数据为100. 那么节数据就是从10 ~ 100都是上一个节. 我们的节展开就要从100位置展开.
例如下图:
上一个节开始位置是8400 节数据对齐后的大小是0x600 他俩相加则是 0x8A00. 所以我们的偏移位置在0x8A00开始.
4.修改扩展头中PE的镜像大小 SizeofImage
我们新增了0x1000节数据大小.那么我们的镜像大小也要加0x1000大小进行映射.注意.要按照内存对齐.
我们的原镜像大小以及按照内存对齐的方式存放了. 就是0x1D000. 那么我们加了0x1000的数据就是 0x1E000大小.我们修改为0x1E000
保存文件
5.保存文件内存中查看是否映射.
首先运行一下:
可以成功运行.
去内存中查看.节表是否映射. 我们节在内存中展开的偏移是 0x1D000 加上我们的ImageBase 就是 0x41D000位置.
跳转过去之后发现就是我们刚才填写FFFF的数据.已经成功映射了.至此我们就为这个PE文件新增了一个节.
三丶总结
根据上面实战添加节.进行一个总结.
1.一个节表0x28个字节.在最后一个节表位置添加.如果SizeofHeaders 有足够空间的情况下.
2.修改文件头中节表个数. 文件.SectionNumber = 原有节个数 + 你新增节的个数. 例如: 原为7.你增加了一个节.就为8
3.修改节属性:
节.VirtuallAddress 内存中展开的位置.按照内存对齐. 可以参照上一个节.virtuallAddress位置.我们进行修改.
节.SizeofRawData 节数据按照文件对齐后的大小. 节.SizeofRawData = 你添加的节数据大小. 按照文件对齐存放. 例如添加了0x1000.那么大小就是0x1000
节.PointerToRawData 文件中的偏移. 节.PointerToRawData = ()上一个节.PointerToRawData + 上一个节.SizeofRawData. )
4.修改扩展头SizeofImage PE镜像大小. 扩展头.SizeofImage = 内存对齐(原SizeofImage值 + 你行增节数据大小 按照内存对齐)
以上是关于新增节代码的主要内容,如果未能解决你的问题,请参考以下文章