Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
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.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-89633 — PoC and exploit chain for CVE-2026-89633, a heap out-of-bounds write in the Linux cifs.ko SMB1 TRANS2 coalescing path, escalating to uid 0 via cred overwrite and PTE aliasing. | Kitploit
Tools/GitHubGitHub/woshigenm/cve-2026-89633
Android SecurityPrivilege EscalationMemory ForensicsVulnerability AnalysisExploitationPapers & ResearchBinary Exploitation
GitHubwoshigenm/cve-2026-89633

CVE-2026-89633

PoC and exploit chain for CVE-2026-89633, a heap out-of-bounds write in the Linux cifs.ko SMB1 TRANS2 coalescing path, escalating to uid 0 via cred overwrite and PTE aliasing.

View Repository
113 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-89633 — cifs SMB1 coalesce_t2 heap OOB write

English | 简体中文

Research PoC/EXP for a heap out-of-bounds write in the Linux cifs.ko SMB1 client. A malicious SMB1 server controls DataOffset in a TRANS2 secondary response, and coalesce_t2() copies the 8-byte secondary payload to &primary->Protocol + DataOffset + accumulated without any target-bounds check. The copy destination is wherever the server points it, relative to the response buffer (server->bigbuf).

This repository keeps two demonstrations with distinct roles; they are not substitutes:

  • POC — trigger the OOB write and observe it: a malicious SMB1 server plus a TCP proxy that patches DataOffset at runtime.
  • EXP 1 (minimal primitive) — the root-side reference chain that turns the write into a real credential overwrite: the target process's cred slab page is placed on a pipe-controlled physical page, then a 4-frame coalesce response zeroes uid/gid/suid/sgid/euid/egid/fsuid/fsgid. It is the most direct proof that the OOB write is controllable and can modify a cred, with the fewest dependencies.
  • EXP 2 (advanced primitive) — the shell-only PTE chain: the same OOB write installs a user-writable PTE, the alias maps the cred page and optionally selinux_state, and the clone becomes uid 0 with full caps without root-side observation. It is an extension of EXP 1, not a replacement.

Kernel-module loading is deliberately out of scope for this repository: the chain stops at uid 0 (and optionally selinux_state permissive) and does not install a module. Even without a loaded module, uid 0 + permissive is the complete LPE demonstration this repository claims.

EXP 2's costs remain explicit: a per-window lottery (~25–33%, ~97–99% over 12 attempts), a bare PTE that stays live until reboot, a dependency on shell-writable tracefs, and build-specific direct-map/call-site/SEL_PFN assumptions. EXP 1 remains the simplest primitive proof and the fallback when shell-writable tracefs is unavailable.

Status

ItemValue
CVECVE-2026-89633
ClassHeap out-of-bounds write (CWE-787)
Componentcifs.ko, SMB1 TRANS2 secondary coalescing
Upstream fix36d01415d881 ("smb: client: fix ... coalesce_t2", 6.12.113)
POCTrigger and OOB write verified (post-mount and during mount)
EXP 1 (minimal primitive)4-frame OOB cred write under root-side observation; uid 0 verified (post-mount and mount-time held response)
EXP 2 (advanced primitive)shell-only PTE chain; uid 2000 → uid 0 + full caps + Permissive verified (SEL_PFN/SEL_OFF); stops at a bare PTE, no module load
Requirementsan SMB1 mount to an attacker-controlled server (privileged gate); the reference gate uses su, and the shell-only placement needs shell-writable tracefs

Tested environment: an arm64 Android 16 vendor build, kernel 6.12.38 with cifs.ko built from the 6.12.23 KMI baseline, SELinux enforcing.

Test scope

  • Verified: the arm64 Android 16 build above (kernel 6.12.38, cifs.ko from the 6.12.23 KMI baseline) — the POC trigger/OOB write (both post-mount and during the mount itself, with no access to the mount point), the EXP 1 root-side reference chain (uid 0), the mount-time held-response variant (no statfs, no access to the mount point), the EXP 2 shell-only placement (tracefs only, no root-side observation), the full EXP 2 acceptance (uid 0 + all cap bits + Permissive with SEL_PFN/SEL_OFF), and the su-driven mount gate (only the mount runs as root; the placement runs as uid 2000) were tested there under SELinux enforcing.
  • Not verified: other 6.12.x builds, other Android versions/SoCs, stock AOSP GKI kernels, or non-arm64 platforms. The call-site link, struct offsets and direct-map constants are build-specific; re-verify them on a different kernel before expecting the EXP to work.

The bug

For an SMB1 TRANS2 response larger than MAX_CIFS_SMALL_BUFFER_SIZE - 4 (444 bytes) the client keeps the primary in server->bigbuf and stores it in mid->resp_buf. The following SMB_COM_TRANSACTION2_SECONDARY responses go through cifs_check_trans2() -> check2ndT2() -> coalesce_t2():

data_area_of_tgt = &primary->Protocol + primary->DataOffset + total_in_tgt;
memcpy(data_area_of_tgt, data_area_of_src, secondary->DataCount);

DataOffset is taken verbatim from the server response. The counter checks (total_in_tgt/byte_count overflow, source-buffer bounds) are present, but there is no check that data_area_of_tgt stays inside the response buffer. Each secondary frame lands 8 bytes further (the accumulated DataCount), so a multi-frame response gives an 8*N byte write at an attacker-chosen offset (16-bit) from the buffer base.

Trigger conditions:

  1. the client mounts an SMB1 share (vers=1.0) from a server the attacker controls;
  2. the client issues any TRANS2 request (the PoC uses QUERY_FS_INFORMATION via statfs);
  3. the server answers with a primary that has TotalDataCount > DataCount and is large enough for the bigbuf path, then one or more secondary frames with TotalDataCount > DataCount.

Repository layout

Makefile
src/poc/poc_smb1_trans2.py   malicious SMB1 server (QFS hook, runtime ctl)
src/poc/smb1_proxy.py        TCP proxy: patches DataOffset, repeats secondaries
src/exp/pipesearch.c         pipe placement/write driver (modes 3, 8, 9)
src/exp/shcred.c             shell-side drain + clone helper (uid 2000)
src/exp/shp4a2.c             trace-based drainer/observer/clone (modes 8/9)
src/exp/pte_fault.c          2 MiB fault + PTE alias writes
src/exp/bscan.c              bigbuf discovery by call site (no kprobes)
src/exp/kslide.c             KASLR slide from a raw call site
src/exp/smbd.c               device-side SMB1 server (held TRANS2)
src/exp/smbd_templates.h     SMB1 response templates for smbd
src/exp/pfn.c                linear-map VA to pfn
src/exp/kflags.c             /proc/kpageflags reader
scripts/setup_device.sh      trace instance + kprobes (root on device)
scripts/start_servers.sh     host: SMB1 server + proxy + mount helper
scripts/probe_round.sh       one probe round: bigbuf base + free target page
scripts/place.sh             placement: pipesearch mode 3 + shcred
scripts/write_cred.sh        4-frame coalesce write + /proc verification
scripts/mount_su.sh          generic su mount gate (target/decoy/abort/unmount)
scripts/chain_shell.sh       shell-only placement for an already-held TRANS2
scripts/gen_smb_templates.py regenerates smbd_templates.h from a capture
docs/analysis.md             vulnerability and chain analysis
docs/exp-protocol.md         shared-page and smbd ctl protocols

Build

make deps        # checks impacket
make helpers     # NDK cross-build of all C helpers
make push        # adb push to /data/local/tmp

NDK, API, ARCH, ADB, DEVICE_DIR are overridable.

POC — trigger and observe the OOB write

The trigger itself only needs the SMB1 mount and the running server/proxy. The kprobes and kflags are observation aids, not part of the trigger — install them when you want the dst/src/len evidence (and they are required by the EXP chain below, which needs the bigbuf base, the placement watch and the target cred address).

  1. Device (root, optional — observation only): install the probes.

    adb push scripts/setup_device.sh /data/local/tmp/
    adb shell su -c 'sh /data/local/tmp/setup_device.sh'
    adb push build/kflags /data/local/tmp/kflags
    
  2. Host: start the SMB1 server and the proxy (the script also creates the share directory and prints the mount command):

    scripts/start_servers.sh /tmp/cifs01-ctl
    

    It runs src/poc/poc_smb1_trans2.py on 1470 and src/poc/smb1_proxy.py (1460 -> 1470) with the control directory /tmp/cifs01-ctl.

Download Tool