最近人变懒了,专题一直没有更新,放一个小技巧出来耍耍。是原先那个随机密码的应用和PE Loader的应用都在这个例子中有体现。一般的壳是附加到应用程序上,这个是相反的想法,把应用程序反附加到壳上.然后随机加密(在一个范围内本例子中是 0 - 0100h).壳在启动后创建0100h个线程并利用线程号解密,当唯一正确的线程解密后利用PE LOADER把正确代码加载到争取的位置并修复引入表。这个样例的很大缺陷是只有被加壳的程序的ImageBase和壳的ImageBase相同是才可以加载争取。打包程序的代码没有考虑末尾数据有些不稳定。有兴趣的朋友再继续研究吧。
样例的代码有三部分

这部分为启动部分

代码:
;; ----------------------------------------
;; code segment
;; ----------------------------------------
.code
;; ----------------------------------------
;; function statement
;; ----------------------------------------
AntiKV proto szFilePath : LPSTR
CheckPacketSuccessRate proto szFilePath : LPSTR

;; AntiAV start
AntiKV_Start:
ifdef DEBUG_ANTIAV
  lea edi, g_szTarget
else
  ;; get command line
  invoke GetCommandLine              ; eax = command line
  mov edi, eax                  ; edi = command line
  mov al, ' '                    ; al = 020h
  mov ecx, MAX_PATH                ; ecx = MAX PATH length
  repnz scasb                    ; edi = target file path
endif
  ;; decrypt it
  invoke AntiKV, edi
  ;; exit
  invoke ExitProcess, 1

;; Anti KV
AntiKV proc uses ebx ecx edx edi esi, szFilePath : LPSTR
  ;; start check the packet success rate
  invoke CheckPacketSuccessRate, edi
  test eax, eax
  jz Error_AntiKV
  ;; rebuild new exe
  invoke ReBuildNewExe, szFilePath, 0100h
  lea eax, g_szSuccessPacket
  invoke crt_printf, eax
Exit_AntiKV:
  assume esi : nothing
  assume edi : nothing
  xor eax, eax
  ret
Error_AntiKV:
  lea eax, g_szCanotLoad
  invoke crt_printf, eax
  jmp Exit_AntiKV
AntiKV endp

CheckPacketSuccessRate proc uses ebx ecx edx edi esi, szFilePath : LPSTR
  LOCAL pPointer : LPVOID
  ;; init data
  mov pPointer, NULL
  ;; map file
  invoke MapFile2Mem, szFilePath, 0, addr pPointer, 1
  test eax, eax                ; eax = file memory size
  jz Error_CheckPacketSuccessRate
  mov esi, pPointer
  add esi, dword ptr [esi+03ch]        ; esi = PE header
  assume esi : ptr IMAGE_NT_HEADERS
                        ; eax = ImageBase
  mov eax, dword ptr [esi].OptionalHeader.ImageBase
  cmp eax, 00400000h              ; check ImageBase == lprotecter ImageBase
  jnz Error_CheckPacketSuccessRate
  invoke FreeMemory, addr pPointer
  mov eax, 1                  ; set return success value
Exit_CheckPacketSuccessRate:
  assume esi : nothing
  ret
Error_CheckPacketSuccessRate:
  cmp pPointer, NULL
  invoke FreeMemory, addr pPointer
  jz @F
  @@:
  xor eax, eax                ; eax = 0 failed value
  jmp Exit_CheckPacketSuccessRate
CheckPacketSuccessRate endp

end AntiKV_Start
这个部分为打包部分
代码:
;; ----------------------------------------
;; Name:ReBuildNewExe
;; Author:logic_yan@hotmail.com
;; Data:2009-3-3
;; Describe:pack orig program to lprotecter
;; data section
;; Arguments:
;; szFileName:file name
;; dwNewSectionSize:new section size
;; dwKeySeed:generate key seed
;; Return:
;; Success:1
;; Failed:0
;; ----------------------------------------
ReBuildNewExe proc uses ebx ecx edx esi edi, szFileName : LPSTR, dwKeySeed : DWORD
  LOCAL hFile : HANDLE
  LOCAL hMap : HANDLE
  LOCAL pLProtecter : LPVOID
  LOCAL pPackFile : LPVOID
  LOCAL dwPackFileSize : DWORD
  LOCAL dwLProtecterSize : DWORD
  LOCAL LProtecterFileInfo : FILEMAPINFO
  LOCAL pTailData : LPVOID
  LOCAL dwTailSize : DWORD
  
  ;; init data
  mov pLProtecter, NULL
  mov pPackFile, NULL
  mov pTailData, NULL
  ;; map pack file
  invoke MapFile2Mem, szFileName, 0, addr pPackFile, 1
  test eax, eax
  jz Error_ReBuildNewExe
  mov dwPackFileSize, eax              ; eax = target file size
  ;; get tail datas
  invoke GetFileTailData, pPackFile, NULL
  test eax, eax
  jz @F
  mov dwTailSize, eax                ; eax = tail data
  ;; allolc
  invoke AllocMemory, eax
  mov pTailData, eax
  ;; get tail data
  invoke GetFileTailData, pPackFile, eax
  @@:
  ;; delete file
  invoke DeleteFile, szFileName
  ;; copy a LProtect
  invoke CopyFile, offset g_szLProtect, szFileName, FALSE
  ;; get lportecter file info
  lea eax, LProtecterFileInfo            ; eax = lprotecter file info
  invoke GetFileMapInfoByFileName, szFileName, eax
  lea eax, LProtecterFileInfo
  assume eax : ptr FILEMAPINFO
  mov eax, dword ptr [eax].dwFileAlign      ; eax = lprotecter file align
  invoke PEAlign, dwPackFileSize, eax        ; eax = packfile file align size
  mov ecx, eax                  ; ecx = packfile file align size
  ;; map lprotect
  invoke MapFile2MemNotClose, szFileName, ecx, addr hFile, addr hMap, addr pLProtecter, 1
  test eax, eax
  jz Error_ReBuildNewExe
  mov dwLProtecterSize, eax            ; eax = lprotecter size
  
  ;; rebuild file
  mov esi, pLProtecter
  add esi, dword ptr [esi+03ch]          ; esi = lprotecter pe header
  assume esi : ptr IMAGE_NT_HEADERS
  mov edi, esi
                          ; edi = lprotecter data section table
  lea edi, [edi+(sizeof IMAGE_NT_HEADERS+sizeof IMAGE_SECTION_HEADER+sizeof IMAGE_SECTION_HEADER)]
  assume edi : ptr IMAGE_SECTION_HEADER
  ;; modify the data section
  ;mov ecx, dword ptr [edi].Misc.VirtualSize
  mov ecx, dwPackFileSize              ; ecx = new data section virtual size
  mov ebx, dword ptr [edi].Misc.VirtualSize    ; ebx = orig data section virtual size
  mov dword ptr [edi].Misc.VirtualSize, ecx
                          ; eax = lprotecter file alignment
  mov eax, dword ptr [esi].OptionalHeader.FileAlignment
  add ecx, ebx                  ; ecx = total virtual size for data section
  invoke PEAlign, ecx, eax            ; eax = new data section file alignment size
  mov dword ptr [edi].SizeOfRawData, eax
  ;; set pointer
  mov edi, dword ptr [edi].PointerToRawData
  add edi, pLProtecter              ; edi = to address
  mov esi, pPackFile                ; esi = from address
  mov ecx, dwPackFileSize              ; ecx = packet file size

  ;; get the crc32 value
  invoke CRC32, esi, ecx              ; eax = CRC32
  mov edx, pLProtecter              ; edx = to address
  add edx, 02h                  ; move to 2 bytes
  mov dword ptr [edx], eax            ; set CRC32 value
  
  ;; get key
  invoke GetRandom, dwKeySeed
  mov ebx, eax                  ; bx = key
;; show debug information
ifdef DEBUG_LCODEBUILDER
  pushad
  lea eax, g_szLCodeBuilderBuffer
  invoke crt_sprintf, eax, offset g_szKeyFormat, ebx
  lea eax, g_szLCodeBuilderBuffer
  invoke crt_printf, eax
  popad
endif
  ;; encode = (x xor bl) - bh
  @@:
  lodsb
  xor al, bl
  sub al, bh
  stosb
  loop @B
  
  ;; modify lprotecter size of image
  mov esi, pLProtecter
  add esi, dword ptr [esi+03ch]          ; esi = lprotecter pe header
  assume esi : ptr IMAGE_NT_HEADERS
  mov edi, esi
                          ; edi = lprotecter data section table
  lea edi, [edi+(sizeof IMAGE_NT_HEADERS+sizeof IMAGE_SECTION_HEADER+sizeof IMAGE_SECTION_HEADER)]
  assume edi : ptr IMAGE_SECTION_HEADER
  ;mov edx, pPackFile
  ;add edx, dword ptr [edx+03ch]          ; edx = pack file pe header
  ;assume edx : ptr IMAGE_NT_HEADERS
  mov ecx, dword ptr [edi].VirtualAddress
  add ecx, dword ptr [edi].Misc.VirtualSize    ; ecx = lprotecter virtual size
  ;mov ecx, dword ptr [esi].OptionalHeader.SizeOfImage
                          ; ecx = tow old size of image add
  ;add ecx, dword ptr [edx].OptionalHeader.SizeOfImage
                          ; eax = section alignment
  mov eax, dword ptr [esi].OptionalHeader.SectionAlignment
  invoke PEAlign, ecx, eax            ; eax = new size of image
  mov dword ptr [esi].OptionalHeader.SizeOfImage, eax
  
  ;; modify init data size
  ;mov eax, dword ptr [edi].SizeOfRawData      ; eax = data section raw size
  ;mov dword ptr [esi].OptionalHeader.SizeOfInitializedData, eax

  ;; free file memory
  invoke FreeFileMemory, addr hFile, addr hMap, addr pLProtecter

  ;; set tail data
  mov eax, dwLProtecterSize
  add eax, dwTailSize
  ;; count alignment
  lea ecx, LProtecterFileInfo
  assume ecx : ptr FILEMAPINFO
  mov ecx, dword ptr [ecx].dwFileAlign      ; eax = lprotecter file align
  invoke PEAlign, eax, ecx 
  ;; reopen lprotect and set tail data
  xchg eax, ecx
  invoke MapFile2MemNotClose, szFileName, ecx, addr hFile, addr hMap, addr pLProtecter, 1
  test eax, eax                  ; eax = lprotecter size
  jz @F
  ;; set tail data
  mov eax, pTailData
  invoke SetFileTailData, pLProtecter, eax, dwTailSize
  ;; free file map
  invoke FreeFileMemory, addr hFile, addr hMap, addr pLProtecter
  @@:
  ;; free tail data
  invoke FreeMemory, addr pTailData
  ;; free memory
  invoke FreeMemory, addr pPackFile
  mov eax, 1                    ; set return value
Exit_ReBuildNewExe:
  assume esi : nothing
  assume edi : nothing
  assume ecx : nothing
  ;assume edx : nothing
  ret
Error_ReBuildNewExe:
  cmp pPackFile, NULL                ; check pPointer alloc
  jz @F
  invoke FreeMemory, addr pPackFile
  @@:
  cmp pLProtecter, NULL
  jz @F
  invoke FreeFileMemory, addr hFile, addr hMap, addr pLProtecter
  @@:
  cmp pTailData, NULL
  jz @F
  invoke FreeMemory, addr pTailData
  @@:
  xor eax, eax                  ; eax = 0
  jmp Exit_ReBuildNewExe
ReBuildNewExe endp
最后这一部分为一个分开的EXE程序也就是壳的主体了
编译一下的代码生成的EXE放置到与打包器同一目录下,在用打包器对其他程序进程加壳。
代码:
.586
.model flat, stdcall
option casemap:none
;; ----------------------------------------
;; header file and lib file
;; ----------------------------------------
include windows.inc
include kernel32.inc

includelib kernel32.lib

include LProtecter.inc
;; ----------------------------------------
;; data segment
;; ----------------------------------------
.data
g_pChaosCode  db 0200h dup (?)
;; ----------------------------------------
;; code segment
;; ----------------------------------------
.code
LProtecter_Start:
  push ebp
  mov ebp, esp
  push 01000h
  mov ecx, offset End_Lord - offset Lord      ; ecx = lord size
  push ecx
  call PEAlign                  ; eax = lord alignment size
  sub esp, eax                  ; create runtime
  lea esi, Lord                  ; esi = lord pointer
  mov edi, esp                  ; edi = runtime space
  rep movsb                    ; copying
  ;; modify the memory attribute
  push eax
  lea ebx, [esp+04h]
  invoke VirtualProtect, ebx, eax, PAGE_EXECUTE_READWRITE, esp
  pop eax
  call esp                    ; run runtime
;; ---------------------------------------------------------------------------------
NeverRun:                      ; never to run...
  ;; some trash code
  invoke lstrcpy, edi, esi
  push ebx
  invoke CreateFile, eax, GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, esp
  pop ebx
  mov esp, ebp
  pop ebp
  retn 00h
LProtecterSign:
  db 01h,09h,08h,03h
;; Lord
Lord:
;; start here
;; the delta is here
delta:
  push ebp
  mov ebp, esp
  sub esp, 01000h                  ; create stack (0400h * 04h) store the thread handle
  mov esi, dword ptr [ebp+04h]          ; esi = never to run eip
                          ; esi = code first eip
  sub esi, offset NeverRun - offset LProtecter_Start
  ;; find MZ sign
    @@:
  dec esi
  xor si, si
  mov ax, word ptr [esi]              ; esi = kernel32.dll handle
  add ax, 0A5B3h                  ; cmp MZ
  jnz @B
  ;; cmp PE sign
  push esi
  add esi, dword ptr [esi+03ch]          ; esi = PE header
  mov ax, word ptr [esi]              ; eax = 05045h
  add ax, 0BAB0h                  ; cmp PE
  pop esi
  jnz @B
  ;; find import table
  mov edi, esi                  ; esi = base of image
  add edi, dword ptr [edi+03ch]          ; edi = PE header
  assume edi : ptr IMAGE_NT_HEADERS
                          ; edi = import table directory
  lea edi, [edi].OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT * sizeof IMAGE_DATA_DIRECTORY]
  mov edi, dword ptr [edi]            ; edi = import RVA
  add edi, esi                  ; edi = import VA
  assume edi : ptr IMAGE_IMPORT_DESCRIPTOR
  mov edi, dword ptr [edi].FirstThunk
  add edi, esi                  ; edi = API address list
  mov edi, dword ptr [edi]            ; edi = some api address
  ;; find kernel32.dll handle
    @@:
  dec edi
  xor di, di
  mov ax, word ptr [edi]              ; edi = kernel32.dll handle
  add ax, 0A5B3h                  ; cmp MZ
  jnz @B
  ;; cmp PE sign
  push edi
  add edi, dword ptr [edi+03ch]          ; edi = PE header
  mov ax, word ptr [edi]              ; ax = 05045h
  add ax, 0BAB0h                  ; cmp PE
  pop edi
  jnz @B
  ;; get api address
  lea eax, [ebp+08h]                ; eax = lord start address
                          ; eax = crc32 list
  add eax, offset ApiNameCrc32 - offset delta
  mov ebx, eax
  sub ebx, offset ApiNameCrc32 - offset ApiBase  ; ebx = api offset sotre list
  lea ecx, [ebp+08h]                ; ecx = delta address
  push ecx                    ; delta address
  push ebx                    ; api offset store pointer
  push eax                    ; crc32 value list
  push edi                    ; dll base
  call GetApiAddress
  ;; memory protect
  push ebx
  push esp                    ; old protect value
  push PAGE_EXECUTE_READWRITE            ; new protect value
  ;; get image base
  mov ecx, esi                  ; esi = lprotect start address
  add ecx, dword ptr [esi+03ch]
  assume ecx : ptr IMAGE_NT_HEADERS        ; PE header
                          ; ecx = image of base
  mov ecx, dword ptr [ecx].OptionalHeader.SizeOfImage
  push ecx                    ; size of image
  push esi                    ; address of start
  mov eax, 0
  xVirtualProtect = dword ptr $-04h
  call eax                    ; VirtualProtect
  pop ebx                      ; ebx = old protect value
  
  ;; create thread now
  xor edi, edi                  ; edi = 0
  lea ebx, [ebp-01000h]              ; ebx = thread handle list pointer
  ;; get evil thread stack size
  ;mov ecx, esi
  ;add ecx, dword ptr [ecx+03ch]          
                          ; ecx = evil section table
  ;add ecx, sizeof IMAGE_NT_HEADERS + \
  ;     sizeof IMAGE_SECTION_HEADER + \
  ;     sizeof IMAGE_SECTION_HEADER + \
  ;     sizeof IMAGE_SECTION_HEADER
  ;assume ecx : ptr IMAGE_SECTION_HEADER      ; edi = evil section table
  ;mov ecx, dword ptr [ecx].SizeOfRawData      ; ecx = evil section raw size
  ;imul ecx, ecx, 02h                ; ecx = evil thread stack size
  @@:
  push ecx
  push esp                    ; thread id
  push 0                      ; create flag
  push edi                    ; count
  lea eax, [ebp+08h]                ; eax = delta address
  add eax, offset EvilThread - offset delta
  push eax                    ; thread address
  ;push ecx                    ; stack size
  push 0                      ; stack size
  push NULL                    ; lpsecurity attribute
  mov eax, 0
  xCreateThread = dword ptr $-04h
  call eax                    ; CreateThread
  pop ecx                      ; ecx = thread id
  mov dword ptr [ebx], eax            ; eax = thread handle
  add ebx, 04h                  ; next thread handle store
  inc edi                      ; id count ++                      
  cmp edi, MAX_DECODE_THREAD            ; if edi == 1024 ?
  jb @B
  
  ;; wait for muti objects
  push INFINITE                  ; wait for run over
  push TRUE                    ; wait all thread
  lea ebx, [ebp-01000h]              ; ebx = thread handle list pointer
  push ebx
  push 0100h                    ; thread count
  mov eax, 0
  xWaitForMultipleObjects = dword ptr $-04h
  call eax                    ; WaitForMultipleObjects
  
  ;; clear the stack
  mov esp, ebp
  pop ebp
  ;; clear the ret eip
  pop eax
  ;; clear 2th
  mov esp, ebp
  pop ebp
  
  ;; get entry of address
  mov eax, esi
  add eax, dword ptr [esi+03ch]          ; eax = PE header
  assume eax : ptr IMAGE_NT_HEADERS
                          ; eax = etry RVA
  mov eax, dword ptr [eax].OptionalHeader.AddressOfEntryPoint
  add eax, esi                  ; eax = entry VA
  push eax
  retn 00h                    ; goto entry pointer
  
;; ----------------------------------------
;; Name:EvilThread
;; Author:logic_yan@hotmail.com
;; Data:2009-3-4
;; Describe:evil thread decode and load
;; orig program to memory
;; Arguments:
;; 1th argument:dekey
;; Return:none
;; ----------------------------------------
EvilThread:
  push ebp
  mov ebp, esp
  call edelta
edelta:
  pop esi
  sub esi, offset edelta - offset delta      ; esi = delta address
  mov esi, dword ptr [esi-04h]          ; esi = never run address
                          ; esi = lprotect start
  sub esi, offset NeverRun - offset LProtecter_Start
  ;; check the evil if exist or not
                          ; eax = lprotecter sign pointer
  lea eax, [esi+(offset LProtecterSign-offset LProtecter_Start)]
  mov eax, dword ptr [eax]            ; eax = lprotecter sign
  add eax, 0FCF7F6FFh                ; cmp sign
  jnz Exit_EvilThread
  ;; get image base
  sub esi, 01000h                  ; esi = MZ header
  ;; get the evil section
  mov edi, esi
  add edi, dword ptr [edi+03ch]
                          ; edi = evil section table
  add edi, sizeof IMAGE_NT_HEADERS + \
       sizeof IMAGE_SECTION_HEADER + \
       sizeof IMAGE_SECTION_HEADER
  assume edi : ptr IMAGE_SECTION_HEADER      ; edi = evil section table
  mov ecx, dword ptr [edi].Misc.VirtualSize    ; ecx = evil section virtual size
  mov edi, dword ptr [edi].VirtualAddress
  add edi, esi                  ; edi = evil section
  mov edx, ecx                  ; edx = evil section virtual size
  push 0100h                    ; alignment
  push edx
  call PEAlign
  mov edx, eax                  ; edx = alloc alignment size 
  ;sub esp, edx                  ; create evil stack
  ;mov ebx, esp                  ; ebx = evil buffer
  ;; start decrypt
  ;; alloc a memory
  push ecx                    ; save ecx
  @@:
  push PAGE_EXECUTE_READWRITE            ; memory attribute
  push MEM_COMMIT                  ; create flag
  push edx                    ; memory size
  push NULL
  mov eax, 0
  xVirtualAlloc = dword ptr $-04h
  call eax                    ; VirtualAlloc
  mov ebx, eax                  ; ebx = pointer
  test ebx, ebx
  jz @B
  ;; decode
  mov edx, dword ptr [ebp+08h]          ; edx = key
  ;; decode = (x xor dl) + dh
  pop ecx                      ; ecx = evil section virtual size
  push ebx
  push ecx
  @@:
  mov al, byte ptr [edi]              ; al = value
  xor al, dl
  add al, dh
  mov byte ptr [ebx], al              ; set to alloc memory
  inc ebx                      ; next to pointer
  inc edi                      ; next load pointer
  loop @B
  pop ecx                      ; ecx = evil section virtual size
  pop ebx                      ; ebx = evil memory
  
  ;; get crc32 value
  push ecx                    ; size
  push ebx                    ; pointer
  call CRC32
  lea edx, [esi+02h]                ; crc32 pointer
  sub eax, dword ptr [edx]            ; check crc32 value
  jnz Exit_EvilThread
ifdef DEBUG_LPROTECTER
  int 03h
endif
  ;; memory loader
  push ecx                    ; from memory size
  push ebx                    ; from memory
  push esi                    ; to memory
  call LoadFileToMemory
  
Exit_EvilThread:
  ;; free memory
  push MEM_RELEASE                ; free flag
  push 0                      ; size must be zero if release
  push ebx                    ; alloc address
  mov eax, 0
  xVirtualFree = dword ptr $-04h
  call eax                    ; VirtualFree
  mov esp, ebp
  pop ebp
  retn 04h
  
;; kernel32.dll API delta
ApiBase:
  dd offset xVirtualAlloc - offset delta
  dd offset xVirtualFree - offset delta   
  dd offset xVirtualProtect - offset delta
  dd offset xWaitForMultipleObjects - offset delta
  ;dd offset xCreateFileA - offset delta
  ;dd offset xWriteFile - offset delta
  ;dd offset xCloseHandle - offset delta  
  dd offset xCreateThread - offset delta
  dd offset xLoadLibraryA - offset delta
  ;dd offset xSleep - offset delta  
  dd offset xGetProcAddress - offset delta
  dd 0
  
;; kernel32.dll API name CRC32 list
ApiNameCrc32:
  dd 09CE0D4Ah                  ; VirtualAlloc
  dd 0CD53F5DDh                  ; VirtualFree
  dd 010066F2Fh                  ; VirtualProtect
  dd 0B98F54C4h                  ; WaitForMultipleObjects
  ;dd 0553B5C78h                  ; CreateFileA
  ;dd 0CCE95612h                  ; WriteFile
  ;dd 0B09315F4h                  ; CloseHandle  
  dd 0906A06B0h                  ; CreateThread
  dd 03FC1BD8Dh                  ; LoadLibraryA
  ;dd 0CEF2EDA8h                  ; Sleep
  dd 0C97C1FFFh                  ; GetProcAddress
  dd 0

;; ----------------------------------------
;; Name:LoadFileToMemory
;; Author:logic_yan@hotmail.com
;; Data:2009-3-4
;; Describe:load file to memory on section
;; alignment
;; Arguments:
;; 1th argument:to memory is size on 
;; section
;; 2th argument:from memory is size on file
;; 3th argument:from memory size
;; Return:none
;; ----------------------------------------
LoadFileToMemory:
  push ebp
  mov ebp, esp
  sub esp, 0100h                  ; create stack
  
  push ebx
  push ecx
  push edx
  push esi
  push edi
  
  ;; copy PE header
  mov ecx, dword ptr [ebp+0Ch]
  add ecx, dword ptr [ecx+03ch]
  add ecx, sizeof IMAGE_NT_HEADERS        ; ecx = 1th section table
  assume ecx : ptr IMAGE_SECTION_HEADER
  mov ecx, dword ptr [ecx].PointerToRawData    ; ecx = PE header size
  mov edi, dword ptr [ebp+08h]          ; edi = to memory start
  mov esi, dword ptr [ebp+0Ch]          ; esi = from memory start
  rep movsb                    ; copying
  
  mov edx, dword ptr [ebp+0Ch]          ; edx = from memory
  add edx, dword ptr [edx+03ch]          ; edx = PE header
  assume edx : ptr IMAGE_NT_HEADERS
                          ; ecx = number of sections
  movzx ecx, word ptr [edx].FileHeader.NumberOfSections
  mov ebx, dword ptr [ebp+0Ch]          
  add ebx, dword ptr [ebx+03ch]          ; edx = PE header
  add ebx, sizeof IMAGE_NT_HEADERS        ; ebx = section table
  assume ebx : ptr IMAGE_SECTION_HEADER
  
CopyEachSection_Loop:
  ;; write each section
  push ecx
  mov esi, dword ptr [ebp+0Ch]
  push dword ptr [ebx].VirtualAddress    ; esi = section file rva
  push esi
  call RVA2Offset              ; eax = section file offset
  add esi, eax              ; esi = section file address
  mov edi, dword ptr [ebp+08h]
  add edi, dword ptr [ebx].VirtualAddress      ; edi = section address
  mov ecx, dword ptr [ebx].Misc.VirtualSize    ; ecx = section virtual size
  cmp ecx, dword ptr [ebx].SizeOfRawData      ; virtual size VS raw size
  jbe @F                      ; if vsize <= rsize ecx = vsize 
  mov ecx, dword ptr [ebx].SizeOfRawData      ; else ecx = rsize
  @@:
  rep movsb
  pop ecx                      ; ecx = number of sections
  add ebx, sizeof IMAGE_SECTION_HEADER      ; next section table
  loop CopyEachSection_Loop
  
  ;; rebuild the import table
  push dword ptr [ebp+08h]            ; image base
  call BuildImportTable
  
  ;; exit
Exit_LoadFileToMemory:
  assume ebx : nothing
  assume ecx : nothing
  assume edx : nothing
  pop edi
  pop esi
  pop edx
  pop ecx
  pop ebx

  mov esp, ebp                  ; clean stack
  pop ebp
  retn 0Ch

;; ----------------------------------------
;; Name:RVA2Offset
;; Author:logic_yan@hotmail.com
;; Data:2009-3-4
;; Describe:RVA to offset
;; Arguments:
;; 1th argument:file map
;; 2th argument:RVA
;; Return:
;; Success:offset
;; Failed:0
;; ----------------------------------------
RVA2Offset:
  push ebp
  mov ebp, esp                  ; create stack
  
  push ebx
  push ecx
  push edx
  push esi
  push edi
  
    mov esi, dword ptr [ebp+08h]           ; esi = file map base 
    add esi, dword ptr [esi+03ch]          ; esi = PE header 
    assume esi : ptr IMAGE_NT_HEADERS 
    mov edi, dword ptr [ebp+0Ch]           ; edi == RVA 
    mov edx, esi                  ; edx = PE header
    add edx, sizeof IMAGE_NT_HEADERS        ; edx = 1th section table 
    movzx ecx, [esi].FileHeader.NumberOfSections  ; ecx = number of sections
    assume edx : ptr IMAGE_SECTION_HEADER 
RVA2Offset_Loop:
    cmp edi, dword ptr [edx].VirtualAddress      ; if ecx >= [edx].VirtualAddress
    jb Continue_RVA2Offset_Loop
    mov eax, dword ptr [edx].VirtualAddress      ; eax = current section RVA           
    add eax, [edx].SizeOfRawData           ; eax = current section end RVA
    cmp edi, eax                  ; if edi < eax, The address is in this section
    jae Continue_RVA2Offset_Loop
    mov eax, dword ptr [edx].VirtualAddress      ; eax = current section RVA
    sub edi, eax                  ; edi = RVA offset
     mov eax, dword ptr [edx].PointerToRawData    ; eax = section file offset 
    add eax, edi                   ; eax = file offset 
  jmp RVA2OffsetExit                ; just exit
Continue_RVA2Offset_Loop:
    add edx, sizeof IMAGE_SECTION_HEADER      ; edx = next section table
  loop RVA2Offset_Loop
    xor eax, eax
RVA2OffsetExit:
  assume esi : nothing
  assume edx : nothing
  
  pop edi
  pop esi
  pop edx
  pop ecx
  pop ebx
  
  mov esp, ebp
  pop ebp                      ; clean stack
  retn 08h
;; ----------------------------------------
;; Name:PEAlign
;; Author:logic_yan@hotmail.com
;; Data:2009-3-4
;; Describe:number to align
;; Algorithms:
;; $1 = dwTarNum / dwAlignTo
;; if remain != 0
;; $r = $1 + 1 * dwAlignTo
;; return $r
;; Arguments:
;; 1th argument:target number
;; 2th argument:alignment
;; Return:
;; Success:alignment number
;; Failed:0
;; ----------------------------------------
PEAlign:
  push ebp
  mov ebp, esp                  ; create stack
  push ecx
  push edx

    mov ecx, dword ptr [ebp+0Ch]          ; ecx = align to
    mov eax, dword ptr [ebp+08h]          ; eax = target number
    xor edx, edx                  ; edx = 0
    div ecx                      ; edx = edx / ecx
    cmp edx, 0                    ; cmp edx, 0
    jz AlreadyAligned
    inc eax                      ; eax = eax + 1
AlreadyAligned:
    mul ecx                      ; eax = eax * ecx
    ;; exit
    pop edx
    pop ecx     
    
    mov esp, ebp                  ; clear stack
    pop ebp
    retn 08h

;; ----------------------------------------
;; Name:BuildImportTable
;; Author:logic_yan@hotmail.com
;; Data:2009-3-7
;; Describe:build a new import table
;; Arguments:
;; 1th argument:file map pointer
;; Return:
;; Success:import table in file offest
;; Failed:0
;; ----------------------------------------
BuildImportTable:
  push ebp
  mov ebp, esp                  ; create stack
  
  push ebx
  push ecx
  push edx
  push esi
  push edi
  
  mov esi, dword ptr [ebp+08h]          ; esi = file map base
  mov edi, esi
  add edi, dword ptr [esi+03ch]          ; edi = PE loader
  assume edi : ptr IMAGE_NT_HEADERS
  ;; check Import Table
                          ; edi = import table directory
  lea edi, [edi].OptionalHeader.DataDirectory[sizeof IMAGE_DATA_DIRECTORY * IMAGE_DIRECTORY_ENTRY_IMPORT]
  assume edi : ptr IMAGE_DATA_DIRECTORY
  mov eax, dword ptr [edi].VirtualAddress      ; eax = import table RVA
  test eax, eax
  jz Exit_BuildImportTable
  ;; exist Import Table
  ;invoke RVA2Offset, pAlloc, eax
  add eax, esi                  ; eax = import table VA
  xchg eax, edi                  ; edi = import table VA
  assume edi : ptr IMAGE_IMPORT_DESCRIPTOR
  ;; import descriptor loop
ImportDescriptor_Loop:
  ;; load dll
  mov eax, dword ptr [edi].Name1          ; eax = dll name
  ;invoke RVA2Offset, pAlloc, eax
  add eax, esi                  ; esi = file map base
  push eax                    ; eax = dll name
  mov eax, 0
  xLoadLibraryA = dword ptr $-04h
  call eax                    ; LoadLibraryA
  mov ebx, eax
  ;; check use OriginalFirstThunk or FirstThunk
;  mov edx, dword ptr [edi].OriginalFirstThunk
;  test edx, edx
;  jnz UseOrignalFirstThunk
  mov edx, dword ptr [edi].FirstThunk        ; edx = firstthunk
;UseOrignalFirstThunk:
  add edx, esi                  ; edx = api store pointer
  mov eax, dword ptr [edx]            ; eax = api name THUNK_DATA
  ;; get api address in one dll
GetApiAddress_Loop:
  ;; ebx -> dll handler
  ;invoke RVA2Offset, pAlloc, eax
  test eax, IMAGE_ORDINAL_FLAG32          ; it's import by index
  jz GetApiByName
  and eax, 0FFFFh                  ; eax = index
  jmp GetApiNow
GetApiByName:
  add eax, esi                  ; eax = api name pointer VA
  assume eax : ptr IMAGE_IMPORT_BY_NAME
  lea eax, [eax].Name1              ; eax = api name
  ;; get api address
GetApiNow:
  push ecx
  push edx
  push eax                    ; eax = api name
  push ebx                    ; ebx = dll handle
  mov eax, 0
  xGetProcAddress = dword ptr $-04h
  call eax                    ; GetProcAddress
  pop edx                      ; edx = api store pointer
  pop ecx
  ;; set api address
  mov dword ptr [edx], eax            ; set address
  ;; next api
  add edx, 04h                  ; edx = next api store address
  mov eax, dword ptr [edx]            ; eax = api name RVA
  test eax, eax
  jnz GetApiAddress_Loop
  ;; next dll
  add edi, sizeof IMAGE_IMPORT_DESCRIPTOR      ; edi = next dll
  mov eax, dword ptr [edi].Name1          ; eax = dll name RVA
  test eax, eax                  ; if eax == 0 then exit
  jnz ImportDescriptor_Loop
  
Exit_BuildImportTable:
  assume eax : nothing
  assume esi : nothing
  assume edi : nothing
  
  pop edi
  pop esi
  pop edx
  pop ecx
  pop ebx
  
  mov esp, ebp
  pop ebp                      ; clean stack
  retn 04h

;; ----------------------------------------
;; Name:SearchExport
;; Author:logic_yan@hotmail.com
;; Data:2009-2-20
;; Describe:get api address by dll export
;; Arguments:
;; 1th argument:dll base address
;; 2th argument:target crc32 value
;; Return:
;; Success:addresss api
;; Failed:0
;; ----------------------------------------
SearchExport:
  push ebp                  ; create stack frame
  mov ebp, esp
  ; save all registry
  push ebx
  push ecx
  push edx
  push esi
  push edi
  
  mov esi, dword ptr [ebp+08h]        ; esi = dll base address
  ;; find export table
  add esi, dword ptr [esi+03ch]        ; esi = PE header
  assume esi : ptr IMAGE_NT_HEADERS
                        ; edi = export table directory
  lea edi, [esi].OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT * sizeof IMAGE_DATA_DIRECTORY]
  mov edi, dword ptr [edi]          ; edi = export RVA
  test edi, edi                ; cmp edi, 0
  jz Exit_SearchExport
  add edi, dword ptr [ebp+08h]        ; edi = export VA
  assume edi : ptr IMAGE_EXPORT_DIRECTORY
  mov esi, dword ptr [edi].AddressOfNames    ; esi = address of names list offset
  add esi, dword ptr [ebp+08h]        ; esi = address of names list
  mov ecx, dword ptr [edi].NumberOfNames    ; ecx = number of names
  xor edx, edx                ; edx = 0
  ;; search loop
  cld
SearchExport_Loop:
  lodsd                    ; eax = api name RVA
  add eax, dword ptr [ebp+08h]        ; eax = api name VA
  ;; work out api name length
  push esi                  ; save esi
  push eax                  ; save eax
  xor ebx, ebx                ; ebx = 0
  mov esi, eax                ; esi = api name VA
  ;; count string length
  @@:
  lodsb                    ; al = the char in api name
  cmp al, 0                  ; if al == 0 then go end
  jz @F
  inc ebx                    ; ebx = count of api name
  jmp @B
  @@:                      ; end count api name length loop
  pop eax                    ; eax = api name VA
  pop esi                    ; esi = PE header
  ;; crc32 eax
  push ebx                  ; ebx = the length of api name
  push eax                  ; eax = api name VA
  call CRC32                  ; eax = CRC32 value
  ;; check target CRC32 value
  cmp eax, dword ptr [ebp+0Ch]        ; cmping...
  jz @F                    ; if == then go exit
  inc edx                    ; edx = index of name
  loop SearchExport_Loop
  @@:                      ; end of search loop
  test ecx, ecx                ; cmp ecx, 0
  jz @F                    ; go to end
  ;; get api address
                        ; esi = address of name ordinals offset
  mov esi, dword ptr [edi].AddressOfNameOrdinals
  add esi, dword ptr [ebp+08h]        ; esi = address of name ordinals address
  imul edx, edx, 02h              ; edx = offset in address of name ordinals
  movzx ebx, word ptr [esi+edx]        ; ebx = index of api
  imul ebx, ebx, 04h              ; ebx = offset of api address
  mov edi, dword ptr [edi].AddressOfFunctions  ; edi = address of functions RVA
  add edi, dword ptr [ebp+08h]        ; edi = address of functions VA
  add edi, ebx                ; edi = current address of function VA
  mov ecx, dword ptr [edi]          ; ecx = api address RVA
  add ecx, dword ptr [ebp+08h]        ; ecx = api address
  @@:                      ; exit SearchExport
  mov eax, ecx                ; eax = api address
  Exit_SearchExport:
  ;; load registry
  pop edi
  pop esi
  pop edx
  pop ecx
  pop ebx
  assume esi : nothing
  assume edi : nothing
  mov esp, ebp                ; clean stack
  pop ebp
  retn 08h
  
;; ----------------------------------------
;; Name:CRC32
;; Author:logic_yan@hotmail.com
;; Data:2009-2-20
;; Describe:work out CRC32 value
;; Arguments:
;; 1th:string ptr
;; 2th:string ptr count
;; Return:
;; Success:CRC32 value
;; Failed:0
;; ----------------------------------------
CRC32:
    push ebp                    ; create stack
    mov ebp, esp
    sub esp, 0400h
     ;; savel registry
    push ebx
   push ecx
   push edx
   push esi
   push edi
    ;; dynamic create CRC32 table
    xor ecx, ecx                  ; ecx = 0
    lea esi, [ebp-0400h]              ; esi = crc32 table pointer
    CreateCRC32Tbl_Loop1:
    cmp ecx, 0100h
    jz EndCreateCRC32Tbl_Loop1
    mov edx, ecx
    push ecx
    mov ecx, 08h
    CreateCRC32Tbl_Loop2:
    test edx, 01h
    jz CreateCRC32Tbl_Loop2_Tmp1
    shr edx, 01h
    xor edx, 0EDB88320h
    jmp CreateCRC32Tbl_Loop2_Tmp2
    CreateCRC32Tbl_Loop2_Tmp1:
    shr edx, 01h
    CreateCRC32Tbl_Loop2_Tmp2:
    dec ecx
    jnz CreateCRC32Tbl_Loop2
    pop ecx
    mov dword ptr [esi+ecx*04h], edx
    inc ecx
   jmp CreateCRC32Tbl_Loop1
    EndCreateCRC32Tbl_Loop1:
    
    ;; calcu CRC32 value
    mov edx, 0FFFFFFFFh                ; edx = 0FFFFFFFFh
    mov ecx, dword ptr [ebp+0Ch]          ; ecx = string length
    mov edi, dword ptr [ebp+08h]          ; edi = string ptr
    @@:
    mov al, byte ptr [edi]              ; al = char of string
    movzx eax, al
    xor eax, edx
    and eax, 0FFh
    mov eax, dword ptr [esi+eax*04h]
    shr edx, 08h
    and edx, 00FFFFFFh
    xor edx, eax
    inc edi
    dec ecx
    jnz @B
    xor edx, 0FFFFFFFFh
    mov eax, edx
Exit_EndCRC32:   
    pop edi
    pop esi
    pop edx
    pop ecx
    pop ebx
    mov esp, ebp                  ; clean stack
    pop ebp
    retn 08h
    
;; ----------------------------------------
;; Name:GetApiAddress
;; Author:logic_yan@hotmail.com
;; Data:2009-3-4
;; Describe:get api address
;; Arguments:
;; 1th:dll base
;; 2th:crc32 value list pointer
;; 3th:api offset store list pointer
;; 4th:image of base
;; Return:none
;; ----------------------------------------
GetApiAddress:
  push ebp
  mov ebp, esp                  ; create stack
  
  push esi
  push edi
  push edx
  push ebx
  push ecx
  
  mov edx, dword ptr [ebp+08h]          ; edx = dll base
  mov esi, dword ptr [ebp+0Ch]          ; esi = crc32 value list
  mov edi, dword ptr [ebp+010h]          ; edi = api offset store list pointer
  mov ecx, dword ptr [ebp+014h]          ; ecx = base address
  lodsd                      ; eax = CRC32 value
ListCRC32List_Loop:
  push eax
  push edx
  call SearchExport                ; search dll export table
  test eax, eax
  jz @F
  mov ebx, dword ptr [edi]            ; ebx = api delta
  add ebx, ecx                  ; ebx = api store pinter address
  mov dword ptr [ebx], eax            ; set api address
  @@:
  add edi, 04h                  ; edi = next store address
  lodsd                      ; eax = CRC32 value
  test eax, eax
  jnz ListCRC32List_Loop
  
  ;; exit
  pop ecx
  pop ebx
  pop edx
  pop edi
  pop esi
  mov esp, ebp                  ; clean stack
  pop ebp
  retn 010h
End_Lord:

end LProtecter_Start
有兴趣的朋友可以搞的稳定些。。。