<目录>
1.废话一堆
2.覆盖原先的ImageBase
3.基址重定位并完全在内存中运行
4.又是废话一堆
<正文>Loading...
1.废话一堆
抱怨一下,刚才发了N长时间的帖子点了一下预览HTTP链接超时...文章全完了。现在重新开始编辑。
这里我实现了两个PE LOADER.一种是覆盖原先的ImageBase,一种是基址重定位并完全在内存中运行
前者的稳定性来说要比后者要强的多。后者的技术可以让壳出现很多的花样。
2.覆盖原先的ImageBase
覆盖原先的ImageBase式的PE LOADER的原理很简单,就是讲处于在以文件对齐形式的被保护程序复写到
原来的ImageBase按照节对齐。最终修复引入表就可以了。这里有一个技巧上的问题。如果将壳感染到
被保护的程序中,那么这种PE LOADER的用处是不大的。本身就处于正确的ImageBase内。直接加解密就
好了。当时换个想法,如果把被保护的程序感染到壳上,那么这个技巧就相当有用了。可以让壳多余
出一个数据节,然后讲被保护的程序加载到原先ImageBase上。这里有一个问题就是壳的ImageBase要和被
保护程序的ImageBase一致至少99.99%的程序的基地址都是一样的。这种LOADER的稳定性很高的。好处就是
可以用C,Delphi等写壳身。用汇编花很长时间写出来的东西,至少用高级语言会写的很方便。并且你可以
让你的壳看起来像一个3D游戏而不是一个壳。让破解者就累死到这里。PS:让杀毒软件的虚拟机也累到这里。
先来段Pack的代码吧。首先我们自己做一个壳,在这里壳里实现自修改,反破解,反调试等等。如果你够BT的话
可以在这里实现另外一个程序。累死丫的。 等垃圾运行完毕后。将被保护的程序读入到争取的ImageBase后
执行。
这里先SHOW一段打包代码.讲被保护的程序添加的壳当中。壳只有3个段1代码段,2引入表,3数据段,我们把
被保护的程序打包到数据段中,这个段是没有用处的。就是为了打包被保护的程序
;; ----------------------------------------
;; 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
;; init data
mov pLProtecter, NULL
mov pPackFile, NULL
;; map pack file
invoke MapFile2Mem, szFileName, 0, addr pPackFile, 1
test eax, eax
jz Error_ReBuildNewExe
mov dwPackFileSize, eax ; eax = target file size
;; 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 memory
invoke FreeMemory, addr pPackFile
;; free file memory
invoke FreeFileMemory, addr hFile, addr hMap, addr pLProtecter
mov eax, 1 ; set return value
Exit_ReBuildNewExe:
assume esi : nothing
assume edi : 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
@@:
xor eax, eax ; eax = 0
jmp Exit_ReBuildNewExe
ReBuildNewExe endp
;; ----------------------------------------
;; 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
LPeLoader proc uses ebx ecx edx esi edi, pMem : LPVOID
LOCAL pAlloc : LPVOID
LOCAL dwAllocSize : DWORD
mov edx, pMem
add edx, dword ptr [edx+03ch]
assume edx : ptr IMAGE_NT_HEADERS
mov eax, dword ptr [edx].OptionalHeader.SizeOfImage
mov dwAllocSize, eax
;; alloc memory
invoke AllocMemory, eax
test eax, eax
jz Error_LPeLoader
mov pAlloc, eax
;; map between dos header to 1th section datas
mov ebx, edx
add ebx, sizeof IMAGE_NT_HEADERS
assume ebx : ptr IMAGE_SECTION_HEADER
mov ecx, dword ptr [ebx].PointerToRawData
mov edi, pAlloc
mov esi, pMem
cld
rep movsb
;; map section on section alignment
movzx ecx, word ptr [edx].FileHeader.NumberOfSections
MapEachSection_Loop:
;; ecx -> number of sections
;; ebx -> section table
;; edi -> alloc memory pointer
;; edx -> pe header
;; esi -> file memory pointer
;; write each section
push ecx
mov edi, pAlloc
add edi, dword ptr [ebx].VirtualAddress
mov ecx, dword ptr [ebx].SizeOfRawData
rep movsb
pop ecx
;; mov to next section
add ebx, sizeof IMAGE_SECTION_HEADER
mov esi, dword ptr [ebx].PointerToRawData
add esi, pMem
loop MapEachSection_Loop
;; build import table
invoke BuildImportTable, pAlloc
;; build relocation table
invoke BuildRelocation, pAlloc
;; fix absolute address
invoke BaseRelocater, pMem, pAlloc
;; make runtime
invoke MakeOwnRunTime, pAlloc
;; handle tls
invoke HandleTLS, pAlloc
;; exit now
mov eax, pAlloc
Exit_LPeLoader:
assume ebx : nothing
assume edx : nothing
ret
Error_LPeLoader:
xor eax, eax
jmp Exit_LPeLoader
LPeLoader endp
BuildRelocation proc uses ebx ecx edx esi edi, pAlloc : LPVOID
LOCAL dwType : DWORD
LOCAL dwOffset : DWORD
;; start
mov esi, pAlloc
add esi, dword ptr [esi+03ch]
assume esi : ptr IMAGE_NT_HEADERS
;; exist base relocation
lea edi, [esi].OptionalHeader.DataDirectory[sizeof IMAGE_DATA_DIRECTORY * IMAGE_DIRECTORY_ENTRY_BASERELOC]
assume edi : ptr IMAGE_DATA_DIRECTORY
mov eax, dword ptr [edi].VirtualAddress
test eax, eax
jz Exit_BuildRelocation
add eax, pAlloc
xchg eax, edi
assume edi : ptr IMAGE_BASE_RELOCATION
;; delta?
mov edx, pAlloc
mov eax, dword ptr [esi].OptionalHeader.ImageBase
cmp eax, edx
jz Exit_BuildRelocation
sub edx, eax ; edx -> delta
BuildRelocation_Loop:
;; esi -> TypeOffset
;; edi -> IMAGE_BASE_RELOCATION
;; ecx -> count
;; edx -> delta
;; ebx -> base memory
mov ebx, dword ptr [edi].VirtualAddress
add ebx, pAlloc
;; esi -> TypeOffset
mov esi, edi
add esi, sizeof IMAGE_BASE_RELOCATION
mov ecx, dword ptr [edi].SizeOfBlock
sub ecx, sizeof IMAGE_BASE_RELOCATION
shr ecx, 1 ; ecx -> count
push ecx
BuildRelocation_Loop_Inside:
movzx eax, word ptr [esi]
mov dwOffset, eax
and dwOffset, 0FFFh
mov dwType, eax
shr dwType, 0Ch
cmp dwType, IMAGE_REL_BASED_HIGHLOW ; IMAGE_REL_BASED_HIGHLOW = 3
jnz Continue_BuildRelocation_Loop_Inside
;; relocate now
mov eax, ebx
add eax, dwOffset
add dword ptr [eax], edx
Continue_BuildRelocation_Loop_Inside:
loop BuildRelocation_Loop_Inside
pop ecx
imul ecx, ecx, 02h
add esi, ecx
mov edi, esi
mov eax, dword ptr [edi].VirtualAddress
test eax, eax
jnz BuildRelocation_Loop
Exit_BuildRelocation:
assume esi : nothing
assume edi : nothing
ret
BuildRelocation endp
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!