|
[原创]JProfiler 6/7 注册机制逆向工程分析
关键在于有几个方法,之前尝试进行实现,总是和原始的计算出来的数据不同,所以就采用这种方式,如果能够分析出数值计算的方法,那就可以直接写注册机了 |
|
|
|
[原创]JProfiler 6/7 注册机制逆向工程分析
3. 注册机实现 由于 clearCRC32, addCrc32b, getCRC32 这几个方法,以及 LicenseChecker::calculateChecksum 这个方法,分析比较难,实在没有搞懂,但是整个注册机的 逻辑已经清除,因此准备编写注册机。 关键部分在与上述方法没有代码实现,那么只好用 dll, jnilib 这些动态链接库中的方法进行加载调用了。 经过检查 Windows 版本的dll ,没有导出相应的函数,只好在 Linux或者 Mac 中了。 Linux版本已经完成,采用 dlopen, dlsym 就可以将动态链接库加载,并且根据IDA Pro分析出的函数签名,来进行加载调用生成nativeHash。 一下是 Mac OS X 版本的代码,一共参考 // // main.m // jprofiler // // Created by on 12-1-4. // Copyright (c) 2012年 __MyCompanyName__. All rights reserved. // #include <mach-o/dyld.h> #import <Foundation/Foundation.h> char *getHash(char *hash, char *buf, int len, int key1, int key2, int key3) { int sum = 0; int i = 0; for (; i < len; i++) { sum += (hash[i]); } int l1, l2, l3; l1 = sum % key1; l2 = sum % key2; l3 = sum % key3; sprintf(buf, "%d%d%d", l1, l2, l3); return buf; } static void * lookupSymboAddress(const char *symbolName){ void * ret = NULL; if(symbolName != NULL){ bool ok = NSIsSymbolNameDefined(symbolName); if(ok){ NSLog(@"Found"); NSSymbol symb = NSLookupAndBindSymbol(symbolName); ret = NSAddressOfSymbol(symb); if(ret != NULL){ NSLog(@"OK"); } }else{ NSLog(@"NO"); } } return ret; } int main (int argc, const char * argv[]) { // Name: checkLicenseKey__14LicenseCheckerPCcb Linux // Name: __ZN14LicenseChecker15checkLicenseKeyEPKcb Mac OS X // Type: int checkLicenseKey(char const *,bool) typedef int (*CheckFunc)(char const *str, int b); // Name: isChecksumValid__14LicenseCheckerPCc Linux // Name: __ZN14LicenseChecker15isChecksumValidEPKc Mac OS X // Type: int isChecksumValid(char *s) typedef int (*IsChecksumValid)(char *s); // Name: clearCRC32__FPUi Linux // Name: __Z10clearCRC32Pj Mac OS X // Type: int clearCRC32(char *s) typedef int (*ClearCRC32)(unsigned int *crcValue); // Name: addCrc32b__FPUiPCci Linux // Name: __Z9addCrc32bPjPKci Mac OS X // Type: int addCrc32b(unsigned int *, char const *, int) typedef int (*AddCrc32b)(unsigned int * crcValue, char const *str, int len); // Name: getCRC32__FPUiPCUi Linux // Name: __Z8getCRC32PjPKj Mac OS X // Type: int getCRC32(unsigned int *, unsigned int const *) typedef int (*GetCRC32)(unsigned int *crcValue, unsigned int const *oldCRCValue); // Name: calculateChecksum__14LicenseCheckerUiPcb Linux // Name: __ZN14LicenseChecker17calculateChecksumEjPcb Mac OS X // Type: int calculateChecksum(unsigned int, char *, bool) typedef int (*CalculateChecksum)(unsigned int crcValue, char *content, int b); char *nativeKeyForJ6[] = { "__jprofiler_static_tt6", "$jprofiler6__cleanup" }; char *nativeKeyForJ7[] = { "__jpmmp_dynamic_tt8", "_$$$dynup_jps" }; int javaCodeKeyForJ6[] = {7, 38, 11}; int javaCodeKeyForJ7[] = {12, 4, 66}; @autoreleasepool { char * lic = "A-J6-CRACKER#21781-\0"; char *licType = "A"; char *version = "6"; char *user = "CRACKER"; char *userID = "21781"; char *expiredDays = "1000"; switch (argc) { case 1: printf("Usage: jprofilercracker <licType> <version> <User> <userID> [expiredDays]"); // return -1; break; case 2: licType = argv[1]; break; case 3: licType = argv[1]; version = argv[2]; break; case 4: licType = argv[1]; version = argv[2]; user = argv[3]; break; case 5: licType = argv[1]; version = argv[2]; user = argv[3]; userID = argv[4]; break; case 6: licType = argv[1]; version = argv[2]; user = argv[3]; userID = argv[4]; expiredDays = argv[5]; break; } int totalLen = strlen(licType)+2+strlen(version)+1+strlen(user)+1+strlen(userID)+1; int isTrail = 0; if(strncmp(licType,"E",1) == 0 || strncmp(licType,"T",1) == 0 ){ totalLen += (11 + strlen(expiredDays)); isTrail = 1; } char *nkey1, *nkey2; int *jkey; if (strncmp(version, "6", 1) == 0) { nkey1 = nativeKeyForJ6[0]; nkey2 = nativeKeyForJ6[1]; jkey = javaCodeKeyForJ6; }else if (strncmp(version, "7", 1) == 0) { nkey1 = nativeKeyForJ7[0]; nkey2 = nativeKeyForJ7[1]; jkey = javaCodeKeyForJ7; } char *nl = (char*)(malloc(totalLen)); sprintf(nl,"%s-J%s-%s#%s-",licType,version,user,userID); if(isTrail){ // TODO Get Current time and add expired days and gen yyyy.mm.dd-days sprintf(nl,"%s-J%s-%s#%s-",licType,version,user,userID); } lic = nl; bool b = NSAddLibrary("./jprofiler.dylib"); if(b){ CheckFunc func = (CheckFunc) lookupSymboAddress( "__ZN14LicenseChecker15checkLicenseKeyEPKcb"); IsChecksumValid isChecksumValid = (IsChecksumValid) lookupSymboAddress( "__ZN14LicenseChecker15isChecksumValidEPKc"); ClearCRC32 clearCRC32 = (ClearCRC32) lookupSymboAddress("__Z10clearCRC32Pj"); AddCrc32b addCrc32b = (AddCrc32b) lookupSymboAddress("__Z9addCrc32bPjPKci"); GetCRC32 getCRC32 = (GetCRC32) lookupSymboAddress("__Z8getCRC32PjPKj"); CalculateChecksum calculateChecksum = (CalculateChecksum) lookupSymboAddress("__ZN14LicenseChecker17calculateChecksumEjPcb"); NSLog(@"OK!"); if (func != NULL && isChecksumValid != NULL && clearCRC32 != NULL && addCrc32b != NULL && getCRC32 != NULL) { printf("func found OK\nGen Key for %s\n", lic); if (isChecksumValid != NULL) { char *dd = strrchr(lic, '-'); // printf("strrchr ret %s\n", dd); int len = dd - lic; // printf("sub ret %d\n", len); unsigned int crcValue = 0; unsigned int tempCRC = 0; unsigned int tempCRC2 = 0; // char *str2; char var10[100]; char var20[100]; clearCRC32(&crcValue); addCrc32b(&crcValue, lic, len); addCrc32b(&crcValue, nkey1, strlen(nkey1)); getCRC32(&tempCRC, &crcValue); // printf("tempCRC %d\n", tempCRC); clearCRC32(&crcValue); addCrc32b(&crcValue, lic, len); addCrc32b(&crcValue, nkey2, strlen(nkey2)); getCRC32(&tempCRC2, &crcValue); // printf("tempCRC2 %d\n", tempCRC2); calculateChecksum(tempCRC, var10, 1); calculateChecksum(tempCRC2, var20, 1); // printf("var10 = %s\n",var10); // printf("var20 = %s\n",var20); int v10len = strlen(var10); int v20len = strlen(var20); int hashLen = v10len + v20len; char * buf = (char*) (malloc(hashLen)); int i; for (i = 0; i < v10len; i++) { buf[i] = var10[i]; } int j; for (j = 0; j < v20len; j++) { buf[v10len + j] = var20[j]; } char code[100]; getHash(buf, code, hashLen, jkey[0],jkey[1],jkey[2]); printf("license is : %s%s#%s\n", lic, buf, code); free(buf); } } else { printf("func not found\n"); } }else{ NSLog(@"Error!"); } free(nl); } return 0; } |
|
[原创]JProfiler 6/7 注册机制逆向工程分析
Native部分 错误提示信息为 Invalid license key 通过IDA Pro 查找,(针对 64bit Mac OS X 动态库) 找到引用 这个字符串类的地方,在 方法 LiveProfiling::initCommunication(JNIEnv *) 中 会进行打印操作,那么我们定位逻辑,到底从哪里来得。 这个流程是通过 LiveProfilingSession::initParameters(JNIEnv *) 这个方法的返回值进行 处理的。那么进入这个部分 LiveProfilingSession::initParameters(JNIEnv *) 仔细找找能够发现 LicenseChecker::checkLicenseKey(char *, bool) 这个方法, 那么以后就着重 LicenseChecker C++ 类进行分析了。 64位汇编中经常有 rbx, r12d 这种,不明白, 这样也导致了最终注册机没有采用全部独立编写的问题。 LicenseChecker::checkLicenseKey 的逻辑 { License:String if(license startsWith("FLOAT")){ // goto FLOAT license check }else{ char ch = license charAt(0); if(ch == 'A'){ // 正式版 LicenseChecker::checkNormalLicense(license) }else{ // 试用版 } } } LicenseChecker::checkNormalLicense(license) 逻辑 { license countDashes 获取 - 个数 if(count > 3){ LicenseChecker::isChecksumValid(license); } } LicenseChecker::isChecksumValid(license) 逻辑 { strrchr 查找 license 最后一个 - 的位置 计算这个之前的个数 必须大于4 if(len > 4){ int crcValue; clearCRC32(&crcValue); // crcValue = -1 addCrc32b(&crcValue, license, len); // 最后一个 - 之前的内容加到 crcValue中 addCrc32b(&crcValue, "jprofiler version key1", ""len); // 插入特定版本的key1 tempCRC = 0; getCRC32(&tempCRC, &crcValue); // 将 crcValue中数值处理到 tempCRC clearCRC32(&crcValue); // crcValue = -1 addCrc32b(&crcValue, license, len); // 最后一个 - 之前的内容加到 crcValue中 addCrc32b(&crcValue, "jprofiler version key2", ""len); // 插入特定版本的key2 tempCRC2 = 0; getCRC32(&tempCRC2, &crcValue); // 将 crcValue中数值处理到 tempCRC var10:String var20:String LicenseChecker::calculateChecksum(tempCRC, var10, true); // 将tempCRC转换为字符串 LicenseChecker::calculateChecksum(tempCRC2, var20, true); // 将tempCRC2转换为字符串 nativeHash <= var10 append var20; // 和 license中最后的 - 之后的内容进行比较 是否相等 } } 由此可见上面的方法,就是 nativeHash的计算方法 |
|
[求助]JAVA程序能加密吗?
有,代码混淆 和 类加载加密 |
|
不知道有没有朋友做iphone上的开发
我是做iPhone开发的 |
|
[转帖]修改java字节码
还可以,感觉已经深入到字节代码的级别了,你提到的这两个工具 应用也很广泛,在类文件修改、生成方面用的很多。 同时建议通过字节代码的阅读理解,进行更深的研究,比如混淆代码的回复等 希望Java破解的高手越来越多 |
|
[原创]JVMTI应用简单分析,基于JVMTI的类加载器分析,TBCredit类文件解密
我把完整的解密代码上传上来,主要是 header_key, cls_key的说明 |
|
[求助]Java程序的破解
舵手兄说的对,混淆器生成的名字是很乱,但是,总有方法看懂的 |
|
[讨论]10年了,我们那些人都在哪?
记得vhly这个网名,也已经注册10年了,有很多事情,已经模糊,有些就让它随风而逝,有些却 历历在目 我说的10年,是 vhly 第一个注册网站用户的时间,仔细一看,自己在看雪上注册 是 2004年 |
|
会java反编译的进来看看
我记得我发过一篇帖子,说的就是这个的解密操作,你找找TBCredit |
|
[求助]Java怎么破解?
看雪搞Java的人不是没有,干什么去 IT168 |
|
[求助][Java]jar包破解
首先,找到 META-INF/ 文件夹,将其中 的 MANIFEST.MF 中 包括签名的数据删除 |
|
[求助]一个JAVA代码不会弄了谁帮下我
给你说一下几个问题 1、代码缩进,就是在论坛发帖子也要注意格式 2、死循环 3、循环中使用try{...}catch 方式 4、输入获取方式不正确 5、错误的break语句 6、根据程序上下文,b变量使用错误 7、针对Enumeration的使用,针对Vector 应该使用 elementAt,如果使用 nextElement会增加代码片断执行时间,尤其是在 J2ME 等受限设备上。 8、针对代码片断功能,这个实现算法过于复杂 9、针对 Vector 的使用,如果是在 JDK1.5之后的,Vector可以使用自动封装和解封,即 v.addElement(34); 这种,直接被处理成 v.addElement(new Integer(34)); 10、针对 1.5之后,可以使用泛型 Vecot<Integer> v = new Vector<Integer>(); import java.util.*; public class Testvector1 { public static void main(String[] args) { int b=0; Vector v=new Vector(); System.out.println("please enter a number"); while(true) { try { b= System.in.read(); }catch(Exception e) { System.out.println(e.getMessage()); } // try end } // while end if(b=='\r' || b=='\n') break; else { int num=b-'0'; v.addElement(new Integer(num)); } // else end } // main() End int sum=0; // 这个被编译成 Testvector1 的成员变量 Enumeration e=v.elements(); // 此处必然找不到 v while(e.hasMoreElements()) { Integer intobj=(Integer)e.nextElement(); sum = sum+intobj.intValue(); } System.out.println(sum); } } // 看了一下上面的代码,发现这是一个测试 Vector的例子,可以写成这样 public class TestVector2{ public static void main(String[] args){ String line; Vector<Integer> v = new Vector<Integer>(); long sum = 0; int b; System.out.println("please enter a number"); try{ while(true){ b = System.out.read(); if(b == '\n' || b =='\r'){ // 当输入 回车的时候,退出循环 break; } if(b >= '0' && b <= '9'){ b = b - '0'; v.addElement(new Integer(b)); }else{ // TODO 此处提示用户,输入的不是数字 } } int sum = 0; int size = v.size(); Integer in; for(int i = 0; i<size;i++){ in = v.elementAt(i); sum += in. intValue(); } System.out.println(sum); }catch(Exception ex){ System.out.println("出现异常:"+e.getMessage()); } } } |
|
[原创]JVMTI应用简单分析,基于JVMTI的类加载器分析,TBCredit类文件解密
没想到舵手兄也来了,其实这个,要是去掉某些特定的文字就好了,主要是介绍 基于 JVMTI 实现的类文件加密保护的方式,同时也是发现现在越来越多的保护方式都是倾向于 agent 的方式,所以,权当抛砖引玉了 |
|
|
操作理由
RANk
{{ user_info.golds == '' ? 0 : user_info.golds }}
雪币
{{ experience }}
课程经验
{{ score }}
学习收益
{{study_duration_fmt}}
学习时长
基本信息
荣誉称号:
{{ honorary_title }}
能力排名:
No.{{ rank_num }}
等 级:
LV{{ rank_lv-100 }}
活跃值:
在线值:
浏览人数:{{ visits }}
最近活跃:{{ last_active_time }}
注册时间:{{ user_info.create_date_jsonfmt }}
勋章
兑换勋章
证书
证书查询 >
能力值