[GWCTF 2019]babyvm
生活随笔
收集整理的這篇文章主要介紹了
[GWCTF 2019]babyvm
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
系統學習vm虛擬機逆向
64位vm的題目
找到主函數
分析sub_CD1函數:
sub_B5F代表mov操作,其中 0xE1,0xE2...代表不同的寄存器。
?
sub_A64是一個異或操作xor。
sub_AC5是一個讀取操作并判斷他的長度是否等于21
?
sub_956是空操作nop。
?
sub_A08 兩個數相乘操作mul
?
sub_8F0是一個交換操作swap
sub_99c線性運算
?
該函數是對6010A0操作碼內容的執行,一直到0xf4結束
下面我們對操作碼進行虛擬化指令分析?
opcode=[ 0xF5, 0xF1, 0xE1, 0x00, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,0x20, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x01, 0x00, 0x00, 0x00,0xF2, 0xF1, 0xE4, 0x21, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02,0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x22, 0x00, 0x00, 0x00,0xF1, 0xE1, 0x03, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x23,0x00, 0x00, 0x00, 0xF1, 0xE1, 0x04, 0x00, 0x00, 0x00, 0xF2,0xF1, 0xE4, 0x24, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x05, 0x00,0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x25, 0x00, 0x00, 0x00, 0xF1,0xE1, 0x06, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x26, 0x00,0x00, 0x00, 0xF1, 0xE1, 0x07, 0x00, 0x00, 0x00, 0xF2, 0xF1,0xE4, 0x27, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x08, 0x00, 0x00,0x00, 0xF2, 0xF1, 0xE4, 0x28, 0x00, 0x00, 0x00, 0xF1, 0xE1,0x09, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x29, 0x00, 0x00,0x00, 0xF1, 0xE1, 0x0A, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,0x2A, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0B, 0x00, 0x00, 0x00,0xF2, 0xF1, 0xE4, 0x2B, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0C,0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2C, 0x00, 0x00, 0x00,0xF1, 0xE1, 0x0D, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2D,0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0E, 0x00, 0x00, 0x00, 0xF2,0xF1, 0xE4, 0x2E, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0F, 0x00,0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2F, 0x00, 0x00, 0x00, 0xF1,0xE1, 0x10, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x30, 0x00,0x00, 0x00, 0xF1, 0xE1, 0x11, 0x00, 0x00, 0x00, 0xF2, 0xF1,0xE4, 0x31, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x12, 0x00, 0x00,0x00, 0xF2, 0xF1, 0xE4, 0x32, 0x00, 0x00, 0x00, 0xF1, 0xE1,0x13, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x33, 0x00, 0x00,0x00, 0xF4, 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, 0x00, 0xF5, 0xF1,0xE1, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x01, 0x00, 0x00,0x00, 0xF2, 0xF1, 0xE4, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE1,0x01, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x02, 0x00, 0x00, 0x00,0xF2, 0xF1, 0xE4, 0x01, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02,0x00, 0x00, 0x00, 0xF1, 0xE2, 0x03, 0x00, 0x00, 0x00, 0xF2,0xF1, 0xE4, 0x02, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x03, 0x00,0x00, 0x00, 0xF1, 0xE2, 0x04, 0x00, 0x00, 0x00, 0xF2, 0xF1,0xE4, 0x03, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x04, 0x00, 0x00,0x00, 0xF1, 0xE2, 0x05, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,0x04, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x05, 0x00, 0x00, 0x00,0xF1, 0xE2, 0x06, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x05,0x00, 0x00, 0x00, 0xF1, 0xE1, 0x06, 0x00, 0x00, 0x00, 0xF1,0xE2, 0x07, 0x00, 0x00, 0x00, 0xF1, 0xE3, 0x08, 0x00, 0x00,0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00, 0x00, 0xF6, 0xF7, 0xF1,0xE4, 0x06, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x07, 0x00, 0x00,0x00, 0xF1, 0xE2, 0x08, 0x00, 0x00, 0x00, 0xF1, 0xE3, 0x09,0x00, 0x00, 0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00, 0x00, 0xF6,0xF7, 0xF1, 0xE4, 0x07, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x08,0x00, 0x00, 0x00, 0xF1, 0xE2, 0x09, 0x00, 0x00, 0x00, 0xF1,0xE3, 0x0A, 0x00, 0x00, 0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00,0x00, 0xF6, 0xF7, 0xF1, 0xE4, 0x08, 0x00, 0x00, 0x00, 0xF1,0xE1, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x13, 0x00, 0x00,0x00, 0xF8, 0xF1, 0xE4, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xE7,0x13, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0E, 0x00, 0x00, 0x00,0xF1, 0xE2, 0x12, 0x00, 0x00, 0x00, 0xF8, 0xF1, 0xE4, 0x0E,0x00, 0x00, 0x00, 0xF1, 0xE7, 0x12, 0x00, 0x00, 0x00, 0xF1,0xE1, 0x0F, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x11, 0x00, 0x00,0x00, 0xF8, 0xF1, 0xE4, 0x0F, 0x00, 0x00, 0x00, 0xF1, 0xE7,0x11, 0x00, 0x00, 0x00, 0xF] reg = {0xe1:'eax',0xe2:'ebx',0xe3:'ecx',0xe5:'edx'} operation = {0xf1:'mov',0xf2:'xor',0xf5:'read',0xf4:'nop',0xf7:'add',0xf8:'swap',0xf6:'mul'} i = 0 for j in range(len(opcode)):if(opcode[i] == 0xF1 ):print('mov ',end='')if (opcode[i+1] == 0xe1):print('eax ' + 'flag[' + str(opcode[i + 2]) + ']')elif(opcode[i+1] == 0xe2):print('ebx '+'flag['+str(opcode[i+2])+']')elif(opcode[i+1] == 0xe3):print('ecx ','flag['+str(opcode[i+2])+']')elif(opcode[i+1] == 0xe4):print('flag['+str(opcode[i+2])+'] '+'eax')elif(opcode[i+1] == 0xe5):print('edx '+'flag['+str(opcode[i+2])+']')elif(opcode[i+1] == 0xe7):print('flag['+str(opcode[i+2])+'] '+'ebx')i+=6elif(opcode[i] == 0xf2):print('xor eax ecx')i+=1elif(opcode[i] == 0xf5):print('read')i+=1elif(opcode[i] == 0xf4):print('nop')i+=1elif(opcode[i] == 0xf7):print('eax=eax*ecx')i+=1elif(opcode[i] == 0xf8):print('swap eax ebx')i+=1elif(opcode[i] == 0xf6):print('mul eax=ecx+2*ebx+3*eax')i+=1else:i+=1?得到,注意我們得到兩段代碼。
read mov eax flag[0] xor eax ecx mov flag[32] eax mov eax flag[1] xor eax ecx mov flag[33] eax mov eax flag[2] xor eax ecx mov flag[34] eax mov eax flag[3] xor eax ecx mov flag[35] eax mov eax flag[4] xor eax ecx mov flag[36] eax mov eax flag[5] xor eax ecx mov flag[37] eax mov eax flag[6] xor eax ecx mov flag[38] eax mov eax flag[7] xor eax ecx mov flag[39] eax mov eax flag[8] xor eax ecx mov flag[40] eax mov eax flag[9] xor eax ecx mov flag[41] eax mov eax flag[10] xor eax ecx mov flag[42] eax mov eax flag[11] xor eax ecx mov flag[43] eax mov eax flag[12] xor eax ecx mov flag[44] eax mov eax flag[13] xor eax ecx mov flag[45] eax mov eax flag[14] xor eax ecx mov flag[46] eax mov eax flag[15] xor eax ecx mov flag[47] eax mov eax flag[16] xor eax ecx mov flag[48] eax mov eax flag[17] xor eax ecx mov flag[49] eax mov eax flag[18] xor eax ecx mov flag[50] eax mov eax flag[19] xor eax ecx mov flag[51] eax nop read mov eax flag[0] mov ebx flag[1] xor eax ecx mov flag[0] eax mov eax flag[1] mov ebx flag[2] xor eax ecx mov flag[1] eax mov eax flag[2] mov ebx flag[3] xor eax ecx mov flag[2] eax mov eax flag[3] mov ebx flag[4] xor eax ecx mov flag[3] eax mov eax flag[4] mov ebx flag[5] xor eax ecx mov flag[4] eax mov eax flag[5] mov ebx flag[6] xor eax ecx mov flag[5] eax mov eax flag[6] mov ebx flag[7] mov ecx flag[8] mov edx flag[12] mul eax=ecx+2*ebx+3*eax eax=eax*ecx mov flag[6] eax mov eax flag[7] mov ebx flag[8] mov ecx flag[9] mov edx flag[12] mul eax=ecx+2*ebx+3*eax eax=eax*ecx mov flag[7] eax mov eax flag[8] mov ebx flag[9] mov ecx flag[10] mov edx flag[12] mul eax=ecx+2*ebx+3*eax eax=eax*ecx mov flag[8] eax mov eax flag[13] mov ebx flag[19] swap eax ebx mov flag[13] eax mov flag[19] ebx mov eax flag[14] mov ebx flag[18] swap eax ebx mov flag[14] eax mov flag[18] ebx mov eax flag[15] mov ebx flag[17] swap eax ebx mov flag[15] eax mov flag[17] ebx?我們用sub_F83的check函數會得到假的flag:
This_is_not_flag_233查看qword_2022A8的交叉引用,找到真正的check函數,再結合第二段寫腳本
from z3 import * import reflag = '69 45 2A 37 09 17 C5 0B 5C 72 33 76 33 21 74 31 5F 33 73 72'.split(' ') flag = [int(_, 16) for _ in flag]# 置換 flag[15], flag[17] = flag[17], flag[15] flag[14], flag[18] = flag[18], flag[14] flag[19], flag[13] = flag[13], flag[19]# z3 a6, a7, a8 = BitVecs('a6 a7 a8', 8) s = Solver() s.add(flag[6] == (a8 + 2 * a7 + 3 * a6) * flag[12]) s.add(flag[7] == (flag[9] + 2 * a8 + 3 * a7) * flag[12]) s.add(flag[8] == (flag[10] + 2 * flag[9] + 3 * a8) * flag[12]) if s.check() == sat:m = s.model()for i in m:index = int(re.search(r'\d+', str(i)).group())flag[index] = m[i].as_long()# 異或 for i in range(5, -1, -1):flag[i] ^= flag[i + 1]print(''.join([chr(_) for _ in flag]))得到flag
flag{Y0u_hav3_r3v3rs3_1t!}
參考[GWCTF 2019]babyvm??
babyvm-vm逆向
[GW-CTF2019] babyvm
總結
以上是生活随笔為你收集整理的[GWCTF 2019]babyvm的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [HDCTF2019]MFC
- 下一篇: Hgame 2022 Answer‘s