最近人变懒了,专题一直没有更新,放一个小技巧出来耍耍。是原先那个随机密码的应用和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放置到与打包器同一目录下,在用打包器对其他程序进程加壳。
代码:
.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