• [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
    je $ + "+ hex(getQword(i)).encode() + b"
    ")
            i+=9
        elif codes[i] == 0xF:
            fp.write(b"cmp rflag,1
    je $ - "+ hex(getQword(i)).encode() + b"
    ")
            i+=9
        elif codes[i] == 0x10:
            fp.write(b"push reg
    ")
            i+=1
        elif codes[i] == 0x11:
            fp.write(b"pop reg
    ")
            i+=1
        elif codes[i] == 0x12:
            fp.write(b"pop mem[reg]
    ")
            i+=1
        elif codes[i] == 0x13:
            fp.write(b"push mem[reg]
    ")
            i+=1
        elif codes[i] == 0x20:
            fp.write(b"mov reg," + hex(getQword(i)).encode()+ b"
    ")
            i+=9
        elif codes[i] == 0x21:
            fp.write(b"mov reg,getchar()
    ")
            i+=1
        elif codes[i] == 0x22:
            fp.write(b"putchar(reg)
    ")
            i+=1
        elif codes[i] == 0x30:
            fp.write(b"sadd
    ")
            i+=1
        elif codes[i] == 0x31:
            fp.write(b"ssub
    ")
            i+=1
        elif codes[i] == 0x32:
            fp.write(b"sxor
    ")
            i+=1
        elif codes[i] == 0x33:
            fp.write(b"slhs
    ")
            i+=1
        elif codes[i] == 0x34:
            fp.write(b"srhs
    ")
            i+=1
        elif codes[i] == 0x40:
            fp.write(b"scmp
    ")
            i+=1
        elif codes[i] == 0x80:
            fp.write(b"end
    ")
            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}

  • 相关阅读:
    点击按钮在表格的某一行下,在添加一行(HTML+JS)
    13
    12 stark组件之pop,按钮,url,页面
    11 stark组件之delete按钮、filter过滤
    解决 AttributeError: 'ForeignKey' object has no attribute 're'
    360面经
    4 django篇
    0- 26个面试经典问题回答
    如何学习??
    LeetCode
  • 原文地址:https://www.cnblogs.com/csuchenzc/p/14000723.html
Copyright © 2020-2023  润新知