{
	"id": "e8b75f51-1622-4437-90c9-58b7d6690390",
	"created_at": "2026-04-06T01:31:33.296522Z",
	"updated_at": "2026-04-10T13:11:45.456933Z",
	"deleted_at": null,
	"sha1_hash": "0511afe5dd337266562c75e40c6c05cfb79399e0",
	"title": "Windows kernel zero-day exploit (CVE-2021-1732) is used by BITTER APT in targeted attack -    安恒威胁情报中心",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 2094528,
	"plain_text": "Windows kernel zero-day exploit (CVE-2021-1732) is used by\r\nBITTER APT in targeted attack -    安恒威胁情报中心\r\nBy 猎影实验室\r\nPublished: 2021-02-10 · Archived: 2026-04-06 00:34:28 UTC\r\nBackground\r\nIn December 2020, DBAPPSecurity Threat Intelligence Center found a new component of BITTER APT. Further\r\nanalysis into this component led us to uncover a zero-day vulnerability in win32kfull.sys. The origin in-the-wild\r\nsample was designed to target newest Windows10 1909 64-bits operating system at that time. The vulnerability\r\nalso affects and could be exploited on the latest Windows10 20H2 64-bits operating system. We reported this\r\nvulnerability to MSRC, and it is fixed as CVE-2021-1732 in the February 2021 Security Update.\r\nSo far, we have detected a very limited number of attacks using this vulnerability. The victims are located in\r\nChina.\r\nTimeline\r\n· 2020/12/10: DBAPPSecurity Threat Intelligence Center caught a new component of BITTER APT.\r\n· 2020/12/15: DBAPPSecurity Threat Intelligence Center uncovered an unknown windows kernel\r\nvulnerability in the component and started the root cause analysis.\r\n· 2020/12/29: DBAPPSecurity Threat Intelligence Center reported the vulnerability to MSRC.\r\n· 2020/12/29: MSRC confirmed the report has been received and opened a case for it.\r\n· 2020/12/31: MSRC confirmed the vulnerability is a zero-day and asked for more information.\r\n· 2020/12/31: DBAPPSecurity provided more detail to MSRC.\r\n· 2021/01/06: MSRC thanked for the addition information and started working for a fix for the\r\nvulnerability.\r\n· 2021/02/09: MSRC fixes the vulnerability as CVE-2021-1732.\r\nHighlights\r\nAccording to our analysis, the in-the-wild zero-day has the following highlights:\r\n1. 1. It targets the latest version of Windows10 operating system\r\n1. 1.1. The in-the-wild sample targets the latest version of Windows10 1909 64-bits operating system\r\n(The sample was compiled in May 2020).\r\n2. 1.2. The origin exploit aims to target several Windows 10 versions, from Windows10 1709 to\r\nWindows10 1909.\r\n3. 1.3. The origin exploit could be exploited on Windows10 20H2 with minor modifications.\r\n2. 2. The vulnerability is high quality and the exploit is sophisticated\r\nhttps://ti.dbappsecurity.com.cn/blog/articles/2021/02/10/windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack/\r\nPage 1 of 15\n\n1. 2.1. The origin exploit bypasses KASLR with the help of the vulnerability feature.\r\n2. 2.2. This is not a UAF vulnerability. The whole exploit process is not involved heap spray or\r\nmemory reuse. The Type Isolation mitigation can’t mitigate this exploit. It is unable to detect it by\r\nDriver Verifier, the in-the-wild sample can exploit successfully when Driver Verifier is turned on.\r\nIt’s hard to hunt the in-the-wild sample through sandbox.\r\n3. 2.3. The arbitrary read primitive is achieved by vulnerability feature in conjunction with\r\nGetMenuBarInfo, which is impressive.\r\n4. 2.4. After achieving arbitrary read/write primitives, the exploit uses Data Only Attack to perform\r\nprivilege escalation, which can’t be mitigated by current kernel mitigations.\r\n5. 2.5. The success rate of the exploit is almost 100%.\r\n6. 2.6. When finishing exploit, the exploit will restore all key struct members, there will be no BSOD\r\nafter exploit.\r\n3. 3. The attacker used it with caution\r\n1. 3.1. Before exploit, the in-the-wild sample detects specific antivirus software.\r\n2. 3.2. The in-the-wild sample performs operating system build version check, if current build version\r\nis under than 16535(Windows10 1709), the exploit will never be called.\r\n3. 3.3. The in-the-wild sample was compiled in May 2020, and caught by us in December 2020, it\r\nsurvived at least 7 months. This indirectly reflects the difficulty of capturing such stealthy sample.\r\nTechnical Analysis\r\n0x00 Trigger Effect\r\nIf we run the in-the-wild sample in the lasted windows10 1909 64-bits environment, we could observe current\r\nprocess initially runs under Medium Integrity Level.\r\nhttps://ti.dbappsecurity.com.cn/blog/articles/2021/02/10/windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack/\r\nPage 2 of 15\n\nAfter the exploit code executing, we could observe current process runs under System Integrity Level. This\r\nindicates that the Token of the current process has been replaced with the Token of System process, which is a\r\ncommon method of exploiting kernel privilege escalation vulnerabilities.\r\nhttps://ti.dbappsecurity.com.cn/blog/articles/2021/02/10/windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack/\r\nPage 3 of 15\n\nIf we run the in-the-wild sample in the lasted windows10 20H2 64-bits environment, we could observe BSOD\r\nimmediately.\r\n0x01 Overview Of The Vulnerability\r\nThis vulnerability is caused by xxxClientAllocWindowClassExtraBytes callback in\r\nwin32kfull!xxxCreateWindowEx. The callback causes the setting of a kernel struct member and its corresponding\r\nflag to be out of sync.\r\nWhen xxxCreateWindowEx creating a window that has WndExtra area, it will call\r\nxxxClientAllocWindowClassExtraBytes to trigger a callback, the callback will return to user mode to allocate\r\nWndExtra area. In the custom callback function, the attacker could call NtUserConsoleControl and pass in the\r\nhandle of current window, this will change a kernel struct member (which points to the WndExtra area) to offset,\r\nand setting a corresponding flag to indicate that the member now is an offset. After that, the attacker could call\r\nNtCallbackReturn in the callback and return an arbitrary value. When the callback ends and return to kernel mode,\r\nthe return value will overwrite the previous offset member, but the corresponding flag is not cleared. After that,\r\nthe unchecked offset value is directly used by kernel code for heap memory addressing, causing out-of-bounds\r\naccess.\r\n0x02 Root Cause\r\nWe completely reversed the exploit code of the in-the-wild sample, and constructed a poc base it. The following\r\nfigure is the main execution logic of our poc, we will explain the vulnerability trigger logic in conjunction with\r\nthis figure.\r\nhttps://ti.dbappsecurity.com.cn/blog/articles/2021/02/10/windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack/\r\nPage 4 of 15\n\nIn win32kfull!xxxCreateWindowEx, it will call user32!_xxxClientAllocWindowClassExtraBytes callback\r\nfunction to allocate the memory of WndExtra by default. The return value of the callback is a use mode pointer\r\nwhich will then been saved to a kernel struct member (the WndExtra member).\r\nIf we call win32kfull!xxxConsoleControl in a custom _xxxClientAllocWindowClassExtraBytes callback and pass\r\nin the handle of current window, the WndExtra member will be change to an offset, and a corresponding flag will\r\nbe set (|=0x800).\r\nhttps://ti.dbappsecurity.com.cn/blog/articles/2021/02/10/windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack/\r\nPage 5 of 15\n\nThe poc triggers an BSOD when calling DestoryWindow, win32kfull!xxxFreeWindow will check the flag above,\r\nif it has been set, indicating the WndExtra member is an offset, xxxFreeWindow will call RtlFreeHeap to free the\r\nWndExtra area; if not, indicating the WndExtra member is an use mode pointer, xxxFreeWindow will call\r\nxxxClientFreeWindowClassExtraBytes to free the WndExtra area.\r\nhttps://ti.dbappsecurity.com.cn/blog/articles/2021/02/10/windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack/\r\nPage 6 of 15\n\nWe could call NtCallbackReturn in the end of custom _xxxClientAllocWindowClassExtraBytes callback and\r\nreturn an arbitrary value. When the callback finishes and return to kernel mode, the return value will overwrite the\r\noffset member, but the corresponding flag is not cleared.\r\nIn the poc, we return an user mode heap address, the address overwrites the origin offset to an user mode heap\r\naddress(fake_offset). This finally causes win32kfull!xxxFreeWindow to trigger an out-of-bound access when\r\nusing RtlFreeHeap to release a kernel heap.\r\nWhat RtlFreeHeap expects to free is RtlHeapBase+offset\r\nWhat RtlFreeHeap actually free is RtlHeapBase+fake_offset\r\nhttps://ti.dbappsecurity.com.cn/blog/articles/2021/02/10/windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack/\r\nPage 7 of 15\n\nIf we call the RtlFreeHeap here, it will trigger a BSOD.\r\n0x03 Exploit\r\nThe in-the-wild sample is a 64-bits program, it first calls CreateToolhelp32Snapshot and some other functions to\r\nenumerate process to detect “avp.exe” (avp.exe is a process of Kaspersky Antivirus Software).\r\nhttps://ti.dbappsecurity.com.cn/blog/articles/2021/02/10/windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack/\r\nPage 8 of 15\n\nHowever, when detecting the “avp.exe” process, it will only save some value to custom struct and will not exit\r\nprocess, the full exploit function will still be called. We install the Kaspersky antivirus product and run the\r\nsample; it will obtain system privileges as usual.\r\nIt then calls IsWow64Process to check whether the current environment is 32-bits or 64-bits, and fix some offsets\r\nbased on the result. Here the code developer seems make a mistake, according to the source code below, g_x64\r\nshould be understood as g_x86, but subsequent calls indicate that this variable represents the 64-bits environment.\r\nHowever, the code developer forces g_x64 to TRUE at initialization, the call to IsWow64Process actually can be\r\nignored here. But this seems to imply that the developer had also developed another 32-bits version exploit.\r\nhttps://ti.dbappsecurity.com.cn/blog/articles/2021/02/10/windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack/\r\nPage 9 of 15\n\nAfter fixing some offsets, it obtains the address of RtlGetNtVersionNumbers, NtUserConsoleControl and\r\nNtCallbackReturn. Then it calls RtlGetNtVersionNumbers to get the build number of current operating system, the\r\nexploit function will only be called when the build number is larger than 16535(Windows10 1709), and if the\r\nbuild number larger than 18204(Windows10 1903), it will fix some kernel struct offset. This seems to imply that\r\nsupport for these versions was added later.\r\nIf the current environment passes the check, the exploit will be called by the in the wild sample. The exploit first\r\nsearches bytes to get the address of HmValidateHandle, and hooks\r\nUSER32!_xxxClientAllocWindowClassExtraBytes to a custom callback function.\r\nhttps://ti.dbappsecurity.com.cn/blog/articles/2021/02/10/windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack/\r\nPage 10 of 15\n\nThe exploit then registers two type of windows class. The name of one class is “magicClass”, which is used to\r\ncreate the vulnerability window. The name of another class is “nolmalClass”, which is used to create normal\r\nwindows which will assist the arbitrary address write primitive later.\r\nThe exploit creates 10 windows using normalClass, and call HmValidateHandle to leak the user mode tagWND\r\naddress of each window and an offset of each window through the tagWND address. Then the exploit destroys the\r\nlast 8 windows, only keep the window 0 and window 1.\r\nIf current program is 64-bits, the exploit will call NtUserConsoleControl and pass the handle of windows 1, this\r\nwill change the WndExtra member of window 0 to an offset. The exploit then leaks the kernel tagWND offset of\r\nwindows 0 for later use.\r\nThen the exploit uses magicClass to create another window (windows 2), windows 2 has a certain cbWndExtra\r\nvalue which was generated before. In the process of creating window 2, it will trigger the\r\nxxxClientAllocWindowClassExtraBytes callback, and enter the custom callback function.\r\nIn the custom callback function, the exploit first checks if the cbWndExtra of current window match a certain\r\nvalue, then checks if current process is 64-bits. If both checks pass, the exploit calls NtUserConsoleControl and\r\npasses the handle of windows 2, this changes the WndExtra of window 2 to an offset and set the corresponding\r\nflag. Then the exploit call NtCallbackReturn and pass the kernel tagWND offset of windows 0. When return to\r\nkernel mode, kernel WndExtra offset of windows 2 will been changed to the kernel tagWND offset of windows 0.\r\nThis causes the subsequent read/write on the WndExtra area of window 2 to the read/write on the kernel tagWND\r\nstructure of window 0.\r\nhttps://ti.dbappsecurity.com.cn/blog/articles/2021/02/10/windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack/\r\nPage 11 of 15\n\nAfter window 2 is created, the exploit obtains the primitive to write the kernel tagWND of window 0 by setting\r\nthe WndExtra area of window 2. The exploit makes a call to SetWindowLongW on window 2 to test if this\r\nprimitive works fine.\r\nIf all works fine, the exploit calls SetWindowLongW to set cbWndExtra of windows 0 to 0xfffffff, this gives\r\nwindow 0 the OOB read/write primitives. The exploit then using the OOB write primitive to modify the style of\r\nwindow 1(dwStyle|=WS_CHILD), after that, the exploit replaces the origin spmenu of window 1 with a fake\r\nspmenu.\r\nThe arbitrary read primitive is achieved by fake spmenu works with GetMenuBarInfo. The exploit reads a 64-bits\r\nvalue using tagMenuBarInfo.rcBar.left and tagMenuBarInfo.rcBar.top. This method has not been used publicly\r\nbefore, but is similar with the ideas in《LPE vulnerabilities exploitation on Windows 10 Anniversary Update》\r\n(ZeroNight, 2016)\r\nThe arbitrary write primitive is achieved via window 0 and window 1, work with SetWindowLongPtrA, see\r\nbelow.\r\nhttps://ti.dbappsecurity.com.cn/blog/articles/2021/02/10/windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack/\r\nPage 12 of 15\n\nAfter achieving the arbitrary read/write primitives, the exploit leaks a kernel address from the origin spmemu, then\r\nsearches through it to find the EPROCESS of current process.\r\nFinally, the exploit traversals ActiveProcessLinks to get the Token of SYSTEM EPROCESS and the Token area\r\naddress of current EPROCESS, and swaps the current process Token value with SYSTEM Token.\r\nAfter achieving privilege escalation, the exploit restores the modified area of window 0, window 1 and window 2\r\nusing arbitrary write primitive, such as the origin spmenu of window 1 and the flag of window 2, to ensure that it\r\nwill not cause a BSOD. The entire exploit process is very stable.\r\n0x04 Conclusion\r\nThis zero-day is a new vulnerability which caused by win32k callback, it could be used to escape the sandbox of\r\nMicrosoft IE browser or Adobe Reader on the lasted Windows 10 version. The quality of this vulnerability high\r\nand the exploit is sophisticated. The use of this in-the-wild zero-day reflects the organization’s strong vulnerability\r\nreserve capability. The threat organization may have recruited members with certain strength, or buying it from\r\nvulnerability brokers.\r\nSummary\r\nZero-day plays a pivotal role in cyberspace. It is usually used as a strategic reserve for threat organizations and has\r\na special mission and strategic significance.With the iteration of software/hardware and the improvement of the\r\ndefense system, the cost of mining and exploiting software/hardware zero-day is getting higher and higher.\r\nOver the years, vendors over the world have investment a lot on detecting APT attacks. This makes the APT\r\norganization more cautious in the use of zero-day. In order to maximize its value, it will only be used for very few\r\nspecific targets. A little carelessness will shorten the life cycle of a zero-day. Meanwhile, some zero-days have\r\nbeen lurking for a long time before being exposed, the most remarkable example is the MS17-010 used by\r\nEternalBlue,\r\nhttps://ti.dbappsecurity.com.cn/blog/articles/2021/02/10/windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack/\r\nPage 13 of 15\n\nOver the last year (2020), dozens of 0Day/1Day attacks in the wild were disclosed globally, including three\r\nattacks which tracked by DBAPPSecurity Threat Intelligence Center. Based on the data we have, we predict there\r\nwill be more zero-day disclose on browser and privilege escalation in 2021.\r\nThe detection capability on zero-day is one of key aspect that requires continuous improvement in the APT\r\nconfrontation process. In addition to endpoint attacks, the attacks on boundary systems, critical equipment, and\r\ncentralized control systems are also worth noting. There are also several security incidents in these areas over the\r\npast years.\r\nBeing undiscovered does not mean that it does not exist, it may be more in a stealthy state. The discovery,\r\ndetection and defense of advanced threats attacks require constant iteration and strengthening during the game. It’s\r\nnecessary to think more about how to strengthen the defense capabilities in all points, lines and surfaces. Cyber\r\nsecurity has a long way to go, and we need to encourage each other.\r\nHow To Defend Against Such Attacks\r\nThe DBAPPSecurity APT Attack Early Warning Platform could find known/unknown threat. The platform can\r\nmonitor, capture and analyze the threats of malicious files or programs in real time, and can conduct powerful\r\nmonitoring of malicious samples such as Trojan horses associated with each stage of email delivery, vulnerability\r\nexploitation, installation/implantation and C2.\r\nAt the same time, the platform conducts in-depth analysis of network traffic based on two-way traffic analysis,\r\nintelligent machine learning, efficient sandbox dynamic analysis, rich signature libraries, comprehensive detection\r\nstrategies, and massive threat intelligence data. The detection capability completely covers the entire APT attack\r\nchain, effectively discovering APT attacks, unknown threats and network security incidents that users care about.\r\nYara Rule\r\nrule apt_bitter_win32k_0day {\r\n meta:\r\n author = \"dbappsecurity_lieying_lab\"\r\n data = \"01-01-2021\"\r\n strings:\r\n $s1 = \"NtUserConsoleControl\" ascii wide\r\n $s2 = \"NtCallbackReturn\" ascii wide\r\n $s3 = \"CreateWindowEx\" ascii wide\r\n $s4 = \"SetWindowLong\" ascii wide\r\n $a1 = {48 C1 E8 02 48 C1 E9 02 C7 04 8A}\r\n $a2 = {66 0F 1F 44 00 00 80 3C 01 E8 74 22 FF C2 48 FF C1}\r\n $a3 = {48 63 05 CC 69 05 00 8B 0D C2 69 05 00 48 C1 E0 20 48 03 C1}\r\n condition:\r\nhttps://ti.dbappsecurity.com.cn/blog/articles/2021/02/10/windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack/\r\nPage 14 of 15\n\nuint16(0) == 0x5a4d and all of ($s*) and 1 of ($a*)\r\n}\r\nSource: https://ti.dbappsecurity.com.cn/blog/articles/2021/02/10/windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack/\r\nhttps://ti.dbappsecurity.com.cn/blog/articles/2021/02/10/windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack/\r\nPage 15 of 15\n\n$s3 $s4 = \"CreateWindowEx\" = \"SetWindowLong\" ascii wide ascii wide  \n$a1 = {48 C1 E8 02 48 C1 E9 02 C7 04 8A} \n$a2 = {66 0F 1F 44 00 00 80 3C 01 E8 74 22 FF C2 48 FF C1}\n$a3 = {48 63 05 CC 69 05 00 8B 0D C2 69 05 00 48 C1 E0 20 48 03 C1}\ncondition:    \n   Page 14 of 15",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://ti.dbappsecurity.com.cn/blog/articles/2021/02/10/windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack/"
	],
	"report_names": [
		"windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack"
	],
	"threat_actors": [
		{
			"id": "655f7d0b-7ea6-4950-b272-969ab7c27a4b",
			"created_at": "2022-10-27T08:27:13.133291Z",
			"updated_at": "2026-04-10T02:00:05.315213Z",
			"deleted_at": null,
			"main_name": "BITTER",
			"aliases": [
				"T-APT-17"
			],
			"source_name": "MITRE:BITTER",
			"tools": [
				"ZxxZ"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "bf6cb670-bb69-473f-a220-97ac713fd081",
			"created_at": "2022-10-25T16:07:23.395205Z",
			"updated_at": "2026-04-10T02:00:04.578924Z",
			"deleted_at": null,
			"main_name": "Bitter",
			"aliases": [
				"G1002",
				"T-APT-17",
				"TA397"
			],
			"source_name": "ETDA:Bitter",
			"tools": [
				"Artra Downloader",
				"ArtraDownloader",
				"Bitter RAT",
				"BitterRAT",
				"Dracarys"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775439093,
	"ts_updated_at": 1775826705,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/0511afe5dd337266562c75e40c6c05cfb79399e0.pdf",
		"text": "https://archive.orkl.eu/0511afe5dd337266562c75e40c6c05cfb79399e0.txt",
		"img": "https://archive.orkl.eu/0511afe5dd337266562c75e40c6c05cfb79399e0.jpg"
	}
}