中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 搜索 | 上传 | 帮助 »
作者:
标题: 这是什么编码方式 上一主题 | 下一主题
phai2003
初级用户




积分 20
发帖 9
注册 2007-11-3
状态 离线
『楼 主』:  这是什么编码方式

请高手们看看下面的这个程序 它用的是编码还是其它什么方法.顺便回答我下面的问题 如果是编码,那么它是如何自解码的? 以下是一个延时程序,虽然从表面上看与那个毫无关联. 复制内容到剪贴板 代码: Bj@jzh`0X-`/PPPPPPa(DE(DM(DO(Dh(Ls(Lu(LX(LeZRR]EEEUYRX2Dx= 0DxFP,0Xx.t0P,=XtGsB4o@$?PIyU WwX0GwUY Wv;ovBX2Gv0ExGIuht6 T}{z~~@GwkBG@OEKcUt`~}@MqqBsy?seHB~_Phxr?@zAB`LrPEyoDt@Cj? pky_jN@QEKpEt@ij?jySjN@REKpEt@jj?jyGjN@SEKkjtlGuNw?p@pjirz LFvAURQ?OYLTQ@@?~QCoOL~RDU@?aU?@{QOq?@}IKuNWpe~FpeQFwH?Vkk _GSqoCvH{OjeOSeIQRmA@KnEFB?p??mcjNne~B?M??QhetLBgBPHexh@e= EsOgwTLbLK?sFU`?LDOD@@K@xO?SUudA?_FKJ@N?KD@?UA??O}HCQOQ??R _OQOL?CLA?CEU?_FU?UAQ?UBD?LOC?ORO?UOL?UOD?OOI?UgL?LOR@YUO? dsmSQswDOR[BQAQ?LUA?_L_oUNUScLOOuLOODUO?UOE@OwH?UOQ?DJTSDM QTqrK@kcmSULkPcLOOuLOOFUO?hwDTqOsTdbnTQrrDsdFTlnBTm`lThKcT @dmTkRQSoddTT~?K?OCOQp?o??Gds?wOw?PGAtaCHQvNntQv_w?A?it\EH {zpQpKGk?Jbs?FqokOH{T?jPvP@IQBDFAN?OHROL?Kj??pd~aN?OHROd?G Q??PGT~B??OC~?ipO?T?~U?p~cUo0x 复制这个代码保存为sleep.com 然后在COMMAND.COM里运行就能看到一个EXE文件的镜像. 或用sleep.com>sleep.exe生成一个EXE文件. 这是德国人写的一个东东.可以说是纯P的.没有使用DEBUG技术. 对其代码进行分析,当分析关键代码时,遇到前所未有的困难. 这个程序可以自己改变文本(或说是程序)中的内容,从而更接近机器码. 最后在一个代码串中反复执行.什么时候出来就不知道了. 这个代码如下: 0C1E:0132 55 PUSH BP 0C1E:0133 59 POP CX 0C1E:0134 52 PUSH DX 0C1E:0135 58 POP AX 0C1E:0136 324478 XOR AL,[SI+78] 0C1E:0139 3D0D0A CMP AX,0A0D 0C1E:013C 304478 XOR [SI+78],AL 0C1E:013F 46 INC SI 0C1E:0140 50 PUSH AX 0C1E:0141 2C30 SUB AL,30 0C1E:0143 58 POP AX 0C1E:0144 78EE JS 0134 0C1E:0146 7430 JZ 0178 0C1E:0148 50 PUSH AX 0C1E:0149 2C3D SUB AL,3D 0C1E:014B 58 POP AX 0C1E:014C 7407 JZ 0155 0C1E:014E 7302 JNB 0152 0C1E:0150 346F XOR AL,6F 0C1E:0152 40 INC AX 0C1E:0153 243F AND AL,3F 0C1E:0155 50 PUSH AX 0C1E:0156 49 DEC CX 0C1E:0157 79DB JNS 0134 0C1E:0159 205777 AND [BX+77],DL 0C1E:015C 58 POP AX 0C1E:015D 304777 XOR [BX+77],AL 0C1E:0160 55 PUSH BP 0C1E:0161 59 POP CX 0C1E:0162 205776 AND [BX+76],DL 0C1E:0165 C1 DB C1 0C1E:0166 6F DB 6F 0C1E:0167 7602 JBE 016B 0C1E:0169 58 POP AX 0C1E:016A 324776 XOR AL,[BX+76] 0C1E:016D 304578 XOR [DI+78],AL 0C1E:0170 47 INC DI 0C1E:0171 49 DEC CX 0C1E:0172 75EE JNZ 0162 0C1E:0174 74BC JZ 0132 我执行了二百遍,代码也未发生改变. 但用g 176时,结果就出来了.显示如下: (因为cs:0176永远都执行不到,程序根本不能从里面出去,所以这跟直接用g是没差别的) MZP☺☺ ♦ P☺ @ É ⁿ╛ü ☼╢L f1╥f1└Ix ¼,0r¶< w►fk╥ f☺┬.╟♠/ 1 δΣ. &/ ♫ fi╥Φ♥ fë╤f┴Θ►┤å═§╕ L═! PE L☺☺ PyÑ6 α ☼☺♂☺♣♀ ☻ ~► ► @ ► ☻ ♦ ♦ ☻ ♥ ► ► ► ► ► ►► ( ► ► .text ▄ ► ☻ ☻ α V► d► v► F► 8► ► KERNEL32.dll V► d► v► ExitProcess GetCommandLineA Sleep §♦►@ 1╥H@Ç8 t◄Ç8"u☻≈╥ ╥u∩Ç8 uΩ@ⁿë╞1╥1└└t#,0r§< w◄k╥ ☺┬╟♣╔►@ ═►@ δΓ %╔►@ Ñ ►@ R ►@ j § ►@ 这就是sleep.exe的镜像了.看到了吧,还有API呢. 这显然是用高级语言编写然后用了某种技术,使之成为纯文本. 不过程序并没退出,还会继续,不过要人干预,所以并没影响sleep.exe的使用. 出口就在cs:136上.再执行,就会进入到小于CS:100的地方去了,显然会出错. 这是一个标准的PE文件,反编译后能了解其内容. 0040107E: FF 15 04 10 40 00 CALL DWORD PTR [00401004] ; GetCommandLineA 00401084: 31 D2 XOR EDX,EDX 00401086: 48 DEC EAX 00401087: 40 INC EAX 00401088: 80 38 00 CMP BYTE PTR [EAX],00 0040108B: 74 11 JZ 0040109E 0040108D: 80 38 22 CMP BYTE PTR [EAX],22 00401090: 75 02 JNZ 00401094 00401092: F7 D2 NOT EDX 00401094: 09 D2 OR EDX,EDX 00401096: 75 EF JNZ 00401087 00401098: 80 38 20 CMP BYTE PTR [EAX],20 0040109B: 75 EA JNZ 00401087 0040109D: 40 INC EAX 0040109E: FC CLD 0040109F: 89 C6 MOV ESI,EAX 004010A1: 31 D2 XOR EDX,EDX 004010A3: 31 C0 XOR EAX,EAX 004010A5: AC LODS AL,BYTE PTR DS:[ESI] 004010A6: 08 C0 OR AL,AL 004010A8: 74 23 JZ 004010CD 004010AA: 2C 30 SUB AL,30 004010AC: 72 15 JB 004010C3 004010AE: 3C 09 CMP AL,09 004010B0: 77 11 JNBE 004010C3 004010B2: 6B D2 0A IMUL EDX,EDX,0A 004010B5: 01 C2 ADD EDX,EAX 004010B7: C7 05 C9 10 40 00 CD 10 40 00 MOV DWORD PTR [004010C9],004010CD 004010C1: EB E2 JMP 004010A5 004010C3: FF 25 C9 10 40 00 JMP DWORD PTR [004010C9] 004010C9: A5 MOVS DWORD PTR DS:[ESI],DWORD PTR ES:[EDI] 004010CA: 10 40 00 ADC [EAX+00],AL 004010CD: 52 PUSH EDX 004010CE: FF 15 08 10 40 00 CALL DWORD PTR [00401008] ; Sleep 004010D4: 6A 00 PUSH 00 004010D6: FF 15 00 10 40 00 CALL DWORD PTR [00401000] ; ExitProcess 也能用工具看到他有exe文件的格式: 00000000 5A4D Signature: MZ 00000002 0150 Extra Bytes 00000004 0001 Pages 00000006 0000 Reloc Items 00000008 0004 Header Size 0000000A 0000 Min Alloc 0000000C FFFF Max Alloc 0000000E 0000 Initial SS 00000010 0150 Initial SP 00000012 0000 Check Sum 00000014 0000 Initial IP 00000016 0000 Initial CS 00000018 0040 Reloc Table 0000001A 0000 Overlay 00000090 00004550 Signature: PE 00000094 014C Machine: 014C=I386 00000096 0001 Number of Sections 00000098 36A57950 Time/Date Stamp 0000009C 00000000 Pointer to Symbol Table 000000A0 00000000 Number of Symbols 000000A4 00E0 Optional Header Size 000000A6 010F Characteristics 00000188 .text Section Name 00000190 000000DC Virtual Size 00000194 00001000 RVA/Offset 00000198 00000200 Size of Raw Data 0000019C 00000200 Pointer to Raw Data 000001A0 00000000 Pointer to Relocs 000001A4 00000000 Pointer to Line Numbers 000001A8 0000 Number of Relocs 000001AA 0000 Number of Line Numbers 000001AC E0000020 Section Flags (Writeable, Readable, Executable, Code) 不再怀疑它是一个正宗的PE文件了吧. 至于sleep.exe原理吗,很简单,看下面就知道了 00000000 ExitProcess 00000000 GetCommandLineA 00000000 Sleep 这三个都是kernel32.dll中的API,也就是说可以直接用高级汇编语言,比如win32asm调用. 我的问题是为什么虽然这个代码串是一个死循环,但程序依然能运行.在不出来的情况下执行了.并显示了上面的EXE镜象. 希望有汇编高手能给予解答.


2007-11-4 10:56
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
phai2003
初级用户




积分 20
发帖 9
注册 2007-11-3
状态 离线
『第 2 楼』:  

对Sleep.exe的研究已有所突破 已经大致了解它的工作原理了 那的确是个能自解码的程序. [ Last edited by phai2003 on 2007-11-4 at 12:32 PM ]


2007-11-4 12:25
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
phai2003
初级用户




积分 20
发帖 9
注册 2007-11-3
状态 离线
『第 3 楼』:  

程序是从 jz 0178出去的.这个前面忽略了. 然后通过用了INT 21 ah:40 来输出.然后返回.没用ah:4c int 21结束程序 上面的问题已解决了.但编码方式仍未解决


2007-11-4 18:04
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
phai2003
初级用户




积分 20
发帖 9
注册 2007-11-3
状态 离线
『第 4 楼』:  

以下是本人对此的最新研究成果: 最开头的两行 Bj@jzh`0X-`/PPPPPPa(DE(DM(DO(Dh(Ls(Lu(LX(LeZRR]EEEUYRX2Dx= 0DxFP,0Xx.t0P,=XtGsB4o@$?PIyU WwX0GwUY Wv;ovBX2Gv0ExGIuht6 就是解码程序.后面的是被解码的. (DM(DO(Dh(Ls(Lu(LX(Le这段反汇编是 0C1E:0100 42 INC DX 0C1E:0101 6A DB 6A ;这其实是6A40: PUSH 0040 0C1E:0102 40 INC AX 0C1E:0103 6A DB 6A ;这其实是6A7A: PUSH 007A 0C1E:0104 7A68 JPE 016E 0C1E:0106 60 DB 60 ;这其实是686030: PUSH 3060 0C1E:0107 30582D XOR [BX+SI+2D],BL 0C1E:010A 60 DB 60 ;这其实是58: POP AX 0C1E:010B 2F DAS ;这其实是2D602F SUB AX,2F60 0C1E:010C 50 PUSH AX ;所以40,7A,3060就是很关键的值 0C1E:010D 50 PUSH AX ;AX经SUB后就得到COM程序的入口100 0C1E:010E 50 PUSH AX 0C1E:010F 50 PUSH AX 0C1E:0110 50 PUSH AX 0C1E:0111 50 PUSH AX ;al:40 cl:7a 40,7a就是这么用的 0C1E:0112 61 DB 61 ;这代码实际上是popa 0C1E:0113 284445 SUB [SI+45],AL // ;AL:40 [SI+45]: EE 所以0144:78EE js 0134 0C1E:0116 28444D SUB [SI+4D],AL ;[14d]:7407: je 0155 0C1E:0119 28444F SUB [SI+4F],AL ;[14f]:7302: jnb 0152 0C1E:011C 284468 SUB [SI+68],AL ;这些代码是将关键的地方改成跳转 JBE 016B 0C1E:011F 284C73 SUB [SI+73],CL ;[173]:75EE: JNZ 0162 0C1E:0122 284C75 SUB [SI+75],CL ;[175]:74BC: JZ 0132 0C1E:0125 284C58 SUB [SI+58],CL ;[158]:79dbJNS 0134 0C1E:0128 284C65 SUB [SI+65],CL //(DM(DO(Dh(Ls(Lu(LX(Le的反汇编 shr word ptr [bx+76],02 0C1E:012B 5A POP DX 0C1E:012C 52 PUSH DX 0C1E:012D 52 PUSH DX 0C1E:012E 5D POP BP 0C1E:012F 45 INC BP 0C1E:0130 45 INC BP 0C1E:0131 45 INC BP 0C1E:0132 55 PUSH BP 0C1E:0133 59 POP CX 0C1E:0134 52 PUSH DX // 0C1E:0135 58 POP AX 0C1E:0136 324478 XOR AL,[SI+78] 0C1E:0139 3D0D0A CMP AX,0A0D 0C1E:013C 304478 XOR [SI+78],AL ;[si+78]=0 就是填充0 0C1E:013F 46 INC SI 0C1E:0140 50 PUSH AX ;保存AX 0C1E:0141 2C30 SUB AL,30 AL=AL-30h 0C1E:0143 58 POP AX 弹出AX 0C1E:0144 78EE JS 0134 0C1E:0146 7430 JZ 0178 若是回车换行,就跳 0C1E:0148 50 PUSH AX 0C1E:0149 2C3D SUB AL,3D 0C1E:014B 58 POP AX 0C1E:014C 7407 JZ 0155 0C1E:014E 7302 JNB 0152 0C1E:0150 346F XOR AL,6F 0C1E:0152 40 INC AX 0C1E:0153 243F AND AL,3F ;解码 0C1E:0155 50 PUSH AX 0C1E:0156 49 DEC CX ;循环次数 0C1E:0157 79DB JNS 0134 //p 这段是解码程序 0C1E:0159 205777 AND [BX+77],DL 0C1E:015C 58 POP AX 这是关键值 0C1E:015D 304777 XOR [BX+77],AL 0C1E:0160 55 PUSH BP 0C1E:0161 59 POP CX 0C1E:0162 205776 AND [BX+76],DL dl=0 0C1E:0165 C1 DB C1 ;使[bx+76]=40h 0C1E:0166 6F DB 6F ; 这三行不对, 0C1E:0167 7602 JBE 016B ;shr word ptr [bx+76],02 0C1E:0169 58 POP AX 0C1E:016A 324776 XOR AL,[BX+76] ;[bx+76]=0 或 [bx+76]+40 0C1E:016D 304578 XOR [DI+78],AL ;[di+78]=al 没执行前等于0 0C1E:0170 47 INC DI ;[bx+76]的值就是临时存存储用的 0C1E:0171 49 DEC CX 0C1E:0172 75EE JNZ 0162 0C1E:0174 74BC JZ 0132 以下是输出的.从0C1E:0178过来的. 这时已有镜象了,但还是把它拷到033F开头的地方去.并适当 填充0 0C1E:0176 0000 ADD [BX+SI],AL ;这两句会在运行时变动的.最后才变为CLD 0C1E:0178 FC CLD ;[0176]有时会变成40 0C1E:0179 BED501 MOV SI,01D5 0C1E:017C BF3F03 MOV DI,033F 0C1E:017F AC LODSB 0C1E:0180 3806D001 CMP [01D0],AL 0C1E:0184 7516 JNZ 019C 0C1E:0186 A4 MOVSB 0C1E:0187 81FE3F03 CMP SI,033F 0C1E:018B 72F2 JB 017F 0C1E:018D B440 MOV AH,40 0C1E:018F BA3F03 MOV DX,033F ;[033f]=sleep.exe的镜象 0C1E:0192 89F9 MOV CX,DI 0C1E:0194 29D1 SUB CX,DX 0C1E:0196 BB0100 MOV BX,0001 0C1E:0199 CD21 INT 21 ;打印字符 0C1E:019B C3 RET ;返回,跳到0c1e:0去了.也就是int 20 0C1E:019C 3A06D101 CMP AL,[01D1] 0C1E:01A0 7505 JNZ 01A7 0C1E:01A2 31C0 XOR AX,AX 0C1E:01A4 AB STOSW 0C1E:01A5 EBE0 JMP 0187 0C1E:01A7 3A06D201 CMP AL,[01D2] 0C1E:01AB 7506 JNZ 01B3 0C1E:01AD 31C0 XOR AX,AX 0C1E:01AF AB STOSW 0C1E:01B0 AA STOSB 0C1E:01B1 EBD4 JMP 0187 ;显然这是个循环 程序用了INT 21 ah:40 来输出.然后返回.没用ah:4c int 21结束程序


2007-11-4 19:10
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
dikex
高级用户

潜水修练批处理



积分 788
发帖 366
注册 2006-12-31
状态 离线
『第 5 楼』:  

老实说,这个和脚本等没有太大的联系-_-




正在潜水修练的批处理小白
2007-11-4 19:22
查看资料  发短消息  网志   编辑帖子  回复  引用回复
knoppix7
银牌会员





积分 1287
发帖 634
注册 2007-5-2
来自 cmd.exe
状态 离线
『第 6 楼』:  

编码方式很特殊的说.国内还没有看到相关资料.


2007-11-4 19:44
查看资料  发短消息  网志   编辑帖子  回复  引用回复
phai2003
初级用户




积分 20
发帖 9
注册 2007-11-3
状态 离线
『第 7 楼』:  

算法分析: 以4个字符为一组: 假设为A B C D 则(((D-40)+1)&00 << 2) xor C 有时要再加40 (((B-40)+1)&00 << 2) xor A 有时要再加40


2007-11-4 20:48
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
phai2003
初级用户




积分 20
发帖 9
注册 2007-11-3
状态 离线
『第 8 楼』:  

已解,呵呵


2007-11-12 15:02
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
knoppix7
银牌会员





积分 1287
发帖 634
注册 2007-5-2
来自 cmd.exe
状态 离线
『第 9 楼』:  

能写个程序实现从EXE到这个的转化就好了..


2007-11-12 17:27
查看资料  发短消息  网志   编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: