解题过程中,虽然解出来了,但是磕磕绊绊犯了一些错误,记录一下


分析过程

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二星题的更多相关文章

  1. 攻防世界 misc Exercise 刷题记录

    1.base64stego 1.zip伪加密 2. base64文件隐写,在网上找一个脚本

  2. 攻防世界pwn高手区——pwn1

    攻防世界 -- pwn1 攻防世界的一道pwn题,也有一段时间没有做pwn了,找了一道栈题热身,发现还是有些生疏了. 题目流程 拖入IDA中,题目流程如图所示,当v0为1时,存在栈溢出漏洞.在gdb中 ...

  3. 攻防世界 reverse 进阶 10 Reverse Box

    攻防世界中此题信息未给全,题目来源为[TWCTF-2016:Reverse] Reverse Box 网上有很多wp是使用gdb脚本,这里找到一个本地还原关键算法,然后再爆破的 https://www ...

  4. 攻防世界Web刷题记录(新手区)

    攻防世界Web刷题记录(新手区) 1.ViewSource 题如其名 Fn + F12 2.get post 3.robots robots.txt是搜索引擎中访问网站的时候要查看的第一个文件.当一个 ...

  5. CTF--web 攻防世界web题 robots backup

    攻防世界web题 robots https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=0&id=506 ...

  6. CTF--web 攻防世界web题 get_post

    攻防世界web题 get_post https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=0&id=5 ...

  7. 攻防世界web新手区做题记录

    学校信安协会第一次培训结束后的作业,要求把攻防世界的web新手区题目做一遍并写题解. 第一题 view_source 查看源代码右键不能用,但是F12能用,于是找到源代码 输入到flag框即可 后来在 ...

  8. 记录下做攻防世界的misc题

    0x00 记录一下,代表自己做过 0x01 flag_universe 看简介是来自2018年的百越杯. 将文件下载下来后,就一个flag_universe.pcapng文件,wireshark打开. ...

  9. 攻防世界 reverse evil

    这是2017 ddctf的一道逆向题, 挑战:<恶意软件分析> 赛题背景: 员工小A收到了一封邮件,带一个文档附件,小A随手打开了附件.随后IT部门发现小A的电脑发出了异常网络访问请求,进 ...

  10. 攻防世界 reverse tt3441810

    tt3441810 tinyctf-2014 附件给了一堆数据,将十六进制数据部分提取出来, flag应该隐藏在里面,(这算啥子re,) 保留可显示字符,然后去除填充字符(找规律 0.0) 处理脚本: ...

随机推荐

  1. vscode中python类型注解插件及自动格式化

    # 插件名称 Python Type Hint # 如何ctrl+s保存时格式化,推荐安装yapf包 (flake8貌似不支持有类型注解的) 1.安装yapf包:pip install yapf 2. ...

  2. 【补档_C51单片机】基于C51的蜂鸣器音乐盒工程源码解析(可播放《打上花火》)

    项目地址:https://gitee.com/daycen/c51-music-box 通过Keil uVision3打开即可使用 以前做的一些小硬件,现补档至博客 1 功能及总体方案 1.1 功能描 ...

  3. Vue源码学习(十一):计算属性computed初步学习

    好家伙,   1.Computed实现原理 if (opts.computed) { initComputed(vm,opts.computed); } function initComputed(v ...

  4. NodeJS内存泄露

    p.p1 { margin: 0; font: 13px "Helvetica Neue"; color: rgba(0, 0, 0, 1) } p.p2 { margin: 0; ...

  5. 智联招聘基于 Nebula Graph 的推荐实践分享

    本文首发于 Nebula Graph Community 公众号 本文整理自智联招聘资深工程师李世明在「智联招聘推荐场景应用」的实践分享 搜索推荐架构 在讲具体的应用场景之前,我们先看下智联招聘搜索和 ...

  6. C++ //案列-评委打分 //(容器添加 删除 算法排序 随机数 字符串追加)描述:5名选手 ABCDE,10个评委分别对每一位选手打分,去除最高分,去除评委中的 //的最低分,取平均分

    1 #include<iostream> 2 #include<string> 3 #include<deque> 4 #include<vector> ...

  7. 摆脱鼠标系列 - vscode vim 插件 常用快捷键整理

    列表 只总结当前用到的快捷键,并且对 ctrl+c v w 这三个快捷键还是用vscode,过渡下. 复制当前行 yy 复制当前单词 yaw 移动到下一个单词 w 下移10行 . 这个有不管用了,估计 ...

  8. k8s如何对外访问service

    在Kubernetes(K8s)中,可以通过以下几种方式对外访问Service: 1.NodePort: 这是最常见的对外访问Service的方式.通过将Service的类型设置为NodePort,K ...

  9. 【预训练语言模型】使用Transformers库进行GPT2预训练

    基于 HuggingFace的Transformer库,在Colab或Kaggle进行预训练. 本教程提供:英文数据集wikitext-2和代码数据集的预训练. 注:可以自行上传数据集进行训练 目的: ...

  10. 基于python的固定间隔时间执行实例解析

    一 概念 datetime的用法如下: import datetime. # 打印当前时间 time1 = datetime.datetime.now() print(time1) # 打印按指定格式 ...