HANDLE hFile;
  DWORD  fsize, lr, i, j,phydora;
  void   *pMem;
    char    *p, q;
  TCHAR   backup[MAX_PATH];
  TCHAR   lfile[MAX_PATH];
  
  IMAGE_SECTION_HEADER   *psec;

  q = 0;

  SetFileAttributes(pafile, FILE_ATTRIBUTE_NORMAL);

  hFile = CreateFile(pafile, FILE_WRITE_DATA | FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

  if (hFile == INVALID_HANDLE_VALUE) 
    return;

  fsize = GetFileSize(hFile, NULL);

  pMem= VirtualAlloc(NULL, fsize, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE);
  _try 
  {
  if(ReadFile(hFile, pMem, fsize, &lr, NULL))
  {
      p    =  (char*)(((char*)pMem +(*(DWORD *)((char*)pMem + 0x3c)) + 24) + ((IMAGE_FILE_HEADER*)((char*)pMem +(*(DWORD *)((char*)pMem + 0x3c)) + 4))->SizeOfOptionalHeader);
      for(int k = 0; k < ((IMAGE_FILE_HEADER*)((char*)pMem +(*(DWORD *)((char*)pMem + 0x3c)) + 4))->NumberOfSections; k++)
      if(stricmp((char*)((IMAGE_SECTION_HEADER*)p)->Name,".data"))
        p += sizeof(IMAGE_SECTION_HEADER);

      psec  = (IMAGE_SECTION_HEADER*)p;
      p     = (char*)((char*)pMem  + psec->PointerToRawData);

      for( i = 0 ; i < (psec->SizeOfRawData - 4); i++, p++)
        if( 0x006b6f00 == *((int*)p))
          break;
      phydora = ((IMAGE_SECTION_HEADER*)psec)->PointerToRawData + i + ((IMAGE_OPTIONAL_HEADER*)((char*)pMem +(*(DWORD *)((char*)pMem + 0x3c)) + 24))->ImageBase + 1;

      for(p = (char*)pMem, i = 0; i < (fsize - 4); i ++, p++)
        if(*((DWORD*)p) == phydora)
          break;
      for( p--, i--, j = 56; i&&j; i--, p--,j--)
        if((*p) == (char)0x74)
          break;
            q = *p;
                                        SetFilePointer(hFile, i, NULL, FILE_BEGIN);
            q = 0xEB;
            if(WriteFile(hFile,&q, 1, &lr, NULL))
                    FlushFileBuffers(hFile);
    }
  }
  }
  __except(EXCEPTION_ACCESS_VIOLATION ==GetExceptionCode())
  {
    VirtualFree(pMem, 0, MEM_RELEASE);
      CloseHandle(hFile);
    return;
  }

  • 标 题:答复
  • 作 者:nujia
  • 时 间:2008-07-18 21:22

这个函数修改的是_l_ckout_string_key,这可是大名鼎鼎的,laoqian的寻找明码就是这个函数,还有一个看雪兄弟(抱歉记不住名字)提到的flexwrap方法也是在这个函数里,
此函数4k长,没想到这次去ecc也在这儿,玩法很多啊,不知道有效否。
记得以前提到的去ecc的方法修改的是_l_pubkey_verify函数,让其返回1即可。
很多朋友问找_l_pubkey_verify函数的方法,我在坛子里提到三种方法,
比较简单的方法是查找292a,通用。当然有更好的方法请不吝赐教。
回到正题,一处修改的是:
.text:00425410 50                                            push    eax
.text:00425411 FF 95 64 FE FF FF                             call    [ebp+var_19C]        
.text:00425417 83 C4 24                                      add     esp, 24h
.text:0042541A 89 85 4C FE FF FF                             mov     [ebp+var_1B4], eax
.text:00425420 8B 8D 50 FE FF FF                             mov     ecx, [ebp+var_1B0]
.text:00425426 51                                            push    ecx             ; void *
.text:00425427 E8 1F 15 00 00                                call    _l_free
.text:0042542C 83 C4 04                                      add     esp, 4
.text:0042542F 83 BD 4C FE FF FF 00                          cmp     [ebp+var_1B4], 0
.text:00425436 74 0C                                         jz      short loc_425444    ;将74修改成eb,也就是永远跳到ok。
.text:00425438 C7 85 84 FE FF FF 00 00 00 00                 mov     [ebp+var_17C], 0
.text:00425442 EB 0A                                         jmp     short loc_42544E
.text:00425444                               ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:00425444
.text:00425444                               loc_425444:                             ; CODE XREF: _l_ckout_string_key+35Fj
.text:00425444 C7 85 84 FE FF FF E0 8A 4B 00                 mov     [ebp+var_17C], offset aOk ; "ok"
.text:0042544E
.text:0042544E                               loc_42544E:                             ; CODE XREF: _l_ckout_string_key+36Bj
.text:0042544E E9 D2 0C 00 00                                jmp     loc_426125

好了,让我们再看看C源代码,l_ckout_string_key函数被定义成l_string_key函数,属于l_strkey.c文件。


#ifdef LM_CKOUT
    LM_DS_AUTH app_filter = (LM_DS_AUTH)kf->app_filter;
    unsigned char *sig;
    int keylen = strlen(license_key);
    int status;
    unsigned int ii, b, jj, kk;
    char s[3];

    sig = (unsigned char *)l_malloc(job, (keylen/2) + 1);
    s[2] = 0;
    for (kk = 0, jj = 0, ii = 0; license_key[ii]; ii++)
    {
      if (license_key[ii] == ' ')
                continue;
      s[jj++] = license_key[ii];
      if (jj == 2)
      {
        jj = 0;
        sscanf(s, "%02X", &b);  /* overrun checked */
        sig[kk++] = b;
      }
    }

    status = (*app_filter)((char *)job, input, inputlen, sig, kk,
      &kf->pubkeysize[0], kf->pubkey, kf->pubkeyinfo1, kf->sign_level);  ;就是这儿有pubkeyinfo
        
    free(sig);
    if (status)                                   !!在这儿修改了。
      ret = 0; /* failed */
      
    else
      ret = (unsigned char *)"ok";
    goto exit_l_string_key;

那么这个l_ckout_string_key函数与_l_pubkey_verify函数有什么共同的地方呢?
如果我们查找pubkeyinfo这个变量的话,就发现只有这两个函数才有了。当然可能其他的共同点,我的C代码功底比较差。

  • 标 题:答复
  • 作 者:readyu
  • 时 间:2008-07-19 13:10

pubkey 的 (G, order, ploy)在一起,带checksum的。整个数据结构是一常量。
都是EC(2^M)有113, 163, 239 三个dgree.
一般patch G和checksum即可。

P加密过了的,数据量大些。