一个最简单的壳的源代码[TASM] by 小零

 
代码
.386
.model flat,stdcall
locals

extrn ExitProcess:PROC

.data
   db 0
   
.code
   start:
   IMAGE_DOS_SIGNATURE equ 5A4Dh            ;ZM
   IMAGE_NT_SIGNATURE equ 4550h            ;EP
   ;nop                                    ;代码开头当然你也可以设置一些别的东西
db '$Packer_Begin$'                            ;ShellCode技术~~方便提取代码
   BeginTempStub:
  ; these fields are if we load at right base (0x00400000)
  ; and the section is assumed to start at VA 4000h since
  ; basic masm project does that
  ImportDescStart:
  dd 0 ; Orig First Thunk
  dd 0 ; no
  dd 0 ; no
  ddRvaName dd 1234567h ; dd 4028h (name of dll (rva))
  ddFirstThunk dd 896969h ; dd 4035h (first thunk (rva))
  ImportDescEnd:

  db 20 dup(0) ; end of Import Desc
 
  szUser32 db "KERNEL32.DLL",0
 
  dwFirstThunk dd 0 ; 403Dh ; rva to beep
  dwSecondThunk dd 0
  dd 0
 
  wImportHint dw 0
  szApiGetModule db "LoadLibraryA",0
 
  wImportHinted dw 0
  szApiGetProc db "GetProcAddress",0
 
  nop
  nop
  nop
  nop
  nop
  nop
  nop
  nop
  nop
 
  call GetDelta                    ;PE Virus最经典的技术..代码自定位
GetDelta:
  pop ebp                            ;ebp中保存当前代码段的地址
  sub ebp, offset GetDelta        ;ebp-GetDalta的数据偏移~ebp中就保存了当前代码段的地址
 
  jmp OverData                    ;跳转到初始化数据结束的地方
 
BeginData:
  szKernel db "KERNEL32.DLL",0    ;k32的字符串信息
  dwBeginVirtAddr dd 0            ;虚拟地址开始长度
  dwTotalSize dd 0 ; div by 4        ;加密的长度
  dwCurrentKey dd 0                ;加密密钥
  dwOldOEP dd 0                    ;保存老的OEP地址
  dwOrigDesc dd 0
  dwBaseOfDLL dd 0                ;DLL的基址-主要是保存k32的基址
 
  ddCurrentBase dd 0                ;一个临时变量存储基址用的
 
  szIsDebuggerPresent db "IsDebuggerPresent",0;这个函数都知道吧
  _IsDebuggerPresent dd 0                        ;函数地址存储位置
 
  szExitProcess db "ExitProcess",0            ;呵呵~
  _ExitProcess dd 0
 
  szCreateFileA db "CreateFileA",0            ;^_^~
  _CreateFileA dd 0
 
  szSleep db "Sleep",0                        ;吼吼
  _Sleep dd 0
 
  szNtIce db "/.NTICE",0
  szRegIce db "/.SICE",0                    ;SoftICE的后门指令判断SoftICE是否存在
 
  db 090h
  db 0CCh
  ; these are filled in
  ddCheckAppDebug dd 0
  ddCheckSoftice dd 0
  ddDelayTimeWait dd 0                
 
OverData:
  ; get KERNEL32 base
  lea ebx, [ebp+szKernel]                    ;首先将szKernel的数据存入ebx            
  push ebx                                
  call dword ptr [ebp+dwFirstThunk]        ;dwFirstThunk-中保存的是LoadLibraryA函数地址
  mov dword ptr [ebp+dwBaseOfDLL], eax
  ; get ExitProcess API
  lea ebx, [ebp+szExitProcess]            ;将ExitProcess字符串保存在ebx中
  push ebx
  push eax                                ;其实此时eax中保存的也是k32的基址
  call dword ptr [ebp+dwSecondThunk]        ;dwSecondThunk-中保存的是GetProcAddress地址
  mov dword ptr [ebp+_ExitProcess], eax    ;将获取的地址存入_ExitProcess变量中
  ; get CreateFileA API
  lea ebx, [ebp+szCreateFileA]            ;开始获取CreateFileA函数地址
  push ebx                                
  push dword ptr [ebp+dwBaseOfDLL]        ;eax中保存着调用完API后的返回值
  call dword ptr [ebp+dwSecondThunk]        ;开始调用GetProcAddress获取地址
  mov dword ptr [ebp+_CreateFileA], eax    ;保存CreateFileA函数地址
  ; get Sleep API
  lea ebx, [ebp+szSleep]                    ;获取Sleep函数
  push ebx                                
  push dword ptr [ebp+dwBaseOfDLL]        ;压入k32基址
  call dword ptr [ebp+dwSecondThunk]        ;开始调用GetProcAddress获取地址Sleep地址
  mov dword ptr [ebp+_Sleep], eax            ;保存地址
 
  cmp dword ptr [ebp+ddCheckAppDebug], 0    ;判断是否要检测调试器
  jz NoDebugger                            ;如果不需要就直接跳转过去
  ; check for Application Debugger        ;下面是检测是否有调试器
  lea ebx, [ebp+szIsDebuggerPresent]        ;老问题~压入IsDebuggerPresent字符串
  push ebx                                
  push dword ptr [ebp+dwBaseOfDLL]        
  call dword ptr [ebp+dwSecondThunk]        ;获取IsDebuggerPresent函数地址
  mov dword ptr [ebp+_IsDebuggerPresent],eax;保存函数地址
  call eax                                ;此时eax中保存的是IsDebuggerPresent的地址
  or eax, eax                                ;判断是否有调试器
  jz NoDebugger                            ;如果没有就跳转到NoDebugger
  push 0                                    
  call dword ptr [ebp+_ExitProcess]        ;如果有就退出进程
 
NoDebugger:                                    
  cmp dword ptr [ebp+ddCheckSoftice], 0    ;判断是否要要检测SoftICE
  jz JmpOverSoftDbg                        ;不需要就跳转到JmpOverSoftDbg
  push 0
   push 0
   push 3
   push 0
   push 1
   push 080000000h or 040000000h
   lea esi, [ebp+szNtIce]
   push esi
   call dword ptr [ebp+_CreateFileA]        ;使用SoftICE给自己留的一个内核后门检测
   inc eax                                    ;至于如何判断出来的~你去查查看雪论坛精华贴就知道了
   jnz SoftDebug                            ;检测到即跳转到~SoftDebug
  dec eax                                    
  push 0
   push 0
   push 3
   push 0
   push 1
   push 080000000h or 040000000h
   lea esi, [ebp+szRegIce]
   push esi
   call dword ptr [ebp+_CreateFileA]        ;开始检测第二个后门指令
   inc eax                                    
   jz JmpOverSoftDbg                        ;没有检测到就跳转到JmpOverSoftDbg处
  dec eax
 
SoftDebug:
  push 0
  call dword ptr [ebp+_ExitProcess]        ;如果检测到有SotfICE就退出进程
                                         ;PS:太温柔了吧~应该是ExitWindowEx嘿嘿~~
 
JmpOverSoftDbg:
  call GetBaseOfPE                        ;检测完毕以后就开始获取PE基址
 
GetBaseOfPE:                                ;edx中保存着PE Base
  pop edx
 
LoopToFindMZ:
  cmp word ptr [edx], IMAGE_DOS_SIGNATURE    ;循环查找MZ标记函数
  jz LoopToFindNT                            ;跳转到查找PE头部的地方
  dec edx                                    ;edx-1
  jmp LoopToFindMZ
 
LoopToFindNT:
  movzx ecx, word ptr [edx+3ch]            
  add ecx, edx
  cmp dword ptr [ecx], IMAGE_NT_SIGNATURE    ;判断是否是PE标记
  jz FinishLooping
  jmp LoopToFindMZ
 
FinishLooping:
  mov dword ptr [ebp+ddCurrentBase], edx    ;当前地址
  mov esi, edx
  add esi, dword ptr [ebp+dwBeginVirtAddr];程序开始段的虚拟地址
  mov edi, dword ptr [ebp+dwCurrentKey]    ;将加密密钥保存到edi
  mov ecx, dword ptr [ebp+dwTotalSize]    ;将需要解密的总字节保存到ecx中
 
LoopXorLoop:
  xor dword ptr [esi], edi                ;开始异或解密
  add esi, 4                                ;地址+4
  loop LoopXorLoop
  ; time to patch the IAT
  mov esi, dword ptr [ebp+dwOrigDesc]        ;
  add esi, dword ptr [ebp+ddCurrentBase]    ;
  sub esi, 20                                ;
 
BeginPatchIAT:                                ;解密代码完毕开始人工填写IAT
  add esi, 20                                ;esi+20
  cmp dword ptr [esi], 0                    ;IAT是否更新完毕~完毕的话就跳转到JmpOutOf
  jz JmpOutOf                                ;
  mov ebx, dword ptr [esi+12]
  add ebx, dword ptr [ebp+ddCurrentBase]
  push esi
  push ebx
  call dword ptr [ebp+dwFirstThunk]
  pop esi
  mov dword ptr [ebp+dwBaseOfDLL], eax
 
BeginPatch:                                    ;开始填写导入表
  mov edi, dword ptr [esi+16]
  add edi, dword ptr [ebp+ddCurrentBase]
 
BeginFoo:                                    ;开始IAT
  cmp dword ptr [edi], 0
  jz BeginPatchIAT
  mov ebx, dword ptr [edi]
  add ebx, dword ptr [ebp+ddCurrentBase]
  add ebx, 2 ; fuck u word!!
  push edi
  push ebx
  push dword ptr [ebp+dwBaseOfDLL]
  call dword ptr [ebp+dwSecondThunk]
  pop edi
  mov dword ptr [edi], eax
  add edi, 4
  jmp BeginFoo
 
JmpOutOf:                                    ;填写导入表完毕
  ; use delay load feature
  mov ebx, dword ptr [ebp+ddDelayTimeWait]
  push ebx
  call dword ptr [ebp+_Sleep]
  ; data unencrypted so jmp back to orig host.
  mov edx, dword ptr [ebp+ddCurrentBase]
  add edx, dword ptr [ebp+dwOldOEP]        ;计算老的OEP
  jmp edx                                    ;跳转到OEP
  int 3h                                    ;这句没用的~放着吓唬别人的
  db '$Packer_End$'                        ;代码结束标记方便提取PackStub代码
 

  FinishTempStub:
   
   end start

<script type="text/javaScript">function doZoom(size){ document.getElementById('zoom').style.fontSize=size+'px'}</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值