大家好,我是你们的老朋友,任雪飘!一个伪全站,伪全能的垃圾!接下来由我为你们介绍一关,比我还厉害的关卡。ctf 逆向分析之我的脑残题目!easy-100,别喷!!!!!
废话多了点,我们直接开干,下面看代码。
package com.example.ring.myapplication;
import android.content.pm.ApplicationInfo;
import android.os.Bundle;
import android.support.v7.a.q;
import android.widget.Button;
import java.io.InputStream;
public class MainActivity extends q {
private String v;
/* access modifiers changed from: protected */
@Override // android.support.v4.c.ac, android.support.v4.c.an, android.support.v7.a.q
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_main);
ApplicationInfo applicationInfo = getApplicationInfo();
int i = applicationInfo.flags & 2;
applicationInfo.flags = i;
if (i != 0) {
}
p();
((Button) findViewById(R.id.sureButton)).setOnClickListener(new d(this));
}
private void p() {
try {
InputStream open = getResources().getAssets().open("url.png");
int available = open.available();
byte[] bArr = new byte[available];
open.read(bArr, 0, available);
byte[] bArr2 = new byte[16];
System.arraycopy(bArr, 144, bArr2, 0, 16);
this.v = new String(bArr2, "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
}
/* access modifiers changed from: private */
public boolean a(String str, String str2) {
return new c().a(str, str2).equals(new String(new byte[]{21, -93, -68, -94, 86, 117, -19, -68, -92, 33, 50, 118, 16, 13, 1, -15, -13, 3, 4, 103, -18, 81, 30, 68, 54, -93, 44, -23, 93, 98, 5, 59}));
}
}
写的啥,能看懂吗?大佬不看了,直接过
我们小白,我们玩,看下面代码
package com.example.ring.myapplication;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
class d implements View.OnClickListener {
final /* synthetic */ MainActivity a;
d(MainActivity mainActivity) {
this.a = mainActivity;
}
public void onClick(View view) {
if (MainActivity.a(this.a, MainActivity.a(this.a), ((EditText) this.a.findViewById(R.id.passCode)).getText().toString())) {
Toast.makeText(this.a.getApplicationContext(), "Congratulations!", 1).show();
((TextView) this.a.findViewById(R.id.textView)).setText(R.string.nice);
return;
}
Toast.makeText(this.a.getApplicationContext(), "Oh no.", 1).show();
}
}
大概以上就是说判断走向问题,我们一定要让他走到Congratulations!这个输出!
d方法分析完毕了,咱们后悔了,觉得这不是多余的嘛,返回,直接看p方法了!
private void p() {
try {
InputStream open = getResources().getAssets().open("url.png");
int available = open.available();
byte[] bArr = new byte[available];
open.read(bArr, 0, available);
byte[] bArr2 = new byte[16];
System.arraycopy(bArr, 144, bArr2, 0, 16);
this.v = new String(bArr2, "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
}
这边这个意思就是 p方法 保存一张图片的数据,保存在v字符串中。
我们回到onClick方法分析MainActivity.a方法
public boolean a(String str, String str2) {
return new c().a(str, str2).equals(new String(new byte[]{21, -93, -68, -94, 86, 117, -19, -68, -92, 33, 50, 118, 16, 13, 1, -15, -13, 3, 4, 103, -18, 81, 30, 68, 54, -93, 44, -23, 93, 98, 5, 59}));
}
我们跟c这个方法进去
package com.example.ring.myapplication;
import java.io.UnsupportedEncodingException;
public class c {
public String a(String str, String str2) {
String a = a(str);
a aVar = new a();
aVar.a(a.getBytes());
try {
return new String(aVar.b(str2.getBytes()), "utf-8");
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
private String a(String str) {
try {
str.getBytes("utf-8");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i += 2) {
sb.append(str.charAt(i + 1));
sb.append(str.charAt(i));
}
return sb.toString();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
}
然后我们在更aVar.a 方法
package com.example.ring.myapplication;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
public class a {
private SecretKeySpec a;
private Cipher b;
/* access modifiers changed from: protected */
public void a(byte[] bArr) {
if (bArr == null) {
try {
this.a = new SecretKeySpec(MessageDigest.getInstance("MD5").digest("".getBytes("utf-8")), "AES");
this.b = Cipher.getInstance("AES/ECB/PKCS5Padding");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e2) {
e2.printStackTrace();
} catch (NoSuchPaddingException e3) {
e3.printStackTrace();
}
} else {
this.a = new SecretKeySpec(bArr, "AES");
this.b = Cipher.getInstance("AES/ECB/PKCS5Padding");
}
}
/* access modifiers changed from: protected */
public byte[] b(byte[] bArr) {
this.b.init(1, this.a);
return this.b.doFinal(bArr);
}
}
得到了AES 算法采用的是AES/ECB/PKCS5Padding填充方式 ,分析到现在我们就大概明白了,图片中获取的字符串给str,然后str2是我们输入的.
后面的代码主要是AES加密,当做密码,将输入的字符串进行AES加密后和后面给出的字符串比较,如果是一个标记
那就可以识别了 AES 我们就可以直接识别,python 代码如下:
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
#equals比较的字节数组
byteArray =[21, -93, -68, -94, 86, 117, -19, -68, -92, 33,
50, 118, 16, 13, 1, -15, -13, 3, 4, 103, -18,
81, 30, 68, 54, -93, 44, -23, 93, 98, 5, 59]
#读取图片
with open('url.png','rb') as f:
p =f.read()
str1 =p[144:144+16]
print("字节数组:" , str1)
# 字节数组转字符串
byte2str = str1.decode()
print("图片[144:144+16]字符串:"+ byte2str)
# 前后两个字符一组,互换位置,密钥字符串
str2 =""
for i in range(0,len(str1),2):
str2 += chr(str1[i+1])
str2 += chr(str1[i])
print("返回互换位置后的图片字符串:" + str2)
# 把密文字节数组转换为16进制字符串
str3 =""
for i in byteArray:
s=str(hex((i+256)%256))
if len(s) <4:
s = s[0:2]+'0'+s[2:]
print(s)
str3+=s[2:]
print(str3)
# AES算法解密,ECB的工作模式,PKCS5Padding 的填充
# 去掉 PKCS5Padding 的填充
unpad = lambda s: s[:-ord(s[len(s) - 1:])]
# 通过 密钥,工作模式ECB 进行初始操作密码器
cipher = AES.new(str2.encode(), AES.MODE_ECB)
# a2b_hex()16进制转字符串,之后密码器解密字符串,再用unpad表达式去掉 PKCS5Padding 的填充,最后指定utf8的编码格式将bytes解码成字符串str
data_response = unpad(cipher.decrypt(a2b_hex(str3))).decode('utf8')
print("解密得到的明文密码flag:"+data_response)
经计算的到的结果如下:
解密得到的明文密码:LCTF{1t's_rea1ly_an_ea3y_ap4}
到此结束,有参考部分资料,感谢大家对我的关注!
逆向学习,大家一下交流!