CN109471800A - 一种基于Windows操作系统的软件无限断点设置方法 - Google Patents
一种基于Windows操作系统的软件无限断点设置方法 Download PDFInfo
- Publication number
- CN109471800A CN109471800A CN201811289072.7A CN201811289072A CN109471800A CN 109471800 A CN109471800 A CN 109471800A CN 201811289072 A CN201811289072 A CN 201811289072A CN 109471800 A CN109471800 A CN 109471800A
- Authority
- CN
- China
- Prior art keywords
- page
- function
- breakpoint
- operating system
- windows operating
- 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
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F11/00—Error detection; Error correction; Monitoring
- G06F11/36—Preventing errors by testing or debugging software
- G06F11/362—Software debugging
- G06F11/3636—Software debugging by tracing the execution of the program
Landscapes
- Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Computer Hardware Design (AREA)
- Quality & Reliability (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Debugging And Monitoring (AREA)
Abstract
一种基于Windows操作系统的软件无限断点设置方法,首先对被调试软件设置若干断点,然后将断点地址所在的内存页的属性改为不可访问,被调试软件执行过程中触发页面错误异常并执行到MmAccessFault()函数入口时,判断该页面错误异常的内存地址是否是设置的断点,如果是则通过NtProtectVirtualMemory()函数修改断点所在的内存页的属性为可读可写可执行,并将开启单步调试模式,被调试软件继续执行,当触发调试陷阱异常并执行到Windows操作系统内核的KiTrap01()函数的入口时,通过NtProtectVirtualMemory()函数设置该断点所在的内存页的属性为不可访问,恢复断点设置,关闭单步调试模式,被调试软件继续执行。
Description
技术领域
本发明涉及计算机应用技术软件调试领域,具体涉及一种基于Windows操作系统的软件无限断点设置方法。
背景技术
随着网络攻击技术的发展,计算机恶意软件的数量和种类呈现逐年上升的态势,其中大部分是基于Windows操作系统的恶意软件。由于大部分恶意软件无法获得源代码,计算机安全人员为了分析恶意软件的工作原理,需要使用调试器设置断点对恶意软件的二进制程序进行动态调试,以便获得其结构和内部功能。
现有基于Windows操作系统的软件调试器可设置断点的类型主要有两种:一种是硬件断点,另一种是软件断点。硬件断点由CPU处理器提供,但是由于CPU处理存储单元有限,只能设置有限个(一般2到4个)断点。软件断点是通过调试器修改被调试软件代码,插入异常出发指令来实现,可以设置无限多个断点。但是由于很多恶意软件检测自身代码是否被修改,来判断调试器的存在,进而退出运行,令恶意软件无法被调试。
因此,需要一种可以解决以上问题的基于Windows操作系统的软件无限断点设置方法。
发明内容
本发明解决的技术问题是:提供一种基于Windows操作系统的软件无限断点设置方法,能够解决现有针对恶意软件调试中可设置硬件断点数量不多、软件断点设置容易被发现的问题。
本发明的技术解决方案是:一种基于Windows操作系统的软件无限断点设置方法,包括步骤如下:
(1)在Windows操作系统下,通过调试器D对被调试软件S设置若干断点,若干断点内存地址值的集合为P={p1,p2,..,pn},调试器将集合P的各个元素所在的内存页的属性通过NtProtectVirtualMemory()函数改为不可访问PAGE_NOACCESS,转入步骤(2),其中,pi为第i个断点对应的内存地址值,pi、pi对应的内存页可以相同;
(2)运行被调试软件S,当被调试软件S执行过程触发Windows页面错误异常并执行到Windows操作系统内核的MmAccessFault()函数的入口且未开始执行MmAccessFault()函数时,执行钩子函数FuncA,转入步骤(3);
(3)在钩子函数FuncA中,通过寄存器EDI获得引发Windows页面错误异常对应的内存地址值a1,然后与集合P的各个元素进行比较,如果存在a1=pi,pi∈P,则成功触发断点pi,通知调试器D,转入步骤(4);否则,未触发断点,转入步骤(7);
(4)通过NtProtectVirtualMemory()函数设置a1所在的内存页的属性为PAGE_READWRITE和PAGE_EXECUTE,使得该内存页的属性为可读可写可执行,并将标志寄存器的TF标志位置为1,开启单步调试模式,结束钩子函数FuncA执行,然后继续执行MmAccessFault()函数,Windows操作系统处理完异常后,被调试软件S继续执行,转入步骤(5);
(5)当被调试软件S在执行过程中,触发调试陷阱异常并执行到Windows操作系统内核的KiTrap01()函数的入口且未执行KiTrap01()函数时,执行钩子函数FuncB,转入步骤(6);
(6)在钩子函数FuncB中,通过NtProtectVirtualMemory()函数设置a1所在的内存页的属性为不可访问PAGE_NOACCESS,进而恢复断点设置,并将标志寄存器的TF标志位置为0,关闭单步调试模式,结束钩子函数FuncB执行,继续执行KiTrap01()函数,Windows操作系统处理完异常后,转入步骤(9);
(7)计算步骤(3)中a1所在的内存页首地址值元素b1和步骤(1)中集合P的各元素所在的内存页首地址值的集合P′={p′1,p′2,...,p′n},然后将b1与集合P′的各个元素进行比较,如果存在b1=p′i,P′i∈P′,转入步骤(4);否则,转入步骤(8);
(8)结束钩子函数FuncA执行,继续执行MmAccessFault()函数,Windows操作系统处理完异常后,转入步骤(9)。
(9)被调试软件S继续执行,步骤结束。
所述的Windows操作系统的版本为Windows xp、Windows 7(32位)。
所述的钩子函数FuncB为:
通过NtProtectVirtualMemory()函数设置a1所在的内存页的属性为不可访问PAGE_NOACCESS,进而恢复断点设置,并将标志寄存器的TF标志位置为0,关闭单步调试模式。
所述的钩子函数FuncA包括:
步骤(3)、步骤(7)、步骤(4)中的通过NtProtectVirtualMemory()函数设置a1所在的内存页的属性为PAGE_READWRITE和PAGE_EXECUTE,使得该内存页的属性为可读可写可执行,并将标志寄存器的TF标志位置为1,开启单步调试模式.
本发明的优点在于:
(1)可以设置无限个软件断点;
(2)不修改被调试软件的代码;
(3)保证断点的持久性。
附图说明
图1为本发明一种基于Windows操作系统的软件无限断点设置方法的流程图。
具体实施方式
一种基于Windows操作系统的软件的无限断点设置方法,包括步骤如下:
(1)在Windows操作系统下,使用人员通过调试器D对被调试软件S设置若干断点,其内存地址值用集合P={p1,p2,...,pn}表示,调试器将集合P的各个元素所在的内存页的属性通过NtProtectVirtualMemory()函数设置为PAGE_NOACCESS(不可访问),转入步骤(2)。
(2)运行被调试软件S,当执行触发Windows页面错误异常并执行到Windows操作系统内核的MmAccessFault()函数的入口时,进入钩子函数FuncA,转入步骤(3)。
(3)在钩子函数FuncA中,通过寄存器EDI获得引发内存页错误的内存地址值a1,然后与集合P的各个元素进行比较,如果存在a1=pi,pi∈P,则成功触发断点pi,通知调试器D,转入步骤(4);否则,未触发断点,转入步骤(7)。
(4)通过NtProtectVirtualMemory()函数设置a1所在的内存页的属性为PAGE_READWRITE和PAGE_EXECUTE(可读可写可执行),并将标志寄存器的TF标志位置为1,开启单步调试模式。从钩子函数FuncA返回,继续执行MmAccessFault()函数,Windows操作系统处理完异常后,被调试软件S继续执行,转入步骤(5)。
(5)这时由于Windows操作系统开启了单步调试模式,被调试软件S执行触发调试陷阱异常并执行到Windows操作系统内核的KiTrap01()函数的入口时,进入钩子函数FuncB,转入步骤(6)。
(6)在钩子函数FuncB中,通过NtProtectVirtualMemory()函数设置a1所在的内存页的属性为PAGE_NOACCESS(不可访问),恢复断点设置,并将标志寄存器的TF标志位置为0,关闭单步调试模式。最后从钩子函数FuncB返回,继续执行KiTrap01()函数,Windows操作系统处理完异常后,转入步骤(9)。
(7)计算步骤(3)中a1所在的内存页首地址值元素b1和步骤(1)中集合P的各元素所在的内存页首地址值的集合P′={p′1,p′2,...,p′n},然后将b1与集合P′的各个元素进行比较,如果存在b1=p′i,P′i∈P′,转入步骤(4);否则,转入步骤(8)。
(8)从钩子函数FuncA返回,继续执行MmAccessFault()函数,Windows操作系统处理完异常后,转入步骤(9)。
(9)被调试软件S继续执行,步骤结束。
为使本发明实施例的目的、技术方案和优点更加清楚,下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚地描述,显然,所描述的实施例是本发明一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。
如图1所示,本发明实施例1:某Windows软件调试过程中设置若干断点并触发某断点的过程,包括:
S1、使用人员通过调试器D0对被调试软件S0设置若干断点,其内存地址值用集合P0={p1=0x00081234,p2=0x0009445a,p3=0x000a258e}表示,调试器将集合P0的各个元素所在的内存页的属性通过NtProtectVirtualMemory()函数设置为PAGE_NOACCESS(不可访问)。
S2、运行被调试软件S0,S0执行触发Windows页面错误异常并执行到Windows操作系统内核的MmAccessFault()函数的入口时,进入钩子函数MyMmAccessFault()。
S3、在钩子函数MyMmAccessFault()中,通过寄存器EDI获得引发内存页错误的内存地址值a0=0x0009445a,然后与集合P0的各个元素进行比较,发现a0=p2,触发断点p2,通知调试器D0
S4、通过NtProtectVirtualMemory()函数设置a0所在的内存页的属性为PAGE_READWRITE和PAGE_EXECUTE(可读可写可执行),并将标志寄存器的TF标志位置为1,开启单步调试模式。从钩子函数MyMmAccessFault()返回,继续执行MmAccessFault()函数,Windows操作系统处理完异常后,被调试软件S0继续执行。
S5、这时由于Windows操作系统开启了单步调试模式,被调试软件S0执行触发调试陷阱异常并执行到Windows操作系统内核的KiTrap01()函数的入口时,进入钩子函数MyKiTrap01()。
S6、在钩子函数MyKiTrap01()中,通过NtProtectVirtualMemory()函数设置a0所在的内存页的属性为PAGE_NOACCESS(不可访问),恢复断点设置,并将标志寄存器的TF标志位置为0,关闭单步调试模式。最后从钩子函数MyKiTrap01()返回,继续执行KiTrap01()函数,Windows操作系统处理完异常后,被调试软件S0继续执行,结束。
如图1所示,本发明实施例2:某Windows软件调试过程中设置若干断点并未触发断点的过程,包括:
S1、使用人员通过调试器D0对被调试软件S0设置若干断点,其内存地址值用集合P0={p1=0x00081234,p2=0x0009445a,p3=0x000a258e}表示,调试器将集合P0的各个元素所在的内存页的属性通过NtProtectVirtualMemory()函数设置为PAGE_NOACCESS(不可访问)。
S2、运行被调试软件S0,S0执行触发Windows页面错误异常并执行到Windows操作系统内核的MmAccessFault()函数的入口时,进入钩子函数MyMmAccessFault()。
S3、在钩子函数MyMmAccessFault()中,通过寄存器EDI获得引发内存页错误的内存地址值a0=0x00094451,然后与集合P0的各个元素进行比较,发现未触发任何断点。
S4、计算a0所在的内存页首地址值为b0=0x00094000和集合P0的各元素所在的内存页首地址值的集合P0′={p1′=0x00081000,p2′=0x00094000,p3′=0x000a2000},然后将b0与集合P0′的各个元素进行比较,发现存在b1=p2′。
S5、通过NtProtectVirtualMemory()函数设置a0所在的内存页的属性为PAGE_READWRITE和PAGE_EXECUTE(可读可写可执行),并将标志寄存器的TF标志位置为1,开启单步调试模式。从钩子函数MyMmAccessFault()返回,继续执行MmAccessFault()函数,Windows操作系统处理完异常后,被调试软件S0继续执行。
S6、这时由于Windows操作系统开启了单步调试模式,被调试软件S0执行触发调试陷阱异常并执行到Windows操作系统内核的KiTrap01()函数的入口时,进入钩子函数MyKiTrap01()。
S7、在钩子函数MyKiTrap01()中,通过NtProtectVirtualMemory()函数设置a0所在的内存页的属性为PAGE_NOACCESS(不可访问),恢复断点设置,并将标志寄存器的TF标志位置为0,关闭单步调试模式。最后从钩子函数MyKiTrap01()返回,继续执行KiTrap01()函数,Windows操作系统处理完异常后,被调试软件S0继续执行,结束。
虽然结合附图描述了本发明的实施方式,但是本领域技术人员可以在不脱离本发明的精神和范围的情况下做出各种修改和变型,这样的修改和变型均落入由所附权利要求所限定的范围之内。
Claims (6)
1.一种基于Windows操作系统的软件无限断点设置方法,其特征在于包括步骤如下:
(1)在Windows操作系统下,通过调试器D对被调试软件S设置若干断点,若干断点内存地址值的集合为P={p1p2,…,pn},调试器将集合P的各个元素所在的内存页的属性通过NtProtectVirtualMemory()函数改为不可访问PAGE_NOACCESS,转入步骤(2),其中,pi为第i个断点对应的内存地址值,pi、pj对应的内存页可以相同;
(2)运行被调试软件S,当被调试软件S执行过程触发Windows页面错误异常并执行到Windows操作系统内核的MmAccessFault()函数的入口且未开始执行MmAccessFault()函数时,执行钩子函数FuncA,转入步骤(3);
(3)在钩子函数FuncA中,通过寄存器EDI获得引发Windows页面错误异常对应的内存地址值a1,然后与集合P的各个元素进行比较,如果存在a1=pi,pi∈P,则成功触发断点pi,通知调试器D,转入步骤(4);否则,未触发断点,转入步骤(7);
(4)通过NtProtectVirtualMemory()函数设置a1所在的内存页的属性为PAGE_READWRITE和PAGE_EXECUTE,使得该内存页的属性为可读可写可执行,并将标志寄存器的TF标志位置为1,开启单步调试模式,结束钩子函数FuncA执行,然后继续执行MmAccessFault()函数,Windows操作系统处理完异常后,被调试软件S继续执行,转入步骤(5);
(5)当被调试软件S在执行过程中,触发调试陷阱异常并执行到Windows操作系统内核的KiTrap01()函数的入口且未执行KiTrap01()函数时,执行钩子函数FuncB,转入步骤(6);
(6)在钩子函数FuncB中,通过NtProtectVirtualMemory()函数设置a1所在的内存页的属性为不可访问PAGE_NOACCESS,进而恢复断点设置,并将标志寄存器的TF标志位置为0,关闭单步调试模式,结束钩子函数FuncB执行,继续执行KiTrap01()函数,Windows操作系统处理完异常后,转入步骤(9);
(7)计算步骤(3)中a1所在的内存页首地址值元素b1和步骤(1)中集合P的各元素所在的内存页首地址值的集合P′={p′1,p′2,...,p′n},然后将b1与集合P′的各个元素进行比较,如果存在b1=p′i,p′i∈P′,转入步骤(4);否则,转入步骤(8);
(8)结束钩子函数FuncA执行,继续执行MmAccessFault()函数,Windows操作系统处理完异常后,转入步骤(9)。
(9)被调试软件S继续执行,步骤结束。
2.根据权利要求1所述的一种基于Windows操作系统的软件无限断点设置方法,其特征在于:所述的Windows操作系统的版本为Windows xp、Windows 7(32位)。
3.根据权利要求1或2所述的一种基于Windows操作系统的软件无限断点设置方法,其特征在于:所述的钩子函数FuncB为:
通过NtProtectVirtualMemory()函数设置a1所在的内存页的属性为不可访问PAGE_NOACCESS,进而恢复断点设置,并将标志寄存器的TF标志位置为0,关闭单步调试模式。
4.根据权利要求1或2所述的一种基于Windows操作系统的软件无限断点设置方法,其特征在于:所述的钩子函数FuncA包括:
步骤(3)、步骤(7)、步骤(4)中的通过NtProtectVirtualMemory()函数设置a1所在的内存页的属性为PAGE_READWRITE和PAGE_EXECUTE,使得该内存页的属性为可读可写可执行,并将标志寄存器的TF标志位置为1,开启单步调试模式。
5.一种计算机可读存储介质,所述的计算机可读存储介质存储有计算机程序,其特征在于,所述的计算机程序被处理器执行时实现如权利要求1‐权利要求4任一所述方法的步骤。
6.一种基于Windows操作系统的软件无限断点设置终端设备,包括存储器、处理器以及存储在所述存储器中并可在所述处理器上运行的计算机程序,其特征在于:所述的处理器执行所述的计算机程序时实现如权利要求1‐权利要求4任一所述方法的步骤。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201811289072.7A CN109471800B (zh) | 2018-10-31 | 2018-10-31 | 一种基于Windows操作系统的软件无限断点设置方法 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201811289072.7A CN109471800B (zh) | 2018-10-31 | 2018-10-31 | 一种基于Windows操作系统的软件无限断点设置方法 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN109471800A true CN109471800A (zh) | 2019-03-15 |
CN109471800B CN109471800B (zh) | 2021-09-07 |
Family
ID=65666483
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN201811289072.7A Active CN109471800B (zh) | 2018-10-31 | 2018-10-31 | 一种基于Windows操作系统的软件无限断点设置方法 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN109471800B (zh) |
Cited By (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN110889112A (zh) * | 2019-10-23 | 2020-03-17 | 中国航天系统科学与工程研究院 | 一种基于白名单机制的软件运行统一控制系统及方法 |
CN111177619A (zh) * | 2019-12-19 | 2020-05-19 | 山石网科通信技术股份有限公司 | 网页识别方法、装置、存储介质和处理器 |
CN112231198A (zh) * | 2019-07-15 | 2021-01-15 | 腾讯科技(深圳)有限公司 | 一种恶意进程调试方法、装置、电子设备及介质 |
CN112395609A (zh) * | 2019-08-15 | 2021-02-23 | 奇安信安全技术(珠海)有限公司 | 应用层shellcode的检测方法及装置 |
Citations (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US5680620A (en) * | 1995-06-30 | 1997-10-21 | Dell Usa, L.P. | System and method for detecting access to a peripheral device using a debug register |
US7231476B2 (en) * | 2002-11-18 | 2007-06-12 | Arm Limited | Function control for a processor |
CN101364253A (zh) * | 2007-08-06 | 2009-02-11 | 电子科技大学 | 反恶意程序隐蔽调试引擎与方法 |
CN101504626A (zh) * | 2009-03-06 | 2009-08-12 | 中兴通讯股份有限公司 | 一种调试控制实现方法及系统 |
-
2018
- 2018-10-31 CN CN201811289072.7A patent/CN109471800B/zh active Active
Patent Citations (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US5680620A (en) * | 1995-06-30 | 1997-10-21 | Dell Usa, L.P. | System and method for detecting access to a peripheral device using a debug register |
US7231476B2 (en) * | 2002-11-18 | 2007-06-12 | Arm Limited | Function control for a processor |
CN101364253A (zh) * | 2007-08-06 | 2009-02-11 | 电子科技大学 | 反恶意程序隐蔽调试引擎与方法 |
CN101504626A (zh) * | 2009-03-06 | 2009-08-12 | 中兴通讯股份有限公司 | 一种调试控制实现方法及系统 |
Cited By (7)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN112231198A (zh) * | 2019-07-15 | 2021-01-15 | 腾讯科技(深圳)有限公司 | 一种恶意进程调试方法、装置、电子设备及介质 |
CN112231198B (zh) * | 2019-07-15 | 2024-04-12 | 腾讯科技(深圳)有限公司 | 一种恶意进程调试方法、装置、电子设备及介质 |
CN112395609A (zh) * | 2019-08-15 | 2021-02-23 | 奇安信安全技术(珠海)有限公司 | 应用层shellcode的检测方法及装置 |
CN110889112A (zh) * | 2019-10-23 | 2020-03-17 | 中国航天系统科学与工程研究院 | 一种基于白名单机制的软件运行统一控制系统及方法 |
CN110889112B (zh) * | 2019-10-23 | 2022-03-04 | 中国航天系统科学与工程研究院 | 一种基于白名单机制的软件运行统一控制系统及方法 |
CN111177619A (zh) * | 2019-12-19 | 2020-05-19 | 山石网科通信技术股份有限公司 | 网页识别方法、装置、存储介质和处理器 |
CN111177619B (zh) * | 2019-12-19 | 2022-09-09 | 山石网科通信技术股份有限公司 | 网页识别方法、装置、存储介质和处理器 |
Also Published As
Publication number | Publication date |
---|---|
CN109471800B (zh) | 2021-09-07 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
CN109471800A (zh) | 一种基于Windows操作系统的软件无限断点设置方法 | |
WO2021057057A1 (zh) | 操作系统级程序的目标码覆盖率测试方法、系统及介质 | |
CN105723348B (zh) | 使用事务性存储器检测未授权存储器修改及访问 | |
JP5430570B2 (ja) | システムコールカバレッジ基準による試験スイート削減のための方法 | |
KR101519845B1 (ko) | 안티디버깅 방법 | |
TWI544410B (zh) | 利用執行單步驟以進行編碼診斷 | |
US20070079288A1 (en) | System and method for capturing filtered execution history of executable program code | |
EP2668578A1 (en) | Controlling generation of debug exceptions | |
US20110161956A1 (en) | Heap dump object identification in a heap dump analysis tool | |
CN104077220A (zh) | Mips架构操作系统内核的调试方法和装置 | |
EP3918500B1 (en) | Machine learning-based anomaly detections for embedded software applications | |
WO2015035810A1 (zh) | 一种数据断点监控方法、装置及调试器 | |
CN104679645A (zh) | 一种栈空间余量实时检测方法 | |
US9176821B2 (en) | Watchpoint support system for functional simulator | |
CN105740112A (zh) | 一种Linux下的开机自动检测硬件信息的方法 | |
CN110955598A (zh) | 一种内核态程序的断点处理方法及装置 | |
TWI515597B (zh) | 安全保護方法和處理器 | |
CN101364253A (zh) | 反恶意程序隐蔽调试引擎与方法 | |
CN105095079B (zh) | 一种热点模块指令跟踪的方法及设备 | |
US7657792B2 (en) | Identifying race conditions involving asynchronous memory updates | |
EP1967950A2 (en) | Multiprocessor system for continuing program execution upon detection of abnormality | |
CN105787371A (zh) | 一种计算机进程监控方法和系统 | |
CN114510429B (zh) | 一种基于动态符号执行的调试方法、系统和介质 | |
CN111931191A (zh) | Linux平台二进制软件堆溢漏洞动态检测方法及系统 | |
CN107844703B (zh) | 一种基于Android平台Unity3D游戏的客户端安全检测方法及装置 |
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 |