邪修 C 语言 10 连击|计算型 goto、零长数组、运行时改机器码

编程狮(w3cschool.cn) 2025-08-07 11:41:33 浏览数 (173)
反馈

邪修 C 语言,10 段“直接劝退”的黑魔法代码
——仅供技术猎奇,切勿上生产!

编译器警告、UB(未定义行为)、UBSAN 狂怒,请自备防护眼镜 🧨

1️⃣ 一行 main 都没有的程序

#include <stdio.h>
void _start(){puts("邪修C");}

链接时加 -nostartfiles,直接跳过 CRT,Linux 裸奔。

2️⃣ Duff’s Device —— switch 跳进 while

void evil_memcpy(char *dst, char *src, size_t n){
    switch(n & 7){
        case 0: while(n--){ *dst++ = *src++;
        case 7: *dst++ = *src++;
        case 6: *dst++ = *src++;
        case 5: *dst++ = *src++;
        case 4: *dst++ = *src++;
        case 3: *dst++ = *src++;
        case 2: *dst++ = *src++;
        case 1: *dst++ = *src++;
                }break;
    }
}

循环展开 + switch 套 while,上古时代“手动 SIMD”。

3️⃣ 宏黑魔法:让 if 变成代码块

#define evil_if(x) if(x);else


evil_if(0)
    puts("你猜我会打印吗?");

宏定义末尾的分号把 else 直接悬空,编译器当场裂开。

4️⃣ 指针运算玩出花

int a[5] = {1,2,3,4,5};
printf("%d\n", 3[a]); // 输出 4

a[3]3[a] 等价,编译器:你们开心就好。

5️⃣ 结构体“零长度数组”末班车

struct msg {
    int len;
    char data[0]; // 邪修柔性数组
};
struct msg *m = malloc(sizeof *m + 100);
strcpy(m->data, "hello");

0 长度数组是 GNU 私货,标准 C99 请用 char data[]

6️⃣ 位域重叠 + 联合体重写

union {
    struct { unsigned a:4, b:4; } nibble;
    unsigned char byte;
} u = {.byte = 0xAB};
printf("%x %x\n", u.nibble.a, u.nibble.b); // 平台决定大小端

一步踏进 未定义行为 的大坑。

7️⃣ 自修改机器码(mmap 版)

#include <sys/mman.h>
char *code = mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC,
                  MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
unsigned char payload[] = {0x48,0xC7,0xC0,0x01,0x00,0x00,0x00,0xC3}; // x86-64: mov rax,1; ret
memcpy(code, payload, sizeof payload);
int (*ret1)(void) = (int (*)(void))code;
printf("ret=%d\n", ret1());

运行时生成 shellcode,杀毒软件直接报警。

8️⃣ 多重 sizeof 套娃

printf("%zu\n", sizeof sizeof sizeof "abc"); // 输出 8(64 位指针)

连续 sizeof 把任何表达式剥成 size_t,毫无营养。

9️⃣ 逗号运算符“一行流”

int x = (printf("a\n"), printf("b\n"), 3);
printf("%d\n", x); // 依次打印 a b 3

把副作用写进表达式,debug 时想打人。

🔟 GOTO 地狱 + 标签运算

int main(){
    static const void *tab[] = {&&l0, &&l1, &&l2};
    int i = 1;
    goto *tab[i];
l0: puts("zero"); return 0;
l1: puts("one");  return 0;
l2: puts("two");  return 0;
}

计算型 goto(GNU C 扩展)手写跳转表。

邪修口诀

“内存随便指,宏里藏杀机,UB 当特性,编译器哭泣。”

C

0 人点赞