[BUUCTF]REVERSE——[GWCTF 2019]re3

[GWCTF 2019]re3

附件

步骤

  1. 64位程序,无壳儿,直接用ida打开,首先是检索程序里的字符串
    在这里插入图片描述
  2. 根据correct跳转去找到有关flag的函数,下面能看到ABC……*/,猜测程序里存在base64加密
    在这里插入图片描述
  3. 这边没法f5,估计是jz的锅影响了ida的正常运行,先看一下上面的main函数
    main()
    在这里插入图片描述
    输入的字符串长度为32位,利用mprotect函数将dword_400000处的0xF000长度地址修改成了可读可写可执行,sub_402219()里的数据进行了异或处理。
  4. 可以看到sub_402219()函数既作为数据参与异或,又作为函数来引用,而且这个函数打不开
    我们猜测异或完后,这个函数才是真正的函数。所以先将sub_402219()里的数据还原看看,
    直接在伪代码部分点sub_402219跳转不到它的数据段,得在汇编代码里找
    在这里插入图片描述
    找到后按D转换成data型
    在这里插入图片描述
    之后使用idc脚本还原数据,第一次接触idc脚本,简单记录一下
    首先shif+f2调出脚本编辑器,然后就可以编辑idc脚本了,语法跟c有点相似,具体的语法看这篇文章和这篇文章
    在这里插入图片描述
    简单解释一下写法,首先定义一个局部变量addr,就是我们要修复数据的起始位置,i用来遍历,之后的for循环照抄main函数里的,最后就是PatchByte(addr+i,Byte(addr+i)^0x99)这句。
    首先看一下PatchByte的语法,这句话就是从addr开始,利用i遍历地址,将对应地址的值设置为byte_402219[addr+i]=byte_402219[addr+i]^0x99
    在这里插入图片描述
    点击run还原数据
    在这里插入图片描述
    还原后选择数据按c,选择force强制执行,将数据转换成代码
    在这里插入图片描述
    之后在代码开始的地方0x402219按p创建函数
    在这里插入图片描述
    现在回头再去看看我们的main函数
    在这里插入图片描述
    sub_402219()该函数能打开了,19行的的jumpout百度了一下,看雪上给的解释是

函数边界识别错误, 或者是
由于编译器某些原因会把某些代码分出来,不存放在连续区域,而是在其他位置,这些块有时ida能识别出来,被称为chunk,有些不能识别,此时就得自己手动设置。
如果是边界识别错误,那就alt+p,找到正确的末尾;
如果是后者,那就通过append_func_tail来将目标区域添加到本函数中,另外,得先undefine目标区域。

我去百度了这题的wp,发现不影响,我也就没有继续折腾它了。

  1. 继续看main(),之后调用了 sub_40207B()
    sub_40207B(),它的参数unk_603170()直接在ida里看不到,后面动调看看
    sub_40207B()里调用了sub_401CF9函数,它太长了,就不贴了,根据函数特征码,可以发现这是md5加密
    在这里插入图片描述
    n1book的p273有算法的特征码
    在这里插入图片描述
    在这里插入图片描述
    这个函数主要将base64表进行了两次md5加密

  2. 之后是sub_402219()
    在这里插入图片描述
    sub_400A71()
    在这里插入图片描述首先它整体循环了4次,处理数据的时候用到了byte_4023A0
    在这里插入图片描述
    根据上方我贴的n1book里的图,可以发现这个是AES加密的s盒,所以这个函数的作用就是将unk_603170(base64表进行了两次md5加密后的结果)传入作为了密钥
    sub_40196E()里面有同样的特征码,应该是AES加密的步骤,所以它的作用是利用unk_603170(上一层传入的base64表进行了两次md5加密后的结果)作为密钥对我们输入的数据进行了AES加密
    经过9~11行的处理后得到了byte_6030a0里的数据,将byte_6030a0里的数据提取一下
    在这里插入图片描述
    byte_6030a0=BC0AADC0147C5ECCE0B140BC9C51D52B46B2B9434DE5324BAD7FB4B39CDB4B5B

  3. 到这里理清楚了程序的逻辑
    先是base64表进行了两次md5加密的结果传入了unk_603170
    unk_603170,利用它对我们输入的数据进行了AES加密后得到了byte_6030a0
    unk_603170可以通过动调或者在线md5加密平台得到或者自己写md5加密脚本跑一下

  4. 动调找unk_603170的值(主要是我利用工具网站两次md5加密后得不到正确的key,自己写的python被卡在编码的转换之间)
    由于是elf文件,所以要用虚拟机动调,关于如何使用IDA动调ELF文件(使用虚拟机),详细的看这篇文章
    前提是物理机和虚拟机能够互相ping通,ping不通的重置虚拟机网卡。
    调了好久,终于给我弄出来了,unk_603170=CB8D493521B47A4CC1AE7E62229266CE
    在这里插入图片描述
    这边记录一下调试这题的坑
    在这里插入图片描述
    首先你看程序只要输入的字符串长度为32就能绕过这个exit(0),但是实际操作的时候发现不行,我的绕过做法是现在执行if判断前下个断点,然后在执行给unk_603170赋值前在下一个断点
    在这里插入图片描述
    设置好后先f9运行到第一个断点,之后ctrl+f7运行到第二个断点,之后单步f8到unk_603170完成赋值,去查看unk_603170即可。

  5. 最后用unk_603170给byte_6030a0解密即可,在线工具解密失败,贴一下其他师傅python2的exp,自己用python3被编码的转换卡死了

from Crypto.Cipher import AES
import codecs

aes = AES.new(decode_hex('CB8D493521B47A4CC1AE7E62229266CE')[0], AES.MODE_ECB)
print(aes.decrypt(decode_hex('BC0AADC0147C5ECCE0B140BC9C51D52B46B2B9434DE5324BAD7FB4B39CDB4B5B')[0])) 

flag{924a9ab2163d390410d0a1f670}

exp来源:https://www.cnblogs.com/Mayfly-nymph/p/12829168.html

猜你喜欢

转载自blog.csdn.net/mcmuyanga/article/details/114360856