程序读取自身文件

对于一个正在运行的程序,正常情况下是对于其可执行文件本身是具有读权限的(写权限的没有)。换句话说,如果我想要让程序在运行时读取自身文件中的一些内容应该是可行的idea。使用fopen或者CreateFile等函数当然是可以做到这一点的,另外也可以访问当前内存空间,根据文件到进程的映射关系找到那些你希望从可执行文件中搜索的内容。

不过现在就简单的使用fopen来处理这个问题。对编译好的可执行文件后期处理,在末尾附加的一些字符用于控制程序的执行流程。比如在一个固定的EXE文件后面分别附加Yes和No,生成yes.exe和no.exe,两个程序会因此而有不同的行为表现。当然这种行为的控制要在编译源程序时就已经预定良好。程序本身的运行流程包括在运行时对自身文件末尾的附加数据的提取,并以此产生分支达到流程变异。比如使用前缀碰撞法产生相同MD5的两个EXE,主程序相同,仅末尾附加的256个字符不同。

这当中需要注意的一点是,如果使用VC调试这样的程序,会出现一些问题,比如通过

GetCurrentDirectory(MAX_PATH,currentpath);
strcat(currentpath,'\');
strcat(currentpath,AfxGetApp()->m_pszExeName);
strcat(currentpath,".exe");

会在currentpath中获得当前程序的路径,直接运行不存在问题,但如果使用VC调试的话,currentpath当中获得的并不是真实的可执行程序的路径,而是在当前工程下虚拟出来的一个可执行文件路径便于调试。这也就是为什么VC程序调试时可以把工程文件夹作为相对路径(当前路径)。其实这里currentpath完全可以只用上述代码的后两行来获取,不用获取当前文件夹。

另外根据当前状态释放不同EXE,并选择性执行时,可以采用简单的奇偶比对。这样对于生成的两个EXE,调整最后的几个字节就可以很容易产生不同奇偶性的校验码。

如果是采用MFC来完成这一任务的话,可能需要隐藏窗口和任务栏。下面的两行代码就能很好的解决这个问题。

SetWindowPos(&wndTop,0,0,0,0,NULL);
ModifyStyleEx(WS_EX_APPWINDOW,WS_EX_TOOLWINDOW);

最后要说的一点是关于CreateProcess的,如果想要启动诸如txt或者doc等非可执行文件的话,需要将启动程序改写为notepad或者winword。同时调整commandline参数,比如txt的话需要该参数类似 WORDPAD c:\1.txt。

总结一下:

  • 创建MFC工程,导入两个EXE到资源。
  • 程序流程中包括隐藏窗口和任务栏图标。
  • 流程分支是依据当前可执行程序末尾附加的字符的校验值来判定的,每个分支会去释放一个EXE并且执行。
  • 对于编译好的可执行文件,进行MD5前缀碰撞,产生两个EXE,由于文件尾附加的字符的不同所以可以产生不同的执行流程。看起来好像两个不同的EXE同样的MD5,不同的功能。