安云网 - AnYun.ORG | 专注于网络信息收集、网络数据分享、网络安全研究、网络各种猎奇八卦。
当前位置: 安云网 > 技术关注 > 逆向工程 > 一次ELF文件的解构之旅

一次ELF文件的解构之旅

时间:2015-05-05来源:黑客志 作者:黑客志点击:
ZZ 黑客志 http://heikezhi.com/2011/09/15/hackme-deconstructing-an-elf-file/ 一个朋友最近发给我一个他编写的据称很难破解的程序,让我找出它的密码,经过几个小时的Hacking,我顺利找到了密码,并且在这个过程中,除了学到许多新技术之外,

ZZ 黑客志 

//ANYUN.ORG

http://heikezhi.com/2011/09/15/hackme-deconstructing-an-elf-file/ //内容来自AnYun.ORG

一个朋友最近发给我一个他编写的据称很难破解的程序,让我找出它的密码,经过几个小时的Hacking,我顺利找到了密码,并且在这个过程中,除了学到许多新技术之外,还有几个特别有意思的地方,我认为值得写篇文章与大家分享下。 //copyright AnYun.ORG

答应接受他的挑战几分钟后,我就收到了一个名叫“hackme"的二进制文件,感兴趣的同学可以先下载这个文件自己尝试下,然后再回头来看看这篇文章,如果你在破解过程中有什么收获,记得发封[hackme]打头的邮件到manohar dot vanga at gmail dot com和我分享哦,另外,你也可以参加Hacker News上到讨论

//copyright AnYun.ORG

试试手气 //安云网咨询系统

首先,我随机测试了一组密码,和我想的一样,失败,下面是我得到的消息:

//安云网,anyun.org

$ ./hackme
Password, please? password
Oops..

//内容来自安云网

有趣的是,当我试图通过GDB调试这个文件时,我得到了下面这句特别的欢迎词:

//ANYUN.ORG

$ gdb ./hackme
Reading symbols from /tmp/hack/hackme...(no
debugging symbols found)...done.
(gdb) r
Starting program: ./hackme
Fuck off! no debuggers! //copyright AnYun.ORG

Program exited with code 0364.
(gdb) //安云网咨询系统

ptrace也是同样的结果: //本文来自安云网

$ strace ./hackme
execve("./hackme", ["./hackme"], [/* 41 vars */]) = 0
brk(0) = 0x9016000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
... snip ...
ptrace(PTRACE_TRACEME, 0, 0, 0) = -1 EPERM (Operation not permitted)
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 3), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb783e000
write(1, "Fuck off! no debuggers!\n", 24Fuck off! no debuggers!) = 24
_exit(2543604) = ? //内容来自AnYun.ORG

明知故犯 //内容来自AnYun.ORG

尽管密码以明文形式保存的可能性接近于0,我还是决定试试 //安云网,anyun.org

首先,我检查了这个二进制文件中的符号信息有没有被抽取(strip)过:

//本文来自安云网

$ file hackme
hackme: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically
linked (uses shared libs), for GNU/Linux 2.6.27, stripped

//本文来自安云网

很不幸,这是一个抽取过的程序,这条路走不通,GDB对于抽取过的二进制基本不起作用,于是我决定看看这个二进制文件中包含的明文字符串信息:

//安云网咨询系统

$ strings hackme
/lib/ld-linux.so.2
libdl.so.2
__gmon_start__
_Jv_RegisterClasses
dlopen
dlsym
libc.so.6
_IO_stdin_used
__libc_start_main
random
GLIBC_2.1
GLIBC_2.0
PTRh
QVhE
[^Ph
[^_]
8%':!06!
%!'460
&64;3
%'<;!3
UWVS
[^_]
Fuck off! no debuggers!
Password, please?
Congratulations!
Oops..

//copyright AnYun.ORG

我尝试了所有的明文字符串作为密码,不对,很自然的结果,不过这个输出还是提供了一些有用的信息,至少我知道了输入正确密码后我会看到什么,那就是这句”Congratulations!",另外,它还包含了字符串"libc.so.6",这很可疑,不过看了ltrace的输出,我就明白怎么回事了: //安云网咨询系统

view plaincopy to clipboardprint? //本文来自安云网

  1. $ ltrace ./hackme

    //安云网,anyun.org

  2. __libc_start_main(0x8048645, 1, 0xbfb48a04, 0x80486b0, 0x8048720 //安云网咨询系统

  3. <unfinished ...> //安云网咨询系统

  4. dlopen("/lib/libc.so.6", 2)

    //本文来自安云网

  5. = 0xb7757ae0 //安云网,anyun.org

  6. dlsym(0xb7757ae0, "ptrace") //本文来自安云网

  7. = 0x00eddf40

    //安云网咨询系统

  8. dlsym(0xb7757ae0, "scanf") //安云网,anyun.org

  9. = 0x00e621a0 //copyright AnYun.ORG

  10. dlsym(0xb7757ae0, "printf")

    //内容来自AnYun.ORG

  11. = 0x00e5baa0 //ANYUN.ORG

  12. Fuck off! no debuggers!

    //内容来自安云网

  13. +++ exited (status 244) +++

    //安云网,anyun.org


//copyright AnYun.ORG

[ruby] view plaincopy //本文来自安云网

  1. $ ltrace ./hackme   //copyright AnYun.ORG

  2. __libc_start_main(0x8048645, 1, 0xbfb48a04, 0x80486b0, 0x8048720   //安云网,anyun.org

  3. <unfinished ...>  

    //内容来自安云网

  4. dlopen("/lib/libc.so.6", 2)  

    //ANYUN.ORG

  5. = 0xb7757ae0   //copyright AnYun.ORG

  6. dlsym(0xb7757ae0, "ptrace")   //内容来自安云网

  7. = 0x00eddf40   //ANYUN.ORG

  8. dlsym(0xb7757ae0, "scanf")   //安云网,anyun.org

  9. = 0x00e621a0   //copyright AnYun.ORG

  10. dlsym(0xb7757ae0, "printf")  

    //ANYUN.ORG

  11. = 0x00e5baa0  

    //内容来自安云网

  12. Fuck off! no debuggers!   //安云网咨询系统

  13. +++ exited (status 244) +++   //安云网,anyun.org


//本文来自安云网

这里我们再次看到了那句讨人厌的欢迎词,但是不要紧,前面的信息已经足可以说明问题了,libc是通过dlopen动态连接的,而ptrace,scanf以及printf函数的地址都是通过dlsym取得的,很卑鄙的手段!

//安云网,anyun.org

尽管如此,更刺激的是strings的输出显示这个程序调用了random()函数,但是因为它的密码是不变的,所以对random的调用应该是没有经过seed的,我们稍后再来关注这个。 //内容来自安云网

strings的输出同样解释了这个程序是如何阻止调试的,当你在ptrace环境中调用ptrace函数时,它让ptrace返回了-1.

//安云网咨询系统

这个问题可以很容易的通过LD_PRELOAD环境变量来解决,LD_PRELOAD可以包含一个自定义的动态库列表,这个列表中的动态库可以在要调试的可执行文件执行之前预先加载到内存中,这可以很容易的阻止可执行文件调用你不希望它去调用的函数,我很快就写了一个简单的包含我们想要的ptrace函数的新文件: //内容来自安云网

  1. /* fake ptrace() */ //安云网咨询系统

  2. #include <stdio.h>

    //安云网咨询系统

  3. //ANYUN.ORG

  4. long ptrace(int x, int y, int z)

    //内容来自AnYun.ORG

  5. { //本文来自安云网

  6. printf("B-)\n");

    //copyright AnYun.ORG

  7. return 0; //ANYUN.ORG

  8. }

    //本文来自安云网


//内容来自AnYun.ORG

...然后编译: //本文来自安云网

gcc -shared -fPIC -o fake.so fake.c

//安云网,anyun.org

现在使用strace并加上LD_PRELOAD变量来执行这个程序,可以看到,我们的ptrace函数已经起作用了:

//ANYUN.ORG

[ruby] view plaincopy

//本文来自安云网

  1. $ strace -E LD_PRELOAD=./fake.so ./hackme  

    //本文来自安云网

  2. execve("./hackme", ["./hackme"], [/* 24 vars */]) = 0  

    //ANYUN.ORG

  3. brk(0)                                  = 0x9727000   //ANYUN.ORG

  4. access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)  

    //内容来自AnYun.ORG

  5. mmap2(NULL, 8192, PROT_READ|PROT_WRITE,  

    //安云网,anyun.org

  6. MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb78a6000   //ANYUN.ORG

  7. open("./fake", O_RDONLY)                = 3   //内容来自AnYun.ORG

  8. read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\240\3\0\0004\0\0\0"...,512) = 512  

    //本文来自安云网

  9. ... snip ...  

    //安云网,anyun.org

  10. MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb78a1000   //内容来自AnYun.ORG

  11. write(1, "Password, please? ", 18Password, please? ) = 18  

    //内容来自AnYun.ORG

  12. read(0, password "password\n", 1024)    = 9   //内容来自安云网

  13. write(1, "Oops..\n", 7Oops..)           = 7  

    //本文来自安云网

  14. exit_group(7)                           = ?   //安云网,anyun.org


//内容来自AnYun.ORG

看起来存放密码的buffer只有1024字节,我尝试了缓冲区溢出但是遇到了栈地址混淆(Stack randomization)(当然如果我没记错,这也是有办法可以关掉的),只是对于一个慵懒的星期五来说,这过于麻烦了一点,更重要的是,我的目的并不是破解这个程序,我只是想得到那个密码。 //安云网,anyun.org

现在看起来我只有一条路可以走了,那就是逆向这个程序,尽管我实在不愿意在星期五的下午做这种事。但是这种对Geek的挑战还是轻松战胜了我每天都有的懒惰,所以我开始了我的反汇编之旅。 //ANYUN.ORG

反汇编

//ANYUN.ORG

我首先从objdump的输出开始入手(建议你在一个新tab中执行这个命令以便我们更好的继续) //内容来自AnYun.ORG

$ objdump -D ./hackme > out.asm //内容来自安云网

一个抽取过得二进制文件的汇编如我想象的一样,那不是一般的混乱,我需要从中快速的找出密码的生成逻辑,从上面的运行结果,我们知道,生成密码的代码段应该是在“Password,please?”这个字符串与“Oops..."字符串之间,于是我首先需要做的就是定位这些字符串。"Password please?"中的“Pa”字符转成16进制就是50后面跟上61,简单的搜索后,我就定位到了这个字符串:

//ANYUN.ORG

  1. $ grep "50 61" objdumpout.txt

    //内容来自AnYun.ORG

  2. 8048798: 00 50 61 add %dl,0x61(%eax) //copyright AnYun.ORG

[ruby] view plaincopy

//本文来自安云网

  1. $ grep "50 61" objdumpout.txt  

    //ANYUN.ORG

  2.  8048798:       00 50 61              add    %dl,0x61(%eax)  //安云网咨询系统


//copyright AnYun.ORG

这个字符串的地址就是0x8048799(因为它前面还有一个无效字符),搜索这个地址:

//内容来自AnYun.ORG


//内容来自安云网

  1. 804859d: 68 99 87 04 08 push $0x8048799 //copyright AnYun.ORG

  2. 80485a2: ff 15 94 99 04 08 call *0x8049994 //内容来自安云网

    //安云网,anyun.org


//ANYUN.ORG

  1. 804859d:       68 99 87 04 08          push   $0x8048799   //内容来自安云网

  2. 80485a2:       ff 15 94 99 04 08       call   *0x8049994 

    //内容来自安云网


//本文来自安云网

很好!它将这个地址压入了堆栈,并调用了一个函数,我假设这个变量保存的就是dlsym返回的printf函数的地址。

//安云网,anyun.org

现在,我需要找到"Oops..."字符串,同样的方法: //安云网咨询系统

[ruby] view plaincopy

//本文来自安云网

  1. 8048633:       68 c1 87 04 08          push   $0x80487c1  

    //内容来自AnYun.ORG

  2. 8048638:       ff d0                   call   *%eax  

    //copyright AnYun.ORG


//内容来自安云网

同样,我也顺手标注了下“Congratulations”字符串的位置,最后,代码看起来是下面的样子:

//内容来自AnYun.ORG


//安云网咨询系统

[ruby] view plaincopy //安云网,anyun.org

  1. # The "Password, please?" message is being printed here   //内容来自AnYun.ORG

  2. 804859d:       68 99 87 04 08          push   $0x8048799  

    //copyright AnYun.ORG

  3. 80485a2:       ff 15 94 99 04 08       call   *0x8049994   //安云网,anyun.org

  4. 80485a8:       8d 45 84                lea    -0x7c(%ebp),%eax   //安云网咨询系统

  5. ... snip ...  

    //安云网,anyun.org

  6. 8048626:       83 ec 0c                sub    $0xc,%esp  

    //安云网咨询系统

  7. # The "Congratulations!" message is being printed here   //内容来自AnYun.ORG

  8. 8048629:       68 af 87 04 08          push   $0x80487af  

    //copyright AnYun.ORG

  9. 804862e:       eb 08                   jmp    8048638 <dlopen@plt+0x268>   //内容来自安云网

  10. 8048630:       83 ec 0c                sub    $0xc,%esp  

    //内容来自安云网

  11. # The "Oops.." message is being printed here   //ANYUN.ORG

  12. 8048633:       68 c1 87 04 08          push   $0x80487c1   //内容来自AnYun.ORG

  13. 8048638:       ff d0                   call   *%eax   //内容来自AnYun.ORG

我很快标记好了这段汇编程序,所以我可以回忆起来我最终是怎么找到答案的: //安云网咨询系统

//ANYUN.ORG

  1. 804859d:        68 99 87 04 08          push   $0x8048799   //安云网,anyun.org

  2. 80485a2:       ff 15 94 99 04 08       call   *0x8049994  

    //安云网咨询系统

  3. # The "Password, please?" message is being printed here  

    //本文来自安云网

  4.    //安云网,anyun.org

  5. 80485a8:       8d 45 84                lea    -0x7c(%ebp),%eax  

    //安云网,anyun.org

  6. # This is probably the address of the password buffer.   //内容来自安云网

  7.    //ANYUN.ORG

  8. 80485ab:       5b                      pop    %ebx   //内容来自AnYun.ORG

  9. 80485ac:       5e                      pop    %esi   //安云网咨询系统

  10.   

    //安云网咨询系统

  11. 80485ad:       50                      push   %eax   //copyright AnYun.ORG

  12. 80485ae:       68 ac 87 04 08          push   $0x80487ac  

    //内容来自安云网

  13. 80485b3:       ff 15 90 99 04 08       call   *0x8049990  

    //ANYUN.ORG

  14. 80485b9:       83 c4 10                add    $0x10,%esp   //本文来自安云网

  15. # Push the password buffer and the string "%s" onto the stack and call scanf  

    //安云网,anyun.org

  16.   

    //安云网,anyun.org

  17. 80485bc:       31 c0                   xor    %eax,%eax   //内容来自安云网

  18. # Clear EAX.   //安云网咨询系统

  19.   

    //内容来自AnYun.ORG

  20. 80485be:       eb 01                   jmp    80485c1 <dlopen@plt+0x1f1>  

    //本文来自安云网

  21. 80485c0: 40                      inc    %eax   //安云网,anyun.org

  22. 80485c1:  80 7c 05 84 00          cmpb   $0x0,-0x7c(%ebp,%eax,1)   //安云网,anyun.org

  23. 80485c6:       75 f8                   jne    80485c0 <dlopen@plt+0x1f0>  

    //安云网,anyun.org

  24. # Find the string length of the password we entered. Return value in EAX.   //安云网咨询系统

  25.    //内容来自AnYun.ORG

  26. 80485c8:       31 db                   xor    %ebx,%ebx  

    //安云网,anyun.org

  27.   

    //内容来自AnYun.ORG

  28. 80485ca:       83 f8 13                cmp    $0x13,%eax   //安云网咨询系统

  29. 80485cd:       0f 94 c3                sete   %bl   //copyright AnYun.ORG

  30. # Hmm! If the strlen(buf) != 0x13) BL is set to 1! We have our first hint!   //内容来自安云网

  31.    //内容来自安云网




  32. 80485d0:       be 0a 00 00 00          mov    $0xa,%esi  

    //安云网咨询系统

  33. # Move integer 10 into ESI. This is the start of a loop that runs 10 times.  

    //ANYUN.ORG

  34.    //内容来自安云网

  35. 80485d5:       e8 b6 fd ff ff          call   8048390 <random@plt>   //安云网,anyun.org

  36. # Call random(). Return value in EAX   //内容来自AnYun.ORG

  37.   

    //内容来自安云网

  38. 80485da:       b9 13 00 00 00          mov    $0x13,%ecx  

    //copyright AnYun.ORG

  39. 80485df:       99                      cltd  

    //ANYUN.ORG

  40. 80485e0:       f7 f9                   idiv   %ecx  

    //内容来自安云网

  41. # Divide the random number in EAX with 19. EAX is quotient, EDX is remainder.  

    //ANYUN.ORG

  42.    //内容来自安云网

  43. 80485e2:       31 c0                   xor    %eax,%eax  

    //内容来自AnYun.ORG

  44. # Throw away quotient.   //安云网,anyun.org

  45.   

    //copyright AnYun.ORG

  46. 80485e4:       8a 8a 9c 86 04 08       mov    0x804869c(%edx),%cl   //安云网咨询系统

  47. # Hmm. That address looks like a lookup table of some sort.   //安云网,anyun.org

  48. # The operation is basically doing "CL = table[remainder]".   //安云网咨询系统

  49. # Since remainder can't be more that 19, I dump the first 19 bytes of this  

    //本文来自安云网

  50. # address:  

    //copyright AnYun.ORG

  51. #     0xfb, 0x4c, 0x8d, 0x58, 0x0f, 0xd4, 0xe8, 0x94, 0x98, 0xee,  

    //ANYUN.ORG

  52. #     0x6b, 0x18, 0x30, 0xe0, 0x55, 0xc5, 0x28, 0x0e   //ANYUN.ORG

  53.    //copyright AnYun.ORG

  54. 80485ea:       0f b6 7c 15 84          movzbl -0x7c(%ebp,%edx,1),%edi   //copyright AnYun.ORG

  55. # This basically does EDI = password[remainder]   //copyright AnYun.ORG

  56.   

    //本文来自安云网

  57. 80485ef:       42                      inc    %edx  

    //安云网,anyun.org

  58. 80485f0:       89 95 74 ff ff ff       mov    %edx,-0x8c(%ebp)  

    //安云网,anyun.org

  59. # Increment the remainder and store it in another variable   //安云网咨询系统

  60.   

    //安云网,anyun.org

  61. 80485f6:       31 d2                   xor    %edx,%edx  

    //内容来自AnYun.ORG

  62. 80485f8:       eb 0c                   jmp    8048606 <dlopen@plt+0x236>  

    //本文来自安云网

  63. 80485fa:  69 c0 8d 78 01 6d       imul   $0x6d01788d,%eax,%eax  

    //ANYUN.ORG

  64. 8048600:       42                      inc    %edx  

    //内容来自安云网

  65. 8048601:       05 39 30 00 00          add    $0x3039,%eax  

    //copyright AnYun.ORG

  66. 8048606: 3b 95 74 ff ff ff       cmp    -0x8c(%ebp),%edx   //copyright AnYun.ORG

  67. 804860c:       7c ec                   jl     80485fa <dlopen@plt+0x22a>   //安云网,anyun.org

  68. # This is a weird loop. It seems to be a pseudorandom generator.   //内容来自AnYun.ORG

  69. # The loop runs while a counter is less than the incremented remainder above.  

    //ANYUN.ORG

  70. # Inside, it's doing the following (remember eax was cleared above to 0):  

    //安云网咨询系统

  71. #     eax = eax * 0x6d01788d //This is a prime number according to Wolfram Alpha   //本文来自安云网

  72. #     eax += 0x3039 // 12345 in decimal  

    //ANYUN.ORG

  73. # That is an unseeded (or seeded to 0) pseudorandom generator! Nice but  

    //本文来自安云网

  74. # pointless as it is unseeded.   //安云网,anyun.org

  75.    //安云网咨询系统

  76. 804860e:       31 f8                   xor    %edi,%eax   //ANYUN.ORG

  77. # XOR the pseudorandom value above with password[remainder] as stored above   //安云网咨询系统

  78.   

    //copyright AnYun.ORG

  79. 8048610:       38 c1                   cmp    %al,%cl  

    //安云网咨询系统

  80. # Compare the lower byte of the XOR'ed result with the lookup table entry stored in CL   //安云网咨询系统

  81.   

    //内容来自安云网

  82. 8048612:       b8 00 00 00 00          mov    $0x0,%eax   //本文来自安云网

  83. 8048617:       0f 45 d8                cmovne %eax,%ebx  

    //内容来自AnYun.ORG

  84. # If the lower byte of the XOR is not equal to the lookup table entry set EBX=0  

    //ANYUN.ORG

  85.   

    //内容来自AnYun.ORG

  86. 804861a:       4e                      dec    %esi   //安云网,anyun.org

  87. 804861b:       75 b8                   jne    80485d5 <dlopen@plt+0x205>   //内容来自安云网

  88. # Decrement the main loop counter (the one that runs 10 times) and jump  

    //安云网咨询系统

  89. # if more iterations are left  

    //copyright AnYun.ORG

  90.    //copyright AnYun.ORG

  91. 804861d:       85 db                   test   %ebx,%ebx   //内容来自AnYun.ORG

  92. 804861f:       a1 94 99 04 08          mov    0x8049994,%eax  

    //安云网,anyun.org

  93. 8048624:       74 0a                   je     8048630 <dlopen@plt+0x260>   //内容来自安云网

  94. # At last! Jump to the failure message (past the congratulations) if EBX is 0!  

    //本文来自安云网

  95. # EBX should be non-zero in order to print the congratulations message!   //内容来自AnYun.ORG

  96.    //ANYUN.ORG

  97. 8048626:       83 ec 0c                sub    $0xc,%esp   //安云网,anyun.org

  98.    //内容来自AnYun.ORG

  99. # The "Congratulations!" message is being printed here  

    //内容来自AnYun.ORG

  100. 8048629:       68 af 87 04 08          push   $0x80487af  

    //本文来自安云网

  101. 804862e:       eb 08                   jmp    8048638 <dlopen@plt+0x268>   //内容来自安云网

  102. 8048630:       83 ec 0c                sub    $0xc,%esp  

    //安云网咨询系统

  103.   

    //本文来自安云网

  104. # The "Oops.." message is being printed here   //安云网,anyun.org

  105. 8048633:       68 c1 87 04 08          push   $0x80487c1   //内容来自安云网

  106. 8048638:       ff d0                   call   *%eax   //安云网,anyun.org


//ANYUN.ORG

哇!还不坏,情况没我想的那么糟,将这些生成密码的汇编转换成C代码并进行测试花费了我一些时间,最后我得到了下面的C代码:asd ads //内容来自安云网

  1. #include <stdio.h> //ANYUN.ORG

  2. #include <string.h>

    //本文来自安云网

  3. //内容来自AnYun.ORG

  4. int main() //安云网,anyun.org

  5. { //安云网咨询系统

  6. int i, j, edi;

    //内容来自AnYun.ORG

  7. char buf[50], ch;

    //copyright AnYun.ORG

  8. char out[50];

    //copyright AnYun.ORG

  9. unsigned char check;

    //本文来自安云网

  10. int ret = 0, val, len, rem;

    //内容来自AnYun.ORG

  11. int magic;

    //内容来自AnYun.ORG

  12. int k;

    //内容来自安云网

  13. unsigned char arr[] = {0x6a, 0xfb, 0x4c, 0x8d, 0x58, 0x0f, 0xd4, 0xe8,

    //安云网咨询系统

  14. 0x94, 0x98, 0xee, 0x6b, 0x18, 0x30, 0xe0, 0x55, 0xc5, 0x28,

    //安云网,anyun.org

  15. 0x0e};

    //内容来自AnYun.ORG

  16. //安云网咨询系统

  17. for (i = 0; i < 19; i++) //内容来自安云网

  18. out[i] = 'x';

    //内容来自AnYun.ORG

  19. out[i] = '\0'; //copyright AnYun.ORG

  20. //安云网咨询系统

  21. for (i = 10; i > 0; i--) {

    //内容来自安云网

  22. int m2;

    //copyright AnYun.ORG

  23. //内容来自AnYun.ORG

  24. val = random(); //ANYUN.ORG

  25. rem = val%19;

    //ANYUN.ORG

  26. check = arr[rem] & 0xff;

    //ANYUN.ORG

  27. ch = buf[rem++]; //安云网咨询系统

  28. //内容来自AnYun.ORG

  29. j = 0; //安云网,anyun.org

  30. magic = 0; //安云网,anyun.org

  31. printf("rem = %d\n", rem);

    //内容来自AnYun.ORG

  32. while (j < rem) {

    //ANYUN.ORG

  33. magic *= 1828812941;

    //安云网,anyun.org

  34. magic += 12345; //内容来自AnYun.ORG

  35. j++;

    //ANYUN.ORG

  36. }

    //安云网咨询系统

  37. m2 = magic; //安云网咨询系统

  38. //安云网,anyun.org

  39. magic ^= ch;

    //本文来自安云网

  40. out[rem - 1] = (m2 & 0xff) ^ (check & 0xff)); //内容来自AnYun.ORG

  41. }

    //本文来自安云网

  42. printf("Password: %s\n", out); //内容来自AnYun.ORG

  43. } //内容来自AnYun.ORG


//内容来自AnYun.ORG

现在让我们来运行看看:

//copyright AnYun.ORG

$ ./decompiled
rem = 3
rem = 16
rem = 4
rem = 4
rem = 11
rem = 9
rem = 11
rem = 12
rem = 3
rem = 8
Password: xxsaxxxpexYoxxxexxx

//本文来自安云网

那个可执行文件只执行了10次循环,它会持续的检查密码的偏移,而密码中只有那些没有标记成x的字符会起作用(我故意将它显示成了这样) //copyright AnYun.ORG

现在,到了最激动人心的时刻了,让我们来再次运行hackme试试看: //本文来自安云网

$ ./hackme
Password, please? xxsaxxxpexYoxxxexxx
Congratulations!

//内容来自安云网

哈哈,搞定! //安云网咨询系统

结论

//内容来自安云网

那么我从中学到了什么呢?

//ANYUN.ORG

了解你的工具 //本文来自安云网

我可以很容易的基于过去的知识和经验为我遇到的问题选择最合适的工具,你对你的工具了解越多,你就越有可能更快的发现问题的本质(在这个例子中,就是那段反汇编后的密码生成代码)。

//安云网咨询系统

不断尝试 //安云网咨询系统

尽管我知道我不大可能轻松破解这个程序,但我还是尝试了所有这些简单的方法,尽管它们没有提供太多有用的信息,但它们至少帮我排除了一些选项,为我的后续工作扫清了道路。

//安云网咨询系统

掌握汇编 //copyright AnYun.ORG

机器指令很难掌握,在这个过程中,我不知道多少次翻出Intel的汇编手册以帮助我理解这些指令的含义,尽管如此,我还是强烈的推荐你们学习GNU的汇编语法,而不是原始汇编,我对Intel的汇编语法很熟悉(比如NASM),但是对于GAS的语法(也就是AT&T的语法),我发现这篇文章这篇文章都很有帮助。

//ANYUN.ORG

对于这个程序本身的一些看法: //内容来自AnYun.ORG

  • 只检查密码的一部分看起来是行不通的,当然全部检查也不会让破解过程困难多少(补充:程序的作者后来告诉我他将主循环设为10次本来是为了调试的,但是后来忘记改回来了)

    //内容来自安云网

  • 随机数一开始可能是想吓吓我,但是,因为要保证结果的一致性,所以它不能根据种子来产生随机数,如果我有一个不同版本的libc,同时它有一个不同的random实现,那么恐怕作者最初设定的密码也会失效。 //copyright AnYun.ORG

  • 实际上真正的密码是“SesameOpenYourself!”!但是我测试了几个变体,也是有效的,比如“NasaJeeperYouShelby”

    //安云网咨询系统

最后,不管怎么说,这是个愉快的星期五下午,再一次提醒,欢迎发送评论到我的邮箱:manohar dot vanga at gmail dot com,记得在主题中加入[hackme]。 //内容来自安云网

你可以在这里下载全部文件

//copyright AnYun.ORG


//ANYUN.ORG


//copyright AnYun.ORG


//copyright AnYun.ORG


//ANYUN.ORG

顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
验证码: 点击我更换图片
相关内容
推荐内容