首页
社区
课程
招聘
[原创]ECC patcher for the flexlm with ecc
2008-7-13 22:20 16427

[原创]ECC patcher for the flexlm with ecc

2008-7-13 22:20
16427
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;
        }

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞7
打赏
分享
最新回复 (10)
雪    币: 229
活跃值: (22)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
nujia 3 2008-7-16 09:44
2
0
好程序,应该顶,
将74改称eb,
不过特征码为006b6f00这个够吗?抑或我程序看错了,程序功底差了些,
雪    币: 229
活跃值: (22)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
nujia 3 2008-7-16 09:50
3
0
好程序,应该顶,
将74改称eb,
不过特征码为006b6f00这个够吗?抑或我程序看错了,程序功底差了些,
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hswqs 2008-7-16 17:49
4
0
可否提供编译好的程序一试用
雪    币: 229
活跃值: (22)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
nujia 3 2008-7-18 21:22
5
0
这个函数修改的是_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代码功底比较差。
雪    币: 223
活跃值: (23)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
phydora 1 2008-7-18 23:02
6
0
right!
本是为了找一个相对固定的方式抓取pubkey,顺便patch了一下.
我还没找到相对容易的静态获取从文件获取pubkey的方法。
patch方法:
在PE的data段搜索"ok", 得到偏移,根据绝对偏移,找到待patch处.
特征码006b6f00  ok 一般来说是够用的,因为有了PE和偏移查找的叠加,概率很低。
雪    币: 11704
活跃值: (966)
能力值: ( LV12,RANK:779 )
在线值:
发帖
回帖
粉丝
readyu 12 2008-7-19 13:10
7
0
pubkey 的 (G, order, ploy)在一起,带checksum的。整个数据结构是一常量。
都是EC(2^M)有113, 163, 239 三个dgree.
一般patch G和checksum即可。

P加密过了的,数据量大些。
雪    币: 527
活跃值: (220)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
aprice 2008-7-19 13:19
8
0
好东东,受用了
雪    币: 334
活跃值: (47)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
honghan 2017-8-4 14:47
9
0
Mark
雪    币: 101
活跃值: (743)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
tcy027 2020-8-7 09:50
10
0
readyu pubkey 的 (G, order, ploy)在一起,带checksum的。整个数据结构是一常量。 都是EC(2^M)有113, 163, 239 三个dgree. 一般patch G和check ...
readyu大神好!问了一圈,还是只能找您了。您在大作中提到,替换pubkey和checksum可以搞定flexlm。
疑问1:为啥空手剑客他的工具只替换pubkey就行了?
疑问2:pubkey已替换ok,但是lmcrypt.exe新生成的node-locked类型,不能通过验证。不知道是否与checksum未替换有关?如何确认和查看checksum?
雪    币: 213
活跃值: (57)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cree 2022-4-24 17:22
11
0
有点难呀
游客
登录 | 注册 方可回帖
返回