其实在实现这个奇怪的行为之前,你需要了解一以下几样(奇怪的)知识
- c语言main函数的本质
- 汇编语言和机器码
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,然而这种奇怪的技巧,有什么卵用呢?