Syc-bin方向二面-2019

这篇博客记录了作者在2019年参与Syc公司的二面经历,涉及逆向工程解密一道题目。作者详细分析了题目中的加密算法,包括Base58编码和C++实现,通过逆向工程得到了两层加密后的字符串。在二面过程中,作者学习了文件头知识和加密算法的逆向思路,最终解出了正确的答案。
摘要由CSDN通过智能技术生成

syc二面 -2019

这是syc-19年二面题目。
以下为自己的报告,
二面结束后又了解到的关于这道题更多的信息算法是base58编码和c++的做法,目前先鸽,以后更新。
很不错的题目,学到了许多,
附赠文件:⬇⬇ ⬇⬇
链接:https://pan.baidu.com/s/1aP3KaZFQD0P4T-xKn5n-jQ
提取码:1ahh
复制这段内容后打开百度网盘手机App,操作更方便哦

以下是二面最后提交的报告。

syc二面 – 令则

本报告是题目完成后写成,步骤都由复现后写就,可能会有在所难免的细节的疏漏,但基本完全还原整个解题思路和遇到的问题及解决。并且将自己遇到的小的细节和具体的操作原理写了些。

有部分工作是动调和标注,报告忽略了这些繁琐的部分,写出了这些工作的思路,并写出了分析出来的程序逻辑。

题目分析-整体分析

拿到题目后解压,
首先注意到一个exe文件就是我们的题目,然后两个dll是环境配置,然后一个后缀jpg_encode文件,我们首先会了解这是一个加密的jpg文件,在文件内解压,flag极可能在里面,
然后检查题目文件,32位无壳exe文件,其实应该庆幸这样的还可以动调,肝也能有方向,
载入ida,观察主函数,这是个c++写的程序,伪代码的可读性不高。
我们发现字符串sorry和wait的位置,发现sorry以后会直接结束程序,而wait以后会处理第三方文件,那么这个判定的位置就是一个关键,
后面的一部分使用的c语法,可读性极高,我们观察到载入了我们的jgp_encode文件和另一个jgp文件,然后一个读取一个写入,我们需输入一个值,用于异或解密,得到最后的jgp文件。
这样我们有一个大概的想法,使用动调确定了下整个函数的流程,然后答题思路大致有了:

  • 首先我们要得到flag,应该第一个字符串str1输入正确,
  • 应该会在第一个字符串中提示第二个字符串str2,
  • 得到第二个字符串用于解密第三方文件,得到正确解密的end.jgp文件
  • 就是图片直接显示flag或者隐写flag。

逆向1-第一层逆向

由于c++伪代码的复杂,分析直接看的汇编,
工具:
ida,特别是图形界面
od/x32dbg的动态调试,
其实在我的使用中差不多更推荐x32一些,双击后,在栈中可以偏移和地址一起观察到:
X64
分析的两条主线:

  • 根据判定一步步逆向得到正确的数据和字符串,
  • 使用一串abcdefghijklmnopqr来正向了解程序中对字符串的处理。

逆向得到加密后字符串str2

首先从sorry字符串判定的位置入手:
在这里插入图片描述
我们看到是判定的是两个寄存器的值,我们要在这里下断点,,观察整个判定过程
在这里插入图片描述
图示中蓝色为数据的准备,橙色部分为判定,红色部分为错误法显示“sorry”并退出程序,绿色是整个循环的判定,判定字符串是否已经检测完,
注意循环计数器,这里为[ebp-20]
审视判定的两个值,ebx和eax:
在这里插入图片描述
我们可以发现每次的ebx的值就是这个明文字符串s的按计数器选到的值。
审查eax的值,发现前面经历了一系列的计算,然后将这个值和[ebp-70]变量中储存的内存地址传参,调用一个函数,然后将储存eax中的函数返回值拿出来进行比较。

  • 计算部分,涉及到两个:循环计数器[ebp-20] 、已定义的变量[ebp-5c]形成的数组。
  • 函数调用,我们先观察[ebp-70]指向的地址,然后看到这里是一串字符串,观察函数调用后的内存、栈、寄存器,发现这个函数作用:按照参数的数值在指向的内存地址的字符串中选值,并返回这个值。

由此,我们大致可以猜测,这个[ebp-70]指向的地址就是加密完以后的字符,然后按照计算得到的数值选择出值,和明文的字符串s比较。
由此我们可以确定这个加密后字符串的长度,并得到这个加密后的字符串。
但还差一步,即这个计算出的值,我们可以找到[ebp-5c]和周围几个值组成的数组,配合循环计数器,通过汇编语言和动调分析,得到计算过程,并写出脚本得到这些值组成的列表,但里面出现了部分较复杂的汇编语句,我使用了下面更简单的方式。
我们进行动调,并记录下这些值,得到列表:

arr = [0x1,0x5,0x4,0x2,0x3,0x0,0x7,0xB,0xA,0x8,0x9,0x6,0xD,0x11,0x10,0xE,0xF,0xC]

我们可以知道,加密后的字符串str1的第arr[i]位等于s的第i位,可以得到str1:

 s = 'PrSDvCZirMmpygyGhb'
 arr = [0x1,0x5,0x4,0x2,0x3,0x0,0x7,0xB,0xA,0x8,0x9,0x6,0xD,0x11,0x10,0xE,0xF,0xC]
 v20 = [0]*18
 str1 = ''
 for i in range(18):
     v20[arr[i]] = s[i]
 for i in range(18):
     str1 += v20[i]
 print(str1)

如此我们得到了加密后的字符串str1:

str2 = 'CPDvSrpZMmribyGhyg'

下一步继续向上需要定位生成str2的关键加密部分,我们使用一个自己生成的字符串进行动调测试来进行寻找。
###程序流程分析
在main函数最开始下断点,并一直跟踪main函数。
观察调用函数:
*关注函数传入的参数,相对应的内存、栈中的变量和寄存器,
参数、参数指向的地址和寄存器一般就是函数作用到的所有内容了。

main函数的作用:(对照下图

  • 赋值了几个栈内地址,当作定义的局部变量(主要在绿色部分
  • 接收输入的字符串,并调用函数将输入的字符串赋值到内存的三处位置(主要在黄色部分和几个函数直接调用
  • 将内存地址3,内存地址3的最后一位字符,内存地址1分别传入一个lam函数,这个函数会将地址3的数值加密,形成我们得到的加密后的函数。(橙色框中的红色的断点位置
  • 然后进行判定,即我们首先关注并分析完成的sorry的判定位置。(后面紫色粉色部分
  • 判定成功进入第三方文件的处理部分。(蓝色部分
    在这里插入图片描述

这样我们知道了整个加密的关键在于这个lam函数,进入分析:
lam函数的作用:(对照下图

  • 首先处理数据赋值一些局部变量,其中有一部分函数的作用是清空栈内数据,一部分函数是将某变量指向的地址同样赋值给另一变量。(蓝色部分
  • 然后进入循环,共两个大循环,一个负责处理数值,一个使用处理出的数值根据一串字符串进行替换字符的加密。
  • 处理数值的大循环,内部嵌套一个小循环,每个字符会经历小循环,然后结束后进入大循环获取到下一个字符,计算的结果会保留在内存中。(大循环即绿色部分,小循环为黄色部分
  • 替换字符的循环,从内存中取出前面保留下的计算结果,然后得到字符串中的对应位,替换掉main函数内存地址3中的原字符串。替换完成的这个字符串也是main函数sorry判定部分判定的那个字符串。(紫色部分
    在这里插入图片描述

我们分析得到了加密过程的程序流程。

字符测试text

由于是较为复杂且细节并没有太明确的程序,我们使用自己已知测试字符串进行测试,尝试正向实现和逆向求解加密过程,对比动调中的数据,得到正确的逆向脚本。
我们的测试字符串:

str3 = 'abcdefghijklmnopqr'
得到对应数据

先在main函数sorry判定位置下断点。找到变量[ebp-70]指向的内存地址,得到测试字符串str3加密后得到的字符串:

cipher = 'YDXEJ7jpxdNwq9Tj8c4HbeAs'

然后重新载入程序,我们在lam函数的生成字符串处下断点。
通过变量[ebp-64]查找到存放加密后数据的地址,并得到加密后的数据:

 arr = [0x02,0x0F</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值