吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 9432|回复: 25
收起左侧

[原创] 简单分析 FuckProtect 1.0.0.7 CodeReplace

[复制链接]
ShaBility 发表于 2010-8-6 22:59
本帖最后由 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:[ebp+14]
004020BD    FF75 10         push    dword ptr ss:[ebp+10]
004020C0    FF75 0C         push    dword ptr ss:[ebp+C]
004020C3    FF75 08         push    dword ptr ss:[ebp+8]
004020C6    E8 A70B0000     call    00402C72
004020CB    85C0            test    eax, eax
004020CD    75 09           jnz     short 004020D8
004020CF    C745 EC 0000000>mov     dword ptr ss:[ebp-14], 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:[esp+20]
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:[esp+4]      ; 被代码替换的地址
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:[ecx]
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
0040D500  00403249  111_.00403249
0040D504  0040324E  111_.0040324E
0040D508  004034B8  111_.004034B8
0040D50C  00403603  111_.00403603
0040D510  0040365B  ASCII "P@"
0040D514  004036FD  111_.004036FD
0040D518  0040394C  111_.0040394C
0040D51C  00403C75  111_.00403C75
0040D520  00403D32  111_.00403D32
0040D524  00403D37  111_.00403D37
0040D528  00403D21  111_.00403D21
0040D52C  00403D9C  111_.00403D9C
0040D530  00403DB5  111_.00403DB5
0040D534  00403EF2  111_.00403EF2
0040D538  004000A4  111_.004000A4 //edx的值
0040D53C  004000C8  111_.004000C8
0040D540  00400182  111_.00400182
0040D544  0040021B  111_.0040021B
0040D548  00400202  111_.00400202
0040D54C  00400209  111_.00400209
0040D550  00400255  111_.00400255
0040D554  0040027B  111_.0040027B
0040D558  004002DA  111_.004002DA
0040D55C  00400343  111_.00400343
0040D560  00400397  111_.00400397
0040D564  004003E8  111_.004003E8
0040D568  00400451  111_.00400451
0040D56C  00400456  111_.00400456

原来,0040D500 就是保存了各个被代码替换的地址 知道了这些,继续跑下去吧
0040CD8E     8DB480 00DF4000   lea     esi, dword ptr [eax+eax*4+40DF00] //关键点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 [ebp+401F86] //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:[edi], byte ptr [esi] //写入
0040CDB0     83EF 05           sub     edi, 5
0040CDB3     33C0              xor     eax, eax
0040CDB5     8BC8              mov     ecx, eax
0040CDB7     8A040F            mov     al, byte ptr [edi+ecx]
0040CDBA     34 28             xor     al, 28 //开始解密,每个字节异或0x28
0040CDBC     3E:880439         mov     byte ptr [ecx+edi], 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 [ebp+401F8C]
0040CDD0     8917              mov     dword ptr [edi], 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[MAX_PATH] = "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[5] = "";
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[i] ^= 0x28;
   //printf("%02X ", bCr[i]);
  }
  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;
}

写得比较挫,都是抄的。

codereplace.rar

22.27 KB, 下载次数: 16, 下载积分: 吾爱币 -1 CB

Fixcr.rar

1.39 KB, 下载次数: 10, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 1威望 +1 热心值 +1 收起 理由
peace2008 + 1 + 1 精品文章!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

ximo 发表于 2010-8-6 23:05
哎,又被爆菊了。
zzage 发表于 2010-8-6 23:13
哎,又被爆菊了。
ximo 发表于 2010-8-6 23:05



    比你写的那两个垃圾文章牛多了...膜拜晕四大牛!
Tale 发表于 2010-8-6 23:22
Hmily 发表于 2010-8-6 23:29
晕死牛进步很快啊.
yanshaowei 发表于 2010-8-6 23:37
呵呵,很深哦
头像被屏蔽
jinfu 发表于 2010-8-7 00:01
本广告位招租!
破解小乖 发表于 2010-8-7 00:05
很强大。。。
2666fff 发表于 2010-8-7 07:40
又是一小马甲?
zsl01 发表于 2010-8-7 07:52
很强大。。。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-22 22:16

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表