Chinaunix首页 | 论坛 | 博客
  • 博客访问: 8698938
  • 博文数量: 1413
  • 博客积分: 11128
  • 博客等级: 上将
  • 技术积分: 14685
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-13 10:03
个人简介

follow my heart...

文章分类

全部博文(1413)

文章存档

2013年(1)

2012年(5)

2011年(45)

2010年(176)

2009年(148)

2008年(190)

2007年(293)

2006年(555)

分类:

2006-12-30 17:02:52

[点评:了解一下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.
阅读(2412) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~