最近人变懒了,专题一直没有更新,放一个小技巧出来耍耍。是原先那个随机密码的应用和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
有兴趣的朋友可以搞的稳定些。。。
[课程]Android-CTF解题方法汇总!