CatFly【汇编代码还原】
CatFly【难度:1】
题目界面
下载附件,发现是dll文件,放到linux中运行一下,运行界面如图所示:
从上图中可以看到两处字符串,上面的字符串不断滚动,下方字符串在次数上不断累加,猜测上方字符串与flag相关。
静态调试
打开IDA,找到main函数
方便分析,此处只粘贴关键部分代码(源代码的后半部分)
time(&timer);
v13 = 1;
v24 = 0LL;
v23 = 0;
v22 = 0;
v12 = off_FA88;
while ( v13 )
{
if ( dword_E104 )
printf("\x1B[H");
else
printf("\x1B[u");
for ( k = dword_E1EC; k < dword_E1F0; ++k )
{
for ( m = dword_E1F4; m < dword_E1F8; ++m )
{
if ( k <= 23 || k > 42 || m >= 0 )
{
if ( m >= 0 && (unsigned int)k <= 0x3F && m <= 63 )
{ v19 = off_FA20[v24][k][m];
off_FA88 = sub_6314((unsigned int)v24, k, m, (__int64)v12);
}
else
{
v19 = 44;
}
}
else
{
v18 = (2 - m) % 16 / 8;
if ( ((v24 >> 1) & 1) != 0 )
v18 = 1 - v18;
s[128] = (__int64)",,>>&&&+++###==;;;,,";
v19 = asc_BFE3[v18 - 23 + k];
if ( !v19 )
v19 = 44;
}
if ( v25 )
{
printf("%s", *((const char **)&unk_FCC0 + v19));
}
else if ( v19 == v22 || !*((_QWORD *)&unk_FCC0 + v19) )
{
printf("%s", off_FA88);
}
else
{
v22 = v19;
printf("%s%s", *((const char **)&unk_FCC0 + v19), off_FA88);
}
}
sub_65E2(1LL);
}
if ( dword_E100 )
{
time(&time1);
v11 = difftime(time1, timer);
v10 = sub_63FF((unsigned int)(int)v11);
for ( n = (dword_E1FC - 29 - v10) / 2; n > 0; --n )
putchar(32);
dword_E1E8 += printf("\x1B[1;37mYou have nyaned for %d times!\x1B[J\x1B[0m", (unsigned int)++dword_108E0);
}
v22 = 0;
++v23;
if ( dword_104C4 && v23 == dword_104C4 )
sub_6471();
if ( !off_FA20[++v24] )
v24 = 0LL;
usleep(1000 * v27);
}
return 0LL;
因为flag可能与屏幕上滚动的字符串有关,所以此处需要格外关注
printf
函数。从上述关键代码中,可以看到off_FA88最可能与flag有关,因为其他的printf函数打印的基本是一个确定的值。查看目标的交叉引用路径
确定了off_FA88后,开始查找与其相关的函数。
第一处是469行中的对off_FA88的赋值操作
off_FA88的值是sub_6314()函数的返回值。
接下来进入sub_6314()函数
函数伪代码如下图所示:
其功能为:当a2!=18,a3≤4||a3>54时off_FA88不变(v12的值就是off_FA88),所以此处相当于是k=18(一次)且m∈(4,53)时会执行sub_6314函数,即循环执行50次。该函数的返回值是byte_104C8的地址,byte_104C8的值与dword_E120[a3-5],dword_E120[a3-5]的值又与sub_62B5()函数的返回值有关。这里还有个sub_62E3作为逻辑判断的条件。将此处逻辑进行还原,还原代码如下:
for (int i = 0; i < 50; i++) {
dword_E120[i] ^= sub_62B5();
}
查看sub_62B5()函数
函数伪代码如下图所示:
可以看到该函数的返回值与dword_E1E8相关,查看dword_E1E8的交叉引用,可以看到只在main函数中有一次自增操作:
总结整个流程
还原关键汇编代码
此处使用大佬wp给的代码进行分析,基本都给了解析:
#include<stdio.h>
#include<string.h>
//在ida里面点开dword_E1E8会发现初始值为0x1106
int dword_E1E8 = 0x1106;
//同理,ida里也能看到dword_E120的初始值
int dword_E120[50] = { 0x27fb, 0x27a4, 0x464e, 0x0e36, 0x7b70, 0x5e7a, 0x1a4a, 0x45c1, 0x2bdf, 0x23bd, 0x3a15, 0x5b83, 0x1e15, 0x5367, 0x50b8, 0x20ca, 0x41f5, 0x57d1, 0x7750, 0x2adf, 0x11f8, 0x09bb, 0x5724, 0x7374, 0x3ce6, 0x646e, 0x010c, 0x6e10, 0x64f4, 0x3263, 0x3137, 0x00b8, 0x229c, 0x7bcd, 0x73bd, 0x480c, 0x14db, 0x68b9, 0x5c8a, 0x1b61, 0x6c59, 0x5707, 0x09e6, 0x1fb9, 0x2ad3, 0x76d4, 0x3113, 0x7c7e, 0x11e0, 0x6c70 };
//原封不动抄下来就好了
int sub_62B5()
{
dword_E1E8 = 1103515245 * dword_E1E8 + 12345;
return (dword_E1E8 >> 10) & 0x7FFF;
}
//这块是拿来算输出数字n需要多少个字符的。
//因为main函数中的dword_E1E8需要接收printf函数的返回值
//而printf函数的返回值是打印的字符长度
int llog(int n) {
int a = 0;
while (n /= 10)a++;
return a;
}
//这个函数我没有特别放出来,反正这里也是照抄的
int sub_62E3(char a1)
{
int result; // rax if ((a1 & 0x7Fu) <= 0x7E)
result = (a1 & 0x7Fu) > 0x20;
else
result = 0LL;
return result;
} int main() {
//count代表那个不停自增的dword_108E0
int count = 0;
while (1) {
for (int i = 0; i < 50; i++) {
dword_E120[i] ^= sub_62B5();
}
count++;
//计算printf的返回值,更改dword_E1E8,每10倍增加一个位数
dword_E1E8 += 42 + llog(count);
if (count % 1000000 == 0) {
printf("Count:%d\n", count);
}
//flag代表off_FA88
unsigned char flag[51] = { 0 };
for (int i = 0; i < 50; i++) {
//根据出题人所说,出题时循环次数为705980581,但是线性同余随机数算法出现了循环导致在100427942就出现了flag,若只考虑数组的最低字节,能在100001958得到flag
// Loop: 100427942
// if((dword_E120[i] & 0xff00)){
// break;
// }
// Loop: 100001958
if (!sub_62E3(dword_E120[i])) {
break;
}
flag[i] = dword_E120[i] & 0xff;
}
if (memcmp("CatCTF", flag, 6) == 0) {
puts(flag);
printf("Count:%d\n", count);
break;
}
}
}
运行代码,得到flag
CatFly【汇编代码还原】的更多相关文章
- PC逆向之代码还原技术,第五讲汇编中乘法的代码还原
目录 PC逆向之代码还原技术,第五讲汇编中乘法的代码还原 一丶简介乘法指令 1.乘法指令 2.代码还原注意问题 二丶乘法的汇编代码产生的格式 1.高级代码观看 2.乘法的汇编代码还原. 三丶乘法总结 ...
- PC逆向之代码还原技术,第六讲汇编中除法代码还原以及原理第二讲,被除数是正数 除数非2的幂
目录 一丶简介 二丶代码还原讲解 1.被除数无符号 除数非2的幂 2.被除数无符号 除数为特例7 三丶代码还原总结 一丶简介 上一篇博客说的除2的幂. 如果被除数是有符号的,那么会进行调整,并使用位操 ...
- PC逆向之代码还原技术,第四讲汇编中减法的代码还原
目录 PC逆向之代码还原技术,第四讲汇编中减法的代码还原 一丶汇编简介 二丶高级代码对应汇编观看. 1.代码还原解析: 三丶根据高级代码IDA反汇编的完整代码 四丶知识总结 PC逆向之代码还原技术,第 ...
- PC逆向之代码还原技术,第三讲汇编中加法的代码还原
目录 PC逆向之代码还原技术,第三讲汇编中加法的代码还原 一丶汇编简介 二丶高级代码对应汇编观看. 1.代码还原解析: 总结 PC逆向之代码还原技术,第三讲汇编中加法的代码还原 一丶汇编简介 在讲解加 ...
- linux内核分析作业:以一简单C程序为例,分析汇编代码理解计算机如何工作
一.实验 使用gcc –S –o main.s main.c -m32 命令编译成汇编代码,如下代码中的数字请自行修改以防与他人雷同 int g(int x) { return x + 3; } in ...
- GCC 嵌入汇编代码
The format of basic inline assembly is very much straight forward. Its basic form is 基本汇编嵌入格式如下: asm ...
- PC逆向之代码还原技术,第一讲基本数据类型在内存中的表现形式.浮点,指针寻址公式
目录 代码还原技术 一丶简介代码还原 二丶代码还原中的数据类型表现形式 1.整数类型 2.无符号整数 3.有符号整数 4.浮点数数据类型 5.浮点编码 4.Double类型解析. 三丶浮点汇编 1.浮 ...
- RPC远程过程调用学习之路(一):用最原始代码还原PRC框架
RPC: Remote Procedure Call 远程过程调用,即业务的具体实现不是在自己系统中,需要从其他系统中进行调用实现,所以在系统间进行数据交互时经常使用. rpc的实现方式有很多,可以通 ...
- linux内核分析作业4:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
系统调用:库函数封装了系统调用,通过库函数和系统调用打交道 用户态:低级别执行状态,代码的掌控范围会受到限制. 内核态:高执行级别,代码可移植性特权指令,访问任意物理地址 为什么划分级别:如果全部特权 ...
- 简单C程序生成的汇编代码分析
首先给出完整的C代码: int g(int x) { ; } int f(int x) { return g(x); } int main(void) { )+; } 使用命令:gcc –S –o h ...
随机推荐
- Verilog实现定点乘法器
实验目的 理解定点乘法的不同实现算法的原理,掌握基本实现算法. 熟悉并运用 Verilog 语言进行电路设计. 为后续设计 CPU 的实验打下基础. 实验内容 定点乘法器有多种实现,实验要求实现迭代乘 ...
- 基于间隔密度的概念漂移检测算法mdm-DDM
概念漂移 概念漂移是数据流挖掘领域中一个重要的研究点.传统的机器学习算法在操作时通常假设数据是静态的,其数据分布不会随着时间发生变化.然而对于真实的数据流来说,由于数据流天生的时间性,到达的数据的 ...
- containerd镜像拉取配置
背景: 公司要求部署最一套新版的k8s系统来部署生产应用,说实话很头疼.因为k8s自1.23版本之后就用不docker作为容器的默认运行时了,而是采用的containerd,这就带来了一系列的问题.没 ...
- 基于AvaSpe 2048测定物体的光谱曲线
本文介绍基于AvaSpec-ULS2048x64光纤光谱仪测定植被.土壤等地物高光谱曲线的方法. AvaSpec是由荷兰著名的光纤光谱仪器与系统开发公司Avantes制造的系列高性能光谱仪,广 ...
- 解决软件安装无法自定义文件夹,自动安装在C盘 (Windows系统)
其实就是软链接的简单应用 1.软件已经自动安装 2.完全退出当前软件 3.通过软件图标的属性找到其实际的安装目录 4.进入该软件的安装目录 5.将该软件整个剪切(你没有看错)到指定文件夹(自定义的安装 ...
- 安信可开发环境构建-基于Ai-WB2系列 和 Ai-M61 或 Ai-M62 (环境上下文切换)
首先,对于Ai-WB2系列环境的构建官方文档已经讲的非常明白了,这里不做阐述如下链接所示https://blog.csdn.net/Boantong_/article/details/12848091 ...
- windows开发环境备份,再也不怕重装系统了
每次重装系统后,都要重新安装软件,配置环境变量,极为繁琐.故作环境环境变量备份,常用软件恢复记录,前提是你的软件要安装在非系统盘,D/E盘等 软件安装在非系统盘 开发软件安装在非系统盘,建好目录.重装 ...
- Gitlab仓库代码更新时Jenkins自动构建
环境说明 1.Jenkins和gitlab已经都已经安装完毕 2.Jenkins能连接到gitlab获取项目并能手动创建项目 3.Jenkins和gitlab能相互访问的到(gitlab要能连接到Je ...
- camerabin error:"Internal data stream error,使用QT打开MIPI摄像头
使用QT自带的QCamera打开MIPI摄像头 遇到:camerabin error:"Internal data stream error 降低分辨率为640*480 TRANSLATE ...
- Spring/SpringBoot中的声明式事务和编程式事务源码、区别、优缺点、适用场景、实战
一.前言 在现代软件开发中,事务处理是必不可少的一部分.当多个操作需要作为一个整体来执行时,事务可以确保数据的完整性和一致性,并避免出现异常和错误情况.在SpringBoot框架中,我们可以使用声明式 ...