直接贴代码 汇编代码(Masm32) .386 .model flat,stdcall option casemap:none assume fs:nothing ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> .code ORG 0h TestProc proc mov eax,0 ;返回0(false) ret TestProc endp start: end start c++ 代码 #include <stdio.h> #include <iostream> #include <windows.h> using namespace std; // 函数定义预留位置 // 汇编中 0x90 NOP 为空操作 #define __0x4B __asm _emit 0x90 / __asm _emit 0x90 / __asm _emit 0x90 / __asm _emit 0x90 #define __0x10B __0x4B __0x4B __0x4B __0x4B #define __0x40B __0x10B __0x10B __0x10B __0x10B #define __0x100B __0x40B __0x40B __0x40B __0x40B #define __0x400B __0x100B __0x100B __0x100B __0x100B #define __0x1000B __0x400B __0x400B __0x400B __0x400B bool printb() { // 预留 0x1000字节的空间 __0x1000B // 原函数返回是true return true; } int _tmain(int argc, _TCHAR* argv[]) { //调用原函数 cerr<<printb()<<endl; /** 读取编译好的文件。 如果开发网络程序,则由服务端传送给客户端 abc.exe 为编译好的汇编最终可执行代码 **/ FILE* fd = fopen("abc.exe","rb"); unsigned char buf[0x1000]; //暂定大小 0x1000 4k size_t len; fread(buf,1,0x200,fd); // PE文件的头大小为 0x200 len = fread(buf,1,0x1000,fd); // 读入代码段 fclose(fd); // 获取嵌入函数指针 unsigned char* cpb = (unsigned char*)printb; unsigned long offset = 0; // windows 的函数指针通常指向一跳转指令,该跳转指令跳转到真正的函数代码段。 // 跳转指令为 0xE9 后跟跳转相对地址 while ( cpb[0] == (unsigned char)0xe9 ) { memcpy(&offset,cpb+1,4); // 相对地址是相对跳转指令之后。跳转指令长度为5( 0xe9 + 32位数,只适用32位系统) cpb += offset+5 ; } DWORD dwOldFlag; // 将代码段置为可写,len为写入长度 if ( ! VirtualProtect(cpb,len,PAGE_EXECUTE_READWRITE,&dwOldFlag) ) { cerr<<"error"<<endl; return 1; } //直接将代码段覆盖。注意,代码段的入口地址必须对其。本例的入口地址在0x200处。 memcpy(cpb,buf,len); //调用新函数 cerr<<printb()<<endl; return 0; } 预期输出: 1 0