android app病毒扫描_android 扫描nfc打开app - CSDN
  • 分析 源码 自定义View VirusKillingjava 然后在布局中的使用 activity_antivirusixml 最后在Activity中的使用 ...那个扫描状态的自定义View,其实就是2个圆,2根线,一个扇形(只不过扇形在动而已),一个进度的文字,再

    直接上图:

    最近要做杀毒界面的设计,所以想把这个自定义View自己实现一下.

    分析

    1.那个扫描状态的自定义View,其实就是2个圆,2根线,一个扇形(只不过扇形在动而已),一个进度的文字,再加一个%符号.

    2.根据自定义View的宽和高,可以把2个圆按照比例画出来,那中间的十字交叉线也是一样的.

    3.那个扇形有点难实现,首先需要一个矩形来包裹这个扇形,其次每隔一定的事件,扇形需要旋转(这个可以用重新绘制,然后让扇形的角度+1).矩形的4边必须是相等的,其次中心必须在圆形的中心,这样一来,矩形的4条边就很好决定了,矩形左侧的X坐标:mWidth * 0.1,矩形顶部的Y坐标:mWidth * 0.1,矩形右侧的X坐标:mWidth * 0.9,矩形底部的Y坐标:mWidth * 0.9 .

    4.有了扇形,其次就是让进度文字居中显示的难题.首先,必须要拿到文字的宽度和高度,然后根据圆心来决定文字的起始x坐标和起始y坐标.

    //拿到字符串的宽度
    mTextWidth = mTextPaint.measureText(str);
    //文字的x轴坐标
    mTextX = (getWidth() - mTextWidth) / 2;
    //文字的y轴坐标
    //描述给定文本大小的字体的各种指标的类。
    // 记住,Y值增加下降,所以这些值将是正的,测量距离上升的值将为负。 这个类由getFontMetrics()返回。
    Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
    mTextY = getHeight() / 2 + (Math.abs(fontMetrics.ascent) - fontMetrics.descent) / 2;
    //画字
     canvas.drawText(text, mTextX, mTextY, mTextPaint);
    

    5.最后就是进度文字旁边的那个%符号了,这个只要进度文字放置好了,只需要把这个放在进度文字的右边就可以了.

    源码

    自定义View VirusKilling.java

        public class VirusKilling extends View {
    
            private static final String TAG = "VirusKilling";
    
            //2个圆(外圆和内圆)  2根线(十字交叉)   一行文字(中间的显示扫描进度的文字)    2个扇形(扫描 渐变)
            /**
             * 控件宽度
             */
            private float mWidth;
            /**
             * 控件高度
             */
            private float mHeight;
            /**
             * 2圆的画笔
             */
            private Paint mCirclePaint;
            /**
             * 2根线的画笔
             */
            private Paint mLinePaint;
            /**
             * 中间进度文字的画笔
             */
            private Paint mTextPaint;
            /**
             * 中间的进度旁边的 % 符号
             */
            private Paint mPercentSignPaint;
            /**
             * 扇形的画笔
             */
            private Paint mArcPaint;
            /**
             * 扇形的画笔
             */
            private Paint mArcPaint2;
            /**
             * 扇形外面的矩形
             */
            private RectF mRectF;
            /**
             * 内圆半径
             */
            private float radiusInside;
            /**
             * 外圆半径
             */
            private float radiusExt;
            /**
             * 扇形旋转的开始的角度
             */
            private float startAngle = 360;
            /**
             * 是否在旋转
             */
            private boolean running = true;
            /**
             * 开一个子线程,去旋转  扇形
             */
            private Thread mThread;
            /**
             * 更新UI了
             */
            private static final int UPDATE_UI = 1000;
            /**
             * 进度
             */
            private int schedule = 0;
            private Handler mHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                        case UPDATE_UI:
                            synchronized (this) {
                                if (startAngle < 1) {
                                    startAngle = 360;
                                } else {
                                    startAngle--;
                                    invalidate();
                                }
                            }
                            break;
                    }
                }
            };
            /**
             * 中间的进度文字的宽度
             */
            private float mTextWidth;
            /**
             * 中间的进度的文字的X
             */
            private float mTextX;
            /**
             * 中间的进度的文字的Y
             */
            private float mTextY;
            /**
             * 默认扫描速度  20毫秒前进1次  1次1°C
             */
            private int mScanSpeed = 20;
    
    
            public VirusKilling(Context context) {
                super(context);
                initData();
            }
    
    
            public VirusKilling(Context context, @Nullable AttributeSet attrs) {
                super(context, attrs);
                initData();
            }
    
            public VirusKilling(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
                super(context, attrs, defStyleAttr);
                initData();
            }
    
            /**
             * 初始化数据
             */
            private void initData() {
                //圆的画笔
                mCirclePaint = new Paint();
                mCirclePaint.setStrokeWidth(4);  //设置画线的宽度
                mCirclePaint.setAntiAlias(true); //
                mCirclePaint.setStyle(Paint.Style.STROKE);
                mCirclePaint.setColor(Color.parseColor("#E3F0FC"));
    
                //2根线的画笔
                mLinePaint = new Paint();
                mLinePaint.setStrokeWidth(4);  //设置画线的宽度
                mLinePaint.setAntiAlias(true); //
                mLinePaint.setStyle(Paint.Style.STROKE);
                mLinePaint.setColor(Color.parseColor("#E3F0FC"));
    
                //中间的进度文字
                mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
                mTextPaint.setTextSize(90f);
                mTextPaint.setColor(Color.parseColor("#000000"));
    
                //进度旁边的 %  符号
                mPercentSignPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
                mPercentSignPaint.setTextSize(30f);
                mPercentSignPaint.setColor(Color.parseColor("#000000"));
    
                //扇形的画笔
                mArcPaint = new Paint();
                mArcPaint.setStrokeWidth(1);  //设置画线的宽度
                mArcPaint.setColor(Color.parseColor("#2E93FE"));
    
                //引导  扇形 的画笔
                mArcPaint2 = new Paint();
                mArcPaint2.setStrokeWidth(1);  //设置画线的宽度
                mArcPaint2.setColor(Color.parseColor("#3B9BFE"));
            }
    
            //测量自己的宽高
            @Override
            protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                //因为是圆形,所以应该让宽高保持一致
                int width = measureWidth(widthMeasureSpec);
                int height = measureHeight(heightMeasureSpec);
                int suitSize = Math.min(width,height);  //必须是正方形,不然扇形中心不在圆形中心
    
                //该方法必须由onMeasure(int,int)调用来存储测量的宽度和测量高度。
                // 如果没有这样做,将在测量时间触发异常。
                setMeasuredDimension(suitSize, suitSize);
            }
    
            /**
             * 测量View的长度
             */
            private int measureHeight(int measureSpec) {
                int result = 0;
    
                //获取具体的测量模式和大小
                int specMode = MeasureSpec.getMode(measureSpec);
                int specSize = MeasureSpec.getSize(measureSpec);
    
                if (specMode == MeasureSpec.EXACTLY) { //默认的大小(指定了具体的值  比如android:layout_width=100dp)
                    result = measureSpec;
                } else {
                    result = 400;
                    if (specMode == MeasureSpec.AT_MOST) { //wrap_content
                        result = Math.min(result, specSize);
                    }
                }
    
                return result;
            }
    
            /**
             * 测量View的宽度
             */
            private int measureWidth(int measureSpec) {
                int result = 0;
                int specMode = MeasureSpec.getMode(measureSpec);   //获取具体的测量模式(EXACTLY,AT_MOST,UNSPECIFIED)
                int specSize = MeasureSpec.getSize(measureSpec); //获取具体的测量大小
    
                if (specMode == MeasureSpec.EXACTLY) {   //默认模式
                    result = measureSpec;
                } else {
                    result = 400;   //给一个默认的大小
                    if (specMode == MeasureSpec.AT_MOST) {   //如果是wrap_content
                        result = Math.min(result, specSize);   //取最小的  适合控件大小的
                    }
                }
    
                return result;
            }
    
            /*
            * 这个是系统回调方法,是系统调用的,它的方法名已经告诉我们了,这个方法会在这个view的大小发生改变是被系统调用,
            * 我们要记住的就是view
            * 大小变化,这个方法就被执行就可以了。最主要的是,它还在onDraw方法之前调用。
            * */
            @Override
            protected void onSizeChanged(int w, int h, int oldw, int oldh) {
                super.onSizeChanged(w, h, oldw, oldh);
                mWidth = getWidth();
                mHeight = getHeight();
                //扇形外围的矩形
                /*
                首先需要一个矩形来包裹这个扇形,其次每隔一定的事件,扇形需要旋转(这个可以用重新绘制,然后让扇形的角度+1).
                矩形的4边必须是相等的,其次中心必须在圆形的中心,这样一来,
                矩形的4条边就很好决定了,矩形左侧的X坐标:mWidth * 0.1,矩形顶部的Y坐标:mWidth * 0.1,
                矩形右侧的X坐标:mWidth * 0.9,
                矩形底部的Y坐标:mWidth * 0.9
                * 参数:left float:矩形左侧的X坐标 top float:矩形顶部的Y坐标
                * right float:矩形右侧的X坐标 bottom float:矩形底部的Y坐标
                * */
                mRectF = new RectF((float) (mWidth * 0.1), (float) (mWidth * 0.1),
                        (float) (mWidth * 0.9), (float) (mWidth * 0.9));
                // 绘制渐变效果
                LinearGradient gradient = new LinearGradient((float) (mWidth * 0.3),
                        (float) (mWidth * 0.9), (float) (mWidth * 0.1),
                        (float) (mWidth * 0.5),
                        new int[]{Color.parseColor("#B1D6FD"), Color.TRANSPARENT},
                        null, Shader.TileMode.CLAMP);
                mArcPaint.setShader(gradient);
    
                // 2个圆的半径
                radiusExt = (float) (mWidth * 0.4);
                radiusInside = (float) (mWidth * 0.25);
            }
    
            @Override
            protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
                canvasArc(canvas);    //话扇形
                canvasArc2(canvas);   //画扇形  引导
                canvasLines(canvas);  //画线
                canvasCircle(canvas); //画圆
                canvasSche(canvas);  //画进度
                canvasPercent(canvas); //画 %
    
            }
    
            /**
             * 画 % 符号
             *
             * @param canvas
             */
            private void canvasPercent(Canvas canvas) {
                //符号的X
                float perSignX = mTextX + mTextWidth + 5;
    
                //符号的Y
                float perSignY = getHeight() / 2 + 20;
    
                //画字
                canvas.drawText("%", perSignX, perSignY, mPercentSignPaint);
            }
    
            /**
             * 画文字  进度
             *
             * @param canvas
             */
            private void canvasSche(Canvas canvas) {
                String text = String.valueOf(schedule);
                //拿到字符串的宽度
                mTextWidth = mTextPaint.measureText(text);
                //文字的x轴坐标
                mTextX = (getWidth() - mTextWidth) / 2;
                //文字的y轴坐标
                //描述给定文本大小的字体的各种指标的类。
                // 记住,Y值增加下降,所以这些值将是正的,测量距离上升的值将为负。 这个类由getFontMetrics()返回。
                Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
                mTextY = getHeight() / 2 + (Math.abs(fontMetrics.ascent) - fontMetrics.descent) / 2;
                //画字
                canvas.drawText(text, mTextX, mTextY, mTextPaint);
            }
    
            /**
             * 绘制2根线
             *
             * @param canvas
             */
            private void canvasLines(Canvas canvas) {
                //横线
                canvas.drawLine((float) (mWidth * 0.1), (float) (mHeight * 0.5),
                        (float) (mWidth * 0.9), (float) (mHeight * 0.5), mLinePaint);
                //竖线
                canvas.drawLine((float) (mWidth * 0.5), (float) (mHeight * 0.1),
                        (float) (mWidth * 0.5), (float) (mHeight * 0.9), mLinePaint);
            }
    
            /**
             * 绘制旋转的扇形
             *
             * @param canvas
             */
            private void canvasArc(Canvas canvas) {
                canvas.drawArc(mRectF, startAngle, 100, true, mArcPaint);
            }
    
            /**
             * 绘制旋转的扇形
             *
             * @param canvas
             */
            private void canvasArc2(Canvas canvas) {
                //第二个的扇形的角度是1,为什么是1呢,原来我这里只是想要它旋转角度的效果,并不需要它有多宽,
                // 所以在具体实现自定义View的时候,也要学会活学活用。
                canvas.drawArc(mRectF, startAngle, 2, true, mArcPaint2);
            }
    
            /**
             * 绘制四个圆
             *
             * @param canvas
             */
            private void canvasCircle(Canvas canvas) {
                canvas.drawCircle(mWidth / 2, mHeight / 2, radiusInside, mCirclePaint);
                canvas.drawCircle(mWidth / 2, mHeight / 2, radiusExt, mCirclePaint);
            }
    
            /**
             * 开始扫描 动画
             */
            public void startScanning() {
                //运行状态改为true
            running = true;
                //开一个子线程
                mThread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        while (true) {
                            try {
                                Thread.sleep(mScanSpeed);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
    
                            //如果正在执行动画,则发送消息,叫UI线程更新UI
                            if (running) {
                                mHandler.sendEmptyMessage(UPDATE_UI);
                            } else {
                                break;
                            }
                        }
                    }
                });
                mThread.start();
    
            }
    
            /**
             * 重新开启动画
             */
            public void restartScan() {
                running = true;
            }
    
            /**
             * 暂停动画
             */
            public void stopScan() {
                running = false;
            }
    
            /**
             * 是否在转动
             *
             * @return
             */
            public boolean isRunning() {
                return running;
            }
    
            /**
             * 获取当前进度
             *
             * @return 当前进度
             */
            public int getSchedule() {
                return schedule;
            }
    
            /**
             * 设置进度
             *
             * @param schedule 进度
             */
            public void setSchedule(int schedule) {
                if (schedule >= 0 && schedule <= 100) {
                    this.schedule = schedule;
                    this.postInvalidate();  //非UI线程更新UI
                }
            }
    
            /**
             * 设置扫描速度   1000~20   数字越小扫描速度越快
             *
             * @param mScanSpeed 速度  1000~20
             */
            public void setmScanSpeed(int mScanSpeed) {
                //检查参数
                if (mScanSpeed < 20 || mScanSpeed > 1000) {
                    mScanSpeed = 50;  //设置为速度默认值
                } else {
                    this.mScanSpeed = mScanSpeed;
                }
            }
    
            /**
             * 获取当前扫描速度
             *
             * @return
             */
            public int getmScanSpeed() {
                return mScanSpeed;
            }
        }
    

    然后在布局中的使用 activity_antivirusi.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="com.xfhy.mobilesafe.activity.AntivirusiActivity">
    
        <!--病毒查杀界面-->
    
        <TextView
            style="@style/TitleTheme"
            android:text="病毒查杀"/>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="2"
            android:orientation="vertical">
    
            <!--自定义View 扫描病毒的View-->
            <com.xfhy.mobilesafe.view.VirusKilling
                android:id="@+id/vk_scan_virus"
                android:layout_width="200dp"
                android:layout_height="200dp"
                android:layout_gravity="center_horizontal"
                />
    
            <TextView
                android:id="@+id/tv_scan_app_package"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:text="正在扫描:com.xfhy.hehe"
                android:textColor="@color/bright_foreground_light_disabled"
                android:textSize="18sp"/>
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="2"
            android:orientation="vertical"
            android:paddingBottom="10dp"
            android:paddingEnd="20dp"
            android:paddingStart="20dp"
            android:paddingTop="10dp">
    
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1">
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentStart="true"
                    android:gravity="center_vertical"
                    android:text="病毒"
                    android:textColor="@color/colorBlack"
                    android:textSize="22sp"
                    />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentEnd="true"
                    android:gravity="center_vertical"
                    android:text="正在扫描..."
                    android:textColor="@color/bright_foreground_light_disabled"
                    android:textSize="18sp"
                    />
    
            </RelativeLayout>
    
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1">
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentStart="true"
                    android:gravity="center_vertical"
                    android:text="风险软件"
                    android:textColor="@color/colorBlack"
                    android:textSize="22sp"
                    />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentEnd="true"
                    android:gravity="center_vertical"
                    android:text="正在扫描..."
                    android:textColor="@color/bright_foreground_light_disabled"
                    android:textSize="18sp"
                    />
            </RelativeLayout>
    
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1">
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentStart="true"
                    android:gravity="center_vertical"
                    android:text="非官方证书"
                    android:textColor="@color/colorBlack"
                    android:textSize="22sp"
                    />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentEnd="true"
                    android:gravity="center_vertical"
                    android:text="正在扫描..."
                    android:textColor="@color/bright_foreground_light_disabled"
                    android:textSize="18sp"
                    />
    
            </RelativeLayout>
    
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1">
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentStart="true"
                    android:gravity="center_vertical"
                    android:text="云查杀"
                    android:textColor="@color/colorBlack"
                    android:textSize="22sp"
                    />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentEnd="true"
                    android:gravity="center_vertical"
                    android:text="正在扫描..."
                    android:textColor="@color/bright_foreground_light_disabled"
                    android:textSize="18sp"
                    />
            </RelativeLayout>
    
        </LinearLayout>
    
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="20dp"
            android:background="@drawable/selector_button_scan_bg"
            android:text="停止扫描"
            android:textColor="#017EFF"
            android:textSize="20sp"/>
    
    </LinearLayout>
    

    最后在Activity中的使用 AntivirusiActivity.java

    public class AntivirusiActivity extends BaseActivity {
    
        @BindView(R.id.vk_scan_virus)
        VirusKilling vkScanVirus;
        private int sce;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_antivirusi);
            ButterKnife.bind(this);
    
            vkScanVirus.startScanning();
            sce = 0;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        if (sce > 100) {
                            sce = 0;
                        }
                        try {
                            Thread.sleep(200);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        vkScanVirus.setSchedule(sce++);
                    }
    
                }
            }).start();
        }
    }
    

    由于源码中注释非常详细,在中间就不再过多的叙述啦.
    好东西要大家一起分享.

    本文参考

    http://www.jianshu.com/p/1728b725b4a6
    http://blog.csdn.net/qq_25193681/article/details/51891117

    展开全文
  • Android APP安全测试

    2018-03-31 22:59:34
    移动APP面临的威胁:木马、病毒、钓鱼、破解、篡改、二次打包、账号窃取、广告植入、信息劫持等一、Android APP安全测试思路分析:1.安全测试工具2.基础环境3.数据安全4.程序安全5.数据传输6.业务安全二、APP面临的...

    移动APP面临的威胁:木马、病毒、钓鱼、破解、篡改、二次打包、账号窃取、广告植入、信息劫持等

    一、Android APP安全测试思路分析:

    1.安全测试工具

    2.基础环境

    3.数据安全

    4.程序安全

    5.数据传输

    6.业务安全

    二、APP面临的风险

    1.不安全的服务器访问控制

    2.不安全的数据存储

    3.传输层保护不足

    4.非预期的数据泄露

    5.脆弱的认证和授权

    6.已知的不安全加密方式

    7.客户端注入

    8.通过不被信任的输入改变安全设定

    9.会话处理不当

    10.缺乏二进制保护

    三、业务数据流

    数据输入基础环境安全
    数据存储数据安全
    内部传输程序安全
    通讯通讯安全
    服务器业务安全

     四、所需知识

    Linux     Android系统编程         逆向       其它知识  
    常用操作命令adb命令Java语法Smali语法http/ https
     安全框架NDK编程Dex文件格式html
     程序运行机制SDK编程ARM汇编XSS
     常见漏洞  JS

    五、使用工具

    大部分工具获取地址:http://www.androiddevtools.cn/

    基础环境安全数据安全程序安全通讯安全安卓原生工具
    APKToollogcat     DrozerKeytoolBusybox

    Dex2jar、JD-Gui

    Sublime TextSmaliViewBurpsuitesetpropex
    Jeb IDASQLiteIntent FuzzerTcpdumpstrace
    Droid_injectso
     Fiddler

    六、基础环境安全

    1.基础环境安全测试内容:反编译、逆向、Intent注入、键盘记录、屏幕截取等

    2.反编译:工具获取地址:http://www.androiddevtools.cn/

      反编译步骤请参考:https://blog.csdn.net/s13383754499/article/details/78914592

    3.反编译后能干啥?修改资源文件,比如替换应用图标、名称、版本,甚至植入广告等


    七、数据安全

     1.数据存储、日志,硬编码中的用户信息泄露,应用数据一般都存放在/data/data/<appname>目录下,检查sharedpreference 、files、databases存储的用户信息,比如用户的密码、电话、银行卡等信息是否明文显示,或不安全的加密方式

    2.查看数据库文件:chmod修改文件夹或文件权限,使用adb pull命令导出到本地,然后用数据库软件查看,比如SQLite

    3.日志的检测,检查内容和上面相似

     adb shell

    ps | grep mw 查找到客户端的进程号

    logcat | grep pid 查看进程输出的日志

    4.硬编码检测:反编译出来的Smali源码中搜索关键字符串,password,admin,AES_KEY等,是否有账号密码等信息

    八、程序安全

    1.防止二次打包,篡改

    2.Smali :     https://blog.csdn.net/lixpjita39/article/details/75193833


    九、安全扫描工具

    在google市场下个AVL pro用里面的应用分析器


    十、其它测试推荐

    1.IOS

    https://bbs.pediy.com/thread-163216.htm

    2.Android

    https://bbs.pediy.com/thread-163215.htm

    (以上内容纯属学习摘取,大家共同学习进步)

    展开全文
  • androguard是Android静态分析工具,可以解析APK/DEX文件,并提供相关操作API 比如get_xref_from和get_xref_to,可以得到某个函数被哪些函数调用过和调用过哪些函数。通过合理的使用这些API,可以帮助我们确定受关注...

    背景

    androguard是Android静态分析工具,可以解析APK/DEX文件,并提供相关操作API

    比如get_xref_from和get_xref_to,可以得到某个函数被哪些函数调用过和调用过哪些函数。通过合理的使用这些API,可以帮助我们确定受关注的接口是否被某些类/入口调用过,自动化发现漏洞(类似工具JAndroid

     

    源码阅读

    androguard API文档对整个架构没有作说明,只有通过阅读源码了解

     

    为了便于理解源码先了解如何使用:

    from androguard import misc

    a, d, dx = misc.AnalyzeAPK(pkg)

    其中a表示apk文件结构,d表示dex文件结构,dx表示dex文件分析

    几乎所有操作均在dx上发生

     

    下面是需要重点关注的代码

    1、core/analysis/analysis.py:dex分析模块

    其中包含重点子模块:

    Analysis,等同于dx

    ClassAnalysis,类模块

    MethodClassAnalysis,类中方法模块(可获取归属类)

    MethodAnalysis,方法模块

    StringAnalysis,字符串模块

    FieldClassAnalysis,类中变量模块(可获得归属类)

    ExternalClass、ExternalMethod,外部类,不在dex中的API

    可重点看前3个子模块,发现可使用API

     

    2、core/bytecodes/dvm.py:dex结构

    EncodedMethod,方法结构

    ClassDefItem,类结构

    其中包含对类和结构的操作API

     

    实例操作

    1、找到所有调用过webview.loadUrl方法的Activity,Activity必须导出且浏览器可启动(browsable)

    思路:先获取所有调用过webview.loadUrl方法的类(get_xref_from()),然后判断符合条件的Activity是否在这些类中

    需要注意的是get_xref_from获取的是直接调用的那些类,对于间接调用(activity->classA->classB->classC→webview.loadUrl)需要额外操作

    这里解决办法:递归方式保存所有调用链上的类,代码如下:

    def getCallstack(m, callstack, count):
        ##
        #获取函数的调用树,全部存储callstack list
        #count 用于防止栈益处,重载函数可能溢出
        ##
        ref = m.get_xref_from()
        if not ref or len(ref) == 0:
            return
        for c,m,_ in ref:
            callstack.append(c.name+':'+m.name)
            if count[0] > 500:
                print('====max '+c.name+':'+m.name)
                return
            count[0] = count[0]+1
            getCallstack(c.get_method_analysis(m), callstack, count)

     

    因为调用链是树结构,保存所有完整调用链算法较复杂,这里简化处理保存在list中,缺点是无法知道完整的调用链。(另外有些重载函数相互调用过程,会出现递归无法退出,故设定count=500)

    获取符合条件activity可参考工具https://github.com/zzzzfeng/appstarter

    然后判断activity是否在callstack list中

    for m in dx.classes['Landroid/webkit/WebView;'].get_methods():
        if m.name == 'loadUrl':
            cs = []
            count = [0]
            getCallstack(m, cs, count)
            cs = list(set(cs))
            for r in cs:
                if r.split(':')[0] in browsable_activities:
                    print(r)

     

    2、找到所有调用过Intent.parseUri方法的Activity,Activity必须导出且浏览器可启动(browsable)

    代码

    parseuri = dx.get_method_analysis_by_name('Landroid/content/Intent;', 'parseUri', '(Ljava/lang/String; I)Landroid/content/Intent;')
    cs = []
    count = [0]
    getCallstack(m, cs, count)
    cs = list(set(cs))
    for r in cs:
        if r.split(':')[0] in browsable_activities:
            print(r)

     

    3、找到所有调用过getIntent方法的Activity,Activity必须导出且浏览器可启动(browsable)

    代码

    #1、activity.getIntent() 少见
    # getintent = dx.get_method_analysis_by_name('Landroid/app/Activity;', 'getIntent', '()Landroid/content/Intent;')
    # for _, call, _ in getintent.get_xref_from():
    #     if call.class_name in browsable_activities:
    #         print(call.class_name+' '+call.name)
    
    
    #2、getIntent()
    for c in dx.get_classes():
        ss = []
        cc = c
        while cc and cc.extends != 'Ljava/lang/Object;':
            ss.append(cc.extends)
            cc = dx.classes.get(cc.extends)
        if 'Landroid/app/Activity;' in ss:
            for m in c.get_methods():
                if m.name == 'getIntent':
                    if c.name in browsable_activities:
                        print(c.name)

    使用1方式,获取不到this.getIntent调用,原因是this.getIntent在子类实现。故获取到所有父类(链)包含Landroid/app/Activity;类的类,然后判断是否实现getIntent(调用即实现)

     

    总结

    1、有些API在调用链上,但不一定在执行路径上,即代码不会触发

    2、有些API调用在父类上执行并保存变量,但不是符合条件的activity,而子类是导出Activity,上述例子不能覆盖这种情况。有一种思路解决:保存符合条件的acitity类的父类列表,与获得的callstack进行比对

    3、有些API被系统函数如onCreate调用,onCreate这类函数追溯不到startActivity调用。暂时没有好的解决方法

     

    展开全文
  • 实现一个病毒扫描app——python爬取病毒样本 文章目录开篇再开篇正篇 开篇 最近闲来无事,准备做一个病毒扫描app,那么从哪里开始呢? 首先来分析下一般的查杀步骤都有哪些 基于黑白名单的查杀 这种是有一个庞大...

    实现一个病毒扫描app——python爬取病毒样本

    开篇

    最近闲来无事,准备做一个病毒扫描的app,那么从哪里开始呢?

    首先来分析下一般的查杀步骤都有哪些

    1. 基于黑白名单的查杀

      这种是有一个庞大的数据库,里面放着各个厂商扫出来的病毒样本,里面放着病毒文件md5/病毒各种信息

      只需要将你的包名或者签名或者文件md5传进去就能辨别是不是有毒

    2. 基于特征码的扫描

      这种就是有一个病毒特征码库,通过对apk解包,深度扫描文件里是不是存在病毒

    再开篇

    首先我们要做个病毒库,难道要去网络上把各个厂商的病毒库都拿过来,还是要自己做一个网站等着别人来上传病毒,好像都不行,那得到猴年马月去了,今天 我们要做的就是将网络上的别人做好病毒库用python把他们爬取出来

    正篇

    首先我们使用的是python3,python2就不要搞事情了

    首先先确定要爬取的页面

    # 好吧,我就找到这一个免费的
    urlprefix = 'http://www.virscan.org/reportlist'
    

    然后我们既然做爬虫,咱就要伪装成正常用户

    # 伪装成浏览器访问,适用于拒绝爬虫的网站
    headers = {'User-Agent': 'Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10',
               'Referer': 'http://www.baidu.com/'}
    

    第一步要访问这个界面

    import re
    import urllib.parse
    import urllib.request
    import bs4
    import time
    
    reponse = urllib.request.Request(myurl)
    html = urllib.request.urlopen(reponse).read().decode("utf-8")
    
    # 解析html
    soup = bs4.BeautifulSoup(html, 'html.parser')
    

    拿到了html之后,就可以搞事情了

    界面1

    对,就是要拿到这个里面的这个页数的链接

    # 正则解析页面URL
        pattern = r'/reportlist/\w+'
        liResult = soup.find_all('a', href=re.compile(pattern))
    
        # 找到页面最大值
        maxPage = 1
        for link in liResult:
            url2 = link['href']
            page = url2.split('/')[-1]
            if maxPage < int(page):
                maxPage = int(page)
    
        print(maxPage)
        # 访问查找到url
        for x in range(1, maxPage+1):
            pageUrl = myurl+'/%d' % (x)
            # print(pageUrl)
            getReport(pageUrl)
            time.sleep(1)
    

    通过上面的步骤我们拿到了每一页的url,下面开始访问每一页的数据了

    def getReport(myurl):
        #print('---------getReport-->'+myurl)
        reponse = urllib.request.Request(myurl)
        html = urllib.request.urlopen(reponse).read().decode("utf-8")
        # 解析html
        soup = bs4.BeautifulSoup(html, 'html.parser')
    
        # 查找首页所有a链接,匹配想要的URL格式(v.xxx内容)
        pattern = r'http://v.virscan.org/\w+'  # URL格式
        vLinks = soup.find_all('a', href=re.compile(pattern))
        for vlink in vLinks:
            url3 = urllib.parse.quote(vlink['href'])
            url3 = url3.replace('http%3A', 'http:')
            # print(url3)
            if vlink.has_attr('alt'):
                vn = vlink['alt']
            else:
                vn = ''
            # print(vn)
            # 只扫面和Android相关的病毒链接
            if 'android' in url3.lower():
                # 获取到病毒名称
                if vn == '':
                    vn = url3.split('/')[-1][0:-5]
                    vn = urllib.parse.unquote(vn)
                print('get antivirus name :'+vn)
                getAndroidVirusReport(url3)
                time.sleep(1)
    

    通过上面的代码找到的就是它

    图片2

    然后点进去开始爬取详情

    def getAndroidVirusReport(myurl):
        #print('--------getAndroidReport-->'+myurl)
        reponse = urllib.request.Request(myurl)
        html = urllib.request.urlopen(reponse).read().decode("utf-8")
        # 解析html
        soup = bs4.BeautifulSoup(html, 'html.parser')
    
        basepageurl = urllib.parse.unquote(myurl[:-5]) + '/'
    
        # 获取详解界面
        pattern = 'http://v.virscan.org/'
        VInfoLinks = soup.find_all('a', href=re.compile(pattern))
        # 这里是找到页面最大值,然后for循环访问
        maxpagenum = 1
        for link in VInfoLinks:    
            url4 = link['href']
            numstr = url4.split('/')[-1][0:-5]
            try:
                if maxpagenum < int(numstr):
                    maxpagenum = int(numstr)
                   
            except:
                continue
        print('found max page:'+ str(maxpagenum))
    
        for i in range(1, maxpagenum+1):
            url5 = urllib.parse.quote(basepageurl + str(i) + '.html')
            url5 = url5.replace('http%3A','http:')
            #print(url5)
            getAndroidVirusPage(url5)
            time.sleep(1)
    
    

    图片3

    点进去就是上面这样,病毒的文件的md5就拿到了,这时候不要要着急,还要把这个md5取出来

    # 获取病毒md5值
    def getAndroidVirusPage(myurl):
        #print('--------getAndroidVirusPage-->'+myurl)
        reponse = urllib.request.Request(myurl)
        html = urllib.request.urlopen(reponse).read().decode("utf-8")
        # 解析html
        soup = bs4.BeautifulSoup(html, 'html.parser')
        # 拿到md5值
        pattern = r'http://md5.virscan.org/\w+'  #URL格式
        md5Links = soup.find_all('a', href=re.compile(pattern))
        for link in md5Links:    
            url6 = link['href']
            md5str = url6.split('/')[-1][0:-5]
            print("get file md5 :"+md5str)
        
    

    好了,到此结束,我们拿到了病毒文件md5

    下面还要把它存到数据库,然后客户端获取到这个数据库,然后就是各种比对找出病毒就行了

    展开全文
  • Android APP 漏洞分析

    2015-06-12 10:19:58
    由于Android系统开源架构特性,安卓移动应用成为恶意病毒攻击的重点目标。最新调查显示, 绝大多数手机应用都存在着移动应用安全漏洞,这可能会导致它们在未来感染严重的恶意病毒。接下来我们来看一份检测报告是以...

    由于Android系统开源架构特性,安卓移动应用成为恶意病毒攻击的重点目标。最新调查显示, 绝大多数手机应用都存在着移动应用安全漏洞,这可能会导致它们在未来感染严重的恶意病毒。接下来我们来看一份检测报告是以什么方式进行检测分析的。

    爱内测的一份报告

     

    报告中详细指出了apk文件中主要存在的安全问题,以及修复漏洞的建议,文中采用的智能检测方法通过Android组件检测、权限管理、dex保护、数据安全(传输、存储、输出)检测,以及危险调试信息等常见的漏洞风险检测:

     

    全面深入检测应用/一键生成检测报告/专业安全修复建议

     

     

    应用安全进行扫描,包括:

    — Activity安全

    — Receiver安全

    — Service安全

    — ContentProvider安全

    — Intent安全

    — WebView安全

    — 模拟器检测

     

     源码安全进行扫描,包括:

    — 代码混淆

    — Dex保护

    — SO保护

    — 资源文件保护

    — 异常处理

    — 权限管理

    — 动态调试

     

    数据安全进行扫描,包括:

    — 数据访问控制危险

    — 敏感数据加密安全

    — 证书验证安全

    — 远程数据通信加密安全

    — 日志信息移除安全

    — 测试数据移除安全

    展开全文
  • 以下是一些基本安卓 APP要测试的内容,根据不同时期测试内容不一样~测试内容测试类型目标冒烟测试Monkey1.编写adb.exe 的Monkey 命令 2.通过logcat定位...
  • 某安全公司移动病毒分析报告的面试题目,该病毒样本的代码量比较大,最大的分析障碍是该病毒样本的类名称和类方法名称以及类成员变量的名称被混淆为无法辨认的特殊字符,每个被分析的类中所有的字符串都被加密处理了...
  • 一、Android APP安全测试思路分析: 1.安全测试工具 2.基础环境 3.数据安全 4.程序安全 5.数据传输 6.业务安全 二、APP面临的风险 1.不安全的服务器访问控制 2.不安全的数据存储 3.传输层保护不足 4.非...
  • 伴随着移动互联网的高速发展,移动应用APP的安全问题也走进了人们的视角,在企业安全建设过中,往往需要对企业移动应用APP进行一个安全风险评估,从而了解总体的安全情况,以下我们将简要介绍以下的几个APP安全在线...
  • package com.example.thefinalproject; import java.util.List; import com.example.thefinalproject.R; import MD5.MD5Encoder;...import android.app.Activity; import android.content.pm.PackageInfo; import a
  • Android Studio官方文档之构建和运行你的APP 默认情况下,Android Studio设置新的项目并且部署到模拟器或者真机设备上,只需要点击几下。使用即时运行,你并不需要构建一个新的APK即可将改变后的方法和现有的应用...
  • android设备中了病毒,每隔几分钟自动弹色情广告,或者是自动下载安装应用。从应用管理看到奇怪的进程。 前期尝试: 使用查杀工具-顽固木马专杀(英文名应该是Stubborn Trojan Killer),可以看到中了幽灵推病毒,还有...
  • Android系统由于其开源的属性,市场上针对开源代码定制的ROM参差不齐,在系统层面的安全防范和易损性都不一样,Android应用市场对app的审核相对iOS来说也比较宽泛,为很多漏洞提供了可乘之机。市场上一些主流的app...
  • 自己开发的APP安装时,手机360安全卫士提示有木马病毒问题。
  • 计数功能,仿照小米运动的动画
  • 以下是一些基本安卓 APP要测试的内容,根据不同时期测试内容不一样~ 测试内容 测试类型 目标 冒烟测试 Monkey 1.编写adb.exe 的Monkey 命令 2.通过logcat定位问题,保证软件的健壮性 模糊...
  • 自研的手游在百度手机助手扫描病毒,大神们这个是什么类型的病毒,要怎么解决? ![图片说明](https://img-ask.csdn.net/upload/201904/11/1554947496_360205.png)
  • 木马病毒之10086 一、 样本概况 1.1 样本信息 文件名称:10086.apk 文件类型:application/jar 样本包名:iuxkikw.zkjaksj.jhyvu 样本大小:31.3KB MD5:C2CD6ABCB62A8DF958049ACFFA204392 SHA1:DE9BDBF724...
  • “手机杀毒”模块实现 & 病毒数据库
1 2 3 4 5 ... 20
收藏数 937
精华内容 374
关键字:

android app病毒扫描