Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
razer-lycosa-kernel-lpe-BYOVD-Vulnerability-PoC — Two kernel vulnerabilities in Razer Lycosa.sys (CWE-125 memory disclosure + CWE-121 stack overflow) chained to local privilege escalation. Coordinated-disclosure materials, verified on Windows 11. | Kitploit
Tools/GitHubGitHub/416rehman/razer-lycosa-kernel-lpe-byovd-vulnerability-poc
Privilege EscalationVulnerability AnalysisExploitationReverse EngineeringBinary Exploitation
GitHub416rehman/razer-lycosa-kernel-lpe-byovd-vulnerability-poc

razer-lycosa-kernel-lpe-BYOVD-Vulnerability-PoC

Two kernel vulnerabilities in Razer Lycosa.sys (CWE-125 memory disclosure + CWE-121 stack overflow) chained to local privilege escalation. Coordinated-disclosure materials, verified on Windows 11.

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
View RepositoryWebsite
11158 days agoNot yet reviewed

Lycosa.sys, Razer: two kernel vulnerabilities reachable by any local user

Discovered through https://github.com/416rehman/DeepZero

Vendor: Razer Inc. Component: Lycosa.sys, the Razer Lycosa keyboard filter driver, x64 SHA-256: a120a6184ab16864e8a5f1dfd0cd178fca541de463b5cef946e18c34b9b6f716 Reporter reference: a120a6184ab16864 Status: not yet reported to the vendor.

This directory reports two distinct defects in the same routine of the same driver. They have separate root causes and separate fixes, so each has its own self-contained folder and can be tracked and assigned its own identifier:

CVEDefectTypeOutcome
CVE-01Output length is not checked against the buffer, so the driver returns kernel stack memoryCWE-125 out-of-bounds readKernel memory disclosure, defeats address space layout randomisation
CVE-02Input length is not checked against the buffer, so the driver overwrites its own return addressCWE-121 stack buffer overflowArbitrary kernel code execution

Both are reachable from any account that can log in and run a program. No administrative rights, no elevation, no special privilege. Both were confirmed on Windows 11 25H2 (build 26200.8875) with code integrity enforced and test signing off.

Section 3 describes what the two amount to when used together, which is the reason they are reported at the same time and why the chained proof of concept lives in this root directory.


1. Where the defects are

Both live in the IRP_MJ_DEVICE_CONTROL handler at RVA 0x1270, and both act on the same 0x400-byte buffer on the kernel stack. The prologue, read from the shipped binary, fixes the geometry for both:

root@kitploit:~
Lycosa+0x1270  48 89 54 24 10           mov   [rsp+10h], rdx   ; Irp
Lycosa+0x1275  48 89 4c 24 08           mov   [rsp+8], rcx     ; DeviceObject
Lycosa+0x127a  48 81 ec 98 04 00 00     sub   rsp, 498h        ; the frame
Lycosa+0x1291  ba 00 04 00 00           mov   edx, 400h        ; the buffer size
Lycosa+0x1296  48 8d 8c 24 80 00 00 00  lea   rcx, [rsp+80h]   ; the buffer

A 0x400-byte buffer at rsp+0x80, inside a 0x498-byte frame, with no non-volatile registers saved. Counting from the start of the buffer:

root@kitploit:~
0x000 .. 0x3FF   the buffer, which both defects are supposed to stay inside
0x418            the return address of the dispatch routine
0x420            the saved DeviceObject argument
0x428            the saved Irp argument

0x418 is 0x498 - 0x80. The disclosure (CVE-01) reads past 0x3FF and hands back what it finds; the overflow (CVE-02) writes past 0x3FF and replaces it.

2. Reachability, and who can do this

DriverEntry creates the device with no security descriptor and publishes a symbolic link for it, so it is reachable at \\.\Lycosa:

root@kitploit:~
IoCreateDevice(param_1, 0x20, L"\\Device\\Lycosa", 0x22, 0, 0, &device);
IoCreateSymbolicLink(L"\\DosDevices\\Lycosa", L"\\Device\\Lycosa");

Every affected control code decodes as FILE_DEVICE_UNKNOWN, METHOD_BUFFERED, FILE_ANY_ACCESS. FILE_ANY_ACCESS means no particular access right must be held on the handle, so the device object's security descriptor is the only gate, and it grants access to everyone.

All results in these reports were produced from a standard user account whose only group membership is the built-in Users group. The account had no administrative rights, was not elevated, and held no privileges beyond the defaults.

The driver also loads on machines that have never had Razer hardware attached, because the package is validly catalog-signed. That is the pattern used in bring-your-own-vulnerable-driver attacks.

3. The two defects combine

Reported separately because they are separate defects, but a vendor triaging them should know that each makes the other worse.

Modern Windows loads the kernel at a randomised address. An attacker who can overwrite a return address still has to know what to overwrite it with, and that is normally the obstacle. This driver answers both questions on its own:

  1. CVE-01 removes the randomisation. The disclosure returns the dispatch routine's own return address, a code address inside ntoskrnl.exe. Subtracting its known offset within the image gives the base at which the kernel is loaded, and from there every address inside the kernel is known. This costs nothing and disturbs nothing.

  2. CVE-01 also supplies the value CVE-02 needs in order not to fault. As described in CVE-02 section 4.4, the driver reloads the Irp from offset 0x428 on its way out and writes through it. A naive overflow that reaches the return address also destroys that pointer and faults before the routine returns. The reliable exploit instead stops the copy exactly at 0x428, leaving the live Irp of the current request in place, so the driver completes normally.

  3. CVE-02 then redirects execution, with the kernel base already known.

From an unprivileged account, the chained proof of concept reads the frame, calculates the kernel base and the buffer's own kernel address, and sends a return-oriented chain:

root@kitploit:~
step 1, read what is above the buffer on the kernel stack:
   +0x418 return address  0xFFFFF807D565CABB
   +0x498 frame pointer   0xFFFFFD042D313750  (read twice, must match)

step 2, turn those into the two addresses the payload needs:
   kernel base     = 0xFFFFF807D565CABB - 0x25CABB = 0xFFFFF807D5400000
   buffer on stack = 0xFFFFFD042D313750 - 0x500    = 0xFFFFFD042D313250

step 4, overflow with a chain that:
   pivots the stack onto the buffer, calls nt!ZwCreateFile, and
   resumes nt!IopfCallDriver+0x5b

sending 0x428 bytes
call returned: accepted=true error=0

PROOF: C:\Windows\System32\dz_lycosa_kernel_exec.txt now exists.

This is the complete chain, verified end to end. The unprivileged account created a file under C:\Windows\System32, a directory it is otherwise refused write access to, by executing nt!ZwCreateFile in kernel mode. accepted=true means the system call returned normally: the chain resumes the exact address the driver was going to return to (nt!IopfCallDriver+0x5b, which is add rsp,0x38 ; ret), so the thread finishes and the machine keeps running. The created file was confirmed independently from an administrator shell. The full transcript is in logs/exec_create_file.log, and the method is in METHODOLOGY.md.

The practical reading is that this one driver provides, to any user of the machine, both halves of what is normally needed to turn a memory-safety defect into kernel code execution: the address disclosure that removes randomisation, and the control-flow hijack that uses it. Together they were shown to yield a concrete privileged action with the machine left running.

4. Fixing them

The two fixes are independent and both small, stated in full in each report:

  • CVE-01 remediation: bound OutputBufferLength, and set IoStatus.Information to what was actually produced.
  • CVE-02 remediation: bound InputBufferLength.

Both reports also recommend creating the control device with IoCreateDeviceSecure and an SDDL string restricting it to administrators and the system. That alone would not fix either defect, but it would remove the unprivileged reach that gives both their severity.

5. Prior art

Checked before writing up, because a duplicate report wastes a vendor's time:

  • LOLDrivers, 660 entries, searched by SHA-256, by MD5 and by file name. No entry for this driver.
  • Microsoft vulnerable driver blocklist, downloaded from https://aka.ms/VulnerableDriverBlockList and searched across its 1,713 deny rules. This file does not appear. The only Razer driver on that list is Rzpnk.sys, a different component.
  • No CVE was found describing this driver.

We believe both defects are previously unreported and would welcome correction.

Several other drivers shipped in the same package directory share this driver's overall shape and are examined separately. Nothing here is a statement about them.

6. Reproducing

root@kitploit:~
pnputil /add-driver Flter2K.inf /install
sc create lycosa_test type= kernel binPath= C:\path\to\Lycosa.sys start= demand
sc start lycosa_test

Each defect has its own single-purpose proof of concept in its folder, and this root holds the chained one that combines them:

root@kitploit:~
# CVE-01, reads only, safe to run anywhere, quickest confirmation of the report
rustc -O CVE-01-kernel-memory-disclosure/poc/lycosa_disclosure.rs -o disc.exe
disc.exe

# CVE-02, stops the machine by design
rustc -O CVE-02-kernel-stack-overflow/poc/lycosa_overflow.rs -o ovf.exe
ovf.exe --yes-crash-this-machine

# the chain: CVE-01 + CVE-02 into a file created in System32, machine left running
rustc -O poc/lycosa_chain.rs -o chain.exe
chain.exe --exec                              # default target under System32
chain.exe --exec C:\Users\Public\proof.txt    # or any path you choose

Run everything from a standard user account. The chained PoC states the two driver constants it depends on (FRAME and BUF_AT) at the top of its source, so it can be pointed at a different driver build by changing those two numbers. The kernel offsets its --exec mode uses are specific to one Windows build; the program checks the derived kernel base at run time and its --calibrate mode reports the one value that changes between builds.

7. Contents of this directory

root@kitploit:~
README.md                              this overview and the chaining analysis
METHODOLOGY.md                         how both were found and confirmed, in order
poc/lycosa_chain.rs                    the CHAINED proof of concept (both defects)
evidence/                              the binary, its package, decompiled sources, dumps
logs/exec_create_file.log              transcript of the chained run in section 3

CVE-01-kernel-memory-disclosure/       standalone disclosure for the out-of-bounds read
  README.md, poc/lycosa_disclosure.rs, evidence/, logs/
CVE-02-kernel-stack-overflow/          standalone disclosure for the stack overflow
  README.md, poc/lycosa_overflow.rs, evidence/, logs/
Download Tool