Rootkit123 发表于 2021-5-30 13:53

2012DASCTF逆向第一题汇编分析

第一次在论坛发帖,多有不慎,还请多多包涵,如有错误,还请不吝赐教!
这个题其实如果用ida7.5来反编译其实很简单,但是这里我是ida7.0,多少有些问题,所以直接在汇编层面来解决,顺便锻炼了我的汇编阅读能力,本人技术很菜,如有错误,还望师傅们不吝赐教,谢谢!
先看到main函数,找到经过判断之后的关键函数:

这里看到传进来三个参数,但是在函数里面没有 用的这些参数,而且还有一些奇观的函数,这里判断应该是低版本的ida反编译了高版本的编译器编译的程序,所以直接在gdb里面看到汇编代码,直接对汇编进行分析。
先看到这是main函数在调用关键函数的时候的汇编代码

不难看出他只传进去了两个参数,这里看到是我输入,$rsi里面是给出的加密字符串【DASCTF{5c715207e3abed7dfb7c8ea9c82d0e29}】
看到关键函数的汇编:

这里直接把我参数的内容保存下来,【rbp-0x38】是我的输入。
往下看:

这里解析出来了我ida里面没有解析出来的函数,我们把ida修补下:
修完的效果。
接下来就是确定关键函数的参数和这些局部变量的关系,以此来找到关键操作:
首先看前两行直到我们的输入被保存在了两个局部变量里面,然后看到:

相当于是【=malloc(0x80)   =我的输入】
所以我的输入的放在了rbp-0x20指向的空间里

因为函数调用规则是从右到左,所以这里应该是:

rsi=//去除flag头的flag
rdi=//输入
strcpy(rdi,rsi);

这里看到有一个,这里是把我输入的flag的头去了,就剩中间的东西了
根据关键的异或,往上往下找到循环异或的代码块:

对其进行分析
```
0x00005555555553ca <+156>:      mov    eax,DWORD PTR
   0x00005555555553cd <+159>:      movsxd rdx,eax                                        #这里eax是计数器i,放到rdx的低位
   0x00005555555553d0 <+162>:      mov    rax,QWORD PTR #将输入放进rax里面
   0x00005555555553d4 <+166>:      add    rax,rdx                                        #rax+rdx就相当于array的意思,基地址+偏移
   0x00005555555553d7 <+169>:      movzxesi,BYTE PTR                 #给esi赋值,后面异或用到
   0x00005555555553da <+172>:      mov    rdx,QWORD PTR # 0x555555558010 <unk_6984657>
   0x00005555555553e1 <+179>:      mov    eax,DWORD PTR
   0x00005555555553e4 <+182>:      cdqe   
   0x00005555555553e6 <+184>:      add    rax,rdx                                        #和上面一样,这里是【偏移量+段地址】
   0x00005555555553e9 <+187>:      movzxecx,BYTE PTR                 #较小的值拷贝给大的值,剩下0填充例如【0x00000xxxx】
   0x00005555555553ec <+190>:      mov    eax,DWORD PTR
   0x00005555555553ef <+193>:      movsxd rdx,eax
   0x00005555555553f2 <+196>:      mov    rax,QWORD PTR
   0x00005555555553f6 <+200>:      add    rax,rdx                                        #原理同上,这里rax指向了输入的第位
   0x00005555555553f9 <+203>:      xor    esi,ecx                //关键异或
   0x00005555555553fb <+205>:      mov    edx,esi                                        #结果保留在edx里面
   0x00005555555553fd <+207>:      mov    BYTE PTR ,dl
   0x00005555555553ff <+209>:      add    DWORD PTR ,0x1                //计数器+1
   0x0000555555555403 <+213>:      mov    eax,DWORD PTR       #计数器+1给到eax
   0x0000555555555406 <+216>:      movsxd rbx,eax                                        #相当于计数器的值给到rbx的低八位
   0x0000555555555409 <+219>:      mov    rax,QWORD PTR #再把输入放进eax里面,恢复eax在【<+200>】的状态
   0x000055555555540d <+223>:      mov    rdi,rax                                        #把指向输入字符的指针给rdi,当参数给strlen
   0x0000555555555410 <+226>:      call   0x555555555100 <strlen@plt>      //返回输入字符串的长度
   0x0000555555555415 <+231>:      cmp    rbx,rax                                        #当前计数器的值(rbx)和strlen返回值rax比较
   0x0000555555555418 <+234>:      jb   0x5555555553ca <subfhsadkhjbfleiowiuoyfgshjdvbsmnakl+156>#回到循环头
                #rbx小于rax就跳,也就是说:计数器小于字符串长度就继续执行
```

这里看到有一个变量:【rbp-0x24】,【rbp-0x20】,【rip+0x2c2f】。
【rbp-0x24】:这是计数器【i】;

赋初始值为0;

抑或完+1。
【rbp-0x20】:输入的字符串也就是flag**在循环完事之后就是存放输入经过循环的结果**
【rip+0x2c2f】:这里存放的是异或用的数组
看具体的异或过程,到底是谁和谁在异或:
```
0x00005555555553f9 <+203>:      xor    esi,ecx                //关键异或
```
对象是esi和ecx,看到对esi的操作:

就是输入的每一位。

看到ecx的操作:

**总结:我输入的和给出的数组进行按位异或**

关键循环分析完毕,在看到下面的代码:
```
0x000055555555541a <+236>:      mov    rcx,QWORD PTR        # 0x555555558020 <unk_sa7ydu3jb432>
   0x0000555555555421 <+243>:      mov    rdx,QWORD PTR                 #rdx==mallco(0x80),给出的flag
   0x0000555555555425 <+247>:      mov    rax,QWORD PTR                 #输入经过循环异或的flag
   0x0000555555555429 <+251>:      mov    rsi,rdx                                                
   0x000055555555542c <+254>:      mov    rdi,rax                                                #传参
   0x000055555555542f <+257>:      call   rcx                                                      #跳到rcx指向的地址,
   0x0000555555555431 <+259>:      add    rsp,0x38                              #堆栈平衡,函数准备结束
   0x0000555555555435 <+263>:      pop    rbx
   0x0000555555555436 <+264>:      pop    rbp
   0x0000555555555437 <+265>:      ret                                                    #函数结束

```
发现有一个,没有出现在循环异或的程序里,往上看一下:

发现也是一个类似于的结构,相当于【=mallco(0x80)】
动态调试发现rcx就是一个strcmp函数,比较的是 输入经过循环之后的值 和 一开始给出的值 是否相等。
相等返回1
这题就解了。

然后下载了ida7.5来验证自己的思路,发现每一个函数都判断正确,但是在最后的call rcx那里还需要再完善一下。

dingyu914 发表于 2021-8-5 10:45

学习,看不懂,也尝试理解

爱你小吉君 发表于 2021-6-3 09:45

给你点个赞吧

Hmily 发表于 2021-5-30 23:04

@Rootkit123 论坛支持MD格式,但不要分多个MD的的段,直接一头一尾加上就行了。

hans2000 发表于 2021-5-31 10:46

楼主顺便发个题目附件上来吧。
再就是主题是不是写错了?2012?2021?

DawnZii 发表于 2021-5-31 11:18

只能刷666666666了!

CAPFWJ 发表于 2021-6-2 13:55

只能刷666666666了!

shuye001 发表于 2021-6-3 10:45

膜拜CTF大佬。。

Rootkit123 发表于 2021-6-18 12:46

hans2000 发表于 2021-5-31 10:46
楼主顺便发个题目附件上来吧。
再就是主题是不是写错了?2012?2021?

对不起,确实写错了,感谢指正。我尝试发一下源文件(第一次发帖属实不会操作)

Rootkit123 发表于 2021-6-18 12:48

Hmily 发表于 2021-5-30 23:04
@Rootkit123 论坛支持MD格式,但不要分多个MD的的段,直接一头一尾加上就行了。

学习了,感谢!

Rootkit123 发表于 2021-6-18 12:55

这是题目的源文件,题目文件,elf64位
页: [1] 2
查看完整版本: 2012DASCTF逆向第一题汇编分析