本帖最后由 燃病软 于 2023-10-28 16:55 编辑
破解 QCAD for Mac因为今天要修改一个图,不能有其他公司的名字,光改PDF没用,所以只能从dxf文件下手。搜来搜去又不想装Autodesk CAD,太麻烦了,所以随便找了个QCAD破一下,好像这软件还挺好用。 1. 分析没激活前是这样的 充斥着Trial等字样,右下角还有一个审判按钮。 其次,使用大约30-40分钟左右,会有退出弹窗 并显示我试用到期。 并且最重要的是,导出图纸到pdf有一很大的水印,如果没有水印我可能就不会破解他了。 我打算以“This is a trial version of”为切入点,暴力搜索所有文件试试。 就让审判来得更猛烈些吧! 2. 审判常规搜索我们是搜索不到的。所以我们需要用一些特别的手段来暴力搜索所有二进制里的文件。 因为我们知道,英文字符串大部分就是原文在二进制中,所以我们暴力搜索一定能搜索到相关的内容。 find /Applications/QCAD.app/Contents -type f -exec sh -c 'strings "$1" | grep "This is a trial version of" && echo "$1"' sh {} \;
差不多也就搜索到这了。 我们发现第一个文件和第二个文件都存在这个字符串,那么我们就着重搞这两个文件。 首先打开第一个: 因为只有几百K,分析速度很快,我们一搜,还真有。 那这下不得不跳过去看下了: 糟糕糟糕OMG,魔法怎么施灵辣! 却说这大魔导师落叶不愧是强者,事情发展出乎意料却也不急,冷笑着说道:“尔等不过区区Qt多语言,待我略施小技,必取你首级!” 那QCAD本就是小作坊出产,哪里见过这等阵仗?当下心中狂跳,嘴上却是硬道:“兀那乱臣贼子!休要在此胡言乱语妖言惑众,我等在此会你一二,看你还有什么手段?” 那大魔导师落叶出道以来哪里受到如此挫折?闻得QCAD猖狂挑衅,当下却是道心不稳,怒从心中起,恶言道:“区区蝼蚁也敢在本魔导师面前螳臂当车?死来!” 当下落叶长啸一声,法杖高举,大喝道:“天圆地方乾坤倒转,禁术·Hopper disassembler,启动!” 说时迟那时快,原本万里无云的蓝天诡异的传出一声巨响,那QCAD当即被一个邪异蓝色光罩团团围住,进出不得。QCAD惊怒交加,一时不察竟受制于人,怒不可遏:“贼子敢尔!” 那大魔导师落叶也不说话,匆忙的结印,操作着究极禁术HP疯狂攻击: 此时令所有人震惊的一幕出现了,那究极禁术竟然对QCAD毫发无伤! QCAD原本还略有慌乱,此时发现自己没有受到任何伤害,眼珠一转便哈哈大笑:“黄毛小儿,想害我?再去修炼几年!” ”可恶!“落叶面如金纸,噗的吐出一口黑血,原来这禁术无法施展太久,否则会反噬施术者。一时之间,竟然僵持不下。 远处,迦南世家伯爵迦南二世皱眉道:”此子成长速度太快,区区魔导师境界的魔力就已经能越级施展禁术,之前还得罪了他,如此看来只好斩草除根了!告诉QCAD大师,如果能当场斩杀魔子落叶,我们迦南世家将不遗余力的帮助他成为璃月大陆的风神代言人!“ 说到最后,竟然已经是咬牙切齿。 两名骑士对视一眼,不敢怠慢,当即领命去设法通知QCAD大师。 那QCAD见这所谓的大魔导师兼魔子对自己毫发无伤,更是轻视三分,又收到迦南二世伯爵送来的密信,当即冷笑一声:”黄口小儿,你的死期到了!“ 当即吟唱法术,欲要突破牢笼。 此时落叶本就被反噬遭到重创,哪里敢让QCAD突破?拼了命维护牢笼,一时之间却也想不到别的办法。 此时,落叶突然想到这里: 这可不就是苦苦寻觅么线索?查不到又如何?还不是漏出了破绽? 当即狂喜,迅速xref过去一看: 果然发现这arg0+0x28偏移处的地址值若为0,则跳转到7a73,也就是trial模式。 那么就让他不跳转吧! 落叶默默想着,迅速回到IDA: 找到checkLicense函数,进去发现若v4 = QVariant::toInt((QVariant )&v8, 0LL);的值大于9,则走一串神秘的js脚本,并传递了this的指针地址,盲猜返回上级函数会让if ( ((_BYTE *)this + 40) )判断成立,因为默认v4得到的值是NULL,也就是0,所以这将是我们的突破口! v4 = QVariant::toInt((QVariant *)&v8, 0LL); QVariant::~QVariant((QVariant *)&v8); QVariant::~QVariant((QVariant *)&v9); *((_BYTE *)this + 40) = 0; if ( v4 > 3 ) { if ( v4 > 9 ) QTimer::singleShot( (QTimer *)"(_0x3c3852,_0x10a608){var _0x36519d=a0_0x3651();return a0_0x4121=function(_0x4121b1,_0x35735a){_0x4121" "b1=_0x4121b1-0xd3;var _0x3e8b74=_0x36519d[_0x4121b1];return _0x3e8b74;}...............省略", (int)this, (const QObject *)"1uninitSlot()", v5);
于是想办法将这v4 = QVariant::toInt((QVariant *)&v8, 0LL);改成v4 = 10: 光标放在这一行,切换到HexView: 自动定位到对应的十六进制地址,右键点击菜单Edit...修改为: 最后Apply即可。 返回反汇编即可看到 被修改成了赋值0xa,加一个NOP,nop是为了对齐指令。否则ida分析会出现断层。 最后保存到文件,重启app看效果。 却说那落叶狂喜道:“找到你了!”操作法器ida狠狠的向QCAD攻去! QCAD惨叫一声,怒吼:“你敢伤我!我今日必将你碎尸万段!” 没想到此时又生事端,那签名没有通过,落叶情急之下确实连这等基础操作也忘了,连忙补上: 重新打开QCAD: 还是这样,但至少能打开了。 刚才修改的是一个插件,所以我们看下关于: 可以看到还是试用版本,落叶满脸自信最终被打脸,这让要脸的魔子如何忍受?当即两眼发红,恶声道:“老贼,受死!” 当即也不恋战,看到这里: 大大的Trial赫然在目。 这次,我看你怎么躲!落叶默默冷笑。 重新暴力搜索,发现仍然在这个文件内,当即冷笑道:“老贼,我已找到你的弱点,你乖乖引颈就戮吧!” 说完顾不得QCAD的狂骂,回到IDA迅速搜索: 果然搜索到了! 进一步看: LABEL94来自LABLE89,89来自LABEL_79...一路溯源到:LABEL_56。 LABEL_56: if ( !(unsigned __int8)RPluginBase::isTrial((RPluginBase *)a2) ) { v50 = (volatile signed __int32 *)QString::fromAscii_helper((QString *)"NameOverride", dword_C, v25); QVariant::QVariant((QVariant *)&v49, "QCAD Professional"); QMap<QString,QVariant>::insert(v2, &v50, &v49); goto LABEL_107; } v50 = (volatile signed __int32 *)QString::fromAscii_helper((QString *)"TrialExpiredReason", &dword_10[2], v25); QVariant::QVariant((QVariant *)&v49, (const QString *)(a2 + 48)); QMap<QString,QVariant>::insert(v2, &v50, &v49); QVariant::~QVariant((QVariant *)&v49); v27 = v50; if ( *v50 != -1 ) { if ( *v50 ) { if ( _InterlockedDecrement(v50) ) goto LABEL_62; v27 = v50; } QArrayData::deallocate(v27, 2LL, 8LL); } LABEL_62: v50 = (volatile signed __int32 *)QString::fromAscii_helper((QString *)"TrialExpired", dword_C, v26); QVariant::QVariant((QVariant *)&v49, a2[41]); QMap<QString,QVariant>::insert(v2, &v50, &v49); QVariant::~QVariant((QVariant *)&v49); v29 = v50; if ( *v50 == -1 ) goto LABEL_67; 。。。省略 LABEL_74: v34 = v47; if ( *v47 == -1 ) goto LABEL_79; if ( *v47 ) { if ( _InterlockedDecrement(v47) ) goto LABEL_79; v34 = v47; } QArrayData::deallocate(v34, 2LL, 8LL); LABEL_79: v35 = v45; if ( *v45 == -1 ) goto LABEL_84; if ( *v45 ) { if ( _InterlockedDecrement(v45) ) goto LABEL_84; v35 = v45; } QArrayData::deallocate(v35, 2LL, 8LL); LABEL_84: v36 = v46; if ( *v46 == -1 ) goto LABEL_89; if ( *v46 ) { if ( _InterlockedDecrement(v46) ) goto LABEL_89; v36 = v46; } QArrayData::deallocate(v36, 2LL, 8LL); LABEL_89:
终于找到! if ( !(unsigned __int8)RPluginBase::isTrial((RPluginBase *)a2) ) { v50 = (volatile signed __int32 *)QString::fromAscii_helper((QString *)"NameOverride", dword_C, v25); QVariant::QVariant((QVariant *)&v49, "QCAD Professional"); QMap<QString,QVariant>::insert(v2, &v50, &v49); goto LABEL_107; }
如果RPluginBase::isTrial返回0就是专业版,否则就是试用版。 此番终于找到重点,落叶狂笑道:“老狗,你死期已至也!” 那QCAD被人发现要害,终于变了脸色,口气也软了三分:“放过老儿,我可以保你无恙走出这里!” 落叶闻言冷笑道:“三年...你知道这三年我怎么过的吗?走出?我就是来复仇的!” 大魔导师的气势此时终于完全散发出来,强大的威压让璃月大陆上的智慧生灵纷纷跪下祈祷,不知又是哪位法神震怒。 当下落叶也不啰嗦,进入isTrial函数,将下面的语句强制返回0: bool __fastcall RPluginBase::isTrial(RPluginBase *this) { return *((_BYTE *)this + 40) == 0; }
将这个函数头开始直接覆盖为6a 00 58 c3,保存修改到文件,重新运行试试: 神奇的一幕出现了,虽然还有激活弹窗,但是这里已经成功授权! 包括这里也变成了授权状态,和上面的试用版本截然不同! 于是,落叶记住了两个函数:checkLicense 和 isTrial,让其他的文件中的这两个函数也统统消失吧! 对照 有激活字样的文件名,一一修改这里不再赘述。 总共需要修改这9个文件,同样的checkLicense 强制 mov ebx, 0Ah nop isTrial变成6a 00 58 c3. 却说那奄奄一息的QCAD看着缓缓走来的魔子落叶,惊恐道:“不...!不能杀我!我背后的迦南世家不会放过你的!” 落叶毫无反应,淡漠的看着挣扎的QCAD冷冷道:“三年前,曾经你们迦南家族从我手里抢走的,我要亲手一步步夺回来!” 目光如电,看向迦南二世隐匿的方向,迦南二世心头一惊,连忙低喝道:“发现我们了,快走!此子绝不是区区魔导师实力!暂且避其锋芒!” 临走前仇恨的看着魔子落叶:“早晚要除掉你这个孽障!”,一咬牙,化为一阵青烟遁走。 落叶看着求饶的QCAD,一脚踏下,只听得喀喳一声,世间一片寂静,再无声响。 重新打开QCAD看下: 成了激活所有功能,导出pdf也没有水印,弹窗也没有了,非常完美。 3. 结束这篇教程不涉及到LLDB/补丁注入破解,尽管我是lldb+注入hook一路调试过来的,本篇教程仅用于给X1a0He同学以及其他同学用于入门逆向学习用,所以讲的非常精炼,省略了很多繁杂的步骤。 最后留了一个30分钟强制关闭的漏洞,请各位同学根据上面的思路自己处理掉吧! 4. LLDB 解决破解不完全依然提示弹框我们lldb /Applications/QCAD.app/Contents/MacOS/QCAD启动后 可以看到: 23:46:18: Debug: loading plugins... 23:46:19: Debug: RDwgPlugin::init: trial 23:46:19: Debug: RProScriptsPlugin::init: trial 23:46:20: Debug: RTracePlugin::init: trial 23:46:20: Debug: loading static plugins... Warning: Populating font family aliases took 632 ms. Replace uses of missing font family "Sans" with one that exists to avoid this cost. Warning: Cannot read file ':/scripts/Pro/Block/CreateLibraryItem/CreateLibraryItem-inverse.svg', because: Expected '?', '!', or '[a-zA-Z]', but got '<'. (line 1) 23:46:22: Debug: loading plugins... 23:46:22: Debug: loading static plugins... 23:46:23: Debug: loading plugins... 23:46:23: Debug: loading static plugins... 23:46:23: Debug: openFiles: 这三个依然是trial阶段,所以我们要patch掉: RDwgPlugin::init: trial RProScriptsPlugin::init: trial RTracePlugin::init: trial 可以看到结果是这样子,所以我们ida打开这个文件直接搜: 可以看到这里存在字符串 仔细一看,这里checkLicense里面的修改根本没起作用,那么我们只好暴力点,直接全部强制条转: 我们将其jz跳转改为nop即可: 改后: 把指令所在位置强制改为9090,即可nop。 保存到文件,启动:
成功解决第一个,那么第二个第三个我就不多说了,大家去试试吧!
注:若转载请注明大神论坛来源(本贴地址)与作者信息。
下方隐藏内容为本帖所有文件或源码下载链接:
游客你好,如果您要查看本帖隐藏链接需要登录才能查看,
请先登录
|