在编程网站论坛上经常会见到一个所谓的世界编程大赛头名程序,使用十六进制代码编写的,赢得了不少赞叹之声。但回过头来想一想,这里所说的世界编程大赛是一个什么样的竞赛?没听说过!另外这个程序能获奖,那么它是靠什么来评奖的呢?写的程序越难懂越好么?这自然是很荒谬的,唯一的答案是,这只是一个拿来哗众取宠的骗局,稍微懂一点汇编语言和Debug操作的人都不难看出其中的奥妙。
下面我们就来看一下这个程序,我只取了其中的一段。
e100 33 f6 bf 0 20 b5 10 f3 a5 8c c8 5 0 2 50 68 13 1 cb e 1f be a1 1 bf 0 1
e11b 6 57 b8 11 1 bb 21 13 89 7 4b 4b 48 79 f9 ad 86 e0 8b c8 bd ff ff e8 20
e134 0 3d 0 1 74 1a 7f 3 aa eb f3 2d ff 0 50 e8 f 0 5a f7 d8 8b d8 26 8a 1 aa
e14f 4a 75 f9 eb de cb 57 bb 21 13 8b c1 40 f7 27 f7 f5 8b fb ba 11 1 4f 4f 4a
e168 39 5 7f f9 52 8b c5 f7 25 f7 37 2b c8 95 f7 65 2 f7 37 95 2b e8 fe e fe
e181 10 79 6 c6 6 fe 10 7 46 d0 14 d1 d1 d1 e5 79 ec 5a b8 11 1 ff 7 4b 4b 48
e19b 3b d0 75 f7 5f c3 83 f7 83 a6 5d 59 82 cd b2 8 42 46 9 57 a9 c5 ca aa 1b
· · ·
· · ·
· · ·
e10a0 ee 7f 25 4a fa 6 74 19 46 e3 e8 89 7a c6 56 54 a7 43 13 4e bf 97 a5 6f
e10b8 99 2f ac 33 4d fa 58 3a 5a a a4 1a 74 62 c8 4f 3b 78 9 d7 ee 7e ee 2d 69
e10d1 30 40 ea 47 82 3b 85 8e 3 23 8f 74 4e 8 35 ab 74 4 1 57 d5 85 b1 6b 1e
e10ea f4 7d 1e d2 1e b3 fe f3 12 10 32 39 51 48 2d 6f e5 d3 a3 8c 8 8
g
rcx
fff
n1.com
w
q
首先先说一下这个程序,这个程序确实不错,4KB的大小,运行后是一个类似于CS地图的动画(使用debug < hex.txt 命令来运行,hex.txt就是我们将上面代码保存后的文件),当然,画面有点粗糙,好像CS到了任天堂八位机上的感觉。同时还有音乐,在这么小的程序中实现这些功能,作者的功底却是很了不得,也许是另一个编程大赛的作品吧,我曾见过256字节编程大赛,里面的程序都很精彩,但都是用汇编写的,也没达到这个程序发布者说的那个用十六进制数据编程的地步。
好了,我们现在来分析这个程序,最前面的e100 ……这一行中的e是debug中的写内存命令,表示从内存中偏移地址100H处开始写数据,将程序中的每一条指令的十六进制代码写入内存。后面是他写入的数据,然后每一行的开头都指定写入的地址,直到整个程序写完。然后g命令是运行该程序的命令,完毕后,要保存文件了,r命令是用来显示或更改寄存器的值的。而在保存文件过程中BX寄存器存放文件大小的高位字节,CX寄存器存放文件大小的地位字节,后面的fff是指定的文件大小为0fffH字节,即4KB,然后w命令写盘,文件保存完毕,用Q命令退出。
整个过程就是这样,这能说明什么问题呢,就是说我们只要找到了一个已经编译好的可执行文件十六进制数据,只要这个文件不大于64K,我们就可以照葫芦画瓢来写这个程序。要想得到一个文件的十六进制数据简直太简单了,UltraEditor,WinHex等等都可以,实在不行,用Windows自己的Debug也可以,Debug 的d命令就是用来显示16进制数据的。
当然,这样显示然后再复制,粘贴也是很费劲的,一次d命令显示128字节,这个文件可是有4KB的,要是有个64KB大小的文件,我们还不累死,这里我们可以使用DOS中的输入输出重定向来完成。建立一个txt文件hex.txt,在其中输入(我将这个文件编译后保存到我的电脑上的文件名是:hex.txt。)
n d:/work/masm/hex.com
l
d 100 1100
q
保存后运行debug < hex.txt >hex1.txt
就可以将其16进制数据导出到hex1.txt中。面貌如下:
13C0:02C0 69 73 75 61 6C 20 53 74-75 64 69 6F 5C 56 43 39 isual Studio/VC9
13C0:02D0 38 5C 69 6E 63 6C 75 64-65 00 4C 49 42 3D 43 3A 8/include.LIB=C:
13C0:02E0 5C 50 72 6F 67 72 61 6D-20 46 69 6C 65 73 5C 4D /Program Files/M
13C0:02F0 69 63 72 6F 73 6F 66 74-20 56 69 73 75 61 6C 20 icrosoft Visual
13C0:0300 53 74 75 64 69 6F 5C 56-43 39 38 5C 6D 66 63 5C Studio/VC98/mfc/
13C0:0310 6C 69 62 3B 43 3A 5C 50-72 6F 67 72 61 6D 20 46 lib;C:/Program F
13C0:0320 69 6C 65 73 5C 4D 69 63-72 6F 73 6F 66 74 20 56 iles/Microsoft V
13C0:0330 69 73 75 61 6C 20 53 74-75 64 69 6F 5C 56 43 39 isual Studio/VC9
13C0:0340 38 5C 6C 69 62 00 4C 4F-47 4F 4E 53 45 52 56 45 8/lib.LOGONSERVE
13C0:0350 52 3D 5C 5C 4D 53 2D 37-43 39 41 38 30 44 45 42 R=//MS-7C9A80DEB
将冒号前面的数字连同冒号一同删去,替换成e,然后将中间的“-”替换成空格和后面的字符串删除。
然后,在文件末尾加入
g
rcx
fff 注:这里的fff是文件的大小,要换成你所转换的文件的大小的十六进制数据。
n1.com 注:这里的文件名其实是1.com,在debug中由于命令是单字母的,因此命令与参数之间不需要空格
w
q
就可以拿这个文件忽悠人去了,当然,任何文件,比如图片,或者用VB写的编译好的程序,只要大小不超过64K(确切说应该是65280字节,因为程序段前缀要占用256字节,所以,所有教科书上说的命令文件,也就是扩展名为com的文件不能超过64K是错误的,界限应该是65280字节而不是65536字节)都可以这么做。
上面我们说了这个程序其实是个很精彩的程序,那么我们想不想一睹她的风采呢?那好吧,我们就把他反汇编一下吧,新建一个txt文件,在其中输入:
n d:/work/masm/hex.com
l
u 100 1100
q
然后运行命令:debug<hex.txt >hex2.txt
hex2.txt中就有这个程序的汇编代码了,只是有个问题,程序是由代码和数据组成的,这个文件中,代码和数据在同一个段中,反汇编时,debug不能够区分数据和代码,将数据也当代码来反汇编了。因此我们要找出哪些是代码哪些是数据。
由于汇编的指令没有用完所有的256个数据,所以在将数据反汇编时,必然会遇到无法识别的指令,就会用???来表示,而程序和子程序都必须用ret来返回。那么我们就用这两个特征来区分它们。
在反汇编的代码中查找???,找到后将查找方向改为向前,查找ret,这个ret后面的全部是数据,前面不一定全是代码,要再进行一些指令上的判断。或许会是再往前面的那个ret前面的是代码。直到最后将代码完全分析完成。在代码分析中可以使用查找“[”或“]”的方法来查找变量,原理么,应该很容易理解的!!
不过这样分析不是百分之百能成功地,因为有时会碰到代码和数据混合存放的情况(很遗憾,这个里面我发现就有这个迹象,因此到现在还没有分析完全),不过这样会使程序编写的难度增加很多。不过如果有能力的话,自己编写个专用的反汇编程序也可以,采用跟踪反汇编的方式,在碰到一个操作时,如果引用了一个地址,就将该地址标记为“数据”,以后反汇编是将忽略掉这个数据,这样也许会得到更加准确反汇编代码。
写在后面:
在网上还有另一种所谓的世界编程大赛头名程序,一堆乱码似的东西,如下所示:
这个忽悠劲更大,这并不是网上贴的原来的程序,因为那个只是用来忽悠人的,没有收藏价值,我只是找了个类似的程序来举例。
这只是一个Python程序,在linux下写的,因为在linux中,强制换行的是换行符0AH,而在DOS(Windows)下,换行是用0DH(回车符)和0AH(换行符)共同来实现的,所以,用记事本打开时,就会出现乱码,其实只要用代码编辑软件打开(如Win-TC,VC,UltraEditor,Python附带的代码编辑软件IDLE)都不会出现乱码,而是非常清晰的程序格式,因为代码编辑软件显示时是以代码行为单位显示的,换行符不可能出现在意行的中间,而且也没有一种语言为换行符定义了编译后的功能。