一个简单的花指令伪装器-Delphi版木马彩衣
更新时间:2007年01月16日 00:00:00 作者:
说明:以VC++6的花指令为例说明
//VC++6外衣 1
OEPCODEFIVE: THEAD =
($55, $8B, $EC, $6A, $FF, $68, $00, $00, $00, $00, $68, $00, $00, $00, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $83, $EC, $68,
$53, $56, $57, $58, $58, $58, $83, $C4, $68, $58, $67, $64, $A3, $00, $00, $58,
$58, $58, $58, $8B, $E8, $E9, $07, $B9, $FE, $FF, $00, $00, $00, $00, $00, $00);
//VC++6外衣 2
OEPCODEFIVE: THEAD =
($55, $8B, $EC, $6A, $FF, $68, $00, $00, $00, $00, $68, $00, $00, $00, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $83, $EC, $68,
$53, $56, $57, $58, $58, $58, $83, $C4, $68, $58, $67, $64, $A3, $00, $00, $58,
$58, $58, $58, $8B, $E8, $B8, $00, $10, $40, $00, $FF, $E0, $90, $00, $00, $00);
1.直接将入口地址赋给寄存器eax,然后jmp eax
0046902A B8 304A4500 mov eax,Project1.00454A30
0046902F FFE0 jmp eax
00469031 90 nop
2. 直接跳转到入口地址
00469124 - E9 07B9FEFF jmp Project1.00454A30
两种效果实际上是一样的,但我们为了方便修改花指令跳转到原来的入口地址,通常取得原
pe header的AddressOfEntryPoint,然后给寄存器eax保存改值,所以第二种方法就不太方便,
所以一般采用第一种方法,JMPOFF为花指令代码到跳转指令的偏移,如对Visual C++的花指令
JMPOFF=54,其后免跟的是原入口地址,可以随便填写,程序加花指令是会自动修改,一般可以
默认设为00104000(即00401000).
通过汇编修改花指令跳转原入口地址的语句:
asm //这里说明一下,这是嵌入的汇编代码,寄存器—CPU暂时储存数据的东西,比内存更快,以提高效率
PUSHAD
LEA eax, OEPCODE //将OEPCODE的地址交给寄存器
ADD eax, JMPOFF //添加JMPOFF值给寄存器
MOV edx, AddressOfEntryPoint //转移指令,相当于付值语句,左边给右边
MOV DWORD ptr [eax], edx //同上
POPAD
end;
}
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ShellAPI;
type
TForm1 = class(TForm)
Label1: TLabel;
Edit1: TEdit;
Button1: TButton;
RadioGroup1: TRadioGroup;
Label2: TLabel;
Edit2: TEdit;
Label3: TLabel;
Edit3: TEdit;
CheckBox1: TCheckBox;
Button2: TButton;
Label5: TLabel;
OpenDialog1: TOpenDialog;
Label4: TLabel;
procedure Button1Click(Sender: TObject);
procedure obtain;
procedure Button2Click(Sender: TObject);
procedure Label4Click(Sender: TObject);
procedure Edit3KeyPress(Sender: TObject; var Key: Char);
private
{ Private declarations }
FImageBase: DWORD;
procedure SetOepCode;
public
{ Public declarations }
end;
THEAD = array[0..63] of byte;
var
Form1: TForm1;
const
{MYSECTION = 'Fi7ke'; //添加的节名,自定义
JMPOFF = 43; //花指令的机器码,Ollydbg加载后随便取
//Microsoft Visual C++
OEPCODE: THEAD =
($55, $8B, $EC, $6A, $FF, $68, $2A, $2C, $0A, $00, $68, $38,
$90, $0D, $00, $64, $A1, $00, $00, $00, $00, $50, $64, $89,
$25, $00, $00, $00, $00, $58, $64, $A3, $00, $00, $00, $00,
$58, $58, $58, $58, $8B, $E8, $B8, $00, $10, $40, $00, $FF,
$E0, $90, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00); }
//Nothing found * one
OEPCODEONE: THEAD =
($55, $8B, $EC, $83, $C4, $F4, $83, $C4, $0C, $B8, $00, $10, $40, $00, $50, $C3,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00);
//Nothing found * two
OEPCODETWO: THEAD =
($55, $8B, $EC, $41, $52, $90, $5A, $49, $5D, $41, $B8, $00, $10, $40, $00, $FF,
$E0, $90, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00);
//VC++外衣
OEPCODETHREE: THEAD =
($55, $8B, $EC, $6A, $FF, $68, $2A, $2C, $0A, $00, $68, $38, $90, $0D, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $58, $64, $A3,
$00, $00, $00, $00, $58, $58, $58, $58, $8B, $E8, $B8, $00, $10, $40, $00, $FF,
$E0, $90, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00);
//VC++5外衣
OEPCODEFOUR: THEAD =
($55, $8B, $EC, $6A, $FF, $68, $48, $54, $41, $00, $68, $A8, $21, $40, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $83, $C4, $94,
$53, $56, $57, $00, $00, $B8, $00, $10, $40, $00, $FF, $E0, $90, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00);
//VC++6外衣
OEPCODEFIVE: THEAD =
($55, $8B, $EC, $6A, $FF, $68, $00, $00, $00, $00, $68, $00, $00, $00, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $83, $EC, $68,
$53, $56, $57, $58, $58, $58, $83, $C4, $68, $58, $67, $64, $A3, $00, $00, $58,
$58, $58, $58, $8B, $E8, $B8, $00, $10, $40, $00, $FF, $E0, $90, $00, $00, $00);
//C外衣
OEPCODESIX: THEAD =
($55, $8B, $EC, $6A, $FF, $68, $11, $11, $11, $00, $68, $22, $22, $22, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $58, $64, $A3,
$00, $00, $00, $00, $58, $58, $58, $58, $8B, $E8, $B8, $00, $10, $40, $00, $FF,
$E0, $90, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00);
OepCount = 6;
//OEPCODEARRAY :array[0..OepCount-1,0..63] of byte=(
//OEPCODEARRAY :array[0..OepCount-1] of array[0..63] of byte=(
OEPCODEARRAY :array[0..OepCount-1] of THEAD=(
($55, $8B, $EC, $83, $C4, $F4, $83, $C4, $0C, $B8, $00, $10, $40, $00, $50, $C3,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00), //Nothing found * one
($55, $8B, $EC, $6A, $FF, $68, $2A, $2C, $0A, $00, $68, $38, $90, $0D, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $58, $64, $A3,
$00, $00, $00, $00, $58, $58, $58, $58, $8B, $E8, $B8, $00, $10, $40, $00, $FF,
$E0, $90, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00), //VC++外衣
($55, $8B, $EC, $6A, $FF, $68, $48, $54, $41, $00, $68, $A8, $21, $40, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $83, $C4, $94,
$53, $56, $57, $00, $00, $B8, $00, $10, $40, $00, $FF, $E0, $90, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00), //VC++5外衣
($55, $8B, $EC, $6A, $FF, $68, $00, $00, $00, $00, $68, $00, $00, $00, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $83, $EC, $68,
$53, $56, $57, $58, $58, $58, $83, $C4, $68, $58, $67, $64, $A3, $00, $00, $58,
$58, $58, $58, $8B, $E8, $B8, $00, $10, $40, $00, $FF, $E0, $90, $00, $00, $00), //VC++6外衣
($55, $8B, $EC, $6A, $FF, $68, $11, $11, $11, $00, $68, $22, $22, $22, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $58, $64, $A3,
$00, $00, $00, $00, $58, $58, $58, $58, $8B, $E8, $B8, $00, $10, $40, $00, $FF,
$E0, $90, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00), //C外衣
($55, $8B, $EC, $41, $52, $90, $5A, $49, $5D, $41, $B8, $00, $10, $40, $00, $FF,
$E0, $90, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00) //Nothing found * two
);
JMPOFFARRAY :array[0..OepCount-1] of integer=(10,43,38,54,43,11);
{Nothing found * ONE:
Borland Delphi 6.0 - 7.0
00469022 0055 8B add byte ptr ss:[ebp-75],dl
00469025 EC in al,dx
00469026 83C4 F4 add esp,-0C
00469029 83C4 0C add esp,0C
0046902C B8 304A4500 mov eax,Project1.00454A30
00469031 50 push eax
00469032 C3 retn
Nothing found * TWO
00454A72 55 push ebp
00454A73 8BEC mov ebp,esp
00454A75 41 inc ecx
00454A76 52 push edx
00454A77 90 nop
00454A78 5A pop edx
00454A79 49 dec ecx
00454A7A 5D pop ebp
00454A7B 41 inc ecx
0046902A B8 304A4500 mov eax,Project1.00454A30
0046902F FFE0 jmp eax
00469031 90 nop
C外衣:
00454A6C 55 push ebp
00454A6D 8BEC mov ebp,esp
00454A6F 6A FF push -1
00454A71 68 11111100 push 111111
00454A76 68 22222200 push 222222
00454A7B 64:A1 00000>mov eax,dword ptr fs:[0]
00454A81 50 push eax
00454A82 64:8925 000>mov dword ptr fs:[0],esp
00454A89 58 pop eax
00454A8A 64:A3 00000>mov dword ptr fs:[0],eax
00454A90 58 pop eax
00454A91 58 pop eax
00454A92 58 pop eax
00454A93 58 pop eax
00454A94 8BE8 mov ebp,eax
00454A96 - E9 65F5CAFF jmp 00104000
VC++5外衣:
0046905F P> 55 push ebp
00469060 8BEC mov ebp,esp
00469062 6A FF push -1
00469064 68 48544100 push Project1.00415448
00469069 68 A8214000 push Project1.004021A8
0046906E 64:A1 0000000>mov eax,dword ptr fs:[0]
00469074 50 push eax
00469075 64:8925 00000>mov dword ptr fs:[0],esp
0046907C 83C4 94 add esp,-6C
0046907F 53 push ebx
00469080 56 push esi
00469081 57 push edi
00469082 0000 add byte ptr ds:[eax],al
0046902A B8 304A4500 mov eax,Project1.00454A30
0046902F FFE0 jmp eax
00469031 90 nop
VC++外衣:
00469000 P> 55 push ebp
00469001 8BEC mov ebp,esp
00469003 6A FF push -1
00469005 68 2A2C0A00 push 0A2C2A
0046900A 68 38900D00 push 0D9038
0046900F 64:A1 0000000>mov eax,dword ptr fs:[0]
00469015 50 push eax
00469016 64:8925 00000>mov dword ptr fs:[0],esp
0046901D 58 pop eax
0046901E 64:A3 0000000>mov dword ptr fs:[0],eax
00469024 58 pop eax
00469025 58 pop eax
00469026 58 pop eax
00469027 58 pop eax
00469028 8BE8 mov ebp,eax
0046902A B8 304A4500 mov eax,Project1.00454A30
0046902F FFE0 jmp eax
00469031 90 nop
VC++6外衣:
004690EF P> 55 push ebp
004690F0 8BEC mov ebp,esp
004690F2 6A FF push -1
004690F4 68 00000000 push 0
004690F9 68 00000000 push 0
004690FE 64:A1 0000000>mov eax,dword ptr fs:[0]
00469104 50 push eax
00469105 64:8925 00000>mov dword ptr fs:[0],esp
0046910C 83EC 68 sub esp,68
0046910F 53 push ebx
00469110 56 push esi
00469111 57 push edi
00469112 58 pop eax
00469113 58 pop eax
00469114 58 pop eax
00469115 83C4 68 add esp,68
00469118 58 pop eax
00469119 67:64:A3 0000 mov dword ptr fs:[0],eax
0046911E 58 pop eax
0046911F 58 pop eax
00469120 58 pop eax
00469121 58 pop eax
00469122 8BE8 mov ebp,eax
0046902A B8 304A4500 mov eax,Project1.00454A30
0046902F FFE0 jmp eax
00469031 90 nop
}
function IntToHex(Int: Int64; IntSize: Byte): String;
procedure AddSection(FName,MySection: string;SecSize:DWord);
implementation
{$R *.dfm}
var
OEPCODE: THEAD;
JMPOFF :integer;
function IntToHex(Int: Int64; IntSize: Byte): String;
const
HexChars: array[0..15] of Char = ('0', '1', '2', '3', '4', '5','6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
var
n: Byte;
begin
Result := '';
for n := 0 to IntSize - 1 do
begin
Result := HexChars[Int and $F] + Result;
Int := Int shr $4;
end;
end;
procedure AddSection(FName,MySection: string;SecSize:DWord);
var
DOSHEADER: IMAGE_DOS_HEADER; //DOS MZ header
PEHEADER: IMAGE_NT_HEADERS; //PE header
SectionHeader: IMAGE_SECTION_HEADER; //节表
MySectionHeader: IMAGE_SECTION_HEADER; //自定义节表
fs: TFileStream;
AddressOfEntryPoint: DWORD; //入口点
i:integer;
begin
fs := TFileStream.Create(FName, fmOpenReadWrite +
fmShareDenyWrite);
try
{Tstream中定义的虚方法有四个:
1、Read:此方法实现将数据从流中读出。函数原形为:
Function Read(var Buffer;Count:Longint):Longint;virtual;abstract;
参数Buffer为数据读出时放置的缓冲区,Count为需要读出的数据的字节数,该方法返回值为实际读出的字节数,它可以小于或等于Count中指定的值。
2、Write:此方法实现将数据写入流中。函数原形为:
Function Write(var Buffer;Count:Longint):Longint;virtual;abstract;
参数Buffer为将要写入流中的数据的缓冲区,Count为数据的长度字节数,该方法返回值为实际写入流中的字节数。
3、Seek:此方法实现流中读取指针的移动。函数原形为:
Function Seek(Offset:Longint;Origint:Word):Longint;virtual;abstract;
参数Offset为偏移字节数,参数Origint指出Offset的实际意义,其可能的取值如下:
soFromBeginning:Offset为移动后指针距离数据开始的位置。此时Offset必须大于或者等于零。
soFromCurrent:Offset为移动后指针与当前指针的相对位置。
soFromEnd:Offset为移动后指针距离数据结束的位置。此时Offset必须小于或者等于零。该方法返回值为移动后指针的位置。
4、Setsize:此方法实现改变数据的大小。函数原形为:
Function Setsize(NewSize:Longint);virtual; }
//将指针偏移量放到文件头部
fs.Seek(0, soFromBeginning);
//读取DOS头信息
fs.Read(DOSHEADER, sizeof(DOSHEADER));
//DOS MZ header 又命名为 IMAGE_DOS_HEADER.。其中只有两个域比较重要:
//e_magic 包含字符串"MZ",e_lfanew 包含PE header在文件中的偏移量。
//将指针移到PE header在文件中的偏移量
fs.Seek(DOSHEADER._lfanew, soFromBeginning);
//读取PE header头信息
fs.Read(PEHEADER, sizeOf(PEHEADER));
//PEHEADER.FileHeader.NumberOfSections:文件的节数目。如果我们要在文件中增加或删除一个节,就需要修改这个值。
//将指针移到节表在当前位置的相对偏移量
fs.Seek(sizeOf(SectionHeader) *
(PEHEADER.FileHeader.NumberOfSections - 1), soFromCurrent);
//读取节表的信息
fs.Read(SectionHeader, sizeof(IMAGE_SECTION_HEADER));
//节名长不超过8字节。记住节名仅仅是个标记而已,我们选择任何名字甚至空着也行
{ MySectionHeader.Name[0] := ord('F');
MySectionHeader.Name[1] := ord('i');
MySectionHeader.Name[2] := ord('7');
MySectionHeader.Name[3] := ord('k');
MySectionHeader.Name[4] := ord('e');
MySectionHeader.Name[5] := 0;
MySectionHeader.Name[6] := 0;
MySectionHeader.Name[7] := 0; }
for i:=0 to 7 do
begin
MySectionHeader.Name[i] :=0;
if i<length(MySection) then
MySectionHeader.Name[i] :=Ord(MySection[i+1]);
end;
//VirtualAddress 本节的RVA(相对虚拟地址)。PE装载器将节映射至内存时会读取本值,因此如果域值是1000h,
//而PE文件装在地址400000h处,那么本节就被载到401000h。
//SizeOfImage 内存中整个PE映像体的尺寸。它是所有头和节经过节对齐处理后的大小。
MySectionHeader.VirtualAddress := PEHEADER.OptionalHeader.SizeOfImage;
//节的大小 $200十六进制 = 512字节 最好大于 512 不然可能会出错
//MySectionHeader.Misc.VirtualSize := $200;
MySectionHeader.Misc.VirtualSize := SecSize; //StrToInt(IntToHex(SecSize,sizeof(SecSize)));
//SizeOfRawData 经过文件对齐处理后节尺寸,PE装载器提取本域值了解需映射入内存的节字节数。
//(译者注: 假设一个文件的文件对齐尺寸是0x200,如果前面的 VirtualSize域指示本节长度是0x388字节,
//则本域值为0x400,表示本节是0x400字节长)。
//FileAlignment 文件中节对齐的粒度。例如,如果该值是(200h),,那么每节的起始地址必须是512的倍数。
//若第一节从文件偏移量200h开始且大小是10个字节,则下一节必定位于偏移量400h:
//即使偏移量512和1024之间还有很多空间没被使用/定义。
MySectionHeader.SizeOfRawData := (MySectionHeader.VirtualAddress div
PEHEADER.OptionalHeader.FileAlignment + 1) * PEHEADER.OptionalHeader.FileAlignment -
PEHEADER.OptionalHeader.SizeOfImage;
//这是节基于文件的偏移量,PE装载器通过本域值找到节数据在文件中的位置。
MySectionHeader.PointerToRawData :=
SectionHeader.SizeOfRawData + SectionHeader.PointerToRawData;
//包含标记以指示节属性,比如节是否含有可执行代码、初始化数据、未初始数据,是否可写、可读等。
MySectionHeader.Characteristics := $E0000020;
{PE装载器的工作:
1.读取 IMAGE_FILE_HEADER 的 NumberOfSections域,知道文件的节数目。
2.SizeOfHeaders 域值作为节表的文件偏移量,并以此定位节表。
3.遍历整个结构数组检查各成员值。
4.对于每个结构,我们读取PointerToRawData域值并定位到该文件偏移量。然后再读取SizeOfRawData域值来决定
映射内存的字节数。将VirtualAddress域值加上ImageBase域值等于节起始的虚拟地址。然后就准备把节映射进内存,
并根据Characteristics域值设置属性。
5.遍历整个数组,直至所有节都已处理完毕。
注意我们并没有使用节名: 这其实并不重要。}
//节表数量加一
Inc(PEHEADER.FileHeader.NumberOfSections);
//写入新加入的节表
fs.Write(MySectionHeader, sizeOf(MySectionHeader));
//将指针移到PE header在文件中的偏移量
fs.Seek(DOSHEADER._lfanew, soFromBeginning);
//PE装载器准备运行的PE文件的第一个指令的RVA。若您要改变整个执行的流程,
//可以将该值指定到新的RVA,这样新RVA处的指令首先被执行。
AddressOfEntryPoint := PEHEADER.OptionalHeader.AddressOfEntryPoint;
//将入口地址指定到新加节表的RVA(相对虚拟地址)
PEHEADER.OptionalHeader.AddressOfEntryPoint :=
MySectionHeader.VirtualAddress;
//win32子系统版本。
PEHEADER.OptionalHeader.MajorLinkerVersion := 7;
PEHEADER.OptionalHeader.MinorLinkerVersion := 0;
AddressOfEntryPoint := AddressOfEntryPoint +
PEHEADER.OptionalHeader.ImageBase;
asm //这里说明一下,这是嵌入的汇编代码,寄存器—CPU暂时储存数据的东西,比内存更快,以提高效率
PUSHAD
LEA eax, OEPCODE //将OEPCODE的地址交给寄存器
ADD eax, JMPOFF //添加JMPOFF值给寄存器
MOV edx, AddressOfEntryPoint //转移指令,相当于付值语句,左边给右边
MOV DWORD ptr [eax], edx //同上
POPAD
end;
//更改内存中整个PE映像体的尺寸
PEHEADER.OptionalHeader.SizeOfImage :=
PEHEADER.OptionalHeader.SizeOfImage + MySectionHeader.Misc.VirtualSize;
//写入PEHEADER信息
fs.Write(PEHEADER, sizeof(PEHEADER));
//移动指针到文件尾部
fs.Seek(fs.Size, soFromBeginning);
//写入花指令数据
fs.Write(OEPCODE, MySectionHeader.Misc.VirtualSize);
finally
fs.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if OpenDialog1.Execute then
edit1.Text :=OpenDialog1.FileName;
end;
procedure TForm1.obtain;
var
DOSHEADER: IMAGE_DOS_HEADER;
PEHEADER: IMAGE_NT_HEADERS;
fs: TFileStream;
begin
fs := TFileStream.Create(Edit1.Text, fmOpenReadWrite +
fmShareDenyWrite);
try
fs.Seek(0, soFromBeginning);
fs.Read(DOSHEADER, sizeof(DOSHEADER));
fs.Seek(DOSHEADER._lfanew, soFromBeginning);
fs.Read(PEHEADER, sizeOf(PEHEADER));
FImageBase := PEHEADER.OptionalHeader.ImageBase;
finally
fs.Free;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
FName,SecName:string;
SecSize:DWord;
begin
if trim(Edit1.Text) = '' then
begin
Messagebox(Handle, '请选择你要伪装的程序!', '提示', MB_OK + MB_ICONSTOP);
Exit;
end;
FName :=trim(Edit1.Text);
SecName :=trim(Edit2.Text);
if SecName='' then SecName:='.hnxyy';
SecSize :=512;
if trim(edit3.Text)<>'' then
begin
SecSize :=strtoint(trim(Edit3.Text));
if SecSize<512 then SecSize :=512;
end;
if CheckBox1.Checked then
CopyFile(PChar(FName),PChar(Fname+'.bak'),False);
SetOepCode;
AddSection(FName,SecName,SecSize);
Messagebox(Handle, '伪装成功!', '提示', MB_OK + MB_ICONINFORMATION);
end;
procedure TForm1.SetOepCode;
begin
OEPCODE :=OEPCODEARRAY[RadioGroup1.ItemIndex];
JMPOFF :=JMPOFFARRAY[RadioGroup1.ItemIndex];
end;
procedure TForm1.Label4Click(Sender: TObject);
begin
ShellExecute(Handle, 'open','http://forum.wrsky.com', '', '', SW_SHOWNORMAL);
end;
procedure TForm1.Edit3KeyPress(Sender: TObject; var Key: Char);
begin
if not (key in ['0'..'9',#8,#13]) then
begin
key :=#0;
end;
end;
end.
//VC++6外衣 1
OEPCODEFIVE: THEAD =
($55, $8B, $EC, $6A, $FF, $68, $00, $00, $00, $00, $68, $00, $00, $00, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $83, $EC, $68,
$53, $56, $57, $58, $58, $58, $83, $C4, $68, $58, $67, $64, $A3, $00, $00, $58,
$58, $58, $58, $8B, $E8, $E9, $07, $B9, $FE, $FF, $00, $00, $00, $00, $00, $00);
//VC++6外衣 2
OEPCODEFIVE: THEAD =
($55, $8B, $EC, $6A, $FF, $68, $00, $00, $00, $00, $68, $00, $00, $00, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $83, $EC, $68,
$53, $56, $57, $58, $58, $58, $83, $C4, $68, $58, $67, $64, $A3, $00, $00, $58,
$58, $58, $58, $8B, $E8, $B8, $00, $10, $40, $00, $FF, $E0, $90, $00, $00, $00);
1.直接将入口地址赋给寄存器eax,然后jmp eax
0046902A B8 304A4500 mov eax,Project1.00454A30
0046902F FFE0 jmp eax
00469031 90 nop
2. 直接跳转到入口地址
00469124 - E9 07B9FEFF jmp Project1.00454A30
两种效果实际上是一样的,但我们为了方便修改花指令跳转到原来的入口地址,通常取得原
pe header的AddressOfEntryPoint,然后给寄存器eax保存改值,所以第二种方法就不太方便,
所以一般采用第一种方法,JMPOFF为花指令代码到跳转指令的偏移,如对Visual C++的花指令
JMPOFF=54,其后免跟的是原入口地址,可以随便填写,程序加花指令是会自动修改,一般可以
默认设为00104000(即00401000).
通过汇编修改花指令跳转原入口地址的语句:
asm //这里说明一下,这是嵌入的汇编代码,寄存器—CPU暂时储存数据的东西,比内存更快,以提高效率
PUSHAD
LEA eax, OEPCODE //将OEPCODE的地址交给寄存器
ADD eax, JMPOFF //添加JMPOFF值给寄存器
MOV edx, AddressOfEntryPoint //转移指令,相当于付值语句,左边给右边
MOV DWORD ptr [eax], edx //同上
POPAD
end;
}
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ShellAPI;
type
TForm1 = class(TForm)
Label1: TLabel;
Edit1: TEdit;
Button1: TButton;
RadioGroup1: TRadioGroup;
Label2: TLabel;
Edit2: TEdit;
Label3: TLabel;
Edit3: TEdit;
CheckBox1: TCheckBox;
Button2: TButton;
Label5: TLabel;
OpenDialog1: TOpenDialog;
Label4: TLabel;
procedure Button1Click(Sender: TObject);
procedure obtain;
procedure Button2Click(Sender: TObject);
procedure Label4Click(Sender: TObject);
procedure Edit3KeyPress(Sender: TObject; var Key: Char);
private
{ Private declarations }
FImageBase: DWORD;
procedure SetOepCode;
public
{ Public declarations }
end;
THEAD = array[0..63] of byte;
var
Form1: TForm1;
const
{MYSECTION = 'Fi7ke'; //添加的节名,自定义
JMPOFF = 43; //花指令的机器码,Ollydbg加载后随便取
//Microsoft Visual C++
OEPCODE: THEAD =
($55, $8B, $EC, $6A, $FF, $68, $2A, $2C, $0A, $00, $68, $38,
$90, $0D, $00, $64, $A1, $00, $00, $00, $00, $50, $64, $89,
$25, $00, $00, $00, $00, $58, $64, $A3, $00, $00, $00, $00,
$58, $58, $58, $58, $8B, $E8, $B8, $00, $10, $40, $00, $FF,
$E0, $90, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00); }
//Nothing found * one
OEPCODEONE: THEAD =
($55, $8B, $EC, $83, $C4, $F4, $83, $C4, $0C, $B8, $00, $10, $40, $00, $50, $C3,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00);
//Nothing found * two
OEPCODETWO: THEAD =
($55, $8B, $EC, $41, $52, $90, $5A, $49, $5D, $41, $B8, $00, $10, $40, $00, $FF,
$E0, $90, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00);
//VC++外衣
OEPCODETHREE: THEAD =
($55, $8B, $EC, $6A, $FF, $68, $2A, $2C, $0A, $00, $68, $38, $90, $0D, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $58, $64, $A3,
$00, $00, $00, $00, $58, $58, $58, $58, $8B, $E8, $B8, $00, $10, $40, $00, $FF,
$E0, $90, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00);
//VC++5外衣
OEPCODEFOUR: THEAD =
($55, $8B, $EC, $6A, $FF, $68, $48, $54, $41, $00, $68, $A8, $21, $40, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $83, $C4, $94,
$53, $56, $57, $00, $00, $B8, $00, $10, $40, $00, $FF, $E0, $90, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00);
//VC++6外衣
OEPCODEFIVE: THEAD =
($55, $8B, $EC, $6A, $FF, $68, $00, $00, $00, $00, $68, $00, $00, $00, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $83, $EC, $68,
$53, $56, $57, $58, $58, $58, $83, $C4, $68, $58, $67, $64, $A3, $00, $00, $58,
$58, $58, $58, $8B, $E8, $B8, $00, $10, $40, $00, $FF, $E0, $90, $00, $00, $00);
//C外衣
OEPCODESIX: THEAD =
($55, $8B, $EC, $6A, $FF, $68, $11, $11, $11, $00, $68, $22, $22, $22, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $58, $64, $A3,
$00, $00, $00, $00, $58, $58, $58, $58, $8B, $E8, $B8, $00, $10, $40, $00, $FF,
$E0, $90, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00);
OepCount = 6;
//OEPCODEARRAY :array[0..OepCount-1,0..63] of byte=(
//OEPCODEARRAY :array[0..OepCount-1] of array[0..63] of byte=(
OEPCODEARRAY :array[0..OepCount-1] of THEAD=(
($55, $8B, $EC, $83, $C4, $F4, $83, $C4, $0C, $B8, $00, $10, $40, $00, $50, $C3,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00), //Nothing found * one
($55, $8B, $EC, $6A, $FF, $68, $2A, $2C, $0A, $00, $68, $38, $90, $0D, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $58, $64, $A3,
$00, $00, $00, $00, $58, $58, $58, $58, $8B, $E8, $B8, $00, $10, $40, $00, $FF,
$E0, $90, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00), //VC++外衣
($55, $8B, $EC, $6A, $FF, $68, $48, $54, $41, $00, $68, $A8, $21, $40, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $83, $C4, $94,
$53, $56, $57, $00, $00, $B8, $00, $10, $40, $00, $FF, $E0, $90, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00), //VC++5外衣
($55, $8B, $EC, $6A, $FF, $68, $00, $00, $00, $00, $68, $00, $00, $00, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $83, $EC, $68,
$53, $56, $57, $58, $58, $58, $83, $C4, $68, $58, $67, $64, $A3, $00, $00, $58,
$58, $58, $58, $8B, $E8, $B8, $00, $10, $40, $00, $FF, $E0, $90, $00, $00, $00), //VC++6外衣
($55, $8B, $EC, $6A, $FF, $68, $11, $11, $11, $00, $68, $22, $22, $22, $00, $64,
$A1, $00, $00, $00, $00, $50, $64, $89, $25, $00, $00, $00, $00, $58, $64, $A3,
$00, $00, $00, $00, $58, $58, $58, $58, $8B, $E8, $B8, $00, $10, $40, $00, $FF,
$E0, $90, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00), //C外衣
($55, $8B, $EC, $41, $52, $90, $5A, $49, $5D, $41, $B8, $00, $10, $40, $00, $FF,
$E0, $90, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00) //Nothing found * two
);
JMPOFFARRAY :array[0..OepCount-1] of integer=(10,43,38,54,43,11);
{Nothing found * ONE:
Borland Delphi 6.0 - 7.0
00469022 0055 8B add byte ptr ss:[ebp-75],dl
00469025 EC in al,dx
00469026 83C4 F4 add esp,-0C
00469029 83C4 0C add esp,0C
0046902C B8 304A4500 mov eax,Project1.00454A30
00469031 50 push eax
00469032 C3 retn
Nothing found * TWO
00454A72 55 push ebp
00454A73 8BEC mov ebp,esp
00454A75 41 inc ecx
00454A76 52 push edx
00454A77 90 nop
00454A78 5A pop edx
00454A79 49 dec ecx
00454A7A 5D pop ebp
00454A7B 41 inc ecx
0046902A B8 304A4500 mov eax,Project1.00454A30
0046902F FFE0 jmp eax
00469031 90 nop
C外衣:
00454A6C 55 push ebp
00454A6D 8BEC mov ebp,esp
00454A6F 6A FF push -1
00454A71 68 11111100 push 111111
00454A76 68 22222200 push 222222
00454A7B 64:A1 00000>mov eax,dword ptr fs:[0]
00454A81 50 push eax
00454A82 64:8925 000>mov dword ptr fs:[0],esp
00454A89 58 pop eax
00454A8A 64:A3 00000>mov dword ptr fs:[0],eax
00454A90 58 pop eax
00454A91 58 pop eax
00454A92 58 pop eax
00454A93 58 pop eax
00454A94 8BE8 mov ebp,eax
00454A96 - E9 65F5CAFF jmp 00104000
VC++5外衣:
0046905F P> 55 push ebp
00469060 8BEC mov ebp,esp
00469062 6A FF push -1
00469064 68 48544100 push Project1.00415448
00469069 68 A8214000 push Project1.004021A8
0046906E 64:A1 0000000>mov eax,dword ptr fs:[0]
00469074 50 push eax
00469075 64:8925 00000>mov dword ptr fs:[0],esp
0046907C 83C4 94 add esp,-6C
0046907F 53 push ebx
00469080 56 push esi
00469081 57 push edi
00469082 0000 add byte ptr ds:[eax],al
0046902A B8 304A4500 mov eax,Project1.00454A30
0046902F FFE0 jmp eax
00469031 90 nop
VC++外衣:
00469000 P> 55 push ebp
00469001 8BEC mov ebp,esp
00469003 6A FF push -1
00469005 68 2A2C0A00 push 0A2C2A
0046900A 68 38900D00 push 0D9038
0046900F 64:A1 0000000>mov eax,dword ptr fs:[0]
00469015 50 push eax
00469016 64:8925 00000>mov dword ptr fs:[0],esp
0046901D 58 pop eax
0046901E 64:A3 0000000>mov dword ptr fs:[0],eax
00469024 58 pop eax
00469025 58 pop eax
00469026 58 pop eax
00469027 58 pop eax
00469028 8BE8 mov ebp,eax
0046902A B8 304A4500 mov eax,Project1.00454A30
0046902F FFE0 jmp eax
00469031 90 nop
VC++6外衣:
004690EF P> 55 push ebp
004690F0 8BEC mov ebp,esp
004690F2 6A FF push -1
004690F4 68 00000000 push 0
004690F9 68 00000000 push 0
004690FE 64:A1 0000000>mov eax,dword ptr fs:[0]
00469104 50 push eax
00469105 64:8925 00000>mov dword ptr fs:[0],esp
0046910C 83EC 68 sub esp,68
0046910F 53 push ebx
00469110 56 push esi
00469111 57 push edi
00469112 58 pop eax
00469113 58 pop eax
00469114 58 pop eax
00469115 83C4 68 add esp,68
00469118 58 pop eax
00469119 67:64:A3 0000 mov dword ptr fs:[0],eax
0046911E 58 pop eax
0046911F 58 pop eax
00469120 58 pop eax
00469121 58 pop eax
00469122 8BE8 mov ebp,eax
0046902A B8 304A4500 mov eax,Project1.00454A30
0046902F FFE0 jmp eax
00469031 90 nop
}
function IntToHex(Int: Int64; IntSize: Byte): String;
procedure AddSection(FName,MySection: string;SecSize:DWord);
implementation
{$R *.dfm}
var
OEPCODE: THEAD;
JMPOFF :integer;
function IntToHex(Int: Int64; IntSize: Byte): String;
const
HexChars: array[0..15] of Char = ('0', '1', '2', '3', '4', '5','6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
var
n: Byte;
begin
Result := '';
for n := 0 to IntSize - 1 do
begin
Result := HexChars[Int and $F] + Result;
Int := Int shr $4;
end;
end;
procedure AddSection(FName,MySection: string;SecSize:DWord);
var
DOSHEADER: IMAGE_DOS_HEADER; //DOS MZ header
PEHEADER: IMAGE_NT_HEADERS; //PE header
SectionHeader: IMAGE_SECTION_HEADER; //节表
MySectionHeader: IMAGE_SECTION_HEADER; //自定义节表
fs: TFileStream;
AddressOfEntryPoint: DWORD; //入口点
i:integer;
begin
fs := TFileStream.Create(FName, fmOpenReadWrite +
fmShareDenyWrite);
try
{Tstream中定义的虚方法有四个:
1、Read:此方法实现将数据从流中读出。函数原形为:
Function Read(var Buffer;Count:Longint):Longint;virtual;abstract;
参数Buffer为数据读出时放置的缓冲区,Count为需要读出的数据的字节数,该方法返回值为实际读出的字节数,它可以小于或等于Count中指定的值。
2、Write:此方法实现将数据写入流中。函数原形为:
Function Write(var Buffer;Count:Longint):Longint;virtual;abstract;
参数Buffer为将要写入流中的数据的缓冲区,Count为数据的长度字节数,该方法返回值为实际写入流中的字节数。
3、Seek:此方法实现流中读取指针的移动。函数原形为:
Function Seek(Offset:Longint;Origint:Word):Longint;virtual;abstract;
参数Offset为偏移字节数,参数Origint指出Offset的实际意义,其可能的取值如下:
soFromBeginning:Offset为移动后指针距离数据开始的位置。此时Offset必须大于或者等于零。
soFromCurrent:Offset为移动后指针与当前指针的相对位置。
soFromEnd:Offset为移动后指针距离数据结束的位置。此时Offset必须小于或者等于零。该方法返回值为移动后指针的位置。
4、Setsize:此方法实现改变数据的大小。函数原形为:
Function Setsize(NewSize:Longint);virtual; }
//将指针偏移量放到文件头部
fs.Seek(0, soFromBeginning);
//读取DOS头信息
fs.Read(DOSHEADER, sizeof(DOSHEADER));
//DOS MZ header 又命名为 IMAGE_DOS_HEADER.。其中只有两个域比较重要:
//e_magic 包含字符串"MZ",e_lfanew 包含PE header在文件中的偏移量。
//将指针移到PE header在文件中的偏移量
fs.Seek(DOSHEADER._lfanew, soFromBeginning);
//读取PE header头信息
fs.Read(PEHEADER, sizeOf(PEHEADER));
//PEHEADER.FileHeader.NumberOfSections:文件的节数目。如果我们要在文件中增加或删除一个节,就需要修改这个值。
//将指针移到节表在当前位置的相对偏移量
fs.Seek(sizeOf(SectionHeader) *
(PEHEADER.FileHeader.NumberOfSections - 1), soFromCurrent);
//读取节表的信息
fs.Read(SectionHeader, sizeof(IMAGE_SECTION_HEADER));
//节名长不超过8字节。记住节名仅仅是个标记而已,我们选择任何名字甚至空着也行
{ MySectionHeader.Name[0] := ord('F');
MySectionHeader.Name[1] := ord('i');
MySectionHeader.Name[2] := ord('7');
MySectionHeader.Name[3] := ord('k');
MySectionHeader.Name[4] := ord('e');
MySectionHeader.Name[5] := 0;
MySectionHeader.Name[6] := 0;
MySectionHeader.Name[7] := 0; }
for i:=0 to 7 do
begin
MySectionHeader.Name[i] :=0;
if i<length(MySection) then
MySectionHeader.Name[i] :=Ord(MySection[i+1]);
end;
//VirtualAddress 本节的RVA(相对虚拟地址)。PE装载器将节映射至内存时会读取本值,因此如果域值是1000h,
//而PE文件装在地址400000h处,那么本节就被载到401000h。
//SizeOfImage 内存中整个PE映像体的尺寸。它是所有头和节经过节对齐处理后的大小。
MySectionHeader.VirtualAddress := PEHEADER.OptionalHeader.SizeOfImage;
//节的大小 $200十六进制 = 512字节 最好大于 512 不然可能会出错
//MySectionHeader.Misc.VirtualSize := $200;
MySectionHeader.Misc.VirtualSize := SecSize; //StrToInt(IntToHex(SecSize,sizeof(SecSize)));
//SizeOfRawData 经过文件对齐处理后节尺寸,PE装载器提取本域值了解需映射入内存的节字节数。
//(译者注: 假设一个文件的文件对齐尺寸是0x200,如果前面的 VirtualSize域指示本节长度是0x388字节,
//则本域值为0x400,表示本节是0x400字节长)。
//FileAlignment 文件中节对齐的粒度。例如,如果该值是(200h),,那么每节的起始地址必须是512的倍数。
//若第一节从文件偏移量200h开始且大小是10个字节,则下一节必定位于偏移量400h:
//即使偏移量512和1024之间还有很多空间没被使用/定义。
MySectionHeader.SizeOfRawData := (MySectionHeader.VirtualAddress div
PEHEADER.OptionalHeader.FileAlignment + 1) * PEHEADER.OptionalHeader.FileAlignment -
PEHEADER.OptionalHeader.SizeOfImage;
//这是节基于文件的偏移量,PE装载器通过本域值找到节数据在文件中的位置。
MySectionHeader.PointerToRawData :=
SectionHeader.SizeOfRawData + SectionHeader.PointerToRawData;
//包含标记以指示节属性,比如节是否含有可执行代码、初始化数据、未初始数据,是否可写、可读等。
MySectionHeader.Characteristics := $E0000020;
{PE装载器的工作:
1.读取 IMAGE_FILE_HEADER 的 NumberOfSections域,知道文件的节数目。
2.SizeOfHeaders 域值作为节表的文件偏移量,并以此定位节表。
3.遍历整个结构数组检查各成员值。
4.对于每个结构,我们读取PointerToRawData域值并定位到该文件偏移量。然后再读取SizeOfRawData域值来决定
映射内存的字节数。将VirtualAddress域值加上ImageBase域值等于节起始的虚拟地址。然后就准备把节映射进内存,
并根据Characteristics域值设置属性。
5.遍历整个数组,直至所有节都已处理完毕。
注意我们并没有使用节名: 这其实并不重要。}
//节表数量加一
Inc(PEHEADER.FileHeader.NumberOfSections);
//写入新加入的节表
fs.Write(MySectionHeader, sizeOf(MySectionHeader));
//将指针移到PE header在文件中的偏移量
fs.Seek(DOSHEADER._lfanew, soFromBeginning);
//PE装载器准备运行的PE文件的第一个指令的RVA。若您要改变整个执行的流程,
//可以将该值指定到新的RVA,这样新RVA处的指令首先被执行。
AddressOfEntryPoint := PEHEADER.OptionalHeader.AddressOfEntryPoint;
//将入口地址指定到新加节表的RVA(相对虚拟地址)
PEHEADER.OptionalHeader.AddressOfEntryPoint :=
MySectionHeader.VirtualAddress;
//win32子系统版本。
PEHEADER.OptionalHeader.MajorLinkerVersion := 7;
PEHEADER.OptionalHeader.MinorLinkerVersion := 0;
AddressOfEntryPoint := AddressOfEntryPoint +
PEHEADER.OptionalHeader.ImageBase;
asm //这里说明一下,这是嵌入的汇编代码,寄存器—CPU暂时储存数据的东西,比内存更快,以提高效率
PUSHAD
LEA eax, OEPCODE //将OEPCODE的地址交给寄存器
ADD eax, JMPOFF //添加JMPOFF值给寄存器
MOV edx, AddressOfEntryPoint //转移指令,相当于付值语句,左边给右边
MOV DWORD ptr [eax], edx //同上
POPAD
end;
//更改内存中整个PE映像体的尺寸
PEHEADER.OptionalHeader.SizeOfImage :=
PEHEADER.OptionalHeader.SizeOfImage + MySectionHeader.Misc.VirtualSize;
//写入PEHEADER信息
fs.Write(PEHEADER, sizeof(PEHEADER));
//移动指针到文件尾部
fs.Seek(fs.Size, soFromBeginning);
//写入花指令数据
fs.Write(OEPCODE, MySectionHeader.Misc.VirtualSize);
finally
fs.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if OpenDialog1.Execute then
edit1.Text :=OpenDialog1.FileName;
end;
procedure TForm1.obtain;
var
DOSHEADER: IMAGE_DOS_HEADER;
PEHEADER: IMAGE_NT_HEADERS;
fs: TFileStream;
begin
fs := TFileStream.Create(Edit1.Text, fmOpenReadWrite +
fmShareDenyWrite);
try
fs.Seek(0, soFromBeginning);
fs.Read(DOSHEADER, sizeof(DOSHEADER));
fs.Seek(DOSHEADER._lfanew, soFromBeginning);
fs.Read(PEHEADER, sizeOf(PEHEADER));
FImageBase := PEHEADER.OptionalHeader.ImageBase;
finally
fs.Free;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
FName,SecName:string;
SecSize:DWord;
begin
if trim(Edit1.Text) = '' then
begin
Messagebox(Handle, '请选择你要伪装的程序!', '提示', MB_OK + MB_ICONSTOP);
Exit;
end;
FName :=trim(Edit1.Text);
SecName :=trim(Edit2.Text);
if SecName='' then SecName:='.hnxyy';
SecSize :=512;
if trim(edit3.Text)<>'' then
begin
SecSize :=strtoint(trim(Edit3.Text));
if SecSize<512 then SecSize :=512;
end;
if CheckBox1.Checked then
CopyFile(PChar(FName),PChar(Fname+'.bak'),False);
SetOepCode;
AddSection(FName,SecName,SecSize);
Messagebox(Handle, '伪装成功!', '提示', MB_OK + MB_ICONINFORMATION);
end;
procedure TForm1.SetOepCode;
begin
OEPCODE :=OEPCODEARRAY[RadioGroup1.ItemIndex];
JMPOFF :=JMPOFFARRAY[RadioGroup1.ItemIndex];
end;
procedure TForm1.Label4Click(Sender: TObject);
begin
ShellExecute(Handle, 'open','http://forum.wrsky.com', '', '', SW_SHOWNORMAL);
end;
procedure TForm1.Edit3KeyPress(Sender: TObject; var Key: Char);
begin
if not (key in ['0'..'9',#8,#13]) then
begin
key :=#0;
end;
end;
end.
最新评论