CN106803028A - 一种防止安卓手机短信验证码被窃取的方法 - Google Patents
一种防止安卓手机短信验证码被窃取的方法 Download PDFInfo
- Publication number
- CN106803028A CN106803028A CN201710035104.XA CN201710035104A CN106803028A CN 106803028 A CN106803028 A CN 106803028A CN 201710035104 A CN201710035104 A CN 201710035104A CN 106803028 A CN106803028 A CN 106803028A
- Authority
- CN
- China
- Prior art keywords
- taint
- array
- short message
- label
- stain
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Granted
Links
- 238000000034 method Methods 0.000 title claims abstract description 346
- 238000012795 verification Methods 0.000 title claims abstract description 61
- 238000003491 array Methods 0.000 claims abstract description 56
- 238000001514 detection method Methods 0.000 claims abstract description 12
- 230000007246 mechanism Effects 0.000 claims abstract description 7
- 239000000284 extract Substances 0.000 claims abstract description 6
- 238000012986 modification Methods 0.000 claims description 28
- 230000004048 modification Effects 0.000 claims description 28
- 230000015654 memory Effects 0.000 claims description 17
- 230000008569 process Effects 0.000 claims description 16
- GOLXNESZZPUPJE-UHFFFAOYSA-N spiromesifen Chemical compound CC1=CC(C)=CC(C)=C1C(C(O1)=O)=C(OC(=O)CC(C)(C)C)C11CCCC1 GOLXNESZZPUPJE-UHFFFAOYSA-N 0.000 claims description 16
- 238000012546 transfer Methods 0.000 claims description 12
- 238000012360 testing method Methods 0.000 claims description 9
- 230000000644 propagated effect Effects 0.000 claims description 7
- 238000003780 insertion Methods 0.000 claims description 6
- 230000037431 insertion Effects 0.000 claims description 6
- 230000006399 behavior Effects 0.000 claims description 5
- 230000008859 change Effects 0.000 claims description 4
- 230000003362 replicative effect Effects 0.000 claims description 3
- 241000208340 Araliaceae Species 0.000 claims description 2
- 235000005035 Panax pseudoginseng ssp. pseudoginseng Nutrition 0.000 claims description 2
- 235000003140 Panax quinquefolius Nutrition 0.000 claims description 2
- 235000008434 ginseng Nutrition 0.000 claims description 2
- 230000005540 biological transmission Effects 0.000 abstract description 5
- 230000006854 communication Effects 0.000 abstract description 3
- 230000002265 prevention Effects 0.000 abstract description 2
- 238000002474 experimental method Methods 0.000 description 4
- 230000006870 function Effects 0.000 description 4
- 230000009471 action Effects 0.000 description 3
- 238000004891 communication Methods 0.000 description 2
- 241000406668 Loxodonta cyclotis Species 0.000 description 1
- 238000013459 approach Methods 0.000 description 1
- 230000009286 beneficial effect Effects 0.000 description 1
- 239000011230 binding agent Substances 0.000 description 1
- 238000007796 conventional method Methods 0.000 description 1
- 238000012217 deletion Methods 0.000 description 1
- 230000037430 deletion Effects 0.000 description 1
- 238000000151 deposition Methods 0.000 description 1
- 238000010586 diagram Methods 0.000 description 1
- 235000013399 edible fruits Nutrition 0.000 description 1
- 230000000694 effects Effects 0.000 description 1
- 238000005516 engineering process Methods 0.000 description 1
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F21/00—Security arrangements for protecting computers, components thereof, programs or data against unauthorised activity
- G06F21/10—Protecting distributed programs or content, e.g. vending or licensing of copyrighted material ; Digital rights management [DRM]
- G06F21/16—Program or content traceability, e.g. by watermarking
-
- H—ELECTRICITY
- H04—ELECTRIC COMMUNICATION TECHNIQUE
- H04W—WIRELESS COMMUNICATION NETWORKS
- H04W4/00—Services specially adapted for wireless communication networks; Facilities therefor
- H04W4/12—Messaging; Mailboxes; Announcements
- H04W4/14—Short messaging services, e.g. short message services [SMS] or unstructured supplementary service data [USSD]
Landscapes
- Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Software Systems (AREA)
- Technology Law (AREA)
- Computer Hardware Design (AREA)
- Computer Security & Cryptography (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Multimedia (AREA)
- Computer Networks & Wireless Communication (AREA)
- Signal Processing (AREA)
- Mobile Radio Communication Systems (AREA)
Abstract
一种防止安卓手机短信验证码被窃取的方法,主要通过对验证码数据进行污点标签的有效添加,并修改了系统中与短信验证码数据相关的数组结构、数组操作、字符串操作、进程间数据传递机制以及对验证码数据进行二次存储时的文件读写相关操作(包括对短信数据库的读写),保证污点标签在传播过程中不会丢失,最终在验证码被发送时(无论是通过短信还是网络发送)提取污点标签,并基于既定规则阻止验证码数据的发送来防止手机短信验证码被窃取。本发明采用基于数据流的保护方式,确保了事件检测的准确性,与其他方法相比系统开销较小,本发明除了用于手机短信验证码,还能够扩展到对其他类型隐私数据的保护。
Description
技术领域
本发明属于移动数据安全领域,具体涉及一种防止安卓手机短信验证码被窃取的方法。
背景技术
当前,智能手机被拦截及窃取短信验证码的恶意软件层出不穷,很多手机应用可能会捆绑携带这类恶意软件,这使得用户在不知不觉间就会被窃取短信验证码信息。作为国内非常通用的一个安全验证手段,越来越多的网站与应用都借助于手机短信验证码来方便用户重置密码(包括登录密码和支付密码),更甚者,短信验证码在很多时候都被作为安全支付的有效手段,一旦被窃取,将很可能会给用户带来严重的经济损失。
在安卓4.4版本以前的系统中,恶意软件通过提高自己拦截短信的权限,使其优先于用户取得短信验证码,可以让自己获取验证码后在用户不知情的情况下删除该信息。而在4.4版本及之后,安卓虽然对短信系统进行了优化,恶意软件无法截断短信广播,用户最终会获得短信验证码信息,但是它仍然无法阻止恶意软件通过借用(或盗用)用户的身份滥用这些验证码,从而达到其最终的目的。传统的保护方法一般是对接收到的短信验证码进行阅读后立刻销毁或者是对验证码进行加密存放的方式来保护短信验证码的安全,但是这些传统方法都有明显的弊端,它们无法确保自己优先于恶意应用获得短信。另一类保护方法是通过修改安卓框架层中访问短信的API函数来判断调用该API函数的应用是否是一个存在于自定义安全列表中的安全应用,从而防止恶意应用获取短信验证码信息。这类方法的问题是只能保护从短信数据库中读取的短信,而无法防止在接收短信时从广播途径直接获取短信内容(并发送出去)的攻击方式。所以,现有方法都无法很好的防止手机短信验证码被窃取。
发明内容
本发明的目的在于针对上述现有技术中的问题,提供一种防止安卓手机短信验证码被窃取的方法,通过数据流抵御恶意软件窃取手机短信验证码的行为,进而有效地保护用户智能手机系统中个人敏感信息的安全,并且具有良好的适用性和扩展性。
为了实现上述目的,本发明采用的技术方案包括以下步骤:
步骤一、按照以下过程进行模块初始化:1.1.设置短信验证码发送地址列表commonNumberList;根据发送短信的源地址是否在commonNumberList列表中判断该短信是否可能是一个验证码短信;1.2对字符数组和字节数组进行标记,在数据末尾添加一个位向量,所述位向量的每一个数据位代表一种标签,定义四个污点标签常量:空污点标签、短信数据标签、数据库标签、验证码标签;1.3.修改安卓系统数组在内存中的分配方式与数组大小的计算方式,让每个数组拥有一个污点标签成员字段,使每个数组能够存储有效的污点标签;1.4.在安卓系统中自定义污点标签添加和读取方法,并注册成虚拟机内部方法,满足污点标签操作相关方法调用的需求;1.5.修改安卓系统中数组在native层和框架层的复制方式,使数组复制时满足污点传播的需求;1.6.安卓系统中每个方法都运行在线程中,在安卓系统中为线程类添加污点标签成员字段,并修改安卓编译器对数组存取操作的编译操作,满足污点传播的需求;1.7.修改安卓系统框架层中字符串类的构造方法和相关操作函数,使字符串类的操作满足污点传播的需求;1.8.修改安卓系统中短信广播机制的信息存储方式,满足污点传播的需求;1.9.修改安卓系统中框架层文件的读写操作,满足短信验证码数据二次存储时污点标签传播的需求;1.10.修改安卓系统中数据库的插入和更新操作,防止短信数据库被污染;
步骤二、接收短信时的标签添加模块;
2.1.在框架层读取短信协议数据单元PDU;
2.2.为短信PDU的字节数组添加污点标签TAINT_SMS;
步骤三、读取短信时的标签添加模块:3.1.读取短信数据库中一条短信的内容;3.2.添加TAINT_DB污点标签到短信内容字符串的污点标签位置;3.3.读取短信的源地址字段;3.4.判断源地址字段是否在地址列表commonNumberList中;如是,表明该条短信是一个疑似验证码短信,执行3.5,否则跳转到3.8;3.5.判断短信内容字段中是否包含4-8位的连续数字或数字加英文,如是,执行3.6,否则跳转到3.8;3.6.判断短信内容字段中是否包含“验证”或“密码”关键字,如是,表明这是一个短信验证码数据,执行3.7,否则跳转到3.8;3.7.添加TAINT_DB_VALIDATECODE污点标签到短信内容字符串的污点标签位置;3.8返回短信内容;
步骤四、通过短信发送验证码时的检测模块:4.1.读取待发送短信的污点标签,并将其赋给TAG;4.2.判断TAG是否大于TAINT_NONE,如是,执行4.3,否则交由系统直接发送短信;4.3.判断TAG是否大于或等于TAINT_DB,如是,执行4.4,否则跳转到4.5;4.4.判断TAG是否大于或等于TAINT_DB_VALIDATECODE,如是,代表正在发送一个短信验证码数据,执行4.5,否则交由系统直接发送短信;4.5.禁止短信发送,并提示用户有短信验证码正在试图通过短信发送出去,并打印出短信内容和目的地址;
步骤五、通过网络发送验证码时的检测模块:5.1.读取待发送短信数据中的污点标签,并将其赋给TAG;5.2.判断TAG是否大于TAINT_NONE,如是,执行5.3,否则交由系统直接发送;5.3.判断TAG是否大于或等于TAINT_DB,如是,执行5.4,否则跳转到5.5;5.4.判断TAG是否大于或等于TAINT_DB_VALIDATECODE,如是,代表正在发送一个短信验证码数据,执行5.5,否则交由系统直接发送;5.5.禁止网络传输数据,提示用户有短信验证码数据正在试图通过网络发送出去,并打印出数据内容和目的地址。
步骤1.3的具体过程包括:1.3.1.修改安卓系统中native层数组类Array的结构,为其增加一个存储污点标签的32位字段taint_tag;1.3.2.修改安卓系统中native层数组类Array中所包含的方法ComputeArraySize(),使得在给数组分配空间时,每个数组额外增加4个字节的空间;1.3.3.修改安卓系统中native层数组类Array中所包含的方法SizeOf(),将其原计算结果增加4个字节,与ComputerArraySize()保持一致;1.3.4在安卓系统中native层数组类Array中自定义两个新的方法,分别是污点添加方法AddTaintData(size_tcomponent_size,int32_ttaintTag)和污点获取方法GetTaintData(size_t component_size);所述的污点添加方法AddTaintData(size_t component_size,int32_t taintTag)根据数组元素类型所占的字节大小component_size和数组在内存中的起始地址,计算得到数组对象中taint_tag字段所在的地址空间,从这个地址空间读取taint_tag的值,将其与参数taintTag进行按位或运算,得到新的标签值,存入taint_tag字段所在的地址空间;污点获取方法GetTaintData(size_t component_size)根据数组元素类型所占的字节大小component_size和数组在内存中的起始地址,计算得到数组对象中taint_tag字段所在的地址空间,从这个地址空间读取并返回taint_tag的值。
所述步骤1.4的具体过程包括:1.4.1.自定义Taint_getTaintByteArray(JNIEnv*env,jclass,jbyteArray theArray)方法,获取目标字节数组的污点标签,框架层通过jni调用传来的参数theArray字节数组强制类型转换成Array对象,然后调用Array对象的类内方法GetTaintData(size_t component_size)获取并返回这个字节数组的污点标签;1.4.2.自定义Taint_addTaintByteArray(JNIEnv*env,jclass,jbyteArray theArray,jint taint_tag)方法,给目标字节数组添加污点标签,框架层通过jni调用传来的参数theArray字节数组强制类型转换成Array对象,然后调用Array对象的类内方法AddTaintData(size_t component_size,int32_t taintTag)把污点标签存入这个字节数组的污点标签字段;1.4.3.自定义Taint_getTaintCharArray(JNIEnv*env,jclass,jcharArray theArray)方法,获取目标字符数组的污点标签,框架层通过jni调用传来的参数theArray字符数组强制类型转换成Array对象,然后调用Array对象的类内方法GetTaintData(size_t component_size)获取并返回这个字符数组的污点标签;1.4.4.自定义Taint_addTaintCharArray(JNIEnv*env,jclass,jcharArray theArray,jint taint_tag)方法,用于给目标字符数组添加污点标签,框架层通过jni调用传来的参数theArray字符数组强制类型转换成Array对象,然后调用Array对象的类内方法AddTaintData(size_tcomponent_size,int32_t taintTag)把污点标签存入这个字符数组的污点标签字段;1.4.5.自定义Taint_getTaintString(JNIEnv*env,jclass,jstring theString)方法,获取目标字符串的污点标签,首先把框架层String类型的theString参数强制类型转换成native层的String对象,然后调用String类内方法GetCharArray()获取数据所在的字符数组,最后调用GetTaintData()方法获取并返回这个字符数组的污点标签;1.4.6.自定义Taint_addTaintString(JNIEnv*env,jclass,jstring theString,jint taint_tag)方法,为目标字符串添加污点标签,首先把框架层的String类型的theString参数强制类型转换成native层的String对象,然后调用String类内方法GetCharArray()获取数据所在的字符数组,最后调用AddTaintData()方法为该字符数组添加污点标签;1.4.7自定义Taint_getTaintFile(JNIEnv*env,jclass,jint fd,jint taint_tag)方法,读取目标文件扩展字段的污点标签,直接通过系统调用_NR_fgetxattr()获取指定文件的扩展字段所包含的污点标签;1.4.8.自定义Taint_addTaintFile(JNIEnv*env,jclass,jint fd,jint taint_tag)方法,为目标文件扩展字段添加污点标签,首先调用Taint_getTaintFile()方法获取该文件的原污点标签,然后与新污点标签taint_tag进行按位或运算,得到结果,最后通过系统调用__NR_fsetxattr()将结果添加到指定文件的扩展字段中。
步骤1.5的具体过程为:1.5.1.修改框架层arraycopy(char[]src,int srcPos,byte[]dst,int dstPos,int length)方法和arraycopy(byte[]src,int srcPos,byte[]dst,int dstPos,int length)方法,所有的数组复制操作都通过调用native层的System_arraycopyTUnchecked()方法进行;1.5.2.修改native层的System_arraycopy(JNIEnv*env,jclass,jobject javaSrc,jint srcPos,jobject javaDst,jint dstPos,jintlength)方法,在System_arraycopy()方法的末尾增加了以下操作:首先将javaSrc变量由jobject类型强制转换为Array类型,然后判断javaSrc所含数组元素的类型是否是char或byte类型,如是,则调用GetTaintData()方法提取出数组中的污点标签,再调用AddTaintData()方法将提出的污点标签添加到目的数组javaDst中;1.5.3.修改native层的System_arraycopyTUnchecked(JNIEnv*env,jobject javaSrc,jint srcPos,jobjectjavaDst,jint dstPos,jint count)方法,在System_arraycopyTUnchecked()方法的末尾增加以下操作:首先,将javaSrc变量由jobject类型强制转换为Array类型,然后判断javaSrc所含数组元素的类型是否是char或byte类型,如是,则调用GetTaintData()方法提取出数组中的污点标签,再调用AddTaintData()方法将提取出的污点标签添加到目的数组javaDst中。
步骤1.6的具体过程为:1.6.1.在Thread类中添加一个32位大小的taint_tag字段保存污点标签;1.6.2.在Thread类中添加一个ThreadTaintTagOffset()方法,返回Thread类中taint_tag字段的类内地址偏移量;1.6.3.修改GenArrayGet()方法,在GenArrayGet()方法的末尾增加以下操作:先申请一个临时寄存器t1,通过指定数组的起始地址和污点标签字段的偏移量,调用loadWordDisp()方法将该数组的污点标签存入寄存器t1;然后申请一个临时寄存器t2,根据r9寄存器中保存的Thread对象的地址和Thread类中taint_tag字段的类内偏移值,调用loadWordDisp()方法将Thread对象中的taint_tag字段存入寄存器t2;将t1和t2进行按位或运算,结果保存在t1中;最后调用StoreWordDisp()方法把t1中的值存入Thread对象的taint_tag字段中;1.6.4.修改GenArrayPut()方法,在GenArrayPut()方法的末尾增加了以下操作:先申请一个临时寄存器t1,根据rs_rARM_SELF寄存器中保存的Thread对象的地址和Thread类中taint_tag字段的类内偏移量,调用loadWordDisp()方法将Thread对象中的taint_tag字段存入寄存器t1,申请一个临时寄存器t2,通过指定数组的起始地址和污点标签字段的偏移量,调用loadWordDisp()方法将该数组的污点标签存入寄存器t2,将t1和t2按位或运算,结果保存在t1中,调用StoreWordDisp()方法把t1中的值存入目标数组的污点标签字段taint_tag中。
步骤1.7的具体过程为:1.7.1.修改String类的构造方法String(byte[]data,intoffset,int byteCount,Charset charset),在String()方法的末尾增加以下操作:首先调用Taint_getTaintByteArray()方法取出参数data数组的污点标签,然后调用Taint_addTaintCharArray()方法把取出的污点标签添加到字符串的成员字段value数组的污点标签字段taint_tag中;1.7.2.修改String类的getBytes()方法,在getBytes()方法的末尾增加以下操作:首先调用Taint_getTaintCharArray()方法取出字符串的value字符数组中的污点标签,然后调用Taint_addTaintByteArray()方法把取出的污点标签添加到待返回的字节数组中;1.7.3.修改String类的split()方法,在split()方法的末尾增加以下操作:首先调用Taint_getTaintCharArray()方法取出字符串的value字符数组中的污点标签,然后调用Taint_addTaintStringArray()方法把取出的污点标签添加到待返回的字符串数组中的每一个字符串对象中。
步骤1.8的具体过程为:1.8.1.在框架层的Parcel类定义中添加成员字段taintTag,初始值置为0;1.8.2.在native层的Parcel类定义中添加成员字段taintTag,初始值置为0;并在Parcel类定义中添加自定义的nativeSetTaint()和nativeGetTaint()方法,分别用来设置和获取native层Parcel对象的taintTag字段数值;1.8.3.修改框架层的Parcel类中appendFrom(Parcel parcel,int offset,int length)方法,在appendFrom()方法的末尾增加以下操作:首先,获取参数parcel中taintTag字段的值,与当前Parcel对象中taintTag字段的值进行按位或操作后,将结果赋值给当前Parcel对象的taintTag字段,然后调用native层的nativeSetTaint()方法更新污点标签;1.8.4.修改框架层的Parcel类中writeByteArray(byte[]b,int offset,int len)方法,在writeByteArray()方法的末尾增加以下操作:首先,通过Taint_getTaintByteArray()方法获取参数b的污点标签值,与当前Parcel对象中的taintTag字段的值进行按位或操作后,将结果赋值给当前Parcel对象的taintTag字段,然后调用native层的nativeSetTaint()方法更新污点标签;1.8.5.修改框架层的Parcel类中createByteArray()方法,在createByteArray()方法的末尾增加以下操作:首先调用nativeGetTaint()方法获取native层的污点标签,然后调用Taint_addTaintByteArray()方法把这个污点标签添加到待返回的字节数组中。
步骤1.9的具体过程为:1.9.1.修改Posix类中的read(),pread(),readBytes()和preadBytes()方法,在这些方法的末尾增加以下操作:首先调用Taint_getTaintFile()方法获取文件的污点标签,然后调用Taint_addTaintByteArray()方法将取出的污点标签存入将要保存文件数据的字节数组中;1.9.2.修改Posix类中的write(),pwrite(),writeBytes()和pwriteBytes()方法,在这些方法的末尾增加以下操作:首先调用Taint_getTaintByteArray()方法获取字节数组的污点标签,然后调用Taint_addTaintFile()方法把取出的数组中的污点标签存入到目标文件的扩展字段中。
步骤1.10的具体过程为:1.10.1.修改ContentResolver类中的insert()方法,在insert()方法的开始增加以下操作:获取短信数据的污点标签进行比较,如果该污点标签的数值大于或等于TAINT_DB_VALIDATECODE,则禁止插入,并返回空值;1.10.2.修改ContentResolver类中的update()方法,在update()方法的开始增加以下操作:获取短信数据的污点标签进行比较,如果该污点标签的数值大于或等于TAINT_DB_VALIDATECODE,则禁止更新,并返回空值。
与现有技术相比,本发明具有如下的有益效果:通过修改安卓的框架层,在获得短信验证码的初期,即存入短信数据库之前就对其添加污点标签,并保证后续对验证码数据的所有操作都附带这个标签。因此在短信验证码数据被发送时,对标签进行提取就能够检测到事件的发生,有效的防止短信验证码数据被窃取。本发明采用基于数据流的保护方式,仅针对所要保护的数据,通过对其添加污点标签,使得数据无论位于安卓系统的任意层次空间,污点标签都会一直跟随这个数据,确保了事件检测的准确性,并且与其他方法相比系统开销较小(平均2%左右)。此外,本发明具有良好的适用性和扩展性,除了用于手机短信验证码的保护,还能够扩展到对智能手机中其他类型隐私数据的保护,比如通信录、个人照片及文件等。
附图说明
图1本发明的整体结构框图;
图2本发明从短信数据库取出短信内容时的污点标签添加流程图;
图3本发明通过短信方式发送时污点标签检测流程图;
图4本发明通过网络方式发送时污点标签检测流程图;
图5安卓5.0原版系统和应用本发明的安卓5.0系统性能测试结果图。
具体实施方式
参见图1,本发明包括初始化模块、接收短信时的标签添加模块、读取短信时的标签添加模块、通过短信发送验证码时的检测模块以及通过网络发送验证码时的检测模块五个部分。
本发明主要通过对验证码数据进行污点标签的有效添加,并修改了系统中与短信验证码数据相关的数组结构、数组操作、字符串操作、进程间数据传递机制以及对验证码数据进行二次存储时的文件读写相关操作(包括对短信数据库的读写),保证污点标签在传播过程中不会丢失,最终在验证码被发送时(无论是通过短信还是网络发送)提取污点标签,并基于既定规则阻止验证码数据的发送来防止手机短信验证码被窃取。具体包括以下步骤:
一、初始化模块
1.1)设置短信验证码发送地址列表commonNumberList;
把一些常见的短信验证码发送者的地址记录在commonNumberList地址列表中,就可以根据发送短信的源地址是否在commonNumberList列表中判断该短信是否可能是一个验证码短信。本发明在commonNumberList列表中设置了106*,95???,12306,10086,10000,10010号码。其中,106*表示以106开头的电话号码,长度不固定,一般不超过20位,大多数公司通过此类号码发送包括短信验证码在内的信息;95???表示以95开头的电话号码,长度为5位,是各大银行以及金融公司的验证码发送号码;12306是铁路服务网站的短信验证码发送号码;10086、10000、10010则分别是移动、电信、联通三大运营商发送信息的号码。本发明认为验证码短信主要来源于这些号码,用户后期可以根据需要添加新的号码。
1.2)定义四个污点标签常量,分别是:TAINT_NONE=0x00000000,代表空污点标签,即这个数据不包含任何有效污点标签;TAINT_SMS=0x00000100,代表短信数据标签,说明含有这个标签的数据是一条短信;TAINT_DB=0x00010000,代表数据库标签,含有这个标签的数据来自短信数据库;TAINT_DB_VALIDATECODE=0x00020000,代表验证码标签,含有这个标签的数据是一个短信验证码数据;
污点标签(简称为标签)通过在数据末尾添加一个32位的位向量来实现,位向量的每一个数据位代表一种标签,所以理论上允许存储32种不同的污点标签(如果有更多的需求,可以申请开辟两个甚至更多的变量,保存在数组元素的末尾来标记数组)。目前,本发明主要是对字符数组和字节数组这两种数据类型进行标记(即添加污点标签)。字符数组中每个元素占16位,而字节数组中每个元素占8位。一般来说,短信在框架层以字节数组的形式存储和传递,在应用层以字符串对象或字符数组的形式存储和传播。而当短信以字符串对象形式存储和传播时,它的实际内容存放在字符串对象所包含的字符数组内。因此,本发明只需要对字符数组和字节数组这两种数据类型进行标记,就可以保证涵盖所有的短信验证码数据。
1.3)修改安卓系统中数组在内存中的分配方式与数组大小的计算方式,让每个数组拥有一个污点标签成员字段,使每个数组能够存储有效的污点标签;
短信验证码以数组形式存在于系统中,所以本发明通过修改数组类的结构,为其增加成员字段,并修改其数据空间的计算方式,在数组数据末尾开辟新空间,存放污点标签,使得每一个数组都携带一个污点标签。而且,本发明具有很好的可扩展性,它可以通过开辟更多的新空间,增加标签数据位来支持更多的标签。
1.3.1)修改安卓系统中native层数组类Array的结构,为其增加一个存储污点标签的32位字段taint_tag;
1.3.2)修改安卓系统中native层数组类Array中所包含的方法ComputeArraySize(),使得在给数组分配空间时,每个数组额外增加4个字节的空间;
1.3.3)修改安卓系统中native层数组类Array中所包含的方法SizeOf(),将其原计算结果增加4个字节,与ComputerArraySize()保持一致;
1.3.4)在安卓系统中native层数组类Array中自定义两个新的方法,分别是污点添加方法AddTaintData(size_t component_size,int32_t taintTag)和污点获取方法GetTaintData(size_t component_size)。污点添加方法AddTaintData(size_tcomponent_size,int32_t taintTag)根据数组元素类型所占的字节大小component_size和数组在内存中的起始地址,计算得到数组对象中taint_tag字段所在的地址空间,从这个地址空间读取taint_tag的值,并将其与参数taintTag进行按位或运算,得到新的标签值,存入taint_tag字段所在的地址空间;污点获取方法GetTaintData(size_t component_size)根据数组元素类型所占的字节大小component_size和数组在内存中的起始地址,计算得到数组对象中taint_tag字段所在的地址空间,从这个地址空间读取并返回taint_tag的值。
1.4)在安卓系统中自定义污点标签添加和读取方法,并注册成虚拟机内部方法,满足污点标签操作相关方法调用的需求;
自定义的针对数组对象的污点标签添加和获取方法位于安卓的native层。该方法首先将携带污点标签的数据对象的类型强制转换为native层对应的类型,然后调用该类型的类内方法添加或获取污点标签。而自定义的针对文件的污点标签操作的相关方法则是直接通过系统调用_NR_fgetxattr()和_NR_fsetxattr()实现的。
本发明共添加了八个方法,分别完成字符数组污点标签的读取和添加,字节数组污点标签的读取和添加,字符串污点标签的读取和添加,文件扩展字段污点标签的读取和添加。在安卓系统启动时,将这些方法注册成虚拟机内部方法。并且,本发明只定义了对数据进行污点标签添加或读取的方法,而未定义删除方法,即不支持污点标签的删除操作。
1.4.1)自定义Taint_getTaintByteArray(JNIEnv*env,jclass,jbyteArraytheArray)方法,用于获取目标字节数组的污点标签。本方法把框架层通过jni调用传来的参数theArray字节数组强制类型转换成Array对象,然后调用Array对象的类内方法GetTaintData(size_t component_size),获取并返回这个字节数组的污点标签;
1.4.2)自定义Taint_addTaintByteArray(JNIEnv*env,jclass,jbyteArraytheArray,jint taint_tag)方法,用于给目标字节数组添加污点标签。本方法把框架层通过jni调用传来的参数theArray字节数组强制类型转换成Array对象,然后调用Array对象的类内方法AddTaintData(size_t component_size,int32_t taintTag),把污点标签存入这个字节数组的污点标签字段;
1.4.3)自定义Taint_getTaintCharArray(JNIEnv*env,jclass,jcharArraytheArray)方法,用于获取目标字符数组的污点标签。本方法把框架层通过jni调用传来的参数theArray字符数组强制类型转换成Array对象,然后调用Array对象的类内方法GetTaintData(size_t component_size),获取并返回这个字符数组的污点标签;
1.4.4)自定义Taint_addTaintCharArray(JNIEnv*env,jclass,jcharArraytheArray,jint taint_tag)方法,用于给目标字符数组添加污点标签。本方法把框架层通过jni调用传来的参数theArray字符数组强制类型转换成Array对象,然后调用Array对象的类内方法AddTaintData(size_t component_size,int32_t taintTag)(,把污点标签存入这个字符数组的污点标签字段;
1.4.5)自定义Taint_getTaintString(JNIEnv*env,jclass,jstring theString)方法,用于获取目标字符串的污点标签。该方法首先把框架层的String类型的theString参数强制类型转换成native层的String对象,然后调用String类内方法GetCharArray()获取数据所在的字符数组,最后调用GetTaintData()方法获取并返回这个字符数组的污点标签;
1.4.6)自定义Taint_addTaintString(JNIEnv*env,jclass,jstring theString,jint taint_tag)方法,用于为目标字符串添加污点标签。该方法首先把框架层的String类型的theString参数强制类型转换成native层的String对象,然后调用String类内方法GetCharArray()获取数据所在的字符数组,最后调用AddTaintData()方法为该字符数组添加污点标签;
1.4.7)自定义Taint_getTaintFile(JNIEnv*env,jclass,jint fd,jint taint_tag)方法,用于读取目标文件扩展字段的污点标签。该方法直接通过系统调用_NR_fgetxattr()获取指定文件的扩展字段所包含的污点标签;
1.4.8)自定义Taint_addTaintFile(JNIEnv*env,jclass,jint fd,jint taint_tag)方法,用于为目标文件扩展字段添加污点标签。该方法首先调用Taint_getTaintFile()方法获取该文件的原污点标签,然后与新污点标签taint_tag进行按位或运算,得到结果,最后通过系统调用_NR_fsetxattr()将结果添加到指定文件的扩展字段中。
1.5)修改安卓系统中数组在native层和框架层的复制方式,使数组复制时满足污点传播的需求;
短信验证码以字符或字节数组的形式存储。在安卓框架层中,String、StringBuiler、StringBuffer这些与字符/字节相关类的许多方法都是通过数组复制实现的。为了满足数据复制时污点传播的需求,本发明修改了数组复制操作相关的方法。
数组复制操作在安卓的框架层和native层都涉及,它会开辟新的数组空间,并把数组元素存入新的数组中。因此,为了满足污点传播的需求,在进行复制操作时,需要先提取原数组的污点标签,然后在新数组中添加原数组的污点标签。
1.5.1)修改框架层arraycopy(char[]src,int srcPos,byte[]dst,int dstPos,int length)方法和arraycopy(byte[]src,int srcPos,byte[]dst,int dstPos,intlength)方法。在安卓5.0版本之前,arraycopy()方法调用native层的System_arraycopy()方法进行数组的复制操作,而在安卓5.0及其以后版本中,对于数组元素个数小于32的数组直接在框架层进行复制操作。本发明去掉在arraycopy(char[]src,int srcPos,byte[]dst,int dstPos,int length)方法和arraycopy(byte[]src,int srcPos,byte[]dst,int dstPos,int length)方法中对数组长度的判断,让所有的数组复制操作都通过调用native层的System_arraycopyTUnchecked()方法进行;
1.5.2)修改native层的System_arraycopy(JNIEnv*env,jclass,jobjectjavaSrc,jint srcPos,jobject javaDst,jint dstPos,jint length)方法。该方法是把源数组javaSrc中的元素复制到目的数组javaDst中。本发明在System_arraycopy()方法的末尾增加了以下操作:首先,它将javaSrc变量由jobject类型强制转换为Array类型,然后判断javaSrc所含数组元素的类型是否是char或byte类型,如果是,则调用GetTaintData()方法提取出数组中的污点标签,再调用AddTaintData()方法将提出的污点标签添加到目的数组javaDst中;
1.5.3)修改native层的System_arraycopyTUnchecked(JNIEnv*env,jobjectjavaSrc,jint srcPos,jobject javaDst,jint dstPos,jint count)方法。在System_arraycopyTUnchecked()方法的末尾增加以下操作:首先,将javaSrc变量由jobject类型强制转换为Array类型,然后判断javaSrc所含数组元素的类型是否是char或byte类型,如果是,则调用GetTaintData()方法提取出数组中的污点标签,再调用AddTaintData()方法将提取出的污点标签添加到目的数组javaDst中。
1.6)在安卓系统中为线程类添加污点标签成员字段,并修改安卓编译器对数组存取操作的编译操作,满足污点传播的需求;
由于本发明仅为每个数组添加一个污点标签,而不是为数组中的每个元素添加标签,因此,如果单独将数组中的某一个或几个元素复制到新的数组时,可能会丢失污点标签。
安卓系统中每个方法都运行在线程(Thread)中。本发明在线程类中添加了污点标签成员字段,使得当程序通过数组下标对数组中元素进行提取(对应编译时的AGET操作)并存入另一个数组(对应编译时的APUT操作)时附带污点标签数据。具体来说,在提取数组元素时(AGET操作),把被提取元素所在数组的污点标签取出,添加到线程的污点标签成员字段中;当存入数组元素到指定目的数组时(APUT操作),再将线程中存储的污点标签取出,添加到目的数组的污点标签成员字段中。本发明通过修改编译器操作,满足上述需求。
1.6.1)在Thread类中添加一个32位大小的taint_tag字段,用来保存污点标签;
1.6.2)在Thread类中添加一个ThreadTaintTagOffset()方法,返回Thread类中taint_tag字段的类内地址偏移量;
1.6.3)修改GenArrayGet()方法(编译应用时遇到AGET指令所对应的机器指令的生成方法,用来获取指定数组指定下标的数组元素)。本发明在GenArrayGet()方法的末尾增加了以下操作:先申请一个临时寄存器t1,通过指定数组的起始地址和污点标签字段的偏移量,调用loadWordDisp()方法将该数组的污点标签存入寄存器t1;然后,申请一个临时寄存器t2,根据r9寄存器中保存的Thread对象的地址,和Thread类中taint_tag字段的类内偏移值,调用loadWordDisp()方法将Thread对象中的taint_tag字段存入寄存器t2;紧接着,将t1和t2进行按位或运算,结果保存在t1中;最后,调用StoreWordDisp()方法把t1中的值存入Thread对象的taint_tag字段中;
1.6.4)修改GenArrayPut()方法(编译应用时遇到APUT指令所对应的机器指令的生成方法,用来把数据存入指定数组下标的内存中)。本发明在GenArrayPut()方法的末尾增加了以下操作:先申请一个临时寄存器t1,根据rs_rARM_SELF寄存器中保存的Thread对象的地址,和Thread类中taint_tag字段的类内偏移量,调用loadWordDisp()方法将Thread对象中的taint_tag字段存入寄存器t1。然后,申请一个临时寄存器t2,通过指定数组的起始地址和污点标签字段的偏移量,调用loadWordDisp()方法将该数组的污点标签存入寄存器t2。紧接着,将t1和t2进行按位或运算,结果保存在t1中。最后,调用StoreWordDisp()方法把t1中的值存入目标数组的污点标签字段taint_tag中;
1.7)修改安卓系统框架层中字符串类的构造方法和相关操作函数,使字符串类的操作满足污点传播的需求;
字符串有增加、新建、复制、截取等多种相关操作,本发明需保证在将带有污点标签的字符串数据移入新的字符串时,必须将原有的污点标签数据同时移入。为此,本发明在框架层修改了字符串的构造方法相关的操作函数,使得数据在传播的过程中污点标签不会消失。
1.7.1)修改String类的构造方法String(byte[]data,int offset,intbyteCount,Charset charset)。本发明在String()方法的末尾增加了以下操作:首先调用Taint_getTaintByteArray()方法取出参数data数组的污点标签,然后调用Taint_addTaintCharArray()方法把取出的污点标签添加到字符串的成员字段value数组的污点标签字段taint_tag中;
1.7.2)修改String类的getBytes()方法。本发明在getBytes()方法的末尾增加了以下操作:首先调用Taint_getTaintCharArray()方法取出字符串的value字符数组中的污点标签,然后调用Taint_addTaintByteArray()方法把取出的污点标签添加到待返回的字节数组中;
1.7.3)修改String类的split()方法。本发明在split()方法的末尾增加了以下操作:首先调用Taint_getTaintCharArray()方法取出字符串的value字符数组中的污点标签,然后调用Taint_addTaintStringArray()方法把取出的污点标签添加到待返回的字符串数组中的每一个字符串对象中。
1.8)修改安卓系统中短信广播机制的信息存储方式,满足污点传播的需求;
系统获取短信后,把短信协议数据单元PDU字节数组放入intent对象中,然后通过广播发送这个intent对象。短信应用接收到广播后,把短信内容存入短信数据库中。而系统的广播机制是通过进程间通信实现的。安卓系统的进程间通信主要是通过其Binder机制,把intent对象内的数据全部打包到Parcel对象中去,由序列化的Parcel对象进行信息传递。为此,本发明修改了Parcel对象的框架层与native层的实现,为其增加了污点标签成员字段,并修改了其相关方法,使得当字节数组或字符数组写入Parcel对象时,先取出它们携带的污点标签添加到Parcel的污点标签成员字段中;而当要从Parcel对象中读取数组时,则把Parcel对象的污点标签添加到相应的目的数组中。
1.8.1)在框架层的Parcel类定义中添加成员字段taintTag,初始值置为0;
1.8.2)在native层的Parcel类定义中添加成员字段taintTag,初始值置为0;并在Parcel类定义中添加自定义的nativeSetTaint()和nativeGetTaint()方法,分别用来设置和获取native层的Parcel对象的taintTag字段数值(即污点标签);
1.8.3)修改框架层的Parcel类中appendFrom(Parcel parcel,int offset,intlength)方法,本发明在appendFrom()方法的末尾增加了以下操作:首先,获取参数parcel中taintTag字段的值,与当前Parcel对象中taintTag字段的值进行按位或操作后,将结果赋值给当前Parcel对象的taintTag字段,然后调用native层的nativeSetTaint()方法更新污点标签;
1.8.4)修改框架层的Parcel类中writeByteArray(byte[]b,int offset,intlen)方法,本发明在writeByteArray()方法的末尾增加了以下操作:首先通过Taint_getTaintByteArray()方法获取参数b的污点标签值,与当前Parcel对象中的taintTag字段的值进行按位或操作后,将结果赋值给当前Parcel对象的taintTag字段,然后调用native层的nativeSetTaint()方法更新污点标签;
1.8.5)修改框架层的Parcel类中createByteArray()方法,本发明在createByteArray()方法的末尾增加了以下操作:首先调用nativeGetTaint()方法获取native层的污点标签,然后调用Taint_addTaintByteArray()方法把这个污点标签添加到待返回的字节数组中。
1.9)修改安卓系统中框架层文件的读写操作,满足短信验证码数据二次存储时污点标签传播的需求;
当将携带污点标签的短信验证码数据进行二次存储时,数组中保存的污点标签就会丢失。为此,在进行二次存储时,本发明利用文件的可扩展字段保存污点标签,以防止其丢失。
在安卓框架层中所有文件的读写操作最后都是通过调用Posix类中定义的方法实现的,主要包括read(),pread(),readBytes(),preadBytes(),write(),pwrite(),writeBytes(),pwriteBytes()方法。为此,本发明修改了以上所有与文件读写相关的方法。修改后的方法除了完成原有操作外,在读取文件时,还会通过相关系统调用读取文件扩展字段中的污点标签,然后把污点标签添加到待存放文件字节流的字节数组中;而在写入文件时,还会取出字节数组中的污点标签,通过相关系统调用将其写入文件系统的扩展字段中。
1.9.1)修改Posix类中的read(),pread(),readBytes()和preadBytes()方法,本发明在这些方法的末尾增加了以下操作:首先调用Taint_getTaintFile()方法获取文件的污点标签,然后调用Taint_addTaintByteArray()方法将取出的污点标签存入将要保存文件数据的字节数组中;
1.9.2)修改Posix类中的write(),pwrite(),writeBytes()和pwriteBytes()方法,本发明在这些方法的末尾增加以下操作:首先调用Taint_getTaintByteArray()方法获取字节数组的污点标签,然后调用Taint_addTaintFile()方法把取出的数组中污点标签存入目标文件的扩展字段中。
1.10)修改安卓系统中数据库的插入和更新操作,防止短信数据库被污染;
在本发明中,从短信数据库中取出的短信数据经过逻辑判断后,可能会被添加上污点标签TAINT_DB_VALIDATECODE,代表该短信是一条验证码短信。如果再次把带有该标签的数据存入短信数据库中,将导致整个短信数据库文件携带上污点标签TAINT_DB_VALIDATECODE,从而使得所有后续从短信数据库中取出的短信都会携带该标签。为了防止发生这样的问题,在把短信数据插入或更新到短信数据库前,本发明会先获取短信数据的污点标签进行比较,如果污点标签数值大于或等于TAINT_DB_VALIDATECODE,操作将被禁止。
1.10.1)修改ContentResolver类中的insert()方法,本发明中在insert()方法的开始增加了以下操作:获取短信数据的污点标签进行比较,如果该污点标签的数值大于或等于TAINT_DB_VALIDATECODE,则禁止插入,并返回空值;
1.10.2)修改ContentResolver类中的update()方法,本发明中在update()方法的开始增加了以下操作:获取短信数据的污点标签进行比较,如果该污点标签的数值大于或等于TAINT_DB_VALIDATECODE,则禁止更新,并返回空值。
二.接收短信时的标签添加模块
当手机接收到短信时,短信在框架层以协议数据单元PDU字节数组的形式存储,然后将PDU封装在intent对象内部,通过广播的形式告诉应用层的短信应用有新短信到达。短信应用从intent对象中获取PDU字节数组,然后调用SmsMessage类的内部方法createFromPdu()解析PDU字节数组,得到短信内容。
接收短信时的标签添加模块步骤进一步阐述如下。
(2.1)在框架层读取短信协议数据单元PDU;
(2.2)调用addTaintByteArray()方法为短信PDU的字节数组添加污点标签TAINT_SMS;
本发明在短信PDU被广播发送之前,通过调用addTaintByteArray()方法为短信PDU的字节数组添加污点标签TAINT_SMS。在正常情形下,系统自带的短信应用会把所有接收到的短信存入短信数据库中,其他应用需要使用短信数据时,都应从短信数据库中去获取,而不是直接获取广播中的内容。然而在安卓系统中,只要注册了短信广播的应用都可以监听短信广播,获取短信内容。因此某些恶意应用会在短信广播的中途获取短信内容并将其转发出去。
本发明认为任何从短信广播中获取短信内容并直接发送出去(而不是从短信数据库中获取短信内容进行发送)的行为都是非法的。为此,本发明为此类短信数据添加了一个污点标签TAINT_SMS。需要指出的是,系统默认会为所有收到的短信添加污点标签TAINT_SMS。但正常从数据库中取出的短信除了包含TAINT_SMS标签之外,还会包含TAINT_DB标签。
三.读取短信时的标签添加模块
在安卓系统中,当要发送短信时,无论是转发还是直接发送,都会先把发送的短信内容存入短信数据库中;然后调用CursorWrapper类中的方法查询短信数据库,获取待发送的短信,发送出去。
如图2所示,读取短信时的标签添加模块步骤进一步阐述如下。
3.1)读取短信数据库中一条短信的内容body;
本发明通过调用CursorWrapper类中的getString()方法获取短信数据库中的短信内容,即数据库短信记录的body字段;
3.2)调用Taint_addTaintString()方法添加TAINT_DB污点标签到body字符串的污点标签位置;本发明对于从短信数据库中取出的短信数据,都会调用Taint_addTaintString()方法为其添加TAINT_DB污点标签,代表这个短信是从短信数据库中取出的;
3.3)读取短信的源地址字段SA;
通过调用CursorWrapper类中的getString()方法获取短信数据库中的源地址字段SA;
3.4)判断SA是否在地址列表commonNumberList中;如果是,表明该条短信是一个疑似验证码短信,执行3.5),否则跳转到(3.8);
3.5)判断body字段中是否包含4-8位连续数字(或数字加英文),如果是,执行3.6),否则跳转到3.8);
一般的验证码数据都包含4-8个连续的数字(或数字加英文),为此,本发明先在验证码中扫描连续的数字和英文,只有通过这个扫描后,才进行更加耗时的文字内容的判断;
3.6)判断body字段中是否包含“验证”或“密码”关键字,如果是,表明这是一个短信验证码数据,执行3.7),否则跳转到3.8);
3.7)调用Taint_addTaintString()方法添加TAINT_DB_VALIDATECODE污点标签到body字符串的污点标签位置;
3.8)返回body。
四.通过短信发送验证码时的检测模块
如图3所示,通过短信发送验证码时的检测模块步骤进一步阐述如下。
4.1)读取待发送短信的污点标签,并将其赋给TAG;
调用Taint_getTaintString()方法,读取待发送短信的污点标签,并将结果赋值给TAG;
4.2)判断TAG是否大于TAINT_NONE,如是,执行4.3),否则交由系统直接发送短信;
TAG大于TAINT_NONE(数值为0),代表数据包含了有效污点标签,TAG等于TAINT_NONE则代表数据不包含有效污点标签;
4.3)判断TAG是否大于或等于TAINT_DB,如果是,执行4.4),否则跳转到4.5);
如果TAG大于等于TAINT_DB,说明这是一个从短信数据库中取出的短信;如果TAG大于0且小于TAINT_DB,说明这个不是从短信数据库中取出的,而是从短信广播中直接获取并转发出来的,对于此类短信,系统均认为是非法的,将禁止发送;
4.4)判断TAG是否大于或等于TAINT_DB_VALIDATECODE,如果是,代表正在发送一个短信验证码数据,执行4.5),否则交由系统直接发送短信;
如果TAG大于等于TAINT_DB_VALIDATECODE,代表这是一个验证码数据,因此,系统将禁止发送;
4.5)禁止短信发送,并提示用户有短信验证码正在试图通过短信发送出去,并打印出短信内容和目的地址。
五.通过网络发送验证码时的检测模块;
如图4所示,通过网络发送验证码时的检测模块步骤进一步阐述如下。
5.1)读取待发送短信数据中的污点标签,并将其赋给TAG;
调用Taint_getTaintByteArray()方法,读取短信数据的污点标签,并将结果赋值给TAG;
5.2)判断TAG是否大于TAINT_NONE,如果是,执行5.3),否则交由系统直接发送;
TAG大于TAINT_NONE(数值为0),代表包含了有效污点标签,TAG=TAINT_NONE(数值为0)代表不包含有效污点标签;
5.3)判断TAG是否大于或等于TAINT_DB,如果是,执行5.4),否则跳转到5.5);
如果TAG大于等于TAINT_DB,说明这是一个从短信数据库中取出的短信;如果TAG大于0且小于TAINT_DB,说明这个不是从短信数据库中取出的,而是从短信广播中直接获取内容后通过网络转发,对于此类网络转发,系统均认为是非法的,将禁止发送;
5.4)判断TAG是否大于或等于TAINT_DB_VALIDATECODE,如果是,代表正在发送一个短信验证码数据,执行5.5),否则交由系统直接发送;如果TAG大于等于TAINT_DB_VALIDATECODE,代表这是一个验证码数据,因此,系统将禁止发送;
5.5)禁止网络传输数据,提示用户有短信验证码数据正在试图通过网络发送出去,并打印出数据内容和目的地址。
本发明的功能效果可以通过以下实验进一步说明:
步骤A,开启两个手机模拟器A和B,A模拟器作为验证码短信发送者(将A模拟器的号码添加进短信验证码发送地址列表commonNumberList中),B模拟器作为验证码接收者,装有恶意软件。B模拟器中的恶意软件通过广播接收模拟器A发来的短信,通过短信方式发送给一个指定号码;紧接着,恶意软件从短信数据库中取出收到的短信并通过网络发送出去;
步骤B,在模拟器A中编辑短信“验证码保护测试短信,验证码:123456”,发送给B;
步骤C,模拟器B在logcat日志中看到以下信息:“add TAINT_SMS successfully”,说明发送广播之前成功对这个验证码短信添加了污点标签TAINT_SMS;
步骤D,模拟器B在logcat日志中看到以下信息:“SmsManager:Can not sendSmswith TAINT_SMS”,说明恶意软件试图通过短信发送的方式将这条验证码信息发送出去,本发明成功检测到了该操作,并禁止了这次传输;
步骤E,模拟器B在logcat日志中看到以下信息:“CursorWrapper-getString:addTAINT_DB_VALIDATECODE successfully”,说明恶意软件从短信数据库中提取了一条短信,本发明经过逻辑判断,发现这是一条验证码短信,所以为短信内容添加了TAINT_DB_VALIDATECODE标签;
步骤F,模拟器B在logcat日志中看到以下信息:“Posix:can not sendData withTAINT_DB_VALIDATECODE”,说明恶意软件正在通过网络发送验证码短信,本发明成功检测到了该操作,并禁止了这次传输。
本发明的性能效果可以通过以下实验进一步说明:
1)实验条件
将本发明实现在修改的安卓5.0版本中。使用Eclipse在PC机上启动安卓模拟器进行测试。PC机选用惠普Pro 3380MT台式机,它的CPU是CoreTM i5-3470,内存为4GB。
2)实验内容
选用benchmark测试工具CF_bench分别对安卓5.0原版系统和应用本发明的安卓5.0系统进行对比测试,得出本发明所带来的性能损失。测试的任务包括18项,分别是:本地MIPS值,JavaMIPS值,本地MSFLOPS值,JavaMSFLOPS值,本地MDFLOPS值,JavaMDFLOPS值,本地内存读取值,Java内存读取值,本地内存写入值,Java内存写入值,本地磁盘读取值,本地磁盘写入值,Java高效MIPS值,Java高效MSFLOPS值,Java高效MDFLOPS值,Java高效内存读取,Java高效内存写入,本地内存分配,共测试10次取平均值。
3)结果分析:测试结果如图5所示,安卓5.0原版系统和应用本发明的安卓5.0系统进行对比,性能损耗较小。性能损耗最大为12%(本地磁盘写入值),损耗最小为0(JavaMIPS值等),18项测试的平均性能损耗为2%。
Claims (9)
1.一种防止安卓手机短信验证码被窃取的方法,其特征在于,包括以下步骤:
步骤一、按照以下过程进行模块初始化:1.1.设置短信验证码发送地址列表commonNumberList;根据发送短信的源地址是否在commonNumberList列表中判断该短信是否可能是一个验证码短信;1.2对字符数组和字节数组进行标记,在数据末尾添加一个位向量,所述位向量的每一个数据位代表一种标签,定义四个污点标签常量:空污点标签、短信数据标签、数据库标签、验证码标签;1.3.修改安卓系统数组在内存中的分配方式与数组大小的计算方式,让每个数组拥有一个污点标签成员字段,使每个数组能够存储有效的污点标签;1.4.在安卓系统中自定义污点标签添加和读取方法,并注册成虚拟机内部方法,满足污点标签操作相关方法调用的需求;1.5.修改安卓系统中数组在native层和框架层的复制方式,使数组复制时满足污点传播的需求;1.6.安卓系统中每个方法都运行在线程中,在安卓系统中为线程类添加污点标签成员字段,并修改安卓编译器对数组存取操作的编译操作,满足污点传播的需求;1.7.修改安卓系统框架层中字符串类的构造方法和相关操作函数,使字符串类的操作满足污点传播的需求;1.8.修改安卓系统中短信广播机制的信息存储方式,满足污点传播的需求;1.9.修改安卓系统中框架层文件的读写操作,满足短信验证码数据二次存储时污点标签传播的需求;1.10.修改安卓系统中数据库的插入和更新操作,防止短信数据库被污染;
步骤二、接收短信时的标签添加模块;
2.1.在框架层读取短信协议数据单元PDU;
2.2.为短信PDU的字节数组添加污点标签TAINT_SMS;
步骤三、读取短信时的标签添加模块:3.1.读取短信数据库中一条短信的内容;3.2.添加TAINT_DB污点标签到短信内容字符串的污点标签位置;3.3.读取短信的源地址字段;3.4.判断源地址字段是否在地址列表commonNumberList中;如是,表明该条短信是一个疑似验证码短信,执行3.5,否则跳转到3.8;3.5.判断短信内容字段中是否包含4-8位的连续数字或数字加英文,如是,执行3.6,否则跳转到3.8;3.6.判断短信内容字段中是否包含“验证”或“密码”关键字,如是,表明这是一个短信验证码数据,执行3.7,否则跳转到3.8;3.7.添加TAINT_DB_VALIDATECODE污点标签到短信内容字符串的污点标签位置;3.8返回短信内容;
步骤四、通过短信发送验证码时的检测模块:4.1.读取待发送短信的污点标签,并将其赋给TAG;4.2.判断TAG是否大于TAINT_NONE,如是,执行4.3,否则交由系统直接发送短信;4.3.判断TAG是否大于或等于TAINT_DB,如是,执行4.4,否则跳转到4.5;4.4.判断TAG是否大于或等于TAINT_DB_VALIDATECODE,如是,代表正在发送一个短信验证码数据,执行4.5,否则交由系统直接发送短信;4.5.禁止短信发送,并提示用户有短信验证码正在试图通过短信发送出去,并打印出短信内容和目的地址;
步骤五、通过网络发送验证码时的检测模块:5.1.读取待发送短信数据中的污点标签,并将其赋给TAG;5.2.判断TAG是否大于TAINT_NONE,如是,执行5.3,否则交由系统直接发送;5.3.判断TAG是否大于或等于TAINT_DB,如是,执行5.4,否则跳转到5.5;5.4.判断TAG是否大于或等于TAINT_DB_VALIDATECODE,如是,代表正在发送一个短信验证码数据,执行5.5,否则交由系统直接发送;5.5.禁止网络传输数据,提示用户有短信验证码数据正在试图通过网络发送出去,并打印出数据内容和目的地址。
2.根据权利要求1所述防止安卓手机短信验证码被窃取的方法,其特征在于,步骤1.3的具体过程包括:1.3.1.修改安卓系统中native层数组类Array的结构,为其增加一个存储污点标签的32位字段taint_tag;1.3.2.修改安卓系统中native层数组类Array中所包含的方法ComputeArraySize(),使得在给数组分配空间时,每个数组额外增加4个字节的空间;1.3.3.修改安卓系统中native层数组类Array中所包含的方法SizeOf(),将其原计算结果增加4个字节,与ComputerArraySize()保持一致;1.3.4在安卓系统中native层数组类Array中自定义两个新的方法,分别是污点添加方法AddTaintData(size_t component_size,int32_t taintTag)和污点获取方法GetTaintData(size_t component_size);所述的污点添加方法AddTaintData(size_t component_size,int32_t taintTag)根据数组元素类型所占的字节大小component_size和数组在内存中的起始地址,计算得到数组对象中taint_tag字段所在的地址空间,从这个地址空间读取taint_tag的值,并将其与参数taintTag进行按位或运算,得到新的标签值,存入taint_tag字段所在的地址空间;污点获取方法GetTaintData(size_t component_size)根据数组元素类型所占的字节大小component_size和数组在内存中的起始地址,计算得到数组对象中taint_tag字段所在的地址空间,从这个地址空间读取并返回taint_tag的值。
3.根据权利要求1所述防止安卓手机短信验证码被窃取的方法,其特征在于,所述步骤1.4的具体过程包括:1.4.1.自定义Taint_getTaintByteArray(JNIEnv*env,jclass,jbyteArray theArray)方法,获取目标字节数组的污点标签,框架层通过jni调用传来的参数theArray字节数组强制类型转换成Array对象,然后调用Array对象的类内方法GetTaintData(size_t component_size)获取并返回这个字节数组的污点标签;1.4.2.自定义Taint_addTaintByteArray(JNIEnv*env,jclass,jbyteArray theArray,jint taint_tag)方法,给目标字节数组添加污点标签,框架层通过jni调用传来的参数theArray字节数组强制类型转换成Array对象,然后调用Array对象的类内方法AddTaintData(size_tcomponent_size,int32_t taintTag)把污点标签存入这个字节数组的污点标签字段;1.4.3.自定义Taint_getTaintCharArray(JNIEnv*env,jclass,jcharArray theArray)方法,获取目标字符数组的污点标签,框架层通过jni调用传来的参数theArray字符数组强制类型转换成Array对象,然后调用Array对象的类内方法GetTaintData(size_t component_size)获取并返回这个字符数组的污点标签;1.4.4.自定义Taint_addTaintCharArray(JNIEnv*env,jclass,jcharArray theArray,jint taint_tag)方法,用于给目标字符数组添加污点标签,框架层通过jni调用传来的参数theArray字符数组强制类型转换成Array对象,然后调用Array对象的类内方法AddTaintData(size_t component_size,int32_ttaintTag)把污点标签存入这个字符数组的污点标签字段;1.4.5.自定义Taint_getTaintString(JNIEnv*env,jclass,jstring theString)方法,获取目标字符串的污点标签,首先把框架层String类型的theString参数强制类型转换成native层的String对象,然后调用String类内方法GetCharArray()获取数据所在的字符数组,最后调用GetTaintData()方法获取并返回这个字符数组的污点标签;1.4.6.自定义Taint_addTaintString(JNIEnv*env,jclass,jstring theString,jint taint_tag)方法,为目标字符串添加污点标签,首先把框架层的String类型的theString参数强制类型转换成native层的String对象,然后调用String类内方法GetCharArray()获取数据所在的字符数组,最后调用AddTaintData()方法为该字符数组添加污点标签;1.4.7自定义Taint_getTaintFile(JNIEnv*env,jclass,jint fd,jint taint_tag)方法,读取目标文件扩展字段的污点标签,直接通过系统调用_NR_fgetxattr()获取指定文件的扩展字段所包含的污点标签;1.4.8.自定义Taint_addTaintFile(JNIEnv*env,jclass,jint fd,jint taint_tag)方法,为目标文件扩展字段添加污点标签,首先调用Taint_getTaintFile()方法获取该文件的原污点标签,然后与新污点标签taint_tag进行按位或运算,得到结果,最后通过系统调用_NR_fsetxattr()将结果添加到指定文件的扩展字段中。
4.根据权利要求1所述防止安卓手机短信验证码被窃取的方法,其特征在于,步骤1.5的具体过程为:1.5.1.修改框架层arraycopy(char[]src,int srcPos,byte[]dst,intdstPos,int length)方法和arraycopy(byte[]src,int srcPos,byte[]dst,int dstPos,int length)方法,所有的数组复制操作都通过调用native层的System_arraycopyTUnchecked()方法进行;1.5.2.修改native层的System_arraycopy(JNIEnv*env,jclass,jobject javaSrc,jint srcPos,jobject javaDst,jint dstPos,jintlength)方法,在System_arraycopy()方法的末尾增加了以下操作:首先将javaSrc变量由jobject类型强制转换为Array类型,然后判断javaSrc所含数组元素的类型是否是char或byte类型,如是,则调用GetTaintData()方法提取出数组中的污点标签,再调用AddTaintData()方法将提出的污点标签添加到目的数组javaDst中;1.5.3.修改native层的System_arraycopyTUnchecked(JNIEnv*env,jobject javaSrc,jint srcPos,jobjectjavaDst,jint dstPos,jint count)方法,在System_arraycopyTUnchecked()方法的末尾增加以下操作:首先,将javaSrc变量由jobject类型强制转换为Array类型,然后判断javaSrc所含数组元素的类型是否是char或byte类型,如是,则调用GetTaintData()方法提取出数组中的污点标签,再调用AddTaintData()方法将提取出的污点标签添加到目的数组javaDst中。
5.根据权利要求1所述防止安卓手机短信验证码被窃取的方法,其特征在于,步骤1.6的具体过程为:1.6.1.在Thread类中添加一个32位大小的taint_tag字段保存污点标签;1.6.2.在Thread类中添加一个ThreadTaintTagOffset()方法,返回Thread类中taint_tag字段的类内地址偏移量;1.6.3.修改GenArrayGet()方法,在GenArrayGet()方法的末尾增加以下操作:先申请一个临时寄存器t1,通过指定数组的起始地址和污点标签字段的偏移量,调用loadWordDisp()方法将该数组的污点标签存入寄存器t1;然后申请一个临时寄存器t2,根据r9寄存器中保存的Thread对象的地址和Thread类中taint_tag字段的类内偏移值,调用loadWordDisp()方法将Thread对象中的taint_tag字段存入寄存器t2;将t1和t2进行按位或运算,结果保存在t1中;最后调用StoreWordDisp()方法把t1中的值存入Thread对象的taint_tag字段中;1.6.4.修改GenArrayPut()方法,在GenArrayPut()方法的末尾增加了以下操作:先申请一个临时寄存器t1,根据rs_rARM_SELF寄存器中保存的Thread对象的地址和Thread类中taint_tag字段的类内偏移量,调用loadWordDisp()方法将Thread对象中的taint_tag字段存入寄存器t1,申请一个临时寄存器t2,通过指定数组的起始地址和污点标签字段的偏移量,调用loadWordDisp()方法将该数组的污点标签存入寄存器t2,将t1和t2按位或运算,结果保存在t1中,调用StoreWordDisp()方法把t1中的值存入目标数组的污点标签字段taint_tag中。
6.根据权利要求1所述防止安卓手机短信验证码被窃取的方法,其特征在于,步骤1.7的具体过程为:1.7.1.修改String类的构造方法String(byte[]data,int offset,intbyteCount,Charset charset),在String()方法的末尾增加以下操作:首先调用Taint_getTaintByteArray()方法取出参数data数组的污点标签,然后调用Taint_addTaintCharArray()方法把取出的污点标签添加到字符串的成员字段value数组的污点标签字段taint_tag中;1.7.2.修改String类的getBytes()方法,在getBytes()方法的末尾增加以下操作:首先调用Taint_getTaintCharArray()方法取出字符串的value字符数组中的污点标签,然后调用Taint_addTaintByteArray()方法把取出的污点标签添加到待返回的字节数组中;1.7.3.修改String类的split()方法,在split()方法的末尾增加以下操作:首先调用Taint_getTaintCharArray()方法取出字符串的value字符数组中的污点标签,然后调用Taint_addTaintStringArray()方法把取出的污点标签添加到待返回的字符串数组中的每一个字符串对象中。
7.根据权利要求1所述防止安卓手机短信验证码被窃取的方法,其特征在于,步骤1.8的具体过程为:1.8.1.在框架层的Parcel类定义中添加成员字段taintTag,初始值置为0;1.8.2.在native层的Parcel类定义中添加成员字段taintTag,初始值置为0;并在Parcel类定义中添加自定义的nativeSetTaint()和nativeGetTaint()方法,分别用来设置和获取native层Parcel对象的taintTag字段数值;1.8.3.修改框架层的Parcel类中appendFrom(Parcel parcel,int offset,int length)方法,在appendFrom()方法的末尾增加以下操作:首先,获取参数parcel中taintTag字段的值,与当前Parcel对象中taintTag字段的值进行按位或操作后,将结果赋值给当前Parcel对象的taintTag字段,然后调用native层的nativeSetTaint()方法更新污点标签;1.8.4.修改框架层的Parcel类中writeByteArray(byte[]b,int offset,int len)方法,在writeByteArray()方法的末尾增加以下操作:首先,通过Taint_getTaintByteArray()方法获取参数b的污点标签值,与当前Parcel对象中的taintTag字段的值进行按位或操作后,将结果赋值给当前Parcel对象的taintTag字段,然后调用native层的nativeSetTaint()方法更新污点标签;1.8.5.修改框架层的Parcel类中createByteArray()方法,在createByteArray()方法的末尾增加以下操作:首先调用nativeGetTaint()方法获取native层的污点标签,然后调用Taint_addTaintByteArray()方法把这个污点标签添加到待返回的字节数组中。
8.根据权利要求1所述防止安卓手机短信验证码被窃取的方法,其特征在于,步骤1.9的具体过程为:1.9.1.修改Posix类中的read(),pread(),readBytes()和preadBytes()方法,在这些方法的末尾增加以下操作:首先调用Taint_getTaintFile()方法获取文件的污点标签,然后调用Taint_addTaintByteArray()方法将取出的污点标签存入将要保存文件数据的字节数组中;1.9.2.修改Posix类中的write(),pwrite(),writeBytes()和pwriteBytes()方法,在这些方法的末尾增加以下操作:首先调用Taint_getTaintByteArray()方法获取字节数组的污点标签,然后调用Taint_addTaintFile()方法把取出的数组中的污点标签存入到目标文件的扩展字段中。
9.根据权利要求1所述防止安卓手机短信验证码被窃取的方法,其特征在于,步骤1.10的具体过程为:1.10.1.修改ContentResolver类中的insert()方法,在insert()方法的开始增加以下操作:获取短信数据的污点标签进行比较,如果该污点标签的数值大于或等于TAINT_DB_VALIDATECODE,则禁止插入,并返回空值;1.10.2.修改ContentResolver类中的update()方法,在update()方法的开始增加以下操作:获取短信数据的污点标签进行比较,如果该污点标签的数值大于或等于TAINT_DB_VALIDATECODE,则禁止更新,并返回空值。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201710035104.XA CN106803028B (zh) | 2017-01-18 | 2017-01-18 | 一种防止安卓手机短信验证码被窃取的方法 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201710035104.XA CN106803028B (zh) | 2017-01-18 | 2017-01-18 | 一种防止安卓手机短信验证码被窃取的方法 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN106803028A true CN106803028A (zh) | 2017-06-06 |
CN106803028B CN106803028B (zh) | 2019-08-30 |
Family
ID=58984497
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN201710035104.XA Active CN106803028B (zh) | 2017-01-18 | 2017-01-18 | 一种防止安卓手机短信验证码被窃取的方法 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN106803028B (zh) |
Cited By (5)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN107330345A (zh) * | 2017-07-05 | 2017-11-07 | 北京理工大学 | 一种检测隐私数据泄露的方法和装置 |
CN109145645A (zh) * | 2018-08-29 | 2019-01-04 | 西安电子科技大学 | 一种保护安卓手机中短信验证码的方法 |
WO2020199035A1 (zh) * | 2019-03-29 | 2020-10-08 | 华为技术有限公司 | 一种减少嗅探攻击的方法、装置及集成电路 |
CN112512046A (zh) * | 2020-12-16 | 2021-03-16 | 南京理工大学 | 一种Android应用程序短信验证码认证过程安全性检测方法 |
CN112860224A (zh) * | 2019-11-28 | 2021-05-28 | 北京达佳互联信息技术有限公司 | 一种函数执行环境构建方法、装置、电子设备及存储介质 |
Citations (5)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN103309808A (zh) * | 2013-06-13 | 2013-09-18 | 中国科学院信息工程研究所 | 基于标签的安卓用户隐私泄露黑盒检测方法及系统 |
CN103729595A (zh) * | 2014-01-02 | 2014-04-16 | 东南大学 | 一种Android应用程序隐私数据泄露离线检测方法 |
CN104217162A (zh) * | 2014-09-05 | 2014-12-17 | 四川长虹电器股份有限公司 | 一种智能终端恶意软件的检测方法及系统 |
CN104361281A (zh) * | 2014-11-17 | 2015-02-18 | 西安电子科技大学 | 一种安卓平台钓鱼攻击的解决方法 |
CN104965788A (zh) * | 2015-07-03 | 2015-10-07 | 电子科技大学 | 一种代码静态检测方法 |
-
2017
- 2017-01-18 CN CN201710035104.XA patent/CN106803028B/zh active Active
Patent Citations (5)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN103309808A (zh) * | 2013-06-13 | 2013-09-18 | 中国科学院信息工程研究所 | 基于标签的安卓用户隐私泄露黑盒检测方法及系统 |
CN103729595A (zh) * | 2014-01-02 | 2014-04-16 | 东南大学 | 一种Android应用程序隐私数据泄露离线检测方法 |
CN104217162A (zh) * | 2014-09-05 | 2014-12-17 | 四川长虹电器股份有限公司 | 一种智能终端恶意软件的检测方法及系统 |
CN104361281A (zh) * | 2014-11-17 | 2015-02-18 | 西安电子科技大学 | 一种安卓平台钓鱼攻击的解决方法 |
CN104965788A (zh) * | 2015-07-03 | 2015-10-07 | 电子科技大学 | 一种代码静态检测方法 |
Cited By (8)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN107330345A (zh) * | 2017-07-05 | 2017-11-07 | 北京理工大学 | 一种检测隐私数据泄露的方法和装置 |
CN107330345B (zh) * | 2017-07-05 | 2020-11-27 | 北京理工大学 | 一种检测隐私数据泄露的方法和装置 |
CN109145645A (zh) * | 2018-08-29 | 2019-01-04 | 西安电子科技大学 | 一种保护安卓手机中短信验证码的方法 |
CN109145645B (zh) * | 2018-08-29 | 2021-09-10 | 西安电子科技大学 | 一种保护安卓手机中短信验证码的方法 |
WO2020199035A1 (zh) * | 2019-03-29 | 2020-10-08 | 华为技术有限公司 | 一种减少嗅探攻击的方法、装置及集成电路 |
CN112860224A (zh) * | 2019-11-28 | 2021-05-28 | 北京达佳互联信息技术有限公司 | 一种函数执行环境构建方法、装置、电子设备及存储介质 |
CN112860224B (zh) * | 2019-11-28 | 2023-12-12 | 北京达佳互联信息技术有限公司 | 一种函数执行环境构建方法、装置、电子设备及存储介质 |
CN112512046A (zh) * | 2020-12-16 | 2021-03-16 | 南京理工大学 | 一种Android应用程序短信验证码认证过程安全性检测方法 |
Also Published As
Publication number | Publication date |
---|---|
CN106803028B (zh) | 2019-08-30 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
CN106803028B (zh) | 一种防止安卓手机短信验证码被窃取的方法 | |
Musch et al. | New Kid on the Web: A Study on the Prevalence of WebAssembly in the Wild | |
CN104766012B (zh) | 基于动态污点追踪的数据安全动态检测方法及系统 | |
CN108289095A (zh) | 一种敏感数据存储方法、装置及系统 | |
CN111400757B (zh) | 防止安卓第三方库中native代码泄露用户隐私的方法 | |
CN108399332A (zh) | 在虚拟机中针对恶意性对文件进行分析的系统和方法 | |
CN110046494B (zh) | 基于终端的大数据处理方法及系统 | |
CN102467628A (zh) | 一种基于浏览器内核拦截技术的数据保护方法 | |
CN107944274A (zh) | 一种基于宽度学习的Android平台恶意应用离线检测方法 | |
CN111881449B (zh) | 恶意代码辅助分析方法及装置 | |
CN104361281B (zh) | 一种安卓平台钓鱼攻击的解决方法 | |
CN107450964A (zh) | 一种用于发现虚拟机自省系统中是否存在漏洞的方法 | |
CN103329141B (zh) | 数据安全存储方法及装置 | |
US11947666B2 (en) | Systems and methods for exploit prevention and malicious code neutralization using non-predictable results for JavaScript-enabled applications | |
CN109558207A (zh) | 在虚拟机中形成用于进行文件的防病毒扫描的日志的系统和方法 | |
CN108334404A (zh) | 应用程序的运行方法和装置 | |
Da et al. | Detection of Android malware security on system calls | |
CN104615935B (zh) | 一种面向Xen虚拟化平台的隐藏方法 | |
CN107066886A (zh) | 一种Android加固脱壳的检测方法 | |
CN108734014A (zh) | 密码数据验证方法和装置、密码数据保护方法和装置 | |
CN112883374B (zh) | 一种基于ART环境下的Android平台应用程序通用脱壳方法及系统 | |
CN103997490B (zh) | 未知文件样本安全性鉴定的方法及装置 | |
CN111212420A (zh) | 一种通过vsa技术伪装设备信息的方法 | |
CN109145645A (zh) | 一种保护安卓手机中短信验证码的方法 | |
CN112395617A (zh) | 防护docker逃逸漏洞的方法、装置、存储介质及计算机设备 |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |