-
-
[旧帖] [原创]一个8086汇编程序的反汇编 0.00雪花
-
2011-3-8 11:07 2824
-
【文章标题】: 一个8086汇编程序的反汇编
【文章作者】: nanlingcg
【作者邮箱】: 1097519717@qq.com
【作者QQ号】: 1097519717
【软件名称】: 8086变化七彩HELLO WORLD!
【软件大小】: 724字节
【下载地址】: 无
【加壳方式】: 无
【保护方式】: 无
【编写语言】: 8086汇编
【使用工具】: 8086编译器
【操作平台】: DOS
【软件介绍】: 可单变和连续变色
【作者声明】: 初学汇编,希望能获得个邀请码.^-^
--------------------------------------------------------------------------------
【详细过程】
这个8086汇编小程序很好玩,运行后,输出经典的HELLO WORLD!按T可以单色变,按P可以连续变色,按Q就退出了.
小程序附后,先来反汇编.
IDA反汇编如下:
dseg:0000 ;
dseg:0000 ; +-------------------------------------------------------------------------+
dseg:0000 ; | This file is generated by The Interactive Disassembler (IDA) |
dseg:0000 ; | Copyright (c) 2007 by DataRescue sa/nv, |
dseg:0000 ; | Licensed to: Mach EDV Dienstleistungen, Jan Mach, 1 user, adv, 11/2007 |
dseg:0000 ; +-------------------------------------------------------------------------+
dseg:0000 ;
dseg:0000 ; Input MD5 : DAE8B672F3ED9BAEAE2398C07F4F160F
dseg:0000
dseg:0000 ; File Name : C:\Documents and Settings\Administrator\桌面\变幻七.exe
dseg:0000 ; Format : MS-DOS executable (EXE)
dseg:0000 ; Base Address: 0h Range: 0h-D4h Loaded length: D4h
dseg:0000 ; Entry Point : 3:0
dseg:0000
dseg:0000 .386
dseg:0000 .model large
dseg:0000
dseg:0000 ; ===========================================================================
dseg:0000
dseg:0000 ; Segment type: Pure data
dseg:0000 dseg segment para stack 'DATA' use16
dseg:0000 assume cs:dseg
dseg:0000 db 48h ; H
dseg:0001 db 45h ; E
dseg:0002 db 4Ch ; L
dseg:0003 db 4Ch ; L
dseg:0004 db 4Fh ; O
dseg:0005 db 20h
dseg:0006 db 57h ; W
dseg:0007 db 4Fh ; O
dseg:0008 db 52h ; R
dseg:0009 db 4Ch ; L
dseg:000A db 44h ; D
dseg:000B db 21h ; !
dseg:000C word_C dw 0 ; DATA XREF: start+Fw
dseg:000C ; start+8Dr
dseg:000E word_E dw 0 ; DATA XREF: start+18w
dseg:000E ; start+96r
dseg:0010 unk_10 db 1Eh ; DATA XREF: start+1Do
dseg:0011 dd 3B850h
dseg:0015 aOFV db '庁鋊',0
dseg:001C db 9Ch ; ?
dseg:001D db 2Eh ; .
dseg:001E db 0FFh
dseg:001F db 1Eh
dseg:0020 db 0Ch
dseg:0021 db 0
dseg:0022 db 58h ; X
dseg:0023 db 1Fh
dseg:0024 word_24 dw 0CFh ; DATA XREF: start+Ar
dseg:0024 ; start+1Dw ...
dseg:0026 word_26 dw 0 ; DATA XREF: start+13r
dseg:0026 ; start+24w ...
dseg:0028 align 10h
dseg:0028 dseg ends
dseg:0028
seg001:0000 ; ===========================================================================
seg001:0000
seg001:0000 ; Segment type: Pure code
seg001:0000 seg001 segment byte public 'CODE' use16
seg001:0000 assume cs:seg001
seg001:0000 assume es:nothing, ss:dseg, ds:nothing, fs:nothing, gs:nothing
seg001:0000
seg001:0000 ; =============== S U B R O U T I N E =======================================
seg001:0000
seg001:0000 ; Attributes: noreturn
seg001:0000
seg001:0000 public start
seg001:0000 start proc near
seg001:0000 mov ax, seg dseg
seg001:0003 mov ds, ax
seg001:0005 assume ds:dseg
seg001:0005 mov ax, 0
seg001:0008 mov es, ax
seg001:000A assume es:dseg
seg001:000A push es:word_24
seg001:000F pop word_C
seg001:0013 push es:word_26
seg001:0018 pop word_E
seg001:001C cli
seg001:001D mov es:word_24, offset unk_10
seg001:0024 mov es:word_26, ds
seg001:0029 sti
seg001:002A
seg001:002A loc_5A: ; CODE XREF: start+66j
seg001:002A ; start+7Cj
seg001:002A mov ax, 0B800h
seg001:002D mov es, ax
seg001:002F assume es:nothing
seg001:002F mov di, 7C4h
seg001:0032 mov si, 0
seg001:0035 mov ah, cs:byte_98
seg001:003A mov cx, 0Ch
seg001:003D
seg001:003D loc_6D: ; CODE XREF: start+46j
seg001:003D mov al, [si]
seg001:003F mov es:[di], ax
seg001:0042 inc si
seg001:0043 add di, 2
seg001:0046 loop loc_6D
seg001:0048 mov cx, 0
seg001:004B
seg001:004B loc_7B: ; CODE XREF: start:loc_7Bj
seg001:004B loop loc_7B
seg001:004D
seg001:004D loc_7D: ; CODE XREF: start+85j
seg001:004D cmp cs:byte_AE, 94h ; '?
seg001:0053 jnz short loc_99
seg001:0055 inc cs:byte_98
seg001:005A and cs:byte_98, 0Fh
seg001:0060 mov cs:byte_AE, 0
seg001:0066 jmp short loc_5A
seg001:0066 ; ---------------------------------------------------------------------------
seg001:0068 byte_98 db 0Fh ; DATA XREF: start+35r
seg001:0068 ; start+55w ...
seg001:0069 ; ---------------------------------------------------------------------------
seg001:0069
seg001:0069 loc_99: ; CODE XREF: start+53j
seg001:0069 cmp cs:byte_AE, 99h ; '?
seg001:006F jnz short loc_AF
seg001:0071 inc cs:byte_98
seg001:0076 and cs:byte_98, 0Fh
seg001:007C jmp short loc_5A
seg001:007C ; ---------------------------------------------------------------------------
seg001:007E byte_AE db 0 ; DATA XREF: start:loc_7Dr
seg001:007E ; start+60w ...
seg001:007F ; ---------------------------------------------------------------------------
seg001:007F
seg001:007F loc_AF: ; CODE XREF: start+6Fj
seg001:007F cmp cs:byte_AE, 90h ; '?
seg001:0085 jnz short loc_7D
seg001:0087 mov ax, 0
seg001:008A mov es, ax
seg001:008C assume es:dseg
seg001:008C cli
seg001:008D push word_C
seg001:0091 pop es:word_24
seg001:0096 push word_E
seg001:009A pop es:word_26
seg001:009F sti
seg001:00A0 mov ah, 4Ch
seg001:00A2 int 21h ; DOS - 2+ - QUIT WITH EXIT CODE (EXIT)
seg001:00A2 start endp ; AL = exit code
seg001:00A2
seg001:00A2 seg001 ends
seg001:00A2
seg001:00A2
seg001:00A2 end start
通过IDA的反汇编,手工分析在前一段很不得要领.好在是8086程序,就用DEBUG再反汇编一次.
如下:
C:\DOCUME~1\ADMINI~1>debug e:\abc\abc1\7c.exe
-u
0D13:0000 B8100D MOV AX,0D10
0D13:0003 8ED8 MOV DS,AX
0D13:0005 B80000 MOV AX,0000
0D13:0008 8EC0 MOV ES,AX
0D13:000A 26 ES:
0D13:000B FF362400 PUSH [0024]
0D13:000F 8F060C00 POP [000C]
0D13:0013 26 ES:
0D13:0014 FF362600 PUSH [0026]
0D13:0018 8F060E00 POP [000E]
0D13:001C FA CLI
0D13:001D 26 ES:
0D13:001E C70624001000 MOV WORD PTR [0024],0010
0D13:0024 26 ES:
0D13:0025 8C1E2600 MOV [0026],DS
0D13:0029 FB STI
0D13:002A B800B8 MOV AX,B800
0D13:002D 8EC0 MOV ES,AX
0D13:002F BFC407 MOV DI,07C4
0D13:0032 BE0000 MOV SI,0000
0D13:0035 2E CS:
0D13:0036 8A266800 MOV AH,[0068]
0D13:003A B90C00 MOV CX,000C
0D13:003D 8A04 MOV AL,[SI]
0D13:003F 26 ES:
0D13:0040 8905 MOV [DI],AX
0D13:0042 46 INC SI
0D13:0043 83C702 ADD DI,+02
0D13:0046 E2F5 LOOP 003D
0D13:0048 B90000 MOV CX,0000
0D13:004B E2FE LOOP 004B
0D13:004D 2E CS:
0D13:004E 803E7E0094 CMP BYTE PTR [007E],94
0D13:0053 7514 JNZ 0069
0D13:0055 2E CS:
0D13:0056 FE066800 INC BYTE PTR [0068]
0D13:005A 2E CS:
0D13:005B 802668000F AND BYTE PTR [0068],0F
0D13:0060 2E CS:
0D13:0061 C6067E0000 MOV BYTE PTR [007E],00
0D13:0066 EBC2 JMP 002A
0D13:0068 0F DB 0F
0D13:0069 2E CS:
0D13:006A 803E7E0099 CMP BYTE PTR [007E],99
0D13:006F 750E JNZ 007F
0D13:0071 2E CS:
0D13:0072 FE066800 INC BYTE PTR [0068]
0D13:0076 2E CS:
0D13:0077 802668000F AND BYTE PTR [0068],0F
0D13:007C EBAC JMP 002A
0D13:007E 002E803E ADD [3E80],CH
0D13:0082 7E00 JLE 0084
0D13:0084 90 NOP
0D13:0085 75C6 JNZ 004D
0D13:0087 B80000 MOV AX,0000
0D13:008A 8EC0 MOV ES,AX
0D13:008C FA CLI
0D13:008D FF360C00 PUSH [000C]
0D13:0091 26 ES:
0D13:0092 8F062400 POP [0024]
0D13:0096 FF360E00 PUSH [000E]
0D13:009A 26 ES:
0D13:009B 8F062600 POP [0026]
0D13:009F FB STI
0D13:00A0 B44C MOV AH,4C
0D13:00A2 CD21 INT 21
到这里看到INT 21H(4CH)了.该结束了.(IDA也就解析到这).
两相比照,在代码段2A到7C段基本一致,所不同的是2A以前和7C以后,互相比对:首先看2A以前,DEBUG更合理,
0D13:0000 B8100D MOV AX,0D10
0D13:0003 8ED8 MOV DS,AX
0D13:0005 B80000 MOV AX,0000
0D13:0008 8EC0 MOV ES,AX <--确定DS和ES
0D13:000A 26 ES:
0D13:000B FF362400 PUSH [0024]
0D13:000F 8F060C00 POP [000C]
0D13:0013 26 ES:
0D13:0014 FF362600 PUSH [0026]
0D13:0018 8F060E00 POP [000E]
0D13:001C FA CLI <--保存0:24和0:26进DS:0C和DS:0E
0D13:001D 26 ES:
0D13:001E C70624001000 MOV WORD PTR [0024],0010
0D13:0024 26 ES:
0D13:0025 8C1E2600 MOV [0026],DS <--10和DS进0:24和0:26
0D13:0029 FB STI
很显然,这是在修改INT 9.
再看2A-7C一节:
0D13:0029 FB STI
0D13:002A B800B8 MOV AX,B800 <--修改ES指向文本模式显存映射.
0D13:002D 8EC0 MOV ES,AX
0D13:002F BFC407 MOV DI,07C4
0D13:0032 BE0000 MOV SI,0000
0D13:0035 2E CS:
0D13:0036 8A266800 MOV AH,[0068] <--等下说
0D13:003A B90C00 MOV CX,000C
0D13:003D 8A04 MOV AL,[SI] <--DS:[SI]=DS:[0]进AL,等下反汇编DS段,或者参看IDA的反汇编,其实指向存在DS段的"HELLO WORLD!"ASCII
0D13:003F 26 ES:
0D13:0040 8905 MOV [DI],AX
0D13:0042 46 INC SI <--SI自加1,
0D13:0043 83C702 ADD DI,+02 <--DI自加2,指向显存映射的.
0D13:0046 E2F5 LOOP 003D <--循环执行3D到这共CX(0C)次,其实就是单字符向屏幕输出12个字符.正是HELLO WORLD!,抓了图的,就略了.
0D13:0048 B90000 MOV CX,0000
0D13:004B E2FE LOOP 004B <--延时一下
0D13:004D 2E CS:
0D13:004E 803E7E0094 CMP BYTE PTR [007E],94
0D13:0053 7514 JNZ 0069
0D13:0055 2E CS:
0D13:0056 FE066800 INC BYTE PTR [0068]
0D13:005A 2E CS:
0D13:005B 802668000F AND BYTE PTR [0068],0F
0D13:0060 2E CS:
0D13:0061 C6067E0000 MOV BYTE PTR [007E],00
0D13:0066 EBC2 JMP 002A
0D13:0068 0F DB 0F
0D13:0069 2E CS:
0D13:006A 803E7E0099 CMP BYTE PTR [007E],99
0D13:006F 750E JNZ 007F
0D13:0071 2E CS:
0D13:0072 FE066800 INC BYTE PTR [0068]
0D13:0076 2E CS:
0D13:0077 802668000F AND BYTE PTR [0068],0F
0D13:007C EBAC JMP 002A <--这段是一个多分支检测,用BYTE PTR CS:[007E]来分别和某个数比较以修改CS:[68],并确定程序走向.(从简).
再看下面从7E开始,IDA和DEBUG解析出了不同结果.经比较分析,IDA的解析更可靠,IDA把7E解析为一个字节的数据而不是代码,参考IDA用DEBUG反汇编7F以后一段.(7E为一个数据了).
-u 7F
0D13:007F 2E CS:
0D13:0080 803E7E0090 CMP BYTE PTR [007E],90 <--依然是分支比较.
0D13:0085 75C6 JNZ 004D
0D13:0087 B80000 MOV AX,0000 <--下面修改ES及和代码段开头相对应的用DS:0C和DS:0E修改0:24和0:26
0D13:008A 8EC0 MOV ES,AX
0D13:008C FA CLI
0D13:008D FF360C00 PUSH [000C]
0D13:0091 26 ES:
0D13:0092 8F062400 POP [0024]
0D13:0096 FF360E00 PUSH [000E]
0D13:009A 26 ES:
0D13:009B 8F062600 POP [0026]
0D13:009F FB STI <--修改是回复INT 9
0D13:00A0 B44C MOV AH,
0D13:00A2 CD21 INT 21 <--程序退出,返回到系统.
到这里是不是该借书了呢?不?还有疑问,CS[68]和CS:[7E]到底是什么?INT 9是修改成什么了?
0D13:001E C70624001000 MOV WORD PTR [0024],0010
0D13:0024 26 ES:
0D13:0025 8C1E2600 MOV [0026],DS
0D13:0029 FB STI
这节已告诉我们INT 9的向量被修改为DS:0010了.那么我门再反汇编DS:0010一段.
-u ds:0010
0D10:0010 1E PUSH DS
0D10:0011 50 PUSH AX
0D10:0012 B8130D MOV AX,0D13
0D10:0015 8ED8 MOV DS,AX
0D10:0017 E460 IN AL,60
0D10:0019 A27E00 MOV [007E],AL <--这,开始修改7E处了.
0D10:001C 9C PUSHF
0D10:001D 2E CS:
0D10:001E FF1E0C00 CALL FAR [000C]
0D10:0022 58 POP AX
0D10:0023 1F POP DS
0D10:0024 CF IRET <--到这中断程序返回了,后面的是没用的.
0D10:0025 0000 ADD [BX+SI],AL
0D10:0027 0000 ADD [BX+SI],AL
0D10:0029 0000 ADD [BX+SI],AL
0D10:002B 0000 ADD [BX+SI],AL
0D10:002D 0000 ADD [BX+SI],AL
其实这个新INT 9只有这是有意义的
0D10:0017 E460 IN AL,60
0D10:0019 A27E00 MOV [007E],AL <--这,开始修改7E处了.
读60端口,取按键扫描码进CS:[7E].
CS:[7E]的用处终于知道了,是用来存键盘扫描码的.那么毫无疑问上面把7E当数据处理是正确的.CS:68被处理成数据经分析也无不妥.
那么.我们就大概复原下这个程序的大概面貌.
DS:
0D10:0000 DB "HELLO WORLD!" <--用来向屏幕输出的.
0D10:0000 DB 00,00,00,00 <--用来保存0;24和0:26(即INT 9向量)的.
0D10:0010 1E PUSH DS <--用来修改为INT 9的中断程序代码
0D10:0011 50 PUSH AX
0D10:0012 B8130D MOV AX,0D13
0D10:0015 8ED8 MOV DS,AX
0D10:0017 E460 IN AL,60
0D10:0019 A27E00 MOV [007E],AL
0D10:001C 9C PUSHF
0D10:001D 2E CS:
0D10:001E FF1E0C00 CALL FAR [000C]
0D10:0022 58 POP AX
0D10:0023 1F POP DS
0D10:0024 CF IRET
CS:
0D13:0000 B8100D MOV AX,0D10
0D13:0003 8ED8 MOV DS,AX <--确定DS
0D13:0005 B80000 MOV AX,0000
0D13:0008 8EC0 MOV ES,AX <--保存和修改INT 9向量
0D13:000A 26 ES:
0D13:000B FF362400 PUSH [0024]
0D13:000F 8F060C00 POP [000C]
0D13:0013 26 ES:
0D13:0014 FF362600 PUSH [0026]
0D13:0018 8F060E00 POP [000E]
0D13:001C FA CLI
0D13:001D 26 ES:
0D13:001E C70624001000 MOV WORD PTR [0024],0010
0D13:0024 26 ES:
0D13:0025 8C1E2600 MOV [0026],DS
0D13:0029 FB STI
0D13:002A B800B8 MOV AX,B800 <--ES和DI指向屏幕显存地址
0D13:002D 8EC0 MOV ES,AX
0D13:002F BFC407 MOV DI,07C4
0D13:0032 BE0000 MOV SI,0000
0D13:0035 2E CS:
0D13:0036 8A266800 MOV AH,[0068] <--6E为颜色码
0D13:003A B90C00 MOV CX,000C
0D13:003D 8A04 MOV AL,[SI]
0D13:003F 26 ES:
0D13:0040 8905 MOV [DI],AX
0D13:0042 46 INC SI
0D13:0043 83C702 ADD DI,+02
0D13:0046 E2F5 LOOP 003D
0D13:0048 B90000 MOV CX,0000
0D13:004B E2FE LOOP 004B <循环12次一字节输出HELLO WORLD!
0D13:004D 2E CS:
0D13:004E 803E7E0094 CMP BYTE PTR [007E],94 <--键盘扫描码比较,以确定是否修改6E(颜色码)或跳走.
0D13:0053 7514 JNZ 0069
0D13:0055 2E CS:
0D13:0056 FE066800 INC BYTE PTR [0068]
0D13:005A 2E CS:
0D13:005B 802668000F AND BYTE PTR [0068],0F
0D13:0060 2E CS:
0D13:0061 C6067E0000 MOV BYTE PTR [007E],00
0D13:0066 EBC2 JMP 002A <--键盘扫描码为94,修改6E后跳到2A处执行(改变颜色,再向屏幕输出HELLO WORLD!)
0D13:0068 0F DB 0F
0D13:0069 2E CS:
0D13:006A 803E7E0099 CMP BYTE PTR [007E],99 <--键盘扫描码比较,以确定是否修改6E(颜色码)或跳走.
0D13:006F 750E JNZ 007F
0D13:0071 2E CS:
0D13:0072 FE066800 INC BYTE PTR [0068]
0D13:0076 2E CS:
0D13:0077 802668000F AND BYTE PTR [0068],0F
0D13:007C EBAC JMP 002A <--键盘扫描码为99,修改6E后跳到2A处执行(改变颜色,再向屏幕输出HELLO WORLD!)
0D13:007E 00 DB 00
0D13:007F 2E CS:
0D13:0080 803E7E0090 CMP BYTE PTR [007E],90 <--键盘扫描码比较,不是就继续跳到此为止D处继续比较键盘扫描码,是则就执行后面的恢复INT 9和退出整个程序
0D13:0085 75C6 JNZ 004D
0D13:0087 B80000 MOV AX,0000 <--恢复INT 9
0D13:008A 8EC0 MOV ES,AX
0D13:008C FA CLI
0D13:008D FF360C00 PUSH [000C]
0D13:0091 26 ES:
0D13:0092 8F062400 POP [0024]
0D13:0096 FF360E00 PUSH [000E]
0D13:009A 26 ES:
0D13:009B 8F062600 POP [0026]
0D13:009F FB STI
0D13:00A0 B44C MOV AH, ,--退出整个程序,返回系统.
0D13:00A2 CD21 INT 21
--------------------------------------------------------------------------------
【经验总结】
整个程序总体来看很简单,但,在程序中于代码段中加入了数据,数据段中加入了代码,使反汇编难度加大.单凭IDA或DEBUG完
全反汇编有一定难度.
鉴于初学汇编,谨以此文贴出,借以希望获得"看雪"邀请码一个,以便更好学习.
--------------------------------------------------------------------------------
2011年03月08日 CG 11:02:32
【文章作者】: nanlingcg
【作者邮箱】: 1097519717@qq.com
【作者QQ号】: 1097519717
【软件名称】: 8086变化七彩HELLO WORLD!
【软件大小】: 724字节
【下载地址】: 无
【加壳方式】: 无
【保护方式】: 无
【编写语言】: 8086汇编
【使用工具】: 8086编译器
【操作平台】: DOS
【软件介绍】: 可单变和连续变色
【作者声明】: 初学汇编,希望能获得个邀请码.^-^
--------------------------------------------------------------------------------
【详细过程】
这个8086汇编小程序很好玩,运行后,输出经典的HELLO WORLD!按T可以单色变,按P可以连续变色,按Q就退出了.
小程序附后,先来反汇编.
IDA反汇编如下:
dseg:0000 ;
dseg:0000 ; +-------------------------------------------------------------------------+
dseg:0000 ; | This file is generated by The Interactive Disassembler (IDA) |
dseg:0000 ; | Copyright (c) 2007 by DataRescue sa/nv, |
dseg:0000 ; | Licensed to: Mach EDV Dienstleistungen, Jan Mach, 1 user, adv, 11/2007 |
dseg:0000 ; +-------------------------------------------------------------------------+
dseg:0000 ;
dseg:0000 ; Input MD5 : DAE8B672F3ED9BAEAE2398C07F4F160F
dseg:0000
dseg:0000 ; File Name : C:\Documents and Settings\Administrator\桌面\变幻七.exe
dseg:0000 ; Format : MS-DOS executable (EXE)
dseg:0000 ; Base Address: 0h Range: 0h-D4h Loaded length: D4h
dseg:0000 ; Entry Point : 3:0
dseg:0000
dseg:0000 .386
dseg:0000 .model large
dseg:0000
dseg:0000 ; ===========================================================================
dseg:0000
dseg:0000 ; Segment type: Pure data
dseg:0000 dseg segment para stack 'DATA' use16
dseg:0000 assume cs:dseg
dseg:0000 db 48h ; H
dseg:0001 db 45h ; E
dseg:0002 db 4Ch ; L
dseg:0003 db 4Ch ; L
dseg:0004 db 4Fh ; O
dseg:0005 db 20h
dseg:0006 db 57h ; W
dseg:0007 db 4Fh ; O
dseg:0008 db 52h ; R
dseg:0009 db 4Ch ; L
dseg:000A db 44h ; D
dseg:000B db 21h ; !
dseg:000C word_C dw 0 ; DATA XREF: start+Fw
dseg:000C ; start+8Dr
dseg:000E word_E dw 0 ; DATA XREF: start+18w
dseg:000E ; start+96r
dseg:0010 unk_10 db 1Eh ; DATA XREF: start+1Do
dseg:0011 dd 3B850h
dseg:0015 aOFV db '庁鋊',0
dseg:001C db 9Ch ; ?
dseg:001D db 2Eh ; .
dseg:001E db 0FFh
dseg:001F db 1Eh
dseg:0020 db 0Ch
dseg:0021 db 0
dseg:0022 db 58h ; X
dseg:0023 db 1Fh
dseg:0024 word_24 dw 0CFh ; DATA XREF: start+Ar
dseg:0024 ; start+1Dw ...
dseg:0026 word_26 dw 0 ; DATA XREF: start+13r
dseg:0026 ; start+24w ...
dseg:0028 align 10h
dseg:0028 dseg ends
dseg:0028
seg001:0000 ; ===========================================================================
seg001:0000
seg001:0000 ; Segment type: Pure code
seg001:0000 seg001 segment byte public 'CODE' use16
seg001:0000 assume cs:seg001
seg001:0000 assume es:nothing, ss:dseg, ds:nothing, fs:nothing, gs:nothing
seg001:0000
seg001:0000 ; =============== S U B R O U T I N E =======================================
seg001:0000
seg001:0000 ; Attributes: noreturn
seg001:0000
seg001:0000 public start
seg001:0000 start proc near
seg001:0000 mov ax, seg dseg
seg001:0003 mov ds, ax
seg001:0005 assume ds:dseg
seg001:0005 mov ax, 0
seg001:0008 mov es, ax
seg001:000A assume es:dseg
seg001:000A push es:word_24
seg001:000F pop word_C
seg001:0013 push es:word_26
seg001:0018 pop word_E
seg001:001C cli
seg001:001D mov es:word_24, offset unk_10
seg001:0024 mov es:word_26, ds
seg001:0029 sti
seg001:002A
seg001:002A loc_5A: ; CODE XREF: start+66j
seg001:002A ; start+7Cj
seg001:002A mov ax, 0B800h
seg001:002D mov es, ax
seg001:002F assume es:nothing
seg001:002F mov di, 7C4h
seg001:0032 mov si, 0
seg001:0035 mov ah, cs:byte_98
seg001:003A mov cx, 0Ch
seg001:003D
seg001:003D loc_6D: ; CODE XREF: start+46j
seg001:003D mov al, [si]
seg001:003F mov es:[di], ax
seg001:0042 inc si
seg001:0043 add di, 2
seg001:0046 loop loc_6D
seg001:0048 mov cx, 0
seg001:004B
seg001:004B loc_7B: ; CODE XREF: start:loc_7Bj
seg001:004B loop loc_7B
seg001:004D
seg001:004D loc_7D: ; CODE XREF: start+85j
seg001:004D cmp cs:byte_AE, 94h ; '?
seg001:0053 jnz short loc_99
seg001:0055 inc cs:byte_98
seg001:005A and cs:byte_98, 0Fh
seg001:0060 mov cs:byte_AE, 0
seg001:0066 jmp short loc_5A
seg001:0066 ; ---------------------------------------------------------------------------
seg001:0068 byte_98 db 0Fh ; DATA XREF: start+35r
seg001:0068 ; start+55w ...
seg001:0069 ; ---------------------------------------------------------------------------
seg001:0069
seg001:0069 loc_99: ; CODE XREF: start+53j
seg001:0069 cmp cs:byte_AE, 99h ; '?
seg001:006F jnz short loc_AF
seg001:0071 inc cs:byte_98
seg001:0076 and cs:byte_98, 0Fh
seg001:007C jmp short loc_5A
seg001:007C ; ---------------------------------------------------------------------------
seg001:007E byte_AE db 0 ; DATA XREF: start:loc_7Dr
seg001:007E ; start+60w ...
seg001:007F ; ---------------------------------------------------------------------------
seg001:007F
seg001:007F loc_AF: ; CODE XREF: start+6Fj
seg001:007F cmp cs:byte_AE, 90h ; '?
seg001:0085 jnz short loc_7D
seg001:0087 mov ax, 0
seg001:008A mov es, ax
seg001:008C assume es:dseg
seg001:008C cli
seg001:008D push word_C
seg001:0091 pop es:word_24
seg001:0096 push word_E
seg001:009A pop es:word_26
seg001:009F sti
seg001:00A0 mov ah, 4Ch
seg001:00A2 int 21h ; DOS - 2+ - QUIT WITH EXIT CODE (EXIT)
seg001:00A2 start endp ; AL = exit code
seg001:00A2
seg001:00A2 seg001 ends
seg001:00A2
seg001:00A2
seg001:00A2 end start
通过IDA的反汇编,手工分析在前一段很不得要领.好在是8086程序,就用DEBUG再反汇编一次.
如下:
C:\DOCUME~1\ADMINI~1>debug e:\abc\abc1\7c.exe
-u
0D13:0000 B8100D MOV AX,0D10
0D13:0003 8ED8 MOV DS,AX
0D13:0005 B80000 MOV AX,0000
0D13:0008 8EC0 MOV ES,AX
0D13:000A 26 ES:
0D13:000B FF362400 PUSH [0024]
0D13:000F 8F060C00 POP [000C]
0D13:0013 26 ES:
0D13:0014 FF362600 PUSH [0026]
0D13:0018 8F060E00 POP [000E]
0D13:001C FA CLI
0D13:001D 26 ES:
0D13:001E C70624001000 MOV WORD PTR [0024],0010
0D13:0024 26 ES:
0D13:0025 8C1E2600 MOV [0026],DS
0D13:0029 FB STI
0D13:002A B800B8 MOV AX,B800
0D13:002D 8EC0 MOV ES,AX
0D13:002F BFC407 MOV DI,07C4
0D13:0032 BE0000 MOV SI,0000
0D13:0035 2E CS:
0D13:0036 8A266800 MOV AH,[0068]
0D13:003A B90C00 MOV CX,000C
0D13:003D 8A04 MOV AL,[SI]
0D13:003F 26 ES:
0D13:0040 8905 MOV [DI],AX
0D13:0042 46 INC SI
0D13:0043 83C702 ADD DI,+02
0D13:0046 E2F5 LOOP 003D
0D13:0048 B90000 MOV CX,0000
0D13:004B E2FE LOOP 004B
0D13:004D 2E CS:
0D13:004E 803E7E0094 CMP BYTE PTR [007E],94
0D13:0053 7514 JNZ 0069
0D13:0055 2E CS:
0D13:0056 FE066800 INC BYTE PTR [0068]
0D13:005A 2E CS:
0D13:005B 802668000F AND BYTE PTR [0068],0F
0D13:0060 2E CS:
0D13:0061 C6067E0000 MOV BYTE PTR [007E],00
0D13:0066 EBC2 JMP 002A
0D13:0068 0F DB 0F
0D13:0069 2E CS:
0D13:006A 803E7E0099 CMP BYTE PTR [007E],99
0D13:006F 750E JNZ 007F
0D13:0071 2E CS:
0D13:0072 FE066800 INC BYTE PTR [0068]
0D13:0076 2E CS:
0D13:0077 802668000F AND BYTE PTR [0068],0F
0D13:007C EBAC JMP 002A
0D13:007E 002E803E ADD [3E80],CH
0D13:0082 7E00 JLE 0084
0D13:0084 90 NOP
0D13:0085 75C6 JNZ 004D
0D13:0087 B80000 MOV AX,0000
0D13:008A 8EC0 MOV ES,AX
0D13:008C FA CLI
0D13:008D FF360C00 PUSH [000C]
0D13:0091 26 ES:
0D13:0092 8F062400 POP [0024]
0D13:0096 FF360E00 PUSH [000E]
0D13:009A 26 ES:
0D13:009B 8F062600 POP [0026]
0D13:009F FB STI
0D13:00A0 B44C MOV AH,4C
0D13:00A2 CD21 INT 21
到这里看到INT 21H(4CH)了.该结束了.(IDA也就解析到这).
两相比照,在代码段2A到7C段基本一致,所不同的是2A以前和7C以后,互相比对:首先看2A以前,DEBUG更合理,
0D13:0000 B8100D MOV AX,0D10
0D13:0003 8ED8 MOV DS,AX
0D13:0005 B80000 MOV AX,0000
0D13:0008 8EC0 MOV ES,AX <--确定DS和ES
0D13:000A 26 ES:
0D13:000B FF362400 PUSH [0024]
0D13:000F 8F060C00 POP [000C]
0D13:0013 26 ES:
0D13:0014 FF362600 PUSH [0026]
0D13:0018 8F060E00 POP [000E]
0D13:001C FA CLI <--保存0:24和0:26进DS:0C和DS:0E
0D13:001D 26 ES:
0D13:001E C70624001000 MOV WORD PTR [0024],0010
0D13:0024 26 ES:
0D13:0025 8C1E2600 MOV [0026],DS <--10和DS进0:24和0:26
0D13:0029 FB STI
很显然,这是在修改INT 9.
再看2A-7C一节:
0D13:0029 FB STI
0D13:002A B800B8 MOV AX,B800 <--修改ES指向文本模式显存映射.
0D13:002D 8EC0 MOV ES,AX
0D13:002F BFC407 MOV DI,07C4
0D13:0032 BE0000 MOV SI,0000
0D13:0035 2E CS:
0D13:0036 8A266800 MOV AH,[0068] <--等下说
0D13:003A B90C00 MOV CX,000C
0D13:003D 8A04 MOV AL,[SI] <--DS:[SI]=DS:[0]进AL,等下反汇编DS段,或者参看IDA的反汇编,其实指向存在DS段的"HELLO WORLD!"ASCII
0D13:003F 26 ES:
0D13:0040 8905 MOV [DI],AX
0D13:0042 46 INC SI <--SI自加1,
0D13:0043 83C702 ADD DI,+02 <--DI自加2,指向显存映射的.
0D13:0046 E2F5 LOOP 003D <--循环执行3D到这共CX(0C)次,其实就是单字符向屏幕输出12个字符.正是HELLO WORLD!,抓了图的,就略了.
0D13:0048 B90000 MOV CX,0000
0D13:004B E2FE LOOP 004B <--延时一下
0D13:004D 2E CS:
0D13:004E 803E7E0094 CMP BYTE PTR [007E],94
0D13:0053 7514 JNZ 0069
0D13:0055 2E CS:
0D13:0056 FE066800 INC BYTE PTR [0068]
0D13:005A 2E CS:
0D13:005B 802668000F AND BYTE PTR [0068],0F
0D13:0060 2E CS:
0D13:0061 C6067E0000 MOV BYTE PTR [007E],00
0D13:0066 EBC2 JMP 002A
0D13:0068 0F DB 0F
0D13:0069 2E CS:
0D13:006A 803E7E0099 CMP BYTE PTR [007E],99
0D13:006F 750E JNZ 007F
0D13:0071 2E CS:
0D13:0072 FE066800 INC BYTE PTR [0068]
0D13:0076 2E CS:
0D13:0077 802668000F AND BYTE PTR [0068],0F
0D13:007C EBAC JMP 002A <--这段是一个多分支检测,用BYTE PTR CS:[007E]来分别和某个数比较以修改CS:[68],并确定程序走向.(从简).
再看下面从7E开始,IDA和DEBUG解析出了不同结果.经比较分析,IDA的解析更可靠,IDA把7E解析为一个字节的数据而不是代码,参考IDA用DEBUG反汇编7F以后一段.(7E为一个数据了).
-u 7F
0D13:007F 2E CS:
0D13:0080 803E7E0090 CMP BYTE PTR [007E],90 <--依然是分支比较.
0D13:0085 75C6 JNZ 004D
0D13:0087 B80000 MOV AX,0000 <--下面修改ES及和代码段开头相对应的用DS:0C和DS:0E修改0:24和0:26
0D13:008A 8EC0 MOV ES,AX
0D13:008C FA CLI
0D13:008D FF360C00 PUSH [000C]
0D13:0091 26 ES:
0D13:0092 8F062400 POP [0024]
0D13:0096 FF360E00 PUSH [000E]
0D13:009A 26 ES:
0D13:009B 8F062600 POP [0026]
0D13:009F FB STI <--修改是回复INT 9
0D13:00A0 B44C MOV AH,
0D13:00A2 CD21 INT 21 <--程序退出,返回到系统.
到这里是不是该借书了呢?不?还有疑问,CS[68]和CS:[7E]到底是什么?INT 9是修改成什么了?
0D13:001E C70624001000 MOV WORD PTR [0024],0010
0D13:0024 26 ES:
0D13:0025 8C1E2600 MOV [0026],DS
0D13:0029 FB STI
这节已告诉我们INT 9的向量被修改为DS:0010了.那么我门再反汇编DS:0010一段.
-u ds:0010
0D10:0010 1E PUSH DS
0D10:0011 50 PUSH AX
0D10:0012 B8130D MOV AX,0D13
0D10:0015 8ED8 MOV DS,AX
0D10:0017 E460 IN AL,60
0D10:0019 A27E00 MOV [007E],AL <--这,开始修改7E处了.
0D10:001C 9C PUSHF
0D10:001D 2E CS:
0D10:001E FF1E0C00 CALL FAR [000C]
0D10:0022 58 POP AX
0D10:0023 1F POP DS
0D10:0024 CF IRET <--到这中断程序返回了,后面的是没用的.
0D10:0025 0000 ADD [BX+SI],AL
0D10:0027 0000 ADD [BX+SI],AL
0D10:0029 0000 ADD [BX+SI],AL
0D10:002B 0000 ADD [BX+SI],AL
0D10:002D 0000 ADD [BX+SI],AL
其实这个新INT 9只有这是有意义的
0D10:0017 E460 IN AL,60
0D10:0019 A27E00 MOV [007E],AL <--这,开始修改7E处了.
读60端口,取按键扫描码进CS:[7E].
CS:[7E]的用处终于知道了,是用来存键盘扫描码的.那么毫无疑问上面把7E当数据处理是正确的.CS:68被处理成数据经分析也无不妥.
那么.我们就大概复原下这个程序的大概面貌.
DS:
0D10:0000 DB "HELLO WORLD!" <--用来向屏幕输出的.
0D10:0000 DB 00,00,00,00 <--用来保存0;24和0:26(即INT 9向量)的.
0D10:0010 1E PUSH DS <--用来修改为INT 9的中断程序代码
0D10:0011 50 PUSH AX
0D10:0012 B8130D MOV AX,0D13
0D10:0015 8ED8 MOV DS,AX
0D10:0017 E460 IN AL,60
0D10:0019 A27E00 MOV [007E],AL
0D10:001C 9C PUSHF
0D10:001D 2E CS:
0D10:001E FF1E0C00 CALL FAR [000C]
0D10:0022 58 POP AX
0D10:0023 1F POP DS
0D10:0024 CF IRET
CS:
0D13:0000 B8100D MOV AX,0D10
0D13:0003 8ED8 MOV DS,AX <--确定DS
0D13:0005 B80000 MOV AX,0000
0D13:0008 8EC0 MOV ES,AX <--保存和修改INT 9向量
0D13:000A 26 ES:
0D13:000B FF362400 PUSH [0024]
0D13:000F 8F060C00 POP [000C]
0D13:0013 26 ES:
0D13:0014 FF362600 PUSH [0026]
0D13:0018 8F060E00 POP [000E]
0D13:001C FA CLI
0D13:001D 26 ES:
0D13:001E C70624001000 MOV WORD PTR [0024],0010
0D13:0024 26 ES:
0D13:0025 8C1E2600 MOV [0026],DS
0D13:0029 FB STI
0D13:002A B800B8 MOV AX,B800 <--ES和DI指向屏幕显存地址
0D13:002D 8EC0 MOV ES,AX
0D13:002F BFC407 MOV DI,07C4
0D13:0032 BE0000 MOV SI,0000
0D13:0035 2E CS:
0D13:0036 8A266800 MOV AH,[0068] <--6E为颜色码
0D13:003A B90C00 MOV CX,000C
0D13:003D 8A04 MOV AL,[SI]
0D13:003F 26 ES:
0D13:0040 8905 MOV [DI],AX
0D13:0042 46 INC SI
0D13:0043 83C702 ADD DI,+02
0D13:0046 E2F5 LOOP 003D
0D13:0048 B90000 MOV CX,0000
0D13:004B E2FE LOOP 004B <循环12次一字节输出HELLO WORLD!
0D13:004D 2E CS:
0D13:004E 803E7E0094 CMP BYTE PTR [007E],94 <--键盘扫描码比较,以确定是否修改6E(颜色码)或跳走.
0D13:0053 7514 JNZ 0069
0D13:0055 2E CS:
0D13:0056 FE066800 INC BYTE PTR [0068]
0D13:005A 2E CS:
0D13:005B 802668000F AND BYTE PTR [0068],0F
0D13:0060 2E CS:
0D13:0061 C6067E0000 MOV BYTE PTR [007E],00
0D13:0066 EBC2 JMP 002A <--键盘扫描码为94,修改6E后跳到2A处执行(改变颜色,再向屏幕输出HELLO WORLD!)
0D13:0068 0F DB 0F
0D13:0069 2E CS:
0D13:006A 803E7E0099 CMP BYTE PTR [007E],99 <--键盘扫描码比较,以确定是否修改6E(颜色码)或跳走.
0D13:006F 750E JNZ 007F
0D13:0071 2E CS:
0D13:0072 FE066800 INC BYTE PTR [0068]
0D13:0076 2E CS:
0D13:0077 802668000F AND BYTE PTR [0068],0F
0D13:007C EBAC JMP 002A <--键盘扫描码为99,修改6E后跳到2A处执行(改变颜色,再向屏幕输出HELLO WORLD!)
0D13:007E 00 DB 00
0D13:007F 2E CS:
0D13:0080 803E7E0090 CMP BYTE PTR [007E],90 <--键盘扫描码比较,不是就继续跳到此为止D处继续比较键盘扫描码,是则就执行后面的恢复INT 9和退出整个程序
0D13:0085 75C6 JNZ 004D
0D13:0087 B80000 MOV AX,0000 <--恢复INT 9
0D13:008A 8EC0 MOV ES,AX
0D13:008C FA CLI
0D13:008D FF360C00 PUSH [000C]
0D13:0091 26 ES:
0D13:0092 8F062400 POP [0024]
0D13:0096 FF360E00 PUSH [000E]
0D13:009A 26 ES:
0D13:009B 8F062600 POP [0026]
0D13:009F FB STI
0D13:00A0 B44C MOV AH, ,--退出整个程序,返回系统.
0D13:00A2 CD21 INT 21
--------------------------------------------------------------------------------
【经验总结】
整个程序总体来看很简单,但,在程序中于代码段中加入了数据,数据段中加入了代码,使反汇编难度加大.单凭IDA或DEBUG完
全反汇编有一定难度.
鉴于初学汇编,谨以此文贴出,借以希望获得"看雪"邀请码一个,以便更好学习.
--------------------------------------------------------------------------------
2011年03月08日 CG 11:02:32
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
谁下载
看原图