您的位置:首页 > 其它

打开64K程序神话的大门

2006-12-11 21:58 267 查看
想必大家都领教过那个用64k显示3d并且还有声音的程序,紫丁香C版版主SwordLea将其反编译,得到了64K的第一层代码,下面是我在紫丁香的文章:

这两天学习了一下老lee反汇编出来的代码,大概弄懂了整个代码的执行流程,贴出来跟大
家交流一下,本人汇编也不是很熟,肯定有不对的地方,还请高人指出。

整个代码主要分三个部分,一个是标记为start的入口函数,一个是标记为sub_155的字函
数,这个函数主要进行一些解码的数据运算,还有就是最后那一大串的db数据,SwordLee
说的对,真正执行的代码其实是这些,之前的start和sub_155就是首先对这些数据解压,
然后重新跳转到解压后的代码开始执行的。

start函数:

seg000:0100 xor si, si
seg000:0102 mov di, 2000h
seg000:0105 mov ch, 10h
seg000:0107 rep movsw
作用是从0向2000h传送16个字,这里没有弄懂,不知道为什么一开始要干这个。

seg000:0109 mov ax, cs
seg000:010B add ax, 200h
seg000:010E push ax
seg000:010F push 113h
seg000:0112 retf
跳转到CS+200h:113h,好像是跳到下一句,这里没有看懂。

seg000:0113 push cs
seg000:0114 pop ds
seg000:0115 mov si, 1A1h
seg000:0118 mov di, 100h

指定源地址为cs:1a1h,即db数据序列开始处;目的地址为cs:100h,即dos的com程序指令
开始处,之后的代码就是从si取出一个字节,解压后放到di,显然就是将db数据序列处理
后放到com程序的代码区,最后跳转执行。

seg000:011B push es
seg000:011C push di
...
seg000:0154 retf
start在解压完毕后跳转到[es:di],即seg000:100h处执行(正是解压后的代码序列),才
开始执行真正的代码

seg000:011D mov ax, 111h
seg000:0120 mov bx, 1321h
seg000:0123
seg000:0123 loc_123: ;
seg000:0123 mov [bx], ax
seg000:0125 dec bx
seg000:0126 dec bx
seg000:0127 dec ax
seg000:0128 jns short loc_123

从1321h处开始放置字数据:111h,110h,...0h,这里在sub_155子过程里要用到,可能是某
个解压算法要用的什么表;

之后我们就开始解压了:

seg000:012A lodsw
seg000:012B xchg ah, al
seg000:012D mov cx, ax
seg000:012F mov bp, 0FFFFh
seg000:0132
-----si ->ax; ah al交换; cx=ax; bp = 0ffffh

seg000:0132 loc_132: ;
seg000:0132 ;
seg000:0132 call sub_155
seg000:0135 cmp ax, 100h
seg000:0138 jz short locret_154
seg000:013A jg short loc_13F

-------调用sub_155,ax为100h时跳到locret_154(start结束),ax大于100h时到loc_13F

seg000:013C stosb
seg000:013D jmp short loc_132
seg000:013F ;
-------ax -> di;然后回到上面的loc_132,进行下一个db的处理
seg000:013F
seg000:013F loc_13F: ;
seg000:013F sub ax, 0FFh
seg000:0142 push ax
seg000:0143 call sub_155
seg000:0146 pop dx
seg000:0147 neg ax
seg000:0149 mov bx, ax

-------ax -=0ffh, 然后调用sub_155, bx = ax的补
seg000:014B
seg000:014B loc_14B: ;
seg000:014B mov al, es:[bx+di]
seg000:014E stosb
seg000:014F dec dx
seg000:0150 jnz short loc_14B
seg000:0152 jmp short loc_132
seg000:0154 ;

--------es:[bx+di]->al,ax ->di,若(--dx)!=0 则重复,否则跳到loc_132

这里对每一个db字节的数据进行一次算术处理。sub_155的参数为cx。每一次都将要解
压的数据放在ax中后将高低字节交换,放到cx中,然后调用sub_155,处理完毕后放在seg000:0100h开始的一段内存内。最后,start调用retf返回到es:di,就是刚才说过的seg000:0100h,这时,这个地址开始的内存中已经是解压好的指令了。

sub_155子过程只是进行了一系列的算术运算,辅助start进行解压。

整个程序大概流程就是这样,说到底这不是真正最后我们看到的效果所执行的代码,还希
望哪位大牛能搞出被解压后的代码让我们大家长长见识
-------

p.s.我们用Ctrl-C复制到debug,程序刚开始运行后,可以输入Esc回到debug,然后我们就可以使用u指令将解压缩后的代码弄出来,比如头20B的代码如下:

MOV AX,CS

MOV DS,AX

MOV DI,4248

ADD AX,1000

STOSW

ADD AX,1000

MOV CX,0014

STOSW

INC AH

LOOP 0115

MOV DI,13AE

MOV CX,1FDE

.....

因为最后还是个COM程序,所以不会超过64K,有兴趣的话可以都弄出来 : )
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: