返回列表 发帖

RELOC的深入利用

RELOC的深入利用
大家知道RELOC是改壳的利器,使用方法是输入入口点、文件偏移、区段零区域位置、零区域偏移及一个偏移量作为参数。图片教程里说明前四个参数都是使用PEID找到,但所谓“偏移量”却写得相当笼统,只给出了UPX壳的“偏移量”为6
今天,我们就来揭开RELOC的运行机理及“偏移量”的确定方法
使用的例子为UPXSHELL,本身已经加了UPX,我电脑上的UPX全加不了,就用这个吧
入口点A1210 入口点RVA 37610 零区域位置A13C7 文件偏移377C7
004A1210 >  60              pushad
004A1211    BE 00A04600    mov esi,UPXShell.0046A000
004A1216    8DBE 0070F9FF  lea edi,dword ptr ds:[esi+FFF97000]  ——跳回的地方
004A121C    C787 0CF70700 4>mov dword ptr ds:[edi+7F70C],F427AB44
004A1226    57              push edi
004A1227    83CD FF        or ebp,FFFFFFFF
004A122A    EB 0E          jmp short UPXShell.004A123A
004A122C    90              nop
004A122D    90              nop
004A122E    90              nop
004A122F    90              nop
004A1230    8A06            mov al,byte ptr ds:[esi]
004A1232    46              inc esi
004A1233    8807            mov byte ptr ds:[edi],al
004A1235    47              inc edi
004A1236    01DB            add ebx,ebx
004A1238    75 07          jnz short UPXShell.004A1241
004A123A    8B1E            mov ebx,dword ptr ds:[esi]
004A123C    83EE FC        sub esi,-4

004A123F    11DB            adc ebx,ebx
004A1241  ^ 72 ED          jb short UPXShell.004A1230
这是本身入口处的汇编代码
使用RELOC后的如下
004A1210 > /E9 B2010000    jmp RELOC过d.004A13C7
004A1215  |90              nop
004A1216  |8DBE 0070F9FF  lea edi,dword ptr ds:[esi+FFF97000]
004A121C  |C787 0CF70700 4>mov dword ptr ds:[edi+7F70C],F427AB44
004A1226  |57              push edi
004A1227  |83CD FF        or ebp,FFFFFFFF
这里会跳到
004A13C7    60              pushad
004A13C8    BE 00A04600    mov esi,RELOC过d.0046A000
004A13CD  ^ E9 44FEFFFF    jmp RELOC过d.004A1216
再跳到
004A1216    8DBE 0070F9FF  lea edi,dword ptr ds:[esi+FFF97000]  ——跳回的地方
004A121C    C787 0CF70700 4>mov dword ptr ds:[edi+7F70C],F427AB44
004A1226    57              push edi
004A1227    83CD FF        or ebp,FFFFFFFF
004A122A    EB 0E          jmp short RELOC过d.004A123A
004A122C    90              nop
004A122D    90              nop
004A122E    90              nop
004A122F    90              nop
004A1230    8A06            mov al,byte ptr ds:[esi]
004A1232    46              inc esi
004A1233    8807            mov byte ptr ds:[edi],al
004A1235    47              inc edi
004A1236    01DB            add ebx,ebx
004A1238    75 07          jnz short RELOC过d.004A1241
004A123A    8B1E            mov ebx,dword ptr ds:[esi]
004A123C    83EE FC        sub esi,-4
004A123F    11DB            adc ebx,ebx
004A1241  ^ 72 ED          jb short RELOC过d.004A1230
可以得出RELOC改写了原入口点的代码,一个跳转跳到零区域(400000+A13C7=4A13C7)
再在零区域中执行了一部分指令后跳回入口点附近,执行余下应该执行的语句
大家仔细看,在零区域执行了是
004A13C7    60              pushad
004A13C8    BE 00A04600    mov esi,RELOC过d.0046A000
两句指令,一共是1+5=6字节!!
$ ==>    >  60              pushad
$+1      >  BE 00A04600    mov esi,RELOC过d.0046A000
$+6 前两句指令大小之和    >^ E9 44FEFFFF    jmp RELOC过d.004A1216
然后跳回的区域和RELOC处理之前的地址是完全相同的
现在可以判断出RELOC的工作机理为:修改入口处为绝对跳转,跳到你原来设定的零区域,然后把从入口点向下数你所填写的“偏移量”的大小的 数据 移到零区域执行,再跳回剩下的指令
为什么的得出的是移动一定长度“数据”的结论,因为它没有对语句的完整性作检测。比如换了一款壳,还是使用偏移量6进行处理,那么原来的一句语句很可能会被拆成两句,那执行自然会出错,免杀失败了。
接下来来实际操作,先把UPX的壳脱掉(用工具或手脱都可),然后用ASPROTECT这款猛壳压缩一下(大家免杀中使用得比较多,所以以它为例)压缩好了,OD载入,开头几句指令为
00401000 >  68 01604A00    push unpacked.004A6001
00401005    E8 01000000    call unpacked.0040100B
0040100A    C3              retn
0040100B    C3              retn
0040100C    9A 7FCE2B84 A45>call far 58A4:842BCE7F
语句长度为
$ ==>    >  68 01604A00    push unpacked.004A6001
$+5      >  E8 01000000    call unpacked.0040100B
$+A      >  C3              retn
$+B      >  C3              retn
$+C      >  9A 7FCE2B84 A45>call far 58A4:842BCE7F
可以看到
push unpacked.004A6001
call unpacked.0040100B
这两句后是两个连续得RET,不宜改动,可以只移动push unpacked.004A6001一句或两句都移
push unpacked.004A6001一句为5字节
加壳后的程序入口点1000 入口点RVA 1000 零区域位置A33F8 文件偏移3B7F8 偏移量使用5
处理结束后执行,是成功运行的,再OD载入看看
00401000 >- E9 F3230A00    jmp server.004A33F8
00401005    E8 01000000    call server.0040100B
0040100A    C3              retn
0040100B    C3              retn
第一句是跳转了吧?
好,再试试偏移量A,转换为十进制是10
发现出错了,那就还是使用上一种吧,现在可以得出ASPROTECT壳的偏移量使用5
本人得出的心得是偏移量一般在3-9个字节为宜,不然出错的几率很大
大家确定偏移量只要注意不要把汇编指令误拆分开来,一般都能成功的

返回列表