二进制逆向:简介

目录

1.C编译过程

(1)预处理阶段

(2)编译阶段

(3)汇编阶段

(4)链接阶段

2.符号和剥离的二进制文件

3.反汇编二进制文件

4.加载并执行二进制文件


1.C编译过程

c++程序在Linux中编译链接及装载过程_lalaguo的博客-CSDN博客

C语言编译原理介绍_Greens_Ren的博客-CSDN博客_c语言编译原理

 HelloWorld.c

#include<stdio.h>
#define FORMAT_STRING "%s"
#define MESSAGE "Hello,world!\n"
int main(int argc, char* argv[]){
    printf(FORMAT_STRING, MESSAGE);

    return 0;
}
(1)预处理阶段
gcc -E -P HelloWorld.c

 

/*...*/
extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
extern int __uflow (FILE *);
extern int __overflow (FILE *, int);

int main(int argc, char* argv[]){
    printf("%s", "Hello,world!\n");
    return 0;
}

其中包含了stdio.h的所有类型定义,全局变量,函数原型都存在其中。预处理器还完整扩展了#define定义的任何宏的所有用法。

(2)编译阶段
gcc -S -masm=intel HelloWorld.c
cat HelloWorld.s
        .file   "HelloWorld.c"
        .intel_syntax noprefix
        .text
        .section        .rodata
.LC0:
        .string "Hello,world!"
        .text
        .globl  main
        .type   main, @function
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, 16
        mov     DWORD PTR -4[rbp], edi
        mov     QWORD PTR -16[rbp], rsi
        lea     rdi, .LC0[rip]
        call    puts@PLT
        mov     eax, 0
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (Debian 10.2.1-6) 10.2.1 20210110"
        .section        .note.GNU-stack,"",@progbits

gcc通过将对printf替换为puts进行优化

(3)汇编阶段
gcc -c HelloWorld.c
file HelloWorld.o
HelloWorld.o: ELF 64-bit LSB relocatable, 
x86-64, version 1 (SYSV), not stripped

 ELF重定位文件,64位,LSB最低有效位,未剥夺的。

(4)链接阶段

链接时会包含额外的优化LTO(Link-Time Optimization)

gcc HelloWorld.c
file a.out
a.out: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked,
interpreter /lib64/ld-linux-x86-64.so.2, 
BuildID[sha1]=17d0303e23196158edff6a71e3c0af20ec6f08da, for GNU/Linux 3.2.0, not stripped

可执行文件名为a.out,动态链接,解释器/lib64/ld-linux-x86-64.so.2的文件输出会告诉你当加载到内存中执行时,哪个动态链接器将被用来解析动态库的最终关系。

2.符号和剥离的二进制文件

readelf --syms a.out
/*...*/    
    54: 0000000000002000     4 OBJECT  GLOBAL DEFAULT   17 _IO_stdin_used
    55: 0000000000004038     0 NOTYPE  GLOBAL DEFAULT   26 _end
    56: 0000000000001050    34 FUNC    GLOBAL DEFAULT   15 _start
    57: 0000000000004030     0 NOTYPE  GLOBAL DEFAULT   26 __bss_start
    58: 0000000000001135    34 FUNC    GLOBAL DEFAULT   15 main
    59: 0000000000004030     0 OBJECT  GLOBAL HIDDEN    25 __TMC_END__
    60: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMC[...]
    61: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@G[...]
    62: 0000000000001000     0 FUNC    GLOBAL HIDDEN    12 _init

main函数有一个符号,指定了当二进制文件加载到内存时将驻留的地址0x1135,还显示代码大小34字节,并指出你正在处理一个函数符号FUNC

剥离符号信息:

strip --strip-all a.out
file a.out
a.out: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, 
interpreter /lib64/ld-linux-x86-64.so.2, 
BuildID[sha1]=17d0303e23196158edff6a71e3c0af20ec6f08da, 
for GNU/Linux 3.2.0, stripped
readelf --syms a.out
Symbol table '.dynsym' contains 7 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _[...]@GLIBC_2.34 (2)
     2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterT[...]
     3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@GLIBC_2.2.5 (3)
     4: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     5: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMC[...]
     6: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND [...]@GLIBC_2.2.5 (3)

3.反汇编二进制文件

└─$ objdump -sj .rodata HelloWorld.o 

HelloWorld.o:     file format elf64-x86-64

Contents of section .rodata:
 0000 48656c6c 6f2c776f 726c6421 00        Hello,world!.   
                                                                                                                                                

└─$ objdump -M intel -d HelloWorld.o 

HelloWorld.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <main>:
   0:   55                      push   rbp
   1:   48 89 e5                mov    rbp,rsp
   4:   48 83 ec 10             sub    rsp,0x10
   8:   89 7d fc                mov    DWORD PTR [rbp-0x4],edi
   b:   48 89 75 f0             mov    QWORD PTR [rbp-0x10],rsi
   f:   48 8d 3d 00 00 00 00    lea    rdi,[rip+0x0]        # 16 <main+0x16>
  16:   e8 00 00 00 00          call   1b <main+0x1b>
  1b:   b8 00 00 00 00          mov    eax,0x0
  20:   c9                      leave  
  21:   c3                      ret

4.加载并执行二进制文件

当决定运行一个二进制文件时,操作系统首先要为运行的程序创建一个进程,其中包括虚拟地址空间。随后操作系统将解释器映射到进程的虚拟内存中,他知道如何加载二进制文件并执行必要的重定位。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值