我们如何编写一段可以在程序内存中不停移动的代码呢?就是让shellcode代码在内存中复制自己,一直执行下去,也就是内存蠕虫。我们需要将shellcode代码偏移出蠕虫的长度,复制到蠕虫后面的内存中,然后执行。在实现过程中,我们也将之前相同长度的代码改成\x90,也就是bug走的路,最后吃掉了所有的内存。为此,我们需要知道shellcode的长度,并计算shellcode每次移动了多少。我们的shllcode以调用printf函数为例。1.编写printf程序#include"stdio.h"intmain(){printf("begin\n");char*str="a=%d\n";__asm{moveax,5pusheaxpushstrmoveax,0x00401070callleaxaddesp,8ret}return0;}0×00401070是我机器上printf的地址,把自己机器上的printf地址改一下,在最后加一个ret,因为执行完shellcode后,会回到复制的shellcode的代码执行。上述编译转换成shellcode形式,shellcode为:charshellcode[]="\xB8\x05\x00\x00\x00\x50\xFF\x75\xFC\xB8\x70\x10\x40\x00\xFF\xD0\x83\x**\x08\xc3";2.编写蠕虫代码insect:movbl,byteptrds:[eax+edx]movbyteptrds:[eax+edx+20],blmovbyteptrds:[eax+edx],0x90incedxcmpedx,20jeeejmpinsectee:addeax,20pusheaxcalleaxpopeaxxoredx,edxjmpinsectshellcode的长度为20,假设数据的地址是s,我们把数据复制到地址s+20,原来的数据变成了0×90,说明数据之前已经在这里了,昆虫段就是用来复制数据的,复制了20次,正好完成复制shellcode。因为shellcode相当于向下移动了20位,所以我们需要将eax加20,将edx恢复为0,以便下次复制,然后执行我们的shellcode,然后跳转到昆虫部分继续执行.这就是ee段的作用。inscet和ee部分加起来就是将我们的shellcode复制到其他地方,然后执行shellcode,再复制,如此循环往复。3.最终程序#include"stdio.h"charshellcode[]="\xB8\x05\x00\x00\x00\x50\xFF\x75\xFC\xB8\x70\x10\x40\x00\xFF\xD0\x83\x**\x08\xc3";intmain(){printf("begin\n");char*str="a=%d\n";__asm{leeaax,shellcodepusheaxcalleaxpopeaxxoredx,edxinsect:movbl,byteptrds:[eax+edx]movbyteptrds:[eax+edx+20],blmovbyteptrds:[eax+edx],0x90incedxcmpedx,20jeeejmpinsectee:addeax,20pusheaxcalleaxpopeaxxoredx,edxjmpinsect}return0;}调试时,找到shellcode所在位置,一步步调试可以看到复制shellcode,将原来的转换为0×90,仍然执行printf。复制前:复制后:4.综上所述,首先要计算shellcode的长度,计算每次shellcode的位置,然后写复制程序,并且还有一个转移到首地址的程序复制的shellcode,执行复制的shellcode,然后再次复制执行,循环继续。当然,在一段内存中循环执行也是可以的,只要找到位置跳转到即可。
