- UID
- 20912
注册时间2006-8-25
阅读权限30
最后登录1970-1-1
龙战于野
该用户从未签到
|
楼主 |
发表于 2007-10-15 15:45:14
|
显示全部楼层
增加区块的程序实现...- {-------------------------增加区块 -------------------------------}
- { }
- { }
- {1.定义附加段填充数据 }
- { }
- {2.读取PE信息 }
- { }
- {3.块填充大小=(待增加数据大小/区块物理对齐大小+1)*区块物理对齐大小 }
- { }
- {4.计算块各项属性 }
- { A.读取区块信息 }
- { B.块物理位置=最后一块的物理位置+最后一块物理大小 }
- { C.映象中偏移=最后一块的映象中偏移+最后一块映象大中大小 }
- { }
- {5.增加块,定义块各项属性 }
- { A.增加块 }
- { B.校正新节物理偏移 }
- { C.校正新节映象偏移 }
- { D.设置区块属性 }
- { E.保存整个块表 }
- { }
- {6.修正PE头信息 }
- { A.校正内存映象大小=原野内存映象大小+已定义块映象大小 }
- { B.更正块数=原块数目+1 }
- { C.保存修改过的映象头 }
- { }
- {7.定位到文件末尾,追加待增加数据,长度为物理大小 }
- { A.填充数据到物理对齐 }
- { B.填充自定义数据 }
- { }
- {8.退出 }
- {*****************************************************************}
- unit Unit1;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, StdCtrls;
- type
- TForm1 = class(TForm)
- Button1: TButton;
- Edit1: TEdit;
- procedure Button1Click(Sender: TObject);
- private
- { Private declarations }
- public
- { Public declarations }
- end;
- var
- Form1 : TForm1;
- implementation
- {$R *.dfm}
- function AttachStart: DWORD; stdcall; //我们定义的待填充数据
- begin
- asm
- mov eax,eax
- end;
- end;
- function AttachEnd: DWORD; stdcall;
- begin
- end;
- {-------------------------增加区块--------------------------------}
- procedure AddSection(lFileName: string; lBackup: Boolean); //打开exe文件,是否备份
- var
- hFile : THandle; //文件句柄
- ImageDosHeader : IMAGE_DOS_HEADER; //DOS部首
- ImageNtHeaders : IMAGE_NT_HEADERS; //映象头
- ImageSectionHeader: IMAGE_SECTION_HEADER; //块表
- lPointerToRawData : DWORD; //指向文件中的偏移
- lVirtualAddress : DWORD; //指向内存中的偏移
- i : Integer; //循环变量
- BytesRead, ByteSWrite: Cardinal; //读写用参数
- AttachSize : DWORD; //附加段大小
- AttachData : Integer; //附加段填充数据
- begin
- {1.定义附加段填充数据}
- //定义附加段填充数据
- AttachData := 0;
- {2.读取PE信息}
- //打开文件
- hFile := CreateFile(PChar(lFileName), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
- //校验
- if hFile = INVALID_HANDLE_VALUE then
- begin
- ShowMessage('打开文件失败');
- exit;
- end;
- //确认备份
- if lBackup then CopyFile(PChar(lFileName), PChar(lFileName + '.bak'), False);
- try
- //读取DOS部首到ImageDosHeader
- ReadFile(hFile, ImageDosHeader, SizeOf(ImageDosHeader), BytesRead, nil);
- //校验
- if ImageDosHeader.e_magic <> IMAGE_DOS_SIGNATURE then
- begin
- ShowMessage('不是有效的PE文件!');
- exit;
- end;
- //指向映象头
- SetFilePointer(hFile, ImageDosHeader._lfanew, nil, FILE_BEGIN);
- //读取映向头到ImageNtHeaders
- ReadFile(hFile, ImageNtHeaders, SizeOf(ImageNtHeaders), BytesRead, nil);
- //校验
- if ImageNtHeaders.Signature <> IMAGE_NT_SIGNATURE then
- begin
- ShowMessage('不是有效的PE文件');
- exit;
- end;
- {3.块填充大小=(待增加数据大小/区块物理对齐大小+1)*区块物理对齐大小}
- //计算加入块对齐后大小
- AttachSize := ((Integer(@AttachEnd) - Integer(@AttachStart)) div ImageNtHeaders.OptionalHeader.FileAlignment + 1) * ImageNtHeaders.OptionalHeader.FileAlignment;
- {4.计算块各项属性}
- //初始化文件中偏移和映象中偏移
- lPointerToRawData := 0;
- lVirtualAddress := 0;
- for i := 0 to ImageNtHeaders.FileHeader.NumberOfSections - 1 do
- begin
- {A.读取区块信息}
- //读取块表中信息
- ReadFile(hFile, ImageSectionHeader, SizeOf(ImageSectionHeader), BytesRead, nil);
- {B.块物理位置=最后一块的物理位置+最后一块物理大小}
- //计算文件中偏移
- if lPointerToRawData < ImageSectionHeader.PointerToRawData + ImageSectionHeader.SizeOfRawData then
- lPointerToRawData := ImageSectionHeader.PointerToRawData + ImageSectionHeader.SizeOfRawData;
- {C.映象中偏移=最后一块的映象中偏移+最后一块映象大中大小}
- //计算映象中偏移
- if lVirtualAddress < ImageSectionHeader.VirtualAddress + ImageSectionHeader.Misc.VirtualSize then
- lVirtualAddress := ImageSectionHeader.VirtualAddress + ImageSectionHeader.Misc.VirtualSize;
- end;
- {5.增加块,定义块各项属性}
- {A.增加块}
- //新建区块,名为.EN
- Move('.EN'#0, ImageSectionHeader.Name[0], 5);
- //设法初始属性
- ImageSectionHeader.Misc.VirtualSize := AttachSize;
- ImageSectionHeader.VirtualAddress := lVirtualAddress;
- ImageSectionHeader.SizeOfRawData := AttachSize;
- ImageSectionHeader.PointerToRawData := lPointerToRawData;
- ImageSectionHeader.PointerToRelocations := 0;
- ImageSectionHeader.PointerToLinenumbers := 0;
- ImageSectionHeader.NumberOfRelocations := 0;
- {B.校正新节物理偏移}
- //校正新节物理偏移(物理区块对齐)
- if ImageSectionHeader.VirtualAddress mod ImageNtHeaders.OptionalHeader.SectionAlignment > 0 then
- ImageSectionHeader.VirtualAddress := (ImageSectionHeader.VirtualAddress div ImageNtHeaders.OptionalHeader.SectionAlignment + 1) * ImageNtHeaders.OptionalHeader.SectionAlignment;
- {C.校正新节映象偏移}
- //校正新节映象偏移(映象中区块对齐)
- if ImageSectionHeader.Misc.VirtualSize mod ImageNtHeaders.OptionalHeader.SectionAlignment > 0 then
- ImageSectionHeader.Misc.VirtualSize := (ImageSectionHeader.Misc.VirtualSize div ImageNtHeaders.OptionalHeader.SectionAlignment + 1) * ImageNtHeaders.OptionalHeader.SectionAlignment;
- {D.设置区块属性}
- //设置区块属性
- ImageSectionHeader.Characteristics := $E00000E0;
- {E.保存整个块表}
- //保存区块信息
- WriteFile(hFile, ImageSectionHeader, SizeOf(ImageSectionHeader), ByteSWrite, nil);
- {6.修正PE头信息}
- {A.校正内存映象大小=原野内存映象大小+已定义块映象大小}
- //校正内存映象大小
- ImageNtHeaders.OptionalHeader.SizeOfImage := ImageNtHeaders.OptionalHeader.SizeOfImage + ImageSectionHeader.Misc.VirtualSize;
- {B.更正块数=原块数目+1}
- //校正块数目
- Inc(ImageNtHeaders.FileHeader.NumberOfSections);
- {C.保存修改过的映象头}
- //定位到映象头
- SetFilePointer(hFile, ImageDosHeader._lfanew, nil, FILE_BEGIN);
- //保存校正过的映象头
- WriteFile(hFile, ImageNtHeaders, SizeOf(ImageNtHeaders), ByteSWrite, nil);
- {7.定位到文件末尾,追加待增加数据,长度为物理大小}
- {A.填充数据到物理对齐}
- //定位到新节开始处
- SetFilePointer(hFile, ImageSectionHeader.PointerToRawData, nil, FILE_BEGIN);
- //用00数据填充满新节
- for i := 1 to AttachSize do
- begin
- WriteFile(hFile, PByte(@AttachData)^, 1, ByteSWrite, nil);
- end;
- {B.填充自定义数据}
- //指向新节开始处
- SetFilePointer(hFile, ImageSectionHeader.PointerToRawData, nil, FILE_BEGIN);
- //填充我们定义的数据示例
- WriteFile(hFile, PByte(@AttachStart)^, Integer(@AttachEnd) - Integer(@AttachStart), ByteSWrite, nil);
- //没有异常,显示增加区块成功!
- ShowMessage('增加区块成功!');
- finally
- {8.退出}
- //关闭文件
- CloseHandle(hFile);
- end;
- end;
- {*************************Func end*********************************}
- procedure TForm1.Button1Click(Sender: TObject);
- begin
- AddSection(Edit1.text, true);//Edit1.text为文件路径,true表示备份
- end;
复制代码
[ 本帖最后由 fonge 于 2007-10-15 15:47 编辑 ] |
|