第一次遇見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}