16位簡單ASM題的記錄——[HGAME 2022 week1]easyasm

demo41發表於2024-06-03

第一次遇見16位,和純看彙編的題目,記錄一下

DIE

16位,IDA用32位或者64位都可以開啟

IDA

主要彙編部分

seg003:0000 ; =============== S U B R O U T I N E =======================================
seg003:0000
seg003:0000 ; Attributes: noreturn
seg003:0000
seg003:0000                 public start
seg003:0000 start           proc near
seg003:0000                 mov     ax, seg dseg
seg003:0003                 mov     ds, ax          ; 資料段暫存器ds。
seg003:0005                 assume ds:dseg
seg003:0005                 mov     ax, seg seg001  ; 告訴彙編器ds暫存器現在指向dseg段。
seg003:0008                 mov     es, ax          ; 額外段暫存器es。
seg003:000A                 assume es:seg001
seg003:000A                 mov     si, 0           ; 告訴彙編器es暫存器現在指向seg001段。
seg003:000A                                         ; 將暫存器si置零,用於遍歷陣列或字串。
seg003:000D
seg003:000D loc_100DD:                              ; CODE XREF: start+38↓j
seg003:000D                 cmp     si, 28          ; 比較暫存器si的值與28(即檢查是否已經處理了28個位元組)。
seg003:0010                 jz      short loc_10135 ; 成功跳轉
seg003:0010                                         ; 如果si等於28,跳轉到標籤loc_10135。
seg003:0012                 xor     ax, ax          ; 將暫存器ax清零。
seg003:0014                 mov     al, [si]        ; 將ds:[si]處的位元組值載入到al(si是索引暫存器,指向當前要處理的資料位元組)。
seg003:0016                 shl     al, 1
seg003:0018                 shl     al, 1
seg003:001A                 shl     al, 1
seg003:001C                 shl     al, 1           ; 將al中的值左移4次(每次左移一位,相當於乘以16)。
seg003:001E                 push    ax              ; 將ax的值壓入堆疊。
seg003:001F                 xor     ax, ax          ; 將暫存器ax清零。
seg003:0021                 mov     al, [si]        ; 將ds:[si]處的位元組值再次載入到al。
seg003:0023                 shr     al, 1
seg003:0025                 shr     al, 1
seg003:0027                 shr     al, 1
seg003:0029                 shr     al, 1           ; 將al中的值右移4次(每次右移一位,相當於除以16)。
seg003:002B                 pop     bx              ; 將堆疊中的值,即左移處理後的值,彈出到暫存器bx。
seg003:002C                 add     ax, bx          ; 將ax和bx的值相加,結果存入ax。
seg003:002E                 xor     ax, 17h         ; 將ax的值與17h(23十進位制)異或。
seg003:0031                 add     si, 1           ; 將si加1,指向下一個位元組。
seg003:0034                 cmp     al, es:[si-1]   ; 將al中的值與es:[si-1]處的值比較。
seg003:0038                 jz      short loc_100DD ; 如果相等,跳回到標籤loc_100DD繼續處理下一個位元組。
seg003:003A                 mov     ax, 0B800h      ; 將影片記憶體段地址B800h載入到ax。
seg003:003D                 mov     es, ax          ; 將暫存器ax的值(即影片記憶體段地址B800h)載入到額外段暫存器es。
seg003:003F                 assume es:nothing
seg003:003F                 mov     byte ptr es:0, 77h ; 'w' ; 告訴彙編器es暫存器現在指向影片記憶體段。
seg003:0045                 mov     byte ptr es:2, 72h ; 'r'
seg003:004B                 mov     byte ptr es:4, 6Fh ; 'o'
seg003:0051                 mov     byte ptr es:6, 6Eh ; 'n'
seg003:0057                 mov     byte ptr es:8, 67h ; 'g'
seg003:005D                 mov     byte ptr es:0Ah, 21h ; '!' ; 將字串“wrong!”依次寫入影片記憶體,顯示在螢幕上。
seg003:0063
seg003:0063 loc_10133:                              ; CODE XREF: start:loc_10133↓j
seg003:0063                 jmp     short loc_10133 ; 無限迴圈,使程式停止在此。
seg003:0065 ; ---------------------------------------------------------------------------
seg003:0065
seg003:0065 loc_10135:                              ; CODE XREF: start+10↑j
seg003:0065                 mov     ax, 0B800h
seg003:0068                 mov     es, ax
seg003:006A                 mov     byte ptr es:0, 72h ; 'r'
seg003:0070                 mov     byte ptr es:2, 69h ; 'i'
seg003:0076                 mov     byte ptr es:4, 67h ; 'g'
seg003:007C                 mov     byte ptr es:6, 68h ; 'h'
seg003:0082                 mov     byte ptr es:8, 74h ; 't'
seg003:0088                 mov     byte ptr es:0Ah, 21h ; '!' ; 將字串“right!”依次寫入影片記憶體,顯示在螢幕上。
seg003:008E
seg003:008E loc_1015E:                              ; CODE XREF: start:loc_1015E↓j
seg003:008E                 jmp     short loc_1015E ; 無限迴圈,使程式停止在此。
seg003:008E start           endp
seg003:008E
seg003:008E seg003          ends
seg003:008E
seg003:008E
seg003:008E                 end start

dseg段

dseg:0000 ; Segment type: Pure data
dseg:0000 dseg            segment para public 'DATA' use16
dseg:0000                 assume cs:dseg
dseg:0000 aHgameFillInYou db 'hgame{Fill_in_your_flag}',0
dseg:0019                 db    0
dseg:001A                 db    0
dseg:001B                 db    0
dseg:001C                 db    0
dseg:001D                 db    0
dseg:001E                 db    0
dseg:001F                 db    0
dseg:0020                 db    0
dseg:0021                 db    0
dseg:0022                 db    0
dseg:0023                 db    0
dseg:0024                 db    0
dseg:0025                 db    0
dseg:0026                 db    0
dseg:0027                 db    0
dseg:0028                 db    0
dseg:0029                 db    0
dseg:002A                 db    0
dseg:002B                 db    0
dseg:002C                 db    0
dseg:002D                 db    0
dseg:002E                 db    0
dseg:002F                 db    0
dseg:002F dseg            ends

seg001段

seg001:0000 ; Segment type: Regular
seg001:0000 seg001          segment byte public 'UNK' use16
seg001:0000                 assume cs:seg001
seg001:0000                 assume es:nothing, ss:nothing, ds:dseg, fs:nothing, gs:nothing
seg001:0000                 db  91h
seg001:0001                 db  61h ; a
seg001:0002                 db    1
seg001:0003                 db 0C1h
seg001:0004                 db  41h ; A
seg001:0005                 db 0A0h
seg001:0006                 db  60h ; `
seg001:0007                 db  41h ; A
seg001:0008                 db 0D1h
seg001:0009                 db  21h ; !
seg001:000A                 db  14h
seg001:000B                 db 0C1h
seg001:000C                 db  41h ; A
seg001:000D                 db 0E2h
seg001:000E                 db  50h ; P
seg001:000F                 db 0E1h
seg001:0010                 db 0E2h
seg001:0011                 db  54h ; T
seg001:0012                 db  20h
seg001:0013                 db 0C1h
seg001:0014                 db 0E2h
seg001:0015                 db  60h ; `
seg001:0016                 db  14h
seg001:0017                 db  30h ; 0
seg001:0018                 db 0D1h
seg001:0019                 db  51h ; Q
seg001:001A                 db 0C0h
seg001:001B                 db  17h
seg001:001C                 db    0
seg001:001D                 db    0
seg001:001E                 db    0
seg001:001F                 db    0
seg001:001F seg001          ends

shift+E提取出來

0x91, 0x61, 0x01, 0xC1, 0x41, 0xA0, 0x60, 0x41, 0xD1, 0x21, 
0x14, 0xC1, 0x41, 0xE2, 0x50, 0xE1, 0xE2, 0x54, 0x20, 0xC1, 
0xE2, 0x60, 0x14, 0x30, 0xD1, 0x51, 0xC0, 0x17

疑問:0B800h為什麼是影片記憶體?

x86組合語言之視訊記憶體操控螢幕輸出

操控視訊記憶體輸出字串

前面咱們介紹過使用中斷的方式輸出字串, 今天我們學習一種不使用中斷的方式實現字串的列印

在8086的記憶體地址結構中,B8000H~BFFFFH這部分的記憶體區域為視訊記憶體區域,一旦向這個地址空間寫入資料,cpu會從0號偏移地址開始讀取資料然後顯示輸出, (每寫入一次資料就從0開始讀取一次)

程式碼嘗試:

start:
       mov ax,0B800H
       mov ds,ax
  
     
       mov dl,'a'           
       mov ds:[0],dl
end start

在這塊區域中,每個字元固定佔用兩個位元組的空間,也就是ds:[0]ds:[1]存放一個字元的資訊,前者存放字元具體的內容,後者存放字元對應的顏色

比如:

start:
       mov ax,0B800H
       mov ds,ax
  
     
       mov dl,'a'           
       mov ds:[0],dl
       
       mov dl,00000100B ;讓字元以紅色顯示          
       mov ds:[1],dl
end start

作者:亂碼三千
連結:https://juejin.cn/post/7028744851805978638
來源:稀土掘金
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
彙編都標註好了註釋,邏輯不難理解
將dseg的每個位元組左移與右移的結果相加,再進行異或操作,最後與seg001比較

EXP

 1 flag = ''
 2 
 3 seg001 = [
 4     0x91, 0x61, 0x01, 0xC1, 0x41, 0xA0, 0x60, 0x41, 0xD1, 0x21,
 5     0x14, 0xC1, 0x41, 0xE2, 0x50, 0xE1, 0xE2, 0x54, 0x20, 0xC1,
 6     0xE2, 0x60, 0x14, 0x30, 0xD1, 0x51, 0xC0, 0x17
 7 ]
 8 
 9 for i in seg001:
10     add = i ^ 23
11     temp1 = add >> 4  # 低位
12     temp2 = add << 4  # 高位
13     flag += chr((temp1 + temp2) & 0xFF)  ##第一次漏了,報錯:TypeError: ord() expected string of length 1, but int found
14 
15 print(flag)

flag

hgame{welc0me_to_4sm_w0rld}

相關文章