-
-
[原创]KCTF2020秋季赛 第四题 突破重围
-
发表于: 2020-11-24 23:04 4545
-
老规矩,直接上jadx,部分函数关键如下
在assets找到 b.txt,实际上是个dex,类反编译后的代码如下
check函数将input加密后再跟内置的加密flag比较,容易看出crypt方法是RC4算法。那么重点就是crackjni函数
so对字符串做了加密,可以弄个脚本解密,或者直接附加。
crackjni函数主要是把RC4过的输入再做一次AES加密,以及对b.txt这个DEX动一点手脚
总结一下input加密流程:RC4("kaokaonio")->AESEncrypt("kaokaonikaokaoni")->RC4("keepGoing")->base64
逆回去搞定了
得到flag:flag{thisiskey!}
protected void onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView((
int
) R.layout.activity_main);
int
sdkVersion
=
VERSION.SDK_INT;
if
(System.getProperty(
"os.arch"
).toLowerCase().contains(
"x86"
)) {
Toast.makeText(getApplicationContext(),
"This APP is only support arm and arm64,exit......!"
,
1
).show();
new Thread(new Runnable() {
public void run() {
try
{
Thread.currentThread();
Thread.sleep(
5000
);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.exit(
0
);
}
}).start();
}
if
(sdkVersion <
24
|| sdkVersion >
28
) {
Toast.makeText(getApplicationContext(),
"This APP is only support Android 7,Android 7.1,Android 8,Android 8.1,Android 9,exit......!"
,
1
).show();
new Thread(new Runnable() {
public void run() {
try
{
Thread.currentThread();
Thread.sleep(
5000
);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.exit(
0
);
}
}).start();
}
appContext
=
getApplicationContext();
final Context tmpcontext
=
this;
System.loadLibrary(
"crack"
);
init();
final EditText inputEditText
=
(EditText) findViewById(R.
id
.inputEditText);
((Button) findViewById(R.
id
.checkButton)).setOnClickListener(new OnClickListener() {
public void onClick(View view) {
boolean check
=
MainActivity.this.check(inputEditText.getText().toString());
CharSequence charSequence
=
BuildConfig.FLAVOR;
CharSequence charSequence2
=
"result"
;
if
(check) {
new Builder(tmpcontext).setTitle(charSequence2).setMessage(
"Congratulations! app is exit....."
).show();
inputEditText.setText(charSequence);
new Thread(new Runnable() {
public void run() {
try
{
Thread.currentThread();
Thread.sleep(
5000
);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.exit(
0
);
}
}).start();
return
;
}
new Builder(tmpcontext).setTitle(charSequence2).setMessage(
"Sorry,wrong key ,app is exit....."
).show();
inputEditText.setText(charSequence);
new Thread(new Runnable() {
public void run() {
try
{
Thread.currentThread();
Thread.sleep(
5000
);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.exit(
0
);
}
}).start();
}
});
}
public void init() {
String filename
=
"b.txt"
;
copyAssetAndWrite(filename);
testDexClassLoader(appContext, new
File
(appContext.getCacheDir(), filename).getAbsolutePath());
}
public boolean check(String content) {
DexClassLoader dexClassLoader
=
dexClassLoader;
if
(dexClassLoader !
=
null) {
Class<?> clazz
=
null;
try
{
clazz
=
dexClassLoader.loadClass(
"com.kanxue.crackme.Crack"
);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if
(clazz !
=
null) {
try
{
Method testFuncMethod
=
null;
for
(Method i : clazz.getDeclaredMethods()) {
if
(i.getName().contains(
"check"
)) {
testFuncMethod
=
i;
}
}
return
((Boolean) testFuncMethod.invoke(null, new
Object
[]{content})).booleanValue();
} catch (IllegalAccessException e2) {
e2.printStackTrace();
} catch (InvocationTargetException e3) {
e3.printStackTrace();
}
}
}
return
false;
}
protected void onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView((
int
) R.layout.activity_main);
int
sdkVersion
=
VERSION.SDK_INT;
if
(System.getProperty(
"os.arch"
).toLowerCase().contains(
"x86"
)) {
Toast.makeText(getApplicationContext(),
"This APP is only support arm and arm64,exit......!"
,
1
).show();
new Thread(new Runnable() {
public void run() {
try
{
Thread.currentThread();
Thread.sleep(
5000
);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.exit(
0
);
}
}).start();
}
if
(sdkVersion <
24
|| sdkVersion >
28
) {
Toast.makeText(getApplicationContext(),
"This APP is only support Android 7,Android 7.1,Android 8,Android 8.1,Android 9,exit......!"
,
1
).show();
new Thread(new Runnable() {
public void run() {
try
{
Thread.currentThread();
Thread.sleep(
5000
);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.exit(
0
);
}
}).start();
}
appContext
=
getApplicationContext();
final Context tmpcontext
=
this;
System.loadLibrary(
"crack"
);
init();
final EditText inputEditText
=
(EditText) findViewById(R.
id
.inputEditText);
((Button) findViewById(R.
id
.checkButton)).setOnClickListener(new OnClickListener() {
public void onClick(View view) {
boolean check
=
MainActivity.this.check(inputEditText.getText().toString());
CharSequence charSequence
=
BuildConfig.FLAVOR;
CharSequence charSequence2
=
"result"
;
if
(check) {
new Builder(tmpcontext).setTitle(charSequence2).setMessage(
"Congratulations! app is exit....."
).show();
inputEditText.setText(charSequence);
new Thread(new Runnable() {
public void run() {
try
{
Thread.currentThread();
Thread.sleep(
5000
);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.exit(
0
);
}
}).start();
return
;
}
new Builder(tmpcontext).setTitle(charSequence2).setMessage(
"Sorry,wrong key ,app is exit....."
).show();
inputEditText.setText(charSequence);
new Thread(new Runnable() {
public void run() {
try
{
Thread.currentThread();
Thread.sleep(
5000
);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.exit(
0
);
}
}).start();
}
});
}
public void init() {
String filename
=
"b.txt"
;
copyAssetAndWrite(filename);
testDexClassLoader(appContext, new
File
(appContext.getCacheDir(), filename).getAbsolutePath());
}
public boolean check(String content) {
DexClassLoader dexClassLoader
=
dexClassLoader;
if
(dexClassLoader !
=
null) {
Class<?> clazz
=
null;
try
{
clazz
=
dexClassLoader.loadClass(
"com.kanxue.crackme.Crack"
);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if
(clazz !
=
null) {
try
{
Method testFuncMethod
=
null;
for
(Method i : clazz.getDeclaredMethods()) {
if
(i.getName().contains(
"check"
)) {
testFuncMethod
=
i;
}
}
return
((Boolean) testFuncMethod.invoke(null, new
Object
[]{content})).booleanValue();
} catch (IllegalAccessException e2) {
e2.printStackTrace();
} catch (InvocationTargetException e3) {
e3.printStackTrace();
}
}
}
return
false;
}
package com.kanxue.crackme;
import
android.util.Base64;
import
java.lang.reflect.Field;
import
java.lang.reflect.InvocationTargetException;
import
java.lang.reflect.Method;
public
class
Crack {
public static boolean check(String content) {
if
(content !
=
null) {
if
(content.length()
=
=
16
) {
Class MyCrackClass
=
null;
Field cryptfield
=
null;
byte[] result
=
crypt(content.getBytes());
Method crackjni
=
null;
try
{
MyCrackClass
=
Crack.
class
.getClassLoader().loadClass(
"com.kanxue.crackme.MyCrack"
);
cryptfield
=
MyCrackClass.getDeclaredField(
"crypt"
);
Method[] methods
=
MyCrackClass.getDeclaredMethods();
for
(
int
i
=
0
; i < methods.length; i
+
+
) {
if
(methods[i].getName().equals(
"crackjni"
)) {
crackjni
=
methods[i];
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e2) {
e2.printStackTrace();
}
if
(crackjni !
=
null) {
try
{
result
=
(byte[]) crackjni.invoke(null, new
Object
[]{result});
} catch (IllegalAccessException e3) {
e3.printStackTrace();
} catch (InvocationTargetException e4) {
e4.printStackTrace();
}
}
String finalresult
=
Base64.encodeToString(crypt(result),
0
);
String cryptcontent
=
"test"
;
if
(!(cryptfield
=
=
null || MyCrackClass
=
=
null)) {
try
{
cryptcontent
=
(String) cryptfield.get(null);
} catch (IllegalAccessException e5) {
e5.printStackTrace();
}
}
if
(finalresult.equals(cryptcontent)) {
return
true;
}
return
false;
}
}
return
false;
}
public static byte[] crypt(byte[] b_data) {
String mKkey
=
"kaokaonio"
;
if
(b_data
=
=
null) {
return
null;
}
int
i;
int
x
=
0
;
int
y
=
0
;
byte[] b_key
=
mKkey.getBytes();
byte[] key
=
new byte[
256
];
for
(i
=
0
; i <
256
; i
+
+
) {
key[i]
=
(byte) i;
}
i
=
0
;
int
index2
=
0
;
if
(b_key !
=
null) {
if
(b_key.length !
=
0
) {
byte tmp;
for
(
int
i2
=
0
; i2 <
256
; i2
+
+
) {
index2
=
(((b_key[i] &
255
)
+
(key[i2] &
255
))
+
index2) &
255
;
tmp
=
key[i2];
key[i2]
=
key[index2];
key[index2]
=
tmp;
i
=
(i
+
1
)
%
b_key.length;
}
byte[] result
=
new byte[b_data.length];
for
(
int
i3
=
0
; i3 < b_data.length; i3
+
+
) {
x
=
(x
+
1
) &
255
;
y
=
((key[x] &
255
)
+
y) &
255
;
tmp
=
key[x];
key[x]
=
key[y];
key[y]
=
tmp;
result[i3]
=
(byte) (b_data[i3] ^ key[((key[x] &
255
)
+
(key[y] &
255
)) &
255
]);
}
return
result;
}
}
return
null;
}
}
package com.kanxue.crackme;
import
android.util.Base64;
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
赞赏
他的文章
看原图
赞赏
雪币:
留言: