HWS2022 winter writeup
HWS2022 硬件冬令营逆向部分 writeup
逆向部分全是 vm 题目,做起来很肝,当然也学到了很多
1. Reverse
1.1. EasyVM
1 | import base64 |
1.2. BabyVM
存在很多花指令,根据花指令特征先编写脚本去除花指令
1 | import ida_bytes |
虚拟机的指令是以一个结构体形式储存,结构体形式如下
1 | struct frame |
0x7DE000
至 0x7DF158
部分是储存指令的内存区域,在这个地方创建结构体数组,可以使我们更加清晰的分析虚拟机指令的组成
通过动态调试我们可以知道 0x7DE000
到 0x7DEA50
部分的 opcode 是用来输出提示信息,以及输入,对我们输入部分进行储存的指令
0x7DEA68
至 0x7DF4E8
指令部分,是进行输入加密和 check 以及结果输出的指令部分,这里我们先利用 IDAPython 提取出对应的指令序列 然后根据逆向出来的指令操作,打印出这部分指令的伪代码 ,打印脚本如下
1 | con = [[6, 0, 18446744073709551615], [26, 0, 125], [28, 18, 18446744073709551615], [1, 0, 119], [1, 1, 114], [1, 2, 111], [1, 3, 110], [1, 6, 103], [1, 7, 33], [24, 0, 18446744073709551615], [24, 1, 18446744073709551615], [24, 2, 18446744073709551615], [24, 3, 18446744073709551615], [24, 6, 18446744073709551615], [24, 7, 18446744073709551615], [1, 0, 10], [24, 0, 18446744073709551615], [25, 18446744073709551615, 18446744073709551615], [1, 8, 256], [26, 8, 225], [30, 25, 18446744073709551615], [6, 0, 18446744073709551615], [4, 8, 0], [9, 8, 1], [29, 19, 18446744073709551615], [6, 0, 18446744073709551615], [26, 0, 123], [31, 3, 18446744073709551615], [6, 0, 18446744073709551615], [26, 0, 103], [31, 3, 18446744073709551615], [6, 0, 18446744073709551615], [26, 0, 97], [31, 3, 18446744073709551615], [6, 0, 18446744073709551615], [26, 0, 108], [31, 3, 18446744073709551615], [6, 0, 18446744073709551615], [26, 0, 102], [31, 3, 18446744073709551615], [18, 9, 9], [1, 10, 225], [3, 7, 9], [3, 6, 10], [17, 6, 66], [13, 6, 2], [27, 6, 7], [31, 3, 18446744073709551615], [7, 9, 1], [7, 10, 1], [26, 9, 32], [30, 42, 18446744073709551615], [1, 0, 99], [1, 1, 111], [1, 2, 114], [1, 3, 114], [1, 6, 101], [1, 7, 99], [24, 0, 18446744073709551615], [24, 1, 18446744073709551615], [24, 2, 18446744073709551615], [24, 3, 18446744073709551615], [24, 6, 18446744073709551615], [24, 7, 18446744073709551615], [1, 0, 116], [1, 1, 108], [1, 2, 121], [1, 3, 33], [1, 6, 10], [24, 0, 18446744073709551615], [24, 1, 18446744073709551615], [24, 2, 18446744073709551615], [24, 3, 18446744073709551615], [24, 6, 18446744073709551615], [25, 18446744073709551615, 18446744073709551615]] |
指令的伪代码如下
1 | __0 : arr[0] = memory[arr[4]] --- arr[4]-- |
通过分析这些伪代码指令 和动态调试,知道了就只是做了一个异或 66 再左移 2 位的操作,从内存中提取出加密后的指令序列,编写代码
1 | arr = [156, 448, 472, 468, 468, 488, 456, 152, 456, 448, 492, 140, 468, 140, 492, 492, 448, 448, 472, 468, 156, 464, 464, 464, 468, 488, 464, 492, 456, 456, 488, 140] |
1.3. babyre
LLVM 还有控制流平坦化,先尝试网上通用的 deflat 脚本,发现会报错,似乎是有一些 汇编指令 angr 没有办法去模拟
这可就很难受了
(呜呜呜)
观察代码块后,发现程序中还是由一些花指令,先去除花指令再说 然后就只能手动去分析流程图中的真实块
然后对每一个真实块用注释的形式去给他一个编号,通过动态调试以及静态分析的方法去弄清除每一个真实块的代码行为
将所有的真实块编号标记好之后我们可以将每一个真实块看作 一行代码 (伪汇编代码)
列出程序逻辑如下
1 | __step 0: input_func |
其中step_19
异或的不是他们 base
加密后的值 而是他们的下标
程序流程分析出来,先编写一遍对应的加密代码,根据加密代码再逆向整个过程
加密代码如下
1 | import libnum |
根据加密代码 再编写解题代码,即可得到 flag
1 | import libnum |
2. Misc
搜到这两篇文章
Higaisa APT最新LNK攻击
https://www.freebuf.com/articles/network/241414.html
使用Winrm.vbs绕过应用白名单执行任意未签名代码的分析
https://www.freebuf.com/articles/system/178339.html
根据文章中说的方法提取出 xls 脚本 如下
1 |
|
将得到的 676d60667a64333665326564333665326564333665326536653265643336656564333665327c
每两个字符切割为一个 16 进制数据,然后再异或 1 输出,即可得到结果
脚本
1 | arr = [0x67, 0x6d, 0x60, 0x66, 0x7a, 0x64, 0x33, 0x36, 0x65, 0x32, 0x65, 0x64, 0x33, 0x36, 0x65, 0x32, 0x65, 0x64, 0x33, 0x36, 0x65, 0x32, 0x65, 0x36, 0x65, 0x32, 0x65, 0x64, 0x33, 0x36, 0x65, 0x65, 0x64, 0x33, 0x36, 0x65, 0x32, 0x7c] |