说明:以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,然后jmpeax
0046902AB8304A4500moveax,Project1.00454A30
0046902FFFE0jmpeax
0046903190nop
2.直接跳转到入口地址
00469124-E907B9FEFFjmpProject1.00454A30
两种效果实际上是一样的,但我们为了方便修改花指令跳转到原来的入口地址,通常取得原
peheader的AddressOfEntryPoint,然后给寄存器eax保存改值,所以第二种方法就不太方便,
所以一般采用第一种方法,JMPOFF为花指令代码到跳转指令的偏移,如对VisualC++的花指令
JMPOFF=54,其后免跟的是原入口地址,可以随便填写,程序加花指令是会自动修改,一般可以
默认设为00104000(即00401000).
通过汇编修改花指令跳转原入口地址的语句:
asm//这里说明一下,这是嵌入的汇编代码,寄存器—CPU暂时储存数据的东西,比内存更快,以提高效率
PUSHAD
LEAeax,OEPCODE//将OEPCODE的地址交给寄存器
ADDeax,JMPOFF//添加JMPOFF值给寄存器
MOVedx,AddressOfEntryPoint//转移指令,相当于付值语句,左边给右边
MOVDWORDptr[eax],edx//同上
POPAD
end;
}
unitUnit1;
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;
procedureButton1Click(Sender:TObject);
procedureobtain;
procedureButton2Click(Sender:TObject);
procedureLabel4Click(Sender:TObject);
procedureEdit3KeyPress(Sender:TObject;varKey:Char);
private
{Privatedeclarations}
FImageBase:DWORD;
procedureSetOepCode;
public
{Publicdeclarations}
end;
THEAD=array[0..63]ofbyte;
var
Form1:TForm1;
const
{MYSECTION='Fi7ke';//添加的节名,自定义
JMPOFF=43;//花指令的机器码,Ollydbg加载后随便取
//MicrosoftVisualC++
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);}
//Nothingfound*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);
//Nothingfound*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]ofbyte=(
//OEPCODEARRAY:array[0..OepCount-1]ofarray[0..63]ofbyte=(
OEPCODEARRAY:array[0..OepCount-1]ofTHEAD=(
($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),//Nothingfound*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)//Nothingfound*two
);
JMPOFFARRAY:array[0..OepCount-1]ofinteger=(10,43,38,54,43,11);
{Nothingfound*ONE:
BorlandDelphi6.0-7.0
0046902200558Baddbyteptrss:[ebp-75],dl
00469025ECinal,dx
0046902683C4F4addesp,-0C
0046902983C40Caddesp,0C
0046902CB8304A4500moveax,Project1.00454A30
0046903150pusheax
00469032C3retn
Nothingfound*TWO
00454A7255pushebp
00454A738BECmovebp,esp
00454A7541incecx
00454A7652pushedx
00454A7790nop
00454A785Apopedx
00454A7949dececx
00454A7A5Dpopebp
00454A7B41incecx
0046902AB8304A4500moveax,Project1.00454A30
0046902FFFE0jmpeax
0046903190nop
C外衣:
00454A6C55pushebp
00454A6D8BECmovebp,esp
00454A6F6AFFpush-1
00454A716811111100push111111
00454A766822222200push222222
00454A7B64:A100000>moveax,dwordptrfs:[0]
00454A8150pusheax
00454A8264:8925000>movdwordptrfs:[0],esp
00454A8958popeax
00454A8A64:A300000>movdwordptrfs:[0],eax
00454A9058popeax
00454A9158popeax
00454A9258popeax
00454A9358popeax
00454A948BE8movebp,eax
00454A96-E965F5CAFFjmp00104000
VC++5外衣:
0046905FP>55pushebp
004690608BECmovebp,esp
004690626AFFpush-1
004690646848544100pushProject1.00415448
0046906968A8214000pushProject1.004021A8
0046906E64:A10000000>moveax,dwordptrfs:[0]
0046907450pusheax
0046907564:892500000>movdwordptrfs:[0],esp
0046907C83C494addesp,-6C
0046907F53pushebx
0046908056pushesi
0046908157pushedi
004690820000addbyteptrds:[eax],al
0046902AB8304A4500moveax,Project1.00454A30
0046902FFFE0jmpeax
0046903190nop
VC++外衣:
00469000P>55pushebp
004690018BECmovebp,esp
004690036AFFpush-1
00469005682A2C0A00push0A2C2A
0046900A6838900D00push0D9038
0046900F64:A10000000>moveax,dwordptrfs:[0]
0046901550pusheax
0046901664:892500000>movdwordptrfs:[0],esp
0046901D58popeax
0046901E64:A30000000>movdwordptrfs:[0],eax
0046902458popeax
0046902558popeax
0046902658popeax
0046902758popeax
004690288BE8movebp,eax
0046902AB8304A4500moveax,Project1.00454A30
0046902FFFE0jmpeax
0046903190nop
VC++6外衣:
004690EFP>55pushebp
004690F08BECmovebp,esp
004690F26AFFpush-1
004690F46800000000push0
004690F96800000000push0
004690FE64:A10000000>moveax,dwordptrfs:[0]
0046910450pusheax
0046910564:892500000>movdwordptrfs:[0],esp
0046910C83EC68subesp,68
0046910F53pushebx
0046911056pushesi
0046911157pushedi
0046911258popeax
0046911358popeax
0046911458popeax
0046911583C468addesp,68
0046911858popeax
0046911967:64:A30000movdwordptrfs:[0],eax
0046911E58popeax
0046911F58popeax
0046912058popeax
0046912158popeax
004691228BE8movebp,eax
0046902AB8304A4500moveax,Project1.00454A30
0046902FFFE0jmpeax
0046903190nop
}
functionIntToHex(Int:Int64;IntSize:Byte):String;
procedureAddSection(FName,MySection:string;SecSize:DWord);
implementation
{$R*.dfm}
var
OEPCODE:THEAD;
JMPOFF:integer;
functionIntToHex(Int:Int64;IntSize:Byte):String;
const
HexChars:array[0..15]ofChar=('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f');
var
n:Byte;
begin
Result:='';
forn:=0toIntSize-1do
begin
Result:=HexChars[Intand$F]+Result;
Int:=Intshr$4;
end;
end;
procedureAddSection(FName,MySection:string;SecSize:DWord);
var
DOSHEADER:IMAGE_DOS_HEADER;//DOSMZheader
PEHEADER:IMAGE_NT_HEADERS;//PEheader
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:此方法实现将数据从流中读出。函数原形为:
FunctionRead(varBuffer;Count:Longint):Longint;virtual;abstract;
参数Buffer为数据读出时放置的缓冲区,Count为需要读出的数据的字节数,该方法返回值为实际读出的字节数,它可以小于或等于Count中指定的值。
2、Write:此方法实现将数据写入流中。函数原形为:
FunctionWrite(varBuffer;Count:Longint):Longint;virtual;abstract;
参数Buffer为将要写入流中的数据的缓冲区,Count为数据的长度字节数,该方法返回值为实际写入流中的字节数。
3、Seek:此方法实现流中读取指针的移动。函数原形为:
FunctionSeek(Offset:Longint;Origint:Word):Longint;virtual;abstract;
参数Offset为偏移字节数,参数Origint指出Offset的实际意义,其可能的取值如下:
soFromBeginning:Offset为移动后指针距离数据开始的位置。此时Offset必须大于或者等于零。
soFromCurrent:Offset为移动后指针与当前指针的相对位置。
soFromEnd:Offset为移动后指针距离数据结束的位置。此时Offset必须小于或者等于零。该方法返回值为移动后指针的位置。
4、Setsize:此方法实现改变数据的大小。函数原形为:
FunctionSetsize(NewSize:Longint);virtual;}
//将指针偏移量放到文件头部
fs.Seek(0,soFromBeginning);
//读取DOS头信息
fs.Read(DOSHEADER,sizeof(DOSHEADER));
//DOSMZheader又命名为IMAGE_DOS_HEADER.。其中只有两个域比较重要:
//e_magic包含字符串"MZ",e_lfanew包含PEheader在文件中的偏移量。
//将指针移到PEheader在文件中的偏移量
fs.Seek(DOSHEADER._lfanew,soFromBeginning);
//读取PEheader头信息
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;}
fori:=0to7do
begin
MySectionHeader.Name[i]:=0;
ifi<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.VirtualAddressdiv
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));
//将指针移到PEheader在文件中的偏移量
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
LEAeax,OEPCODE//将OEPCODE的地址交给寄存器
ADDeax,JMPOFF//添加JMPOFF值给寄存器
MOVedx,AddressOfEntryPoint//转移指令,相当于付值语句,左边给右边
MOVDWORDptr[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;
procedureTForm1.Button1Click(Sender:TObject);
begin
ifOpenDialog1.Executethen
edit1.Text:=OpenDialog1.FileName;
end;
procedureTForm1.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;
procedureTForm1.Button2Click(Sender:TObject);
var
FName,SecName:string;
SecSize:DWord;
begin
iftrim(Edit1.Text)=''then
begin
Messagebox(Handle,'请选择你要伪装的程序!','提示',MB_OK+MB_ICONSTOP);
Exit;
end;
FName:=trim(Edit1.Text);
SecName:=trim(Edit2.Text);
ifSecName=''thenSecName:='.hnxyy';
SecSize:=512;
iftrim(edit3.Text)<>''then
begin
SecSize:=strtoint(trim(Edit3.Text));
ifSecSize<512thenSecSize:=512;
end;
ifCheckBox1.Checkedthen
CopyFile(PChar(FName),PChar(Fname+'.bak'),False);
SetOepCode;
AddSection(FName,SecName,SecSize);
Messagebox(Handle,'伪装成功!','提示',MB_OK+MB_ICONINFORMATION);
end;
procedureTForm1.SetOepCode;
begin
OEPCODE:=OEPCODEARRAY[RadioGroup1.ItemIndex];
JMPOFF:=JMPOFFARRAY[RadioGroup1.ItemIndex];
end;
procedureTForm1.Label4Click(Sender:TObject);
begin
ShellExecute(Handle,'open','http://forum.wrsky.com','','',SW_SHOWNORMAL);
end;
procedureTForm1.Edit3KeyPress(Sender:TObject;varKey:Char);
begin
ifnot(keyin['0'..'9',#8,#13])then
begin
key:=#0;
end;
end;
end.