原文:http://www.pediy.com/kssd/index.html -- 病毒技术 -- 病毒知识 -- Anti Virus专题
下面的代码都是内联汇编,较比较汇编会有些限制,可能写法上有时候会不一样。黑色是代码,红色是编译的汇编代码
int g_nTest;
__asm
{
call Dels
00401004 call 013C13A3 ; call指令会将下一句指令的地址入栈
Dels:
pop ebx
00401009 pop ebx ; 将栈中保存的地址弹到ebx中
lea eax, g_nTest
0040100A lea eax,ds:[00401000h] ; 获得全局变量的地址
sub eax, Dels
00401010 sub eax,00401009h ; 获得全局变量和Dels的差值
lea edx, [ebx + eax]
00401006 lea edx,[ebx+eax] ; 用ebx即Dels的地址加上差值就得到了全局变量的地址
}
假如g_nTest的地址为00401000h,将上面的重定位代码感染到被感染的程序空间中的地址为00801004h的地方,g_nTest对应的地址就应为00801000h,就会是下面这种情况:
call指令执行后,将地址00801009h压入堆栈(应为call指令占用5个字节),然后pop给ebx,然后求得全局变量和Dels的差值,即00401000h - 00401009h,然后加到ebx(00801009h)上即可得到全局变量在被感染程序中的位置(00801000h)。其实意思也就说,在病毒本体的时候,全局变量和call指令的下一句指令的差和在被感染程序中是一样的,它是不变的,在被感染程序中获得call的下一句指令的地址,然后加上差值,即可找到全局变量
以下摘自原文,里面加了点自己的注释,括号里的
"比如我们的szText变量(也就是全局变量)相对于病毒起始位置的偏移是9h(这里的起始位置可以理解为一个点,同全局变量与call下一句指令的地址的差值,也即偏移是一样的), 那么只要通过求得病毒插入到被感染对象后的病毒起始位置 + 这个变量相对病毒起始位置的偏移 = 变量在被感染对象中的位置。"
还有一种方法是罗云彬的《Windows环境下32位汇编程序语言设计》第13章远程线程中说到的,代码如下:
int g_nTest;
__asm
{
call Dels
00401004 call 00401009 ; 保存下句指令地址到堆栈
Dels:
pop ebx
00401009 pop ebx; 弹到ebx
sub ebx, Dels
0040100A sub ebx,00401009h; 减去Dels获得差值
lea edx, [ebx + g_nTest]
00401010 lea edx,[ebx+00401000h]; 差值加上全局变量
}
这个重定位方法是这样的:如果g_nTest的地址为00401000h,这个代码没有插入到别的程序中,将指令保存到堆栈弹到ebx后,ebx减去Dels为0,然后加上全局变量就等于lea edx, [g_nTest]
如果插入到别的程序地址为00801004h的位置,g_nTest地址变为00801000h,那么pop到ebx 的值即为00801009h,减去Dels为00801009h - 00401009h = 00400000h,然后加上全局变量就变成了lea edx, [00400000h + 00401000h],这样就获得了全局变量的地址