iOS的UAF错误到底是什么错误

Posted dinghing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS的UAF错误到底是什么错误相关的知识,希望对你有一定的参考价值。

Use After Free

UAF 就是 Use After Free的缩写,是一种比较常见的内存错误式利用。很多ios的越狱都是利用的这种方法。
在此简单的举个例子说明UAF出现的情况

代码说明一切

    class Car
    {
        public:
            virtual void setValue(int value)=0;
            virtual int getValue()=0;

        protected:
            int mValue;
    };

    class Electric_car: public Car
    {
        public:
            void setValue(int value){
            mValue = value;
        }

        int getValue(){
        mValue += 1;
        cout<<"This is Electric_car‘s getValue"<<endl;
        return mValue;
        }
    };

    class Fuel_car : public Car
    {
        public:
            void setValue(int value){
            mValue = value;
        }
        int getValue(){
        cout<<"This is Fuel_car‘s getValue"<<endl;
        mValue += 100;
        return mValue;
        }
    };

    void handleObject(Car* car)
    {
        car->setValue(0);
        cout<<car->getValue()<<endl;
    }  

这个程序有三个类,其中Fuel_car和Electric_car都是继承自Car。并且分别实现了Car类的虚函数。因此当程序调用handleObject这个函数的时候,无论出入的参数是Electric_car还是Fuel_car,handleObject函数都可以正常被调用。

接着我们来看一下主函数的情况

    int main(void) {
    Electric_car *myElectric_car = new Electric_car();
    printf("Electric_car=%p\n",myElectric_car);   

    handleObject(myElectric_car);

    free(myElectric_car); 

    Fuel_car *myFuel_car = new Fuel_car();
    printf("Fuel_car=%p\n",myFuel_car);   

    handleObject(c);
    }
  1. 我们先new一个Electric_car,然后再调用handleObject来打印它的value值。最后释放掉这个Electric_car。
  2. 接着,我们new一个Fuel_car,然后调用handleObject来打印Electric_car(请注意是Electric_car,不是Fuel_car) 

按照以上的步骤调用了相关函数之后会发生什么情况呢,正常情况下会出现内存泄漏的报错。但是上面主函数只是free掉了myElectric_car,并且没有把指针也置为NULL。这个时候如果有另一个对象(比如上面的Fuel_car)刚好被分配到了myElectric_car的指针地址里面。handleObject就会对这个对象进行处理并且不会出现错误。这就是典型的UAF错误

简单看一下运行结果吧。

    myElectric_car=0x15b23a76  
    This is Electric_car‘s getValue
    1
    myFuel_car=0x15b23a76 
    This is Fuel_car‘s getValue
    100  

可以看到Electric_car对象在内存中的地址为0x15b23a76,然后Electric_car就被free掉了。随后,程序又创建了另一个对象myFuel_car。因为堆的特性,系统会把刚刚free掉的内存再分配给myFuel_car。因此myFuel_car在内存中的地址也是0x15b23a76。所以当程序调用handleObject(myElectric_car)的时候,本应该期待调用Electric_car‘s getValue()函数却调用了Fuel_car‘s getValue()函数,这就造成一个UAF错误。

总结

以上就是对UAF错误发生原因的介绍,对应方法一般为释放内存之后还要记得把指针也释放掉。 提一个有意思的话题,在iOS9.0中,有人就用这个UAF错误实现了越狱。主要漏洞发生的函数是IOHIDResourceUserClient。 你能找出问题吗(同学们这是一道送分题啊)

    //----------------------------------------------------------------------------
    // IOHIDResourceDeviceUserClient::terminateDevice
    //----------------------------------------------------------------------------  
    IOReturn IOHIDResourceDeviceUserClient::terminateDevice()
    {
        if (_device) {
            _device->terminate();
    }
        OSSafeRelease(_device);

    return kIOReturnSuccess;
    }
(最近在尝试在gitpage上写文章,所以这篇文章也放到了自己的github上)

以上是关于iOS的UAF错误到底是什么错误的主要内容,如果未能解决你的问题,请参考以下文章

我在这里遇到的这个错误到底是啥? (iOS、Xcode、Healthkit)

为啥这个代码片段说包含错误?

iOS swift 中的错误域 = NSCocoaErrorDomain 代码 = 3840?

为啥代码片段在 matplotlib 2.0.2 上运行良好,但在 matplotlib 2.1.0 上引发错误

片段事务中的实例化错误

null?对象?异常?到底应该如何返回错误信息