[UNCTF2020]BetterCpu WriteUp
这题不同前一题虚拟机ezvm一样,指令很多而且复杂,需要通过写文档和脚本来化简过程。

直接丢进IDA7.2(如果使用IDA7.0则虚拟机的emulator部分会分析出错)查看。
进入main函数后按F5反编译,再进入ezvm::ezvm()里看构造函数的初始化,因为出题人已经给了符号表,所以捋清整个控制流其实是不难的(比赛时没做出来,问就是没加载符号表和不会写脚本)。&v1 + 4的地址就是局部变量enc_flag的地址,故unk_409020就是加密后的flag。
怎么加载符号表?就是进入IDA7.2时会弹出一个关于DWARF debug informa的对话框,选Yes就行了 。 
然后进入ezvm::run(),里面一大段switch显然就是虚拟机的emulator部分,而且显然是个栈式虚拟机(什么是堆栈虚拟机和寄存器虚拟机?)如果还不清楚,后面写脚本生成的伪汇编代码就会看的更清楚。
需要注意的是,这个虚拟机栈的sp并不是指向栈的第一个元素,而是指向第一个元素的前面一个元素。
下面是虚拟机机器码的文档(其实也可以不用写)。
BetterCpu Virtual Machine Instructment 9bytes
0xEu
cmp rflag,1
je $+idata 9bytes
0xFu
cmp rflag,1
je $-idata 0x10u
push reg 0x11u
pop reg 0x12u
pop mem[reg] 0x13u
push mem[reg] 9bytes
0x20u
mov reg,idata 0x21u
mov reg,getchar() 0x22u
putchar(reg) 0x30u
sadd 0x31u
ssub 0x32u
sxor 0x33u
slhs 0x34u
srhs 0x40u
scmp 0x80u
return
其中sdd,ssub,sxor,scmp是我自己编的指令方便写脚本,请读者可以对照反编译结构自行理解。
下面就可以写脚本将机器码翻译成汇编代码了。
codes =[
0x20, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x12, 0x21, 0x10, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x13, 0x30, 0x11, 0x12, 0x20, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x30, 0x12, 0x20, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x20, 0x2C,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x0F,
0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x12, 0x20,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x30,
0x11, 0x13, 0x20, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x30, 0x20, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x32, 0x20, 0x42, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x10, 0x31, 0x20, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x13, 0x30, 0x11, 0x12, 0x20, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x30, 0x12,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
0x20, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x40, 0x0F, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x12, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x13, 0x30, 0x11, 0x13, 0x20, 0x50, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x13, 0x30, 0x11, 0x13, 0x40, 0x0E, 0x98,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x30, 0x12, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x20,
0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40,
0x0F, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x20,
0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x20,
0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x20,
0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x20,
0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x20,
0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x20,
0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x20,
0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x20,
0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x80,
0x20, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x20, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
] fp = open('./codes.asm','wb')
def getQword(i):
return (codes[i+1] + (codes[i+2] << 8) + (codes[i+3] << 16) + (codes[i+4] << 32) + (codes[i+5] << 8) +
(codes[i+6] << 40) + (codes[i+7] << 48) + (codes[i+8] << 56)) i = 0
while i < len(codes):
if codes[i] == 0xE:
fp.write(b"cmp rflag,1\nje $ + "+ hex(getQword(i)).encode() + b"\n")
i+=9
elif codes[i] == 0xF:
fp.write(b"cmp rflag,1\nje $ - "+ hex(getQword(i)).encode() + b"\n")
i+=9
elif codes[i] == 0x10:
fp.write(b"push reg\n")
i+=1
elif codes[i] == 0x11:
fp.write(b"pop reg\n")
i+=1
elif codes[i] == 0x12:
fp.write(b"pop mem[reg]\n")
i+=1
elif codes[i] == 0x13:
fp.write(b"push mem[reg]\n")
i+=1
elif codes[i] == 0x20:
fp.write(b"mov reg," + hex(getQword(i)).encode()+ b"\n")
i+=9
elif codes[i] == 0x21:
fp.write(b"mov reg,getchar()\n")
i+=1
elif codes[i] == 0x22:
fp.write(b"putchar(reg)\n")
i+=1
elif codes[i] == 0x30:
fp.write(b"sadd\n")
i+=1
elif codes[i] == 0x31:
fp.write(b"ssub\n")
i+=1
elif codes[i] == 0x32:
fp.write(b"sxor\n")
i+=1
elif codes[i] == 0x33:
fp.write(b"slhs\n")
i+=1
elif codes[i] == 0x34:
fp.write(b"srhs\n")
i+=1
elif codes[i] == 0x40:
fp.write(b"scmp\n")
i+=1
elif codes[i] == 0x80:
fp.write(b"end\n")
break
生成的伪汇编代码如下:
mov reg,0x57
putchar(reg)
mov reg,0x65
putchar(reg)
mov reg,0x31
putchar(reg)
mov reg,0x63
putchar(reg)
mov reg,0x30
putchar(reg)
mov reg,0x6d
putchar(reg)
mov reg,0x65
putchar(reg)
mov reg,0xa
putchar(reg)
mov reg,0x50
putchar(reg)
mov reg,0x6c
putchar(reg)
mov reg,0x65
putchar(reg)
mov reg,0x61
putchar(reg)
mov reg,0x73
putchar(reg)
mov reg,0x65
putchar(reg)
mov reg,0x20
putchar(reg)
mov reg,0x49
putchar(reg)
mov reg,0x6e
putchar(reg)
mov reg,0x50
putchar(reg)
mov reg,0x75
putchar(reg)
mov reg,0x74
putchar(reg)
mov reg,0x3a
putchar(reg)
mov reg,0xa
putchar(reg)
;print Welc0me Input mov reg,0x0
push reg
pop mem[reg] ;将UserInput字符串放入memory+0x100处
loop_1:
mov reg,getchar()
push reg
mov reg,0x100
push reg
mov reg,0x0
push mem[reg]
;stack men[reg] 0x100 UserInput
sadd
pop reg
pop mem[reg]
mov reg,0x1
push reg
mov reg,0x0
push mem[reg]
sadd
pop mem[reg]
mov reg,0x0
push mem[reg]
mov reg,0x2c
push reg
scmp
cmp rflag,1 ;循环够0x2C次
je loop_1 mov reg,0x0
push reg
pop mem[reg] loop_2:
mov reg,0x100
push reg
mov reg,0x0
push mem[reg]
sadd
pop reg
push mem[reg];pointer to UserInput
mov reg,0x66
push reg
sadd
mov reg,0x36
push reg
sxor
mov reg,0x42
push reg
ssub
mov reg,0x100
push reg
mov reg,0x0
push mem[reg]
sadd
pop reg
pop mem[reg]
;enc_flag[i] == (UserInput[i] + 0x66)^0x36-0x42
mov reg,0x1
push reg
mov reg,0x0
push mem[reg]
sadd
pop mem[reg]
mov reg,0x0
push mem[reg]
mov reg,0x2c
push reg
scmp
cmp rflag,1
je loop_2 mov reg,0x0
push reg
pop mem[reg]
mov reg,0x100
push reg
mov reg,0x0
push mem[reg]
sadd
pop reg
push mem[reg]
mov reg,0x150
push reg
mov reg,0x0
push mem[reg]
sadd
pop reg
push mem[reg]
scmp
cmp rflag,1
je $ + 0x98
mov reg,0x1
push reg
mov reg,0x0
push mem[reg]
sadd
pop mem[reg]
mov reg,0x0
push mem[reg]
mov reg,0x2c
push reg
scmp
cmp rflag,1
je $ - 0x63 ;print Success
mov reg,0x53
putchar(reg)
mov reg,0x75
putchar(reg)
mov reg,0x63
putchar(reg)
mov reg,0x63
putchar(reg)
mov reg,0x65
putchar(reg)
mov reg,0x73
putchar(reg)
mov reg,0x73
putchar(reg)
mov reg,0x21
putchar(reg)
mov reg,0xa
putchar(reg)
end
加密过程很简单,注释已经写好在伪汇编代码里了,直接写脚本得flag:
#include<iostream>
#include<string>
using namespace std; int enc_flag[]= {171,160,189,170,184,149,74,86,87,77,177,72,67,177,183,173,177,92,187,170,170,187,172,177,74,182,175,160,177,71,66,92,121,173,177,91,107,177,108,104,107,94,147,4,0};
string flag;
int main(void){
for(int i = 0;i < 0x2c; ++i){
flag += ((enc_flag[i]+0x42)^0x36)-0x66;
}
cout << flag << endl;
return 0;
}
flag: unctf{THIS_VM_is_Better_Than_YLB's_E5_2650}
<s>YLBNB!</s>
[UNCTF2020]BetterCpu WriteUp的更多相关文章
- UNCTF2020 web writeup
1.Easy_ssrf 给了file_get_contents,直接读取flag即可 2.Easyunserialize 利用点在 构造uname反序列化逃逸即可 3.Babyeval 两个过滤,绕过 ...
- 2016第七季极客大挑战Writeup
第一次接触CTF,只会做杂项和一点点Web题--因为时间比较仓促,写的比较简略.以后再写下工具使用什么的. 纯新手,啥都不会.处于瑟瑟发抖的状态. 一.MISC 1.签到题 直接填入题目所给的SYC{ ...
- ISCC2016 WriteUp
日期: 2016-05-01~ 注:隔了好久才发布这篇文章,还有两道Pwn的题没放,过一阵子放上.刚开始做这个题,后来恰巧赶上校内CTF比赛,就把重心放在了那个上面. 这是第一次做类似于CTF的题,在 ...
- 参加 Tokyo Westerns / MMA CTF 2nd 2016 经验与感悟 TWCTF 2016 WriteUp
洒家近期参加了 Tokyo Westerns / MMA CTF 2nd 2016(TWCTF) 比赛,不得不说国际赛的玩法比国内赛更有玩头,有的题给洒家一种一看就知道怎么做,但是做出来还需要洒家拍一 ...
- 爱春秋之戏说春秋 Writeup
爱春秋之戏说春秋 Writeup 第一关 图穷匕见 这一关关键是给了一个图片,将图片下载到本地后,打开以及查看属性均无任何发现,尝试把图片转换为.txt格式.在文本的最后发现这样一串有规律的代码: 形 ...
- 《安全智库》:48H急速夺旗大战通关writeup(通关策略)
作者:ByStudent 题目名字 题目分值 地址 MallBuilder2 350 mall.anquanbao.com.cn MallBuilder1 200 mall.anquanbao.c ...
- iscc2016 pwn部分writeup
一.pwn1 简单的32位栈溢出,定位溢出点后即可写exp gdb-peda$ r Starting program: /usr/iscc/pwn1 C'mon pwn me : AAA%AAsAAB ...
- We Chall-Training: Encodings I -Writeup
MarkdownPad Document html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,ab ...
- We Chall-Encodings: URL -Writeup
MarkdownPad Document html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,ab ...
随机推荐
- 【C语言C++编程学习笔记】基础语法,第一个简单的实例编程入门教程!
C语言/C++编程学习:一个简单的实例 让我们来看一个简单的C语言程序.从下面的程序可以看出编写C语言程序的一些基本特征. 如果你能知道该程序将会在显示器上显示一些内容,那说明你还是知道一些的! ...
- 【图论】USACO11JAN Roads and Planes G
题目内容 洛谷链接 Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到\(T\)个城镇 (\(1 <= T <= 25,000\)),编号为\(1\)到\ ...
- 自定义常用input表单元素一:纯css 实现自定义checkbox复选框
最下面那个是之前写的 今天在做项目的时候发现,之前写的貌似还是有点多,起码增加的span标签可以去掉,这样保持和原生相同的结构最好的,仅仅是样式上的变化.今天把项目中的这个给更新上来.下面就直接还是 ...
- spring boot:用dynamic-datasource-spring-boot-starter配置多数据源访问seata(seata 1.3.0 / spring boot 2.3.3)
一,dynamic-datasource-spring-boot-starter的优势? 1,dynamic-datasource-spring-boot-starter 是一个基于springboo ...
- linux设置系统变量
[root@localhost test]# export AUTHOR=brady [root@localhost test]# echo $AUTHOR brady [root@localhost ...
- PowerShell 定时输出citrix desktop昨日连接会话
asnp citrix*$now_date = [datetime]::Today$day2 = [datetime]::Today - [TimeSpan]::FromHours(24)$fiel_ ...
- 用Hugo在gitee上构建博客(Windows环境下)
目录 用Hugo在gitee上构建博客(Windows环境下) 1.为什么要用gitee? 2.安装git 3.安装Hugo 4.创建远程仓库 5.搭建博客 (以下所有命令都在git bash中输入) ...
- ucore操作系统学习(三) ucore lab3虚拟内存管理分析
1. ucore lab3介绍 虚拟内存介绍 在目前的硬件体系结构中,程序要想在计算机中运行,必须先加载至物理主存中.在支持多道程序运行的系统上,我们想要让包括操作系统内核在内的各种程序能并发的执行, ...
- Linux入门到放弃之六《磁盘和文件系统管理三》
设置磁盘配额 对之前创建的逻辑卷设置磁盘配额,要求用户student对该逻辑卷 容量的软限制是:5G,硬限制是7G,文件个数软限制为:25个,硬限制为30个. (1)首先对/etc/fstab文件进行 ...
- git常见操作和指令
1.指令集 1.1 本地与远程操作 创建文件 echo > README.md(文件名) 创建文件时输入信息 echo "(message)" >> README ...