c语言hallowold程序,借助编译器阅读耗子叔6个变态的C语言Hello World程序

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

_____

这段代码初步一看,有点晕,但是如果耐心下来仔细读读,从一个安全从业者的角度来说,其实就是最为初级的加密,定义了一堆宏进行替换,很容易就可以把代码还原解读了,但是有一种更加快速不烧脑的方法,就是汇编。

gcc -std=c99 -S -o hello1.s -O2 -masm=intel -m64 hello1.c

汇编之后的结果:

hello1.s

.file"2.c"

.intel_syntax noprefix

.text

.globlmain

main:

.LFB0:

.cfi_startproc

pushrbp

.cfi_def_cfa_offset 16

.cfi_offset 6, -16

movrbp, rsp

.cfi_def_cfa_register 6

movedi, 72

callputchar

movedi, 101

callputchar

movedi, 108

callputchar

movedi, 108

callputchar

movedi, 111

callputchar

movedi, 44

callputchar

movedi, 32

callputchar

movedi, 119

callputchar

movedi, 111

callputchar

movedi, 114

callputchar

movedi, 108

callputchar

movedi, 100

callputchar

movedi, 33

callputchar

moveax, 0

poprbp

.cfi_def_cfa 7, 8

ret

.cfi_endproc

.LFE0:

.sizemain, .-main

.ident"GCC: (GNU) 4.9.2 20150212 (Red Hat 4.9.2-6)"

.section.note.GNU-stack,"",@progbits

如果懂汇编,这很容易读,不懂的也没事,简单的说就是,把字符串"hello,world!"对应的ascii码逐一的送入edi寄存器,64位操作系统函数的前留给参数分别保存在rdi,rsi,rdx,rcx,r8,r9,之后才是栈,压入之后,调用putchar函数输出字符到stdout。

再来看hello2.c

#include

int 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++]);

}

这一段代码没用使用宏,主要是靠运算来混淆,也是看的头晕,我一直感觉加一减一这种问题很容易导致出错。。如果依然使用上面的方法通过gcc的O0不优化得到的汇编代码:

hello2.s

.file"2.c"

.intel_syntax noprefix

.text

.globlmain

.typemain, [[@function](http://my.oschina.net/u/569418)](http://my.oschina.net/u/569418)

main:

.LFB0:

.cfi_startproc

pushrbp

.cfi_def_cfa_offset 16

.cfi_offset 6, -16

movrbp, rsp

.cfi_def_cfa_register 6

subrsp, 80

movDWORD PTR [rbp-4], 0

learax, [rbp-80]

movQWORD PTR [rbp-16], rax

movrax, QWORD PTR [rbp-16]

leardx, [rax+4]

movQWORD PTR [rbp-16], rdx

movDWORD PTR [rax], 72

movrax, QWORD PTR [rbp-16]

leardx, [rax+4]

movQWORD PTR [rbp-16], rdx

movedx, DWORD PTR [rbp-4]

leaecx, [rdx+1]

movDWORD PTR [rbp-4], ecx

movsxrdx, edx

movedx, DWORD PTR [rbp-80+rdx*4]

addedx, 29

movDWORD PTR [rax], edx

movrax, QWORD PTR [rbp-16]

leardx, [rax+4]

movQWORD PTR [rbp-16], rdx

movedx, DWORD PTR [rbp-4]

leaecx, [rdx+1]

movDWORD PTR [rbp-4], ecx

movsxrdx, edx

movedx, DWORD PTR [rbp-80+rdx*4]

addedx, 7

movDWORD PTR [rax], edx

movrax, QWORD PTR [rbp-16]

leardx, [rax+4]

movQWORD PTR [rbp-16], rdx

movedx, DWORD PTR [rbp-4]

leaecx, [rdx+1]

movDWORD PTR [rbp-4], ecx

movsxrdx, edx

movedx, DWORD PTR [rbp-80+rdx*4]

movDWORD PTR [rax], edx

movrax, QWORD PTR [rbp-16]

leardx, [rax+4]

movQWORD PTR [rbp-16], rdx

movedx, DWORD PTR [rbp-4]

leaecx, [rdx+1]

movDWORD PTR [rbp-4], ecx

movsxrdx, edx

movedx, DWORD PTR [rbp-80+rdx*4]

addedx, 3

movDWORD PTR [rax], edx

movrax, QWORD PTR [rbp-16]

leardx, [rax+4]

movQWORD PTR [rbp-16], rdx

movedx, DWORD PTR [rbp-4]

leaecx, [rdx+1]

movDWORD PTR [rbp-4], ecx

movsxrdx, edx

movedx, DWORD PTR [rbp-80+rdx*4]

subedx, 67

movDWORD PTR [rax], edx

movrax, QWORD PTR [rbp-16]

leardx, [rax+4]

movQWORD PTR [rbp-16], rdx

movedx, DWORD PTR [rbp-4]

leaecx, [rdx+1]

movDWORD PTR [rbp-4], ecx

movsxrdx, edx

movedx, DWORD PTR [rbp-80+rdx*4]

subedx, 12

movDWORD PTR [rax], edx

movrax, QWORD PTR [rbp-16]

leardx, [rax+4]

movQWORD PTR [rbp-16], rdx

movedx, DWORD PTR [rbp-4]

leaecx, [rdx+1]

movDWORD PTR [rbp-4], ecx

movsxrdx, edx

movedx, DWORD PTR [rbp-80+rdx*4]

addedx, 87

movDWORD PTR [rax], edx

movrax, QWORD PTR [rbp-16]

leardx, [rax+4]

movQWORD PTR [rbp-16], rdx

movedx, DWORD PTR [rbp-4]

leaecx, [rdx+1]

movDWORD PTR [rbp-4], ecx

movsxrdx, edx

movedx, DWORD PTR [rbp-80+rdx*4]

subedx, 8

movDWORD PTR [rax], edx

movrax, QWORD PTR [rbp-16]

leardx, [rax+4]

movQWORD PTR [rbp-16], rdx

movedx, DWORD PTR [rbp-4]

leaecx, [rdx+1]

movDWORD PTR [rbp-4], ecx

movsxrdx, edx

movedx, DWORD PTR [rbp-80+rdx*4]

addedx, 3

movDWORD PTR [rax], edx

movrax, QWORD PTR [rbp-16]

leardx, [rax+4]

movQWORD PTR [rbp-16], rdx

movedx, DWORD PTR [rbp-4]

leaecx, [rdx+1]

movDWORD PTR [rbp-4], ecx

movsxrdx, edx

movedx, DWORD PTR [rbp-80+rdx*4]

subedx, 6

movDWORD PTR [rax], edx

movrax, QWORD PTR [rbp-16]

leardx, [rax+4]

movQWORD PTR [rbp-16], rdx

movedx, DWORD PTR [rbp-4]

leaecx, [rdx+1]

movDWORD PTR [rbp-4], ecx

movsxrdx, edx

movedx, DWORD PTR [rbp-80+rdx*4]

subedx, 8

movDWORD PTR [rax], edx

movrax, QWORD PTR [rbp-16]

leardx, [rax+4]

movQWORD PTR [rbp-16], rdx

movedx, DWORD PTR [rbp-4]

leaecx, [rdx+1]

movDWORD PTR [rbp-4], ecx

movsxrdx, edx

movedx, DWORD PTR [rbp-80+rdx*4]

subedx, 67

movDWORD PTR [rax], edx

movrax, QWORD PTR [rbp-16]

leardx, [rax+4]

movQWORD PTR [rbp-16], rdx

movedx, DWORD PTR [rbp-4]

movsxrdx, edx

movedx, DWORD PTR [rbp-80+rdx*4]

subedx, 33

movDWORD PTR [rax], edx

subQWORD PTR [rbp-16], 4

movrax, QWORD PTR [rbp-16]

moveax, DWORD PTR [rax]

movDWORD PTR [rbp-4], eax

jmp.L2

.L3:

moveax, DWORD PTR [rbp-4]

leaedx, [rax+1]

movDWORD PTR [rbp-4], edx

cdqe

moveax, DWORD PTR [rbp-80+rax*4]

movedi, eax

callputchar

.L2:

moveax, DWORD PTR [rbp-4]

cdqe

moveax, DWORD PTR [rbp-80+rax*4]

cdqe

testrax, rax

jne.L3

moveax, 0

leave

.cfi_def_cfa 7, 8

ret

.cfi_endproc

.LFE0:

.sizemain, .-main

.ident"GCC: (GNU) 4.9.2 20150212 (Red Hat 4.9.2-6)"

.section.note.GNU-stack,"",@progbits

可以看到,挺难读的。。其实可以使用O2优化,执行:

gcc -std=c99 -S -o hello2.s -O2 -masm=intel -m64 hello2.c

.file"2.c"

.intel_syntax noprefix

.section.text.unlikely,"ax",@progbits

.LCOLDB0:

.section.text.startup,"ax",@progbits

.LHOTB0:

.p2align 4,,15

.globlmain

.typemain, @function

main:

.LFB3:

.cfi_startproc

pushrbp

.cfi_def_cfa_offset 16

.cfi_offset 6, -16

pushrbx

.cfi_def_cfa_offset 24

.cfi_offset 3, -24

movedi, 72

movebx, 101

subrsp, 72

.cfi_def_cfa_offset 96

movDWORD PTR [rsp], 72

movDWORD PTR [rsp+4], 101

learbp, [rsp+8]

movDWORD PTR [rsp+8], 108

movDWORD PTR [rsp+12], 108

movDWORD PTR [rsp+16], 111

movDWORD PTR [rsp+20], 44

movDWORD PTR [rsp+24], 32

movDWORD PTR [rsp+28], 119

movDWORD PTR [rsp+32], 111

movDWORD PTR [rsp+36], 114

movDWORD PTR [rsp+40], 108

movDWORD PTR [rsp+44], 100

movDWORD PTR [rsp+48], 33

movDWORD PTR [rsp+52], 0

jmp.L2

.p2align 4,,10

.p2align 3

.L7:

moveax, DWORD PTR [rbp+0]

movedi, ebx

addrbp, 4

movebx, eax

.L2:

movrsi, QWORD PTR stdout[rip]

call_IO_putc

testebx, ebx

jne.L7

addrsp, 72

.cfi_def_cfa_offset 24

xoreax, eax

poprbx

.cfi_def_cfa_offset 16

poprbp

.cfi_def_cfa_offset 8

ret

.cfi_endproc

.LFE3:

.sizemain, .-main

.section.text.unlikely

.LCOLDE0:

.section.text.startup

.LHOTE0:

.ident"GCC: (GNU) 4.9.2 20150212 (Red Hat 4.9.2-6)"

.section.note.GNU-stack,"",@progbits

这次代码量少了很多,好读多了,大概意思就是把hello,world!的ascii码送入rsp栈中,之后跳到L2,L2中逻辑是先调用系统调用_IO_PUTC输入rdi中的字符到stdout中,之后使用test指令,测试ebx是否为零,jnz和jne效果等同,根据ZF标志位来跳转,如果不为零,跳转到L7,直到遇到字符串结尾字符'\0',ZF=0,jne .L7不成立往下执行程序结束。

其余的4段就不解析了,差不多。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值