本帖最后由 winding 于 2018-3-17 17:08 编辑
(接一楼)
随便打开一个看看
[JavaScript] 纯文本查看 复制代码 {
"version":27,
"tile":[["11","11","11","0","0","0","11","11","11"],
["11","0","0","0","0","0","0","0","11"],
["11","0","0","0","0","0","0","0","11"],
["0","0","0","11","0","11","0","0","0"],
["0","0","0","0","0","0","0","0","0"],
["0","0","0","11","0","11","0","0","0"],
["11","0","0","0","0","0","0","0","11"],
["11","0","0","0","0","0","0","0","11"],
["11","11","11","0","0","0","11","11","11"]],
"items":[["0","0","0","0","0","0","0","0","0"],
["0","0","0","0","0","0","0","0","0"],
["0","0","0","0","0","0","0","0","0"],
["0","0","0","0","22","0","0","0","0"],
["0","0","0","22","23","22","0","0","0"],
["0","0","0","0","22","0","0","0","0"],
["0","0","0","0","0","0","0","0","0"],
["0","0","0","0","0","0","0","0","0"],
["0","0","0","0","0","0","0","0","0"]],
"clay":[["0","0","0","2","2","2","0","0","0"],
["0","2","2","2","2","2","2","2","0"],
["0","2","2","2","2","2","2","2","0"],
["2","2","2","0","2","0","2","2","2"],
["2","2","2","2","2","2","2","2","2"],
["2","2","2","0","2","0","2","2","2"],
["0","2","2","2","2","2","2","2","0"],
["0","2","2","2","2","2","2","2","0"],
["0","0","0","2","2","2","0","0","0"]],
"stepLimit":"26",
"targets":[{"type":"3","code":"1","num":"57"}],
"ruleDefinitions":
{
"Initialization":[{"code":"1","weight":"10"},{"code":"501","weight":"5"},{"code":"4","weight":"10"},
{"code":"5","weight":"10"},{"code":"6","weight":"10"}],
"Rule1":[{"code":"1","weight":"10"}],
"Rule2":[{"code":"1","weight":"10"},{"code":"2","weight":"10"},{"code":"3","weight":"10"},
{"code":"5","weight":"10"},{"code":"6","weight":"10"}],
"SweetTimeRule":[{"code":"2","weight":"10"},{"code":"3","weight":"10"},{"code":"1","weight":"10"},
{"code":"4","weight":"10"},{"code":"5","weight":"10"},{"code":"6","weight":"10"}]
},
"spawnTiles":
[
{"x":"0","y":"3","rule":"Initialization"},{"x":"1","y":"1","rule":"Initialization"},{"x":"2","y":"1","rule":"Initialization"},
{"x":"3","y":"0","rule":"Initialization"},{"x":"4","y":"0","rule":"Initialization"},{"x":"5","y":"0","rule":"Initialization"},
{"x":"6","y":"1","rule":"Initialization"},{"x":"7","y":"1","rule":"Initialization"},{"x":"8","y":"3","rule":"Initialization"}
],
"playMode":"0",
"hitPoints":"30",
"starScoresNew":["29720","40407","43880"],
"restStepScoreNew":"3000"
}
"playMode"是游戏模式,0的代表普通消除关卡,"targets":[{"type":"3","code":"1","num":"57"}],这个是目标,正则替换就好了,保留一种类型,数量num=1,或者直接num=0。playMode=1是打到女巫模式,"witchHitPoints":"120",是女巫血量(这时targets表示会对女巫产生打击的种类和点数),改成0。好了,打开即通关,感觉偶已经无敌了。。。。吼吼吼。。。。朋友还需要把前700关逐一点开一遍。。。咳咳咳
(四)账号绑定
游戏里有绑定微信的功能,点击提示只有oppo游戏中心版本可以绑定,可能有检测。试验的时候,先绑定正版,卸载正版再绑定逆向版,竟然成功了,顿时没有逆向的欲望了。BABY,拿着破解版去朋友圈争锋吧,你是无敌的,嘿嘿嘿。
三、扩展
(一)未回答的疑惑
疑惑一的解答(讨论):androidkiller反编出来活动灰色点不开,几种情况。(1)加壳了,先检查有无壳;(2)多个dex,灰色点不开的到第二个第三个smali文件夹里找找;(3)在jar包里,曾经碰到过;(4)在伪装的jar、so文件里,后缀名不一定准确,有时候故意改了;(5)其他地方,本例中的在哪里偶也没找到,或者用文件管理器到模拟器安装目录下找找?
疑惑三的解答(讨论):有时候app保留的LOG,都在一些包里,跟疑惑二类似。本例中,类似o_a等的LOG输出,有时跟nearme牵扯着,可搜不到,nearme包下也没有。想起来assets有个nearme文件夹,下边有个oppo_game_service_200604.so。拖到ida里,竟然直接弹出这个
分明是个apk文件,改文件名,拖进andiodkiller里
果然在这里。那么,这里也可以搞事情了,嘿嘿,我就不测试了。
(二)关于injectlog的使用
强调一下偶是借用,这是别人的成果,原贴在一楼。偶主要和同是小白的坛友们说一下一些坑和改进。
A.首先,需要自己编译和反编,得到InjectLog.smali。原贴没提供,这个是偶反编的。
[Asm] 纯文本查看 复制代码 .class public Lcom/hook/testsmali/InjectLog;
.super Ljava/lang/Object;
.source "InjectLog.java"
# direct methods
.method public constructor <init>()V
.locals 0
.prologue
.line 3
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
.method public static PrintFunc()V
.locals 6
.prologue
.line 7
invoke-static {}, Ljava/lang/Thread;->currentThread()Ljava/lang/Thread;
move-result-object v0
.line 8
.local v0, "cur_thread":Ljava/lang/Thread;
invoke-virtual {v0}, Ljava/lang/Thread;->getStackTrace()[Ljava/lang/StackTraceElement;
move-result-object v1
.line 9
.local v1, "stack":[Ljava/lang/StackTraceElement;
const-string v2, "InjectLog"
new-instance v3, Ljava/lang/StringBuilder;
invoke-direct {v3}, Ljava/lang/StringBuilder;-><init>()V
const/4 v4, 0x3
aget-object v4, v1, v4
invoke-virtual {v4}, Ljava/lang/StackTraceElement;->toString()Ljava/lang/String;
move-result-object v4
invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v3
const-string v4, "["
invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v3
invoke-virtual {v0}, Ljava/lang/Thread;->getId()J
move-result-wide v4
invoke-virtual {v3, v4, v5}, Ljava/lang/StringBuilder;->append(J)Ljava/lang/StringBuilder;
move-result-object v3
const-string v4, "]"
invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v3
invoke-virtual {v3}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v3
invoke-static {v2, v3}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
.line 10
return-void
.end method
B.用python把对以上print方法的调用插进每个smali方法中,原贴作者提供了py代码,原代码偶就不贴了。里面几个坑:python要用3.0以上版本,不然clear()方法不支持;编码统一为UTF8,并去掉汉字,不懂编码咋这么乱;如果自己修改py文件,不要用tab键,用空格;原作者代码中遇到没有.prologue的错误处理,会中断执行,把错误处理注释掉。
C.把InjectLog.smali文件保存到相应位置。
D.每次操作都麻烦,偶凑了个批处理,作为androidkiller的自定义工具。
[Asm] 纯文本查看 复制代码 @echo off
color 0A
echo ===========injectlog===========
:start
cls
set current_dir=%~dp0
pushd %current_dir%
:start
echo.请输入要注入LOG的逆向工程名称(对于ak,是apk 的文件名)
set /p inputgc=
if not exist .\projects\%inputgc%\ (
echo "工程文件夹不存在"
goto start
)
xcopy smalihook.py /y .\projects\%inputgc%\Project\smali\
set do_dir=.\projects\%inputgc%\Project\smali\
pushd %do_dir%
call python.exe smalihook.py
del smalihook.py
pushd %current_dir%
xcopy InjectLog.smali /y .\projects\%inputgc%\Project\smali\com\hook\testsmali\
if exist .\projects\%inputgc%\Project\smali_classes2\ (
echo "存在dex2,继续处理"
rem goto starttwo
) else (
goto done
)
:done
echo "已处理完毕"
pause
exit
:starttwo
xcopy smalihook.py /y .\projects\%inputgc%\Project\smali_classes2\
set did_dir=.\projects\%inputgc%\Project\smali_classes2\
pushd %did_dir%
call python.exe smalihook.py
del smalihook.py
pushd %current_dir%
xcopy InjectLog.smali /y .\projects\%inputgc%\Project\smali_classes2\com\hook\testsmali\
goto done
是个半成品,对多dex的处理没弄完。
E.原作者的py脚本实际使用的时候还有些问题,做了一些改进。
[Asm] 纯文本查看 复制代码 import os
class ParserError(Exception):
pass
#
def inject_code_to_method_section(method_section):
#
if method_section[0].find("static constructor") != -1:
return method_section
#
if method_section[0].find("synthetic") != -1:
return method_section
#
if method_section[0].find("abstract") != -1:
return method_section
#
inject_code = [
'\n',
' invoke-static {}, Lcom/hook/testsmali/InjectLog;->PrintFunc()V\n',
'\n'
]
#
for i in range(0, len(method_section)):
if method_section[i].find(".prologue") != -1:
method_section[i + 1: i + 1] = inject_code
return method_section
#
for ii in range(0, len(method_section)-1):
if len(method_section[ii].strip())!= 0 and len(method_section[ii+1].strip()) == 0 :
method_section[ii + 1: ii + 1] = inject_code
return method_section
return method_section
def inject_log_code(content):
new_content = []
method_section = []
is_method_begin = False
for line in content:
if line[:7] == ".method":
is_method_begin = True
method_section.append(line)
continue
if is_method_begin:
method_section.append(line)
else:
new_content.append(line)
if line[:11] == ".end method":
if not is_method_begin:
raise ParserError(".method error")
is_method_begin = False
new_method_section = inject_code_to_method_section(method_section)
new_content.extend(new_method_section)
method_section.clear()
return new_content
def main():
walker = os.walk("./")
for root, directory, files in walker:
for file_name in files:
if file_name[-6:] != ".smali" or file_name[:5] == "Cocos":
continue
file_path = root + "/" + file_name
print(file_path)
file = open(file_path,'r',encoding='UTF-8')
lines = file.readlines()
file.close()
new_code = inject_log_code(lines)
file = open(file_path, "w")
file.writelines(new_code)
file.close()
if __name__ == '__main__':
main()
主要是1.跳过cocos2文件,应该这些东西即使不做任何操作,也经常调用,LOG会晃眼;2.脚本有的app会做处理,没有.prologue,本例就是这样,这种情况下会原作者的py脚本会跳过去,那么这个方法是否执行就不知道了,如果不能保证100%知道程序执行逻辑,这个神器的作用就打折扣了。偶改了下逻辑判断,如果存在.prologue就插在.prologue后第一行,如果不存在.prologue,就从方法开始,插到第一个空行。smali文件中方法的头部信息,和正式代码之间,都存在一个空行,嘿嘿。
|