目录

记一次Linux简单的逆向工程实验

我的实验环境

0x0 准备工作

0x1 开始逆向工程

0x2 结尾


记一次Linux简单的逆向工程实验

逆向工程,通过反汇编、反编译和动态跟踪等方法,分析出其动画效果的实现过程,这种行为就是逆向工程。但逆向工程不仅仅是反编译,而且还要推倒出设计,并且文档化,逆向别人的软件时要遵循相关的条约,逆向软件工程的目的是使软件得以维护。

我的实验环境

系统:Ubuntu 16.04 STL (4.15.0-88-generic)

CPU架构:x86_64

工具:Vim 7.4、Gedit 3.18.3、GCC (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0、Objdump (GNU Binutils for Ubuntu) 2.26.1

0x0 准备工作

因为是实验,所以我写了一个名为"test"的简单C程序来作为本次实验的逆向目标。

#include <stdlib.h>

int main(int argc, char* argv[])
{
    int a = 1;
    a += 1;
    while (1) {
        if (a > 1) {
            a -= 1;
        }
        else {
            break;
        }
    }
    exit(0);
}

之后我们编译运行一次。

linux怎么反编译java文件 linux 反编译_linux怎么反编译java文件

编译和运行没有任何问题,之后我们使用 objdump -d test > test_rev.s 来反汇编得到 test 的反汇编代码,并将它重定向到一个名为"test_rev.s"的文件里,再用 gedit 将它打开,打开后我们得到如下内容,这就是 test 的反汇编代码了(我这里使用的是AT&T的汇编格式,如果想看Intel的汇编格式可以在使用objdump的时候加上 -M intel 就可以看到Intel格式的汇编了)。

test:     file format elf64-x86-64


Disassembly of section .init:

00000000004003c8 <_init>:
  4003c8:	48 83 ec 08          	sub    $0x8,%rsp
  4003cc:	48 8b 05 25 0c 20 00 	mov    0x200c25(%rip),%rax        # 600ff8 <_DYNAMIC+0x1d0>
  4003d3:	48 85 c0             	test   %rax,%rax
  4003d6:	74 05                	je     4003dd <_init+0x15>
  4003d8:	e8 43 00 00 00       	callq  400420 <exit@plt+0x10>
  4003dd:	48 83 c4 08          	add    $0x8,%rsp
  4003e1:	c3                   	retq   

Disassembly of section .plt:

00000000004003f0 <__libc_start_main@plt-0x10>:
  4003f0:	ff 35 12 0c 20 00    	pushq  0x200c12(%rip)        # 601008 <_GLOBAL_OFFSET_TABLE_+0x8>
  4003f6:	ff 25 14 0c 20 00    	jmpq   *0x200c14(%rip)        # 601010 <_GLOBAL_OFFSET_TABLE_+0x10>
  4003fc:	0f 1f 40 00          	nopl   0x0(%rax)

0000000000400400 <__libc_start_main@plt>:
  400400:	ff 25 12 0c 20 00    	jmpq   *0x200c12(%rip)        # 601018 <_GLOBAL_OFFSET_TABLE_+0x18>
  400406:	68 00 00 00 00       	pushq  $0x0
  40040b:	e9 e0 ff ff ff       	jmpq   4003f0 <_init+0x28>

0000000000400410 <exit@plt>:
  400410:	ff 25 0a 0c 20 00    	jmpq   *0x200c0a(%rip)        # 601020 <_GLOBAL_OFFSET_TABLE_+0x20>
  400416:	68 01 00 00 00       	pushq  $0x1
  40041b:	e9 d0 ff ff ff       	jmpq   4003f0 <_init+0x28>

Disassembly of section .plt.got:

0000000000400420 <.plt.got>:
  400420:	ff 25 d2 0b 20 00    	jmpq   *0x200bd2(%rip)        # 600ff8 <_DYNAMIC+0x1d0>
  400426:	66 90                	xchg   %ax,%ax

Disassembly of section .text:

0000000000400430 <_start>:
  400430:	31 ed                	xor    %ebp,%ebp
  400432:	49 89 d1             	mov    %rdx,%r9
  400435:	5e                   	pop    %rsi
  400436:	48 89 e2             	mov    %rsp,%rdx
  400439:	48 83 e4 f0          	and    $0xfffffffffffffff0,%rsp
  40043d:	50                   	push   %rax
  40043e:	54                   	push   %rsp
  40043f:	49 c7 c0 d0 05 40 00 	mov    $0x4005d0,%r8
  400446:	48 c7 c1 60 05 40 00 	mov    $0x400560,%rcx
  40044d:	48 c7 c7 26 05 40 00 	mov    $0x400526,%rdi
  400454:	e8 a7 ff ff ff       	callq  400400 <__libc_start_main@plt>
  400459:	f4                   	hlt    
  40045a:	66 0f 1f 44 00 00    	nopw   0x0(%rax,%rax,1)

0000000000400460 <deregister_tm_clones>:
  400460:	b8 3f 10 60 00       	mov    $0x60103f,%eax
  400465:	55                   	push   %rbp
  400466:	48 2d 38 10 60 00    	sub    $0x601038,%rax
  40046c:	48 83 f8 0e          	cmp    $0xe,%rax
  400470:	48 89 e5             	mov    %rsp,%rbp
  400473:	76 1b                	jbe    400490 <deregister_tm_clones+0x30>
  400475:	b8 00 00 00 00       	mov    $0x0,%eax
  40047a:	48 85 c0             	test   %rax,%rax
  40047d:	74 11                	je     400490 <deregister_tm_clones+0x30>
  40047f:	5d                   	pop    %rbp
  400480:	bf 38 10 60 00       	mov    $0x601038,%edi
  400485:	ff e0                	jmpq   *%rax
  400487:	66 0f 1f 84 00 00 00 	nopw   0x0(%rax,%rax,1)
  40048e:	00 00 
  400490:	5d                   	pop    %rbp
  400491:	c3                   	retq   
  400492:	0f 1f 40 00          	nopl   0x0(%rax)
  400496:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
  40049d:	00 00 00 

00000000004004a0 <register_tm_clones>:
  4004a0:	be 38 10 60 00       	mov    $0x601038,%esi
  4004a5:	55                   	push   %rbp
  4004a6:	48 81 ee 38 10 60 00 	sub    $0x601038,%rsi
  4004ad:	48 c1 fe 03          	sar    $0x3,%rsi
  4004b1:	48 89 e5             	mov    %rsp,%rbp
  4004b4:	48 89 f0             	mov    %rsi,%rax
  4004b7:	48 c1 e8 3f          	shr    $0x3f,%rax
  4004bb:	48 01 c6             	add    %rax,%rsi
  4004be:	48 d1 fe             	sar    %rsi
  4004c1:	74 15                	je     4004d8 <register_tm_clones+0x38>
  4004c3:	b8 00 00 00 00       	mov    $0x0,%eax
  4004c8:	48 85 c0             	test   %rax,%rax
  4004cb:	74 0b                	je     4004d8 <register_tm_clones+0x38>
  4004cd:	5d                   	pop    %rbp
  4004ce:	bf 38 10 60 00       	mov    $0x601038,%edi
  4004d3:	ff e0                	jmpq   *%rax
  4004d5:	0f 1f 00             	nopl   (%rax)
  4004d8:	5d                   	pop    %rbp
  4004d9:	c3                   	retq   
  4004da:	66 0f 1f 44 00 00    	nopw   0x0(%rax,%rax,1)

00000000004004e0 <__do_global_dtors_aux>:
  4004e0:	80 3d 51 0b 20 00 00 	cmpb   $0x0,0x200b51(%rip)        # 601038 <__TMC_END__>
  4004e7:	75 11                	jne    4004fa <__do_global_dtors_aux+0x1a>
  4004e9:	55                   	push   %rbp
  4004ea:	48 89 e5             	mov    %rsp,%rbp
  4004ed:	e8 6e ff ff ff       	callq  400460 <deregister_tm_clones>
  4004f2:	5d                   	pop    %rbp
  4004f3:	c6 05 3e 0b 20 00 01 	movb   $0x1,0x200b3e(%rip)        # 601038 <__TMC_END__>
  4004fa:	f3 c3                	repz retq 
  4004fc:	0f 1f 40 00          	nopl   0x0(%rax)

0000000000400500 <frame_dummy>:
  400500:	bf 20 0e 60 00       	mov    $0x600e20,%edi
  400505:	48 83 3f 00          	cmpq   $0x0,(%rdi)
  400509:	75 05                	jne    400510 <frame_dummy+0x10>
  40050b:	eb 93                	jmp    4004a0 <register_tm_clones>
  40050d:	0f 1f 00             	nopl   (%rax)
  400510:	b8 00 00 00 00       	mov    $0x0,%eax
  400515:	48 85 c0             	test   %rax,%rax
  400518:	74 f1                	je     40050b <frame_dummy+0xb>
  40051a:	55                   	push   %rbp
  40051b:	48 89 e5             	mov    %rsp,%rbp
  40051e:	ff d0                	callq  *%rax
  400520:	5d                   	pop    %rbp
  400521:	e9 7a ff ff ff       	jmpq   4004a0 <register_tm_clones>

0000000000400526 <main>:
  400526:	55                   	push   %rbp
  400527:	48 89 e5             	mov    %rsp,%rbp
  40052a:	48 83 ec 20          	sub    $0x20,%rsp
  40052e:	89 7d ec             	mov    %edi,-0x14(%rbp)
  400531:	48 89 75 e0          	mov    %rsi,-0x20(%rbp)
  400535:	c7 45 fc 01 00 00 00 	movl   $0x1,-0x4(%rbp)
  40053c:	83 45 fc 01          	addl   $0x1,-0x4(%rbp)
  400540:	83 7d fc 01          	cmpl   $0x1,-0x4(%rbp)
  400544:	7e 06                	jle    40054c <main+0x26>
  400546:	83 6d fc 01          	subl   $0x1,-0x4(%rbp)
  40054a:	eb f4                	jmp    400540 <main+0x1a>
  40054c:	90                   	nop
  40054d:	bf 00 00 00 00       	mov    $0x0,%edi
  400552:	e8 b9 fe ff ff       	callq  400410 <exit@plt>
  400557:	66 0f 1f 84 00 00 00 	nopw   0x0(%rax,%rax,1)
  40055e:	00 00 

0000000000400560 <__libc_csu_init>:
  400560:	41 57                	push   %r15
  400562:	41 56                	push   %r14
  400564:	41 89 ff             	mov    %edi,%r15d
  400567:	41 55                	push   %r13
  400569:	41 54                	push   %r12
  40056b:	4c 8d 25 9e 08 20 00 	lea    0x20089e(%rip),%r12        # 600e10 <__frame_dummy_init_array_entry>
  400572:	55                   	push   %rbp
  400573:	48 8d 2d 9e 08 20 00 	lea    0x20089e(%rip),%rbp        # 600e18 <__init_array_end>
  40057a:	53                   	push   %rbx
  40057b:	49 89 f6             	mov    %rsi,%r14
  40057e:	49 89 d5             	mov    %rdx,%r13
  400581:	4c 29 e5             	sub    %r12,%rbp
  400584:	48 83 ec 08          	sub    $0x8,%rsp
  400588:	48 c1 fd 03          	sar    $0x3,%rbp
  40058c:	e8 37 fe ff ff       	callq  4003c8 <_init>
  400591:	48 85 ed             	test   %rbp,%rbp
  400594:	74 20                	je     4005b6 <__libc_csu_init+0x56>
  400596:	31 db                	xor    %ebx,%ebx
  400598:	0f 1f 84 00 00 00 00 	nopl   0x0(%rax,%rax,1)
  40059f:	00 
  4005a0:	4c 89 ea             	mov    %r13,%rdx
  4005a3:	4c 89 f6             	mov    %r14,%rsi
  4005a6:	44 89 ff             	mov    %r15d,%edi
  4005a9:	41 ff 14 dc          	callq  *(%r12,%rbx,8)
  4005ad:	48 83 c3 01          	add    $0x1,%rbx
  4005b1:	48 39 eb             	cmp    %rbp,%rbx
  4005b4:	75 ea                	jne    4005a0 <__libc_csu_init+0x40>
  4005b6:	48 83 c4 08          	add    $0x8,%rsp
  4005ba:	5b                   	pop    %rbx
  4005bb:	5d                   	pop    %rbp
  4005bc:	41 5c                	pop    %r12
  4005be:	41 5d                	pop    %r13
  4005c0:	41 5e                	pop    %r14
  4005c2:	41 5f                	pop    %r15
  4005c4:	c3                   	retq   
  4005c5:	90                   	nop
  4005c6:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
  4005cd:	00 00 00 

00000000004005d0 <__libc_csu_fini>:
  4005d0:	f3 c3                	repz retq 

Disassembly of section .fini:

00000000004005d4 <_fini>:
  4005d4:	48 83 ec 08          	sub    $0x8,%rsp
  4005d8:	48 83 c4 08          	add    $0x8,%rsp
  4005dc:	c3                   	retq

可以看到反汇编代码里面有很多的与初始化、操作系统相关的代码段,每个段的含义我就不在这里讲了,我们直接找 test 程序的 main 函数,因为这个实验程序很简单,所以我们忽略一些初始化相关的段之后,剩下的就是程序里编写的函数代码了,我们看到在地址 400526 的地方出现了名为 main 的段名,那么这就是这个实验程序的入口 main 函数了(真实情况下的逆向不会这么简单的,但因为是实验,所以这个程序写的很简单!),看到它的反汇编代码后,我们就要开始分析它的反汇编代码了。

0x1 开始逆向工程

如前所诉,我们截取了 400526 地址位置的 main 函数段里的汇编代码,得到如下。

0000000000400526 <main>:
  400526:	55                   	push   %rbp
  400527:	48 89 e5             	mov    %rsp,%rbp
  40052a:	48 83 ec 20          	sub    $0x20,%rsp
  40052e:	89 7d ec             	mov    %edi,-0x14(%rbp)
  400531:	48 89 75 e0          	mov    %rsi,-0x20(%rbp)
  400535:	c7 45 fc 01 00 00 00 	movl   $0x1,-0x4(%rbp)
  40053c:	83 45 fc 01          	addl   $0x1,-0x4(%rbp)
  400540:	83 7d fc 01          	cmpl   $0x1,-0x4(%rbp)
  400544:	7e 06                	jle    40054c <main+0x26>
  400546:	83 6d fc 01          	subl   $0x1,-0x4(%rbp)
  40054a:	eb f4                	jmp    400540 <main+0x1a>
  40054c:	90                   	nop
  40054d:	bf 00 00 00 00       	mov    $0x0,%edi
  400552:	e8 b9 fe ff ff       	callq  400410 <exit@plt>
  400557:	66 0f 1f 84 00 00 00 	nopw   0x0(%rax,%rax,1)
  40055e:	00 00

首先从第一条指令开始看。。。我们可以看到它先把 rbp 的值 push 入栈,然后将 rsp 的值传给 rbp (Intel和AT&T格式有一些不同,AT&T格式的源操作数和目标操作数与Intel是相反的),然后将栈顶向下减少 0x20 个字节,之后将 disi 的值分别存入栈中,然后我们看到地址 400535 的这个位置将一个值 1 存入了栈中,并且栈向下减少了 0x4 个字节,由此可以推断这里应该是给一个变量赋值位 1,并且因为栈向下减小了 0x4 个字节,所以我们可以推断这个变量的类型应该是一个 4字节 类型的变量,在这里我们给他假定一个名字 "a",然后再看 40053c 这个地址执行了 add 指令,这里 add 指令让变量 a 增加了 1,再看 400540 这个地址他执行了 cmp 指令,这说明代码里应该有一个 if,来用变量 a 对比 1,具体对比条件我们要看下一条 jle 指令,从 jle 指令我们就能知道这个 cmp 的对比条件是小于等于,也就是说 a 是否小于等于 1,反过来说就是 1 是否大于 a,而且我们还从 jle 这个指令的功能码中知道这个变量 a 是一个有符号数,如果条件,成立,那么变量 a 将会减 1,然后 jmp 无条件跳转到 400540 这个地址,也就是说再执行这个地址的 cmp 指令,那么可以推断程序代码里应该有一个循环,而且 if 是嵌在循环里的,而且这个循环没有直接的循环条件,那我们可以推断出它应该是一个无限循环,退出循环必须依靠 if 来退出,那么我们可以推断出 ifelse,并且这个 else 里面应该有一个 break 用来跳出循环,然后的 40054d-400552 这两个地址位置显而易见是调用了 exit 系统调用,而这个时候我们也可以从 40054d 这个地址的 mov 指令的目标操作数 edi 得出返回值类型应该是 32位 的数,而这个数正是 0,至此我们的分析就完成了,但是这个也仅仅是一次很简单的实验,并不能代表什么,真正的逆向工程比这个要复杂得多得多!那么综上所述,我们可以写一个函数来把我们分析出来的代码写出来。

// 因为有exit系统调用的原因,
// 所以我们要包含stdlib.h这个头文件。
#include <stdlib.h>

// 刚刚我们分析了返回值的类型是32位的,一般情况下
// 在C语言当中int类型是32位的,所以返回值自然是int
// 函数名我们随便取一个,我们再代码当中并没有见到将
// 寄存器直接拿来用或者是pop指令,所以这个函数应该没有使用形参
int test(void)
{
    // 用我们刚刚假定的变量a
    // 我们也推断出它的类型应该是32位的,所以我们也使用int
    // 而且它有一个赋值的操作
    int a = 1;
    // 有一个加1的操作
    a++;
    // 有一个无限循环,并且循环里嵌入了一个if
    while (1) {
        // if判断a是否小于等于1
        if (a <= 1) {
            // a小于等于1的话退出循环
            break;
        }
        else {
            // 否则a减1
            a--;
        }
    }
    // 有exit系统调用,参数是0
    exit(0);
}

0x2 结尾

做这个实验的目的是为了巩固我自己所学的知识和帮助一些初学者认识一下到底什么是"逆向工程.