
2020——网鼎杯 (青龙组)signal
发布日期:2021-05-07 12:08:46
浏览次数:29
分类:原创文章
本文共 5318 字,大约阅读时间需要 17 分钟。
文章目录
vm_operad
int __cdecl vm_operad(int *a1, int a2){ int result; // eax@2 char v3[100]; // [sp+13h] [bp-E5h]@4 char v4[100]; // [sp+77h] [bp-81h]@5 char v5; // [sp+DBh] [bp-1Dh]@5 int v6; // [sp+DCh] [bp-1Ch]@1 int v7; // [sp+E0h] [bp-18h]@1 int v8; // [sp+E4h] [bp-14h]@1 int v9; // [sp+E8h] [bp-10h]@1 int v10; // [sp+ECh] [bp-Ch]@1 v10 = 0; v9 = 0; v8 = 0; v7 = 0; v6 = 0; while ( 1 ) { result = v10; if ( v10 >= a2 ) return result; switch ( a1[v10] ) { case 10: read(v3); ++v10; break; case 1: v4[v7] = v5; ++v10; ++v7; ++v9; break; case 2: v5 = a1[v10 + 1] + v3[v9]; v10 += 2; break; case 3: v5 = v3[v9] - LOBYTE(a1[v10 + 1]); v10 += 2; break; case 4: v5 = a1[v10 + 1] ^ v3[v9]; v10 += 2; break; case 5: v5 = a1[v10 + 1] * v3[v9]; v10 += 2; break; case 6: ++v10; break; case 7: if ( v4[v8] != a1[v10 + 1] ) { printf("what a shame..."); exit(0); } ++v8; v10 += 2; break; case 11: v5 = v3[v9] - 1; ++v10; break; case 12: v5 = v3[v9] + 1; ++v10; break; case 8: v3[v6] = v5; ++v10; ++v6; break; default: continue; } }}
函数功能
利用文件字符串中保存的流程数据(以及加密数据)和控制台数据配合进行验证flag(这个文件字符串中保存的数据既起到了流程的作用还有加密作用)
read
size_t __cdecl read(char *a1){ size_t result; // eax@1 printf("string:"); scanf("%s", a1); result = strlen(a1); if ( result != 15 ) { puts("WRONG!\n"); exit(0); } return result;}
函数功能
这个read函数用来读取控制台输入的命令,我觉得就是flag
0A 00 00 00 04 00 00 00 10 00 00 00 08 00 00 0003 00 00 00 05 00 00 00 01 00 00 00 04 00 00 0020 00 00 00 08 00 00 00 05 00 00 00 03 00 00 0001 00 00 00 03 00 00 00 02 00 00 00 08 00 00 000B 00 00 00 01 00 00 00 0C 00 00 00 08 00 00 0004 00 00 00 04 00 00 00 01 00 00 00 05 00 00 0003 00 00 00 08 00 00 00 03 00 00 00 21 00 00 0001 00 00 00 0B 00 00 00 08 00 00 00 0B 00 00 0001 00 00 00 04 00 00 00 09 00 00 00 08 00 00 0003 00 00 00 20 00 00 00 01 00 00 00 02 00 00 0051 00 00 00 08 00 00 00 04 00 00 00 24 00 00 0001 00 00 00 0C 00 00 00 08 00 00 00 0B 00 00 0001 00 00 00 05 00 00 00 02 00 00 00 08 00 00 0002 00 00 00 25 00 00 00 01 00 00 00 02 00 00 0036 00 00 00 08 00 00 00 04 00 00 00 41 00 00 0001 00 00 00 02 00 00 00 20 00 00 00 08 00 00 0005 00 00 00 01 00 00 00 01 00 00 00 05 00 00 0003 00 00 00 08 00 00 00 02 00 00 00 25 00 00 0001 00 00 00 04 00 00 00 09 00 00 00 08 00 00 0003 00 00 00 20 00 00 00 01 00 00 00 02 00 00 0041 00 00 00 08 00 00 00 0C 00 00 00 01 00 00 0007 00 00 00 22 00 00 00 07 00 00 00 3F 00 00 0007 00 00 00 34 00 00 00 07 00 00 00 32 00 00 0007 00 00 00 72 00 00 00 07 00 00 00 33 00 00 0007 00 00 00 18 00 00 00 07 00 00 00 A7 FF FF FF07 00 00 00 31 00 00 00 07 00 00 00 F1 FF FF FF07 00 00 00 28 00 00 00 07 00 00 00 84 FF FF FF07 00 00 00 C1 FF FF FF 07 00 00 00 1E 00 00 0007 00 00 00 7A 00 00 00
流程代码
case 10: read(v3); ++v10; break; case 1: v4[v7] = v5; ++v10; ++v7; ++v9; break; case 2: v5 = a1[v10 + 1] + v3[v9]; v10 += 2; break; case 3: v5 = v3[v9] - LOBYTE(a1[v10 + 1]); v10 += 2; break; case 4: v5 = a1[v10 + 1] ^ v3[v9]; v10 += 2; break; case 5: v5 = a1[v10 + 1] * v3[v9]; v10 += 2; break; case 6: ++v10; break; case 7: if ( v4[v8] != a1[v10 + 1] ) { printf("what a shame..."); exit(0); } ++v8; v10 += 2; break; case 11: v5 = v3[v9] - 1; ++v10; break; case 12: v5 = v3[v9] + 1; ++v10; break; case 8: v3[v6] = v5; ++v10; ++v6; break; default: continue;
简介每个数字所要做的事(但是流程不是按照这样进行的)
- 0x0A:读取控制台所输入的15个字符
- 0x4:求v5值,文件字符串下一个位置值 ^ 控制台第一个数据
- 0x10:continue
- 0x08:v5赋给v3数组的第一个元素
- 0x03:(v3数组的第一个元素-文件字符串下一个位置值)赋给v5
- 0x05:求V5值,文件字符串下一个位置值 * 控制台第一个数据
- 0x01:v5赋给v4数组的第一个元素,然后v9自增,也就代表接下来需要利用到控制台第二个数据
- 0x4:求v5值,文件字符串下一个位置值 ^ 控制台第一个数据
- 0x20:continue
- 0x08:v5赋给v3数组的第二个元素
- 0x05:求V5值,文件字符串下一个位置值 * 控制台第二个数据
- 0x03:(v3数组的第二个元素 - 文件字符串下一个位置值)赋给v5
- 0x01:v5赋给v4数组的第二个元素,然后v9自增,也就代表接下来需要利用到控制台第三个数据
……………………………………
注意:
文件字符串遇到2 ,3,4,5,7
时,那么下一个值并不控制流程(流程直接跳过!),而是被当计算数据所用了。。所以才说执行流程并非是上面所写的
验证数据(逆向重点)
07 00 00 00 22 00 00 00 07 00 00 00 3F 00 00 0007 00 00 00 34 00 00 00 07 00 00 00 32 00 00 0007 00 00 00 72 00 00 00 07 00 00 00 33 00 00 0007 00 00 00 18 00 00 00 07 00 00 00 A7 FF FF FF07 00 00 00 31 00 00 00 07 00 00 00 F1 FF FF FF07 00 00 00 28 00 00 00 07 00 00 00 84 FF FF FF07 00 00 00 C1 FF FF FF 07 00 00 00 1E 00 00 0007 00 00 00 7A 00 00 00
这里全是用来验证的:
依次是 22h 3fh 34h 32h 72h 33h 18h ffffffa7h 31h fffff1h 28h ffff84h 1eh 7ah
所以按照标准字符串,然后把每个字符都逆着做一遍操作,然后就得到了我们所输在控制台的东西,紧接着就结束了。。。
逆向思维
- (0x22+5)^ 0x10
- (0x3f/3) ^ 0x20
- (0x34 + 1) + 2
- (0x32 ^ 4) - 1
- (0x72 + 0x21) / 3
- (0x33 + 1) + 1
- (0x18 + 0x20) ^ 9
- (0xa7 ^ 0x24) -0x51
- (0x31 + 1) - 1
- (0xf1 - 0x25) / 2
- (0x28 ^ 0x41) - 0x36
- (0x84 / 1) - 0x20
- (0xc1 - 0x25) / 3
- (0x1e + 0x20) ^ 9
- (0x7a - 1) - 0x41
flag{ 757515121f3d478}
发表评论
最新留言
做的很好,不错不错
[***.243.131.199]2025年04月09日 16时51分52秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
python负数存储
2019-03-05
求二维数组中最大值的位置
2019-03-05
python中sort和sorted的区别
2019-03-05
maven安装
2021-05-08
合并两个有序数组
2021-05-08
Ubuntu 环境下使用中文输入法
2021-05-08
聊聊我的五一小假期
2021-05-08
面向对象之异常处理:多路捕获
2021-05-08
Python简易五子棋
2021-05-08
Vue新建项目——页面初始化
2021-05-08
Cent OS 7.6 服务器软件安装(这篇博客主要是为了方便我配置云主机的)
2021-05-08
Node.js包使用系列(一)——修改NPM全局下载和缓存路径
2021-05-08
TDengine使用(一)——TDengine下载与安装
2021-05-08
6.14编一个程序,将两个字符串s1和s2比较,不要用strcmp函数。
2021-05-08
Java纯文本文件显示工具制作
2021-05-08
Unity2D Fixed Joint 2D详解
2021-05-08
六、Numpy的使用(详解)
2019-03-05
三、案例:留言板 & url.parse()
2019-03-05
Python中的filter()函数!!!1
2019-03-05