作 者: sdzbyy
时 间: 2007-05-23,00:49

学习CRC32的一个习作,老实说,对CRC的原理还是不太明白,我是菜鸟,请大家不吝赐教。


原理:

     关于CRC32知识,这里有很好的解释http://www.pediy.com/tutorial/chap6/Chap6-2-4.htm


步骤:

     pe文件通过比较自己的CRC32效验值,来判断自己是否被改写。
     (1)为原pe文件添加一个新的节,将自效验部分(Loader)写入该新节。
     (2)将原pe文件的ep改为新节的开始。
     (3)计算原pe文件部分(在程序里计算的是从pe文件的开头到+0xe5)的CRC32效验值,并将该效验值保存在Loader中。
     (4)修改后的pe文件开始运行时,先计算相应部分的(在程序里计算的是从pe文件的开头到+0xe5 )CRC32效验值。与原pe文件的CRC32效验值比较,若相等则跳转到原pe的ep,否则直接调用ExitProcess退出。


测试:

     (1)打开程序CRC32为记事本添加自效验。
     (3)修改从记事本开头到0xe5范围内的任意一个字节(不要修改关键数据,如“MZ“),再运行,记事本直接ExitProcess,退出。

 为PE文件添加CRC32自效验_byte

 

说明:
     (1)源码在vc7+xp_xp2下编译通过。
     (2)卡巴斯基会将已添加自效验的记事本误报为病毒。
     (3)因为图简单所以将自效验的范围定为"MZ"到0XE5。(添加了新的节以后,记事本的头部会改变,但0xe6之前的不会变)
     (4)在调用ExitProcess时使用了硬编码:mov eax,07c81caa2h(Kernel32.ExitProcess),call eax

 

源码:

// AddCRC32.h: interface for the CAddCRC32 class. // // #include "PE.h" #if !defined(AFX_ADDCRC32_H__187EB449_8B77_4294_946C_51C947245FA9__INCLUDED_) #define AFX_ADDCRC32_H__187EB449_8B77_4294_946C_51C947245FA9__INCLUDED_ #if _MSC_VER > 1000 #pragma once #pragma comment(lib,"CRC32Dll.lib") extern "C" _declspec (dllimport) _stdcall void init_crc32table(void); extern "C" _declspec (dllimport) _stdcall void arraycrc32(void); #endif // _MSC_VER > 1000 class CAddCRC32 : public CPE { public: DWORD cNewOEP; public: CAddCRC32(); virtual ~CAddCRC32(); InitCRC32(); ArrayCRC32(); AddSection(DWORD AddrToAdd); void InjectLoader(); }; #endif // !defined(AFX_ADDCRC32_H__187EB449_8B77_4294_946C_51C947245FA9__INCLUDED_)

 

// AddCRC32.cpp: implementation of the CAddCRC32 class. // // #include "stdafx.h" #include "crc_protector.h" #include "AddCRC32.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif //===================================== //用于Loader的全局变量(传递给内联汇编代码) DWORD NewOEP; //新的入口点 DWORD OldOEP; //旧的入口点 DWORD CRC32; //计算得到的CRC效验值 DWORD OriginalCRC32; //原始CRC效验值 DWORD dwFileSize; //文件的大小 DWORD InjectAddr; //注入Loader的位置 DWORD CRC32Table[256]= { 0x00000000,0x77073096,0xEE0E612C,0x990951BA, 0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3, 0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988, 0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91, 0x1DB71064 ,0x6AB020F2 ,0xF3B97148,0x84BE41DE, 0x1ADAD47D ,0x6DDDE4EB ,0xF4D4B551 ,0x83D385C7, 0x136C9856 ,0x646BA8C0 ,0xFD62F97A ,0x8A65C9EC, 0x14015C4F ,0x63066CD9 ,0xFA0F3D63 ,0x8D080DF5, 0x3B6E20C8 ,0x4C69105E ,0xD56041E4 ,0xA2677172, 0x3C03E4D1 ,0x4B04D447 ,0xD20D85FD ,0xA50AB56B, 0x35B5A8FA ,0x42B2986C ,0xDBBBC9D6 ,0xACBCF940, 0x32D86CE3 ,0x45DF5C75 ,0xDCD60DCF ,0xABD13D59, 0x26D930AC ,0x51DE003A ,0xC8D75180 ,0xBFD06116, 0x21B4F4B5 ,0x56B3C423 ,0xCFBA9599 ,0xB8BDA50F, 0x2802B89E ,0x5F058808 ,0xC60CD9B2 ,0xB10BE924, 0x2F6F7C87 ,0x58684C11 ,0xC1611DAB ,0xB6662D3D, 0x76DC4190 ,0x01DB7106 ,0x98D220BC ,0xEFD5102A, 0x71B18589 ,0x06B6B51F ,0x9FBFE4A5 ,0xE8B8D433, 0x7807C9A2 ,0x0F00F934 ,0x9609A88E ,0xE10E9818, 0x7F6A0DBB ,0x086D3D2D ,0x91646C97 ,0xE6635C01, 0x6B6B51F4 ,0x1C6C6162 ,0x856530D8 ,0xF262004E, 0x6C0695ED ,0x1B01A57B ,0x8208F4C1 ,0xF50FC457, 0x65B0D9C6 ,0x12B7E950 ,0x8BBEB8EA ,0xFCB9887C, 0x62DD1DDF ,0x15DA2D49 ,0x8CD37CF3 ,0xFBD44C65, 0x4DB26158 ,0x3AB551CE ,0xA3BC0074 ,0xD4BB30E2, 0x4ADFA541 ,0x3DD895D7 ,0xA4D1C46D ,0xD3D6F4FB, 0x4369E96A ,0x346ED9FC ,0xAD678846 ,0xDA60B8D0, 0x44042D73 ,0x33031DE5 ,0xAA0A4C5F ,0xDD0D7CC9, 0x5005713C ,0x270241AA ,0xBE0B1010 ,0xC90C2086, 0x5768B525 ,0x206F85B3 ,0xB966D409 ,0xCE61E49F, 0x5EDEF90E ,0x29D9C998 ,0xB0D09822 ,0xC7D7A8B4, 0x59B33D17 ,0x2EB40D81 ,0xB7BD5C3B ,0xC0BA6CAD, 0xEDB88320 ,0x9ABFB3B6 ,0x03B6E20C ,0x74B1D29A, 0xEAD54739 ,0x9DD277AF ,0x04DB2615 ,0x73DC1683, 0xE3630B12 ,0x94643B84 ,0x0D6D6A3E ,0x7A6A5AA8, 0xE40ECF0B ,0x9309FF9D ,0x0A00AE27 ,0x7D079EB1, 0xF00F9344 ,0x8708A3D2 ,0x1E01F268 ,0x6906C2FE, 0xF762575D ,0x806567CB ,0x196C3671 ,0x6E6B06E7, 0xFED41B76 ,0x89D32BE0 ,0x10DA7A5A ,0x67DD4ACC, 0xF9B9DF6F ,0x8EBEEFF9 ,0x17B7BE43 ,0x60B08ED5, 0xD6D6A3E8 ,0xA1D1937E ,0x38D8C2C4 ,0x4FDFF252, 0xD1BB67F1 ,0xA6BC5767 ,0x3FB506DD ,0x48B2364B, 0xD80D2BDA ,0xAF0A1B4C ,0x36034AF6 ,0x41047A60, 0xDF60EFC3 ,0xA867DF55 ,0x316E8EEF ,0x4669BE79, 0xCB61B38C ,0xBC66831A ,0x256FD2A0 ,0x5268E236, 0xCC0C7795 ,0xBB0B4703 ,0x220216B9 ,0x5505262F, 0xC5BA3BBE ,0xB2BD0B28 ,0x2BB45A92 ,0x5CB36A04, 0xC2D7FFA7 ,0xB5D0CF31 ,0x2CD99E8B ,0x5BDEAE1D, 0x9B64C2B0 ,0xEC63F226 ,0x756AA39C ,0x026D930A, 0x9C0906A9 ,0xEB0E363F ,0x72076785 ,0x05005713, 0x95BF4A82 ,0xE2B87A14 ,0x7BB12BAE ,0x0CB61B38, 0x92D28E9B ,0xE5D5BE0D ,0x7CDCEFB7 ,0x0BDBDF21, 0x86D3D2D4 ,0xF1D4E242 ,0x68DDB3F8 ,0x1FDA836E, 0x81BE16CD ,0xF6B9265B ,0x6FB077E1 ,0x18B74777, 0x88085AE6 ,0xFF0F6A70 ,0x66063BCA ,0x11010B5C, 0x8F659EFF ,0xF862AE69 ,0x616BFFD3 ,0x166CCF45, 0xA00AE278 ,0xD70DD2EE ,0x4E048354 ,0x3903B3C2, 0xA7672661 ,0xD06016F7 ,0x4969474D ,0x3E6E77DB, 0xAED16A4A ,0xD9D65ADC ,0x40DF0B66 ,0x37D83BF0, 0xA9BCAE53 ,0xDEBB9EC5 ,0x47B2CF7F ,0x30B5FFE9, 0xBDBDF21C ,0xCABAC28A ,0x53B39330 ,0x24B4A3A6, 0xBAD03605 ,0xCDD70693 ,0x54DE5729 ,0x23D967BF, 0xB3667A2E ,0xC4614AB8 ,0x5D681B02 ,0x2A6F2B94, 0xB40BBE37 ,0xC30C8EA1 ,0x5A05DF1B ,0x2D02EF8D }; //===================================== //全局函数 //===================================== DWORD GetFunctionRVA(void* FuncName)//计算函数的RVA { DWORD dwRVA=DWORD(FuncName); return(dwRVA); } int NumOfNOP(PBYTE addrOfNOP)//计算NOP的个数 { BYTE OpNopCode=0x90; int NumOfNOP=0; PBYTE Pointer=addrOfNOP; do { NumOfNOP++; Pointer++; } while(*Pointer==OpNopCode); return NumOfNOP; } DWORD GetFunctionSize(void* FuncName)//计算函数的大小 { DWORD dwRVA=GetFunctionRVA(FuncName); PBYTE pFuncBody=(PBYTE)dwRVA; BYTE _temp; bool notEnd=TRUE; DWORD l=0; do { CopyMemory(&_temp,pFuncBody+l,1); if(_temp==0xC3)//0xC3为retn指令 { notEnd=FALSE; } l++; }while(notEnd); return(l); } //全局函数 //===================================== void Loader()// { //放入被PE文件的.crc32节中,效验crc32值 // PBYTE RAVOfDest=RVAOfEndSectionTable+pImageBase; _asm { //拷贝开始标志nop数目为3 nop nop nop jmp endofcrc32table crc32tbl: nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop //给crc32table预留的256个DWORD空间 endofcrc32table: nop nop xor eax,eax // nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop //18个nop //mov ebx,开头的位置 //mov ecx,总的字节数 //mov edi,originalcrc32 mov eax,-1 or ecx,ecx jz $Done or ebx,ebx jz $Done next: mov dl,[ebx] xor dl,al movzx edx,dl shr eax,8 //use esi nop nop nop nop nop nop //4个nop,标记此处插入mov esi,crc32table地址 xor eax,[esi+edx*4] //use esi inc ebx dec ecx jne next not eax cmp eax,edi jz $Done// mov eax,07c81caa2h//exitprocess call eax //push //call $Done://计算crc32的部分 nop nop nop nop nop//5个nop,nop的数量来标示injection结束 } } //===================================== //全局函数 // // Construction/Destruction // CAddCRC32::CAddCRC32() { } CAddCRC32::~CAddCRC32() { } CAddCRC32::InitCRC32() { init_crc32table(); } CAddCRC32::ArrayCRC32() { DWORD tmp1=0xe5;//baseofdata-baseofcode DWORD tmp2=(DWORD)(pImageBase);// __asm { mov ebx,tmp2 mov ecx,tmp1 } OriginalCRC32=arraycrc32();//计算crc32值 } CAddCRC32::AddSection(DWORD AddrToAdd) { //pSection指向新添加的节表 PIMAGE_SECTION_HEADER pSection=(PIMAGE_SECTION_HEADER)AddrToAdd; // //添加节表名 BYTE Name[8]=".crc32"; PBYTE ptmp; ptmp=pSection->Name; for(int i=0;i<8;i++) { *(ptmp)=Name[i]; ptmp++; } // //将VirtualSize(内存块大小)的大小设置为LenOfNewSection DWORD LenOfNewSection=0x789; pSection->Misc.VirtualSize=LenOfNewSection; // //计算相关的数据: //(1)新节的virtual offset //(2)新节的对齐文件大小 //(1) DWORD SectionAlignment,FileAlignment; SectionAlignment=pImageOptionalHeader->SectionAlignment; FileAlignment=pImageOptionalHeader->FileAlignment; PIMAGE_SECTION_HEADER ForwardSection=(PIMAGE_SECTION_HEADER)(AddrToAdd-0x28); DWORD ForwardVA,ForwardVS; ForwardVA=ForwardSection->VirtualAddress; ForwardVS=ForwardSection->Misc.VirtualSize; UINT residue,quotient,tmp1,sec_NewVA; residue=(UINT)ForwardVS%SectionAlignment; quotient=(UINT)ForwardVS/SectionAlignment; if(residue!=0x0)quotient++; tmp1=(UINT)quotient*SectionAlignment; sec_NewVA=tmp1+ForwardVA; //(1) //(2) UINT tmp2,tmp3,tmp4,sec_NewSR; tmp2=(UINT)LenOfNewSection%FileAlignment; tmp3=(UINT)LenOfNewSection/FileAlignment; if(tmp2!=0x0)tmp3++; tmp4=(UINT)tmp3*FileAlignment; sec_NewSR=tmp4; //(2) //内存中块的rva值 pSection->VirtualAddress=sec_NewVA; NewOEP=sec_NewVA+pImageOptionalHeader->ImageBase;; cNewOEP=sec_NewVA; // //文件中的块大小 pSection->SizeOfRawData=sec_NewSR; // //文件中的块偏移 pSection->PointerToRawData=ForwardSection->PointerToRawData+ForwardSection->SizeOfRawData; InjectAddr=pSection->PointerToRawData;//文件偏移量 // //obj文件使用 pSection->NumberOfLinenumbers=0x0; pSection->NumberOfRelocations=0x0; pSection->PointerToLinenumbers=0x0; pSection->PointerToRelocations=0x0; // //修改该节的属性(可读写) pSection->Characteristics=0x0C00000E0; // // //修改节的数目 UINT NewNum=NumberOfSection+1; CopyMemory(&pImageFileHeader->NumberOfSections,&NewNum,2); // //更新imagesize UINT tmp3_1,tmp3_2,tmp3_3,tmp3_4; tmp3_1=LenOfNewSection+pImageOptionalHeader->SizeOfImage; tmp3_2=tmp3_1/SectionAlignment; tmp3_3=tmp3_1%SectionAlignment; if(tmp3_3!=0)tmp3_2++; tmp3_4=(UINT)tmp3_2*SectionAlignment; pImageOptionalHeader->SizeOfImage=tmp3_4; //将bound import设置成零 pImageOptionalHeader->DataDirectory[11].VirtualAddress=0x0; pImageOptionalHeader->DataDirectory[11].Size=0x0; //修改文件的大小 ::SetFilePointer(hFile,pSection->PointerToRawData+pSection->SizeOfRawData,0,FILE_BEGIN); ::SetEndOfFile(hFile); } void CAddCRC32::InjectLoader()//InjectAddr注入的位置 { //保存老的ep OldOEP=pImageOptionalHeader->AddressOfEntryPoint+pImageOptionalHeader->ImageBase; // BYTE OpNOPCode=0x90; DWORD Pointer=InjectAddr; PBYTE ptmp=(PBYTE)Pointer;//指向待Inject的位置 DWORD FuncRVA=GetFunctionSize(Loader);//Loader的大小 DWORD dwRVA=GetFunctionRVA(Loader);//Loader的RVA PBYTE pFuncBody=(PBYTE)dwRVA; while(1) { if(NumOfNOP(pFuncBody)==3) { pFuncBody=pFuncBody+3; break; } else { pFuncBody++; } } //定位到1024个nop上 //将loader的Opcode写入PE文件的.crc32节中 for(;ptmp<(PBYTE)(Pointer+FuncRVA);) { if(*pFuncBody==OpNOPCode && NumOfNOP(pFuncBody)>256)//若为NOP,则开始Inject { PDWORD CRC=CRC32Table; for(int i=0;i<256;i++)//将crc32table写入.crc节 { DWORD num=4; ::SetFilePointer(hFile,(LONG)ptmp,0,FILE_BEGIN); ::WriteFile(hFile,CRC,num,&num,NULL); ptmp=ptmp+4; CRC++; } pFuncBody=pFuncBody+1024; } if(*pFuncBody==OpNOPCode && NumOfNOP(pFuncBody)==18 ) { // BYTE OpMovEbx=0xBB; DWORD tmp=(DWORD)(pImageOptionalHeader->ImageBase);//效验计算开始位置:imagebase BYTE MovEbx[5]; CopyMemory(MovEbx,&OpMovEbx,1); CopyMemory(&MovEbx[1],&tmp,4);//mov eax,ep DWORD num=5; ::SetFilePointer(hFile,(LONG)ptmp,0,FILE_BEGIN); ::WriteFile(hFile,MovEbx,num,&num,NULL); ptmp=ptmp+5; pFuncBody=pFuncBody+5; // BYTE OpMovEcx=0xB9; tmp=0xe5;//效验计算的结束位置:新的入口点的前一个字节 BYTE MovEcx[5]; CopyMemory(MovEcx,&OpMovEcx,1); CopyMemory(&MovEcx[1],&tmp,4);//mov eax,ep num=5; ::SetFilePointer(hFile,(LONG)ptmp,0,FILE_BEGIN); ::WriteFile(hFile,MovEcx,num,&num,NULL); ptmp=ptmp+5; pFuncBody=pFuncBody+5; // BYTE OpMovEdi=0xBF; tmp=OriginalCRC32;//效验计算的结束位置:新的入口点的前一个字节 BYTE MovEdi[5]; CopyMemory(MovEdi,&OpMovEdi,1); CopyMemory(&MovEdi[1],&tmp,4);//mov eax,ep num=5; ::SetFilePointer(hFile,(LONG)ptmp,0,FILE_BEGIN); ::WriteFile(hFile,MovEdi,num,&num,NULL); ptmp=ptmp+5; pFuncBody=pFuncBody+5; } if(*pFuncBody==OpNOPCode && NumOfNOP(pFuncBody)==6 ) { BYTE OpMovEsi=0xBE; DWORD tmp=NewOEP+5;//jmp xxxx BYTE MovEsi[5]; CopyMemory(MovEsi,&OpMovEsi,1); CopyMemory(&MovEsi[1],&tmp,4);//mov eax,ep DWORD num=5; ::SetFilePointer(hFile,(LONG)ptmp,0,FILE_BEGIN); ::WriteFile(hFile,MovEsi,num,&num,NULL); ptmp=ptmp+5; pFuncBody=pFuncBody+5; } if(*pFuncBody==OpNOPCode && NumOfNOP(pFuncBody)==5 ) { BYTE OpMovEax=0xB8; BYTE OEP_Jmp[7]; CopyMemory(OEP_Jmp,&OpMovEax,1); CopyMemory(&OEP_Jmp[1],&OldOEP,4);//mov eax,ep OEP_Jmp[5]=0xFF; OEP_Jmp[6]=0xE0;//jmp eax DWORD num=7; ::SetFilePointer(hFile,(LONG)ptmp,0,FILE_BEGIN); ::WriteFile(hFile,OEP_Jmp,num,&num,NULL); goto exit; } //处理不是nop的部分,直接拷贝 DWORD num=1; ::SetFilePointer(hFile,(LONG)ptmp,0,FILE_BEGIN); ::WriteFile(hFile,pFuncBody,num,&num,NULL); pFuncBody++; ptmp++; } //修改程序的oe exit: pImageOptionalHeader->AddressOfEntryPoint=cNewOEP; }