arm32下根据虚函数识别全局对象

来源:互联网 发布:淘宝网男士羽绒服2016 编辑:程序博客网 时间:2024/05/24 05:02

0x0 概述

本文描述了arm32汇编下,如何通过识别虚函数进而实现全局对象的识别。

0x1 c代码

#include <stdio.h>class CGlobal{        public:                CGlobal(){                        printf("CGLoabla \r\n");                }                CGlobal(int nInt){                        printf("CGloabal(int nInt) %d\r\n",nInt);                }                CGlobal(char *pChar){                        printf("CGlobal(char *pChar) %s   \r\n",pChar);                }                virtual ~CGlobal(){                        printf("~CGlobal() \r\n");                }                void Show(){                        printf("对象首地址:%p \r\n",this);                }};CGlobal g_void;CGlobal g_int(10);CGlobal g_pChar((char *)"hello");int main(){        g_void.Show();        g_int.Show();        g_pChar.Show();}
0x2 全局对象的识别

全局对象需要在main函数执行之前完成初始化,并且要在main函数执行完成之后进行析构。bionic里有一个函数用来进行析构函数的登记,以便于执行完main函数后调用全局对象的析构函数,这个函数的原型为:

/* The "C++ ABI for ARM" document states that static C++ constructors, * which are called from the .init_array, should manually call * __aeabi_atexit() to register static destructors explicitly. * * Note that 'dso_handle' is the address of a magic linker-generate * variable from the shared object that contains the constructor/destructor */int __attribute__((weak))__aeabi_atexit(void *object, void (*destructor) (void *), void *dso_handle)
该函数的第一个参数为对象地址,第二个参数是对象的析构函数,第三个参数是编译器生成的变量(我们暂且不管)。可以根据这个函数的前两个参数识别出全局对象的地址和其析构函数地址。其中一个全局对象的识别如下:


其中unk_4004即一个对象的地址,sub_6B8为其析构函数。

0x3 析构函数解析与构造(及析构)函数的识别
进入析构函数,汇编如下:


这里析构函数首先将一个地址写到对象的开头,这个地址就是虚表的地址。构造函数和析构函数首先将虚表的地址写到对象的开头,这是识别构造函数和析构函数的充分条件。这里的标号采用的是一个地址标号+8的形式,不知道前边空两个是什么意思,注意就好。下面看一下虚表的构造

使用IDA的Xref graph to功能即可查看那些函数调用了虚表地址,这些函数就是构造函数和析构函数。


这里有四个函数调用了虚表地址,进一步分析即可确定其为构造函数还是析构函数。

0x4 总结

含有虚函数的对象,其构造函数析构函数首先将虚表写入对象的开头。这是识别析构函数和构造函数的充分条件。全局对象的识别相对容易,根据_atabi_atexit函数即可。

0 0
原创粉丝点击