|
|
发表于
2022-5-11 19:08:23
来自手机
|
显示全部楼层
| 阅读模式
来自 马来西亚
前言:
前几天在MT求助区看到一篇求破帖子,对于求破的我从来都不会提供协助,但这不影响我把软件下来玩。
https://bbs.binmt.cc/thread-85240-1-1.html
结果发现挺适合作为教学题材。今天就用它玩吧。
课前准备:
1.apk反编译工具 (教学使用MT)
2.一款短信轰炸 (今日主角)
3.抓包工具 (黄鸟)
3.编程基础
4.还有爆米花
其实吧,什么软件并不重要,重要的是题材内容是否让你有受益。
此次教程分为3种玩法
-日常玩法
-引流玩法
-商业玩法
课程:
-日常玩法
也许大部分人一开始接触破解的目的都很单纯,想白漂这软件,所以接触了破解。
至于我初接触的时候,是在2006年,那时候仅觉得好玩。所以从渗透到破解都接触了。
一开始也没有太多心思,纯属为了玩。然后就会试着去破解,从中追求成功后的喜悦并提升自身的技术能力。
併坚着日常玩法,只为了学术研究。
至于软件并无难度,但为了剧情发展,就过一遍破解。
1.软件为卡密登录,连网验证,可以通过抓包作为入手点。
开启黄鸟进行抓包,随意输入卡密并点击登录。
图中可以发现提示"卡密不存在"
2.前往黄鸟查看抓包信息,结果发现数据都经过加密,无法直接查看内容。
请求链接

请求数据
响应结果

3.由于数据经过加密,导致无法直接从数据里寻找关键信息。那就从请求链接试试吧。
在请求链接可以发现,id参数是用来进行不同的请求,这里变量内容是kmlogon,为请求登录验证。

4.使用MT反编译并搜索kmlogon,得出4条结果。这里先说下此软件功能。
软件是一款短信轰炸,主要有2个功能,qq查绑和短信轰炸,短信轰炸分为本地和云端2种功能,合计这里就有3个验证和1个登录验证,一共会有4次验证卡密。
但是现在是需要先绕过登录验证,所以选择第一条结果进行分析。
5.为了方便讲解,这里转为java模式。
-从橘色线可以发现,请求和响应数据都是经过rc4算法加密,密钥为 b4pz8eNP3efcwaw11266
-从代码里可以看到一共有2个判断,分别为蓝色和黄色线。
-黄色线主要判断请求数据是否过期。
-蓝色线为关键判断,判断返回码是否为1428,是则登录成功。然而我们并非正版手段,所以不可能得到1428的返回码。
-再往下看有2条线,分别是红和绿,当卡密不存在,就会执行红线代码。当卡密正确,就会执行绿线代码。
-从这2条代码可以发现,区别仅仅只是调用2条不同接口。当验证成功,调用main$4$2,失败则调用main$4$3。
6.所以只需将main$4$3替换成main$4$2即可。这样就完成了登录
修改前
修改后
7.接下来还有3个功能都会经过卡密验证才能使用,所以都需要一一修改。
下图分别为3个功能验证的位置
轰炸功能(本地)
轰炸功能(云端)

QQ查绑
8.从之前登录分析中提过,当返回码为1428即为验证成功。所以只需要强制让软件认为返回码是1428即可。
分别将3处验证的返回码改为1428即可解锁功能。
修改前

修改后

9.到这里其实已经破解完所有功能了。现在可以打包测试了。找了小伙伴测试,功能一切正常。至此破解完成。
引流玩法
-引流玩法:
这一玩啊,就玩了6年,从电脑到手机,天天都在研究各种加密手段。最疯狂时期,一个月内破解了上百款电脑程序,就因为这样收过版权警告,也收过律师函,未了避免不必要的纠纷,后来转玩外挂破解。才发现外挂加密手法更有意思。让我有了新的认知。然而我并不怎么玩游戏,外挂对于我的实用性不大。
直到2012-2013年左右,看着认识的人创业的创业,进企业的进企业,对此自己有了新想法,我也应该认认真真的去为未来做规划,由于我所居住的国家并没有中国互联网发达,所以逆向变成了冷门技术,不好寻找到与逆向有关的行业。当时就投了一份简历到中国的某企业,可是投完后我后悔了,父母在,不远行。我不想离父母太远。我就盼着简历泡汤吧,结果有天负责人说要和我网上进行面试,但当时我已决定不去了,就敷衍了对方。还害了小伙伴被领导训了一顿。
后来决定另寻他路,找各种项目,为了提高自己的业界知名度,我走上了引流之路,对软件的破解从单纯到有意图的破解。
所以让我们开始引流玩法吧
1.从日常玩法中,已知软件是连网验证,并经由rc4加密,那就把对方的授权验证改为自己的授权吧。也已知授权验证地址为wy.llua.cn,那么就使用mt修改成自己的服务器地址吧。
修改前
修改后(bomb为我服务器的对应目录)
2.接下来就要仿造每一条请求的响应数据,从第一条开始顺着仿吧。仿之前得先解密,已知加密方式为rc4,也在日常玩法里得到了密钥b4pz8eNP3efcwaw11266
首先第一条链接id=ini
get模式发送请求
加密数据
解密后得知是检测版本更新
3.接着看第二条,可以发现2,5,6,7条都是来自kmlogon的变量,说明结果都一样。但由于没有正版卡密,所以只能从代码分析出正确的结构。不过先来看看解密前后的结果。
kmlogon是通过post方式发包
post方式就会有postfield,这里可以看到data和value两个参数
data为将数据加密后的结果
value为随机数
由于仅需要仿响应包,对于请求包基本无需做任何更改。
不过还是解密看看数据内容
解密后可以看到
kami=卡密
markcode = 用户id
t= 当前时间戳
sign= 服务器验证数据有效性的标记
接着看看响应包
解密后可看见错误验证的返回结果
code= 返回码
msg= 提示信息
time= 时间戳
check= 一串md5标记
4.由于返回结果是错误的,所以得反编译apk进行分析,看看正确的响应包结果。
反编译后直接对登录验证代码进行分析
以下为对代码进行解读
- @Override
- public void run() {
- try {
- //发出请求并获取返回数据,然后进行解密,获取解密后的json格式数据
- zf.json json = this.this$0.zf.json(rc4.decryRC4(this.this$0.wl.hq("https://wy.llua.cn/api/?id=kmlogon&app=11266", new String[]{"data=" + rc4.encryRC4String(this.val$body, "b4pz8eNP3efcwaw11266", "UTF-8"), "value=" + this.val$random}, "UTF-8"), "b4pz8eNP3efcwaw11266", "UTF-8"));
- //获取code的返回码
- JSONObject jSONObject = json.json;
- String valueOf = String.valueOf(json.hq(jSONObject, "code"));
- //获取check的信息
- String.valueOf(json.hq(jSONObject, "check"));
- //获取time的时间戳
- long parseLong = Long.parseLong(String.valueOf(json.hq(jSONObject, "time")));
- //获取msg值的内容
- String valueOf2 = String.valueOf(json.hq(jSONObject, "msg"));
- //判断time与当前时间是否仅相差30秒,少于或超过都视为无效验证
- if (parseLong - this.val$time > 30 || parseLong - this.val$time < -30) {
- this.this$0.gj.jmxc(new main$4$1(this));
- //接着判断返回码是否为1428,是则验证通过
- } else if (valueOf.equals("1428")) {
- //接着获取msg的json数据
- zf.json json2 = this.this$0.zf.json(valueOf2);
- JSONObject jSONObject2 = json2.json;
- this.this$0.wj.xrwb("/storage/emulated/0/BRkm.log", this.val$km);
- //如果是正版卡密,msg值是一个包含vip值的数组,而不是字符串数据
- long parseLong2 = Long.parseLong(String.valueOf(json2.hq(jSONObject2, "vip")));
- //然后再获取vip到期时间 this.this$0.gj.sc(Long.valueOf(parseLong2));
- String SJC = rc4.SJC(Long.valueOf(parseLong2));
- this.this$0.gj.sc(SJC);
- this.this$0.gj.jmxc(new main$4$2(this, SJC));
- } else {
- this.this$0.gj.jmxc(new main$4$3(this, valueOf2));
- }
- } catch (Throwable th) {
- }
- }
- }
复制代码
从解密过程得知,错误响应包的msg是一个value值而不是一个数组,所以需要进行修改。
修改前
- {"code":149,"msg":"卡密不存在","time":1652253584,"check":"1df6e6275bbe0c97cd323a5ebf26d366"}
复制代码
修改后(需包含vip到期时间)
- {"code":1428,"msg":{"vip":1964875325},"time":1652253584,"check":"1df6e6275bbe0c97cd323a5ebf26d366"}
复制代码
5.最后剩下2条请求,第3条komunmachine是解绑请求,无需解绑功能,直接抄返回信息即可。接着最后一条为notice请求,即登录后的公告提示信息。这里可以改为自己需要的内容。这2部就不掩饰了。
6.分析完毕后,接下来就要编写服务器代码,这里使用php编写
新建bomb目录

接着再建个index.php文件

打开index.php写入以下代码并保存。
- <?php
- //强制content-type类型
- header("Content-type: text/html; charset=utf-8");
- //忽略错误
- error_reporting(0);
- //利用id来区分请求数据
- $id = $_GET["id"];
- //app = 获取软件版本号
- $app = $_GET["app"];
- //获取10位时间戳
- $timestamp = time();
- //随机生成check值
- $check = md5($timestamp);
- //这里简单弄个用户验证,大量可以使用database 或直接弄成卡密生成模式
- $userdata = array("120570033436643|1922368643", "imei|timestamp");
- //ini = 初始化检测版本更新,这里判断id是否为ini
- if(strcmp($id, "ini") === 0){
- //这里判断版本号是否小于最新版本号,是则提示更新
- if($app < 11266){
- //返回rc4加密后的数据
- die(bin2hex(rc4("b4pz8eNP3efcwaw11266", '{"code":200,"msg":{"version":"11300","version_info":"","app_update_show":"增加服务器,让速度更快","app_update_url":"http://update.xxx.com/new.apk","app_update_must":"y"},"time":'.$timestamp.',"check":"'.$check.'"}')));
- }else{
- //返回rc4加密后的数据
- die(bin2hex(rc4("b4pz8eNP3efcwaw11266", '{"code":200,"msg":{"version":"1","version_info":"","app_update_show":"增加服务器,让速度更快","app_update_url":"","app_update_must":"n"},"time":'.$timestamp.',"check":"'.$check.'"}')));
- }
- //kmlogon = 登录验证
- }else if(strcmp($id, "kmlogon") === 0){
- //解密data
- $data = rc4("b4pz8eNP3efcwaw11266", hex2bin($_POST["data"]));
- //正则提取markcode
- preg_match('/markcode=(.*?)&/mi', $data, $m);
- //验证用户是否在数据库里
- for ($i=0; $i < count($userdata); $i++){
- $splitdata = explode("|", $userdata[$i]);
- if(strcmp($m[1],$splitdata[0]) === 0){
- die(bin2hex(rc4("b4pz8eNP3efcwaw11266", '{"code":1428,"msg":{"vip":'.$splitdata[1].'},"time":'.$timestamp.',"check":"'.$check.'"}')));
- }else{
- die(bin2hex(rc4("b4pz8eNP3efcwaw11266", '{"code":149,"msg":"进群领取: 940944972","time":'.$timestamp.',"check":"'.$check.'"}')));
- }
- }
- //kmunmachine = 解绑卡密
- }else if(strcmp($id, "kmunmachine") === 0){
- //没写卡密验证,这里就不多做处理
- die(bin2hex(rc4("b4pz8eNP3efcwaw11266", '{"code":149,"msg":"此功能未开放","time":'.$timestamp.',"check":"'.$check.'"}')));
- //notice = 公告信息
- }else if(strcmp($id, "notice") === 0){
- die(bin2hex(rc4("b4pz8eNP3efcwaw11266", '{"code":200,"msg":{"app_gg":"更多精彩内容 尽在GNet云搜"},"time":'.$timestamp.',"check":"'.$check.'"}')));
- }
- //rc4是公开的加密算法,网上有现成代码直接使用,这里就不细说
- function rc4($pwd, $data)
- {
- $key = array();
- $box = array();
- $cipher = '';
- $pwd_length = strlen($pwd);
- $data_length = strlen($data);
- for ($i = 0; $i < 256; $i++)
- {
- $key[$i] = ord($pwd[$i % $pwd_length]);
- $box[$i] = $i;
- }
- for ($j = $i = 0; $i < 256; $i++)
- {
- $j = ($j + $box[$i] + $key[$i]) % 256;
- $tmp = $box[$i];
- $box[$i] = $box[$j];
- $box[$j] = $tmp;
- }
- for ($a = $j = $i = 0; $i < $data_length; $i++)
- {
- $a = ($a + 1) % 256;
- $j = ($j + $box[$a]) % 256;
- $tmp = $box[$a];
- $box[$a] = $box[$j];
- $box[$j] = $tmp;
- $k = $box[(($box[$a] + $box[$j]) % 256)];
- $cipher .= chr(ord($data[$i]) ^ $k);
- $cipher1 = base64_encode($cipher);
- }
- return $cipher;
- }
- ?>
复制代码
7.最后还需要对apk包再做些修改,因为作者写死了公告信息,所以要让他能实现连网获取。搜索字符并删除图中标记的几行即可。
8.对于apk包这里再总结一下
-需改服务器链接为自己的链接
-需要公告信息
完成后打包就是引流版本了
商业玩法
-商业玩法:
引流之后的一年里,断断续续接了几个项目,直到2014年尾,获得了一个长期项目,跨境合作,时间自由,远端工作,就这样维持了好几年,本以为我也逐渐淡出了互联网。结果2019因为疫情影响,业绩大不如前,最后宣告解散。
由于这几年长期负责幕后,没有了自己的关系链,解散后游手好闲了一段时间。
2020年尾却传来了噩耗,父亲病逝,交托于我这个家,让我无法再继续这样下去,我重拾遗忘的破解,接触着新的知识,继续奔波在人群中。
这时候的想法出现了质上的变化,不再以技术为主,而是以生活为本,打理好这一个家。
所以技术最终变成了为商而动。
所有光鲜亮丽的背后,都有一段脏兮兮的故事。
接下来就把别人的东西变成自己的东西吧,所以扒人家东西就离不开爬虫技术。
但此次教学只是个简单的演示,请自行举一反三,也并非鼓励此种做法,仅只是有时候业务需要而已。
1.从上面分析过程,得知软件里有2个功能,QQ查绑和短信轰炸,2个功能都需要连网使用,脱离软件它依然可以正常运作。所以主要做法是将这两个功能提取出来放到自己写好的壳里。
2.同样的先来抓包,首先抓取qq查绑

3.获取了请求链接,浏览器访问看看
https://zy.xywlapi.cc/qqapi?qq=
可以看见是一个免费的api接口
只需要对接到自己的程序里即可。
4.接下来抓轰炸接口
lx= 轰炸模式 0本地 1云端
phone= 骗子手机号码
sign= 验证链接有效性。
提交成功后返回信息
5.需要模拟请求就必须解开sign的加密,就得从apk里分析sign如何形成。
搜索154.86.26.81定位到关键处
这里只提取算法部分解释
- //获取当前10位时间戳
- String valueOf = String.valueOf(System.currentTimeMillis() / 1000);
- //加密格式 md5(手机号|当前时间戳 + [BRnb])
- //小写md5
- String encodeMD5 = rc4.encodeMD5(String.valueOf(this.val$phone) + "|" + valueOf + "[BRnb]");
- //加密格式 base64_encode(base64_encode(base64_encode(base64_encode(当前时间戳|上面的md5值|md5(手机号)))))
- //小写md5
- String hq = main2.5.access$0(this.this$1).wl.hq("http://154.86.26.81/port/?lx=0&phone=" + this.val$phone + "&sign=" + rc4.encoder(rc4.encoder(rc4.encoder(rc4.encoder(String.valueOf(valueOf) + "|" + main2.5.access$0(this.this$1).zf.zhxx(encodeMD5) + "|" + rc4.encodeMD5(this.val$phone))))), "UTF-8");
复制代码
6.sign的加密已处理完毕,现在可以套在自己的程序里使用了,有需要的请自行编写,这里就不编写了,主要懒惰弄ui。
成品图:
后记: 远离非法行为,教学只是演练,所有非法行为与本教学无关。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
-
查看全部评分
总评分:好评 +21
金币 +21
|