攻防世界 Replace Reverse二星题
解题过程中,虽然解出来了,但是磕磕绊绊犯了一些错误,记录一下
分析过程
PE查壳

有一个upx壳,最下面给了脱壳提示: upx.exe -d Replace.exe

脱壳结束,丢到IDA里,SHIF+F12,查看字符串,看到一个可疑的”Well Done!\n“,点进去看看,发现就是主函数,反汇编主函数

- Buffer很明显是输入,且长度要<=37
- 判断函数==1就成功,显然这就是关键
sub_401090函数(改了一点名称)
1 // 最后要输出1
2 // a1是输入,a2是输入的长度且为35
3 int __fastcall sub_401090(int a1, int a2)
4 {
5 int v4; // edx
6 char char_v5; // al
7 int high4; // esi
8 int low4; // edi
9 char char_v8; // al
10 int v9; // eax
11 char char_v10; // cl
12 int v11; // eax
13 int v12; // ecx
14
15 if ( a2 != 35 )
16 return -1;
17 v4 = 0;
18 while ( 1 )
19 {
20 char_v5 = *(_BYTE *)(v4 + a1);
21 high4 = (char_v5 >> 4) % 16; // 先右移4位,相当于把原来8位的高4位数移动到低4位,新高4位全都置零——再%16,相当于取出变换后新8位的低4位——也就是取出原来数的高4位
22 low4 = ((16 * char_v5) >> 4) % 16; // 先*16,相当于左移4位,原来的低4位移动到高4位,新的低4位置零——再右移4位,相当于移回来了,不过高4位都是0——再%16,取出低4位——原就是取出原来数的低4位
23 char_v8 = byte_402150[2 * v4];
24 if ( char_v8 < 48 || char_v8 > 57 )
25 v9 = char_v8 - 87;
26 else
27 v9 = char_v8 - 48;
28 char_v10 = byte_402151[2 * v4];
29 v11 = 16 * v9; // v9*16,相当于左移4位————为后面组成新的8位做准备,作为新数的高4位
30 if ( char_v10 < 48 || char_v10 > 57 )
31 v12 = char_v10 - 87;
32 else
33 v12 = char_v10 - 48; // 作为新数的低4位
34 if ( (unsigned __int8)byte_4021A0[16 * high4 + low4] != ((v11 + v12) ^ 25) )// 16 * high4 + low4——操作的目的是组成新的8位数——其实就是原来输入的数
35 // ((v11 + v12) ^ 25)——将上面获得v11与v12组成新的数,与25异或
36 // 最后进行比较,相等才能return 1
37 break;
38 if ( ++v4 >= 35 )
39 return 1;
40 }
41 return -1;
42 }
总而言之,从byte_402150取一个元素作为char_v8,变换后获得组成高位的v11;从byte_402151取一个元素作为char_v10,变换后获得组成低位的v12,最后组成一个新的数去异或
【异或后得到的值】要与 【将输入作为下标,从byte_4021A0中取出的数】 相等
byte_402150与byte_402151

!!在这里我就犯了一个错误,我还以为是我IDA又出现问题了....byte_402150数组的32h后面没有 0 表示结束,所以要继续往下读取,一直到出现 0 ,即byte_402150是50+byte_402151
unsigned char ida_chars[] =
{
50,97, 52, 57, 102, 54, 57, 99, 51, 56, 51,
57, 53, 99, 100, 101, 57, 54, 100, 54, 100,
101, 57, 54, 100, 54, 102, 52, 101, 48, 50,
53, 52, 56, 52, 57, 53, 52, 100, 54, 49,
57, 53, 52, 52, 56, 100, 101, 102, 54, 101,
50, 100, 97, 100, 54, 55, 55, 56, 54, 101,
50, 49, 100, 53, 97, 100, 97, 101, 54, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0
};
unsigned char ida_chars[] =
{
97, 52, 57, 102, 54, 57, 99, 51, 56, 51,
57, 53, 99, 100, 101, 57, 54, 100, 54, 100,
101, 57, 54, 100, 54, 102, 52, 101, 48, 50,
53, 52, 56, 52, 57, 53, 52, 100, 54, 49,
57, 53, 52, 52, 56, 100, 101, 102, 54, 101,
50, 100, 97, 100, 54, 55, 55, 56, 54, 101,
50, 49, 100, 53, 97, 100, 97, 101, 54, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0
};
byte_4021A0
选中全部,SHIF+E-->选中‘C unsigned char array (decimal)’,得到数组的值(上面也是这么得到的)
unsigned char ida_chars[] =
{
99, 124, 119, 123, 242, 107, 111, 197, 48, 1,
103, 43, 254, 215, 171, 118, 202, 130, 201, 125,
250, 89, 71, 240, 173, 212, 162, 175, 156, 164,
114, 192, 183, 253, 147, 38, 54, 63, 247, 204,
52, 165, 229, 241, 113, 216, 49, 21, 4, 199,
35, 195, 24, 150, 5, 154, 7, 18, 128, 226,
235, 39, 178, 117, 9, 131, 44, 26, 27, 110,
90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
83, 209, 0, 237, 32, 252, 177, 91, 106, 203,
190, 57, 74, 76, 88, 207, 208, 239, 170, 251,
67, 77, 51, 133, 69, 249, 2, 127, 80, 60,
159, 168, 81, 163, 64, 143, 146, 157, 56, 245,
188, 182, 218, 33, 16, 255, 243, 210, 205, 12,
19, 236, 95, 151, 68, 23, 196, 167, 126, 61,
100, 93, 25, 115, 96, 129, 79, 220, 34, 42,
144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
224, 50, 58, 10, 73, 6, 36, 92, 194, 211,
172, 98, 145, 149, 228, 121, 231, 200, 55, 109,
141, 213, 78, 169, 108, 86, 244, 234, 101, 122,
174, 8, 186, 120, 37, 46, 28, 166, 180, 198,
232, 221, 116, 31, 75, 189, 139, 138, 112, 62,
181, 102, 72, 3, 246, 14, 97, 53, 87, 185,
134, 193, 29, 158, 225, 248, 152, 17, 105, 217,
142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
140, 161, 137, 13, 191, 230, 66, 104, 65, 153,
45, 15, 176, 84, 187, 22
};
解题脚本(自己写的常规版本)
1 key1=[
2 50,97, 52, 57, 102, 54, 57, 99, 51, 56, 51,
3 57, 53, 99, 100, 101, 57, 54, 100, 54, 100,
4 101, 57, 54, 100, 54, 102, 52, 101, 48, 50,
5 53, 52, 56, 52, 57, 53, 52, 100, 54, 49,
6 57, 53, 52, 52, 56, 100, 101, 102, 54, 101,
7 50, 100, 97, 100, 54, 55, 55, 56, 54, 101,
8 50, 49, 100, 53, 97, 100, 97, 101, 54
9 ]
10 key2=[
11 97, 52, 57, 102, 54, 57, 99, 51, 56, 51,
12 57, 53, 99, 100, 101, 57, 54, 100, 54, 100,
13 101, 57, 54, 100, 54, 102, 52, 101, 48, 50,
14 53, 52, 56, 52, 57, 53, 52, 100, 54, 49,
15 57, 53, 52, 52, 56, 100, 101, 102, 54, 101,
16 50, 100, 97, 100, 54, 55, 55, 56, 54, 101,
17 50, 49, 100, 53, 97, 100, 97, 101, 54
18 ]
19 str=[
20 99, 124, 119, 123, 242, 107, 111, 197, 48, 1,
21 103, 43, 254, 215, 171, 118, 202, 130, 201, 125,
22 250, 89, 71, 240, 173, 212, 162, 175, 156, 164,
23 114, 192, 183, 253, 147, 38, 54, 63, 247, 204,
24 52, 165, 229, 241, 113, 216, 49, 21, 4, 199,
25 35, 195, 24, 150, 5, 154, 7, 18, 128, 226,
26 235, 39, 178, 117, 9, 131, 44, 26, 27, 110,
27 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
28 83, 209, 0, 237, 32, 252, 177, 91, 106, 203,
29 190, 57, 74, 76, 88, 207, 208, 239, 170, 251,
30 67, 77, 51, 133, 69, 249, 2, 127, 80, 60,
31 159, 168, 81, 163, 64, 143, 146, 157, 56, 245,
32 188, 182, 218, 33, 16, 255, 243, 210, 205, 12,
33 19, 236, 95, 151, 68, 23, 196, 167, 126, 61,
34 100, 93, 25, 115, 96, 129, 79, 220, 34, 42,
35 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
36 224, 50, 58, 10, 73, 6, 36, 92, 194, 211,
37 172, 98, 145, 149, 228, 121, 231, 200, 55, 109,
38 141, 213, 78, 169, 108, 86, 244, 234, 101, 122,
39 174, 8, 186, 120, 37, 46, 28, 166, 180, 198,
40 232, 221, 116, 31, 75, 189, 139, 138, 112, 62,
41 181, 102, 72, 3, 246, 14, 97, 53, 87, 185,
42 134, 193, 29, 158, 225, 248, 152, 17, 105, 217,
43 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
44 140, 161, 137, 13, 191, 230, 66, 104, 65, 153,
45 45, 15, 176, 84, 187, 22
46 ]
47 flag = ""
48 for i in range(35):
49 v8 = key1[2*i]
50 if v8 < 48 or v8 > 57:
51 v11 = 16 * (v8 - 87)
52 else:
53 v11 = 16 * (v8 - 48)
54 v10 = key2[2 * i]
55 if v10 < 48 or v10 > 57:
56 v12 = v10 - 87
57 else:
58 v12 = v10 - 48
59 v4=((v11 + v12) ^ 25)
60 flag += chr(str.index(v4))
61
62 print(flag)
这里我犯了一个弱智错误
- 最初写脚本的时候,想照着反汇编代码的思路去写,在后面写了一个 for j in range(len(str_data)): if str[i]==((v11 + v12) ^ 25):v4=((v11 + v12) ^ 25)
- 结果导致运行没有报错,也没有结果
str[i]==((v11 + v12) ^ 25)这一行代码在每次循环中都会遍历str列表来查找是否存在相等的值,这会导致程序在执行时花费很长时间,因为它的时间复杂度是 O(n),其中 n 是str列表的长度。由于列表长度非常大,因此这种线性搜索的方法会非常慢,尤其是在内层循环中还嵌套了一个循环。这也解释了为什么代码没有输出也没有报错,因为它可能需要很长时间才能完成运行
解题脚本(枚举正向爆破)
这个版本是我参考别的大佬的wp时候学到的,记录一下
由于用了取余 % 运算,所以采用枚举正向爆破的方法,让flag中的每一个字符遍历常用的字符(ascii码表中32-126),带入加密算法,如果成功,就把这个flag存入
list1=[50, 97, 52, 57, 102, 54, 57, 99, 51, 56, 51, 57, 53, 99, 100, 101, 57, 54, 100, 54, 100, 101, 57, 54, 100, 54, 102, 52, 101, 48, 50, 53, 52, 56, 52, 57, 53, 52, 100, 54, 49, 57, 53, 52, 52, 56, 100, 101, 102, 54, 101, 50, 100, 97, 100, 54, 55, 55, 56, 54, 101, 50, 49, 100, 53, 97, 100, 97, 101, 54]
list2=[97, 52, 57, 102, 54, 57, 99, 51, 56, 51, 57, 53, 99, 100, 101, 57, 54, 100, 54, 100, 101, 57, 54, 100, 54, 102, 52, 101, 48, 50, 53, 52, 56, 52, 57, 53, 52, 100, 54, 49, 57, 53, 52, 52, 56, 100, 101, 102, 54, 101, 50, 100, 97, 100, 54, 55, 55, 56, 54, 101, 50, 49, 100, 53, 97, 100, 97, 101, 54]
list3=[99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
v4=0
flag=""
for i in range(35):
v8=list1[2*i]
if v8 < 48 or v8 > 57:
v9=v8 - 87
else:
v9=v8 - 48
v10=list2[2*i]
v11=16*v9
if v10 <48 or v10 > 57:
v12=v10-87
else:
v12=v10-48
v4=((v11+v12)^25)
for a in range(32,127):
v5=a
v6=(v5>>4)%16
v7=((16*v5)>>4)%16
if list3[16*v6+v7] == v4:
flag+=chr(a)
print(flag)
flag
flag{Th1s_1s_Simple_Rep1ac3_Enc0d3}
攻防世界 Replace Reverse二星题的更多相关文章
- 攻防世界 misc Exercise 刷题记录
1.base64stego 1.zip伪加密 2. base64文件隐写,在网上找一个脚本
- 攻防世界pwn高手区——pwn1
攻防世界 -- pwn1 攻防世界的一道pwn题,也有一段时间没有做pwn了,找了一道栈题热身,发现还是有些生疏了. 题目流程 拖入IDA中,题目流程如图所示,当v0为1时,存在栈溢出漏洞.在gdb中 ...
- 攻防世界 reverse 进阶 10 Reverse Box
攻防世界中此题信息未给全,题目来源为[TWCTF-2016:Reverse] Reverse Box 网上有很多wp是使用gdb脚本,这里找到一个本地还原关键算法,然后再爆破的 https://www ...
- 攻防世界Web刷题记录(新手区)
攻防世界Web刷题记录(新手区) 1.ViewSource 题如其名 Fn + F12 2.get post 3.robots robots.txt是搜索引擎中访问网站的时候要查看的第一个文件.当一个 ...
- CTF--web 攻防世界web题 robots backup
攻防世界web题 robots https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=0&id=506 ...
- CTF--web 攻防世界web题 get_post
攻防世界web题 get_post https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=0&id=5 ...
- 攻防世界web新手区做题记录
学校信安协会第一次培训结束后的作业,要求把攻防世界的web新手区题目做一遍并写题解. 第一题 view_source 查看源代码右键不能用,但是F12能用,于是找到源代码 输入到flag框即可 后来在 ...
- 记录下做攻防世界的misc题
0x00 记录一下,代表自己做过 0x01 flag_universe 看简介是来自2018年的百越杯. 将文件下载下来后,就一个flag_universe.pcapng文件,wireshark打开. ...
- 攻防世界 reverse evil
这是2017 ddctf的一道逆向题, 挑战:<恶意软件分析> 赛题背景: 员工小A收到了一封邮件,带一个文档附件,小A随手打开了附件.随后IT部门发现小A的电脑发出了异常网络访问请求,进 ...
- 攻防世界 reverse tt3441810
tt3441810 tinyctf-2014 附件给了一堆数据,将十六进制数据部分提取出来, flag应该隐藏在里面,(这算啥子re,) 保留可显示字符,然后去除填充字符(找规律 0.0) 处理脚本: ...
随机推荐
- [BUUCTF][Web][GXYCTF2019]Ping Ping Ping 1
打开靶机对应URL 提示有ip参数 尝试构造url http://714ad4a2-64e2-452b-8ab9-a38df80dc584.node4.buuoj.cn:81/?ip=127.0.0. ...
- .NET Core 集成微信支付签名错误
.NET Core 集成微信支付签名错误 The provided data is tagged with 'Universal' class value '16', but it should ha ...
- 你不得不知道的 MySQL 优化原理
目录 MySQL逻辑架构 MySQL查询过程 客户端/服务端通信协议 查询缓存 查询优化 查询执行引擎 返回结果给客户端 总结 性能优化建议 Scheme设计与数据类型优化 创建高性能索引 索引相关的 ...
- JAVA对象的生命周期(二)-对象的创建
目录 对象创建的几种方式 类加载检查. 内存分配 初始化零值 设置对象头 执行init方法 对象创建的几种方式 new clone newInstance 反序列化 String s = " ...
- Vue3学习(二十一)- 文档管理页面布局修改
写在前面 按照国际惯例,要先聊下生活,吐槽一番,今天是2月14日,也是下午听老妈说,我才知道! 现在真的是对日期节日已经毫无概念可言,只知道星期几. 现在已经觉得写博客也好,学习文章也罢,和写日记一样 ...
- Python实现snap:对齐多张遥感影像的空间范围
本文介绍基于Python中ArcPy模块,实现基于栅格图像批量裁剪栅格图像,同时对齐各个栅格图像的空间范围,统一其各自行数与列数的方法. 首先明确一下我们的需求.现有某一地区的多张栅格遥感影像 ...
- Java 关于变量的赋值
1 /** 2 * 3 * @Description 4 * @author Bytezero·zhenglei! Email:420498246@qq.com 5 * @version 6 * @d ...
- STM32F103xC,xD,xE引脚定义
STM32F103xC,xD,xE引脚定义 由于在使用STM32系列芯片过程中发现互联网没有整理好的引脚定义,因此自己整理一份,方便以后查阅. GPIOA Pin 重新上电时的功能 默认功能 重映射 ...
- vite ts 安装 js-cookie 库,vscode找不到类型说明(有波浪线),解决方案
vite ts 安装 js-cookie 库,vscode找不到类型说明(有波浪线),解决方案 先安装库 https://www.npmjs.com/package/js-cookie 再安装类型 h ...
- 我的电脑 属性 代理 win10 不用的时候记得关闭,git python node 等