第一次有耐心脱壳,脱完后,才在这里知道是 CrypKeyInstant,我脱的版本到底是多少这就不太清楚 ,但是和很下面这个链接上的讨论很像:双进程,大量 cc,抽代码。
http://bbs.pediy.com/showthread.php?t=33856

这个壳代码很清晰,并且抽出代码没有加密,所以搞起来也比较容易,没有多少技术含量,高手可以略过。  


/////////////////////////////////////////////////////////////////////////////////////////////////////
// 写的很乱, 写的时候很有针对性。
// 如果要要改, 把 protected_module_table  改为发生异常后第一个循环查找的 call 的返回值
//   
 
#include <windows.h>
#include <stdio.h>

//char* protected_module_table = (char*)0x4034B0;
// 
typedef unsigned long u32;

#include <PSHPACK1.H>
struct trap_record 
{
  char  attr; // 
  u32    trap_addr;
  u32    patch_code_record_off;
  u32    patch_code_record_size;
};
#include <poppack.h>

// struct patch_code_record 
// {
//   char is_used;
// //  char patch_code[1];
// };

//base --> 0x20
//first --> 0x48aea

HANDLE __hProcess1, __hProcess2;
u32 __trap_hash_table;
void* __big_buf = NULL;

void __fastcall xf(u32 p_tr)
{
  trap_record tr;
  u32 tmp;

  if ( 
    !ReadProcessMemory(__hProcess1, (void*)p_tr, &tr, sizeof (tr), &tmp) 
    )
  {
    printf("读取地址 %08X 失败!\n", p_tr);
    return ;
  }
  
  if ( tr.attr == 0 )
  {
    xf(tr.patch_code_record_off + __trap_hash_table);
    xf(tr.patch_code_record_size + __trap_hash_table);
  }
  else
  {
    printf(
      "trap_record.attr                   = 0x%08X\n"
      "trap_record.trap_addr              = 0x%08X\n"
      "trap_record.patch_code_record_off  = 0x%08X\n"
      "trap_record.patch_code_record_size = 0x%08X\n"
      "-------------------------------------------------------\n",
      tr.attr, 
      tr.trap_addr, 
      tr.patch_code_record_off, 
      tr.patch_code_record_size
      );

      ReadProcessMemory(__hProcess1, (PVOID)(__trap_hash_table + tr.patch_code_record_off + 1), __big_buf, tr.patch_code_record_size, &tmp);
      WriteProcessMemory(__hProcess2, (PVOID)tr.trap_addr, __big_buf, tr.patch_code_record_size, &tmp);
      FlushInstructionCache(__hProcess2, (PVOID)tr.trap_addr, tr.patch_code_record_size);
  }
}

int main(int argc, char* argv[])
{
  DWORD dwPid1, dwPid2;

  printf("请分别输入调试和被调试进程的 PID: \n");
  scanf("%d %d", &dwPid1, &dwPid2);
  
//   BOOL bOK = DebugActiveProcess(dwPid1); // 暂停调试器
//   if ( !bOK )
//   {
//     printf("绑定 %d 进程失败!\n", dwPid1);
//     return -1;
//   }
//   
//   DEBUG_EVENT de;
//   if ( !WaitForDebugEvent(&de, 5000) )
//   {
//     printf("等待 %d 进程的调试事件失败!\n");
//     return -2;
//   }
//  
//  HANDLE hProcess1 = de.u.CreateProcessInfo.hProcess;

  // 最好在打开这两个进程的之前已经暂停
  HANDLE hProcess1 = OpenProcess(PROCESS_VM_READ | PROCESS_VM_OPERATION, FALSE, dwPid1); 
  HANDLE hProcess2 = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, dwPid2);
  
  __hProcess1 = hProcess1;
  __hProcess2 = hProcess2;

  if ( hProcess2 == NULL || hProcess1 == NULL )
  {
    printf("打开 %d 进程进行写操作失败!\n");
    return -3;
  }
  
  u32 *index_table = NULL;
  __try
  {
    u32 tmp;
    u32 a[3];

    ReadProcessMemory(hProcess1, (PVOID)0x4034B0, a + 0, 4, &tmp);
    ReadProcessMemory(hProcess1, (PVOID)(a[0] + 0x18), a + 1, 4, &tmp);
     ReadProcessMemory(hProcess1, (PVOID)(a[0] + 0x38), a + 2, 4, &tmp);
    
    __big_buf = VirtualAlloc(NULL, 1024 * 1024, MEM_COMMIT, PAGE_READWRITE);
    __trap_hash_table = a[2];

    xf(a[1] + a[2]);
  }
  __except ( EXCEPTION_EXECUTE_HANDLER )
  {
    printf("发生了一个异常!\n");
  }
  
  if ( __big_buf != NULL )
  {
    VirtualFree(__big_buf, 1024 * 1024, MEM_DECOMMIT);
    VirtualFree(__big_buf, 0, MEM_RELEASE);

    __big_buf = NULL;
  }

  printf("ok Dump!!\n");
  scanf("%d", &dwPid1);

  return 0;
}