应用侧漏洞与CTF题解:https://wnagzihxa1n.gitbook.io

大土豆安全笔记

Android开发学着学着发现了一些奇奇怪怪的技术,我得回去再看看Java的技术,依旧是B站上面的教程,六百集,不过不是全部看一遍,怪我之前学的不扎实,关注了一些Java编程的公众号,学到了很多安全之外的技术,比如优化好几百万的数据表查询,其中用到的思想确实很开阔眼界,也有一些框架使用,之后开发一些自动化项目都是可以用得上的

说到自动化,我最近在整理SO自动化的资料,这部分的基础知识其实不多,但是做好了基础的分析之后,在这个基础上去做很多其它事情,就很有意思了,比如漏洞挖掘,协议分析等

胖友,听说过拒绝服务吗?

CVE-2017-0780,Android Message的拒绝服务

补丁捕获了创建FrameSequenceDrawable对象时可能抛出的异常

从补丁位置处开始分析

@Override
public Drawable getDrawable(Resources resources) {
    return new FrameSequenceDrawable(mFrameSequence);
}

对象FrameSequenceDrawable定义如下

它有两个构造方法,第一个不用管,我们看第二个,它会调用方法acquireAndValidateBitmap()

public FrameSequenceDrawable(FrameSequence frameSequence) {
    this(frameSequence, sAllocatingBitmapProvider);
}

public FrameSequenceDrawable(FrameSequence frameSequence, BitmapProvider bitmapProvider) {
    if (frameSequence == null || bitmapProvider == null) throw new IllegalArgumentException();

    mFrameSequence = frameSequence;
    mFrameSequenceState = frameSequence.createState();
    final int width = frameSequence.getWidth();
    final int height = frameSequence.getHeight();

    mBitmapProvider = bitmapProvider;
    mFrontBitmap = acquireAndValidateBitmap(bitmapProvider, width, height); // <--
    mBackBitmap = acquireAndValidateBitmap(bitmapProvider, width, height); // <--
    mSrcRect = new Rect(0, 0, width, height);
    mPaint = new Paint();
    mPaint.setFilterBitmap(true);

    mFrontBitmapShader
        = new BitmapShader(mFrontBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
    mBackBitmapShader
        = new BitmapShader(mBackBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

    mLastSwap = 0;

    mNextFrameToDecode = -1;
    mFrameSequenceState.getFrame(0, mFrontBitmap, -1);
    initializeDecodingThread();
}

方法acquireBitmap()可能返回空,而方法acquireAndValidateBitmap()没有做异常捕获,后面直接调用空对象操作,会造成拒绝服务

private static Bitmap acquireAndValidateBitmap(BitmapProvider bitmapProvider,
        int minWidth, int minHeight) {
    Bitmap bitmap = bitmapProvider.acquireBitmap(minWidth, minHeight);

    if (bitmap.getWidth() < minWidth
            || bitmap.getHeight() < minHeight
            || bitmap.getConfig() != Bitmap.Config.ARGB_8888) {
        throw new IllegalArgumentException("Invalid bitmap provided");
    }

    return bitmap;
}

方法acquireBitmap()最后会调用到方法nativeCreate(),是一个Native函数

函数注册

static const JNINativeMethod gBitmapMethods[] = {
    {   "nativeCreate",             "([IIIIIIZ)Landroid/graphics/Bitmap;",
        (void*)Bitmap_creator },
    ...
};

有兴趣的同学可以完整的跟一下

static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
                              jint offset, jint stride, jint width, jint height,
                              jint configHandle, jboolean isMutable) {
    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
    if (NULL != jColors) {
        size_t n = env->GetArrayLength(jColors);
        if (n < SkAbs32(stride) * (size_t)height) {
            doThrowAIOOBE(env);
            return NULL;
        }
    }

    // ARGB_4444 is a deprecated format, convert automatically to 8888
    if (colorType == kARGB_4444_SkColorType) {
        colorType = kN32_SkColorType;
    }

    SkBitmap bitmap;
    bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType));

    Bitmap* nativeBitmap = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);
    if (!nativeBitmap) {
        return NULL;
    }

    if (jColors != NULL) {
        GraphicsJNI::SetPixels(env, jColors, offset, stride,
                0, 0, width, height, bitmap);
    }

    return GraphicsJNI::createBitmap(env, nativeBitmap,
            getPremulBitmapCreateFlags(isMutable));
}

想法:话说这种漏洞完全可以自动化啊,不是Fuzz,通过搜索含有抛出异常的函数,往回找调用栈,看是不是所有抛出的异常都被捕获了

我今天发现一个神器,用来搜索API文档贼好用,叫Dash,设置个快捷键,指哪打哪

IMAGE