攻防世界 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) 处理脚本: ...
随机推荐
- Linux Ubuntu 遇到的一些问题
Ubuntu 国内下载地址:https://mirrors.tuna.tsinghua.edu.cn/# 1. 安装一些常用的软件时,需要下载 amd.deb 类型的包,并使用下面命令安装 sudo ...
- java个人博客
效果浏览 首页 详情页 Aboutme 后台管理 管理/添加博客 添加分类 管理员管理 友情链接 访问地址 前台地址http://localhost 后台地址:http://localhost/adm ...
- 【C++ OOP 02 对象的初始化和清理】构造/析构函数、深/浅拷贝、初始化列表以及静态成员
[对象的初始化和清理] 生活中我们买的电子产品都基本会有出厂设置,在某一天我们不用时候也会删除一些自己信息数据保证安全 C++中的面向对象来源于生活,每个对象也都会有初始设置以及 对象销毁前的清理数据 ...
- 数据结构(三):舞伴配对问题(C++,队列)
好家伙, 题目如下: 1.舞伴配对问题:假设在周末舞会上,男士们和女士们进入舞厅时,各自排成一队.跳舞开始时,依次从男队和女队的队头上各出一人配成舞伴. 2.若两队初始人数不相同,则较长的那一队中未配 ...
- C++ 多线程笔记1 线程的创建
C++ 多线程笔记1 线程的创建 里面代码会用到的头文件 #include <iostream> #include <string> #include <memory&g ...
- CYQ.Data 支持 DaMeng 达梦数据库
DaMeng 达梦数据库介绍: 达梦数据库(DMDB)是中国自主研发的关系型数据库管理系统,由达梦科技股份有限公司开发. 达梦数据库提供了企业级的数据库解决方案,广泛应用于金融.电信.政府.制造等行业 ...
- Mac上LLAMA2大语言模型安装到使用
LLAMA介绍 LLaMA是由Facebook的母公司Meta AI设计的一个新的大型语言模型.LLaMA拥有70亿到650亿个参数的模型集合,是目前最全面的语言模型之一. Llama是目前唯一一个可 ...
- Zabbix 7.0编译部署教程
Zabbix7.0 alpha版本.beta版本已经陆续发布,Zabbix7.0 LTS版本发布时间也越来越近.据了解,新的版本在性能提升.架构优化等新功能方面有非常亮眼的表现,不少小伙伴对此也已经跃 ...
- TI工程师总结的判断ADS129x是否工作正常的方法步骤
当大多数 ADC 出现无响应时,可以通过一些基本的调试技术帮助验证器件是否仍然正常工作.以下是 ADS129x 器件出现无响应时需要采取的一些基本步骤: 为器件通电.然后探测器件电源引脚或最近的去耦电 ...
- KETTLE4个工作中有用的复杂实例--2、两表数据比较,循环取数据,比较后自动同步(部门、单位数据同步)
附:Kettle实战视频教程,需要的朋友可以看看学习下哈~~ kettle实战第一讲-文件和数据库表的互相转换处理_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili kettle实战第二讲-数据库单 ...