首页
社区
课程
招聘
[旧帖] [原创]加壳原理与简单实现加壳 0.00雪花
发表于: 2010-3-16 09:39 1392

[旧帖] [原创]加壳原理与简单实现加壳 0.00雪花

2010-3-16 09:39
1392
加壳原理与简单实现加壳
{*****************************************************************
AddShell()源自于前一段时间有写的addsection()新增区段代码,
在增加区段代码的基础上,追加了
1.修改启动入口点位置
2.增加一段壳头xor $50的代码function AttachStart-function AttachEnd
这一段代码是先填充,再被修改成合适原EXE的壳头
3.修改原启动代码入口点所在区段的段属性可写并进行xor $50运算加密

不支持addshell()处理已经过addshell的exe
*****************************************************************}

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Button2: TButton;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
private
    { Private declarations }
public
    { Public declarations }
end;

var
Form1            : TForm1;

implementation

{$R *.dfm}
function AttachStart: dword; stdcall;  //我们定义的待填充数据
asm
      pushfd
      pushad
      mov eax,$12345678      //将会被自动计算并修改为加密初始地址
      mov ebx,$1234          //将会被自动计算并修改为加密大小
      mov ecx,0
      @AA:
      xor byte ptr[eax],$50
      inc eax
      inc ecx
      cmp ecx,ebx
      jbe @aa
      popad
      popfd
      push $12345678        //将会被自动计算并修改为原OEP
      ret
end;

function AttachEnd: dword; stdcall;
begin
end;

{-------------------------增加区块并实现简易加壳--------------------------------}
procedure AddShell(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, ChangeData: integer;      //附加段填充数据
OEP              : integer;          //使用过程中用到的EP
lpBuffer          : array[0..1024 * 400] of byte; {待加密数据存储缓冲区}
nNumberOfBytesToRead, lpNumberOfBytesRead: dword; //加密时用到的一些数据
StartEN, SizeEN, StartCr: dword;      //加密用的开始物理地址和大小
begin

//定义附加段填充数据
AttachData := 0;

//打开文件
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;
    {********************************}
    {OEP=基址+原EP}
    OEP := ImageNtHeaders.OptionalHeader.ImageBase + ImageNtHeaders.OptionalHeader.AddressOfEntryPoint;

    {********************************}

    //计算加入块对齐后大小
    AttachSize := ((integer(@AttachEnd) - integer(@AttachStart)) div ImageNtHeaders.OptionalHeader.FileAlignment + 1) * ImageNtHeaders.OptionalHeader.FileAlignment;

    //初始化文件中偏移和映象中偏移
    lPointerToRawData := 0;
    lVirtualAddress := 0;

    for i := 0 to ImageNtHeaders.FileHeader.NumberOfSections - 1 do
    begin

      //读取块表中信息
      ReadFile(hFile, ImageSectionHeader, SizeOf(ImageSectionHeader), BytesRead, nil);

      {********************************}
      {查找原EP所在区段(原EP所在区段),记录物理偏移(加密用初始地址),物理大小(加密用长度)}
      if LPCSTR(@ImageSectionHeader.Name[0]) = '.EN' then
      begin
        ShowMessage('已经过本addshell处理!');
        exit;
      end;

      if ImageNtHeaders.OptionalHeader.AddressOfEntryPoint > ImageSectionHeader.VirtualAddress then
      begin
        StartEN := ImageSectionHeader.PointerToRawData;
        SizeEN := ImageSectionHeader.SizeOfRawData;
        StartCr := ImageNtHeaders.OptionalHeader.ImageBase + ImageSectionHeader.VirtualAddress;
      end;

      {********************************}

      //计算文件中偏移
      if lPointerToRawData < ImageSectionHeader.PointerToRawData + ImageSectionHeader.SizeOfRawData then
        lPointerToRawData := ImageSectionHeader.PointerToRawData + ImageSectionHeader.SizeOfRawData;

      //计算映象中偏移
      if lVirtualAddress < ImageSectionHeader.VirtualAddress + ImageSectionHeader.Misc.VirtualSize then
        lVirtualAddress := ImageSectionHeader.VirtualAddress + ImageSectionHeader.Misc.VirtualSize;
    end;

    {增加块,定义块各项属性}

    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;

    //校正新节物理偏移(物理区块对齐)
    if ImageSectionHeader.VirtualAddress mod ImageNtHeaders.OptionalHeader.SectionAlignment > 0 then
      ImageSectionHeader.VirtualAddress := (ImageSectionHeader.VirtualAddress div ImageNtHeaders.OptionalHeader.SectionAlignment + 1) * ImageNtHeaders.OptionalHeader.SectionAlignment;

    //校正新节映象偏移(映象中区块对齐)
    if ImageSectionHeader.Misc.VirtualSize mod ImageNtHeaders.OptionalHeader.SectionAlignment > 0 then
      ImageSectionHeader.Misc.VirtualSize := (ImageSectionHeader.Misc.VirtualSize div ImageNtHeaders.OptionalHeader.SectionAlignment + 1) * ImageNtHeaders.OptionalHeader.SectionAlignment;

    //设置区块属性
    ImageSectionHeader.Characteristics := $E00000E0;

    //保存区块信息
    WriteFile(hFile, ImageSectionHeader, SizeOf(ImageSectionHeader), ByteSWrite, nil);

    //校正内存映象大小
    ImageNtHeaders.OptionalHeader.SizeOfImage := ImageNtHeaders.OptionalHeader.SizeOfImage + ImageSectionHeader.Misc.VirtualSize;
    //更新OEP
    ImageNtHeaders.OptionalHeader.AddressOfEntryPoint := ImageSectionHeader.VirtualAddress;

    //校正块数目
    Inc(ImageNtHeaders.FileHeader.NumberOfSections);

    //定位到映象头
    SetFilePointer(hFile, ImageDosHeader._lfanew, nil, FILE_BEGIN);

    //保存校正过的映象头
    WriteFile(hFile, ImageNtHeaders, SizeOf(ImageNtHeaders), ByteSWrite, nil);

    //定位到新节开始处
    SetFilePointer(hFile, ImageSectionHeader.PointerToRawData, nil, FILE_BEGIN);

    //用00数据填充满新节
    for i := 1 to AttachSize do
    begin
      WriteFile(hFile, PByte(@AttachData)^, 1, ByteSWrite, nil);
    end;

    {填充自定义数据}
      //指向新节开始处
    SetFilePointer(hFile, ImageSectionHeader.PointerToRawData, nil, FILE_BEGIN);

    //填充我们定义的数据
    WriteFile(hFile, PByte(@AttachStart)^, integer(@AttachEnd) - integer(@AttachStart), ByteSWrite, nil);
    {********************************}
    //修改所谓的外壳处大量数据
    ChangeData := ImageSectionHeader.PointerToRawData + 3;
    SetFilePointer(hFile, ChangeData, nil, FILE_BEGIN);
    WriteFile(hFile, StartCr, 4, ByteSWrite, nil); //开始加密地址
    ChangeData := ChangeData + 5;
    SetFilePointer(hFile, ChangeData, nil, FILE_BEGIN);
    WriteFile(hFile, SizeEN, 4, ByteSWrite, nil); //大小
    ChangeData := ChangeData + 21;
    SetFilePointer(hFile, ChangeData, nil, FILE_BEGIN);
    WriteFile(hFile, OEP, 4, ByteSWrite, nil); //跳回OEP

    {********************************}
    //没有异常,显示增加区块成功!
    ShowMessage('增加区块成功!');

    SetFilePointer(hFile, StartEN, nil, FILE_BEGIN);
    ReadFile(hFile, lpBuffer, SizeEN, BytesRead, nil);
    for i := 0 to SizeEN - 1 do
    begin
      byte(pointer(integer(@lpBuffer) + i)^) := byte(pointer(integer(@lpBuffer) + i)^) xor $50;
    end;
    SetFilePointer(hFile, StartEN, nil, FILE_BEGIN);
    WriteFile(hFile, lpBuffer, SizeEN, ByteSWrite, nil);
    //没有异常,显示变换成功!
    ShowMessage('变换数据成功!');

    {********************************}
    SetFilePointer(hFile, (ImageDosHeader._lfanew + SizeOf(ImageNtHeaders)), nil, FILE_BEGIN);

    for i := 0 to ImageNtHeaders.FileHeader.NumberOfSections - 1 do
    begin

      //读取块表中信息
      ReadFile(hFile, ImageSectionHeader, SizeOf(ImageSectionHeader), BytesRead, nil);
      if ImageSectionHeader.PointerToRawData = StartEN then
      begin
        ImageSectionHeader.Characteristics := $E00000E0;
        SetFilePointer(hFile, -SizeOf(ImageSectionHeader), nil, FILE_CURRENT);
        //保存区块信息
        WriteFile(hFile, ImageSectionHeader, SizeOf(ImageSectionHeader), ByteSWrite, nil);
        Break;
      end;
    end;
    ShowMessage('修改区段属性成功!');
    {********************************}

finally

    {8.退出}
        //关闭文件
    CloseHandle(hFile);
end;

end;
{*************************Func end*********************************}

procedure TForm1.Button1Click(Sender: TObject);//addshell
begin

AddShell(Edit1.text, true);
end;

procedure TForm1.Button3Click(Sender: TObject);//browser
begin
with TOpenDialog.Create(Self) do
try
    Filter := '可执行文件 (*.exe)|*.exe';
    if Execute then
    begin
      Edit1.text := FileName;
    end;
finally
    Free;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);//exit
begin
close;
end;

end.

//就这些了,p>

[课程]Linux pwn 探索篇!

收藏
免费 0
支持
分享
最新回复 (7)
雪    币: 48
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
delphi看的困难,还是支持一下
2010-3-16 11:21
0
雪    币: 0
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
现在还在用E

在学VB

E语言是个胎子、每次加壳都报毒
2010-3-16 11:26
0
雪    币: 6
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
谢谢楼主,学习了。
2010-3-16 11:33
0
雪    币: 11
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
学习一下,感谢分享
2010-3-16 13:05
0
雪    币: 115
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
楼主太强悍了,说实话我基本上没看懂
2010-3-16 14:01
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
谢谢楼主,学习了。
2010-3-16 15:05
0
雪    币: 370
活跃值: (52)
能力值: ( LV13,RANK:350 )
在线值:
发帖
回帖
粉丝
8
http://blog.shuren100.com/760972/viewspace-84258
http://www.5luyu.cn/article/kaiyuan/297.htm

如果是转帖请注明 谢谢
2010-3-16 18:18
0
游客
登录 | 注册 方可回帖
返回
//