首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

六種極致混淆的 C 語言 Hello World 寫法賞析

     編輯:關於C

前言:當代碼變成謎題

以下六個程式片段皆能輸出 Hello, World,卻將原始碼混淆至極致。前五個可在 GCC 編譯通過,最後一個需 G++(C++ 編譯器)。這不僅是技巧展示,更能加深對預處理器、指標運算、位運算與控制流的理解。

hello1.c:巨集層層包裹

#define _________ }
#define ________ putchar
#define _______ main
#define _(a) ________(a);
#define ______ _______(){
#define __ ______ _(0x48)_(0x65)_(0x6C)_(0x6C)
#define ___ _(0x6F)_(0x2C)_(0x20)_(0x77)_(0x6F)
#define ____ _(0x72)_(0x6C)_(0x64)_(0x21)
#define _____ __ ___ ____ _________
#include<stdio.h>
_____

利用巨集遞迴展開,將 main(){ putchar(...); } 拆解為單字元輸出,十六進位碼對應 ASCII:0x48=H、0x65=e... 最後 _____ 展開為完整函數。

hello2.c:指標算術與陣列操作

#include<stdio.h>
main(){
    int x=0,y[14],*z=&y;*(z++)=0x48;*(z++)=y[x++]+0x1D;
    *(z++)=y[x++]+0x07;*(z++)=y[x++]+0x00;*(z++)=y[x++]+0x03;
    *(z++)=y[x++]-0x43;*(z++)=y[x++]-0x0C;*(z++)=y[x++]+0x57;
    *(z++)=y[x++]-0x08;*(z++)=y[x++]+0x03;*(z++)=y[x++]-0x06;
    *(z++)=y[x++]-0x08;*(z++)=y[x++]-0x43;*(z++)=y[x]-0x21;
    x=*(--z);while(y[x]!=NULL)putchar(y[x++]);
}

透過指標 z 遍歷陣列 y,利用位移量編碼字元,最後反向輸出。展示指標運算的靈活與危險。

hello3.c:goto 與標籤編織的狀態機

#include<stdio.h>
#define __(a) goto a;
#define ___(a) putchar(a);
#define _(a,b) ___(a) __(b);
main()
{ _:__(t)a:_('r',g)b:_('$',p)
c:_('l',f)d:_(' ',s)e:_('a',s)
f:_('o',q)g:_('l',h)h:_('d',n)
i:_('e',w)j:_('e',x)k:_('\n',z)
l:_('H',l)m:_('X',i)n:_('!',k)
o:_('z',q)p:_('q',b)q:_(',',d)
r:_('i',l)s:_('w',v)t:_('H',j)
u:_('a',a)v:_('o',a)w:_(')',k)
x:_('l',c)y:_('\t',g)z:___(0x0)}

將輸出流程拆解為標籤跳轉,每個標籤輸出一字元並跳往下一標籤,構成隱式有限狀態機。

hello4.c:遞迴輸出字元陣列

int n[]={0x48,0x65,0x6C,0x6C,0x6F,0x2C,0x20,0x77,0x6F,0x72,0x6C,0x64,0x21,0x0A,0x00},*m=n;
main(n){putchar(*m)!='\0'?main(m++):exit(n++);}

利用 main 遞迴呼叫自身,配合指標遞增遍歷字元陣列,遇結束符 \0 則退出。展示遞迴替代迴圈的技巧。

hello5.c:純位運算編碼字元碼

main(){int i,n[]={(((1<<1)<<(1<<1)<<(1<<1)<<(1<<(1>>1)))+((1<<1)<<(1<<1))), ... }; for(i=(1>>1);i<(((1<<1)<<(1<<1))+((1<<1)<<(1<<(1>>1)))+(1<<1));i++) printf("%c",n[i]);}

所有字元碼(ASCII)均由 1 的左移、右移、加減運算組合而成,零硬編碼數值。極致展示位運算的表達能力。

hello6.cpp:C++ 專屬,前置/後置遞增減運算符的藝術

#include <stdio.h>
#define _(_) putchar(_);
int main(void){int i = 0;_(++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++i)_(++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++i)_(++++++++++++++++++++++++++++++++++++++++++++++++++++++++i)_(--++i)_(++++++i)_(------...i)_(----------------i)_(++++++i)_(------------i)_(--------i)_(----------------------------i)_(------------------i)return i;}

利用大量 ++/-- 運算子疊加產生目標 ASCII 碼,僅 C++ 允許此類運算子連續作用於同一變數(C 標準未定義行為)。

總結:可讀性與維護性的反面教材

這些寫法雖展示語言特性邊界,但實務中應極力避免。良好的代碼應清晰表達意圖,而非炫技。理解它們有助於看懂混淆代碼、逆向分析與編譯器原理,但請勿在生產環境模仿。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved