• Home
  • About
    • Rhy7hm photo

      Rhy7hm

      天天被计算机教做人

    • Learn More
    • Email
  • Posts
    • All Posts
    • All Tags
  • Projects

【hitcon2017】VOID

02 Jul 2019

Reading time ~1 minute

hitcon-quals-2017 void

最近被布置了这道题,2017年hitcon资格赛的家徒四壁~Everlasting Imaginative Void~

题目: https://github.com/david942j/ctf-writeups/tree/master/hitcon-quals-2017/void

参考:

http://h3ysatan.blogspot.com/2018/02/quick-notes-hitcon-ctf-2017-qual-elf.html

https://azure.kdays.cn/2017/11/08/HITCON2017-writeup/

http://pzhxbz.cn/?p=103

程序是动态链接的,根据.rela.dyn的内容可以看到,0x200DD8处内容被重定向到了0x935h处的代码。 注:0x200DD8可能会被IDA认为是LOAD段的内容,这是因为IDA会把自己不认识的段都认为是LOAD。

Elf64_Rela <200DD8h, 8, 935h> ; R_X86_64_RELATIVE +935h

而0x200DD8恰好是_fini_array[1],在退出时会被执行。

使用gdb调试可以让程序流程更加清楚:

先进行初始化,在elf_dynamic_do_Rela里会将0x200DD8处的值修改为0x935h

再注:sub_935处可能会被IDA认为是数据,按C可看到代码,为call sub_284,即调用sub_284函数。

按G然后0x284,enter,追踪至sub_284函数,经调试,可以看到它先判断输入内容的第16个字符是否!,

(因为在进行函数调用的时候,会将返回地址,即sub_935的下一条指令地址0x93A压栈,而0x284的第一条指令是pop rdi,此时rdi寄存器的值即为0x93A,此后将[rdi+200715h],即0x20104f处的值与!进行对比,而保存之前通过scanf传入的字符串的buf位于0x201040,所以是和输入的第16个字符进行对比)

如果不是则直接返回至_dl_fini,而后执行_fini_array[1],即0x200DD0,即sub_6B0。

如果输入内容的第16个字符为!,会依次执行0x93A处的代码,将0x0000555555554000至0x0000555555555000处地址的权限修改为可读可写可执行,然后继续接着执行, 从0x55555555486e开始,令 将输入保存至xmm1 寄存器,然后在与初始向量异或后,使用aesenc指令和aesenclast指令进行AES加密。其初始向量iv为0x798处的16byetes,而秘钥为从0x7a8开始的十个16byete。

若加密后的结果与0x2846fb67171be9b047cf6d49120447e7匹配,则在0x55555555489f跳至0x5555555548a2,然后显示Good

最终被我翻了几页谷歌找到了脚本:

https://github.com/5unKn0wn/ctfs/blob/master/2017/hitcon/void.py

脚本中的oneRoundDecrypt函数其实对应aesenc指令,而finalRoundDecrypt则对应aesenclast指令。



revers Share Tweet +1