bugku_ctf {Reverse}逆向浅谈之easy-100

本文介绍了如何通过逆向分析Android应用来解密隐藏的字符串。通过分析Java代码,提取关键步骤,包括从资源文件中读取数据、字符串重组、AES加密过程,并使用Python实现解密,最终得到解密后的密码。这是一个关于移动安全和加密技术的实际案例。
摘要由CSDN通过智能技术生成

大家好,我是你们的老朋友,任雪飘!一个伪全站,伪全能的垃圾!接下来由我为你们介绍一关,比我还厉害的关卡。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}

到此结束,有参考部分资料,感谢大家对我的关注!

逆向学习,大家一下交流!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

埋谷与麦谷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值