16位简单ASM题的记录——[HGAME 2022 week1]easyasm

asm,hgame,week1,easyasm · 浏览次数 : 0

小编点评

# 0B800H 是视频内存 作者在代码中使用了右移与异或运算来模拟字符串的打印在显存内存中。 * 代码首先将字符串的第一个字符存储在 ds[0] 中。 * 然后,它使用右移运算将字符信息右移 2311 位,形成一个新的变量 temp1。 * temp1 的低位 12 位表示字符的颜色,而高位 13 位表示字符的闪烁效果。 * 代码使用 temp1 和 temp2 运算出字符的颜色,并将其与 seg001 的 EXP 1 flag 进行异或运算。 * 如果 flag 的值为 1,则表示该字符应该闪烁;否则,则表示该字符应该是黑色。 * 最后,代码将 flag 的值打印出来。

正文

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

 

与16位简单ASM题的记录——[HGAME 2022 week1]easyasm相似的内容:

16位简单ASM题的记录——[HGAME 2022 week1]easyasm

第一次遇见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:00

[转帖]32位CPU和64位CPU 区别

操作系统只是硬件和应用软件中间的一个平台。 32位操作系统针对的32位的CPU设计。 64位操作系统针对的64位的CPU设计。 操作系统只是硬件和应用软件中间的一个平台。 我们的CPU从原来的8位,16位,到现在的32位和64位。 cpu处理计算的时候“数据”和“指令”是不同对待的。 8位的CPU,

[转帖]存储器系统

https://juejin.cn/post/6844903472341450765 基础概念 存储器容量:取决于寻址方式,16位机能产生16位地址,因此能在2^16=64K个存储器单元中寻址,同理,32位机能使用包含4G个单元的存储器。 MAR(存储器地址寄存器)和 MDR(存储器数据寄存器):通

Scala语法篇

Scala基础篇 数据类型 下表中列出的数据类型都是对象,可以直接对它们调用方法。 数据类型 描述 Byte 8位有符号补码整数。数值区间为 -128 到 127 Short 16位有符号补码整数。数值区间为 -32768 到 32767 Int 32位有符号补码整数。数值区间为 -21474836

[转帖]使用 Shell 运算进行进制转换 16进制转10进制

使用 Shell 运算进行进制转换 工作时候常常遇到一些问题,拿到的数字是16进制的,但是运算的时候是10进制的,shell可以很方便的处理这类的进制转换问题,一种情况是使用 Shell 运算把一个数字从给定的进制转换位十进制。如果数字以运算展开式的形式提供,那么假定它带有十进制符号,除非 它前面带

STM32 + RT-Thread + LVGL

一、基本信息 MCU:STM32F103ZET6 RT-Thread:5.0.2 LVGL:8.3.11 LCD:ST7735s 编译环境:RTThread studio 二、LVGL 移植要求 16、32或64位微控制器或处理器 建议速度大于16 MHz 闪存/ROM: > 64 kB(建议180

一种优秀的虚拟机内存架构 - AQ

源链接:https://www.axa6.com/zh/an-excellent-virtual-machine-memory-architecture 简介 虚拟机内存架构直接影响虚拟机的性能和占用。设计一个优秀的架构可以有效提升性能和效率。 本文将介绍AQ虚拟机使用的内存架构,以及AQ虚拟机内存

FPGA CFGBVS 管脚接法

说明 新设计了1个KU040 FPGA板子,回来之后接上JTAG FPGA不识别。做如下检查: 1、电源测试点均正常; 2、查看贴片是否有漏焊,检查无异常,设计上NC的才NC; 3、反复检查JTAG接线是否异常,贴片是否异常; 上述检查均无问题,开始查看原理图,逐个对照XILINX手册进行研究。 其

Python 生成条形码、二维码 (Code 128、EAN-13、QR code等)

条形码和二维码是现代信息交换和数据存储的重要工具,它们将信息以图形的形式编码,便于机器识别和数据处理,被广泛应用于物流、零售、医疗、教育等各领域。本文将介绍如何使用Python快速生成各种常见的条形码如Code 128、EAN-13,以及生成二维码。 Python条码库 本文需要用到 Spire.B

CaiT:Facebook提出高性能深度ViT结构 | ICCV 2021

CaiT通过LayerScale层来保证深度ViT训练的稳定性,加上将特征学习和分类信息提取隔离的class-attention层达到了很不错的性能,值得看看 来源:晓飞的算法工程笔记 公众号 论文: Going deeper with Image Transformers 论文地址:https:/