[hgame 2023]vm

cunno發表於2024-11-07

---這是我的第一個部落格---如有錯誤希望大佬能指出---

[hgame 2023]vm

進來之後看到第8行和第12行有不知道的函式,分別是sub_140001000,sub_1400010B0。

進入第8行的sub_140001000看看。

[hgame 2023]vm

再進入sub_140001060。

[hgame 2023]vm

會發現初始化了一些以a1為基地址的資料。

vm逆向,即虛擬機器逆向。這裡的虛擬機器類似java虛擬機器,python虛擬機器,能夠解釋一系列自研的指令。

而這裡對a1的初始化,很可能是對自研的指令系統的暫存器初始化。

建一個結構體方便下面的分析。

[hgame 2023]vm

在Structure視窗右鍵,點選add struct type或者按快捷鍵insert可以新建一個結構體。

我命名為了VM。

[hgame 2023]vm

在ends處點選d可以新建結構體成員。

根據上上上個圖,會發現也許可以這樣建結構體。

[hgame 2023]vm

不過這個題有提示怎麼建結構體。

[hgame 2023]vm

右鍵想轉為結構體的變數可以轉為指定結構體,這裡轉a1。

[hgame 2023]vm

[hgame 2023]vm

[hgame 2023]vm

會發現這個函式需要返回0才算成功。

然後進入這個函式看看。

[hgame 2023]vm

這也是a1,把它轉成結構體。

[hgame 2023]vm

會發現如果這個陣列指定下標的值如果不是255,就執行下面的函式。返回值是zzz。那麼zzz必須是0。

byte_140005360陣列裡也許就是這道題的加密過程的指令了。進入sub_140001940函式看看。

[hgame 2023]vm

又有a1,把a1轉成結構體。

[hgame 2023]vm

看到很多case。這個陣列也是上面說到的陣列,進去看看。

[hgame 2023]vm

果然是一堆。那麼可以把陣列重新命名為opcode。

回到之前的函式,每個case下面的函式就是根據不同指令 [opcode陣列] 做出的不同處理。

並且陣列的下標是結構體a1的成員xxx,那麼xxx就是指令暫存器ip。

把每個case裡面的函式的a1都轉成結構體。

[hgame 2023]vm

進入case 0,發現根據opcode的ip的下一個資料執行不同賦值操作。

如果在main函式里重新命名了,會發現陣列dword_140005040就是存放使用者輸入的flag的陣列。

下面是重新命名後的。

[hgame 2023]vm

會發現裡面涉及到opcode[ip~ip+3],一共4位元組的資料。函式的後面ip也進行了+4。

[hgame 2023]vm

看外層函式的case 1,會發現把暫存器的值賦值到了一個什麼陣列。

[hgame 2023]vm

再看外層函式的case 2,把同樣的陣列的值賦給暫存器。

這個函式代表記憶體區域的那部分呢?我們會發現yyy進行了自增自減。可以猜測是棧。而yyy代表sp。

那麼這兩個函式分別是入棧和出棧。

[hgame 2023]vm

看這個函式,會發現是一些有關暫存器的運算。

[hgame 2023]vm

在這個函式,會發現zzz代表reg[0]和reg[1]相不相等。相等則是0。相當於組合語言的cmp,比較之後給zzz賦值。

[hgame 2023]vm

這個函式相當於jmp ip+1即jmp opcode[ip+1]。

[hgame 2023]vm

這個函式即je opcode[ip+1]。

[hgame 2023]vm

這個函式即jne opcode[ip+1]。

下面是我的程式碼。

python指令碼
 opcode = [0x00, 0x03, 0x02, 0x00, 0x03, 0x00, 0x02, 0x03, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x02, 0x32,
          0x03, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
          0x01, 0x00, 0x00, 0x03, 0x02, 0x64, 0x03, 0x00, 0x02, 0x03,
          0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x01, 0x00, 0x00, 0x03,
          0x00, 0x08, 0x00, 0x02, 0x02, 0x01, 0x03, 0x04, 0x01, 0x00,
          0x03, 0x05, 0x02, 0x00, 0x03, 0x00, 0x01, 0x02, 0x00, 0x02,
          0x00, 0x01, 0x01, 0x00, 0x00, 0x03, 0x00, 0x01, 0x03, 0x00,
          0x03, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x01, 0x28,
          0x04, 0x06, 0x5F, 0x05, 0x00, 0x00, 0x03, 0x03, 0x00, 0x02,
          0x01, 0x00, 0x03, 0x02, 0x96, 0x03, 0x00, 0x02, 0x03, 0x00,
          0x00, 0x00, 0x00, 0x04, 0x07, 0x88, 0x00, 0x03, 0x00, 0x01,
          0x03, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03,
          0x01, 0x28, 0x04, 0x07, 0x63, 0xFF, 0xFF]
ip = 0
while opcode[ip] != 255:
   print(f"{str(ip)+':':<8}",end='')
   match opcode[ip]:
      case 0:
         match opcode[ip+1]:
            case 0:
               print("mov    reg[0] input[reg[2]]")
            case 1:
               print("mov    input[reg[2]] reg[0]")
            case 2:
               print(f"mov    reg[{opcode[ip+2]}] reg[{opcode[ip+3]}]")
            case 3:
               print(f"mov    reg[{opcode[ip+2]}] {opcode[ip+3]}")
         ip+=4
      case 1:
         match opcode[ip+1]:
            case 0:
               print("push   reg[0]")
            case 1:
               print("push   reg[0]")
            case 2:
               print("push   reg[2]")
            case 3:
               print("push   reg[3]")
         ip+=2
      case 2:
         match opcode[ip+1]:
            case 0:
               print("pop    reg[0]")
            case 1:
               print("pop    reg[1]")
            case 2:
               print("pop    reg[2]")
            case 3:
               print("pop    reg[3]")
         ip+=2
      case 3:
         match opcode[ip+1]:
            case 0:
               print(f"add    reg[{opcode[ip+2]}] reg[{opcode[ip+3]}]")
            case 1:
               print(f"sub    reg[{opcode[ip+2]}] reg[{opcode[ip+3]}]")
            case 2:
               print(f"mul    reg[{opcode[ip+2]}] reg[{opcode[ip+3]}]")
            case 3:
               print(f"xor    reg[{opcode[ip+2]}] reg[{opcode[ip+3]}]")
            case 4:
               print(f"shl    reg[{opcode[ip+2]}] reg[{opcode[ip+3]}]")
               # print(f"        and    reg[{opcode[ip+2]}] 0xFF00")
            case 5:
               print(f"shr    reg[{opcode[ip+2]}] reg[{opcode[ip+3]}]")
         ip+=4
      case 4:
         print("cmp    reg[0] reg[1]")
         ip+=1
      case 5:
         print(f"jmp    {opcode[ip+1]}")
         ip+=2
      case 6:
         print(f"je     {opcode[ip+1]}")
         ip+=2
      case 7:
         print(f"jne    {opcode[ip+1]}")
         ip+=2

下面是得出的結果。

偽彙編程式碼
 0:      mov    reg[2] 0
4:      add    reg[2] reg[3]
8:      mov    reg[0] input[reg[2]]
12:     mov    reg[1] reg[0]
16:     mov    reg[2] 50
20:     add    reg[2] reg[3]
24:     mov    reg[0] input[reg[2]]
28:     add    reg[1] reg[0]
32:     mov    reg[2] 100
36:     add    reg[2] reg[3]
40:     mov    reg[0] input[reg[2]]
44:     xor    reg[1] reg[0]
48:     mov    reg[0] 8
52:     mov    reg[2] reg[1]
56:     shl    reg[1] reg[0]
		and    reg[1] 0xFF00
60:     shr    reg[2] reg[0]
64:     add    reg[1] reg[2]
68:     mov    reg[0] reg[1]
72:     push   reg[0]
74:     mov    reg[0] 1
78:     add    reg[3] reg[0]
82:     mov    reg[0] reg[3]
86:     mov    reg[1] 40
90:     cmp    reg[0] reg[1]
91:     je     95
93:     jmp    0
95:     mov    reg[3] 0
99:     pop    reg[1]
101:    mov    reg[2] 150
105:    add    reg[2] reg[3]
109:    mov    reg[0] input[reg[2]]
113:    cmp    reg[0] reg[1]
114:    jne    136
116:    mov    reg[0] 1
120:    add    reg[3] reg[0]
124:    mov    reg[0] reg[3]
128:    mov    reg[1] 40
132:    cmp    reg[0] reg[1]
133:    jne    99

然後不會了呢。

相關文章