ShaBility 发表于 2010-8-6 22:59

简单分析 FuckProtect 1.0.0.7 CodeReplace

本帖最后由 ShaBility 于 2010-8-7 10:26 编辑

FuckProtect 1.0.0.7 试炼品下载: http://www.52pojie.cn/thread-51624-1-2.html

ximo牛研制的壳,很好很强大,脱壳过程不再说,因为之前已经有人发脱文了。
这次只简单分析一下CodeReplace(可以下载附件进行调试,已脱壳)

OD载入,随便点进一个CALL

004020B3    55            push    ebp
004020B4    E8 C7AC0000   call    0040CD80                  ; <-CodeReplace
004020B9    56            push    esi
004020BA    FF75 14         push    dword ptr ss:
004020BD    FF75 10         push    dword ptr ss:
004020C0    FF75 0C         push    dword ptr ss:
004020C3    FF75 08         push    dword ptr ss:
004020C6    E8 A70B0000   call    00402C72
004020CB    85C0            test    eax, eax
004020CD    75 09         jnz   short 004020D8
004020CF    C745 EC 0000000>mov   dword ptr ss:, 0
004020D6    EB 73         jmp   short 0040214B            ; <-CodeReplace
004020D8    E8 A3AC0000   call    0040CD80
004020DD    56            push    esi



点进看看

0040CD80    60            pushad
0040CD81    8B5424 20       mov   edx, dword ptr ss:
0040CD85    83EA 05         sub   edx, 5
0040CD88    52            push    edx                            ; 获取被代码替换的地址
0040CD89    E8 D2FFFFFF   call    0040CD60



进入到call 0040CD60

0040CD60    8B5424 04       mov   edx, dword ptr ss:      ; 被代码替换的地址
0040CD64    33C0            xor   eax, eax
0040CD66    81F2 10200000   xor   edx, 2010                      ; 异或0x2010
0040CD6C    B9 00D54000   mov   ecx, 0040D500                  ; 关键点1
0040CD71    3B11            cmp   edx, dword ptr ds:
0040CD73    74 06         je      short 0040CD7B
0040CD75    40            inc   eax
0040CD76    83C1 04         add   ecx, 4                         ; 判断下一个DWORD
0040CD79^ EB F6         jmp   short 0040CD71
0040CD7B    C3            retn



关键点1是啥呢 Ctrl+G 0040D500

0040D50000403249111_.00403249
0040D5040040324E111_.0040324E
0040D508004034B8111_.004034B8
0040D50C00403603111_.00403603
0040D5100040365BASCII "P@"
0040D514004036FD111_.004036FD
0040D5180040394C111_.0040394C
0040D51C00403C75111_.00403C75
0040D52000403D32111_.00403D32
0040D52400403D37111_.00403D37
0040D52800403D21111_.00403D21
0040D52C00403D9C111_.00403D9C
0040D53000403DB5111_.00403DB5
0040D53400403EF2111_.00403EF2
0040D538004000A4111_.004000A4 //edx的值
0040D53C004000C8111_.004000C8
0040D54000400182111_.00400182
0040D5440040021B111_.0040021B
0040D54800400202111_.00400202
0040D54C00400209111_.00400209
0040D55000400255111_.00400255
0040D5540040027B111_.0040027B
0040D558004002DA111_.004002DA
0040D55C00400343111_.00400343
0040D56000400397111_.00400397
0040D564004003E8111_.004003E8
0040D56800400451111_.00400451
0040D56C00400456111_.00400456


原来,0040D500 就是保存了各个被代码替换的地址 知道了这些,继续跑下去吧

0040CD8E   8DB480 00DF4000   lea   esi, dword ptr //关键点2
0040CD95   33C9            xor   ecx, ecx
0040CD97   E8 00000000       call    0040CD9C
0040CD9C   5D                pop   ebp
0040CD9D   81ED 4C1F4000   sub   ebp, 00401F4C
0040CDA3   8DBD 861F4000   lea   edi, dword ptr //edi=0040CDD6   预留空位写原来的代码


其实,关键点2就是偷的代码,其算法为:
(GetCall- 40D500)+((GetCall- 40D500)/4)+40DF00
GetCall就是0040D500 保存的被代码替换的地址

Ctrl+G 0040CDD6

0040CDD6   90                nop //这就是预留的空位
0040CDD7   90                nop
0040CDD8   90                nop
0040CDD9   90                nop
0040CDDA   90                nop
0040CDDB   68 90909090       push    90909090
0040CDE0   C3                retn

0040CDA9   B9 05000000       mov   ecx, 5 //偷的是5个字节
0040CDAE   F3:A4             rep   movs byte ptr es:, byte ptr //写入
0040CDB0   83EF 05         sub   edi, 5
0040CDB3   33C0            xor   eax, eax
0040CDB5   8BC8            mov   ecx, eax
0040CDB7   8A040F            mov   al, byte ptr
0040CDBA   34 28             xor   al, 28 //开始解密,每个字节异或0x28
0040CDBC   3E:880439         mov   byte ptr , al
0040CDC0   41                inc   ecx
0040CDC1   83F9 05         cmp   ecx, 5
0040CDC4   ^ 72 F1             jb      short 0040CDB7 //判断是否解密完


0040CDC6   5A                pop   edx //edx=被代码替换的地址
0040CDC7   83C2 05         add   edx, 5 //返回地址
0040CDCA   8DBD 8C1F4000   lea   edi, dword ptr
0040CDD0   8917            mov   dword ptr , edx //修正返回地址
0040CDD2   61                popad
0040CDD3   83C4 04         add   esp, 4 //后面的代码处有入栈操作,故ESP+4
0040CDD6   8BEC            mov   ebp, esp //被偷的代码已经写回来了
0040CDD8   83EC 1C         sub   esp, 1C
0040CDDB   68 90909090       push    90909090
0040CDE0   C3                retn


因为40d500 保存被代码替换的地址和保存偷代码的 40DF00都是硬编码,所以我们可以写个修复程序,贴上关键源码



//把需要修复的程序改名为fuck.exe,修复前请备份
int main()
{
//这个可以自己修改
char szFilename = "fuck.exe";
int sel;
UINT i=0, count=0;
hFile = CreateFile(
szFilename,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("Fail to open file\n");
getchar();
return 0;
}
if (CreateMap()==FALSE)
{
printf("Error\n");
getchar();
return 0;
}
if (IsPE()==FALSE)
{
printf("Error\n");
getchar();
return 0;
}
while(1)
{
//判断是否最后一个区段
printf("File must be DUMPED!!!\nImpRec Fixed? 1:Yes|2:No\n->");
scanf("%d", &sel);
if (sel == 1 || sel ==2)
{
   break;
}
}
PIMAGE_DOS_HEADER imDos = PIMAGE_DOS_HEADER(lpBase);
PIMAGE_NT_HEADERS imNt = PIMAGE_NT_HEADERS((DWORD)lpBase + imDos->e_lfanew);
PIMAGE_SECTION_HEADER imSec = PIMAGE_SECTION_HEADER((DWORD)imNt + sizeof(IMAGE_NT_HEADERS));
i = imNt->FileHeader.NumberOfSections;
i--;
if (sel == 1)
{
   i--;
}
PIMAGE_SECTION_HEADER imfkSec = PIMAGE_SECTION_HEADER((DWORD)imSec + sizeof(IMAGE_SECTION_HEADER) * i);
DWORD dwGetCallRVA = 0x1500 + imfkSec->VirtualAddress;
DWORD dwGetCallOffset = RVAToOffset(dwGetCallRVA);
DWORD dwCrOffset = RVAToOffset((dwGetCallRVA + 0xA00));
DWORD dwCallAddr, dwRead;
BYTE bCr = "";
DWORD dwWrite;
while (1)
{
//读被代码替换的地址
SetFilePointer(hFile, dwGetCallOffset,NULL,FILE_BEGIN);
ReadFile(hFile,&dwCallAddr,sizeof(DWORD),&dwRead,NULL);
if (dwCallAddr == 0x0)
{
   break;
}
dwCallAddr ^=0x2010;
//printf("%08X : ", dwCallAddr);

SetFilePointer(hFile, dwCrOffset,NULL,FILE_BEGIN);
ReadFile(hFile, &bCr, sizeof(bCr), &dwRead, NULL);
for (i = 0; i < 5; i++)
{
   bCr ^= 0x28;
   //printf("%02X ", bCr);
}
dwCallAddr = RVAToOffset((dwCallAddr-imNt->OptionalHeader.ImageBase));
SetFilePointer(hFile, dwCallAddr,NULL,FILE_BEGIN);
//修复
WriteFile(hFile, &bCr, sizeof(bCr), &dwWrite, NULL);
//printf("\n");
count++;
dwCrOffset += sizeof(bCr);
dwGetCallOffset += sizeof(DWORD);
}
printf("Replace : %d\n", count);
printf("File Fixed\n");
SetEndOfFile(hFile);
DeleteMap();

getchar();
getchar();
return 0;
}


写得比较挫,都是抄的。:lol :rggrg

ximo 发表于 2010-8-6 23:05

哎,又被爆菊了。:'(weeqw

zzage 发表于 2010-8-6 23:13

哎,又被爆菊了。
ximo 发表于 2010-8-6 23:05 http://www.52pojie.net/images/common/back.gif


    比你写的那两个垃圾文章牛多了...膜拜晕四大牛!

Tale 发表于 2010-8-6 23:22

93太牛了 闭关了这么久 太强了

Hmily 发表于 2010-8-6 23:29

晕死牛进步很快啊.

yanshaowei 发表于 2010-8-6 23:37

呵呵,很深哦

jinfu 发表于 2010-8-7 00:01

本广告位招租!:Dweeqw

破解小乖 发表于 2010-8-7 00:05

很强大。。。

2666fff 发表于 2010-8-7 07:40

又是一小马甲?

zsl01 发表于 2010-8-7 07:52

很强大。。。:victory:
页: [1] 2 3
查看完整版本: 简单分析 FuckProtect 1.0.0.7 CodeReplace