业余时间写的,纯兴趣更新!
运行apk,随便输入,点击确定,弹框错误。
将其拖入jeb中,查看类MainActivity中的onCreate方法。
即调用了checkSN方法。参数1为 "Tenshine",参数2为我们输入的字符串。
看下checkSN的实现(具体看代码中的分析)
安装apk安装失败
将其拖入jadx发现AndroidManifest.xml清单文件没有内容
应该是AndroidManifest.xml文件被做了手脚。将其提取出来进行修改。
apktool提取失败。
把apk后缀改成zip,将其拉出来。
找三个正常的清单文件(apk逆向,app1,app2),查看它们文件头哪些是共同的地方。
然后再查看下本题
所以这里我们将不一致的地方改为一致,即第一行的偏移0x6-0xB位置和第三行的偏移为偏移0x1-0xF
将其再覆盖掉apk中的清单文件,然后便可以安装成功了.
但安装成功后,却没有显示桌面图标.使用am进行打开Mainactivity界面
同时看下logcat
先不点安装,点空白处。
点击注册
这里填过信息后点注册一直报错"请输入正确的身份证"。
本想好好分析下代码,可我懒死了.
修复过AndroidManifest.xml文件后拖入jadx中,再看下清单文件中的内容。发现可疑的字符串,其实就是flag。
附件是个zip压缩包,解压后
查看FoundItFun.docx,发现只有一句话。
jadx
水啊水啊,如果checkSN方法返回true,则注册成功。
checkSN
什么都不输入就会返回true的,返回successed对应的字符串。
对其进行解密得到
MD5免费在线解密破解_MD5在线加密-SOMD5
但最终的flag需要在后面再添加上ANDROID即
脑洞,无聊。
jadx
如果getSecret(getFlag())的返回值和getSecret(encrypt(sInput)))相等就证明Success。
即getFlag()的返回值和encrypt(sInput))返回值相等,就证明Success。
这这两个函数都是在phcm的so库中实现的。
所以分析下so库中的这两个函数
首先这里是getFlag函数,静态分析太累,动态分析太懒,这里其实不用取分析这个算法,它的返回值是固定的,所以直接用frida去hook这个函数打印出它的返回值就好了,也可以通过向smali代码中插入log去打印。
然后看encrypt函数,将每个字符对应的ascii进行减一。
所以这里只要首先获得getFlag函数的返回值,然后再将返回值的每个字符对应的ascii进行加一即可。
利用frida去hook native层的getFlag方法的返回值。
run.py
hook.js
成功将返回值给打印出来。
然后再将返回值的每个字符对应的ascii进行加一便是我们的输入即flag
上面其实是hook的java层,也可以去hook native层,效果是一样的
native_hook.js
这里我们也尝试下通过改smali代码的方式将这个返回值给打印出来吧。
重新编译签名安装运行。成功将其打印出来。
后面就一样了。
打开后
### 分析
jadx(太好用了吧)
然后看下这个广播接收者
主要做的就是接收传过来msg值,根据值的不同会跳转到不同的Activity
ThisIsTheRealOne.class
调用了hello-jni.so中的orThat方法,参数都是固定的,没有用户输入。
IsThisTheRealOne.class
调用了hello-jni.so中的perhapsThis方法,参数也都是固定的,没有用户输入。
DefinitelyNotThisOne.class
调用了hello-jni.so中的definitelyNotThis方法,参数也都是固定的,没有用户输入。
学了hook后就懒了呢,因为整个程序都没有用户输入,flag肯定是在某个地方进行生成的,猜测是so库中的definitelyNotThis函数返回值或者是orThat函数返回值或者perhapsThis返回值。那我们直接在java层hook这三个函数好了
java_hook.py
但是现在我们还要解决个问题,我们需要跳转到上面的三个不同Activity中才可以触发hook函数,而看清单中,这三个activity都不是export,也就没办法使用am命令打开。
不过可以将它修改成export后再重新打包,或者将初始Activity指定为上面的其实一个Activity后重新打包。或者按程序逻辑发送不同的广播信息去跳转到不同的Activity中。
(32条消息) 使用am命令发送带参数的广播和服务_sunxiaolin2016的博客-CSDN博客
这里记录下
-n后面是包名/类名
但是这个apk
包名如果写com.example.application 是不行的
写成com.example.hellojni才可以,填清单文件的包名
hook效果
继续
效果
继续
效果
ok,成功拿到flag.
上面是对java层进行的hook,下面是native进行hook
public void onCreate(Bundle arg3) {
super
.onCreate(arg3);
this.setContentView(
0x7F040019
);
this.setTitle(
0x7F06001D
);
this.edit_userName
=
"Tenshine"
;
this.edit_sn
=
this.findViewById(
0x7F0C0051
);
this.btn_register
=
this.findViewById(
0x7F0C0052
);
this.btn_register.setOnClickListener(new View$OnClickListener() {
public void onClick(View arg5) {
if
(!MainActivity.this.checkSN(MainActivity.this.edit_userName.trim(), MainActivity.this.edit_sn.getText().toString().trim())) {
Toast.makeText(MainActivity.this,
0x7F06001E
,
0
).show();
}
else
{
Toast.makeText(MainActivity.this,
0x7F06001B
,
0
).show();
MainActivity.this.btn_register.setEnabled(false);
MainActivity.this.setTitle(
0x7F060019
);
}
}
});
}
public void onCreate(Bundle arg3) {
super
.onCreate(arg3);
this.setContentView(
0x7F040019
);
this.setTitle(
0x7F06001D
);
this.edit_userName
=
"Tenshine"
;
this.edit_sn
=
this.findViewById(
0x7F0C0051
);
this.btn_register
=
this.findViewById(
0x7F0C0052
);
this.btn_register.setOnClickListener(new View$OnClickListener() {
public void onClick(View arg5) {
if
(!MainActivity.this.checkSN(MainActivity.this.edit_userName.trim(), MainActivity.this.edit_sn.getText().toString().trim())) {
Toast.makeText(MainActivity.this,
0x7F06001E
,
0
).show();
}
else
{
Toast.makeText(MainActivity.this,
0x7F06001B
,
0
).show();
MainActivity.this.btn_register.setEnabled(false);
MainActivity.this.setTitle(
0x7F060019
);
}
}
});
}
private boolean checkSN(String str1, String input_str) {
boolean v7
=
false;
if
(str1 !
=
null) {
try
{
if
(str1.length()
=
=
0
) {
return
v7;
}
if
(input_str
=
=
null) {
return
v7;
}
if
(input_str.length() !
=
22
) {
return
v7;
}
MessageDigest v1
=
MessageDigest.getInstance(
"MD5"
);
v1.reset();
v1.update(str1.getBytes());
/
/
对参数
1
进行md5加密
String v3
=
MainActivity.toHexString(v1.digest(), "");
/
/
并赋值给v3
StringBuilder v5
=
new StringBuilder();
int
v4;
for
(v4
=
0
; v4 < v3.length(); v4
+
=
2
) {
/
/
将v3密文每隔一位进行舍弃
v5.append(v3.charAt(v4));
}
if
(!
"flag{"
+
v5.toString()
+
"}"
.equalsIgnoreCase(input_str)) {
return
v7;
/
/
然后拼接上flag{}再与我们的输入将进行比较。
}
}
catch(NoSuchAlgorithmException v2) {
goto label_40;
}
v7
=
true;
}
return
v7;
label_40:
v2.printStackTrace();
return
v7;
}
private boolean checkSN(String str1, String input_str) {
boolean v7
=
false;
if
(str1 !
=
null) {
try
{
if
(str1.length()
=
=
0
) {
return
v7;
}
if
(input_str
=
=
null) {
return
v7;
}
if
(input_str.length() !
=
22
) {
return
v7;
}
MessageDigest v1
=
MessageDigest.getInstance(
"MD5"
);
v1.reset();
v1.update(str1.getBytes());
/
/
对参数
1
进行md5加密
String v3
=
MainActivity.toHexString(v1.digest(), "");
/
/
并赋值给v3
StringBuilder v5
=
new StringBuilder();
int
v4;
for
(v4
=
0
; v4 < v3.length(); v4
+
=
2
) {
/
/
将v3密文每隔一位进行舍弃
v5.append(v3.charAt(v4));
}
if
(!
"flag{"
+
v5.toString()
+
"}"
.equalsIgnoreCase(input_str)) {
return
v7;
/
/
然后拼接上flag{}再与我们的输入将进行比较。
}
}
catch(NoSuchAlgorithmException v2) {
goto label_40;
}
v7
=
true;
}
return
v7;
label_40:
v2.printStackTrace();
return
v7;
}
import
hashlib
str1
=
b
"Tenshine"
str2
=
hashlib.md5(str1).hexdigest()
print
(str2)
flag
=
""
for
i
in
range
(
len
(str2)):
if
(i
%
2
=
=
0
):
flag
+
=
str2[i]
print
(flag)
import
hashlib
str1
=
b
"Tenshine"
str2
=
hashlib.md5(str1).hexdigest()
print
(str2)
flag
=
""
for
i
in
range
(
len
(str2)):
if
(i
%
2
=
=
0
):
flag
+
=
str2[i]
print
(flag)
>apktool d APK逆向
-
2.apk
I: Using Apktool
2.6
.
1
on APK逆向
-
2.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
Exception
in
thread
"main"
brut.androlib.err.RawXmlEncounteredException: Could
not
decode XML
at brut.androlib.res.decoder.XmlPullStreamDecoder.decode(XmlPullStreamDecoder.java:
145
)
at brut.androlib.res.decoder.XmlPullStreamDecoder.decodeManifest(XmlPullStreamDecoder.java:
151
)
at brut.androlib.res.decoder.ResFileDecoder.decodeManifest(ResFileDecoder.java:
159
)
at brut.androlib.res.AndrolibResources.decodeManifestWithResources(AndrolibResources.java:
193
)
at brut.androlib.Androlib.decodeManifestWithResources(Androlib.java:
141
)
at brut.androlib.ApkDecoder.decode(ApkDecoder.java:
109
)
at brut.apktool.Main.cmdDecode(Main.java:
175
)
at brut.apktool.Main.main(Main.java:
79
)
Caused by: java.io.IOException: Expected:
0x001c0001
, got:
0x01001c00
at brut.util.ExtDataInput.skipCheckChunkTypeInt(ExtDataInput.java:
72
)
at brut.androlib.res.decoder.StringBlock.read(StringBlock.java:
50
)
at brut.androlib.res.decoder.AXmlResourceParser.doNext(AXmlResourceParser.java:
814
)
at brut.androlib.res.decoder.AXmlResourceParser.
next
(AXmlResourceParser.java:
98
)
at brut.androlib.res.decoder.AXmlResourceParser.nextToken(AXmlResourceParser.java:
108
)
at org.xmlpull.v1.wrapper.classic.XmlPullParserDelegate.nextToken(XmlPullParserDelegate.java:
105
)
at brut.androlib.res.decoder.XmlPullStreamDecoder.decode(XmlPullStreamDecoder.java:
138
)
...
7
more
>apktool d APK逆向
-
2.apk
I: Using Apktool
2.6
.
1
on APK逆向
-
2.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
Exception
in
thread
"main"
brut.androlib.err.RawXmlEncounteredException: Could
not
decode XML
at brut.androlib.res.decoder.XmlPullStreamDecoder.decode(XmlPullStreamDecoder.java:
145
)
at brut.androlib.res.decoder.XmlPullStreamDecoder.decodeManifest(XmlPullStreamDecoder.java:
151
)
at brut.androlib.res.decoder.ResFileDecoder.decodeManifest(ResFileDecoder.java:
159
)
at brut.androlib.res.AndrolibResources.decodeManifestWithResources(AndrolibResources.java:
193
)
at brut.androlib.Androlib.decodeManifestWithResources(Androlib.java:
141
)
at brut.androlib.ApkDecoder.decode(ApkDecoder.java:
109
)
at brut.apktool.Main.cmdDecode(Main.java:
175
)
at brut.apktool.Main.main(Main.java:
79
)
Caused by: java.io.IOException: Expected:
0x001c0001
, got:
0x01001c00
at brut.util.ExtDataInput.skipCheckChunkTypeInt(ExtDataInput.java:
72
)
at brut.androlib.res.decoder.StringBlock.read(StringBlock.java:
50
)
at brut.androlib.res.decoder.AXmlResourceParser.doNext(AXmlResourceParser.java:
814
)
at brut.androlib.res.decoder.AXmlResourceParser.
next
(AXmlResourceParser.java:
98
)
at brut.androlib.res.decoder.AXmlResourceParser.nextToken(AXmlResourceParser.java:
108
)
at org.xmlpull.v1.wrapper.classic.XmlPullParserDelegate.nextToken(XmlPullParserDelegate.java:
105
)
at brut.androlib.res.decoder.XmlPullStreamDecoder.decode(XmlPullStreamDecoder.java:
138
)
...
7
more
第一行:偏移
0x0
-
0x3
0x6
-
0xB
0xE
-
0xF
第二行:偏移
0x1
-
0xB
0xE
-
0xF
第三行:偏移
0x1
-
0xF
第四行:偏移
0x1
-
0x7
0x9
-
0xB
0xD
-
0xF
第一行:偏移
0x0
-
0x3
0x6
-
0xB
0xE
-
0xF
第二行:偏移
0x1
-
0xB
0xE
-
0xF
第三行:偏移
0x1
-
0xF
第四行:偏移
0x1
-
0x7
0x9
-
0xB
0xD
-
0xF
第一行:偏移
0x0
-
0x3
(一致)
0x6
-
0xB
(不一致
0x8
-
0xB
刚好反转)
0xE
-
0xF
(一致)
第二行:偏移
0x1
-
0xB
(一致)
0xD
-
0xF
(一致)
第三行:偏移
0x1
-
0xF
(不一致
0x2
位置变成
1
了)
第四行:偏移
0x1
-
0x7
(一致)
0x9
-
0xB
(一致)
0xD
-
0xF
(一致)
第一行:偏移
0x0
-
0x3
(一致)
0x6
-
0xB
(不一致
0x8
-
0xB
刚好反转)
0xE
-
0xF
(一致)
第二行:偏移
0x1
-
0xB
(一致)
0xD
-
0xF
(一致)
第三行:偏移
0x1
-
0xF
(不一致
0x2
位置变成
1
了)
第四行:偏移
0x1
-
0x7
(一致)
0x9
-
0xB
(一致)
0xD
-
0xF
(一致)
am start com.example.mmsheniq
/
.Mainactivity
am start com.example.mmsheniq
/
.Mainactivity
8d6efd232c63b7d2
this.btn_register.setOnClickListener(new View.OnClickListener() {
/
/
from
class
: com.droider.crackme0201.MainActivity.
1
@Override
/
/
android.view.View.OnClickListener
public void onClick(View v) {
if
(!MainActivity.this.checkSN(MainActivity.this.edit_userName.getText().toString().trim(), MainActivity.this.edit_sn.getText().toString().trim())) {
Toast.makeText(MainActivity.this, (
int
) R.string.unsuccessed,
0
).show();
return
;
}
Toast.makeText(MainActivity.this, (
int
) R.string.successed,
0
).show();
MainActivity.this.btn_register.setEnabled(false);
MainActivity.this.setTitle(R.string.registered);
}
});
this.btn_register.setOnClickListener(new View.OnClickListener() {
/
/
from
class
: com.droider.crackme0201.MainActivity.
1
@Override
/
/
android.view.View.OnClickListener
public void onClick(View v) {
if
(!MainActivity.this.checkSN(MainActivity.this.edit_userName.getText().toString().trim(), MainActivity.this.edit_sn.getText().toString().trim())) {
Toast.makeText(MainActivity.this, (
int
) R.string.unsuccessed,
0
).show();
return
;
}
Toast.makeText(MainActivity.this, (
int
) R.string.successed,
0
).show();
MainActivity.this.btn_register.setEnabled(false);
MainActivity.this.setTitle(R.string.registered);
}
});
public boolean checkSN(String userName, String sn) {
try
{
if
(userName.length()
=
=
0
&& sn.length()
=
=
0
) {
/
/
什么都不输入就返回true 哈哈
return
true;
}
if
(userName
=
=
null || userName.length()
=
=
0
) {
return
false;
}
if
(sn
=
=
null || sn.length() !
=
16
) {
return
false;
}
MessageDigest digest
=
MessageDigest.getInstance(
"MD5"
);
digest.reset();
digest.update(userName.getBytes());
/
/
对用户名进行md5加密
byte[] bytes
=
digest.digest();
String hexstr
=
toHexString(bytes, BuildConfig.FLAVOR);
/
/
BuildConfig.FLAVOR为空字符串
StringBuilder sb
=
new StringBuilder();
for
(
int
i
=
0
; i < hexstr.length(); i
+
=
2
) {
sb.append(hexstr.charAt(i));
/
/
隔一位取一位
}
String userSN
=
sb.toString();
return
userSN.equalsIgnoreCase(sn);
/
/
用户名经过上面的加密后就再与输入的注册码sn相等即返回true
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return
false;
}
}
public boolean checkSN(String userName, String sn) {
try
{
if
(userName.length()
=
=
0
&& sn.length()
=
=
0
) {
/
/
什么都不输入就返回true 哈哈
return
true;
}
if
(userName
=
=
null || userName.length()
=
=
0
) {
return
false;
}
if
(sn
=
=
null || sn.length() !
=
16
) {
return
false;
}
MessageDigest digest
=
MessageDigest.getInstance(
"MD5"
);
digest.reset();
digest.update(userName.getBytes());
/
/
对用户名进行md5加密
byte[] bytes
=
digest.digest();
String hexstr
=
toHexString(bytes, BuildConfig.FLAVOR);
/
/
BuildConfig.FLAVOR为空字符串
StringBuilder sb
=
new StringBuilder();
for
(
int
i
=
0
; i < hexstr.length(); i
+
=
2
) {
sb.append(hexstr.charAt(i));
/
/
隔一位取一位
}
String userSN
=
sb.toString();
return
userSN.equalsIgnoreCase(sn);
/
/
用户名经过上面的加密后就再与输入的注册码sn相等即返回true
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return
false;
}
}
<string name
=
"successed"
>md5:b3241668ecbeb19921fdac5ac1aafa69<
/
string>
<string name
=
"successed"
>md5:b3241668ecbeb19921fdac5ac1aafa69<
/
string>
YOU_KNOW_
YOU_KNOW_ANDROID
public void onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.etFlag
=
(EditText) findViewById(R.
id
.flag_edit);
}
public void onGoClick(View v) {
String sInput
=
this.etFlag.getText().toString();
if
(getSecret(getFlag()).equals(getSecret(encrypt(sInput)))) {
Toast.makeText(this,
"Success"
,
1
).show();
}
else
{
Toast.makeText(this,
"Failed"
,
1
).show();
}
}
public void onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.etFlag
=
(EditText) findViewById(R.
id
.flag_edit);
}
public void onGoClick(View v) {
String sInput
=
this.etFlag.getText().toString();
if
(getSecret(getFlag()).equals(getSecret(encrypt(sInput)))) {
Toast.makeText(this,
"Success"
,
1
).show();
}
else
{
Toast.makeText(this,
"Failed"
,
1
).show();
}
}
public native String encrypt(String
str
);
public native String getFlag();
static {
System.loadLibrary(
"phcm"
);
}
public native String encrypt(String
str
);
public native String getFlag();
static {
System.loadLibrary(
"phcm"
);
}
int
__fastcall Java_com_ph0en1x_android_1crackme_MainActivity_getFlag(_JNIEnv
*
env)
{
char
*
v1;
/
/
r4
_JNIEnv
*
v2;
/
/
r7
char
*
v3;
/
/
r3
int
v4;
/
/
r0
int
v5;
/
/
r1
char
*
v6;
/
/
r2
const char
*
v7;
/
/
r3
int
v8;
/
/
r0
int
v9;
/
/
r1
int
v10;
/
/
r4
int
v11;
/
/
r0
__int16 v12;
/
/
r3
signed
int
v13;
/
/
r8
signed
int
v14;
/
/
r0
char
*
v15;
/
/
r9
char v16;
/
/
r3
char v17;
/
/
t1
int
v18;
/
/
r1
char s;
/
/
[sp
+
4h
] [bp
-
5Ch
]
char v21[
40
];
/
/
[sp
+
14h
] [bp
-
4Ch
]
char v22;
/
/
[sp
+
40h
] [bp
-
20h
]
v1
=
v21;
v2
=
env;
v3
=
(char
*
)&dword_2770;
do
{
v4
=
*
(_DWORD
*
)v3;
v3
+
=
8
;
v5
=
*
((_DWORD
*
)v3
-
1
);
*
(_DWORD
*
)v1
=
v4;
*
((_DWORD
*
)v1
+
1
)
=
v5;
v1
+
=
8
;
}
while
( v3 !
=
"Hello Ph0en1x"
);
v6
=
&s;
v7
=
"Hello Ph0en1x"
;
do
{
v8
=
*
(_DWORD
*
)v7;
v7
+
=
8
;
v9
=
*
((_DWORD
*
)v7
-
1
);
*
(_DWORD
*
)v6
=
v8;
*
((_DWORD
*
)v6
+
1
)
=
v9;
v10
=
(
int
)(v6
+
8
);
v6
+
=
8
;
}
while
( v7 !
=
"0en1x"
);
v11
=
*
(_DWORD
*
)v7;
v12
=
*
((_WORD
*
)v7
+
2
);
*
(_DWORD
*
)v10
=
v11;
*
(_WORD
*
)(v10
+
4
)
=
v12;
v13
=
strlen(&s);
v14
=
strlen(v21)
-
1
;
v15
=
&v21[v14];
while
( v14 >
0
)
{
v16
=
*
v15
+
1
;
*
v15
=
v16;
v17
=
*
(v15
-
-
-
1
);
v18
=
v14
-
-
%
v13;
v15[
1
]
=
((v16
-
v17) ^
*
(&v22
+
v18
-
60
))
-
1
;
}
v21[
0
]
=
(v21[
0
] ^
0x48
)
-
1
;
return
((
int
(__fastcall
*
)(_JNIEnv
*
, char
*
))v2
-
>functions
-
>NewStringUTF)(v2, v21);
}
int
__fastcall Java_com_ph0en1x_android_1crackme_MainActivity_getFlag(_JNIEnv
*
env)
{
char
*
v1;
/
/
r4
_JNIEnv
*
v2;
/
/
r7
char
*
v3;
/
/
r3
int
v4;
/
/
r0
int
v5;
/
/
r1
char
*
v6;
/
/
r2
const char
*
v7;
/
/
r3
int
v8;
/
/
r0
int
v9;
/
/
r1
int
v10;
/
/
r4
int
v11;
/
/
r0
__int16 v12;
/
/
r3
signed
int
v13;
/
/
r8
signed
int
v14;
/
/
r0
char
*
v15;
/
/
r9
char v16;
/
/
r3
char v17;
/
/
t1
int
v18;
/
/
r1
char s;
/
/
[sp
+
4h
] [bp
-
5Ch
]
char v21[
40
];
/
/
[sp
+
14h
] [bp
-
4Ch
]
char v22;
/
/
[sp
+
40h
] [bp
-
20h
]
v1
=
v21;
v2
=
env;
v3
=
(char
*
)&dword_2770;
do
{
v4
=
*
(_DWORD
*
)v3;
v3
+
=
8
;
v5
=
*
((_DWORD
*
)v3
-
1
);
*
(_DWORD
*
)v1
=
v4;
*
((_DWORD
*
)v1
+
1
)
=
v5;
v1
+
=
8
;
}
while
( v3 !
=
"Hello Ph0en1x"
);
v6
=
&s;
v7
=
"Hello Ph0en1x"
;
do
{
v8
=
*
(_DWORD
*
)v7;
v7
+
=
8
;
v9
=
*
((_DWORD
*
)v7
-
1
);
*
(_DWORD
*
)v6
=
v8;
*
((_DWORD
*
)v6
+
1
)
=
v9;
v10
=
(
int
)(v6
+
8
);
v6
+
=
8
;
}
while
( v7 !
=
"0en1x"
);
v11
=
*
(_DWORD
*
)v7;
v12
=
*
((_WORD
*
)v7
+
2
);
*
(_DWORD
*
)v10
=
v11;
*
(_WORD
*
)(v10
+
4
)
=
v12;
v13
=
strlen(&s);
v14
=
strlen(v21)
-
1
;
v15
=
&v21[v14];
while
( v14 >
0
)
{
v16
=
*
v15
+
1
;
*
v15
=
v16;
v17
=
*
(v15
-
-
-
1
);
v18
=
v14
-
-
%
v13;
v15[
1
]
=
((v16
-
v17) ^
*
(&v22
+
v18
-
60
))
-
1
;
}
v21[
0
]
=
(v21[
0
] ^
0x48
)
-
1
;
return
((
int
(__fastcall
*
)(_JNIEnv
*
, char
*
))v2
-
>functions
-
>NewStringUTF)(v2, v21);
}
int
__fastcall Java_com_ph0en1x_android_1crackme_MainActivity_encrypt(_JNIEnv
*
a1)
{
_JNIEnv
*
v1;
/
/
r6
const char
*
input_str;
/
/
r4
const char
*
i;
/
/
r5
v1
=
a1;
input_str
=
(const char
*
)((
int
(
*
)(void))a1
-
>functions
-
>GetStringUTFChars)();
for
( i
=
input_str; i
-
input_str < strlen(input_str);
+
+
i )
-
-
*
i;
return
((
int
(__fastcall
*
)(_JNIEnv
*
, const char
*
))v1
-
>functions
-
>NewStringUTF)(v1, input_str);
}
int
__fastcall Java_com_ph0en1x_android_1crackme_MainActivity_encrypt(_JNIEnv
*
a1)
{
_JNIEnv
*
v1;
/
/
r6
const char
*
input_str;
/
/
r4
const char
*
i;
/
/
r5
v1
=
a1;
input_str
=
(const char
*
)((
int
(
*
)(void))a1
-
>functions
-
>GetStringUTFChars)();
for
( i
=
input_str; i
-
input_str < strlen(input_str);
+
+
i )
-
-
*
i;
return
((
int
(__fastcall
*
)(_JNIEnv
*
, const char
*
))v1
-
>functions
-
>NewStringUTF)(v1, input_str);
}
import
sys
import
frida
process_name
=
'Android_crackme'
def
on_message(message, data):
if
message[
'type'
]
=
=
'send'
:
print
(f
"[*] {message['payload']}"
)
else
:
print
(message)
if
__name__
=
=
'__main__'
:
try
:
device
=
frida.get_usb_device(timeout
=
1000
)
print
(
"* get usb device成功"
)
except
:
device
=
frida.get_remote_device(timeout
=
1000
)
print
(
"* get remote device成功"
)
if
not
device:
print
(
"* 连接到Frida Server失败"
)
else
:
process
=
device.attach(process_name)
js
=
open
(
'hook.js'
, encoding
=
'utf-8'
).read()
print
(js)
script
=
process.create_script(js)
script.on(
'message'
, on_message)
script.load()
input
()
script.unload()
import
sys
import
frida
process_name
=
'Android_crackme'
def
on_message(message, data):
if
message[
'type'
]
=
=
'send'
:
print
(f
"[*] {message['payload']}"
)
else
:
print
(message)
if
__name__
=
=
'__main__'
:
try
:
device
=
frida.get_usb_device(timeout
=
1000
)
print
(
"* get usb device成功"
)
except
:
device
=
frida.get_remote_device(timeout
=
1000
)
print
(
"* get remote device成功"
)
if
not
device:
print
(
"* 连接到Frida Server失败"
)
else
:
process
=
device.attach(process_name)
js
=
open
(
'hook.js'
, encoding
=
'utf-8'
).read()
print
(js)
script
=
process.create_script(js)
script.on(
'message'
, on_message)
script.load()
input
()
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)