2022 强网逆向部分题解
前言
整个比赛打下来就只有坐牢、坐牢还是坐牢…萌新逆向选手拿到的都是一堆ELF
然后进行着一堆奇怪的函数…完全看不懂…或许只有GameMaster
算是我能看懂的题目吧…
GAME MASTER
感觉整场比赛下来的逆向签到题目,本质上是一个C#
编写的一个21点
游戏,因为看不懂C#
只能连蒙带猜的看,毕竟和C
还是长得有些相似,还算好理解…
我们将其拖入到PE
中进行查看
可以很明显的发现是一个C#
文件,使用dnSpy(32位)
进行打开,直接可以找到关键的主函数
可以很明显的发现程序加载了附件中的game message
,我们往下翻可以发现下面这些特殊操作:
程序中似乎可以输入作弊码,同时在goldFunc
中我们可以看到每一种作弊码对应的效果,有加钱的有减赌注的…同时我们也发现了几个有点不一样的作弊码,他们对我们之前加载的game message
进行了操作,如下图:
大致可以看出来程序将game message
进行了异或以及AES ECB
的解密,对此我们尝试输入对应的作弊码,发现game message
没有什么变化…不知道是不是因为程序没有将写完后的数据关闭,而导致数据仍然停留在内存中,我也看不懂C#
,也不是很清楚…
尝试输入作弊码的师傅可能需要注意一下,第一个大的前缀作弊码输入完后需要再输入一位字符(可以随意输入),之后再进行输入第二段作弊码
对此我们采取手动进行解密game message
的信息,写出如下Python
脚本
1 |
|
之后我们可以将我们的game message
拖入到010
中进行查看,可以发现整个文件是一个PE
文件加上了一堆奇怪的东西
之后我们可以恢复得到一个exe
,将其拖入PE
,同样发现其是一个C#
文件,我们同样直接拖入到dnSpy
进行分析查看
我们可以发现其中的主要关键为其中的Check1
整个函数,在其中我们缺少对应的x
、y
、z
,如果我们采用手逆的话可能会有些麻烦,我们可以直接利用Z3
对其进行约束求解,将解密得到的x
、y
、z
直接应用到下面,按程序逻辑进行执行即可得到对应题目的flag
,写出脚本如下:
1 |
|
之后就可以直接得到flag
啦 ~
EasyRE
又是一个说自己easy
的题目,CTF
里面的easy
以及baby
的题目都不能相信,基本上就是不easy
和卑鄙
了,当然或许有些题是真的easy
以及baby
难度
拿到程序我们将其拖入IDA
中,可以看到程序去除了对应的符号表,显得每一个函数十分的难看,这里我们借助一下Finger
插件进行恢复一下符号,之后我们可以快速的找到程序的主函数
可以看到程序创建了一个子进程re3
,我们将写完的程序进行提出来,我们将其拖入进IDA
可以发现有大量红色的未反编译出的函数,我们手动修复的同时可以发现在一处出现了我们父进程的那两个数字0xCAFEB055
和0xCAFE1055
,同时中间的大部分数据无法还原,因此猜测可能是一个SMC
我们此时回到父进程进行观察那个循环中if
语句对应的操作
可以看到函数中存在有sys_ptrace
以及两个关键的if
判断语句对我们的产生的异常信号进行处理,对于sys_ptrace
的一些知识点可以参考
其中关键的部分在于对于ptrace
的一些参数:
Request | Description |
---|---|
PTRACE_TRACEME | 进程被其父进程跟踪,其父进程应该希望跟踪子进程。该值仅被tracee使用,其余的request值仅被tracer使用 |
PTRACE_PEEKTEXT, PTRACE_PEEKDATA | 从tracee的addr指定的内存地址中读取一个字节作为ptrace()调用的结果 |
PTRACE_PEEKUSER | 从tracee的USER区域中便宜为addr处读取一个字节,该值保存了进程的寄存器和其他信息 |
PTRACE_POKETEXT, PTRACE_POKEDATA | 向tracee的addr内存地址处复制一个字节数据 |
PTRACE_POKEUSER | 向tracee的USER区域中偏移为addr地址处复制一个字节数据 |
PTRACE_GETREGS | 复制tracee的通用寄存器到tracer的data处 |
PTRACE_GETFPREGS | 复制tracee的浮点寄存器到tracer的data处 |
PTRACE_GETREGSET | 读取tracee的寄存器 |
PTRACE_SETREGS | 设置tracee的通用寄存器 |
PTRACE_SETFPREGS | 设置tracee的浮点寄存器 |
PTRACE_CONT | 重新运行stopped状态的tracee进程 |
PTRACE_SYSCALL | 重新运行stopped状态的tracee进程,但是使tracee在系统调用的下一个entry或从系统调用退出或在执行一条指令后stop |
PTRACE_SINGLESTEP | 设置单步执行标志 |
PTRACE_ATTACH | 跟踪指定pid的进程 |
PTRACE_DETACH | 结束跟踪 |
通过这个我们可以还原ptrace
函数的操作,我们进入到sub_401BB1
函数中,观察可以确定其是一个SMC
的解密操作
对此我们可以通过调试时加入断点,来进行提取对应的异或数据值
对此我们可以得到对应的异或数据
1 |
|
之后我们就可以编写一个IDAPython
脚本将我们之前得到的re3
手动SMC
解密回去
1 |
|
解密完成后将发送int 3
指令等传给父进程的数进行patch
处理,随后构建函数,通过一定分析我们可以发现这个函数将我们的输入进行保存,随后进行check
,经过一些资料的查找发现这个是一个数织游戏,其将我们的数据进行统计1
的个数放在第一位,随后进行check
我们的输入
对于求解这个我们需要注意的是,这个静态下直接提取得到的行列数据是有一定问题的,这行与列是在init
被相应修改了,我们可以尝试直接调试拿取数据
我们将数据提取,可以直接到在线网站进行求解