如何在c语言中不用任何括号输出hello world

其实在实现这个奇怪的行为之前,你需要了解一以下几样(奇怪的)知识

  1. c语言main函数的本质
  2. 汇编语言和机器码

1.main的本质初探

在平时写c语言,大多数时候都是int main(),这时候main是什么?我们不妨做个试验:

找一个语法检查比较松的ide(cfree)写入代码

int a=printf;
printf("%d",a);

是不是可以打印出一个奇怪的东西~.~

这里打印的其实是printf的地址。所以在汇编里面,调用函数是call + 地址,这里也是一样的原理。

所以在我们写的程序编译之后。某个函数call了我们的main函数,才让我们的程序得以执行。所以main本身只是一个地址。

所以如果我们写下int main=0x2333;也是可以通过编译的

2.汇编&机器码

知道了一点main函数的真面目,我们就可以搞事情了~

既然是call main,只要能让main所在的地址拥有那么一段可以输出helloworld的代码不就行了?

但是如果我们直接用c语言写的话,你会发现反汇编出来的东西依旧很多,不利于我们实际的操作,所以我们这里用汇编写

(环境 kali linux x64)

global main
    main:
        jmp s
        nop
    s: 
        push 0x64
        pop rdx
        push 0x1
        pop rdi
        mov rax,rdi
        push 0
        push 0x21
        push 0x64
        push 0x6C
        push 0x72
        push 0x6F
        push 0x57
        push 0x20
        push 0x2C
        push 0x6F
        push 0x6C
        push 0x6C
        push 0x65
        push 0x48
        nop
        mov rsi,rsp
        syscall
        push 0x3c
        pop rax
        push 0x1
        pop rdi
        syscall

这一段就是可以输出helloworld的汇编语言,用nasm编译之后,我们开始用objdump反汇编生成的文件

这时候再把前面对应的机器码依次用c写入

(这里留个小问题:为什么用const char? )

做到这一步基本上就已经完成了,最后虽然可能还会有一点小问题,不过也已经不难解决了。

看上去很nb,然而这种奇怪的技巧,有什么卵用呢?

发表评论

电子邮件地址不会被公开。 必填项已用*标注