[点评:了解一下PE吧]
下面给出这个程序的可执行文件,有兴趣的朋友可以看看.
|
文件: | proLanguage.rar |
大小: | 298KB |
下载: | 下载 |
|
这里是程序的分析及源码:
很久以来,一直有许多人想知道一个软件是用什么语言开发的,并且想出了各种奇怪的方法,我以前也用资源查看器,并得出规律,比如说包含 RCData 段的是 Delphi 程序,包含 NetWork 段的是 .NET 程序等等。
但是在对 VCL 作更深一步研究时,我发现,一个 Delphi 程序可以完全不包含 RCData 段,而 .NET 程序也不一定非要有 NetWork 段。但是归根到底,使用的编译器不同,编译出的程序一定不同,这个不同到底在哪里呢?
昨天对 PE 又做了一次研究,终于发现不同语言编译出的程序最大的不同就在程序头,也就是 PE 头部。用 16 进制编译器打开后,就会找到诸如 4D 5A 90 等字样,这其是是 16 进制编码,不同语言一发的程序,这个编码是不同的。
既然找到了关键,接下来就是作系统的分析,我在网上搜寻各种编程语言开发的软件,并截取了 PE
头部。对于一个程序,只要不经过花指令的混淆,那么不论怎么加壳,头部总是不变的(其实就算加花指令也能解开,只不过麻烦一些)。然后就简单了,写一个小
程序,获取 PE 头部,然后再找到每种编程语言的特征字节码,进行比较就行了。
其中,C++ 和 C 语言是比较复杂的,它们的特征码可以变换,所以我例举了所有的特征,只要有一个能对上号,就表明是 C++ 或 C 语言开发的。
完整程序代码如下:
unit frmMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ShellAPI, ComCtrls, StdCtrls, WinSkinData{引用界面包}, OBThread{引用线程包};
type
TFormMain = class(TForm)
Label1: TLabel;
edtSelectFile: TEdit;
btnBrowse: TButton;
Label2: TLabel;
lblLng: TLabel;
lblWeb: TLabel;
{软件界面}
SkinData1: TSkinData;
OD: TOpenDialog;
{线程实例}
OBThread1: TOBThread;
lblHelp: TLabel;
procedure lblWebClick(Sender: TObject);
procedure btnBrowseClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure OBThread1Execute(Sender: TObject; params: Pointer);
procedure OBThread1begin(Sender: TObject);
procedure lblHelpClick(Sender: TObject);
private
procedure Init;
protected
{是否由Asm开发}
function IsAsmOf(ALngName:string;ABytes:array of Byte):Boolean;
{是否由C语言开发}
function IsPucOf(ALngName:string;ABytes:array of Byte):Boolean;
{是否由C++开发}
function IsSpcOf(ALngName:string;ABytes:array of Byte):Boolean;
{是否由其他指定语言开发}
function IsLngOf(ALngName:string;ABytes:array of Byte):boolean;
public
{获取编程语言}
function GetLng(const AName: string): string;
end;
{Key结构}
TKey=record
kKey:Integer;
kValue:Integer;
end;
var
FormMain: TFormMain;
(*语言常量声明*)
//DotNet
DotNet:array[0..4] of Byte=($4D, $5A, $90, $00, $03);
DotNetKey:array[0..0]of TKey;
//Delphi
Delphi:array[0..4]of Byte=($4D, $5A, $50, $00, $02);
DelphiKey:array [0..1]of TKey;
//C++ Builder
BCB:array[0..4]of Byte=($4D, $5A, $50, $00, $02);
BCBKey:array [0..1]of TKey;
//Visual Basic
VB:array[0..4]of Byte=($4D, $5A, $90, $00, $03);
VBkey:array[0..0] of TKey;
//Win32 Asm
WAsm:array[0..4]of Byte=($4D, $5A, $90, $00, $03);
WAsmKey:array[0..0] of TKey;
//Java
Java:array[0..4]of Byte=($4D, $5A, $90, $00, $03);
JavaKey:array[0..0] of TKey;
//Power Builder
PB:array[0..4]of Byte=($4D, $5A, $80, $00, $01);
PBKey:array[0..0] of TKey;
//C++
CPP:array[0..4] of Byte=($4D, $5A, $90, $00, $03);
CPPKey:array[0..5] of TKey;
//80x86 Asm
Asm16:array[0..4]of Byte=($4D, $5A, $90, $00, $03);
Asm16Key:array[0..0]of TKey;
//C语言
TC:array[0..1]of Byte=($4D, $5A);
TCKey:array[0..5]of TKey;
implementation
resourcestring
{字符串常量}
Lng = '开发语言:%s';
Help =
' 本软件可以检测现在较为流行'#13#10+
'的多种编程语言开发的软件,并指'#13#10+
'出它用何种语言所开发。'#13#10#13#10+
' 若检测出的语言为 .NET ,则'#13#10+
'表示软件是采用 .NET 平台下任何'#13#10+
'一种语言所开发的,它们编译后都'#13#10+
'成为 .NET Framework 中间语言。'#13#10#13#10+
' 本软件检测易语言开发的软件'#13#10+
'时会报告成 VB 开发的,这并不是'#13#10+
'软件的问题,而是易语言编译后的'#13#10+
'就是 VB 文件。'#13#10#13#10+
' 另外,对于C++ 的检测可能有'#13#10+
'些问题,有时候软件会把汇编程序'#13#10+
'报告成C++ 的,如果谁有更好的检'#13#10+
'测编程语言的算法,请告知,以便'#13#10+
'我进行改进。'#13#10#13#10+
' 软件制作:Rarnu'#13#10+
' 网址:[url][/url]'#13#10+
' 邮箱:[email]viva_killer@163.com[/email]'#13#10;
{$R *.dfm}
procedure TFormMain.lblWebClick(Sender: TObject);
begin
ShellExecute(0, 'open', 'http:///', nil, nil, SW_SHOW);
end;
procedure TFormMain.btnBrowseClick(Sender: TObject);
begin
if not OD.Execute then Exit;
edtSelectFile.Text:=OD.FileName;
//开启处理线程
self.OBThread1.Execute(nil);
end;
function TFormMain.GetLng(const AName: string): string;
var
ProFile: file of Byte;
Bytes: array[0..63] of Byte;
i: Integer;
begin
//以字节方式打开选定的文件
AssignFile(ProFile, AName);
Reset(ProFile);
//定位到文件头
Seek(ProFile, 0);
//取前64字节码
for i:=0 to 63 do
read(Profile,Bytes[i]);
CloseFile(ProFile);
//判断语言
Result:='未知';
if IsLngOf('DotNet',Bytes) then Result:='.Net';
if IsLngOf('Delphi',Bytes) then Result:='Delphi';
if IsLngOf('BCB',Bytes) then Result:='C++ Builder';
if IsLngOf('VB',Bytes) then Result:='Visual Basic';
if IsLngOf('WAsm',Bytes) then Result:='Win32 Asm';
if IsLngOf('Java',Bytes) then Result:='Java';
if IsLngOf('PB',Bytes) then Result:='Power Builder';
if IsSpcOf('CPP',Bytes) then Result:='C++';
if IsAsmOf('Asm16',Bytes) then Result:='80x86 Asm';
if IsPucOf('TC',Bytes) then Result:='C';
end;
function TFormMain.IsLngOf(ALngName: string;
ABytes: array of Byte): boolean;
var
LngByte:array[0..4] of Byte;
i:integer;
Keys:array of TKey;
begin
//DotNet
if ALngName='DotNet' then
begin
for i:=0 to 4 do
LngByte[i]:=Dotnet[i];
SetLength(Keys,Length(DotNetKey));
for i:=0 to Length(DotNetKey)-1 do
begin
Keys[i].kKey:=Dotnetkey[i].kKey;
Keys[i].kValue:=Dotnetkey[i].kValue;
end;
end;
//Delphi
if ALngName='Delphi' then
begin
for i:=0 to 4 do
LngByte[i]:=Delphi[i];
SetLength(Keys,Length(DelphiKey));
for i:=0 to Length(DelphiKey)-1 do
begin
Keys[i].kKey:=DelphiKey[i].kKey;
Keys[i].kValue:=Delphikey[i].kValue;
end;
end;
//BCB
if ALngName='BCB' then
begin
for i:=0 to 4 do
LngByte[i]:=BCB[i];
SetLength(Keys,Length(BCBKey));
for i:=0 to Length(BCBKey)-1 do
begin
Keys[i].kKey:=BCBkey[i].kKey;
Keys[i].kValue:=BCBkey[i].kValue;
end;
end;
//VB
if ALngName='VB' then
begin
for i:=0 to 4 do
LngByte[i]:=VB[i];
SetLength(Keys,Length(VBKey));
for i:=0 to Length(VBKey)-1 do
begin
Keys[i].kKey:=VBkey[i].kKey;
Keys[i].kValue:=VBkey[i].kValue;
end;
end;
//Win32Asm
if ALngName='WAsm' then
begin
for i:=0 to 4 do
LngByte[i]:=WAsm[i];
SetLength(Keys,Length(WAsmKey));
for i:=0 to Length(WAsmKey)-1 do
begin
Keys[i].kKey:=WAsmkey[i].kKey;
Keys[i].kValue:=WAsmkey[i].kValue;
end;
end;
//Java
if ALngName='Java' then
begin
for i:=0 to 4 do
LngByte[i]:=Java[i];
SetLength(Keys,Length(JavaKey));
for i:=0 to Length(JavaKey)-1 do
begin
Keys[i].kKey:=Javakey[i].kKey;
Keys[i].kValue:=Javakey[i].kValue;
end;
end;
//power builder
if ALngName='PB' then
begin
for i:=0 to 4 do
LngByte[i]:=PB[i];
SetLength(Keys,Length(PBKey));
for i:=0 to Length(PBKey)-1 do
begin
Keys[i].kKey:=PBkey[i].kKey;
Keys[i].kValue:=PBkey[i].kValue;
end;
end;
result:=true;
//起始5字节比较
for i:=0 to 4 do
begin
if LngByte[i]<>ABytes[i] then
begin
Result:=False;
Exit;
end;
end;
//关键码比较
for i:=0 to Length(Keys)-1 do
begin
if ABytes[Keys[i].kKey]<>Keys[i].kValue then
begin
Result:=False;
Exit;
end;
end;
end;
procedure TFormMain.Init;
begin
//关键码初始化
DotNetKey[0].kKey:=60;
DotNetKey[0].kValue:=$80;
DelphiKey[0].kKey:=26;
DelphiKey[0].kValue:=$1A;
DelphiKey[1].kKey:=61;
DelphiKey[1].kValue:=$01;
BCBKey[0].kKey:=26;
BCBKey[0].kValue:=$1A;
BCBKey[1].kKey:=61;
BCBKey[1].kValue:=$02;
VBkey[0].kKey:=60;
VBkey[0].kValue:=$B0;
WAsmKey[0].kKey:=60;
WAsmKey[0].kValue:=$C0;
JavaKey[0].kKey:=60;
JavaKey[0].kValue:=$E0;
PBKey[0].kKey:=60;
PBKey[0].kValue:=$70;
CPPKey[0].kKey:=60;
CPPKey[0].kValue:=$D0;
CPPKey[1].kKey:=60;
CPPKey[1].kValue:=$D8;
CPPKey[2].kKey:=60;
CPPKey[2].kValue:=$C8;
CPPKey[3].kKey:=60;
CPPKey[3].kValue:=$E8;
CPPKey[4].kKey:=60;
CPPKey[4].kValue:=$F0;
CPPKey[5].kKey:=60;
CPPKey[5].kValue:=$F8;
Asm16Key[0].kKey:=61;
Asm16Key[0].kValue:=$01;
TCKey[0].kKey:=24;
TCKey[0].kValue:=$22;
TCKey[1].kKey:=30;
TCKey[1].kValue:=$FB;
TCKey[2].kKey:=31;
TCKey[2].kValue:=$20;
TCKey[3].kKey:=32;
TCKey[3].kValue:=$72;
TCKey[4].kKey:=33;
TCKey[4].kValue:=$6A;
TCKey[5].kKey:=34;
TCKey[5].kValue:=$01;
end;
procedure TFormMain.FormCreate(Sender: TObject);
begin
Init;
end;
procedure TFormMain.OBThread1Execute(Sender: TObject; params: Pointer);
begin
//显示分析结果
lblLng.Caption := Format(Lng,[GetLng(OD.FileName)]);
end;
procedure TFormMain.OBThread1begin(Sender: TObject);
begin
lblLng.Caption:='分析中........';
end;
function TFormMain.IsSpcOf(ALngName: string;
ABytes: array of Byte): Boolean;
var
LngByte:array[0..4] of Byte;
i:integer;
Keys:array of TKey;
begin
//C++
if ALngName='CPP' then
begin
for i:=0 to 4 do
LngByte[i]:=CPP[i];
SetLength(Keys,Length(CPPKey));
for i:=0 to Length(CPPKey)-1 do
begin
Keys[i].kKey:=CPPkey[i].kKey;
Keys[i].kValue:=CPPkey[i].kValue;
end;
end;
for i:=0 to 4 do
begin
if LngByte[i]<>ABytes[i] then
begin
Result:=False;
Exit;
end;
end;
Result:=False;
for i:=0 to Length(Keys)-1 do
begin
if ABytes[Keys[i].kKey]=Keys[i].kValue then
begin
Result:=True;
Exit;
end;
end;
end;
function TFormMain.IsAsmOf(ALngName: string;
ABytes: array of Byte): Boolean;
var
LngByte:array[0..4] of Byte;
i:integer;
Keys:array of TKey;
begin
if ALngName='Asm16' then
begin
for i:=0 to 4 do
LngByte[i]:=Asm16[i];
SetLength(Keys,Length(Asm16Key));
for i:=0 to Length(Asm16Key)-1 do
begin
Keys[i].kKey:=Asm16key[i].kKey;
Keys[i].kValue:=Asm16key[i].kValue;
end;
end;
for i:=0 to 4 do
begin
if LngByte[i]<>ABytes[i] then
begin
Result:=False;
Exit;
end;
end;
result:=True;
for i:=0 to Length(Keys)-1 do
begin
if ABytes[Keys[i].kKey]<>Keys[i].kValue then
begin
Result:=False;
Exit;
end;
end;
if ABytes[60]=$00 then
begin
Result:=False;
Exit;
end;
end;
function TFormMain.IsPucOf(ALngName: string;
ABytes: array of Byte): Boolean;
var
LngByte:array[0..4] of Byte;
i:integer;
Keys:array of TKey;
begin
if ALngName='TC' then
begin
for i:=0 to 1 do
LngByte[i]:=TC[i];
SetLength(Keys,Length(TCKey));
for i:=0 to Length(TCKey)-1 do
begin
Keys[i].kKey:=TCkey[i].kKey;
Keys[i].kValue:=TCkey[i].kValue;
end;
end;
for i:=0 to 1 do
begin
if LngByte[i]<>ABytes[i] then
begin
Result:=False;
Exit;
end;
end;
Result:=True;
for i:=0 to Length(Keys)-1 do
begin
if ABytes[Keys[i].kKey]<>Keys[i].kValue then
begin
Result:=False;
Exit;
end;
end;
end;
procedure TFormMain.lblHelpClick(Sender: TObject);
begin
MessageBox(Handle,PChar(Help),'帮助',MB_OK or MB_ICONINFORMATION);
end;
end.