我们怎么写一段代码, 能够在程序内存里面不停移动? 就是让 shellcode 代码能在内存中不停的复制自己, 并且一直执行下去, 也就是内存蠕虫. 我们要把 shellcode 代码偏移出蠕虫长度再复制到蠕虫后面的内存中, 然后执行. 我们在实现过程中同时把前面同长度代码变成 \ x90, 那个就是虫子走过的路, 最终吃掉所有的内存. 实现这个我们要知道 shellcode 长度, 并且计算好 shellcode 每次移动的位置是多少. 我们的 shllcode 以调用 printf 函数为例.
0*01 写出 printf 程序
- #include "stdio.h"
- int main()
- {
- printf("begin\n");
- char *str="a=%d\n";
- __asm{
- mov eax,5
- push eax
- push str
- mov eax,0x00401070
- call eax
- add esp,8
- ret
- }
- return 0;
- }
0*00401070 是我机子上 printf 的地址, 将自己机子上的 printf 地址更换一下就行, 还要在最后加一个 ret, 因为执行完 shellcode 还要回到复制 shellcode 的代码执行.
上面汇编转成 shellcode 形式, shellcode 为:
char shellcode[]="\xB8\x05\x00\x00\x00\x50\xFF\x75\xFC\xB8\x70\x10\x40\x00\xFF\xD0\x83\x**\x08\xc3";
0*02 编写蠕虫代码
- insect:mov bl,byte ptr ds:[eax+edx]
- mov byte ptr ds:[eax+edx+20],bl
- mov byte ptr ds:[eax+edx],0x90
- inc edx
- cmp edx,20
- je ee
- jmp insect
- ee: add eax,20
- push eax
- call eax
- pop eax
- xor edx,edx
- jmp insect
shellcode 长度是 20, 假设数据的地址是 s, 我们把数据复制到地址为 s+20 处, 原来的数据变为 0*90, 表示数据曾经来过这里, insect 段是用来复制数据用到, 复制了 20 次, 刚刚好把 shellcode 复制完.
因为 shellcode 相当于向下移动 20 位, 所以我们要把 eax 加上 20, 还要把 edx 恢复成 0, 方便下次接着复制, 然后去执行我们的 shellcode, 接着跳转到 insect 段继续执行, 这是 ee 段干的事.
inscet 和 ee 段加起来是复制我们的 shellcode 到其他地方, 然后去执行 shellcode, 然后再复制, 循环下去.
0*03 最终程序
- #include "stdio.h"
- char shellcode[]="\xB8\x05\x00\x00\x00\x50\xFF\x75\xFC\xB8\x70\x10\x40\x00\xFF\xD0\x83\x**\x08\xc3";
- int main()
- {
- printf("begin\n");
- char *str="a=%d\n";
- __asm{
- lea eax,shellcode
- push eax
- call eax
- pop eax
- xor edx,edx
- insect:mov bl,byte ptr ds:[eax+edx]
- mov byte ptr ds:[eax+edx+20],bl
- mov byte ptr ds:[eax+edx],0x90
- inc edx
- cmp edx,20
- je ee
- jmp insect
- ee: add eax,20
- push eax
- call eax
- pop eax
- xor edx,edx
- jmp insect
- }
- return 0;
- }
调试的时候找到 shellcode 位置, 一步步调试能看见 shellcode 被复制, 原来的转成 0*90, 并且 printf 还被执行
没有复制前:
复制后:
来源: http://www.tuicool.com/articles/bq6Fziv