首页
社区
课程
招聘
[原创]软件保护壳技术专题 - 添加新节(练习笔记)
发表于: 2010-8-16 23:59 8110

[原创]软件保护壳技术专题 - 添加新节(练习笔记)

2010-8-16 23:59
8110
跟着玩命的保护壳技术专题学习,随便解决了一些问题,代码并非按玩命的方式写,只是跟着他的原理按自己的编写风格写的,纯新手,高手莫笑!!

添加节 基本步骤:
1.        创建一个映射文件,大小为原文件大小+新节大小(需要对齐)
2.        保存SizeOfImage的地址,保存NumberOfSections的值,然后+1,保存SectionAlignment和FileAlignment的值,用于对齐计算!
3.        定位到节表(IMAGE_SECTION_HEADER),一般用头文件地址+头文件大小, 当然在无法确定数据目录段的数量的时候还是通过[NumberOfRvaAndSizes]*8来定位
4.        NumberOfSections*IMAGE_SECTION_HEADER就是新节表地址,然后就是把节表的结构参数填上, 新节的内存偏移 = 上一节的内存偏移 + 上一节经过节对齐后的长度, 新节的文件偏移 = 上一节的文件偏移 + 上一节进过文件对齐后的长度, 如果文件偏移为0,就要取上面的上面,这种取法可能不标准,然后设置SizeofImage,表示从文件到内存映射文件的内容通过节对齐的大小,这个值等于当前最后一节的内存偏移 + 当前最后一节的经过节对齐的大小,然后把数据移到新节位置,大功告成!

主体部分:
.386
.model flat, stdcall
option casemap:none

include windows.inc
include kernel32.inc
include user32.inc
include macro.asm
includelib kernel32.lib
includelib user32.lib
include		comdlg32.inc
includelib	comdlg32.lib
.data
szSectionName	db '.Alone',0
SecData			db	200 dup('A')

.code
include kernel.asm

_OpenExeFile proc
local OFN:OPENFILENAME,szFileNameBuff[MAX_PATH]:BYTE 
local Map:MapFileHandle
		;以下是打开通用对话框的操作
		invoke RtlZeroMemory,addr OFN,sizeof OFN	;初始化结构
		invoke RtlZeroMemory,addr szFileNameBuff,MAX_PATH
		mov	OFN.lStructSize,sizeof  OFN
		lea	eax,szFileNameBuff
		mov	OFN.lpstrFile,eax
		mov	OFN.nMaxFile,MAX_PATH
		mov	OFN.Flags,OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST
		invoke	GetOpenFileName,addr OFN	;打开通用对话框
		;********************************************
.if	eax
invoke	_CalcAlign,sizeof SecData,200H	;以200H为对齐方式
invoke	_CreatMapFile,addr szFileNameBuff, addr Map,eax;创建一个内存映射文件
mov	eax,Map.lpMemory	;简单判断下PE文件有效性
assume	eax:ptr IMAGE_DOS_HEADER
	.if	[eax].e_magic == IMAGE_DOS_SIGNATURE
		add	eax,[eax].e_lfanew ;到文件头
		assume	eax:ptr IMAGE_NT_HEADERS
		.if	[eax].Signature==IMAGE_NT_SIGNATURE
			invoke	_AddSection,Map.lpMemory,addr szSectionName,sizeof szSectionName,addr SecData,sizeof SecData
			invoke	MessageBox,NULL,CTXT("添加节成功!"),NULL,NULL
			jmp @F
		.endif
	.endif
	invoke MessageBox,NULL,CTXT("不是有效的PE文件!"),NULL,NULL
@@:
invoke	_CloseMapFile, addr Map
.endif
ret
_OpenExeFile endp

;OEP
	Start:
	call _OpenExeFile
	invoke ExitProcess,NULL
	end Start


核心部分,主要便于二次开发

;********************************************************************
; 用一个结构来保存创始内存映射后的句柄
;********************************************************************
MapFileHandle struct
	hFile			dd	?
	dwFileSize	dd ?
	hMapFile		dd	?
	lpMemory		dd	?
MapFileHandle ends
;********************************************************************
; 计算对齐值
;********************************************************************
_CalcAlign proc dwval,dwalign;(dwval+dwalign-1)\dwalign*dwalign
mov	eax,dwalign
dec	eax
add	eax,dwval
xor	edx,edx
mov	ecx,dwalign
div	ecx
imul	ecx
ret
_CalcAlign endp
;********************************************************************
; 增加节 
;********************************************************************
_AddSection proc uses esi edi lpMem,lpSecName,dwSecNameSize,lpSecAddr,DwSecSize;参数:内存映射地址,新节名及大小,节数据及大小
;添加新节相关的PE头属性位于IMAGE_NT_HEADERS结构中的属性:
;SizeOfImage(4字节)	NumberOfSections(2字节)	SectionAlignment(4字节)	FileAlignment(4字节)
local SizeOfImageAddr,NumberOfSections,SectionAlignment,FileAlignment
mov	esi,lpMem
assume	esi:ptr IMAGE_DOS_HEADER
add	esi,[esi].e_lfanew	;到文件头
			;初始化一些变量
			assume	esi:ptr IMAGE_NT_HEADERS
			lea	eax,[esi].OptionalHeader.SizeOfImage
			mov	SizeOfImageAddr,eax	;这个地址的值要修改
			movzx	eax,[esi].FileHeader.NumberOfSections
			mov	NumberOfSections,eax;节个数
			inc	[esi].FileHeader.NumberOfSections	;加一个节
			push	[esi].OptionalHeader.SectionAlignment
			pop	SectionAlignment
			push	[esi].OptionalHeader.FileAlignment
			pop	FileAlignment
add	esi,sizeof IMAGE_NT_HEADERS;到节表地址,当然在无法确定数据目录段的数量的时候还是通过[NumberOfRvaAndSizes]*8来定位节表好
mov	ecx,NumberOfSections
mov	eax,sizeof IMAGE_SECTION_HEADER
imul	ecx
lea	esi,[esi+eax] ; 28=sizeof IMAGE_SECTION_HEADER
assume	esi:ptr IMAGE_SECTION_HEADER
lea	eax,[esi].Name1
invoke RtlMoveMemory,eax,lpSecName,dwSecNameSize ;设置节名
push	DwSecSize
pop	[esi].Misc.VirtualSize;设置内存中节大小
invoke	_CalcAlign,DwSecSize,FileAlignment;计算文件中节大小
mov	[esi].SizeOfRawData,eax	;设置文件中节大小
mov	edi,esi
sub	edi,sizeof IMAGE_SECTION_HEADER	;上一个节指针,不知道这样算标准不?
assume	edi:ptr IMAGE_SECTION_HEADER
; 新节的内存偏移 = 上一节的内存偏移 + 上一节经过节对齐后的长度
mov	eax,[edi].VirtualAddress
add	eax,[edi].Misc.VirtualSize
invoke _CalcAlign,eax,SectionAlignment
mov	[esi].VirtualAddress,eax
; 新节的文件偏移 = 上一节的文件偏移 + 上一节进过文件对齐后的长度
@@:
mov	eax,[edi].PointerToRawData
.if	!eax	;如果文件偏移=0...			;貌似能解决cham说的文件偏移为0的问题
sub	edi,sizeof IMAGE_SECTION_HEADER
jmp @B
.endif
add	eax,[edi].SizeOfRawData
invoke _CalcAlign,eax,FileAlignment
mov	[esi].PointerToRawData,eax
;; SizeofImage表示从文件到内存映射文件的内容通过节对齐的大小,这个值等于当前最后一节的内存偏移 + 当前最后一节的经过节对齐的大小
mov	eax,[esi].VirtualAddress
add	eax,[esi].Misc.VirtualSize
invoke _CalcAlign,eax,SectionAlignment
mov	ecx,SizeOfImageAddr
mov	[ecx],eax	;设置SizeOfImage
;然后把数据放到节区
mov	edi,[esi].PointerToRawData
add	edi,lpMem
invoke	RtlMoveMemory,edi,lpSecAddr,DwSecSize
ret
_AddSection endp
;********************************************************************
; 关闭创建的内存映射文件相关句柄
;********************************************************************
_CloseMapFile proc uses esi lpmapFuct
mov	esi,lpmapFuct
assume	esi:ptr MapFileHandle
	.if	[esi].hFile!=INVALID_HANDLE_VALUE ;文件句柄是否有效
		invoke CloseHandle,[esi].hFile
		.if	[esi].hMapFile
			invoke CloseHandle,[esi].hMapFile
			.if	[esi].lpMemory
				invoke UnmapViewOfFile,[esi].lpMemory
			.endif	
		.endif	
	.endif
ret
_CloseMapFile endp
;********************************************************************
; 创建一个内存映射文件,可读写操作,独占式打开
;********************************************************************
_CreatMapFile proc uses esi lpPath,lpmapFuct,dwSizeEx;dwSizeEx 附加大小
mov	esi,lpmapFuct
invoke	RtlZeroMemory,esi,sizeof MapFileHandle;初始化自己定义的结构
invoke	CreateFile, lpPath,GENERIC_WRITE + GENERIC_READ,FILE_SHARE_DELETE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
		.if eax
			mov	[esi].hFile,eax
			invoke	GetFileSize,eax,NULL
			mov	[esi].dwFileSize,eax
			add	eax,dwSizeEx
			invoke CreateFileMapping,[esi].hFile, 0, PAGE_READWRITE, 0, eax, 0
			.if eax
				mov	[esi].hMapFile,eax
				invoke	MapViewOfFile,eax,FILE_MAP_READ or FILE_MAP_WRITE,NULL,NULL,NULL
				.if	eax
					mov	[esi].lpMemory,eax
					xor	eax,eax	;返回值
					jmp	@F
				.endif	
			.endif	
		.endif	
	invoke _CloseMapFile,lpmapFuct	;中途的失败操作,都会默认这里来关闭文件句柄
	mov	eax,1	;返回值
@@:		
ret
_CreatMapFile endp


好像也解决了如果最后一个节的文件大小为0的情况
http://bbs.pediy.com/showthread.php?t=66612&page=2

[课程]FART 脱壳王!加量不加价!FART作者讲授!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (5)
雪    币: 656
活跃值: (448)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
2
没人顶,只能自己沙发了
2010-8-17 16:52
0
雪    币: 247
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
看着汇编代码纠结啊,如果用C的话,就可以看得快了
2010-8-20 00:03
0
雪    币: 38
活跃值: (52)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
mark,留着以后看看
2010-8-22 06:53
0
雪    币: 1259
活跃值: (38)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
stu
5
不错,不错。
2010-8-22 07:29
0
雪    币: 62
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
可能思路都是一样的原因吧,跟老罗的WIN32汇编有比较大的相似性。
2010-11-10 12:34
0
游客
登录 | 注册 方可回帖
返回
//