上山砍大树 发表于 2019-11-16 09:43

攻防世界 (reverse)no-strings-attached

1.查看文件类型:

(终于学会了贴图:)
发现是ELF格式的可执行文件。所以心中做好了一会儿要转战linux环境的心态。

2.IDA静态分析
放到ida中进行静态分析,查看main函数的反汇编代码:

通过简单地探索,发现除了authenticate()函数外,其他函数对自己没啥用。
所以直接进authenticate()函数进行分析。

可以看到注释我已经在代码段上标注了。
那么接下来就需要分析这个函数要做什么了:
这个函数大体意思就是将输入的字符串数据ws和存在于函数内部的字符串数据s2进行比对,然后再进行下一步操作。、

通过分析可知s2保存的就是flag。(猜也行)
分析s2就需要分析decrypt()函数。
那么decrypt()函数是这样的:

这个函数最后将返回的dest保存到s2中,而dest的值又需要参数s和a2来决定的。
我们暂时不分析while的算法,先回头看看参数s和a2到底是什么。



s和dword_8048A90都是函数中未定义的,所以点开后查看一下参数保存的是什么。
点开s和dword_8048A90发现字符串并不简单,存放在“.rodata(只读代码段)”很长而且没有规律。可以想象一下,参数本身就很复杂,那么参数传递给函数进行处理的过程那么就更加复杂。所以通过参数和对参数的算法操作来获得flag其实是很困难的。
不过我们可以不用像个铁憨憨去分析decrypt(),因为参数和算法都是已经定义好的跟输入没关系,那么函数调用完成后返回的dest会保存在哪里,我们直接找到程序运行时保存dest的地址然后dump出来分析不就ok了?这样就不用做头铁娃了!
带着这个快乐的想法,我们就直接去看看decrypt()的汇编代码:
text:08048658 ; int __cdecl decrypt(wchar_t *s, wchar_t *)
.text:08048658               public decrypt
.text:08048658 decrypt         proc near               ; CODE XREF: authenticate+18↓p
.text:08048658
.text:08048658 var_1C          = dword ptr -1Ch
.text:08048658 var_18          = dword ptr -18h
.text:08048658 var_14          = dword ptr -14h
.text:08048658 var_10          = dword ptr -10h
.text:08048658 dest            = dword ptr -0Ch
.text:08048658 s               = dword ptr8
.text:08048658 arg_4         = dword ptr0Ch
.text:08048658
.text:08048658 ; __unwind {
.text:08048658               push    ebp
.text:08048659               mov   ebp, esp
.text:0804865B               push    ebx
.text:0804865C               sub   esp, 34h
.text:0804865F               mov   eax,
.text:08048662               mov   , eax      ; s
.text:08048665               call    _wcslen
.text:0804866A               mov   , eax
.text:0804866D               mov   eax,
.text:08048670               mov   , eax      ; s
.text:08048673               call    _wcslen
.text:08048678               mov   , eax
.text:0804867B               mov   ebx,
.text:0804867E               mov   eax,
.text:08048681               mov   , eax      ; s
.text:08048684               call    _wcslen
.text:08048689               add   eax, 1
.text:0804868C               mov   , eax      ; size
.text:0804868F               call    _malloc
.text:08048694               mov   , eax
.text:08048697               mov   , ebx    ; src
.text:0804869B               mov   eax,             //从这里可以发现dest保存的值传递给了寄存器eax
.text:0804869E               mov   , eax      ; dest
.text:080486A1               call    _wcscpy
.text:080486A6               mov   , 0
.text:080486AD               jmp   short loc_80486F7
.text:080486AF ; --------------------------------------------------------------------------

通过汇编代码,了解到寄存器eax保存dest的值后返回给s2。
我们刚刚头大的事情仿佛迎刃而解,大体得到flag的方法就是,直接动态调试程序,然后在decrypt()处下断点单步执行到保存dest的值于eax代码后,查看eax保存的值就可以了。

而我们前面也分析了,此文件是ELF格式,所以我们要暂时抛弃微软,进入linux分析。


4.gdb调试
自己百度gdb命令及用途,不用都记住,记住几个本次需要执行用得到的命令就行了,以后用到再说。
而我们需要做什么呢:
1.在decrypt()处下断点。
2.单步执行decrypt()函数。
3.执行完毕后查看寄存器eax保存的值。

实现此想法需要执行的代码:
1.在decrypt()处下断点。
b decrypt
2.单步执行decrypt()(断点处)函数。
r
3.执行一行源程序代码,此行代码中的函数调用也一并执行,就是执行decrypt()函数。
n
4.此时decrypt()执行完毕,然后查看寄存器保存的内容即可。
i r
5.查看内存地址(eax)保存的内容。
x/5sw $eax
----------------------------------------------------------------------
第五条指令中各个参数含义:
x:examine–>检测内存地址中保存的值
5:显示5行目标数据
s:以字符串形式打印
w:以双字打印
---------------------------------------------------------------------------
然后就会打印出:
0x8ca9800:        U"9447{you_are_an_international_mystery}"
0x8ca989c:        U"W\001\xf7a161e8\xf7a161ea\xf7a161ec\xf7a161ee\xf7a161f0\xf7a161f2\xf7a161f4\xf7a161f6\xf7a161f8\xf7a161fa\001\xf7a16200\xf7a16204\xf7a16208\xf7a1620c\xf7a16210\xf7a16214\xf7a16218\xf7a1621c\xf7a16220\xf7a16224\xf7a16228\xf7a1622a\xf7a1622c\xf7a1622e\xf7a16230\xf7a16232\xf7a16234\xf7a16236\xf7a16238\xf7a1623a\060\061\062\063\064\065\066\067\070\071\x175a\xf7a16268\xf7a1bfd0\xf7a27aa0\xf7a2d808\001\xf7a3ff4c"
0x8ca9968:        U"\xf7a3ff54"
0x8ca9970:        U""
0x8ca9974:        U"\xf7a3ff7c\xf7a408b8\xf7a41234\xf7a42a74\xf7a42cec\xf7a42f64\xf7a4329c\xf7a45194\xf7a4708c\xf7a473c4\xf7a4767c\xf7a48f74\xf7a4a7b4\xf7a4b8e4\xf7a4c854\xf7a4cb6c\xf7a52988\xf7a57ba4\021\x435f687a\x54552e4e\x382d46\021\x435f687a\x54552e4e\x382d46!\x8ca9a00\001\x8ca9a80\001"
自己看看哪个是flag吧。:)


个人小结:

[*]实践很重要
[*]“.rodata(只读数据read only data)”段存放的是只读数据,比如字符串常量、全局const变量。
[*]多思考,少头铁。
[*]写writeup的时候把做题时发现问题解决问题的思路先写一下,准备好注释和截图,按照思路一步步写听起来还是挺有逻辑的。
[*]实践相当重要!

上山砍大树 发表于 2019-11-16 19:40

无敌VS小嘟嘟 发表于 2019-11-16 10:21
感谢分享受教了

希望大家都会变得越来越好!由于我第一个帖子写的逻辑不是很流畅,所以写这个writeup之前我就把思路先整理一遍了然后按照思路写的writeup,再发到论坛,希望这样做能对自己和想学习的人有所帮助吧。我也是小白,刚走这条路,难免会犯错,谢谢各位支持了!{:1_919:}

shuijq 发表于 2019-11-17 11:32

被违规无能清零,以后就少回复,贴脸还是罢了。被违规无能清零,以后就少回复,贴脸还是罢了。被违规无能清零,以后就少回复,贴脸还是罢了。

三国三 发表于 2019-11-16 10:30

感谢分享

god321 发表于 2019-11-16 10:41

真心特别感谢楼主分享

shghe 发表于 2019-11-16 10:42

感谢分享 认真学习~~~~~~~

qws1855 发表于 2019-11-16 10:56

感谢分享

sd952202 发表于 2019-11-16 10:59

感谢楼主无私分享~

whofly 发表于 2019-11-16 11:08

你太厉害了 向你学习 逆向技术

sunyixin745 发表于 2019-11-16 12:30

感谢楼主无私分享~

isver2 发表于 2019-11-16 13:40

有用啊,我收藏了先。

SuenDanny 发表于 2019-11-16 15:58

佩服佩服
页: [1] 2 3 4
查看完整版本: 攻防世界 (reverse)no-strings-attached