首页
社区
课程
招聘
[讨论]csdsjkk外壳学习
发表于: 2007-12-15 18:59 6311

[讨论]csdsjkk外壳学习

2007-12-15 18:59
6311
这是csdsjkk写的外壳,并且还提供了源码

壳作者自己的说明:

////////////////////////////////////////////

简单说一下壳采用的几种反跟踪调试的方法:
双进程、
多线程(解码、检测调试、检测api断点)、
iat变形(用importrec自动跟踪可以抓出来)、
自创的花指令等

说实话,我自己跟起都很费力

经过对源码的跟踪和分析,明白了一些

为了帮助更多的人学习这个源码所用的技术以及得到高手的指点和纠正
特附上了解读这个源码后加上的注释,不一定是正确,如果错了,请大家指出来
以免误导初学者

由于源码很长,只能注释一部分,但也一定是最详细的.

注:有API的地方一般不做注释,因为很好理解

start:

;        int 3

        jmp st1

        invoke LoadLibrary,addr shell32
        invoke GetProcAddress,eax,800000e9h

;        invoke VirtualAlloc,0h,10000h,MEM_RESERVE,PAGE_READWRITE
;        invoke VirtualQuery,eax,addr mbi,sizeof MEMORY_BASIC_INFORMATION

;        invoke VirtualAlloc,0h,10000h,MEM_COMMIT,PAGE_READWRITE
;        invoke VirtualAlloc,0h,10000h,MEM_COMMIT,PAGE_READWRITE

;        invoke VirtualProtect,3e0000h,10,PAGE_READONLY,addr temp1       

        mov esi,400000h
@@:
        invoke VirtualQuery,esi,addr mbi,sizeof MEMORY_BASIC_INFORMATION
;        cmp dword ptr mbi[10h],10000h
;        je @f
        mov esi,dword ptr mbi[0]     ;MEMORY_BASIC_INFORMATION.BaseAddress]
        add esi,dword ptr mbi[0ch]   ;MEMORY_BASIC_INFORMATION.RegionSize]
        cmp eax,0
        jne @b
@@:
        mov eax,dword ptr mbi[0]
;        invoke VirtualAlloc,eax,10h,MEM_COMMIT,PAGE_READWRITE
        cmp eax,0
        jne @f

        invoke VirtualQuery,3e0000h,addr mbi,sizeof MEMORY_BASIC_INFORMATION
;        invoke VirtualAlloc,0,10h,MEM_COMMIT,PAGE_READWRITE
        invoke VirtualQuery,3e0000h,addr mbi,sizeof MEMORY_BASIC_INFORMATION

@@:

st1:

        invoke VirtualProtect,addr entry,key_size,PAGE_READWRITE,addr temp1         ;改变内存页的保护属性

        invoke GetTickCount            
        push eax
        invoke GetTickCount
        pop edx
        mul edx
        mov dword ptr dc_edit+1,eax        ;用获得MS级的时间作为随机数
        mov dword ptr ec_edit+1,eax        

        call calc_checksum      ;制作两个代码的校验标志(0-所有代码中数据的字节和)

        invoke GetTickCount
        push eax
        invoke GetTickCount
        pop edx
        mul edx
        mov decode_key,eax     ;用两个随机数相乘的值作为解码值.
        not eax
        mov rnd,eax

        mov esi,offset _ok
        mov edi,offset __ok
        mov eax,decode_key
@@:                           ;把代码2编码,也就是加密
        cmp esi,edi
        jae @f                ;JAE/JNB CF=0 时跳转
        xor [esi],al
        inc eax
        ror eax,7         ;eax循环右移>>7
        inc esi
        jmp @b

@@:

       
        invoke GetCommandLine
        call trans  ;分解命令行

        invoke CreateFile,addr fname1,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,0
        cmp eax,INVALID_HANDLE_VALUE
        je error1
        mov hfile1,eax

        invoke CreateFile,addr fname2,GENERIC_WRITE,0,0,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,0
        cmp eax,INVALID_HANDLE_VALUE
        je error3
        mov hfile3,eax
       
                  

        invoke GetFileSize,hfile1,0
        mov fsize1,eax

        invoke VirtualAlloc,0,fsize1,MEM_COMMIT,PAGE_READWRITE
        mov pt1,eax
        invoke ReadFile,hfile1,pt1,fsize1,addr temp1,0
       

        mov ebx,pt1
        mov esi,[ebx+3ch]                     ;IMAGE_DOS_HEADER.e_lfanew

        cmp flag_clear_boundimport,0
        je @f
        lea eax,[ebx+esi+0d0h]               ;IMAGE_DIRECTORY_ENTRY_IAT.值为12
        mov dword ptr [eax],0
        mov dword ptr [eax+4],0              ;清空这个表
@@:

        cmp flag_clear_load_config,0        ;IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT,值为11
        je @f
        lea eax,[ebx+esi+0c8h]              ;清空这个表(一般来说这两个表都不用.)
@@:
        mov dword ptr [eax],0
        mov dword ptr [eax+4],0
@@:

        mov eax,[ebx+esi+34h]              ;指向ImageBase地址(RVA)
        mov image_base,eax

        push esi
        lea esi,[ebx+esi+78h]             ;IMAGE_DIRECTORY_ENTRY_EXPORT,指向导出表
        mov edi,offset rva_table          ;DIRECTORY表
        mov ecx,80h
        call move_memory                  ;调整各个表
        pop esi

        cmp flag_add_section,0           ;标志
        je @f
        add word ptr [ebx+esi+6],1
@@:
        mov eax,0
        xchg eax,[ebx+esi+80h]            ;IMAGE_DIRECTORY_ENTRY_IMPORT,指向导入表
        mov iat_offs,eax                  ;保存IAT,然后清空IAT
        mov eax,0
        xchg eax,[ebx+esi+84h]
        mov iat_size,eax
        mov eax,0
        xchg eax,[ebx+esi+0a0h]           ;IMAGE_DIRECTORY_ENTRY_BASERELOC,指向重定位表
        mov reloc_offs,eax                ;同样保存后清空
        mov eax,0
        xchg eax,[ebx+esi+0a4h]
        mov reloc_size,eax

       
       
        lea edi,[esi+0f8h]               ;第一个节表
        movzx eax,word ptr [ebx+esi+6]   ;保存节的数目
        mov temp1,eax

st2:
        dec temp1
        jz st3                  
        jmp @f

        cmp dword ptr [ebx+edi+0ch],0       ;;;;;;
        je st3
        cmp dword ptr [ebx+edi+08h],0       ;;;;;;
        je st3

@@:

jmp st24

        mov eax,dword ptr [ebx+esi+0a8h]
        cmp eax,0
        je @f
        add eax,dword ptr [ebx+esi+0ach]
        cmp eax,dword ptr [ebx+edi+0ch]
        jb @f
        mov eax,dword ptr [ebx+edi+0ch]
        add eax,dword ptr [ebx+edi+8]
        cmp eax,dword ptr [ebx+esi+0a8h]
        ja st25
@@:
        mov eax,dword ptr [ebx+esi+88h]
        cmp eax,0
        je @f
        add eax,dword ptr [ebx+esi+8ch]
        cmp eax,dword ptr [ebx+edi+0ch]
        jb @f
        mov eax,dword ptr [ebx+edi+0ch]
        add eax,dword ptr [ebx+edi+8]
        cmp eax,dword ptr [ebx+esi+88h]
        ja st25
@@:
        mov eax,dword ptr [ebx+esi+0c0h]
        cmp eax,0
        je @f
        add eax,dword ptr [ebx+esi+0c4h]
        cmp eax,dword ptr [ebx+edi+0ch]
        jb @f
        mov eax,dword ptr [ebx+edi+0ch]
        add eax,dword ptr [ebx+edi+8]
        cmp eax,dword ptr [ebx+esi+0c0h]
        ja st25
@@:
st24:
        mov eax,[ebx+edi+8]                      ;VirtualSize 节区大小
        cmp eax,[ebx+edi+10h]                    ;SizeOfRawData   判断是否超过了对齐粒度
        jbe @f
        mov eax,[ebx+edi+10h]
@@:
        mov ecx,[ebx+edi+14h]                   ;PointerToRawData 在文件中的偏移
        ;;;;;;add ecx,ebx
        mov edx,[ebx+edi+0ch]                   ;VirtualAddress 节区的RVA
        sub ecx,edx   ;                         ;节区的RVA对应的偏移量
        invoke encode,edx,eax,ebx,ecx           ;对内存中的IAMAGE编码(加密被加壳的程序)
st25:
        add edi,28h                             ;跳到下一个节(对每一节即代码,数据,资源都加密)
        jmp st2
st3:                                            ;各节的加密已经完成了
        push edi
        lea eax,[esi+0f8h]                      ;重新计算节的数目(最后节的节尾-起始节的节头)/节长
        sub edi,eax
        mov edx,0
        mov eax,edi
        mov edi,28h
        div edi
        mov number_of_section,eax
        pop edi
       
        cmp flag_add_section,0                  ;引入的标志
        jne st6
       
        mov eax,fsize1
        sub eax,[ebx+edi+14h]
        test eax,00000fffh
        jz @f
        add eax,1000h
@@:
        and eax,0fffff000h
        push eax
        add eax,key_size
        test eax,00000fffh
        jz @f
        add eax,1000h
@@:
        and eax,0fffff000h
        mov [ebx+edi+08h],eax
        mov [ebx+edi+10h],eax

        or dword ptr [ebx+edi+24h],0a0000020h  ;mov dword ptr [ebx+edi+24h],0e0000040h

        pop ecx
        mov eax,[ebx+edi+0ch]
        add eax,ecx
        add eax,offset entry
        sub eax,offset entry
        xchg [ebx+esi+28h],eax       
        mov shell_eip,eax
        jmp st7

st6:       
        mov eax,key_size                      ;代码长度
        test eax,00000fffh                    ;测试是否对齐(1000h*n)
        jz @f
        add eax,1000h
@@:
        and eax,0fffff000h                    
        mov [ebx+edi+8],eax                   ;写入新节的内容
        sub edi,28h
        mov eax,[ebx+edi+0ch]
        add eax,[ebx+edi+8]
        test eax,00000fffh
        je @f
        add eax,1000h
@@:
        and eax,0fffff000h                    ;计算位置              
        add edi,28h
        mov [ebx+edi+0ch],eax                 ;VirtualAddress 节区的RVA地址
               
        mov eax,key_size
        test eax,00000fffh
        jz @f
        add eax,1000h
@@:
        and eax,0fffff000h
        mov [ebx+edi+10h],eax                ;SizeOfRawData  在文件中对齐后的尺寸
        mov eax,fsize1
        test eax,00000fffh
        je @f
        add eax,1000h
@@:
        and eax,0fffff000h
        mov [ebx+edi+14h],eax                ; PointerToRawData 在文件中的偏移

        mov dword ptr [ebx+edi+24h],0e0000020h  ;Characteristics 节的属性  

        mov eax,[ebx+edi+0ch]
        add eax,offset entry
        sub eax,offset entry
        xchg [ebx+esi+28h],eax                      ;更改AddressOfEntryPoint
        mov shell_eip,eax                     ;入口

st7:

        mov eax,[ebx+edi+0ch]                 ;新节区的VirtualAddress 节区的RVA地址
        add eax,[ebx+edi+8]                   ;VirtualSize 新节区的尺寸
        test eax,00000fffh                    ;测试有没对齐
        je @f
        add eax,1000h
@@:
        and eax,0fffff000h
        mov [ebx+esi+50h],eax                ;更改SizeOfImage 内存中整个PE映像尺寸

;所有的文件头中要修改的部分都修改了

       
        mov eax,decode_key          ;解码键
        xor shell_eip,eax

        lea esi,entry00
        mov ecx,__ok - entry00
@@:
        not byte ptr [esi]         ;加密entry00(解码加到被加壳文件的代码)的代码
        inc esi
        loop @b
        mov flag_reentry,0         ;flag_reentry=0表示已加密

        invoke WriteFile,hfile3,pt1,fsize1,addr temp1,0         ;写到新文件中(不过还是原文件的大小)

        cmp flag_add_section,0                                  ;标志
        jne st75
        mov eax,fsize1
        sub eax,[ebx+edi+14h]
        mov ecx,1000h
        sub ecx,eax
        jns st71
@@:
        add ecx,1000h
        js @b
st71:
        mov eax,ecx
        jmp st8

st75:
        mov eax,fsize1                                           ;新文件的长度
        test eax,00000fffh                                       ;有无对齐
        je @f
        add eax,1000h
@@:
        and eax,0fffff000h
        sub eax,fsize1
st8:
        lea ecx,_fill
        invoke WriteFile,hfile3,ecx,eax,addr temp1,0            ;写入_fill处的数据.现在是空值(加大1K)

        mov eax,key_size                                    
        test eax,00000fffh
        jz @f
        add eax,1000h
@@:
        and eax,0fffff000h
        invoke WriteFile,hfile3,addr entry,eax,addr temp1,0    ;写入entry代码

        invoke CloseHandle,hfile1                              ;关闭这两个文件

        invoke CloseHandle,hfile3

        invoke VirtualFree,pt1,0,MEM_RELEASE

        invoke CreateFile,addr fname2,GENERIC_READ + GENERIC_WRITE,0,0,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,0
        cmp eax,INVALID_HANDLE_VALUE
        je error3
        mov hfile1,eax
       
                  

        invoke GetFileSize,hfile1,0              ;得到文件的大小,用于后面读出全部内容
        mov fsize1,eax

        invoke VirtualAlloc,0,fsize1,MEM_COMMIT,PAGE_READWRITE     ;分配虚拟内存
        mov pt1,eax
        invoke ReadFile,hfile1,pt1,fsize1,addr temp1,0             ;把文件读入缓冲区pt1中

        mov ecx,fsize1
        mov edi,pt1
uu1:
        cmp ecx,8                                 ;在文件中有无'LiNr'和'VoTa'字符串
        jb nofound
        cmp dword ptr [edi],'LiNr' ;'rNiL'        ;加壳后的标志'rNiLaToV'
        jne uu2
        cmp dword ptr [edi+4],'VoTa' ;'aToV'
        je found
uu2:
        inc edi
        loop uu1
        jmp nofound
found:                                            ;已加壳了
        add edi,8
        sub edi,pt1                               ;获得标志'rNiLaToV'的偏移量

        mov ebx,pt1
        mov esi,[ebx+3ch]                        ;获得PE头位置

        movzx ecx,word ptr [ebx+esi+6]           ;扩展为双字NumberOfSections
        mov eax,[ebx+esi+74h]                    ; NumberOfRvaAndSizes
        shl eax,3                                ;NumberOfRvaAndSizes*8(每个IMAGE_DATA_DIRECTORY 8字节)
        lea edx,[ebx+esi+78h]                    ;IMAGE_DIRECTORY_ENTRY_EXPORT
        add edx,eax                              ;得到节表的位置
uu3:
        cmp dword ptr [edx+14h],edi              ;PointerToRawData 在文件中的偏移
        ja s_nt
        mov eax,[edx+8]                          ;VirtualSize 节区的尺寸
        add eax,[edx+14h]                        ;得到代码段的位置
        cmp eax,edi
        jbe s_nt                                 ;超过的话,执行下面的代码

        mov eax,edi                              ;文件尾
        sub eax,[edx+14h]                        ;算出所余的空间
        add eax,[edx+0ch]                        ;VirtualAddress 节区的RVA地址(把这个作为导入表的地址)

        mov [ebx+esi+80h],eax                    ;IMAGE_DIRECTORY_ENTRY_IMPORT的VirtualAddress
        mov dword ptr [ebx+esi+84h],14h          ;IMAGE_DIRECTORY_ENTRY_IMPORT的isize(数据块的长度)
        lea ecx,[eax+size1]                      ;
        mov [ebx+edi+0ch],ecx                    ;VirtualAddress 节区的RVA地址
        lea ecx,[eax+size1+size2]                ;加上DLL的长度后的RVA
        mov [ebx+edi+size1+size2+size3],ecx      ;在原来的函数表后面再填上这个RVA
        lea ecx,[eax+size1+size2+size3]          ;算出新的RVA
        mov [ebx+edi+10h],ecx                    ;SizeOfRawData  在文件中对齐后的尺寸
        jmp found1

s_nt:
        add edx,28h                             ;没超过的话,取下个节
        loop uu3
        jmp nofound

found1:
        invoke SetFilePointer,hfile1,0,0,FILE_BEGIN       
        invoke WriteFile,hfile1,pt1,fsize1,addr temp1,0  ;重写,更改了IAT了.原来全是0
       

nofound:
        invoke CloseHandle,hfile1                        ;关闭原文件

        invoke VirtualFree,pt1,0,MEM_RELEASE             ;释放分配的内存

error1:
error2:
error3:
exit0:
        invoke ExitProcess,0                 ;退出进程,程序终止

_fill   db 1000h dup (0)                     ;填充数据0

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (15)
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
2
顶一下先!
2007-12-15 19:09
0
雪    币: 256
活跃值: (11)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
由于还处于研究阶段,所以还有好多没注释呢.以会后附上完整的源代码注释.
以附件方式传上来.
以供大家参考.新手学习.
如果有人对此已有研究,可以贴上你的心得.大家一块讨论.

附上加壳程序的源码
声明一下,之所以在这里上传是因为方便大家研究而已.内容并无修改
大家最好在csdsjkk的原版上下载
http://bbs.pediy.com/showthread.php?s=&threadid=22270
源码在第47楼
上传的附件:
2007-12-15 19:15
0
雪    币: 256
活跃值: (11)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
奇怪,为什么响应的人这么少呢.高手就是不一样啊.
2007-12-16 16:49
0
雪    币: 256
活跃值: (11)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
看来,做好的注释也没必要再上传了.
2007-12-16 16:50
0
雪    币: 50161
活跃值: (20645)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
6
一般如果不研究这块,是不会静下心将所有的代码耐心看完的,等以后碰到这块,可能会回过头细细研读。
2007-12-16 17:58
0
雪    币: 325
活跃值: (97)
能力值: ( LV13,RANK:530 )
在线值:
发帖
回帖
粉丝
7
LS的都是高手。
晚辈只有干顶地份。
偶连压缩壳都还刚刚入门~
把一个Aspack的流程用IDA分析了一下。
压缩算法还没有去研究。已经脑水不够了
2007-12-16 18:29
0
雪    币: 256
活跃值: (11)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
谢谢老大的嘉奖,等把代码都分析透后,再放上源码
2007-12-16 18:36
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
老大的一句话足够影响一代人亻啊。。
丁楼主
2007-12-16 18:58
0
雪    币: 256
活跃值: (11)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
现在还有很多问题,主要是跟踪得不准确.多线程能跟入,但出不来.特别是线程中有SEH的.
修改EIP后出来也很不正常.如果不能顺利跟踪就很难看懂源码.会给出错误的注释的.
这就会误人子弟了.自己弄错倒没什么,大家都弄错了.那可是偶的过失了.
2007-12-16 19:03
0
雪    币: 319
活跃值: (2459)
能力值: ( LV12,RANK:980 )
在线值:
发帖
回帖
粉丝
11
这个壳我跟踪过。楼主可以参考一下我的脱文。
2007-12-16 19:14
0
雪    币: 256
活跃值: (11)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
能否提供一个地址链接啊

下面这个是不是你写的呀
csdsjkk外壳脱壳笔记

--------------------------------------------------------------------------------

摘自:  2006-04-03 03:09:54  看雪论坛

原程序下载地址:http://bbs.pediy.com/showthread.php?s=&threadid=22270

下面的代码中有几个地方搞不清楚

:[ebx+402156],FFFFFFFD///F4到这里。这段代码全部解压结束。
0046F20E     838B 3F214000 02         or dword ptr ds:[ebx+40213F],2
0046F218   ^ E9 12FFFFFF              jmp 0046F12F
0046F227     83A3 56214000 FD         and dword ptr ds:[ebx+402156],FFFFFFFD///新建EIP跳出循环。
0046F232     6A 00                    push 0
0046F234     6A 00                    push 0
0046F236     E8 A3E6FFFF              call 0046D8DE///检测CC
0046F23E     838B F0204000 02         or dword ptr ds:[ebx+4020F0],2
0046F24A     C9                       leave
0046F24B     C2 0400                  retn 4///返回到系统代码。

77E1A990     50                       push eax///返回到这里。
77E1A991     E8 E0D40000              call 77E27E76  ; ExitThread///F8过。

三、解压子进程代码

走过77E1A991时会陷入死循环。F12暂停。然后到0046F4A5处新建EIP。

0046F4A5    /EB 03                    jmp short 0046F4AA///新建EIP。
0046F4A7    |9A 37A7EB01 9AEB         call far EB9A:01EBA737
0046F4AE     039A E767EB01            add ebx,dword ptr ds:[edx+1EB67E7]
0046F4B4     9A EB039AB7 27E8         call far E827:B79A03EB
0046F4BB     0000                     add byte ptr ds:[eax],al
0046F4BD     0000                     add byte ptr ds:[eax],al

新建EIP后用F7走几步。

去花后:

0046F4C3     5B                       pop ebx
0046F4C9     81EB BF344000            sub ebx,4034BF
0046F4D4     EB 1C                    jmp short 0046F4F2

EIP为什么要在0046F227处建.

mov esi,decode_start[ebx]
这里放入了解码代码的起始地址
对应壳的应该是 0046F4C3     5B      pop ebx
为什么在上面的JMP那里新建EIP,而不是0046F4C3
这个,对应我写的程序是JNE,改EIP后,还要改标志位才能进解码代码
而且,这样进去的有些初始条件不满足,解码程序也不能正常工作.致使
后面就无法分析了.

另外,进入线程必须把所有的其它线程都挂掉吗?
在OD中,对于线程中的线程好像在线程窗口里看不到,更不能将其挂起了
只能用你的那种进入线程的方法.

是不是只能这样做啊

通过这篇笔记,学会了新的跟踪方法.在此向csjwaman您表示感谢

您上QQ吗. 我的QQ是330759606 风之guitar
希望能和您交个朋友.

PE还是刚学,还有很多问题想请您指点一二呢.
2007-12-16 20:34
0
雪    币: 256
活跃值: (11)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
13
由于分析水平有限,把一些简单的先贴上.

但还是有不清楚的地方. 或注释错误的地方. 若有的话,请朋友们指正下

各节的加密:
encode        proc  stdcall uses ebx esi ecx edx      p_offs,p_size,base,xz

;        ret

        mov ebx,0
        mov ecx,p_size            ;节的大小
        cmp ecx,4                 ;是否低于4
        jb ec9
        sub ecx,3                 ;每次处理3字节
        mov esi,p_offs            ;RVA对应的偏移量
        add esi,xz                ;计算节在文件中的位置
        mov edx,base              ;DOS头基址
ec_edit label byte  ;!!!
        mov eax,'jdsg'  ;!!!      ;取字符串'jdsg'作初初始密钥
ec1:
        sub esi,xz                ;新的ESI就是节的RVA
        invoke isnot?,esi         ;检查是否在RVA为ESI的节内
        pushf                     ;保护标志位不被修改,这里存取了数据有无取完的信息
        add esi,xz                ;计算所取数据是是否到节尾
        popf
        jz @f                     ;以下是数据的加密 (数据是代码段时,每行都加密,为数据段时,只加密数据.不包括导入表)
        xor [esi+edx],eax         ;把数据和密钥作XOR ,
;        ror eax,7                 ;然后将密钥循环右移7位(这是高级加密,提高强度)
        add eax,7                 ;得到的密钥再加7
@@:
        inc esi                   ;对下一数据加密
        loop ec1       
ec9:
        ret
encode        endp

各节的解密:
decode        proc stdcall  uses esi ecx edx edi   p_offs,p_size,base,xz  ;这是解密程序

;        ret

dc0:

        mov ecx,p_size                       ;节的长度
        cmp ecx,4                            ;如果比4还要少,肯定该节不存在
        jb dc9
        sub ecx,3                            ;每次取3字节
        mov esi,p_offs                       ;节的RVA
        add esi,xz                           ;

check_int3                                   ;用RSTD检测有无中断

        mov edx,base                         ;基址
dc_edit label byte ;!!!
        mov eax,'jdsg' ;!!!                  ;把这密钥'jdsg'取出来
dc1:
        sub esi,xz                           ;
        invoke isnot?,esi                    ;判断这个RVA在什么节中
        pushf
        add esi,xz                           ;计算所取数据是是否到节尾
        popf
        jz @f                                ;如果是节尾,则往下执行
        push eax
        mov eax,-1                           ;以下是数据的解密
        ;int 0f7h

        mov edi,eax                          
        pop eax
        xor [esi+edx],eax                    ;把数据和密钥作XOR
;        ror eax,7
        add eax,7                            ;得到的密钥再加7
        ;xor [esi+edx],edi
@@:
        inc esi
        loop dc1                             ;继续取下一数据       
dc9:
        ret                                  ;解码完成,返回
decode        endp
2007-12-16 21:45
0
雪    币: 256
活跃值: (11)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
14
今天添上下面的代码,同时请高手们解释一下下面的疑惑.

gfa6:之前已经算出了函数的具体的入口地址.为什么还要定义的DLL组

并且还要call f_LoadLibrary[ebx]   ,以获得DLL的基址.

这个无法理解,是作者故弄玄虚吗.好像这样做是没必要的.

请求高手给予合理的解释.

forwardchain_dll        dd kernel32,user32,gdi32,ntdll,advapi32,ws2_32,mswsock,shlwapi
                        dd 0       
forwardchain_handle        dd 0       ,0     ,0    ,0    ,0       ,0     ,0      ,0
                        dd 0
kernel32                db 'KERNEL32.dll',0
user32                        db 'USER32.dll',0
gdi32                        db 'GDI32.dll',0
ntdll                        db 'NTDLL.dll',0
advapi32                db 'ADVAPI32.dll',0
ws2_32                        db 'WS2_32.dll',0
mswsock                 db 'MSWSOCK.dll',0
shlwapi                        db 'SHLWAPI',0

get_func_address        proc stdcall uses ebx ecx edx esi edi  base,p_funcname
       
local save_ebx:dword

        mov save_ebx,ebx

gfa1:
        mov ebx,base            ;基址
        mov eax,[ebx+3ch]       ;'PE'头
        mov eax,[ebx+eax+78h]   ;export table 导出表
        test p_funcname,80000000h ;测试函数是不是在80000000h以下,
        je gfa5
        mov esi,[ebx+eax+24h]  ;addr of ord       指向函数名序号表的RVA     
        mov edx,[ebx+eax+14h]  ;number of func    导出函数的起始序号
        mov ecx,p_funcname     ;函数名
        and ecx,7fffffffh
        sub ecx,[ebx+eax+10h]
        cmp ecx,edx
        jae @@90
               
        add ecx,ecx
        add ecx,ecx
        mov edi,ecx

        add edi,[ebx+eax+1ch]
        mov eax,[ebx+edi]
        add eax,ebx
       
        jmp gfa6

gfa5:

        cmp ebx,p_funcname      ;与基址比较
        ja @f
;;;        mov eax,p_funcname
;;;        jmp @@9
@@:

        mov esi,[ebx+eax+20h]   ;addr of names    指向函数名地址表的RVA (函数名地址表:它的成员是指向函数名字符串的地址)
        mov edx,[ebx+eax+18h]   ;number of names   以名称导出的函数总数
        push eax
@@0:
        mov ecx,p_funcname
        mov edi,[esi+ebx]       ;内存中的函数表地址
@@:
        mov al,[edi+ebx]        ;按字节比较
        cmp al,[ecx]            ;不是要找的函数就跳,然后继续找下一个
        jne @f
        cmp al,0                ;看是否取完这个函数名的字符串
        je @@1
        inc edi                 ;取下个
        inc ecx
        jmp @b                        ;循环检查在什么位置
@@:
        add esi,4               ;指向下一个导出函数地址(因为地址是一个字,占4个字节)
        dec edx                 ;取一个,就少一个了
        jnz @@0                        ;如果取了所有的函数,就做些清理工作,没有就再次回去找       
        mov eax,0
        jmp @@9
@@1:
        pop eax                ;export table
        sub esi,[ebx+eax+20h]  ;指向函数名地址表的RVA  获得其偏移量 以算出序号(一个函数名地址占4字节)
        shr esi,1              ;除以2(因为每个序号是占2字节的)
        add esi,[ebx+eax+24h]  ;addr of 序号 指向函数名序号表的RVA
        movzx esi,word ptr [ebx+esi]    ;只取前面的2个字节
        shl esi,2                       ;乘以4 (一个函数名地址占4字节)
        add esi,[ebx+eax+1ch]  ;addr of functions     指向导出函数地址表的RVA
        mov eax,[ebx+esi]
        add eax,ebx

gfa6:
        mov ebx,save_ebx    ;(还原ebx)

check_int3

        lea edx,forwardchain_dll[ebx]     ;自己定义的DLL组
        lea edi,forwardchain_handle[ebx]

        add eax,check2[ebx]

gfa70:
        mov esi,[edx]
        cmp esi,0
        je @@9                          ;DLL组都查完了就返回
        add esi,ebx                     ;重定位
        push eax
        push esi
        dec esi
        dec eax
gfa7:
        inc eax
        inc esi
        mov cl,[eax]
        cmp cl,'a'                        ;查看是否是字母
        jb @f
        cmp cl,'z'
        ja @f
        and cl,0dfh
@@:
        cmp cl,[esi]                      ;DLL组的DLL
        jne @f
        cmp cl,'.'
        je gfa75                          ;在内存中搜索指定的DLL字符串
        jmp gfa7
@@:
        pop esi
        pop eax
        add edx,4
        add edi,4
        jmp gfa70
gfa75:
       
        pop esi
        cmp dword ptr [edi],0
        jne @f
       
        push eax
        push esi
        call f_LoadLibrary[ebx]               ;获得DLL的基址
        mov [edi],eax
        pop eax
@@:
        inc eax
        add eax,check1[ebx]               
        mov p_funcname,eax
        mov eax,[edi]
        mov base,eax                           ;DLL的基址
        pop eax
        mov ebx,save_ebx
        jmp gfa1       

@@90:
        mov eax,0
@@9:
        ret
       
get_func_address        endp
2007-12-18 19:37
0
雪    币: 150
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
学习慢慢看!
2007-12-19 00:47
0
雪    币: 166
活跃值: (66)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
路漫漫其修远兮,吾将上下而求索。
期待楼主的完整版本,现在先补习汇编知识~
2007-12-19 23:44
0
游客
登录 | 注册 方可回帖
返回
//