2008年8月26日

本质理解脱壳之 添加节

代码含注释
流程如下:
1 将文件映射到内存得到基地址
2 检验PE标志
3 添加新节
3.1 增加节个数
3.2 得到文件对齐和节对齐值
3.3 通过节个数得到最后一节节头的地址和新节节头的地址
3.4 构建新节节头,包括name,Characteristics,misc.VirtualSize(实际大小),
通过VirtualSize文件对齐得到SizeOfRawData
3.5 通过最后一节节头VirtualAddress+VirtualSize节对齐后得到新节的VirtualAddress
通过最后一节节头PointerToRawData+SizeOfRawData文件对齐后得到新节PointerToRawData
3.6 修改SizeOfImage大小为新节的VirtualAddress+VirtualSize节对齐值
3.7 通过新节的PointerOfRawData(文件中的新节位置),将新节清0
4 修改 AddressOfEntryPoint, 旧的保存到新节最后, 新的指向新节首地址
5 将新节数据填充到新节中




.386
.model flat, stdcall
option casemap:none

include AddSection.Inc

APPEND_SIZE equ 2000h ;;添加到文件尾的大小

.const

g_szTargetFile db 'target.exe', 0
g_szNewSectionName db ".cjay", 0
g_szOpenFileFailed db "打不开文件", 0
g_szErr db "错误", 0
g_szDone db "成功", 0
g_szDoneCap db "Good Job", 0
g_szGetFileSizeFailed db "获取文件大小失败", 0
g_szCreateMapFailed db "创建文件映射失败", 0
g_szMapFileFailed db "映射文件失败", 0
g_szInvalidPE db "无效PE文件", 0

.data
g_bError db 0 ;错误代码
g_dwNewSectionSize dd 0 ;新节长度


;; 函数定义
CryptFile proto szFname : LPSTR ;;加密文件
AddSection proto pMem : LPVOID, pSectionName : LPVOID, dwSectionSize : DWORD ;; 添加新节
PEAlign proto dwTarNum : DWORD, dwAlignTo : DWORD ;;对齐

.code
Start:
invoke CryptFile, offset g_szTargetFile
invoke ExitProcess, 1

CryptFile proc szFname : LPSTR
LOCAL hFile : HANDLE
LOCAL hMap : HANDLE
LOCAL pMem : LPVOID
LOCAL dwOrigFileSize : DWORD ;;存放原始文件大小
LOCAL dwNTHeaderAddr : DWORD ;;存放NT头地址

xor eax, eax
mov hFile, eax
mov hMap, eax
mov pMem, eax

mov g_bError, al
mov eax, offset EndNewSection - offset NewSection
mov g_dwNewSectionSize, eax

;; open File
invoke CreateFile,szFname, \
GENERIC_READ+GENERIC_WRITE,\
FILE_SHARE_READ+FILE_SHARE_WRITE,\
NULL,\
OPEN_EXISTING,\
FILE_ATTRIBUTE_NORMAL,\
0
.IF eax == INVALID_HANDLE_VALUE
jmp OpenFileFailed
.endif
mov hFile, eax

invoke GetFileSize, hFile, NULL
.IF eax == 0
jmp GetFileSizeFailed
.endif

mov dwOrigFileSize, eax
add eax, APPEND_SIZE
xchg eax, ecx

;; create memory map
xor ebx, ebx
invoke CreateFileMapping, hFile, ebx, PAGE_READWRITE, ebx, ecx, ebx
.IF eax == 0
jmp CreateMapFailed
.endif
mov hMap, eax

;; map file to memory
invoke MapViewOfFile, hMap, FILE_MAP_WRITE+FILE_MAP_READ+FILE_MAP_COPY,ebx,ebx,ebx
.IF eax == 0
jmp MapFileFailed
.endif
mov pMem, eax

;; check PE
xchg eax, esi
assume esi : ptr IMAGE_DOS_HEADER
.IF [esi].e_magic != 'ZM'
jmp InvalidPE
.endif
add esi, [esi].e_lfanew
assume esi:ptr IMAGE_NT_HEADERS
.IF word ptr [esi].Signature != 'EP'
jmp InvalidPE
.endif
mov dwNTHeaderAddr, esi

;; add section
invoke AddSection,pMem,offset g_szNewSectionName,g_dwNewSectionSize
;; return New Section Addr(VA)
push eax
mov esi, dwNTHeaderAddr
assume esi : ptr IMAGE_NT_HEADERS
;;AddressOfEntryPoint
mov ebx, dword ptr [esi].OptionalHeader.AddressOfEntryPoint
add ebx, dword ptr [esi].OptionalHeader.ImageBase
;; Save the old entry
mov eax, offset OrigAddressOfEntry
mov dword ptr [eax], ebx
;; New Rntry is at New Section start
pop eax
assume eax : ptr IMAGE_SECTION_HEADER
push dword ptr [eax].VirtualAddress
pop dword ptr [esi].OptionalHeader.AddressOfEntryPoint

mov esi, offset NewSection
mov edi, dword ptr [eax].PointerToRawData
add edi, pMem
mov ecx, g_dwNewSectionSize
cld
rep movsb

LogicShellExit:
;; close handle & write it
.IF pMem != NULL
invoke UnmapViewOfFile, pMem
.endif
.IF hMap != NULL
invoke CloseHandle, hMap
.endif
.IF hFile != NULL
invoke CloseHandle, hFile
.endif
.IF g_bError == 0
;; show success message
invoke MessageBox, NULL, offset g_szDone, offset g_szDoneCap, MB_ICONINFORMATION
.ENDIF
ret
;; ----- Show error message -----
OpenFileFailed:
lea eax, g_szOpenFileFailed
jmp ShowErr
GetFileSizeFailed:
lea eax, g_szGetFileSizeFailed
jmp ShowErr
CreateMapFailed:
lea eax, g_szCreateMapFailed
jmp ShowErr
MapFileFailed:
lea eax, g_szMapFileFailed
jmp ShowErr
InvalidPE:
lea eax, g_szInvalidPE
jmp ShowErr
ShowErr:
invoke MessageBox, NULL, eax, offset g_szErr, MB_ICONERROR
mov al, 1
mov g_bError, al
jmp LogicShellExit
;; ----- NEW SCETION-----
NewSection:
call GetEip
GetEip:
pop eax
add eax, offset OrigAddressOfEntry - offset GetEip
mov eax, dword ptr [eax]
jmp eax
OrigAddressOfEntry dd ?
EndNewSection:

CryptFile endp

AddSection proc uses ebx ecx edx esi edi, pMem:LPVOID, pSectionName:LPVOID, dwSectionSize:DWORD
LOCAL dwNTHeader : LPVOID
LOCAL dwFileAlign : DWORD ;文件对齐
LOCAL dwSecAlig : DWORD ;节对齐
LOCAL dwLastSecTbl : DWORD ;最后一节地址(VA)
mov esi, pMem
add esi, dword ptr [esi+03ch]
mov dwNTHeader, esi
assume esi : ptr IMAGE_NT_HEADERS
mov cx, word ptr [esi].FileHeader.NumberOfSections
movzx ecx, cx
inc word ptr [esi].FileHeader.NumberOfSections
push dword ptr [esi].OptionalHeader.FileAlignment
pop dwFileAlign
push dword ptr [esi].OptionalHeader.SectionAlignment
pop dwSecAlig

add esi, sizeof IMAGE_NT_HEADERS ;Section Header Base
mov eax, sizeof IMAGE_SECTION_HEADER
mov ebx, ecx
imul ebx
add esi, eax

push esi
sub esi, sizeof IMAGE_SECTION_HEADER
mov dwLastSecTbl, esi
pop esi ;; esi保存了新节地址
;; 设置新节
assume esi : ptr IMAGE_SECTION_HEADER
push esi
lea edi, [esi].Name1
mov esi, pSectionName
CopySectionNameLoop:
lodsb
test al, al
jz EndCopySectionNameLoop
stosb
jmp CopySectionNameLoop
EndCopySectionNameLoop:
pop esi
;;属性
push 0E00000E0h
pop dword ptr [esi].Characteristics
;;VirtualSize
push dwSectionSize
pop dword ptr [esi].Misc.VirtualSize
;;SizeOfRawdata
invoke PEAlign, dwSectionSize, dwFileAlign
mov dword ptr [esi].SizeOfRawData, eax
;;VirtualAddress, PointerToRawData
mov eax, dwLastSecTbl
assume eax : ptr IMAGE_SECTION_HEADER
mov ecx, dword ptr [eax].VirtualAddress
add ecx, dword ptr [eax].Misc.VirtualSize
mov ebx, dword ptr [eax].PointerToRawData
add ebx, dword ptr [eax].SizeOfRawData

invoke PEAlign,ecx,dwSecAlig
mov dword ptr [esi].VirtualAddress, eax
invoke PEAlign,ebx,dwFileAlign
mov dword ptr [esi].PointerToRawData, eax
;; SizeOfImage
mov eax, dword ptr [esi].VirtualAddress
add eax, dword ptr [esi].Misc.VirtualSize
invoke PEAlign,eax,dwSecAlig
mov edx, dwNTHeader
assume edx : ptr IMAGE_NT_HEADERS
mov dword ptr [edx].OptionalHeader.SizeOfImage, eax

push dword ptr [esi].PointerToRawData
pop edi
add edi, pMem
;; clear new Section
mov ecx, dwSectionSize
xor eax, eax
cld
rep stosb

;; return New Section Address(VA)
mov eax, esi
assume esi : nothing
assume eax : nothing
assume edx : nothing
ret
AddSection endp

PEAlign proc uses ecx edx, dwTarNum : DWORD, dwAlignTo : DWORD
mov ecx, dwAlignTo
mov eax, dwTarNum
xor edx, edx
div ecx
cmp edx, 0 ;; edx保存余数
jz AlreadyAligned
inc eax
AlreadyAligned:
mul ecx
ret
PEAlign endp

end Start


没有评论: