第一次遇见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
汇编都标注好了注释,逻辑不难理解 将dseg的每个字节左移与右移的结果相加,再进行异或操作,最后与seg001比较疑问: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
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
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}
标签:dseg,16,easyasm,HGAME,db,mov,seg003,seg001,ax From: https://www.cnblogs.com/demo41/p/18228607