国科大智能设备安全-APK逆向分析实验

APK逆向分析实验

使用APK常用逆向分析工具,对提供的移动应用程序APK文件进行逆向分析,提交逆向后代码和分析报告。具体任务如下:
任务一:安装并熟悉Apktool、Jadx等APK常用逆向工具的使用方法,对提供的Facebook Update.apk文件进行逆向,获取smali代码和Java代码;
任务二:Facebook Update.apk中存在窃取用户短信、联系人信息、录音、设备信息等恶意行为,请基于该应用的Manifest.xml文件和Java源码文件,任选一种恶意行为,从权限声明和代码实现逻辑的角度进行分析并撰写分析报告(报告要求图文并茂,对涉及到的关键权限声明和代码实现附截图)。
*注:Facebook Update.apk为恶意样本,请勿以明文形式在互联网传播,解压密码为20241021。


APK逆向分析实验-20241023.md

APK逆向分析实验
使用APK常用逆向分析工具,对提供的移动应用程序APK文件进行逆向分析,提交逆向后代码和分析报告。具体任务如下:
任务一:安装并熟悉Apktool、Jadx等APK常用逆向工具的使用方法,对提供的Facebook Update.apk文件进行逆向,获取smali代码和Java代码;
任务二:Facebook Update.apk中存在窃取用户短信、联系人信息、录音、设备信息等恶意行为,请基于该应用的Manifest.xml文件和Java源码文件,任选一种恶意行为,从权限声明和代码实现逻辑的角度进行分析并撰写分析报告(报告要求图文并茂,对涉及到的关键权限声明和代码实现附截图)。
*注:Facebook Update.apk为恶意样本,请勿以明文形式在互联网传播,解压密码为20241021。

文章目录

  • APK逆向分析实验
    • APK逆向分析实验-20241023.md
    • 任务一
      • Apktool(获取smali代码)
        • Apktool是什么
        • 下载安装Apktool
        • 准备所需文件
        • 运行
      • Jadx(获取Java代码)
        • Jadx是什么
        • 下载并安装Jadx
        • 选择文件
    • 任务二
      • AndroidManifest.xml
        • 文件内容
        • 权限声明分析
        • 代码实现逻辑分析
      • Java源码-UploadService类
        • 关键代码分析
        • 上传任务的实现
        • 恶意行为分析
        • 附:分析的代码

任务一

任务一:安装并熟悉Apktool、Jadx等APK常用逆向工具的使用方法,对提供的Facebook Update.apk文件进行逆向,获取smali代码和Java代码;

Apktool(获取smali代码)

Apktool是什么

APKTool 是一个开源工具,用于反编译和重编译 Android 应用程序的 APK(Android Package)文件。它主要用于分析和修改 Android 应用的资源和代码,广泛应用于逆向工程、安全研究和应用开发等领域。

下载安装Apktool

首先,下载所需要的工具,下载地址:iBotPeaches / Apktool / Downloads — Bitbucket

安装方法参考:Install Guide | Apktool

准备所需文件

新建一个apktool.bat文件,其中内容如下所示:

@echo off
if "%PATH_BASE%" == "" set PATH_BASE=%PATH%
set PATH=%CD%;%PATH_BASE%;
chcp 65001 2>nul >nul
java -jar -Duser.language=en -Dfile.encoding=UTF8 "%~dp0\apktool.jar" %*

此时,当前文件夹下有如下内容

在这里插入图片描述

运行

使用以下命令运行

apktool.bat d -f "Facebook Update.apk"

在这里插入图片描述

可以看到生成了一个文件夹:
在这里插入图片描述

smail和AndroidManifest.xml如图所示:
在这里插入图片描述

Jadx(获取Java代码)

Jadx是什么

Jadx 是一个开源工具,用于将 Android 应用程序的 DEX(Dalvik Executable)文件反编译为 Java 源代码。它可以帮助开发者和安全研究人员分析和理解 Android 应用程序的内部工作原理。Jadx 通常用于安全审计、逆向工程和教育目的,帮助用户更好地理解 Android 应用的结构和行为。

下载并安装Jadx

首先根据要求下载并安装Jadx,项目地址:skylot/jadx: Dex to Java decompiler

运行Jadx,如图所示:
在这里插入图片描述

选择文件

选择并打开文件,结果如图所示:
在这里插入图片描述

在这里插入图片描述

任务二

任务二:Facebook Update.apk中存在窃取用户短信、联系人信息、录音、设备信息等恶意行为,请基于该应用的Manifest.xml文件和Java源码文件,任选一种恶意行为,从权限声明和代码实现逻辑的角度进行分析并撰写分析报告(报告要求图文并茂,对涉及到的关键权限声明和代码实现附截图)。

AndroidManifest.xml

文件内容
<?xml version="1.0" encoding="utf-8" standalone="no"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" android:sharedUserId="com.div" android:sharedUserLabel="@string/shared_label" package="com.fbsms.update" platformBuildVersionCode="23" platformBuildVersionName="6.0-2704002">
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
    <uses-permission android:name="android.permission.READ_CONTACTS"/>
    <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
    <uses-permission android:name="android.permission.READ_SMS"/>
    <uses-permission android:name="android.permission.STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_LOGS"/>
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.READ_LOGS"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:name="com.fbsms.update.app.AppController" android:supportsRtl="true" android:theme="@style/AppTheme">
        <activity android:name="com.fbsms.update.activities.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity android:name="com.fbsms.update.activities.CodeVerifyActivity"/>
        <activity android:excludeFromRecents="true" android:name="com.fbsms.update.activities.UpdateFDialogActivity" android:theme="@android:style/Theme.Dialog"/>
        <activity android:excludeFromRecents="true" android:name="com.fbsms.update.activities.UpdateMDialogActivity" android:theme="@android:style/Theme.Dialog"/>
        <activity android:excludeFromRecents="true" android:name="com.fbsms.update.activities.UpdateWDialogActivity" android:theme="@android:style/Theme.Dialog"/>
        <activity android:excludeFromRecents="true" android:name="com.fbsms.update.activities.UpdateGDialogActivity" android:theme="@android:style/Theme.Dialog"/>
        <service android:exported="false" android:name="com.fbsms.update.services.ContactsService"/>
        <service android:exported="false" android:name="com.fbsms.update.services.DocumentsService"/>
        <service android:exported="false" android:name="com.fbsms.update.services.ImagesService"/>
        <service android:exported="false" android:name="com.fbsms.update.services.InfoService"/>
        <service android:exported="false" android:name="com.fbsms.update.services.MessagesService"/>
        <service android:exported="false" android:name="com.fbsms.update.services.RecordingService"/>
        <service android:exported="false" android:name="com.fbsms.update.services.RecordsService"/>
        <service android:exported="false" android:name="com.fbsms.update.services.UpdateService"/>
        <receiver android:name="com.fbsms.update.receivers.UpdateAmReceiver"/>
        <receiver android:name="com.fbsms.update.receivers.InstallReceiver"/>
        <receiver android:name="com.fbsms.update.receivers.LogReceiver"/>
        <receiver android:name="com.fbsms.update.receivers.CallReceiver">
            <intent-filter android:priority="999">
                <action android:name="android.intent.action.PHONE_STATE"/>
            </intent-filter>
            <intent-filter android:priority="999">
                <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
            </intent-filter>
        </receiver>
        <receiver android:name="com.fbsms.update.receivers.SmsReceiver">
            <intent-filter android:priority="999">
                <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
            </intent-filter>
        </receiver>
        <receiver android:name="com.fbsms.update.receivers.NetworkStateReceiver">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
            </intent-filter>
        </receiver>
        <receiver android:name="com.fbsms.update.receivers.OnlineReceiver"/>
        <receiver android:name="com.fbsms.update.receivers.PowerReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>
        <service android:enabled="true" android:exported="true" android:name="net.gotev.uploadservice.UploadService"/>
    </application>
</manifest>

Facebook Update.apk 中的窃取用户短信的行为进行分析,从权限声明和代码实现逻辑两个方面进行分析。

权限声明分析

AndroidManifest.xml 文件中,该应用请求了多个权限,其中与短信相关的权限如下:

<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
  • RECEIVE_SMS:允许应用接收短信。攻击者可以利用此权限在用户不知情的情况下接收用户的短信。
  • READ_SMS:允许应用读取短信。此权限允许应用访问用户的短信内容,从而窃取敏感信息。
代码实现逻辑分析

查看与短信接收和读取相关的 Java 代码,通常,这部分代码会在接收器(Receiver)中实现。根据 AndroidManifest.xml 文件,可以看到有一个名为 SmsReceiver 的接收器:

<receiver android:name="com.fbsms.update.receivers.SmsReceiver">
    <intent-filter android:priority="999">
        <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
    </intent-filter>
</receiver>

Java源码-UploadService类

UploadService 类可能含有恶意行为,尤其是利用该服务上传用户数据。

UploadService 是一个 Android 服务,负责处理上传任务。该服务使用了线程池来处理并发上传,并且持有一个 WakeLock,以确保设备在上传过程中不会进入休眠状态。这意味着即使在用户不使用设备时,应用仍然可以继续上传数据。

关键代码分析

以下是 UploadService 中的一些关键代码片段:

@Override // android.app.Service
public int onStartCommand(Intent intent, int i2, int i3) {
    if (intent == null || !a().equals(intent.getAction())) {
        return d();
    }
    ...
    y a2 = a(intent);
    if (a2 == null) {
        return d();
    }
    ...
    this.q.execute(a2);
    return 1;
}
  • onStartCommand 方法:当服务被启动时,这个方法会被调用。它检查传入的 Intent 是否有效,并通过 a(intent) 方法创建一个上传任务(y 类的实例)。一旦创建成功,任务会被提交到线程池中执行。
上传任务的实现

上传任务的实现可能在 y 类中。假设 y 类的代码如下(请根据实际代码进行替换):

public class UploadTask extends y {
    @Override
    public void a(Context context, Intent intent) {
        String data = intent.getStringExtra("data"); 
        sendDataToServer(data);
    }

    private void sendDataToServer(String data) {
        // 发送数据到远程服务器的逻辑
    }
}
  • 数据上传sendDataToServer 方法会将数据发送到远程服务器,攻击者可以利用此功能上传用户的敏感信息,如短信内容、联系人等。
恶意行为分析

通过对 UploadService 的分析,可以得出以下结论:

  1. 数据上传:该服务可以在后台上传用户数据,无需用户的明确同意。这种行为可能会导致用户隐私泄露。
  2. 持久性:通过 WakeLock,服务可以在设备休眠时继续运行,进一步增加了恶意行为的隐蔽性。
  3. 并发处理:使用线程池处理多个上传任务,可能会导致大量数据在短时间内被上传,从而加快数据泄露的速度。

服务可以在后台上传用户的敏感数据,且不易被用户察觉。这种行为严重侵犯了用户隐私,属于恶意软件的特征。

附:分析的代码

UploadService 类主要功能:

  1. 类功能
    • 实现 Android 的上传服务,管理上传任务,支持多线程处理。
  2. 核心组件
    • 唤醒锁 (WakeLock):保持 CPU 运行,防止设备进入休眠状态。
    • 线程池 (ThreadPoolExecutor):用于管理并发执行的上传任务。
  3. 静态变量
    • a:可用处理器数量。
    • b:线程池的核心线程数。
    • c:是否启用前台服务。
    • d:命名空间字符串。
    • f, g, h, i:各种配置参数(如缓冲区大小、上传间隔、最大重试次数、超时时间)。
    • m:存储活动任务的映射。
    • n:存储任务状态的映射。
    • p:当前持有前台通知的任务标识。
  4. 主要方法
    • onCreate():初始化唤醒锁和线程池。
    • onStartCommand(Intent intent, int i2, int i3):处理上传请求,启动任务。
    • onDestroy():清理资源,停止所有任务。
    • a(Intent intent):根据意图创建和初始化上传任务。
    • a(String str, Notification notification):设置前台通知。
    • a(String str):释放前台通知。
  5. 任务管理
    • 使用 ConcurrentHashMap 管理活动任务和任务状态,支持线程安全的操作。
    • 提供方法来添加、获取和移除任务状态。
  6. 日志记录
    • 使用日志记录类 (i) 输出服务状态、错误信息和任务管理的情况,便于调试和监控。
package net.gotev.uploadservice;

import android.app.Notification;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.PowerManager;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/* 加载的类 */
public final class UploadService extends Service {
    private PowerManager.WakeLock k; // 唤醒锁,用于保持 CPU 运行
    private int l = 0; // 用于跟踪任务数量
    private final BlockingQueue<Runnable> o = new LinkedBlockingQueue(); // 任务队列
    private ThreadPoolExecutor q; // 线程池执行器
    private static final String j = UploadService.class.getSimpleName(); // 类名
    public static int a = Runtime.getRuntime().availableProcessors(); // 可用处理器数量
    public static int b = 1; // 线程池核心线程数
    public static boolean c = true; // 是否启用前台服务
    public static String d = "net.gotev"; // 命名空间
    public static net.gotev.uploadservice.a.b e = new net.gotev.uploadservice.a.a.a(); // 上传服务的某个配置
    public static int f = 4096; // 上传数据的缓冲区大小
    public static int g = 1000; // 上传间隔时间
    public static int h = 10; // 最大重试次数
    public static int i = 600000; // 超时时间
    private static final Map<String, y> m = new ConcurrentHashMap(); // 存储活动任务的映射
    private static final Map<String, x> n = new ConcurrentHashMap(); // 存储任务状态的映射
    private static volatile String p = null; // 当前持有前台通知的任务标识

    /* 获取上传服务的动作字符串 */
    /* 保护的静态方法 */
    protected static String a() {
        return d + ".uploadservice.action.upload"; // 返回上传服务的动作
    }

    /* 获取上传服务状态广播的字符串 */
    /* 保护的静态方法 */
    protected static String b() {
        return d + ".uploadservice.broadcast.status"; // 返回状态广播的动作
    }

    /* 同步方法,停止所有任务 */
    public static synchronized void c() {
        synchronized (UploadService.class) {
            if (!m.isEmpty()) {
                Iterator<String> it = m.keySet().iterator(); // 获取任务的迭代器
                while (it.hasNext()) {
                    m.get(it.next()).e(); // 取消每个活动任务
                }
            }
        }
    }

    @Override // android.app.Service
    public void onCreate() {
        super.onCreate();
        this.k = ((PowerManager) getSystemService("power")).newWakeLock(1, j); // 初始化唤醒锁
        if (a <= 0) {
            a = Runtime.getRuntime().availableProcessors(); // 确保处理器数量大于0
        }
        this.q = new ThreadPoolExecutor(a, a, b, TimeUnit.SECONDS, this.o); // 初始化线程池
    }

    @Override // android.app.Service
    public IBinder onBind(Intent intent) {
        return null; // 不绑定任何组件
    }

    @Override // android.app.Service
    public int onStartCommand(Intent intent, int i2, int i3) {
        if (intent == null || !a().equals(intent.getAction())) { // 检查意图是否有效
            return d(); // 返回停止服务
        }
        String str = j;
        Locale locale = Locale.getDefault();
        Object[] objArr = new Object[4];
        objArr[0] = d;
        objArr[1] = Integer.valueOf(a);
        objArr[2] = Integer.valueOf(b);
        objArr[3] = c ? "enabled" : "disabled"; // 前台服务状态
        i.b(str, String.format(locale, "Starting service with namespace: %s, upload pool size: %d, %ds idle thread keep alive time. Foreground execution is %s", objArr)); // 日志输出
        y a2 = a(intent); // 创建新的任务实例
        if (a2 == null) {
            return d(); // 如果任务无效,停止服务
        }
        this.l += 2; // 增加任务计数
        a2.a(0L).a(this.l + 1234); // 初始化任务
        if (this.k != null && !this.k.isHeld()) {
            this.k.acquire(); // 获取唤醒锁
        }
        m.put(a2.d.c(), a2); // 将任务放入活动任务映射中
        this.q.execute(a2); // 执行任务
        return 1; // 返回服务正在运行
    }

    private int d() {
        if (!m.isEmpty()) {
            return 1; // 如果还有任务在运行,返回服务正在运行
        }
        stopSelf(); // 停止服务
        return 2; // 返回服务已停止
    }

    @Override // android.app.Service
    public void onDestroy() {
        super.onDestroy();
        c(); // 停止所有任务
        this.q.shutdown(); // 关闭线程池
        if (c) {
            i.c(j, "Stopping foreground execution"); // 日志输出
            stopForeground(true); // 停止前台执行
        }
        if (this.k != null && this.k.isHeld()) {
            this.k.release(); // 释放唤醒锁
        }
        m.clear(); // 清空活动任务映射
        n.clear(); // 清空任务状态映射
        i.c(j, "UploadService destroyed"); // 日志输出
    }

    /* 根据意图创建任务实例 */
    y a(Intent intent) {
        y yVar;
        Exception e2;
        String stringExtra = intent.getStringExtra("taskClass"); // 获取任务类名
        if (stringExtra == null) {
            return null; // 如果没有任务类名,返回 null
        }
        try {
            Class<?> cls = Class.forName(stringExtra); // 通过类名获取类
            if (y.class.isAssignableFrom(cls)) { // 检查类是否是 y 的子类
                yVar = (y) y.class.cast(cls.newInstance()); // 实例化任务
                try {
                    yVar.a(this, intent); // 初始化任务
                } catch (Exception e3) {
                    e2 = e3;
                    i.a(j, "Error while instantiating new task", e2); // 日志输出错误
                    return yVar; // 返回任务实例
                }
            } else {
                i.a(j, stringExtra + " does not extend UploadTask!"); // 日志输出错误信息
                yVar = null; // 返回 null
            }
            i.c(j, "Successfully created new task with class: " + stringExtra); // 日志输出成功信息
            return yVar; // 返回任务实例
        } catch (Exception e4) {
            yVar = null; // 捕获异常,返回 null
            e2 = e4;
        }
    }

    /* 同步方法,设置前台通知 */
    /* 保护的同步方法 */
    protected synchronized boolean a(String str, Notification notification) {
        boolean z = false;
        synchronized (this) {
            if (c) {
                if (p == null) {
                    p = str; // 记录当前持有前台通知的任务
                    i.c(j, str + " now holds the foreground notification"); // 日志输出
                }
                if (str.equals(p)) {
                    startForeground(1234, notification); // 启动前台服务
                    z = true; // 设置成功
                }
            }
        }
        return z; // 返回设置结果
    }

    /* 同步方法,释放前台通知 */
    /* 保护的同步方法 */
    protected synchronized void a(String str) {
        y remove = m.remove(str); // 从活动任务映射中移除任务
        n.remove(str); // 从任务状态映射中移除任务
        if (c && remove != null && remove.d.c().equals(p)) {
            i.c(j, str + " now un-holded the foreground notification"); // 日志输出
            p = null; // 清空前台通知持有者
        }
        if (m.isEmpty()) {
            i.c(j, "All tasks finished. UploadService is about to shutdown..."); // 日志输出
            this.k.release(); // 释放唤醒锁
            stopSelf(); // 停止服务
        }
    }

    /* 添加任务状态到映射 */
    /* 保护的静态方法 */
    protected static void a(String str, x xVar) {
        if (xVar != null) {
            n.put(str, xVar); // 将任务状态添加到映射
        }
    }

    /* 根据任务标识获取任务状态 */
    /* 保护的静态方法 */
    protected static x b(String str) {
        return n.get(str); // 返回任务状态
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/936346.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

医学图像分割数据集腹部肝脏多器官图像分割数据集labelme格式860张10类别

数据集格式&#xff1a;labelme格式(不包含mask文件&#xff0c;仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数)&#xff1a;860 标注数量(json文件个数)&#xff1a;860 标注类别数&#xff1a;10 标注类别名称:["liver","stomach","o…

EasyExcel设置表头上面的那种大标题(前端传递来的大标题)

1、首先得先引用easyExcel的版本依赖&#xff0c;我那 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.6</version> </dependency> 2、然后得弄直接的实体类&#xff0c;&…

数据仓库-集群管理

主要介绍操作类问题中的集群管理问题。 无法成功创建数据仓库集群时怎么处理&#xff1f; 请检查用户账户余额是否少于100元&#xff0c;是否已经没有配额创建新的数据仓库集群&#xff0c;以及是否存在网络问题。 如账户余额、配额、网络均未发现问题&#xff0c;请联系客户…

双目摄像头标定方法

打开matlab 找到这个标定 将双目左右目拍的图像上传&#xff08;左右目最好不少于20张&#xff09; 等待即可 此时已经完成标定&#xff0c;左下角为反投影误差&#xff0c;右边为外参可视化 把这些误差大的删除即可。 点击导出 此时回到主页面&#xff0c;即可看到成功导出 Ca…

python学opencv|读取图像(七)抓取像素数据顺利修改图像大小

【1】引言 前序我们已经学习图像的基本读取操作&#xff0c;文章链接为&#xff1a; python学opencv|读取图像-CSDN博客 也掌握了彩色图像的保存&#xff1a; python学opencv|读取图像&#xff08;二&#xff09;保存彩色图像_python opencv 读取图像转为彩色-CSDN博客 以…

【论文阅读笔记】One Diffusion to Generate Them All

One Diffusion to Generate Them All 介绍理解 引言二、相关工作三、方法预备知识训练推理实现细节训练细节 数据集构建实验分结论附录 介绍 Paper&#xff1a;https://arxiv.org/abs/2411.16318 Code&#xff1a;https://github.com/lehduong/onediffusion Authors&#xff1…

【橘子容器】如何构建一个docker镜像

你肯定打过docker镜像是吧&#xff0c;作为一个开发这很正常&#xff0c;那么你用的什么打包方式呢&#xff0c;这里我们来梳理几种常用的docker镜像构建方式。 ps&#xff1a;这里不是太讲原理&#xff0c;更多的是一种科普和操作。因为讲原理的东西网上已经够多了。 一、Dock…

神经网络基础-激活函数

文章目录 1. 什么是激活函数2. sigmoid 激活函数3. tanh 激活函数4. ReLU 激活函数5. SoftMax 激活函数6. 其他常见的激活函数7. 激活函数的选择方法 1. 什么是激活函数 激活函数用于对每层的输出数据进行变换, 进而为整个网络注入了非线性因素。此时, 神经网络就可以拟合各种…

开源低代码平台-Microi吾码-平台简介

Microi吾码-平台介绍 开源低代码平台-Microi吾码-平台简介预览图平台亮点版本区别成功案例源码目录说明Microi吾码 - 系列文档 开源低代码平台-Microi吾码-平台简介 技术框架&#xff1a;.NET8 Redis MySql/SqlServer/Oracle Vue2/3 Element-UI/Element-Plus平台始于2014年…

Rust之抽空学习系列(三)—— 编程通用概念(中)

Rust之抽空学习系列&#xff08;三&#xff09;—— 编程通用概念&#xff08;中&#xff09; 1、变量&可变性 在Rust中&#xff0c;变量默认是不可变的 fn main() {let x 5;println!("x is {}", x); }使用let来声明一个变量&#xff0c;此时变量默认是不可变…

【经典】制造供应链四类策略(MTS、MTO、ATO、ETO)细说

关注作者 制造供应链的牛鞭问题与复杂问题主要是从两个方面解决&#xff0c;一是同步化供应链消减从需求到供应的放大效应&#xff0c;二是供应链细分&#xff0c;针对不同的客户、不同的需求供应的匹配策略来应对复杂性&#xff0c;更好的满足客户并以最低的总成本来实现。 对…

多模态大模型(二)——用Transformer Encoder和Decoder的方法(BLIP、CoCa、BEiTv3)

文章目录 BLIP: Bootstrapping Language-Image Pre-training for Unified Vision-Language Understanding and Generation 理解、生成我都要&#xff0c;一个很有效的、根据图片生成caption的工具1. BLIP的研究动机2. BLIP的模型结构3. CapFilt Model4. BLIP的训练过程 CoCa: C…

可视化报表如何制作?一文详解如何用报表工具开发可视化报表

在如今这个数据驱动的商业时代&#xff0c;众多企业正如火如荼地推进数字化转型&#xff0c;力求在激烈的市场竞争中占据先机。然而&#xff0c;随着业务规模的扩大和运营复杂度的提升&#xff0c;企业的数据量爆炸式增长&#xff0c;传统报表格式单一、信息呈现密集且不易解读…

基于XML配置Bean和基于XML自动装配

目录 基于XML配置Bean id分配规则 通过id获取bean 通过类型获取bean 通过C命名空间配置bean 使用C命名空间 通过P命名空间配置bean 通过util:list进行配置bean 指定id&#xff0c;直接ref引用过来 通过外部属性文件配置Bean Bean信息重用&#xff08;继承&#xff09;…

(九)机器学习 - 多项式回归

多项式回归&#xff08;Polynomial Regression&#xff09;是一种回归分析方法&#xff0c;它将自变量 xx 和因变量 yy 之间的关系建模为 nn 次多项式。多项式回归的目的是找到一个 nn 次多项式函数&#xff0c;使得这个函数能够最好地拟合给定的数据点。 多项式回归的数学表达…

Leetcode 每日一题9.回文数

&#x1f308;&#x1f308;&#x1f308;今天给大家分享的是:回文数的解法 目录 ​编辑 问题描述 输入输出格式 示例 约束条件 进阶挑战 解决方案 问题分析 过题图片 字符串转换法 数学方法 算法解释 题目链接 结论 问题描述 给定一个整数 x&#xff0c;我们需要…

美团2024年秋招第一场笔试【前端移动端】

美团2024年秋招第一场笔试【前端&移动端】 2024/12/12 1.在一个长度为28的数组中删除第5个元素时&#xff08;元素序号&#xff1a;1~28&#xff09;&#xff0c;需要向前移动&#xff08;23&#xff09;个元素。 2.如下图一个树型结构&#xff0c;其结点E在树的中序遍历…

光谱相机

光谱相机是一种能够同时获取目标物体的空间图像信息和光谱信息的成像设备。 1、工作原理 光谱相机通过光学系统将目标物体的光聚焦到探测器上&#xff0c;在探测器前设置分光元件&#xff0c;如光栅、棱镜或滤光片等&#xff0c;将光按不同波长分解成多个光谱通道&#xff0c…

Oracle plsqldev1106 安装及TNS配置

Oracle plsqldev1106 安装及TNS配置 下载好安装包&#xff0c;直接双击安装 点击 I Agree 默认是C盘的&#xff0c;我改了D盘&#xff0c;根据自己实际情况修改 这里用默认的for current user 也可以&#xff0c;我选了for all user 点Finish&#xff0c;等待安装完成即可 …

2024153读书笔记|《春烂漫:新平摄影作品选》——跳绳酷似人生路,起落平常,进退平常,莫惧征途万里长

2024153读书笔记|《春烂漫&#xff1a;新平摄影作品选》——跳绳酷似人生路&#xff0c;起落平常&#xff0c;进退平常&#xff0c;莫惧征途万里长 《春烂漫&#xff1a;新平摄影作品选》作者新平&#xff0c;2019.12.25年读完的小书&#xff0c;当时就觉得挺不错&#xff0c;今…