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>
_____
这段代码初步一看,有点晕,但是如果耐心下来仔细读读,从一个安全从业者的角度来说,其实就是最为初级的加密,定义了一堆宏进行替换,很容易就可以把代码还原解读了,但是有一种更加快速不烧脑的方法,就是汇编。
gcc -std=c99 -S -o hello1.s -O2 -masm=intel -m64 hello1.c
汇编之后的结果:
hello1.s
.file "2.c"
.intel_syntax noprefix
.text
.globl main
main:
.LFB0:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
mov edi, 72
call putchar
mov edi, 101
call putchar
mov edi, 108
call putchar
mov edi, 108
call putchar
mov edi, 111
call putchar
mov edi, 44
call putchar
mov edi, 32
call putchar
mov edi, 119
call putchar
mov edi, 111
call putchar
mov edi, 114
call putchar
mov edi, 108
call putchar
mov edi, 100
call putchar
mov edi, 33
call putchar
mov eax, 0
pop rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-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<stdio.h>
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
.globl main
.type main, [[@function](http://my.oschina.net/u/569418)](http://my.oschina.net/u/569418)
main:
.LFB0:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
sub rsp, 80
mov DWORD PTR [rbp-4], 0
lea rax, [rbp-80]
mov QWORD PTR [rbp-16], rax
mov rax, QWORD PTR [rbp-16]
lea rdx, [rax+4]
mov QWORD PTR [rbp-16], rdx
mov DWORD PTR [rax], 72
mov rax, QWORD PTR [rbp-16]
lea rdx, [rax+4]
mov QWORD PTR [rbp-16], rdx
mov edx, DWORD PTR [rbp-4]
lea ecx, [rdx+1]
mov DWORD PTR [rbp-4], ecx
movsx rdx, edx
mov edx, DWORD PTR [rbp-80+rdx*4]
add edx, 29
mov DWORD PTR [rax], edx
mov rax, QWORD PTR [rbp-16]
lea rdx, [rax+4]
mov QWORD PTR [rbp-16], rdx
mov edx, DWORD PTR [rbp-4]
lea ecx, [rdx+1]
mov DWORD PTR [rbp-4], ecx
movsx rdx, edx
mov edx, DWORD PTR [rbp-80+rdx*4]
add edx, 7
mov DWORD PTR [rax], edx
mov rax, QWORD PTR [rbp-16]
lea rdx, [rax+4]
mov QWORD PTR [rbp-16], rdx
mov edx, DWORD PTR [rbp-4]
lea ecx, [rdx+1]
mov DWORD PTR [rbp-4], ecx
movsx rdx, edx
mov edx, DWORD PTR [rbp-80+rdx*4]
mov DWORD PTR [rax], edx
mov rax, QWORD PTR [rbp-16]
lea rdx, [rax+4]
mov QWORD PTR [rbp-16], rdx
mov edx, DWORD PTR [rbp-4]
lea ecx, [rdx+1]
mov DWORD PTR [rbp-4], ecx
movsx rdx, edx
mov edx, DWORD PTR [rbp-80+rdx*4]
add edx, 3
mov DWORD PTR [rax], edx
mov rax, QWORD PTR [rbp-16]
lea rdx, [rax+4]
mov QWORD PTR [rbp-16], rdx
mov edx, DWORD PTR [rbp-4]
lea ecx, [rdx+1]
mov DWORD PTR [rbp-4], ecx
movsx rdx, edx
mov edx, DWORD PTR [rbp-80+rdx*4]
sub edx, 67
mov DWORD PTR [rax], edx
mov rax, QWORD PTR [rbp-16]
lea rdx, [rax+4]
mov QWORD PTR [rbp-16], rdx
mov edx, DWORD PTR [rbp-4]
lea ecx, [rdx+1]
mov DWORD PTR [rbp-4], ecx
movsx rdx, edx
mov edx, DWORD PTR [rbp-80+rdx*4]
sub edx, 12
mov DWORD PTR [rax], edx
mov rax, QWORD PTR [rbp-16]
lea rdx, [rax+4]
mov QWORD PTR [rbp-16], rdx
mov edx, DWORD PTR [rbp-4]
lea ecx, [rdx+1]
mov DWORD PTR [rbp-4], ecx
movsx rdx, edx
mov edx, DWORD PTR [rbp-80+rdx*4]
add edx, 87
mov DWORD PTR [rax], edx
mov rax, QWORD PTR [rbp-16]
lea rdx, [rax+4]
mov QWORD PTR [rbp-16], rdx
mov edx, DWORD PTR [rbp-4]
lea ecx, [rdx+1]
mov DWORD PTR [rbp-4], ecx
movsx rdx, edx
mov edx, DWORD PTR [rbp-80+rdx*4]
sub edx, 8
mov DWORD PTR [rax], edx
mov rax, QWORD PTR [rbp-16]
lea rdx, [rax+4]
mov QWORD PTR [rbp-16], rdx
mov edx, DWORD PTR [rbp-4]
lea ecx, [rdx+1]
mov DWORD PTR [rbp-4], ecx
movsx rdx, edx
mov edx, DWORD PTR [rbp-80+rdx*4]
add edx, 3
mov DWORD PTR [rax], edx
mov rax, QWORD PTR [rbp-16]
lea rdx, [rax+4]
mov QWORD PTR [rbp-16], rdx
mov edx, DWORD PTR [rbp-4]
lea ecx, [rdx+1]
mov DWORD PTR [rbp-4], ecx
movsx rdx, edx
mov edx, DWORD PTR [rbp-80+rdx*4]
sub edx, 6
mov DWORD PTR [rax], edx
mov rax, QWORD PTR [rbp-16]
lea rdx, [rax+4]
mov QWORD PTR [rbp-16], rdx
mov edx, DWORD PTR [rbp-4]
lea ecx, [rdx+1]
mov DWORD PTR [rbp-4], ecx
movsx rdx, edx
mov edx, DWORD PTR [rbp-80+rdx*4]
sub edx, 8
mov DWORD PTR [rax], edx
mov rax, QWORD PTR [rbp-16]
lea rdx, [rax+4]
mov QWORD PTR [rbp-16], rdx
mov edx, DWORD PTR [rbp-4]
lea ecx, [rdx+1]
mov DWORD PTR [rbp-4], ecx
movsx rdx, edx
mov edx, DWORD PTR [rbp-80+rdx*4]
sub edx, 67
mov DWORD PTR [rax], edx
mov rax, QWORD PTR [rbp-16]
lea rdx, [rax+4]
mov QWORD PTR [rbp-16], rdx
mov edx, DWORD PTR [rbp-4]
movsx rdx, edx
mov edx, DWORD PTR [rbp-80+rdx*4]
sub edx, 33
mov DWORD PTR [rax], edx
sub QWORD PTR [rbp-16], 4
mov rax, QWORD PTR [rbp-16]
mov eax, DWORD PTR [rax]
mov DWORD PTR [rbp-4], eax
jmp .L2
.L3:
mov eax, DWORD PTR [rbp-4]
lea edx, [rax+1]
mov DWORD PTR [rbp-4], edx
cdqe
mov eax, DWORD PTR [rbp-80+rax*4]
mov edi, eax
call putchar
.L2:
mov eax, DWORD PTR [rbp-4]
cdqe
mov eax, DWORD PTR [rbp-80+rax*4]
cdqe
test rax, rax
jne .L3
mov eax, 0
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-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
.globl main
.type main, @function
main:
.LFB3:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
push rbx
.cfi_def_cfa_offset 24
.cfi_offset 3, -24
mov edi, 72
mov ebx, 101
sub rsp, 72
.cfi_def_cfa_offset 96
mov DWORD PTR [rsp], 72
mov DWORD PTR [rsp+4], 101
lea rbp, [rsp+8]
mov DWORD PTR [rsp+8], 108
mov DWORD PTR [rsp+12], 108
mov DWORD PTR [rsp+16], 111
mov DWORD PTR [rsp+20], 44
mov DWORD PTR [rsp+24], 32
mov DWORD PTR [rsp+28], 119
mov DWORD PTR [rsp+32], 111
mov DWORD PTR [rsp+36], 114
mov DWORD PTR [rsp+40], 108
mov DWORD PTR [rsp+44], 100
mov DWORD PTR [rsp+48], 33
mov DWORD PTR [rsp+52], 0
jmp .L2
.p2align 4,,10
.p2align 3
.L7:
mov eax, DWORD PTR [rbp+0]
mov edi, ebx
add rbp, 4
mov ebx, eax
.L2:
mov rsi, QWORD PTR stdout[rip]
call _IO_putc
test ebx, ebx
jne .L7
add rsp, 72
.cfi_def_cfa_offset 24
xor eax, eax
pop rbx
.cfi_def_cfa_offset 16
pop rbp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE3:
.size main, .-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段就不解析了,差不多。
评论
暂无评论~~